[libvirt] [sandbox 08/11] virt-sandbox-image: add a virt-builder source

Cédric Bosdonnat cbosdonnat at suse.com
Wed Sep 23 07:53:38 UTC 2015


Allow virt-sandbox-image to pull templates from virt-builder and run
sandboxes on top of them.
---
 libvirt-sandbox.spec.in                            |   1 +
 libvirt-sandbox/image/cli.py                       |   1 +
 libvirt-sandbox/image/sources/Makefile.am          |   1 +
 libvirt-sandbox/image/sources/VirtBuilderSource.py | 136 +++++++++++++++++++++
 libvirt-sandbox/image/template.py                  |   2 +
 5 files changed, 141 insertions(+)
 create mode 100644 libvirt-sandbox/image/sources/VirtBuilderSource.py

diff --git a/libvirt-sandbox.spec.in b/libvirt-sandbox.spec.in
index 54fde55..f84eabc 100644
--- a/libvirt-sandbox.spec.in
+++ b/libvirt-sandbox.spec.in
@@ -36,6 +36,7 @@ Requires: systemd >= 198
 Requires: pygobject3-base
 Requires: libselinux-python
 Requires: %{name}-libs = %{version}-%{release}
+Requires: %{_bindir}/virt-builder
 
 %package libs
 Group: Development/Libraries
diff --git a/libvirt-sandbox/image/cli.py b/libvirt-sandbox/image/cli.py
index e991e2d..fb1104a 100755
--- a/libvirt-sandbox/image/cli.py
+++ b/libvirt-sandbox/image/cli.py
@@ -188,6 +188,7 @@ Example supported URI formats:
   docker:///ubuntu?tag=15.04
   docker://username:password@index.docker.io/private/image
   docker://registry.access.redhat.com/rhel6
+  virt-builder:///fedora-20
 """)
     return parser
 
diff --git a/libvirt-sandbox/image/sources/Makefile.am b/libvirt-sandbox/image/sources/Makefile.am
index 069557d..52e9a7e 100644
--- a/libvirt-sandbox/image/sources/Makefile.am
+++ b/libvirt-sandbox/image/sources/Makefile.am
@@ -4,6 +4,7 @@ pythonimage_DATA = \
 	__init__.py \
 	Source.py \
 	DockerSource.py \
+	VirtBuilderSource.py \
 	$(NULL)
 
 EXTRA_DIST = $(pythonimage_DATA)
diff --git a/libvirt-sandbox/image/sources/VirtBuilderSource.py b/libvirt-sandbox/image/sources/VirtBuilderSource.py
new file mode 100644
index 0000000..4a7e383
--- /dev/null
+++ b/libvirt-sandbox/image/sources/VirtBuilderSource.py
@@ -0,0 +1,136 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2015 SUSE LLC
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+# Author: Cedric Bosdonnat <cbosdonnat at suse.com>
+#
+
+from Source import Source
+import os
+import os.path
+import subprocess
+
+class VirtBuilderSource(Source):
+
+    def _get_template_name(self, template):
+        # We shouldn't have '/' in the names, but let's make sure
+        # nobody can try to alter the folders structure later.
+        return template.path[1:].replace('/', '_')
+
+    def download_template(self, template, templatedir):
+        # We don't do anything here: virt-builder will do it for us in
+        # the create action
+        pass
+
+    def _check_disk_format(self,format):
+        supportedFormats = ['qcow2', 'raw']
+        if not format in supportedFormats:
+            raise ValueError(["Unsupported image format %s" % format])
+
+    def create_template(self, template, templatedir,
+                        connect=None, format=None):
+        # FIXME Force qcow2 format: do we really want people to mess with that?
+        if not os.path.exists(templatedir):
+            os.makedirs(templatedir)
+
+        # Get the image using virt-builder
+        templatename = self._get_template_name(template)
+        imagepath_original = "%s/%s-original.qcow2" % (templatedir, templatename)
+        imagepath = "%s/%s.%s" % (templatedir, templatename, format)
+        cmd = ["virt-builder", templatename,
+               "-o", imagepath_original, "--format", "qcow2"]
+        subprocess.call(cmd)
+
+        # We need to convert this image into a single partition one.
+        tarfile = "%s/%s.tar" % (templatedir, templatename)
+        cmd = ["virt-tar-out", "-a", imagepath_original, "/", tarfile]
+        subprocess.call(cmd)
+
+        os.unlink(imagepath_original)
+
+        cmd = ["qemu-img", "create", "-q", "-f", format, imagepath, "10G"]
+        subprocess.call(cmd)
+
+        self.format_disk(imagepath, format, connect)
+        self._extract_tarball(imagepath, format, tarfile, connect)
+        os.unlink(tarfile)
+
+
+    def delete_template(self, template, templatedir):
+        # Check for running sandboxes using this template before killing it
+        images = self._get_template_uses(template, templatedir)
+        if len(images) != 0:
+            imagesStr = ", ".join(images)
+            raise ValueError(["Images still using the template: %s" % imagesStr])
+
+        os.unlink("%s/%s.qcow2" % (templatedir, self._get_template_name(template)))
+        os.unlink("%s/%s.uses" % (templatedir, self._get_template_name(template)))
+
+    def _get_template_uses(self, template, templatedir):
+        uses = open("%s/%s.uses" % (templatedir, self._get_template_name(template)), "r")
+        lines = uses.read()
+        uses.close()
+        return [l for l in lines.split("\n") if l != ""]
+
+    def post_run(self, template, templatedir, imagename):
+        images = self._get_template_uses(template, templatedir)
+        images.remove(imagename)
+
+        uses = open("%s/%s.uses" % (templatedir, self._get_template_name(template)), "w")
+        uses.write("\n".join(images))
+        uses.close()
+
+    def get_command(self, template, templatedir, userargs):
+        return userargs
+
+    def get_disk(self,template, templatedir, imagedir, sandboxname):
+        diskfile = "%s/%s.qcow2" % (templatedir, self._get_template_name(template))
+        tempfile = imagedir + "/" + sandboxname + ".qcow2"
+        if not os.path.exists(imagedir):
+            os.makedirs(imagedir)
+        cmd = ["qemu-img", "create", "-q",
+               "-f", "qcow2",
+               "-o", "backing_fmt=qcow2,backing_file=%s" % diskfile,
+               tempfile]
+        subprocess.call(cmd)
+
+        # Add the image to the uses files
+        uses = open("%s/%s.uses" % (templatedir,
+                                    self._get_template_name(template)), "a")
+        uses.write("%s\n" % sandboxname)
+        uses.close()
+        return tempfile
+
+    def get_env(self,template, templatedir):
+        return []
+
+    def _extract_tarball(self, diskfile, format, tarfile, connect):
+        cmd = ['virt-sandbox']
+        if connect is not None:
+            cmd.append("-c")
+            cmd.append(connect)
+        cmd.append("-p")
+        params = ['-m',
+                  'host-image:/mnt=%s,format=%s' % (diskfile, format),
+                  '--',
+                  '/bin/tar',
+                  'xf',
+                  '%s' % tarfile,
+                  '-C',
+                  '/mnt']
+        cmd = cmd + params
+        subprocess.call(cmd)
diff --git a/libvirt-sandbox/image/template.py b/libvirt-sandbox/image/template.py
index 4713b0a..efdd845 100644
--- a/libvirt-sandbox/image/template.py
+++ b/libvirt-sandbox/image/template.py
@@ -43,6 +43,8 @@ class Template(object):
         docker:///ubuntu
 
         docker+https://index.docker.io/ubuntu?tag=latest
+
+        virt-builder:///fedora-20
         """
 
         self.source = source
-- 
2.1.4




More information about the libvir-list mailing list