[virt-tools-list] [virt-bootstrap] [PATCH v2 10/14] Optimize setting of root password in qcow2 image
Radostin Stoyanov
rstoyanov1 at gmail.com
Tue Aug 1 11:28:51 UTC 2017
Use the python module of libguestfs to set the root password when
creating images with qcow2 format.
---
src/virtBootstrap/sources/docker_source.py | 4 +-
src/virtBootstrap/sources/file_source.py | 4 +-
src/virtBootstrap/utils.py | 63 ++++++++++++++++++++++++------
src/virtBootstrap/virt_bootstrap.py | 14 ++++---
4 files changed, 66 insertions(+), 19 deletions(-)
diff --git a/src/virtBootstrap/sources/docker_source.py b/src/virtBootstrap/sources/docker_source.py
index 0ca3b20..74dc548 100644
--- a/src/virtBootstrap/sources/docker_source.py
+++ b/src/virtBootstrap/sources/docker_source.py
@@ -60,6 +60,7 @@ class DockerSource(object):
self.password = kwargs['password']
self.uid_map = kwargs['uid_map']
self.gid_map = kwargs['gid_map']
+ self.root_password = kwargs['root_password']
self.output_format = kwargs['fmt']
self.insecure = kwargs['not_secure']
self.no_cache = kwargs['no_cache']
@@ -265,7 +266,8 @@ class DockerSource(object):
self.progress("Extracting container layers into qcow2 images",
value=50, logger=logger)
utils.Build_QCOW2_Image(self.tar_files, dest, self.progress,
- self.uid_map, self.gid_map)
+ self.uid_map, self.gid_map,
+ self.root_password)
else:
raise Exception("Unknown format:" + self.output_format)
diff --git a/src/virtBootstrap/sources/file_source.py b/src/virtBootstrap/sources/file_source.py
index 748181f..4e73da2 100644
--- a/src/virtBootstrap/sources/file_source.py
+++ b/src/virtBootstrap/sources/file_source.py
@@ -46,6 +46,7 @@ class FileSource(object):
self.output_format = kwargs['fmt']
self.uid_map = kwargs['uid_map']
self.gid_map = kwargs['gid_map']
+ self.root_password = kwargs['root_password']
self.progress = kwargs['progress'].update_progress
def unpack(self, dest):
@@ -66,7 +67,8 @@ class FileSource(object):
self.progress("Extracting files into qcow2 image", value=0,
logger=logger)
utils.Build_QCOW2_Image([self.path], dest, self.progress,
- self.uid_map, self.gid_map)
+ self.uid_map, self.gid_map,
+ self.root_password)
else:
raise Exception("Unknown format:" + self.output_format)
diff --git a/src/virtBootstrap/utils.py b/src/virtBootstrap/utils.py
index 7bcffa4..6cfe63c 100644
--- a/src/virtBootstrap/utils.py
+++ b/src/virtBootstrap/utils.py
@@ -57,7 +57,8 @@ class Build_QCOW2_Image(object):
"""
Create qcow2 image with backing chains from list of tar files.
"""
- def __init__(self, tar_files, dest, progress, uid_map=None, gid_map=None):
+ def __init__(self, tar_files, dest, progress, uid_map=None, gid_map=None,
+ root_password=None):
"""
Initialize guestfs
"""
@@ -68,6 +69,7 @@ class Build_QCOW2_Image(object):
self.progress = progress
self.uid_map = uid_map
self.gid_map = gid_map
+ self.root_password = root_password
self.fmt = 'qcow2'
self.qcow2_files = [os.path.join(dest, 'layer-%s.qcow2' % i)
for i in range(self.nlayers)]
@@ -76,6 +78,18 @@ class Build_QCOW2_Image(object):
self.create_base_qcow2_layer(self.tar_files[0], self.qcow2_files[0])
if len(self.tar_files) > 1:
self.create_backing_chains()
+ elif self.root_password is not None:
+ # Add base disk and launch
+ self.g.add_drive_opts(
+ self.qcow2_files[0],
+ readonly=False,
+ format=self.fmt
+ )
+ self.g.launch()
+
+ # Set root password
+ if self.root_password is not None:
+ self.set_root_password()
self.g.shutdown()
def create_and_add_disk(self, qcow2_file, backingfile=None,
@@ -150,6 +164,36 @@ class Build_QCOW2_Image(object):
self.tar_in(tar_file, devices[i])
+ def set_root_password(self):
+ """
+ Set root password in the shadow file of image.
+
+ Mount the last the layer to update the shadow file with the
+ hash for the root password.
+ """
+ self.progress("Setting root password", logger=logger)
+
+ last_layer_dev = self.g.list_devices()[-1]
+ self.g.mount(last_layer_dev, '/')
+
+ if not self.g.is_file('/etc/shadow'):
+ logger.error('showfile was not found in this image')
+ return
+
+ shadow_content = self.g.read_file('/etc/shadow').split('\n')
+
+ if not shadow_content:
+ logger.error('showfile was empty')
+ return
+
+ new_shadow_content = set_password_in_shadow_content(
+ shadow_content,
+ self.root_password
+ )
+ self.g.write('/etc/shadow', '\n'.join(new_shadow_content))
+ self.g.umount('/')
+
+
def map_id(self, tar_members, map_uid, map_gid):
"""
Remapping ownership of all files inside image.
@@ -172,6 +216,13 @@ class Build_QCOW2_Image(object):
self.g.lchown(new_uid, new_gid, os.path.join('/', member.name))
+def get_random_string(n=6):
+ """
+ Return random string of lowercase characters with lenght n.
+ """
+ return ''.join(random.choice(string.ascii_lowercase) for _ in range(n))
+
+
def get_compression_type(tar_file):
"""
Get compression type of tar file.
@@ -447,16 +498,6 @@ def set_root_password_in_rootfs(rootfs, password):
os.chmod(shadow_file, shadow_file_permissions)
-def set_root_password_in_image(image, password):
- """
- Set password on the root user within image
- """
- password_hash = passlib.hosts.linux_context.hash(password)
- execute(['virt-edit',
- '-a', image, '/etc/shadow',
- '-e', 's,^root:.*?:,root:%s:,' % re.escape(password_hash)])
-
-
def set_root_password(fmt, dest, root_password):
"""
Set root password
diff --git a/src/virtBootstrap/virt_bootstrap.py b/src/virtBootstrap/virt_bootstrap.py
index 54025d2..3cc7edb 100755
--- a/src/virtBootstrap/virt_bootstrap.py
+++ b/src/virtBootstrap/virt_bootstrap.py
@@ -128,15 +128,17 @@ def bootstrap(uri, dest,
gid_map=gid_map,
not_secure=not_secure,
no_cache=no_cache,
+ root_password=root_password,
progress=prog).unpack(dest)
- if root_password is not None:
- logger.info("Setting password of the root account")
- utils.set_root_password(fmt, dest, root_password)
+ if fmt == "dir":
+ if root_password is not None:
+ logger.info("Setting password of the root account")
+ utils.set_root_password_in_rootfs(dest, root_password)
- if fmt == "dir" and uid_map or gid_map:
- logger.info("Mapping UID/GID")
- utils.mapping_uid_gid(dest, uid_map, gid_map)
+ if uid_map or gid_map:
+ logger.info("Mapping UID/GID")
+ utils.mapping_uid_gid(dest, uid_map, gid_map)
def set_logging_conf(loglevel=None):
--
2.13.3
More information about the virt-tools-list
mailing list