├── icon.png
├── .editorconfig
├── manifests
└── c
│ └── Corsinvest
│ └── cv4pve
│ └── autosnap
│ └── 1.17.0
│ ├── Corsinvest.cv4pve.autosnap.yaml
│ ├── Corsinvest.cv4pve.autosnap.installer.yaml
│ └── Corsinvest.cv4pve.autosnap.locale.en-US.yaml
├── Directory.Build.props
├── Directory.Packages.props
├── src
├── Corsinvest.ProxmoxVE.AutoSnap.Api
│ ├── ResultSnapVm.cs
│ ├── ResultBaseSnap.cs
│ ├── ResultSnap.cs
│ ├── HookPhase.cs
│ ├── Corsinvest.ProxmoxVE.AutoSnap.Api.csproj
│ ├── PhaseEventArgs.cs
│ └── Application.cs
└── Corsinvest.ProxmoxVE.AutoSnap
│ ├── Program.cs
│ ├── Corsinvest.ProxmoxVE.AutoSnap.csproj
│ └── Commands.cs
├── 3rd-party-licenses.md
├── .github
├── workflows
│ ├── publish.yml
│ ├── build.yml
│ └── quality.yml
└── ISSUE_TEMPLATE
│ └── bug_report.yml
├── .vscode
├── launch.json
└── tasks.json
├── hooks
├── hook-template.bat
├── hook-template.ps1
├── hook-template.sh
└── send-metrics.sh
├── Corsinvest.ProxmoxVE.AutoSnap.sln
├── .gitignore
├── README.md
└── LICENSE.md
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Corsinvest/cv4pve-autosnap/HEAD/icon.png
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # All files
2 | [*]
3 | guidelines = 80
4 |
5 | # C# or VB files
6 | [*.{cs,vb}]
7 | guidelines = 80, 120
--------------------------------------------------------------------------------
/manifests/c/Corsinvest/cv4pve/autosnap/1.17.0/Corsinvest.cv4pve.autosnap.yaml:
--------------------------------------------------------------------------------
1 | # Created using wingetcreate 1.10.3.0
2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.10.0.schema.json
3 |
4 | PackageIdentifier: Corsinvest.cv4pve.autosnap
5 | PackageVersion: 1.17.0
6 | DefaultLocale: en-US
7 | ManifestType: version
8 | ManifestVersion: 1.10.0
9 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1.17.0
4 | latest
5 | enable
6 | enable
7 | Corsinvest Srl
8 | Corsinvest Srl
9 | Corsinvest Srl
10 |
11 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | ..\nupkgs\
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap.Api/ResultSnapVm.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: GPL-3.0-only
3 | * SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | */
5 |
6 | namespace Corsinvest.ProxmoxVE.AutoSnap.Api;
7 |
8 | ///
9 | /// Execution Vm
10 | ///
11 | public class ResultSnapVm : ResultBaseSnap
12 | {
13 | ///
14 | /// Vm id
15 | ///
16 | ///
17 | public long VmId { get; internal set; }
18 | }
--------------------------------------------------------------------------------
/3rd-party-licenses.md:
--------------------------------------------------------------------------------
1 | # License overview of included 3rd party libraries
2 |
3 | The project is licensed under the terms of the [LICENSE.md](LICENSE.md)
4 |
5 | However, includes several third-party Open-Source libraries, which are licensed under their own respective Open-Source licenses.
6 |
7 | ## Libraries directly included
8 |
9 | [Corsinvest ProxmoxVE Api](https://github.com/Corsinvest/cv4pve-api-dotnet)
10 | License: GPLv3
11 |
12 | [Corsinvest ProxmoxVE Api Extension](https://github.com/Corsinvest/cv4pve-api-dotnet)
13 | License: GPLv3
14 |
15 | [Dotnet Core](https://github.com/dotnet/core)
16 | License: MIT
17 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 |
8 | jobs:
9 | publish:
10 | uses: Corsinvest/.github/.github/workflows/cv4pve-cli-publish.yml@main
11 | secrets:
12 | NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
13 | WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }}
14 | with:
15 | project-name: cv4pve-autosnap
16 | project-path: src/Corsinvest.ProxmoxVE.AutoSnap/Corsinvest.ProxmoxVE.AutoSnap.csproj
17 | nuget-project-path: src/Corsinvest.ProxmoxVE.AutoSnap.Api/Corsinvest.ProxmoxVE.AutoSnap.Api.csproj
18 | winget-id: Corsinvest.cv4pve.autosnap
19 |
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap/Program.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: GPL-3.0-only
3 | * SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | */
5 |
6 | using Corsinvest.ProxmoxVE.Api.Console.Helpers;
7 | using Corsinvest.ProxmoxVE.AutoSnap;
8 | using Corsinvest.ProxmoxVE.AutoSnap.Api;
9 | using Microsoft.Extensions.Logging;
10 |
11 | var app = ConsoleHelper.CreateApp(Application.Name, "Automatic snapshot VM/CT with retention");
12 | var loggerFactory = ConsoleHelper.CreateLoggerFactory(app.GetLogLevelFromDebug());
13 |
14 | _ = new Commands(app, loggerFactory);
15 | return await app.ExecuteAppAsync(args, loggerFactory.CreateLogger());
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap.Api/ResultBaseSnap.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: GPL-3.0-only
3 | * SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | */
5 |
6 | using System.Diagnostics;
7 |
8 | namespace Corsinvest.ProxmoxVE.AutoSnap.Api;
9 |
10 | ///
11 | /// ResultBase
12 | ///
13 | public class ResultBaseSnap
14 | {
15 | private readonly Stopwatch _execution = new();
16 |
17 | internal void Start() => _execution.Start();
18 | internal void Stop() => _execution.Stop();
19 |
20 | ///
21 | /// Elapsed
22 | ///
23 | public TimeSpan Elapsed => _execution.Elapsed;
24 |
25 | ///
26 | /// Status
27 | ///
28 | ///
29 | public virtual bool Status { get; internal set; }
30 | }
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap.Api/ResultSnap.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: GPL-3.0-only
3 | * SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | */
5 |
6 | namespace Corsinvest.ProxmoxVE.AutoSnap.Api;
7 |
8 | ///
9 | /// Execution Snap
10 | ///
11 | public class ResultSnap : ResultBaseSnap
12 | {
13 | ///
14 | /// Vms
15 | ///
16 | public List Vms { get; } = new List();
17 |
18 | ///
19 | /// Status
20 | ///
21 | ///
22 | public override bool Status
23 | {
24 | get => !Vms.Any(a => !a.Status);
25 | internal set { }
26 | }
27 |
28 | ///
29 | /// Name of the snapshot
30 | ///
31 | public string SnapName { get; internal set; } = default!;
32 | }
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap/Corsinvest.ProxmoxVE.AutoSnap.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net10.0
5 | cv4pve-autosnap
6 | Corsinvest for Proxmox VE Auto Snapshot
7 | Corsinvest for Proxmox VE Auto Snapshot
8 | Corsinvest for Proxmox VE Auto Snapshot
9 | true
10 | false
11 | https://github.com/Corsinvest/cv4pve-autosnap
12 | git
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ "master", "dev" ]
6 | pull_request:
7 | branches: [ "master" ]
8 | workflow_dispatch:
9 |
10 | env:
11 | DOTNET_VERSION: '10.0.x'
12 |
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v4
19 | with:
20 | fetch-depth: 0
21 |
22 | - name: Setup .NET
23 | uses: actions/setup-dotnet@v4
24 | with:
25 | dotnet-version: ${{ env.DOTNET_VERSION }}
26 |
27 | - name: Restore dependencies
28 | run: dotnet restore
29 |
30 | - name: Build
31 | run: dotnet build --no-restore --configuration Release
32 |
33 | - name: Test
34 | run: dotnet test --no-build --configuration Release --verbosity normal
35 |
36 | - name: Upload Build Artifacts
37 | uses: actions/upload-artifact@v4
38 | with:
39 | name: build-artifacts
40 | path: src/**/bin/Release/
41 | retention-days: 7
--------------------------------------------------------------------------------
/manifests/c/Corsinvest/cv4pve/autosnap/1.17.0/Corsinvest.cv4pve.autosnap.installer.yaml:
--------------------------------------------------------------------------------
1 | # Created using wingetcreate 1.10.3.0
2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.10.0.schema.json
3 |
4 | PackageIdentifier: Corsinvest.cv4pve.autosnap
5 | PackageVersion: 1.17.0
6 | InstallerType: zip
7 | NestedInstallerType: portable
8 | NestedInstallerFiles:
9 | - RelativeFilePath: cv4pve-autosnap.exe
10 | PortableCommandAlias: cv4pve-autosnap
11 | ReleaseDate: 2025-12-10
12 | Installers:
13 | - Architecture: x64
14 | InstallerUrl: https://github.com/Corsinvest/cv4pve-autosnap/releases/download/v1.17.0/cv4pve-autosnap.exe-win-x64.zip
15 | InstallerSha256: 7024451885CAE4C8B53237DD0C530DE152D2A28A3DAF6F3FA932669B35480373
16 | - Architecture: x86
17 | InstallerUrl: https://github.com/Corsinvest/cv4pve-autosnap/releases/download/v1.17.0/cv4pve-autosnap.exe-win-x86.zip
18 | InstallerSha256: 54A42B1416714663DB1281E8C8C2AB254E45527E002527B3DFC966E0652D1194
19 | - Architecture: arm64
20 | InstallerUrl: https://github.com/Corsinvest/cv4pve-autosnap/releases/download/v1.17.0/cv4pve-autosnap.exe-win-arm64.zip
21 | InstallerSha256: C62128FBF55DDC628837A6B4D4A56A1145D037F63D07D79B651F8B9226299D45
22 | ManifestType: installer
23 | ManifestVersion: 1.10.0
24 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | // Usare IntelliSense per individuare gli attributi esistenti per il debug C#
6 | // Usa il passaggio del mouse per la descrizione degli attributi esistenti
7 | // Per ulteriori informazioni, visitare https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
8 | "name": ".NET Core Launch (console)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | // Se i framework di destinazione sono stati modificati, assicurarsi di aggiornare il percorso del programma.
13 | "program": "${workspaceFolder}/src/Corsinvest.ProxmoxVE.AutoSnap/bin/Debug/net10.0/cv4pve-autosnap.dll",
14 | "args": [
15 | "@Parm.parm"
16 | ],
17 | "cwd": "${workspaceFolder}/src/Corsinvest.ProxmoxVE.AutoSnap",
18 | // Per ulteriori informazioni sul campo 'console', vedere https://aka.ms/VSCode-CS-LaunchJson-Console
19 | "console": "internalConsole",
20 | "stopAtEntry": false
21 | },
22 | {
23 | "name": ".NET Core Attach",
24 | "type": "coreclr",
25 | "request": "attach"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap.Api/HookPhase.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: GPL-3.0-only
3 | * SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | */
5 |
6 | namespace Corsinvest.ProxmoxVE.AutoSnap.Api;
7 |
8 | ///
9 | /// Hook phase
10 | ///
11 | public enum HookPhase
12 | {
13 | ///
14 | /// Clean Job Start
15 | ///
16 | CleanJobStart = 0,
17 |
18 | ///
19 | /// Clean Job End
20 | ///
21 | CleanJobEnd = 1,
22 |
23 | ///
24 | /// Snap Job Start
25 | ///
26 | SnapJobStart = 2,
27 |
28 | ///
29 | /// Snap Job End
30 | ///
31 | SnapJobEnd = 3,
32 |
33 | ///
34 | /// Snap Create Pre
35 | ///
36 | SnapCreatePre = 4,
37 |
38 | ///
39 | /// Snap Create Post
40 | ///
41 | SnapCreatePost = 5,
42 |
43 | ///
44 | /// Snap Create Abort
45 | ///
46 | SnapCreateAbort = 6,
47 |
48 | ///
49 | /// Snap Remove Pre
50 | ///
51 | SnapRemovePre = 7,
52 |
53 | ///
54 | /// Snap Remove Post
55 | ///
56 | SnapRemovePost = 8,
57 |
58 | ///
59 | /// Snap Remove Abort
60 | ///
61 | SnapRemoveAbort = 9
62 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "command": "dotnet",
7 | "type": "process",
8 | "args": [
9 | "build",
10 | "${workspaceFolder}/Corsinvest.ProxmoxVE.AutoSnap.sln",
11 | "/property:GenerateFullPaths=true",
12 | "/consoleloggerparameters:NoSummary;ForceNoAlign"
13 | ],
14 | "problemMatcher": "$msCompile"
15 | },
16 | {
17 | "label": "publish",
18 | "command": "dotnet",
19 | "type": "process",
20 | "args": [
21 | "publish",
22 | "${workspaceFolder}/Corsinvest.ProxmoxVE.AutoSnap.sln",
23 | "/property:GenerateFullPaths=true",
24 | "/consoleloggerparameters:NoSummary;ForceNoAlign"
25 | ],
26 | "problemMatcher": "$msCompile"
27 | },
28 | {
29 | "label": "watch",
30 | "command": "dotnet",
31 | "type": "process",
32 | "args": [
33 | "watch",
34 | "run",
35 | "--project",
36 | "${workspaceFolder}/Corsinvest.ProxmoxVE.AutoSnap.sln"
37 | ],
38 | "problemMatcher": "$msCompile"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap.Api/Corsinvest.ProxmoxVE.AutoSnap.Api.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0;net9.0;net10.0
4 | Library
5 |
6 | https://github.com/Corsinvest/cv4pve-autosnap
7 | icon.png
8 | README.md
9 | ProxmoxVE;Api,Client;Rest;Corsinvest;AutoSnap
10 | GPL-3.0-only
11 | ..\..\..\.nupkgs\
12 | git
13 | https://github.com/Corsinvest/cv4pve-autosnap
14 | true
15 | true
16 | True
17 |
18 |
19 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
20 |
21 | true
22 | snupkg
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.github/workflows/quality.yml:
--------------------------------------------------------------------------------
1 | name: Quality
2 |
3 | on:
4 | push:
5 | branches: [ "master", "dev" ]
6 | pull_request:
7 | branches: [ "master" ]
8 | workflow_dispatch:
9 |
10 | env:
11 | DOTNET_VERSION: '10.0.x'
12 |
13 | jobs:
14 | analyze:
15 | name: Analyze
16 | runs-on: ubuntu-latest
17 | permissions:
18 | actions: read
19 | contents: read
20 | security-events: write
21 |
22 | steps:
23 | - name: Checkout repository
24 | uses: actions/checkout@v4
25 | with:
26 | fetch-depth: 0
27 |
28 | - name: Initialize CodeQL
29 | uses: github/codeql-action/init@v3
30 | with:
31 | languages: 'csharp'
32 |
33 | - name: Setup .NET
34 | uses: actions/setup-dotnet@v4
35 | with:
36 | dotnet-version: ${{ env.DOTNET_VERSION }}
37 |
38 | - name: Restore dependencies
39 | run: dotnet restore
40 |
41 | - name: Build
42 | run: dotnet build --no-restore --configuration Release
43 |
44 | - name: Perform CodeQL Analysis
45 | uses: github/codeql-action/analyze@v3
46 |
47 | lint:
48 | name: Lint
49 | runs-on: ubuntu-latest
50 |
51 | steps:
52 | - name: Checkout repository
53 | uses: actions/checkout@v4
54 | with:
55 | fetch-depth: 0
56 |
57 | - name: Setup .NET
58 | uses: actions/setup-dotnet@v4
59 | with:
60 | dotnet-version: ${{ env.DOTNET_VERSION }}
61 |
62 | - name: Restore dependencies
63 | run: dotnet restore
64 |
65 | - name: Lint with dotnet format
66 | run: |
67 | dotnet format --verify-no-changes --severity error
--------------------------------------------------------------------------------
/manifests/c/Corsinvest/cv4pve/autosnap/1.17.0/Corsinvest.cv4pve.autosnap.locale.en-US.yaml:
--------------------------------------------------------------------------------
1 | # Created using wingetcreate 1.10.3.0
2 | # yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.10.0.schema.json
3 |
4 | PackageIdentifier: Corsinvest.cv4pve.autosnap
5 | PackageVersion: 1.17.0
6 | PackageLocale: en-US
7 | Publisher: Corsinvest Srl
8 | PublisherUrl: https://www.corsinvest.it
9 | PublisherSupportUrl: https://www.corsinvest.it/cv4pve
10 | PrivacyUrl: https://www.corsinvest.it/privacy
11 | Author: Corsinvest Srl
12 | PackageName: cv4pve-autosnap
13 | PackageUrl: https://github.com/Corsinvest/cv4pve-autosnap
14 | License: GPL-3.0-only
15 | LicenseUrl: https://github.com/Corsinvest/cv4pve-autosnap/blob/master/LICENSE.md
16 | Copyright: Copyright (c) 2019-2025 Corsinvest Srl
17 | CopyrightUrl: https://github.com/Corsinvest/cv4pve-autosnap/blob/master/LICENSE.md
18 | ShortDescription: Automatic Snapshot Tool for Proxmox VE
19 | Description: |-
20 | cv4pve-autosnap is an automatic snapshot tool for Proxmox VE virtual machines and containers.
21 | It creates snapshots with retention policies and supports flexible targeting patterns including
22 | ID/name based selection, bulk operations, and pool-based selections.
23 |
24 | Features:
25 | - Automatic snapshot creation with retention policies
26 | - Support for VMs and Containers
27 | - Flexible VM selection (ID, name, patterns, pools)
28 | - Hook script execution (pre/post snapshot)
29 | - Multiple snapshot labels for different schedules
30 | - Clean command to remove old snapshots
31 | - Status command to view existing snapshots
32 | Moniker: cv4pve-autosnap
33 | Tags:
34 | - automation
35 | - backup
36 | - container
37 | - corsinvest
38 | - proxmox
39 | - proxmoxve
40 | - snapshot
41 | - virtualization
42 | - vm
43 | ReleaseNotesUrl: https://github.com/Corsinvest/cv4pve-autosnap/releases/tag/v1.17.0
44 | ManifestType: defaultLocale
45 | ManifestVersion: 1.10.0
46 |
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap.Api/PhaseEventArgs.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: GPL-3.0-only
3 | * SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | */
5 |
6 | using System.Globalization;
7 | using Corsinvest.ProxmoxVE.Api.Shared.Models.Cluster;
8 |
9 | namespace Corsinvest.ProxmoxVE.AutoSnap.Api;
10 |
11 | ///
12 | /// Phase event arguments
13 | ///
14 | ///
15 | /// Constructor
16 | ///
17 | ///
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | ///
25 | public record PhaseEventArgs(HookPhase Phase,
26 | IClusterResourceVm Vm,
27 | string Label,
28 | int Keep,
29 | string SnapName,
30 | bool VmState,
31 | double Duration,
32 | bool Status)
33 | {
34 | ///
35 | /// Environments
36 | ///
37 | ///
38 | public IReadOnlyDictionary Environments
39 | => new Dictionary
40 | {
41 | {"CV4PVE_AUTOSNAP_PHASE", Application.PhaseEnumToStr(Phase)},
42 | {"CV4PVE_AUTOSNAP_VMID", Vm.VmId + string.Empty },
43 | {"CV4PVE_AUTOSNAP_VMNAME", Vm.Name },
44 | {"CV4PVE_AUTOSNAP_VMTYPE", Vm.Type + string.Empty },
45 | {"CV4PVE_AUTOSNAP_LABEL", Label },
46 | {"CV4PVE_AUTOSNAP_KEEP", Keep + string.Empty },
47 | {"CV4PVE_AUTOSNAP_SNAP_NAME", SnapName },
48 | {"CV4PVE_AUTOSNAP_VMSTATE", VmState ? "1" : "0" },
49 | {"CV4PVE_AUTOSNAP_DURATION", (Duration + string.Empty).Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator,".") },
50 | {"CV4PVE_AUTOSNAP_STATE", Status ? "1" : "0" },
51 | };
52 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 🐛 Bug Report
2 | description: Report a bug in cv4pve-autosnap
3 | title: "[BUG] "
4 | labels: ["bug", "needs investigation"]
5 |
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | ## 🐛 Bug Report
11 |
12 | Thanks for taking the time to fill out this bug report!
13 |
14 | **Before submitting:** Search existing issues to avoid duplicates.
15 |
16 | - type: textarea
17 | id: what-happened
18 | attributes:
19 | label: What happened?
20 | description: Describe the issue briefly
21 | placeholder: Describe your issue!
22 | validations:
23 | required: true
24 |
25 | - type: textarea
26 | id: expected-behavior
27 | attributes:
28 | label: Expected behavior
29 | description: What you expected to happen
30 | placeholder: Describe the expected behavior!
31 | validations:
32 | required: true
33 |
34 | - type: textarea
35 | id: command-used
36 | attributes:
37 | label: Command used
38 | description: |
39 | Paste the exact command you ran. **Remove passwords and API tokens!**
40 | placeholder: |
41 | cv4pve-autosnap --host=pve.local --username=user@pam --password=*** --vmid=100 snap --label=daily --keep=7
42 | render: bash
43 | validations:
44 | required: true
45 |
46 | - type: textarea
47 | id: logs
48 | attributes:
49 | label: Log output
50 | description: |
51 | **Use `--debug` parameter to get detailed logs, then paste the output here.**
52 |
53 | ⚠️ **ATTENTION: Remove sensitive data (passwords, API keys) before pasting!**
54 | placeholder: Run your command with --debug and paste the output here
55 | render: shell
56 | validations:
57 | required: true
58 |
59 | - type: input
60 | id: cv4pve-version
61 | attributes:
62 | label: cv4pve-autosnap Version
63 | placeholder: "v1.14.10"
64 | validations:
65 | required: true
66 |
67 | - type: input
68 | id: proxmox-version
69 | attributes:
70 | label: Proxmox VE Version
71 | placeholder: "8.0.4"
72 | validations:
73 | required: true
74 |
75 | - type: input
76 | id: working-version
77 | attributes:
78 | label: Last working version
79 | description: Did it work before? Which version?
80 | placeholder: "v1.14.8 or 'Never worked'"
81 |
82 | - type: dropdown
83 | id: os
84 | attributes:
85 | label: Operating System
86 | options:
87 | - Linux
88 | - Windows
89 | - macOS
90 | - Docker
91 | - Other
92 | validations:
93 | required: true
94 |
95 | - type: checkboxes
96 | id: pr
97 | attributes:
98 | label: Pull Request
99 | options:
100 | - label: I would like to do a Pull Request
101 |
--------------------------------------------------------------------------------
/hooks/hook-template.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | REM SPDX-License-Identifier: GPL-3.0-only
3 | REM SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | REM
5 | REM Corsinvest automatic snapshot for Proxmox VE cv4pve-autosnap hook script.
6 | REM Process environment variables as received from and set by cv4pve-autosnap.
7 |
8 | ECHO ----------------------------------------------------------
9 | ECHO CV4PVE_AUTOSNAP_PHASE: %CV4PVE_AUTOSNAP_PHASE%
10 | ECHO CV4PVE_AUTOSNAP_VMID: %CV4PVE_AUTOSNAP_VMID%
11 | ECHO CV4PVE_AUTOSNAP_VMNAME: %CV4PVE_AUTOSNAP_VMNAME%
12 | ECHO CV4PVE_AUTOSNAP_VMTYPE: %CV4PVE_AUTOSNAP_VMTYPE%
13 | ECHO CV4PVE_AUTOSNAP_LABEL: %CV4PVE_AUTOSNAP_LABEL%
14 | ECHO CV4PVE_AUTOSNAP_KEEP: %CV4PVE_AUTOSNAP_KEEP%
15 | ECHO CV4PVE_AUTOSNAP_SNAP_NAME: %CV4PVE_AUTOSNAP_SNAP_NAME%
16 | ECHO CV4PVE_AUTOSNAP_VMSTATE: %CV4PVE_AUTOSNAP_VMSTATE%
17 | ECHO CV4PVE_AUTOSNAP_DURATION: %CV4PVE_AUTOSNAP_DURATION%
18 | ECHO CV4PVE_AUTOSNAP_STATE: %CV4PVE_AUTOSNAP_STATE%
19 | ECHO CV4PVE_AUTOSNAP_DEBUG: %CV4PVE_AUTOSNAP_DEBUG%
20 | ECHO CV4PVE_AUTOSNAP_DRY_RUN: %CV4PVE_AUTOSNAP_DRY_RUN%
21 | ECHO ----------------------------------------------------------
22 |
23 | REM Hook script phases:
24 | REM clean-job-start - Before starting cleanup operation
25 | REM clean-job-end - After finishing cleanup operation
26 | REM snap-job-start - Before starting snapshot operation
27 | REM snap-job-end - After finishing snapshot operation
28 | REM snap-create-pre - Before creating snapshot
29 | REM snap-create-post - After successfully creating snapshot
30 | REM snap-create-abort - When snapshot creation is aborted
31 | REM snap-remove-pre - Before removing snapshot
32 | REM snap-remove-post - After successfully removing snapshot
33 | REM snap-remove-abort - When snapshot removal is aborted
34 |
35 | IF "%CV4PVE_AUTOSNAP_PHASE%"=="clean-job-start" (
36 | REM Add custom logic here for cleanup job start
37 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="clean-job-end" (
38 | REM Add custom logic here for cleanup job end
39 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-job-start" (
40 | REM Add custom logic here for snapshot job start
41 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-job-end" (
42 | REM Add custom logic here for snapshot job end
43 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-create-pre" (
44 | REM Add custom logic here for before snapshot creation
45 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-create-post" (
46 | REM Add custom logic here for after successful snapshot creation
47 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-create-abort" (
48 | REM Add custom logic here for when snapshot creation is aborted
49 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-remove-pre" (
50 | REM Add custom logic here for before snapshot removal
51 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-remove-post" (
52 | REM Add custom logic here for after successful snapshot removal
53 | ) ELSE IF "%CV4PVE_AUTOSNAP_PHASE%"=="snap-remove-abort" (
54 | REM Add custom logic here for when snapshot removal is aborted
55 | ) ELSE (
56 | ECHO "unknown phase '%CV4PVE_AUTOSNAP_PHASE%'"
57 | EXIT 1
58 | )
--------------------------------------------------------------------------------
/hooks/hook-template.ps1:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: GPL-3.0-only
2 | # SPDX-FileCopyrightText: Copyright Corsinvest Srl
3 | #
4 | # Corsinvest automatic snapshot for Proxmox VE cv4pve-autosnap hook script.
5 | # Process environment variables as received from and set by cv4pve-autosnap.
6 |
7 | # Display all environment variables for debugging
8 | Write-Host "----------------------------------------------------------"
9 | Write-Host "CV4PVE_AUTOSNAP_PHASE: " $env:CV4PVE_AUTOSNAP_PHASE
10 | Write-Host "CV4PVE_AUTOSNAP_VMID: " $env:CV4PVE_AUTOSNAP_VMID
11 | Write-Host "CV4PVE_AUTOSNAP_VMNAME: " $env:CV4PVE_AUTOSNAP_VMNAME
12 | Write-Host "CV4PVE_AUTOSNAP_VMTYPE: " $env:CV4PVE_AUTOSNAP_VMTYPE
13 | Write-Host "CV4PVE_AUTOSNAP_LABEL: " $env:CV4PVE_AUTOSNAP_LABEL
14 | Write-Host "CV4PVE_AUTOSNAP_KEEP: " $env:CV4PVE_AUTOSNAP_KEEP
15 | Write-Host "CV4PVE_AUTOSNAP_SNAP_NAME: " $env:CV4PVE_AUTOSNAP_SNAP_NAME
16 | Write-Host "CV4PVE_AUTOSNAP_VMSTATE: " $env:CV4PVE_AUTOSNAP_VMSTATE
17 | Write-Host "CV4PVE_AUTOSNAP_DURATION: " $env:CV4PVE_AUTOSNAP_DURATION
18 | Write-Host "CV4PVE_AUTOSNAP_STATE: " $env:CV4PVE_AUTOSNAP_STATE
19 | Write-Host "CV4PVE_AUTOSNAP_DEBUG: " $env:CV4PVE_AUTOSNAP_DEBUG
20 | Write-Host "CV4PVE_AUTOSNAP_DRY_RUN: " $env:CV4PVE_AUTOSNAP_DRY_RUN
21 | Write-Host "----------------------------------------------------------"
22 |
23 | # Hook script phases:
24 | # clean-job-start - Before starting cleanup operation
25 | # clean-job-end - After finishing cleanup operation
26 | # snap-job-start - Before starting snapshot operation
27 | # snap-job-end - After finishing snapshot operation
28 | # snap-create-pre - Before creating snapshot
29 | # snap-create-post - After successfully creating snapshot
30 | # snap-create-abort - When snapshot creation is aborted
31 | # snap-remove-pre - Before removing snapshot
32 | # snap-remove-post - After successfully removing snapshot
33 | # snap-remove-abort - When snapshot removal is aborted
34 |
35 | # Main hook logic based on phase
36 | switch ($env:CV4PVE_AUTOSNAP_PHASE) {
37 | # Clean job phases
38 | "clean-job-start" {
39 | # Add custom logic here for cleanup job start
40 | }
41 | "clean-job-end" {
42 | # Add custom logic here for cleanup job end
43 | }
44 |
45 | # Snap job phases
46 | "snap-job-start" {
47 | # Add custom logic here for snapshot job start
48 | }
49 | "snap-job-end" {
50 | # Add custom logic here for snapshot job end
51 | }
52 |
53 | # Snapshot creation phases
54 | "snap-create-pre" {
55 | # Add custom logic here for before snapshot creation
56 | }
57 | "snap-create-post" {
58 | # Add custom logic here for after successful snapshot creation
59 | }
60 | "snap-create-abort" {
61 | # Add custom logic here for when snapshot creation is aborted
62 | }
63 |
64 | # Snapshot removal phases
65 | "snap-remove-pre" {
66 | # Add custom logic here for before snapshot removal
67 | }
68 | "snap-remove-post" {
69 | # Add custom logic here for after successful snapshot removal
70 | }
71 | "snap-remove-abort" {
72 | # Add custom logic here for when snapshot removal is aborted
73 | }
74 |
75 | default {
76 | Write-Error "Unknown phase '$($env:CV4PVE_AUTOSNAP_PHASE)'"
77 | exit 1
78 | }
79 | }
--------------------------------------------------------------------------------
/hooks/hook-template.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # SPDX-License-Identifier: GPL-3.0-only
3 | # SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | #
5 | # Corsinvest automatic snapshot for Proxmox VE cv4pve-autosnap hook script.
6 | # Process environment variables as received from and set by cv4pve-autosnap.
7 |
8 | hook() {
9 | echo "----------------------------------------------------------"
10 | echo "CV4PVE_AUTOSNAP_PHASE: $CV4PVE_AUTOSNAP_PHASE"
11 | echo "CV4PVE_AUTOSNAP_VMID: $CV4PVE_AUTOSNAP_VMID"
12 | echo "CV4PVE_AUTOSNAP_VMNAME: $CV4PVE_AUTOSNAP_VMNAME"
13 | echo "CV4PVE_AUTOSNAP_VMTYPE: $CV4PVE_AUTOSNAP_VMTYPE"
14 | echo "CV4PVE_AUTOSNAP_LABEL: $CV4PVE_AUTOSNAP_LABEL"
15 | echo "CV4PVE_AUTOSNAP_KEEP: $CV4PVE_AUTOSNAP_KEEP"
16 | echo "CV4PVE_AUTOSNAP_SNAP_NAME: $CV4PVE_AUTOSNAP_SNAP_NAME"
17 | echo "CV4PVE_AUTOSNAP_VMSTATE: $CV4PVE_AUTOSNAP_VMSTATE"
18 | echo "CV4PVE_AUTOSNAP_DURATION: $CV4PVE_AUTOSNAP_DURATION"
19 | echo "CV4PVE_AUTOSNAP_STATE: $CV4PVE_AUTOSNAP_STATE"
20 | echo "CV4PVE_AUTOSNAP_DEBUG: $CV4PVE_AUTOSNAP_DEBUG"
21 | echo "CV4PVE_AUTOSNAP_DRY_RUN: $CV4PVE_AUTOSNAP_DRY_RUN"
22 | echo "----------------------------------------------------------"
23 |
24 | # Hook script phases:
25 | # clean-job-start - Before starting cleanup operation
26 | # clean-job-end - After finishing cleanup operation
27 | # snap-job-start - Before starting snapshot operation
28 | # snap-job-end - After finishing snapshot operation
29 | # snap-create-pre - Before creating snapshot
30 | # snap-create-post - After successfully creating snapshot
31 | # snap-create-abort - When snapshot creation is aborted
32 | # snap-remove-pre - Before removing snapshot
33 | # snap-remove-post - After successfully removing snapshot
34 | # snap-remove-abort - When snapshot removal is aborted
35 |
36 | case "$CV4PVE_AUTOSNAP_PHASE" in
37 | # Clean job phases
38 | clean-job-start)
39 | # Add custom logic here for cleanup job start
40 | ;;
41 | clean-job-end)
42 | # Add custom logic here for cleanup job end
43 | ;;
44 |
45 | # Snap job phases
46 | snap-job-start)
47 | # Add custom logic here for snapshot job start
48 | ;;
49 | snap-job-end)
50 | # Add custom logic here for snapshot job end
51 | ;;
52 |
53 | # Snapshot creation phases
54 | snap-create-pre)
55 | # Add custom logic here for before snapshot creation
56 | ;;
57 | snap-create-post)
58 | # Add custom logic here for after successful snapshot creation
59 | ;;
60 | snap-create-abort)
61 | # Add custom logic here for when snapshot creation is aborted
62 | ;;
63 |
64 | # Snapshot removal phases
65 | snap-remove-pre)
66 | # Add custom logic here for before snapshot removal
67 | ;;
68 | snap-remove-post)
69 | # Add custom logic here for after successful snapshot removal
70 | ;;
71 | snap-remove-abort)
72 | # Add custom logic here for when snapshot removal is aborted
73 | ;;
74 |
75 | *)
76 | echo "unknown phase '$CV4PVE_AUTOSNAP_PHASE'"
77 | return 1
78 | ;;
79 | esac
80 | }
81 |
82 | hook
--------------------------------------------------------------------------------
/Corsinvest.ProxmoxVE.AutoSnap.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32210.238
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C6B0694C-362C-4BEE-8EBA-28ECF5780D57}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Corsinvest.ProxmoxVE.AutoSnap", "src\Corsinvest.ProxmoxVE.AutoSnap\Corsinvest.ProxmoxVE.AutoSnap.csproj", "{6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Corsinvest.ProxmoxVE.AutoSnap.Api", "src\Corsinvest.ProxmoxVE.AutoSnap.Api\Corsinvest.ProxmoxVE.AutoSnap.Api.csproj", "{857DC686-6FB8-4FA6-8534-B062768152E3}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|Any CPU = Release|Any CPU
18 | Release|x64 = Release|x64
19 | Release|x86 = Release|x86
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Debug|x64.ActiveCfg = Debug|Any CPU
25 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Debug|x64.Build.0 = Debug|Any CPU
26 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Debug|x86.ActiveCfg = Debug|Any CPU
27 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Debug|x86.Build.0 = Debug|Any CPU
28 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Release|x64.ActiveCfg = Release|Any CPU
31 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Release|x64.Build.0 = Release|Any CPU
32 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Release|x86.ActiveCfg = Release|Any CPU
33 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37}.Release|x86.Build.0 = Release|Any CPU
34 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Debug|x64.ActiveCfg = Debug|Any CPU
37 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Debug|x64.Build.0 = Debug|Any CPU
38 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Debug|x86.ActiveCfg = Debug|Any CPU
39 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Debug|x86.Build.0 = Debug|Any CPU
40 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Release|x64.ActiveCfg = Release|Any CPU
43 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Release|x64.Build.0 = Release|Any CPU
44 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Release|x86.ActiveCfg = Release|Any CPU
45 | {857DC686-6FB8-4FA6-8534-B062768152E3}.Release|x86.Build.0 = Release|Any CPU
46 | EndGlobalSection
47 | GlobalSection(SolutionProperties) = preSolution
48 | HideSolutionNode = FALSE
49 | EndGlobalSection
50 | GlobalSection(NestedProjects) = preSolution
51 | {6D4D450B-25C7-4CC8-AFB5-3EFCBD32EC37} = {C6B0694C-362C-4BEE-8EBA-28ECF5780D57}
52 | {857DC686-6FB8-4FA6-8534-B062768152E3} = {C6B0694C-362C-4BEE-8EBA-28ECF5780D57}
53 | EndGlobalSection
54 | GlobalSection(ExtensibilityGlobals) = postSolution
55 | SolutionGuid = {FF0CE8AE-82AF-4E55-B4CF-21752D47280F}
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 |
33 | # Visual Studio 2015/2017 cache/options directory
34 | .vs/
35 | # Uncomment if you have tasks that create the project's static files in wwwroot
36 | #wwwroot/
37 |
38 | # Visual Studio 2017 auto generated files
39 | Generated\ Files/
40 |
41 | # MSTest test Results
42 | [Tt]est[Rr]esult*/
43 | [Bb]uild[Ll]og.*
44 |
45 | # NUnit
46 | *.VisualState.xml
47 | TestResult.xml
48 | nunit-*.xml
49 |
50 | # Build Results of an ATL Project
51 | [Dd]ebugPS/
52 | [Rr]eleasePS/
53 | dlldata.c
54 |
55 | # Benchmark Results
56 | BenchmarkDotNet.Artifacts/
57 |
58 | # .NET Core
59 | project.lock.json
60 | project.fragment.lock.json
61 | artifacts/
62 |
63 | # StyleCop
64 | StyleCopReport.xml
65 |
66 | # Files built by Visual Studio
67 | *_i.c
68 | *_p.c
69 | *_h.h
70 | *.ilk
71 | *.meta
72 | *.obj
73 | *.iobj
74 | *.pch
75 | *.pdb
76 | *.ipdb
77 | *.pgc
78 | *.pgd
79 | *.rsp
80 | *.sbr
81 | *.tlb
82 | *.tli
83 | *.tlh
84 | *.tmp
85 | *.tmp_proj
86 | *_wpftmp.csproj
87 | *.log
88 | *.vspscc
89 | *.vssscc
90 | .builds
91 | *.pidb
92 | *.svclog
93 | *.scc
94 |
95 | # Chutzpah Test files
96 | _Chutzpah*
97 |
98 | # Visual C++ cache files
99 | ipch/
100 | *.aps
101 | *.ncb
102 | *.opendb
103 | *.opensdf
104 | *.sdf
105 | *.cachefile
106 | *.VC.db
107 | *.VC.VC.opendb
108 |
109 | # Visual Studio profiler
110 | *.psess
111 | *.vsp
112 | *.vspx
113 | *.sap
114 |
115 | # Visual Studio Trace Files
116 | *.e2e
117 |
118 | # TFS 2012 Local Workspace
119 | $tf/
120 |
121 | # Guidance Automation Toolkit
122 | *.gpState
123 |
124 | # ReSharper is a .NET coding add-in
125 | _ReSharper*/
126 | *.[Rr]e[Ss]harper
127 | *.DotSettings.user
128 |
129 | # JustCode is a .NET coding add-in
130 | .JustCode
131 |
132 | # TeamCity is a build add-in
133 | _TeamCity*
134 |
135 | # DotCover is a Code Coverage Tool
136 | *.dotCover
137 |
138 | # AxoCover is a Code Coverage Tool
139 | .axoCover/*
140 | !.axoCover/settings.json
141 |
142 | # Visual Studio code coverage results
143 | *.coverage
144 | *.coveragexml
145 |
146 | # NCrunch
147 | _NCrunch_*
148 | .*crunch*.local.xml
149 | nCrunchTemp_*
150 |
151 | # MightyMoose
152 | *.mm.*
153 | AutoTest.Net/
154 |
155 | # Web workbench (sass)
156 | .sass-cache/
157 |
158 | # Installshield output folder
159 | [Ee]xpress/
160 |
161 | # DocProject is a documentation generator add-in
162 | DocProject/buildhelp/
163 | DocProject/Help/*.HxT
164 | DocProject/Help/*.HxC
165 | DocProject/Help/*.hhc
166 | DocProject/Help/*.hhk
167 | DocProject/Help/*.hhp
168 | DocProject/Help/Html2
169 | DocProject/Help/html
170 |
171 | # Click-Once directory
172 | publish/
173 |
174 | # Publish Web Output
175 | *.[Pp]ublish.xml
176 | *.azurePubxml
177 | # Note: Comment the next line if you want to checkin your web deploy settings,
178 | # but database connection strings (with potential passwords) will be unencrypted
179 | *.pubxml
180 | *.publishproj
181 |
182 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
183 | # checkin your Azure Web App publish settings, but sensitive information contained
184 | # in these scripts will be unencrypted
185 | PublishScripts/
186 |
187 | # NuGet Packages
188 | *.nupkg
189 | # NuGet Symbol Packages
190 | *.snupkg
191 | # The packages folder can be ignored because of Package Restore
192 | **/[Pp]ackages/*
193 | # except build/, which is used as an MSBuild target.
194 | !**/[Pp]ackages/build/
195 | # Uncomment if necessary however generally it will be regenerated when needed
196 | #!**/[Pp]ackages/repositories.config
197 | # NuGet v3's project.json files produces more ignorable files
198 | *.nuget.props
199 | *.nuget.targets
200 |
201 | # Microsoft Azure Build Output
202 | csx/
203 | *.build.csdef
204 |
205 | # Microsoft Azure Emulator
206 | ecf/
207 | rcf/
208 |
209 | # Windows Store app package directories and files
210 | AppPackages/
211 | BundleArtifacts/
212 | Package.StoreAssociation.xml
213 | _pkginfo.txt
214 | *.appx
215 | *.appxbundle
216 | *.appxupload
217 |
218 | # Visual Studio cache files
219 | # files ending in .cache can be ignored
220 | *.[Cc]ache
221 | # but keep track of directories ending in .cache
222 | !?*.[Cc]ache/
223 |
224 | # Others
225 | ClientBin/
226 | ~$*
227 | *~
228 | *.dbmdl
229 | *.dbproj.schemaview
230 | *.jfm
231 | *.pfx
232 | *.publishsettings
233 | orleans.codegen.cs
234 |
235 | # Including strong name files can present a security risk
236 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
237 | #*.snk
238 |
239 | # Since there are multiple workflows, uncomment next line to ignore bower_components
240 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
241 | #bower_components/
242 |
243 | # RIA/Silverlight projects
244 | Generated_Code/
245 |
246 | # Backup & report files from converting an old project file
247 | # to a newer Visual Studio version. Backup files are not needed,
248 | # because we have git ;-)
249 | _UpgradeReport_Files/
250 | Backup*/
251 | UpgradeLog*.XML
252 | UpgradeLog*.htm
253 | ServiceFabricBackup/
254 | *.rptproj.bak
255 |
256 | # SQL Server files
257 | *.mdf
258 | *.ldf
259 | *.ndf
260 |
261 | # Business Intelligence projects
262 | *.rdl.data
263 | *.bim.layout
264 | *.bim_*.settings
265 | *.rptproj.rsuser
266 | *- [Bb]ackup.rdl
267 | *- [Bb]ackup ([0-9]).rdl
268 | *- [Bb]ackup ([0-9][0-9]).rdl
269 |
270 | # Microsoft Fakes
271 | FakesAssemblies/
272 |
273 | # GhostDoc plugin setting file
274 | *.GhostDoc.xml
275 |
276 | # Node.js Tools for Visual Studio
277 | .ntvs_analysis.dat
278 | node_modules/
279 |
280 | # Visual Studio 6 build log
281 | *.plg
282 |
283 | # Visual Studio 6 workspace options file
284 | *.opt
285 |
286 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
287 | *.vbw
288 |
289 | # Visual Studio LightSwitch build output
290 | **/*.HTMLClient/GeneratedArtifacts
291 | **/*.DesktopClient/GeneratedArtifacts
292 | **/*.DesktopClient/ModelManifest.xml
293 | **/*.Server/GeneratedArtifacts
294 | **/*.Server/ModelManifest.xml
295 | _Pvt_Extensions
296 |
297 | # Paket dependency manager
298 | .paket/paket.exe
299 | paket-files/
300 |
301 | # FAKE - F# Make
302 | .fake/
303 |
304 | # CodeRush personal settings
305 | .cr/personal
306 |
307 | # Python Tools for Visual Studio (PTVS)
308 | __pycache__/
309 | *.pyc
310 |
311 | # Cake - Uncomment if you are using it
312 | # tools/**
313 | # !tools/packages.config
314 |
315 | # Tabs Studio
316 | *.tss
317 |
318 | # Telerik's JustMock configuration file
319 | *.jmconfig
320 |
321 | # BizTalk build output
322 | *.btp.cs
323 | *.btm.cs
324 | *.odx.cs
325 | *.xsd.cs
326 |
327 | # OpenCover UI analysis results
328 | OpenCover/
329 |
330 | # Azure Stream Analytics local run output
331 | ASALocalRun/
332 |
333 | # MSBuild Binary and Structured Log
334 | *.binlog
335 |
336 | # NVidia Nsight GPU debugger configuration file
337 | *.nvuser
338 |
339 | # MFractors (Xamarin productivity tool) working folder
340 | .mfractor/
341 |
342 | # Local History for Visual Studio
343 | .localhistory/
344 |
345 | # BeatPulse healthcheck temp database
346 | healthchecksdb
347 |
348 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
349 | MigrationBackup/
350 |
351 | # Ionide (cross platform F# VS Code tools) working folder
352 | .ionide/
353 |
354 | *.parm
355 |
356 | artifacts_exe/
357 | dotnet-releaser.toml
--------------------------------------------------------------------------------
/src/Corsinvest.ProxmoxVE.AutoSnap/Commands.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: GPL-3.0-only
3 | * SPDX-FileCopyrightText: Copyright Corsinvest Srl
4 | */
5 |
6 | using System.CommandLine;
7 | using Corsinvest.ProxmoxVE.Api.Shared.Utils;
8 | using Corsinvest.ProxmoxVE.Api.Console.Helpers;
9 | using Corsinvest.ProxmoxVE.AutoSnap.Api;
10 | using Microsoft.Extensions.Logging;
11 |
12 | namespace Corsinvest.ProxmoxVE.AutoSnap;
13 |
14 | ///
15 | /// Console command.
16 | ///
17 | public class Commands
18 | {
19 | private string? _scriptHook;
20 | private readonly ILoggerFactory _loggerFactory;
21 | private readonly bool _dryRun;
22 | private readonly bool _debug;
23 | private readonly TextWriter _out;
24 |
25 | public Commands(RootCommand command, ILoggerFactory loggerFactory)
26 | {
27 | _dryRun = command.DryRunIsActive();
28 | _debug = command.DebugIsActive();
29 | _out = Console.Out;
30 |
31 | _loggerFactory = loggerFactory;
32 |
33 | var optVmIds = command.VmIdsOrNamesOption();
34 | optVmIds.Required = true;
35 |
36 | var optTimeout = command.TimeoutOption();
37 | optTimeout.DefaultValueFactory = (_) => 30L;
38 |
39 | var optTimestampFormat = command.AddOption("--timestamp-format", $"Specify different timestamp format");
40 | optTimestampFormat.DefaultValueFactory = (_) => Application.DefaultTimestampFormat;
41 |
42 | var optMaxPercentageStorage = command.AddOption("--max-perc-storage", "Max percentage storage")
43 | .AddValidatorRange(1, 100);
44 | optMaxPercentageStorage.DefaultValueFactory = (_) => 95;
45 |
46 | Snap(command, optVmIds, optTimeout, optTimestampFormat, optMaxPercentageStorage);
47 | Clean(command, optVmIds, optTimeout, optTimestampFormat);
48 | Status(command, optVmIds, optTimestampFormat);
49 | }
50 |
51 | private async Task CreateAppAsync(RootCommand command)
52 | {
53 | var app = new Application(await command.ClientTryLoginAsync(_loggerFactory), _loggerFactory, _out, _dryRun);
54 | app.PhaseEvent += App_PhaseEvent;
55 | return app;
56 | }
57 |
58 | private void App_PhaseEvent(object? sender, PhaseEventArgs e)
59 | {
60 | if (_scriptHook == null || !File.Exists(_scriptHook)) { return; }
61 |
62 | var (stdOut, exitCode) = ShellHelper.Execute(_scriptHook,
63 | true,
64 | new Dictionary(e.Environments)
65 | {
66 | { "CV4PVE_AUTOSNAP_DEBUG", _debug ? "1" : "0" },
67 | { "CV4PVE_AUTOSNAP_DRY_RUN", _dryRun ? "1" : "0" },
68 | },
69 | _out,
70 | _dryRun,
71 | _debug);
72 |
73 | if (exitCode != 0) { _out.WriteLine($"Script return code: {exitCode}"); }
74 | if (!string.IsNullOrWhiteSpace(stdOut)) { _out.Write(stdOut); }
75 | }
76 |
77 | private static Option OptionLabel(Command command)
78 | => command.AddOption("--label", "Is usually 'hourly', 'daily', 'weekly', or 'monthly'");
79 |
80 | private static Option OptionKeep(Command command, int min = 1)
81 | {
82 | var opt = command.AddOption("--keep", "Specify the number which should will keep")
83 | .AddValidatorRange(min, 100);
84 |
85 | opt.Required = true;
86 | return opt;
87 | }
88 |
89 | private void Status(RootCommand command, Option optVmIds, Option optTimestampFormat)
90 | {
91 | var cmd = command.AddCommand("status", "Get list of all auto snapshots");
92 | var optLabel = OptionLabel(cmd);
93 | var optOutput = cmd.TableOutputOption();
94 |
95 | cmd.SetAction(async (parseResult) =>
96 | {
97 | var app = await CreateAppAsync(command);
98 | var snapshots = await app.StatusAsync(parseResult.GetValue(optVmIds)!,
99 | parseResult.GetValue(optLabel)!,
100 | parseResult.GetValue(optTimestampFormat)!);
101 | if (snapshots.Any())
102 | {
103 | var rows = new List