[PATCH V3 0/4] vmiface update support

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> V2 -> V3 just support to change persistent network configure. V1 -> V2 add test case for running VM We allow user change the interface from one network to another network when VM is alive. But we only support change the vm configure no matter vm is alive or not. ShaoHe Feng (4): vmiface update support: update API.md vmiface update support: update model. vmiface update support: update mockmodel vmiface update support: update test case docs/API.md | 8 ++++++++ src/kimchi/API.json | 17 +++++++++++++++++ src/kimchi/control/vm/ifaces.py | 1 + src/kimchi/i18n.py | 1 + src/kimchi/mockmodel.py | 12 ++++++++++++ src/kimchi/model/vmifaces.py | 21 +++++++++++++++++++++ tests/test_model.py | 10 ++++++++++ tests/test_rest.py | 8 ++++++++ 8 files changed, 78 insertions(+) -- 1.9.0

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> update API.md and API.json Test this patch by: $ curl -u <user>:<password> -H "Content-Type: application/json" \
-H "Accept: application/json" http://localhost:8000/vms/<vmname>/ifaces/<mac> \ -X PUT -d ' { "model":"virtio", "network":"default" }'
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 8 ++++++++ src/kimchi/API.json | 17 +++++++++++++++++ src/kimchi/i18n.py | 1 + 3 files changed, 26 insertions(+) diff --git a/docs/API.md b/docs/API.md index c394c69..29b81e8 100644 --- a/docs/API.md +++ b/docs/API.md @@ -227,6 +227,14 @@ A interface represents available network interface on VM. * **DELETE**: detach the network interface from VM +* **PUT**: update the parameters of existing VM interface. + * model *(optional)*: model of emulated network interface card. It will be one of these models: + ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. + This change is only on the persisted VM configuration. + * network *(optional)*: the name of resource network, only be available when the + interface type is network. + This change is on the active VM instance and persisted VM configuration. + **Actions (POST):** *No actions defined* diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 38e9607..01c7898 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -300,6 +300,23 @@ } } }, + "vmiface_update": { + "type": "object", + "error": "KCHVMIF0008E", + "properties": { + "network": { + "description": "the name of one available network", + "minLength": 1, + "type": "string", + "error": "KCHVMIF0005E" + }, + "model": { + "description": "model of emulated network interface card", + "enum": ["ne2k_pci", "i82551", "i82557b", "i82559er", "rtl8139", "e1000", "pcnet", "virtio", "spapr-vlan"], + "error": "KCHVMIF0006E" + } + } + }, "templates_create": { "type": "object", "error": "KCHTMPL0016E", diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py index a1af1f7..b5bcf30 100644 --- a/src/kimchi/i18n.py +++ b/src/kimchi/i18n.py @@ -95,6 +95,7 @@ messages = { "KCHVMIF0005E": _("Network name for virtual machine interface must be a string"), "KCHVMIF0006E": _("Invalid network model card specified for virtual machine interface"), "KCHVMIF0007E": _("Specify type and network to add a new virtual machine interface"), + "KCHVMIF0008E": _("Specify type and network to update a virtual machine interface"), "KCHTMPL0001E": _("Template %(name)s already exists"), "KCHTMPL0002E": _("Template %(name)s does not exist"), -- 1.9.0

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> For network source, change will be on the active VM instance and persisted VM configuration. For model, change will be on the active VM instance only Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/ifaces.py | 1 + src/kimchi/model/vmifaces.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/kimchi/control/vm/ifaces.py b/src/kimchi/control/vm/ifaces.py index 874ef54..1b5dc36 100644 --- a/src/kimchi/control/vm/ifaces.py +++ b/src/kimchi/control/vm/ifaces.py @@ -34,6 +34,7 @@ class VMIfaces(Collection): class VMIface(Resource): def __init__(self, model, vm, ident): super(VMIface, self).__init__(model, ident) + self.update_params = ["model", "network"] self.vm = vm self.ident = ident self.info = {} diff --git a/src/kimchi/model/vmifaces.py b/src/kimchi/model/vmifaces.py index 9bf110e..e377477 100644 --- a/src/kimchi/model/vmifaces.py +++ b/src/kimchi/model/vmifaces.py @@ -129,3 +129,24 @@ class VMIfaceModel(object): dom.detachDeviceFlags(etree.tostring(iface), libvirt.VIR_DOMAIN_AFFECT_CURRENT) + + def update(self, vm, mac, params): + dom = VMModel.get_vm(vm, self.conn) + iface = self._get_vmiface(vm, mac) + + if iface is None: + raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac}) + + # FIXME we will support to change the live VM configuration later. + if iface.attrib['type'] == 'network' and 'network' in params: + iface.source.attrib['network'] = params['network'] + xml = etree.tostring(iface) + dom.updateDeviceFlags(xml, flags=libvirt.VIR_DOMAIN_AFFECT_CONFIG) + + # change on the persisted VM configuration only. + if 'model' in params and dom.isPersistent(): + iface.model.attrib["type"] = params['model'] + xml = etree.tostring(iface) + dom.updateDeviceFlags(xml, flags=libvirt.VIR_DOMAIN_AFFECT_CONFIG) + + return mac -- 1.9.0

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> update mockmodel Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index bce28d1..5166609 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -740,6 +740,18 @@ class MockModel(object): except KeyError: raise NotFoundError("KCHVMIF0001E", {'iface': mac, 'name': vm}) + def vmiface_update(self, vm, mac, params): + dom = self._get_vm(vm) + try: + info = dom.ifaces[mac].info + except KeyError: + raise NotFoundError("KCHVMIF0001E", {'iface': mac, 'name': vm}) + if info['type'] == 'network' and 'network' in params: + info['network'] = params['network'] + if 'model' in params: + info['model'] = params['model'] + return mac + def tasks_get_list(self): with self.objstore as session: return session.get_list('task') -- 1.9.0

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> update test_model.py and test_rest.py Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- tests/test_model.py | 10 ++++++++++ tests/test_rest.py | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/tests/test_model.py b/tests/test_model.py index 05e5741..e860df1 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -149,6 +149,8 @@ class ModelTests(unittest.TestCase): 'subnet': '127.0.100.0/24'} inst.networks_create(net_args) rollback.prependDefer(inst.network_delete, net_name) + inst.network_activate(net_name) + rollback.prependDefer(inst.network_deactivate, net_name) ifaces = inst.vmifaces_get_list('kimchi-ifaces') self.assertEquals(1, len(ifaces)) @@ -172,6 +174,14 @@ class ModelTests(unittest.TestCase): self.assertEquals("test-network", iface['network']) self.assertEquals("virtio", iface["model"]) + # update vm interface + iface_args = {"network": "default", + "model": "e1000"} + inst.vmiface_update('kimchi-ifaces', mac, iface_args) + iface = inst.vmiface_lookup('kimchi-ifaces', mac) + self.assertEquals("default", iface['network']) + self.assertEquals("e1000", iface["model"]) + @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_cdrom(self): inst = model.Model(objstore_loc=self.tmp_store) diff --git a/tests/test_rest.py b/tests/test_rest.py index a260785..26e07c5 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -545,6 +545,14 @@ class RestTests(unittest.TestCase): self.assertEquals('virtio', iface['model']) self.assertEquals('network', iface['type']) + # update vm interface + req = json.dumps({"network": "default", "model": "e1000"}) + resp = self.request('/vms/test-vm/ifaces/%s' % iface['mac'], req, 'PUT') + self.assertEquals(200, resp.status) + update_iface = json.loads(resp.read()) + self.assertEquals('e1000', update_iface['model']) + self.assertEquals('default', update_iface['network']) + # detach network interface from vm resp = self.request('/vms/test-vm/ifaces/%s' % iface['mac'], '{}', 'DELETE') -- 1.9.0
participants (2)
-
Aline Manera
-
shaohef@linux.vnet.ibm.com