[PATCH v2][Kimchi 0/2] Issue #467: Feature: Show boot menu for a guest

Changes: v2: fix import order Ramon Medeiros (2): Issue #467: Feature: Show boot menu for a guest Add test to verify bootmenu and update old tests API.json | 5 +++++ docs/API.md | 1 + i18n.py | 1 + model/vms.py | 30 +++++++++++++++++++++--------- tests/test_mockmodel.py | 2 +- tests/test_model.py | 8 +++++++- xmlutils/bootorder.py | 4 ++++ 7 files changed, 40 insertions(+), 11 deletions(-) -- 2.5.5

Signed-off-by: Ramon Medeiros <ramonn@linux.vnet.ibm.com> --- API.json | 5 +++++ docs/API.md | 1 + i18n.py | 1 + model/vms.py | 30 +++++++++++++++++++++--------- xmlutils/bootorder.py | 4 ++++ 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/API.json b/API.json index 1772abb..4fdd522 100644 --- a/API.json +++ b/API.json @@ -317,6 +317,11 @@ "additionalItems": false, "uniqueItems": true }, + "bootmenu": { + "description": "Bootmenu on guest power on", + "error": "KCHVM0053E", + "type": "boolean" + }, "users": { "description": "Array of users who have permission to the VM", "type": "array", diff --git a/docs/API.md b/docs/API.md index 4a40e70..971f28e 100644 --- a/docs/API.md +++ b/docs/API.md @@ -175,6 +175,7 @@ server. * cores - The number of cores per socket. * threads - The number of threads per core. * bootorder: guest bootorder, types accepted: hd, cdrom, network or fd + * bootmenu: prompts guest bootmenu. Bool type. * **POST**: *See Virtual Machine Actions* diff --git a/i18n.py b/i18n.py index e8fdf88..6ca19fd 100644 --- a/i18n.py +++ b/i18n.py @@ -105,6 +105,7 @@ messages = { "KCHVM0050E": _("Cannot shutdown %(name)s. Virtual machine is shut off."), "KCHVM0051E": _("Cannot reset %(name)s. Virtual machine is already shut off."), "KCHVM0052E": _("Boot order must be a list. Devices accepted: hd, cdrom, fd or network."), + "KCHVM0053E": _("Bootmenu must be boolean. Values accepted: true of false."), "KCHVM0055E": _("Migrate to localhost %(host)s is not allowed."), "KCHVM0056E": _("To migrate a virtual machine to the remote host %(host)s the user %(user)s must have password-less login to the remote host."), diff --git a/model/vms.py b/model/vms.py index 17159fe..dc637d7 100644 --- a/model/vms.py +++ b/model/vms.py @@ -62,6 +62,7 @@ from wok.plugins.kimchi.osinfo import defaults, MEM_DEV_SLOTS from wok.plugins.kimchi.screenshot import VMScreenshot from wok.plugins.kimchi.utils import get_next_clone_name from wok.plugins.kimchi.utils import template_name_from_uri +from wok.plugins.kimchi.xmlutils.bootorder import get_bootmenu_node from wok.plugins.kimchi.xmlutils.bootorder import get_bootorder_node from wok.plugins.kimchi.xmlutils.cpu import get_topology_xml from wok.plugins.kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks @@ -82,7 +83,7 @@ VM_ONLINE_UPDATE_PARAMS = ['graphics', 'groups', 'memory', 'users'] # update parameters which are updatable when the VM is offline VM_OFFLINE_UPDATE_PARAMS = ['cpu_info', 'graphics', 'groups', 'memory', - 'name', 'users', 'bootorder'] + 'name', 'users', 'bootorder', 'bootmenu'] XPATH_DOMAIN_DISK = "/domain/devices/disk[@device='disk']/source/@file" XPATH_DOMAIN_DISK_BY_FILE = "./devices/disk[@device='disk']/source[@file='%s']" @@ -95,6 +96,7 @@ XPATH_DOMAIN_UUID = '/domain/uuid' XPATH_DOMAIN_DEV_CPU_ID = '/domain/devices/spapr-cpu-socket/@id' XPATH_BOOT = 'os/boot/@dev' +XPATH_BOOTMENU = 'os/bootmenu/@enable' XPATH_CPU = './cpu' XPATH_NAME = './name' XPATH_NUMA_CELL = './cpu/numa/cell' @@ -758,9 +760,16 @@ class VMModel(object): for device in os.findall("boot"): os.remove(device) - # add new - for device in get_bootorder_node(params): - os.append(device) + # add new bootorder + if "bootorder" in params: + for device in get_bootorder_node(params["bootorder"]): + os.append(device) + + # update bootmenu + if params.get("bootmenu") is False: + [os.remove(bm) for bm in os.findall("bootmenu")] + elif params.get("bootmenu") is True: + os.append(get_bootmenu_node()) # update <os> return ET.tostring(et) @@ -811,9 +820,9 @@ class VMModel(object): if ('memory' in params and params['memory'] != {}): new_xml = self._update_memory_config(new_xml, params, dom) - # update bootorder - if "bootorder" in params: - new_xml = self._update_bootorder(new_xml, params["bootorder"]) + # update bootorder or bootmenu + if "bootorder" or "bootmenu" in params: + new_xml = self._update_bootorder(new_xml, params) snapshots_info = [] conn = self.conn.get() @@ -1252,8 +1261,10 @@ class VMModel(object): else: maxmemory = memory - # get boot order + # get boot order and bootmenu boot = xpath_get_text(xml, XPATH_BOOT) + bootmenu = "yes" if "yes" in xpath_get_text(xml, XPATH_BOOTMENU) \ + else "no" return {'name': name, 'state': state, @@ -1273,7 +1284,8 @@ class VMModel(object): 'groups': groups, 'access': 'full', 'persistent': True if dom.isPersistent() else False, - 'bootorder': boot + 'bootorder': boot, + 'bootmenu': bootmenu } def _vm_get_disk_paths(self, dom): diff --git a/xmlutils/bootorder.py b/xmlutils/bootorder.py index 6d92bd6..f8bc6ea 100644 --- a/xmlutils/bootorder.py +++ b/xmlutils/bootorder.py @@ -47,3 +47,7 @@ def get_bootorder_xml(boot_order=None): boot_xml += ET.tostring(device, encoding='utf-8', pretty_print=True) return boot_xml + + +def get_bootmenu_node(): + return E.bootmenu(enable="yes", timeout="5000") -- 2.5.5

Signed-off-by: Ramon Medeiros <ramonn@linux.vnet.ibm.com> --- tests/test_mockmodel.py | 2 +- tests/test_model.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/test_mockmodel.py b/tests/test_mockmodel.py index 0db1ff2..43f6d07 100644 --- a/tests/test_mockmodel.py +++ b/tests/test_mockmodel.py @@ -163,7 +163,7 @@ class MockModelTests(unittest.TestCase): keys = set(('name', 'state', 'stats', 'uuid', 'memory', 'cpu_info', 'screenshot', 'icon', 'graphics', 'users', 'groups', - 'access', 'persistent', 'bootorder')) + 'access', 'persistent', 'bootorder', 'bootmenu')) stats_keys = set(('cpu_utilization', 'mem_utilization', 'net_throughput', 'net_throughput_peak', diff --git a/tests/test_model.py b/tests/test_model.py index 09ef995..68fafd4 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -118,7 +118,7 @@ class ModelTests(unittest.TestCase): keys = set(('name', 'state', 'stats', 'uuid', 'memory', 'cpu_info', 'screenshot', 'icon', 'graphics', 'users', 'groups', - 'access', 'persistent', 'bootorder')) + 'access', 'persistent', 'bootorder', 'bootmenu')) stats_keys = set(('cpu_utilization', 'mem_utilization', 'net_throughput', 'net_throughput_peak', @@ -1137,6 +1137,12 @@ class ModelTests(unittest.TestCase): self.assertRaises(OperationFailed, inst.vm_update, u'пeω-∨м', {"bootorder": ["bla"]}) + # enable/disable bootmenu + inst.vm_update(u'пeω-∨м', {"bootmenu": True}) + self.assertEquals("yes", inst.vm_lookup(u'пeω-∨м')['bootmenu']) + inst.vm_update(u'пeω-∨м', {"bootmenu": False}) + self.assertEquals("no", inst.vm_lookup(u'пeω-∨м')['bootmenu']) + def test_get_interfaces(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) -- 2.5.5

Hi Ramon, Sorry, I haven't seen there was a V2 before reviewing the first patch set version. But I think all my comments apply to that version too. Regards, Aline Manera On 07/21/2016 11:24 AM, Ramon Medeiros wrote:
Changes:
v2: fix import order
Ramon Medeiros (2): Issue #467: Feature: Show boot menu for a guest Add test to verify bootmenu and update old tests
API.json | 5 +++++ docs/API.md | 1 + i18n.py | 1 + model/vms.py | 30 +++++++++++++++++++++--------- tests/test_mockmodel.py | 2 +- tests/test_model.py | 8 +++++++- xmlutils/bootorder.py | 4 ++++ 7 files changed, 40 insertions(+), 11 deletions(-)
participants (2)
-
Aline Manera
-
Ramon Medeiros