summaryrefslogtreecommitdiffstats
path: root/sources.py
diff options
context:
space:
mode:
Diffstat (limited to 'sources.py')
-rw-r--r--sources.py104
1 files changed, 104 insertions, 0 deletions
diff --git a/sources.py b/sources.py
new file mode 100644
index 0000000..886ca27
--- /dev/null
+++ b/sources.py
@@ -0,0 +1,104 @@
+#!/usr/bin/python
+# Authors: Cedric Bosdonnat <cbosdonnat@suse.com>
+#
+# Copyright (C) 2017 SUSE, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import hashlib
+import json
+import shutil
+import subprocess
+import tempfile
+import getpass
+
+def checksum(path, sum_type, sum_expected):
+ algorithm = getattr(hashlib, sum_type)
+ try:
+ fd = open(path, 'rb')
+ content = fd.read()
+ fd.close()
+
+ actual = algorithm(content).hexdigest()
+ return actual == sum_expected
+ except:
+ return False
+
+
+class FileSource:
+ def __init__(self, url, insecure):
+ self.path = url.path
+
+ def unpack(dest):
+ # We assume tar is intelligent enough to find out
+ # the compression type to use and to strip leading '/',
+ # not sure if this is safe enough
+ subprocess.check_call(["tar", "-C", dest, "xf", self.path])
+
+class DockerSource:
+ def __init__(self, url, username, password, insecure):
+ self.registry = url.netloc
+ self.image = url.path
+ self.username = username
+ self.password = password
+ self.insecure = insecure
+ if self.image.startswith('/'):
+ self.image = self.image[1:]
+
+ def unpack(self, dest):
+ tmpDest = tempfile.mkdtemp('virt-bootstrap')
+
+ try:
+ # Run skopeo copy into a tmp folder
+ # Note: we don't want to expose --src-cert-dir to users as
+ # they should place the certificates in the system
+ # folders for broader enablement
+ cmd = ["skopeo", "copy",
+ "docker://%s/%s" % (self.registry, self.image),
+ "dir:/%s" % tmpDest]
+ if self.insecure:
+ cmd.append('--src-tls-verify=false')
+ if self.username:
+ if not self.password:
+ self.password = getpass.getpass()
+ cmd.append('--src-creds=%s:%s' % (self.username, self.password))
+
+
+ subprocess.check_call(cmd)
+
+ # Get the layers list from the manifest
+ mf = open("%s/manifest.json" % tmpDest, "r")
+ manifest = json.load(mf)
+
+ # FIXME We suppose the layers are ordered, is this true?
+ for layer in manifest['layers']:
+ sum_type, sum_value = layer['digest'].split(':')
+ layer_file = "%s/%s.tar" % (tmpDest, sum_value)
+ print 'layer_file: (%s) %s' % (sum_type, layer_file)
+
+ # Verify the checksum
+ if not checksum(layer_file, sum_type, sum_value):
+ raise Exception("Digest not matching: %s" % layer['digest'])
+
+ # untar layer into dest
+ subprocess.check_call(["tar", "xf", layer_file, "-C", dest])
+
+ except:
+ shutil.rmtree(tmpDest)
+ raise
+
+ shutil.rmtree(tmpDest)
+