Skip to content

joroec/virsnap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

virsnap

virsnap is a CLI snapshot utility for libvirt. The small tool is designed for the automated creation of virtual machine snapshots (e.g. KVM domains). In addition to creating snapshots, the tool allows to remove expired snapshots if there are enough newer snapshots for this virtual machine.

Usage

virsnap is a small tool that eases the automated creation and deletion of VM snapshots.

Usage:
  virsnap [command]

Available Commands:
  clean       Remove expired snapshots from the system
  create      Create a snapshot of one or more virtual machines
  export      Export a VM by copying the hard drive images to an output directory
  help        Help about any command
  list        List snapshots of one or more virtual machines
  version     Print the version of the software

Flags:
  -h, --help                  help for virsnap
  -e, --log-encoding string   sets the log encoding (console, json) (default "console")
  -l, --log-level string      sets the log level (debug, info, warn, error) (default "info")
  -u, --socket-url string     sets the libvirt socket URL to connect to (default "qemu:///system")

Use "virsnap [command] --help" for more information about a command.

List snapshots

joroec@host:~ $ virsnap list "^examplevm[0-9]*$"
examplevm1 (current state: DOMAIN_PAUSED, 1 snapshots total)
+------------------------+-------------------------------+---------+
|        SNAPSHOT        |             TIME              |  STATE  |
+------------------------+-------------------------------+---------+
| virsnap_heuristic_bose | Thu Jul 11 08:37:50 CEST 2019 | shutoff |
+------------------------+-------------------------------+---------+

examplevm2 (current state: DOMAIN_RUNNING, 2 snapshots total)
+--------------------------+-------------------------------+---------+
|         SNAPSHOT         |             TIME              |  STATE  |
+--------------------------+-------------------------------+---------+
| virsnap_hardcore_galileo | Thu Jul 11 08:39:51 CEST 2019 | running |
| virsnap_angry_hypatia    | Thu Jul 11 08:40:15 CEST 2019 | shutoff |
+--------------------------+-------------------------------+---------+
joroec@host:~ $ virsnap list
examplevm1 (current state: DOMAIN_SHUTOFF, 1 snapshots total)
+------------------------+-------------------------------+---------+
|        SNAPSHOT        |             TIME              |  STATE  |
+------------------------+-------------------------------+---------+
| virsnap_heuristic_bose | Thu Jul 11 08:37:50 CEST 2019 | shutoff |
+------------------------+-------------------------------+---------+

examplevm2 (current state: DOMAIN_RUNNING, 2 snapshots total)
+--------------------------+-------------------------------+---------+
|         SNAPSHOT         |             TIME              |  STATE  |
+--------------------------+-------------------------------+---------+
| virsnap_hardcore_galileo | Thu Jul 11 08:39:51 CEST 2019 | running |
| virsnap_angry_hypatia    | Thu Jul 11 08:40:15 CEST 2019 | shutoff |
+--------------------------+-------------------------------+---------+

othervm1 (current state: DOMAIN_RUNNING, 1 snapshots total)
+-------------------------+-------------------------------+---------+
|        SNAPSHOT         |             TIME              |  STATE  |
+-------------------------+-------------------------------+---------+
| virsnap_gracious_turing | Thu Jul 11 09:05:36 CEST 2019 | shutoff |
+-------------------------+-------------------------------+---------+

Create snapshots

joroec@host:~ $ virsnap create --shutdown --force --verbose "^examplevm2$"
DEBU[0000] Trying to shutdown domain "examplevm2" gracefully.
DEBU[0000] Sending shutdown request to VM "examplevm2".
DEBU[0000] Waiting vor the VM "examplevm2" to shutdown.
DEBU[0065] Beginning creation of snapshot for VM "examplevm2".
INFO[0065] Created snapshot "virsnap_condescending_fermat" for VM "examplevm2".
DEBU[0065] Restoring previous state of vm "examplevm2"
DEBU[0066] Leaving creation of snapshot "virsnap_condescending_fermat" for VM "examplevm2".

Remove expired snapshots

The parameter k specifies the versions to keep:

joroec@host:~ $ virsnap list "^examplevm2$"
examplevm2 (current state: DOMAIN_RUNNING, 4 snapshots total)
+------------------------------+-------------------------------+---------+
|           SNAPSHOT           |             TIME              |  STATE  |
+------------------------------+-------------------------------+---------+
| virsnap_hardcore_galileo     | Thu Jul 11 08:39:51 CEST 2019 | running |
| virsnap_angry_hypatia        | Thu Jul 11 08:40:15 CEST 2019 | shutoff |
| virsnap_cranky_sammet        | Thu Jul 11 09:07:55 CEST 2019 | shutoff |
| virsnap_condescending_fermat | Thu Jul 11 09:09:09 CEST 2019 | shutoff |
+------------------------------+-------------------------------+---------+


joroec@host:~ $ virsnap clean -y -k 2 "^examplevm2$"
INFO[0000] Removing snapshot "virsnap_hardcore_galileo" of VM "examplevm2".
INFO[0000] Removing snapshot "virsnap_angry_hypatia" of VM "examplevm2".


joroec@host:~ $ virsnap list "^examplevm2$"
examplevm2 (current state: DOMAIN_RUNNING, 2 snapshots total)
+------------------------------+-------------------------------+---------+
|           SNAPSHOT           |             TIME              |  STATE  |
+------------------------------+-------------------------------+---------+
| virsnap_cranky_sammet        | Thu Jul 11 09:07:55 CEST 2019 | shutoff |
| virsnap_condescending_fermat | Thu Jul 11 09:09:09 CEST 2019 | shutoff |
+------------------------------+-------------------------------+---------+

Export VMs (incl. snapshots)

You need to have rsync installed on your system to use this feature.

joroec@host:~ $ virsnap export --output-dir "/home/joroe/backup" --snapshot true --log-level debug "^testvm$"
2019-07-29T21:11:54.421+0200    DEBUG   Logger initialized
2019-07-29T21:11:54.424+0200    DEBUG   starting to shutdown VM testvm
2019-07-29T21:11:54.424+0200    DEBUG   Domain 'testvm' is already shutoff.
2019-07-29T21:11:54.424+0200    DEBUG   finshed shutdown process of VM testvm
2019-07-29T21:11:54.424+0200    DEBUG   Beginning creation of snapshot for VM 'testvm'.
2019-07-29T21:11:54.534+0200    INFO    Created snapshot 'virsnap_pensive_kalam' for VM 'testvm'
2019-07-29T21:11:54.534+0200    DEBUG   starting export process of VM testvm
sending incremental file list
testvm.qcow2
 21,479,622,103 100%  245.01MB/s    0:01:23 (xfr#1, to-chk=0/1)

sent 21,484,866,247 bytes  received 35 bytes  254,258,772.57 bytes/sec
total size is 21,479,622,103  speedup is 1.00
2019-07-29T21:13:18.151+0200    INFO    Exported VM testvm
2019-07-29T21:13:18.151+0200    DEBUG   restoring previous state of vm 'testvm'
2019-07-29T21:13:18.154+0200    DEBUG   Domain 'testvm' is already shutoff.

Dependencies

virsnap needs go 1.12+ and uses go modules for dependency management. For more information on go modules, see the corresponding go modules documentation.

Installation

First make sure libvirt is installed. You can use your local packet manager or compile it by yourself.

On Ubuntu, you can use apt:

$ sudo apt-get install libvirt-bin libvirt-dev

On macOS, you can use Homebrew:

$ brew install libvirt

To install virsnap, execute the following in your shell:

$ git clone http://github.com/joroec/virsnap
$ cd virsnap
$ go build -o ./bin/virsnap ./cmd/virsnap
$ sudo install ./bin/virsnap /usr/local/bin/virsnap

This will compile and link the virsnap binary and install it into /usr/local/bin/virsnap. No other file is installed in system directories.

To remove the tool from your system, execute the following in your shell:

$ sudo rm /usr/local/bin/virsnap

Periodical snapshots

To use virsnap for regular snapshotting your virtual machines, determine your init system and instruct it to periodically call virsnap. There are exemplary init configurations in the init directory of this repository.

systemd

Adjust the files init/systemd/virsnap.service and init/systemd/virsnap.timer to your needs. After this, copy both files to /etc/systemd/system.

You can check that your service is found:

$ systemctl status virsnap
● virsnap.service - A CLI snapshot systemd service for libvirt
   Loaded: loaded (/etc/systemd/system/virsnap.service; static; vendor preset: enabled)
   Active: inactive (dead)

Test a single execution of virsnap if desired:

$ systemctl start virsnap

You can watch the logs with:

$ journalctl -u virsnap

Start periodic execution:

$ systemctl enable virsnap.timer

Check if the timer is activated:

$ systemctl status virsnap.timer

Contributing

See CONTRIBUTING.md file.

FAQ

How do I install golang 1.12?

You should always prefer your distribution's packet manager for installing software. If your packet manager does not offer a suitable packet for golang 1.12, you can install it manually. The following are the commands needed for the manual installation on a Ubuntu 18.04 LTS system.

I prefer to compile software by myself. Alternatively, you can use a release link to download a binary release of golang. You can find the direct link to the current go version at the release page. The following will build golang from source:

Visit the official build guide for more information.

Newer versions of the golang compiler are written completely in golang. In compiler construction, there is typically a bootstrap version of a compiler written in another language (e.g. C) to compile the actual compiler. For golang, this is the release branch release-branch.go1.4 which is a bootstrap compiler for golang written in C. You need to have a GCC or Clang compiler installed on your system.

Start with downloading the golang source code:

$ sudo apt-get update && sudo apt-get upgrade
$ git clone https://github.com/golang/go
$ cd go

Now, build the bootstrap compiler:

$ git checkout release-branch.go1.4
$ cd src
$ ./all.bash
...
net/rpc/jsonrpc

Build complete; skipping tests.
To force tests, set GO14TESTS=1 and re-run, but expect some failures.
$ cd ../../
$ cp -r go /tmp/go-bootstrap

Now, change back to the desired release brach and compile the golang compiler:

$ cd go
$ git checkout go1.12.6
$ git clean -df
$ cd src
$ GOROOT_BOOTSTRAP=/tmp/go-bootstrap GOROOT_FINAL=/usr/local/lib/go GOBIN=/usr/local/bin ./make.bash
Building Go cmd/dist using /tmp/go-bootstrap.
Building Go toolchain1 using /tmp/go-bootstrap.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /home/.../go
Installed commands in /home/.../go/bin

The binaries expect /home/.../go to be copied or moved to /usr/local/lib/go

In the last step, you need to install your newly compiled go compiler to your system:

$ cd ../../
$ sudo cp -r go /usr/local/lib/go
$ sudo ln -s /usr/local/lib/go/bin/go /usr/local/bin/go
$ sudo ln -s /usr/local/lib/go/bin/gofmt /usr/local/bin/gofmt

To clean your system from the intermediate products and repositories, you can execute the following commands:

$ rm -rf /tmp/go-bootstrap
$ rm -rf go

Finally, you can set up your golang workspace:

$ mkdir ~/.go-workspace

and add to your ~/.bash_profile / .zshrc:

export GOPATH=$HOME/.go-workspace

Authors

See AUTHORS file.

License

MIT License. See LICENSE file.