From 55128088312fdbcb4f8e0219cb7aace1ce567284 Mon Sep 17 00:00:00 2001 From: Alexander Kharkov Date: Wed, 2 Aug 2017 06:51:29 +0000 Subject: [PATCH] Fixed 'privileged' instance creation using config-drive Exsiting config drive creation flow assume that LXD ALWAYS return UID mapping for instance. For privieged this is not true, as not UID mapping perfomed. Existing code which try simply split JSON answer and lookup in it failed as result. Parser switched to JSON based parsing and have fallback to zero UID if no mapping found in LXD answer. Change-Id: If11bf72a9fdeeaff4f55cfca0ec0bc0a1bc6ce3c Closes-Bug: 1707101 --- nova/virt/lxd/driver.py | 47 +++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/nova/virt/lxd/driver.py b/nova/virt/lxd/driver.py index adefe385..2a9b6e2d 100644 --- a/nova/virt/lxd/driver.py +++ b/nova/virt/lxd/driver.py @@ -1201,9 +1201,40 @@ class LXDDriver(driver.ComputeDriver): format=CONF.config_drive_format) container = self.client.containers.get(instance.name) - container_id_map = container.config[ - 'volatile.last_state.idmap'].split(',') - storage_id = container_id_map[2].split(':')[1] + storage_id = 0 + """ + Determine UID shift used for container uid mapping + Sample JSON config from LXD + { + "volatile.apply_template": "create", + ... + "volatile.last_state.idmap": "[ + { + \"Isuid\":true, + \"Isgid\":false, + \"Hostid\":100000, + \"Nsid\":0, + \"Maprange\":65536 + }, + { + \"Isuid\":false, + \"Isgid\":true, + \"Hostid\":100000, + \"Nsid\":0, + \"Maprange\":65536 + }] ", + "volatile.tap5fd6808a-7b.name": "eth0" + } + """ + container_id_map = json.loads( + container.config['volatile.last_state.idmap']) + uid_map = filter(lambda id_map: id_map.get("Isuid"), container_id_map) + if uid_map: + storage_id = uid_map[0].get("Hostid", 0) + else: + # privileged containers does not have uid/gid mapping + # LXD API return nothing + pass extra_md = {} if admin_password: @@ -1249,10 +1280,12 @@ class LXDDriver(driver.ComputeDriver): for ent in os.listdir(tmpdir): shutil.copytree(os.path.join(tmpdir, ent), os.path.join(configdrive_dir, ent)) - utils.execute('chmod', '-R', '775', configdrive_dir, - run_as_root=True) - utils.execute('chown', '-R', storage_id, configdrive_dir, - run_as_root=True) + + utils.execute('chmod', '-R', '775', configdrive_dir, + run_as_root=True) + utils.execute('chown', '-R', + '%s:%s' % (storage_id, storage_id), + configdrive_dir, run_as_root=True) finally: if mounted: utils.execute('umount', tmpdir, run_as_root=True)