summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRadostin Stoyanov <rstoyanov1@gmail.com>2017-06-16 11:08:19 +0100
committerCédric Bosdonnat <cbosdonnat@suse.com>2017-06-19 14:55:51 +0200
commitb63973fecc2d3bc7b93fe3354088661d343e18d6 (patch)
tree50d2ec678c89933717c6b98edb8de4dba13b0307 /src
parent2366b18b529288138fdbe9f2a7820bd7959109f4 (diff)
downloadvirt-bootstrap.git-b63973fecc2d3bc7b93fe3354088661d343e18d6.tar.gz
virt-bootstrap.git-b63973fecc2d3bc7b93fe3354088661d343e18d6.tar.xz
virt-bootstrap.git-b63973fecc2d3bc7b93fe3354088661d343e18d6.zip
Add automated check for code style
To run the code style checks, run `python setup.py pylint` Only errors could be reported using the option --errors-only. Could be useful to run in interactive git rebase Fix the reported pylint errors as well
Diffstat (limited to 'src')
-rw-r--r--src/virtBootstrap/sources.py93
-rwxr-xr-xsrc/virtBootstrap/virt_bootstrap.py48
2 files changed, 89 insertions, 52 deletions
diff --git a/src/virtBootstrap/sources.py b/src/virtBootstrap/sources.py
index a1f8544..87278d2 100644
--- a/src/virtBootstrap/sources.py
+++ b/src/virtBootstrap/sources.py
@@ -15,6 +15,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Class definitions which process container image or
+archive from source and unpack them in destination directory.
+"""
+
import hashlib
import json
import shutil
@@ -26,22 +31,24 @@ from subprocess import call, CalledProcessError, PIPE, Popen
# Default virtual size of qcow2 image
DEF_QCOW2_SIZE = '5G'
-# default_image_dir - Path where Docker images (tarballs) will be stored
if os.geteuid() == 0:
- virt_sandbox_connection = "lxc:///"
- default_image_dir = "/var/lib/virt-bootstrap/docker_images"
+ LIBVIRT_CONN = "lxc:///"
+ DEFAULT_IMG_DIR = "/var/lib/virt-bootstrap/docker_images"
else:
- virt_sandbox_connection = "qemu:///session"
- default_image_dir = \
- os.environ['HOME'] + "/.local/share/virt-bootstrap/docker_images"
+ LIBVIRT_CONN = "qemu:///session"
+ DEFAULT_IMG_DIR = os.environ['HOME']
+ DEFAULT_IMG_DIR += "/.local/share/virt-bootstrap/docker_images"
def checksum(path, sum_type, sum_expected):
+ """
+ Validate file using checksum.
+ """
algorithm = getattr(hashlib, sum_type)
try:
- fd = open(path, 'rb')
- content = fd.read()
- fd.close()
+ handle = open(path, 'rb')
+ content = handle.read()
+ handle.close()
actual = algorithm(content).hexdigest()
return actual == sum_expected
@@ -50,9 +57,11 @@ def checksum(path, sum_type, sum_expected):
def safe_untar(src, dest):
- # Extract tarball in LXC container for safety
+ """
+ Extract tarball within LXC container for safety.
+ """
virt_sandbox = ['virt-sandbox',
- '-c', virt_sandbox_connection,
+ '-c', LIBVIRT_CONN,
'-m', 'host-bind:/mnt=' + dest] # Bind destination folder
# Compression type is auto detected from tar
@@ -64,16 +73,22 @@ def safe_untar(src, dest):
def get_layer_info(digest, image_dir):
+ """
+ Get checksum type/value and path to corresponding tarball.
+ """
sum_type, sum_value = digest.split(':')
layer_file = "{}/{}.tar".format(image_dir, sum_value)
return (sum_type, sum_value, layer_file)
def untar_layers(layers_list, image_dir, dest_dir):
+ """
+ Untar each of layers from container image.
+ """
for layer in layers_list:
sum_type, sum_value, layer_file = get_layer_info(layer['digest'],
image_dir)
- logging.info('Untar layer file: ({}) {}'.format(sum_type, layer_file))
+ logging.info('Untar layer file: (%s) %s', sum_type, layer_file)
# Verify the checksum
if not checksum(layer_file, sum_type, sum_value):
@@ -139,6 +154,9 @@ def create_qcow2(tar_file, layer_file, backing_file=None, size=DEF_QCOW2_SIZE):
def extract_layers_in_qcow2(layers_list, image_dir, dest_dir):
+ """
+ Extract docker layers in qcow2 images with backing chains.
+ """
qcow2_backing_file = None
for index, layer in enumerate(layers_list):
@@ -146,7 +164,7 @@ def extract_layers_in_qcow2(layers_list, image_dir, dest_dir):
sum_type, sum_value, tar_file = \
get_layer_info(layer['digest'], image_dir)
- logging.info('Untar layer file: ({}) {}'.format(sum_type, tar_file))
+ logging.info('Untar layer file: (%s) %s', sum_type, tar_file)
# Verify the checksum
if not checksum(tar_file, sum_type, sum_value):
@@ -160,17 +178,20 @@ def extract_layers_in_qcow2(layers_list, image_dir, dest_dir):
qcow2_backing_file = qcow2_layer_file
-class FileSource:
- def __init__(self, url, username, password, fmt, insecure, no_cache):
+class FileSource(object):
+ """
+ Extract root filesystem from file.
+ """
+ def __init__(self, url, args):
self.path = url.path
- self.output_format = fmt
+ self.output_format = args.format
def unpack(self, dest):
- '''
+ """
Safely extract root filesystem from tarball
@param dest: Directory path where the files to be extraced
- '''
+ """
if self.output_format == 'dir':
logging.info("Extracting files into destination directory")
safe_untar(self.path, dest)
@@ -190,9 +211,13 @@ class FileSource:
logging.info("Files are stored in: " + dest)
-class DockerSource:
- def __init__(self, url, username, password, fmt, insecure, no_cache):
- '''
+class DockerSource(object):
+ """
+ Extract files from Docker image
+ """
+
+ def __init__(self, url, args):
+ """
Bootstrap root filesystem from Docker registry
@param url: Address of source registry
@@ -201,33 +226,33 @@ class DockerSource:
@param fmt: Format used to store image [dir, qcow2]
@param insecure: Do not require HTTPS and certificate verification
@param no_cache: Whether to store downloaded images or not
- '''
+ """
self.registry = url.netloc
self.image = url.path
- self.username = username
- self.password = password
- self.output_format = fmt
- self.insecure = insecure
- self.no_cache = no_cache
+ self.username = args.username
+ self.password = args.password
+ self.output_format = args.format
+ self.insecure = args.not_secure
+ self.no_cache = args.no_cache
if self.image and not self.image.startswith('/'):
self.image = '/' + self.image
self.url = "docker://" + self.registry + self.image
def unpack(self, dest):
- '''
+ """
Extract image files from Docker image
@param dest: Directory path where the files to be extraced
- '''
+ """
if self.no_cache:
tmp_dest = tempfile.mkdtemp('virt-bootstrap')
images_dir = tmp_dest
else:
- if not os.path.exists(default_image_dir):
- os.makedirs(default_image_dir)
- images_dir = default_image_dir
+ if not os.path.exists(DEFAULT_IMG_DIR):
+ os.makedirs(DEFAULT_IMG_DIR)
+ images_dir = DEFAULT_IMG_DIR
try:
# Run skopeo copy into a tmp folder
@@ -247,8 +272,8 @@ class DockerSource:
check_call(skopeo_copy)
# Get the layers list from the manifest
- mf = open(images_dir+"/manifest.json", "r")
- manifest = json.load(mf)
+ manifest_file = open(images_dir+"/manifest.json", "r")
+ manifest = json.load(manifest_file)
# Layers are in order - root layer first
# Reference:
diff --git a/src/virtBootstrap/virt_bootstrap.py b/src/virtBootstrap/virt_bootstrap.py
index 572e603..3973720 100755
--- a/src/virtBootstrap/virt_bootstrap.py
+++ b/src/virtBootstrap/virt_bootstrap.py
@@ -16,6 +16,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Main executable file which process input arguments
+and calls corresponding methods on appropriate object.
+"""
+
import argparse
import gettext
import sys
@@ -27,7 +32,7 @@ try:
except ImportError:
from urllib.parse import urlparse
-import sources
+from virtBootstrap import sources
gettext.bindtextdomain("virt-bootstrap", "/usr/share/locale")
@@ -37,11 +42,19 @@ try:
localedir="/usr/share/locale",
codeset='utf-8')
except IOError:
- import __builtin__
- __builtin__.__dict__['_'] = unicode
+ try:
+ import __builtin__
+ # pylint: disable=undefined-variable
+ __builtin__.__dict__['_'] = unicode
+ except ImportError:
+ import builtin
+ builtin.__dict__['_'] = str
def get_source(args):
+ """
+ Get object which match the source type
+ """
url = urlparse(args.uri)
scheme = url.scheme
@@ -51,26 +64,27 @@ def get_source(args):
try:
class_name = "%sSource" % scheme.capitalize()
clazz = getattr(sources, class_name)
- return clazz(url,
- args.username,
- args.password,
- args.format,
- args.not_secure,
- args.no_cache)
+ return clazz(url, args)
except Exception:
raise Exception("Invalid image URI scheme: '%s'" % url.scheme)
def set_root_password(rootfs, password):
+ """
+ Set password on the root user in rootfs
+ """
users = 'root:%s' % password
args = ['chpasswd', '-R', rootfs]
- p = Popen(args, stdin=PIPE)
- p.communicate(input=users)
- if p.returncode != 0:
- raise CalledProcessError(p.returncode, cmd=args, output=None)
+ chpasswd = Popen(args, stdin=PIPE)
+ chpasswd.communicate(input=users)
+ if chpasswd.returncode != 0:
+ raise CalledProcessError(chpasswd.returncode, cmd=args, output=None)
def bootstrap(args):
+ """
+ Get source object and call unpack method
+ """
source = get_source(args)
if not os.path.exists(args.dest):
os.makedirs(args.dest)
@@ -123,12 +137,10 @@ def main():
bootstrap(args)
sys.exit(0)
- except KeyboardInterrupt as e:
+ except KeyboardInterrupt:
sys.exit(0)
- except ValueError as e:
- for line in e:
- for l in line:
- sys.stderr.write("%s: %s\n" % (sys.argv[0], l))
+ except ValueError as err:
+ sys.stderr.write("%s: %s\n" % (sys.argv[0], err))
sys.stderr.flush()
sys.exit(1)