summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsystem-version-manager/system-version-manager64
1 files 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":