From 8aefaa4919c9f642f245e1054a953bc403750240 Mon Sep 17 00:00:00 2001 From: James Thomas Date: Fri, 13 Feb 2015 12:50:47 +0000 Subject: Allow system-version-manager to deploy from a rawdisk image --- system-version-manager/system-version-manager | 64 ++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/system-version-manager/system-version-manager b/system-version-manager/system-version-manager index 554e459..9b0ed32 100755 --- a/system-version-manager/system-version-manager +++ b/system-version-manager/system-version-manager @@ -59,6 +59,12 @@ class SystemVersionManager(object): parser_deploy.set_defaults(action='deploy') parser_deploy.add_argument('location') + parser_deploy_from_image = subparsers.add_parser('deploy-from-image', + help='deploy from a rawdisk image') + parser_deploy_from_image.set_defaults(action='deploy-from-image') + parser_deploy_from_image.add_argument('location') + parser_deploy_from_image.add_argument('version_label') + # create the parser for the "get-default" command parser_get_default = subparsers.add_parser('get-default', help='prints the default system') @@ -222,7 +228,57 @@ class SystemVersionManager(object): "/systems/$LABEL/orig" % location) return label - def cmd_deploy(self, location): + def _update_fstab_file(self, location): + # Logic copied from morphlib.writeexts to not create + # a morphlib dependency. + if os.path.exists(location): + fstab = None + old_uuid = None + new_uuid = 'UUID=%s' % self.device_uuid + with open(location, 'r') as f: + fstab=f.read() + for line in fstab.splitlines(): + words = line.split() + if len(words) >= 2 and not words[0].startswith('#'): + device, target = words[0:2] + if (target == '/'): + old_uuid=device + break; + fstab = fstab.replace(old_uuid, new_uuid) + with open(location, 'w') as f: + f.write(fstab) + + def cmd_deploy_from_image(self, location, version_label): + try: + # Mount the image + temp_root = tempfile.mkdtemp() + system_mount_dir = os.path.join(self.mount_dir, 'systems', version_label) + + subprocess.call(['mount', '-t', 'btrfs', '-o', + 'ro,subvol=systems/default/run', location, temp_root]) + + # Create volume on system + os.makedirs(system_mount_dir) + self.status(msg="Creating 'orig' subvolume") + subprocess.call(['btrfs', 'subvolume', 'snapshot', + os.path.join(self.mount_dir, 'systems', + 'default', + 'orig'), + os.path.join(system_mount_dir, 'orig')]) + + self.status(msg="Populating 'orig' subvolume") + subprocess.call(['rsync', '-as', '--checksum', '--numeric-ids', + '--delete', temp_root + os.path.sep, + os.path.join(system_mount_dir, 'orig')]) + self._update_fstab_file(os.path.join(system_mount_dir, 'orig', + 'etc', + 'fstab')) + self.cmd_deploy(system_mount_dir, version_label) + finally: + subprocess.call(['umount', temp_root]) + shutil.rmtree(temp_root) + + def cmd_deploy(self, location, version_label=None): '''Client-side deployment of a new base OS version. This code assumes that the 'orig' subvolume has been correctly created @@ -231,7 +287,8 @@ class SystemVersionManager(object): ''' - label = self._parse_deploy_location(location) + label = (self._parse_deploy_location(location) if version_label is None + else version_label) version_root = os.path.join(self.mount_dir, 'systems', label) install_root = version_root if self.mount_dir != self.boot_dir: @@ -397,6 +454,9 @@ class SystemVersionManager(object): self.cmd_list() elif action == "deploy": self.cmd_deploy(args.location) + elif action == "deploy-from-image": + self.cmd_deploy_from_image(args.location, + args.version_label) elif action == "remove": self.cmd_remove(args.system_name) elif action == "set-default": -- cgit v1.2.1