qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
	dietmar@proxmox.com, Stefan Hajnoczi <stefanha@redhat.com>,
	Markus Armbruster <armbru@redhat.com>
Subject: [Qemu-devel] [RFC 8/8] Add backup.py tool
Date: Sat,  9 Mar 2013 23:22:28 +0100	[thread overview]
Message-ID: <1362867748-30528-9-git-send-email-stefanha@redhat.com> (raw)
In-Reply-To: <1362867748-30528-1-git-send-email-stefanha@redhat.com>

The backup.py tool connects to a running guest's QMP monitor and
orchestrates a live backup.

To invoke a backup:

  qemu -qmp unix:/tmp/monitor.sock,server,nowait ...
  backup.py /tmp/monitor.sock backup-20130301.vma

The script uses vma-writer.py to bundle vmstate and disk backups into a
single backup archive file.  vma-writer.py is launched as a separate
process.

First a 'migrate' command is used to send the vmstate to the writer
process and pause the guest.

Then the 'block-backup' command is used to send a point-in-time copy of
all disks to the writer process before resuming the guest.

The guest continues running while disks are being backed up over NBD.

Finally, the backup completes when the 'block-backup' block jobs finish.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 backup.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)
 create mode 100644 backup.py

diff --git a/backup.py b/backup.py
new file mode 100644
index 0000000..2e0b179
--- /dev/null
+++ b/backup.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+#
+# Live backup tool for QEMU
+#
+# Copyright 2013 Red Hat, Inc. and/or its affiliates
+#
+# Authors:
+#   Stefan Hajnoczi <stefanha@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+import sys; sys.path.append('QMP')
+import qmp
+import subprocess
+
+MIGRATE_PATH = '/tmp/migrate.sock'
+NBD_PATH = '/tmp/nbd.sock'
+
+def find_backup_drives(mon):
+    '''Return list of devices that should be backed up'''
+    result = []
+    for info in mon.command('query-block'):
+        # Skip empty drives
+        if 'inserted' not in info:
+            continue
+
+        # Skip read-only drives
+        if info['inserted']['ro']:
+            continue
+
+        result.append((info['device'], info['inserted']['virtual_size']))
+    return result
+
+def spawn_writer_process(filename, drives):
+    '''Return Popen instance for vma-writer.py process'''
+    args = ['python', 'vma-writer.py',
+            '--output', filename,
+            '--incoming', MIGRATE_PATH,
+            '--nbd', NBD_PATH]
+    for name, size in drives:
+        args.extend(('--drive', 'name=%s,size=%s' % (name, size)))
+    writer = subprocess.Popen(args, stdout=subprocess.PIPE)
+    writer.stdout.readline() # Wait for "Ready"
+    return writer
+
+def main(args):
+    mon = qmp.QEMUMonitorProtocol(args[1])
+    mon.connect()
+
+    drives = find_backup_drives(mon)
+    writer = spawn_writer_process(args[2], drives)
+
+    sys.stderr.write('Running migration...\n')
+    mon.command('migrate', uri='unix:' + MIGRATE_PATH)
+    while True:
+        evt = mon.pull_event(wait=True)
+        if evt['event'] == 'STOP':
+            break
+
+    sys.stderr.write('Running block-backup...\n')
+    for name, _ in drives:
+        mon.command('block-backup',
+                    device=name,
+                    target='nbd+unix:///%s?socket=%s' % (name, NBD_PATH),
+                    format='raw',
+                    mode='existing')
+    mon.command('cont')
+    pending_drives = set(name for name, _ in drives)
+    while pending_drives:
+        evt = mon.pull_event(wait=True)
+        if evt['event'] == 'BLOCK_JOB_COMPLETED':
+            name = evt['data']['device']
+            sys.stderr.write('Finished device "%s"\n' % name)
+            pending_drives.discard(name)
+    sys.stderr.write('Backup complete, terminating writer process\n')
+
+    # Wait for writer process to terminate and print its output
+    sys.stdout.write(writer.communicate()[0])
+
+    mon.close()
+
+if __name__ == '__main__':
+    main(sys.argv)
-- 
1.8.1.4

  parent reply	other threads:[~2013-03-09 22:23 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-09 22:22 [Qemu-devel] [RFC 0/8] block: Live backup prototype Stefan Hajnoczi
2013-03-09 22:22 ` [Qemu-devel] [RFC 1/8] block: add virtual_size to query-block QMP output Stefan Hajnoczi
2013-03-11 17:35   ` Eric Blake
2013-03-09 22:22 ` [Qemu-devel] [RFC 2/8] add basic backup support to block driver Stefan Hajnoczi
2013-03-09 22:22 ` [Qemu-devel] [RFC 3/8] backup: write to BlockDriverState instead of BackupDumpFunc Stefan Hajnoczi
2013-03-10 10:05   ` Dietmar Maurer
2013-03-10 11:13     ` Stefan Hajnoczi
2013-03-09 22:22 ` [Qemu-devel] [RFC 4/8] block: add block_backup QMP command Stefan Hajnoczi
2013-03-14 21:46   ` Eric Blake
2013-03-14 21:52   ` Eric Blake
2013-03-15  8:38     ` Stefan Hajnoczi
2013-04-11 12:32   ` Paolo Bonzini
2013-03-09 22:22 ` [Qemu-devel] [RFC 5/8] Add nbd server Python module Stefan Hajnoczi
2013-03-09 22:22 ` [Qemu-devel] [RFC 6/8] Add VMA backup archive writer " Stefan Hajnoczi
2013-03-09 22:22 ` [Qemu-devel] [RFC 7/8] Add vma-writer.py tool Stefan Hajnoczi
2013-03-09 22:22 ` Stefan Hajnoczi [this message]
2013-03-10  9:14 ` [Qemu-devel] [RFC 0/8] block: Live backup prototype Dietmar Maurer
2013-03-10 10:19   ` Stefan Hajnoczi
2013-03-10 10:38     ` Dietmar Maurer
2013-03-10 11:09       ` Stefan Hajnoczi
2013-03-10 10:50     ` Dietmar Maurer
2013-03-10 11:10       ` Stefan Hajnoczi
2013-03-11  8:58         ` Dietmar Maurer
2013-03-11  9:26         ` Dietmar Maurer
2013-03-11 14:27           ` Stefan Hajnoczi
2013-03-11 15:00             ` Dietmar Maurer
2013-03-11 17:11               ` Stefan Hajnoczi
2013-03-10  9:57 ` Dietmar Maurer
2013-03-10 10:41   ` Stefan Hajnoczi
2013-03-12  9:18   ` Kevin Wolf
2013-03-12 10:50     ` Stefan Hajnoczi
2013-03-12 11:15       ` Dietmar Maurer
2013-03-12 12:18         ` Stefan Hajnoczi
2013-03-12 11:22       ` Kevin Wolf
2013-03-12 11:31         ` Dietmar Maurer
2013-03-12 11:37         ` Dietmar Maurer
2013-03-12 12:17         ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1362867748-30528-9-git-send-email-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=armbru@redhat.com \
    --cc=dietmar@proxmox.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).