[PATCH 1/4] vmiface update support: update API.md

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 716c983..26a4937 100644 --- a/docs/API.md +++ b/docs/API.md @@ -220,6 +220,14 @@ A interface represents available network interface on VM. * **DELETE**: detach the network interface from VM +* **PUT**: update the parameters of existed 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 3360a9c..9ad8e9d 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -288,6 +288,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 3fc3013..1a57bfd 100644 --- a/src/kimchi/i18n.py +++ b/src/kimchi/i18n.py @@ -94,6 +94,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> 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 | 22 ++++++++++++++++++++++ tests/test_model.py | 8 ++++++++ tests/test_rest.py | 8 ++++++++ 8 files changed, 77 insertions(+) -- 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 | 22 ++++++++++++++++++++++ 2 files changed, 23 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..8a28358 100644 --- a/src/kimchi/model/vmifaces.py +++ b/src/kimchi/model/vmifaces.py @@ -129,3 +129,25 @@ 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}) + + # change on the active VM instance and persisted VM configuration. + 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 + + libvirt.VIR_DOMAIN_AFFECT_CURRENT) + + # 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

On 04/18/2014 09:46 AM, shaohef@linux.vnet.ibm.com wrote:
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 | 22 ++++++++++++++++++++++ 2 files changed, 23 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..8a28358 100644 --- a/src/kimchi/model/vmifaces.py +++ b/src/kimchi/model/vmifaces.py @@ -129,3 +129,25 @@ 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}) + + # change on the active VM instance and persisted VM configuration. + 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 + + libvirt.VIR_DOMAIN_AFFECT_CURRENT) +
+ # 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) +
Question: From what I understood this change will only take effect in next boot, right? Should we warn user about it?
+ return mac

On 04/23/2014 12:03 AM, Aline Manera wrote:
On 04/18/2014 09:46 AM, shaohef@linux.vnet.ibm.com wrote:
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 | 22 ++++++++++++++++++++++ 2 files changed, 23 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..8a28358 100644 --- a/src/kimchi/model/vmifaces.py +++ b/src/kimchi/model/vmifaces.py @@ -129,3 +129,25 @@ 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}) + + # change on the active VM instance and persisted VM configuration. + 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 + + libvirt.VIR_DOMAIN_AFFECT_CURRENT) +
+ # 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) +
Question: From what I understood this change will only take effect in next boot, right? Should we warn user about it? Yes. To YuXing: When user want to update the model, please warn user about it.
+ return mac
-- Thanks and best regards! Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

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 8c7d7bb..d788031 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -725,6 +725,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

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 04/18/2014 09:46 AM, shaohef@linux.vnet.ibm.com wrote:
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 8c7d7bb..d788031 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -725,6 +725,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')

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 | 8 ++++++++ tests/test_rest.py | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/test_model.py b/tests/test_model.py index 357d969..6603d9e 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -170,6 +170,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 a40ba93..35fa08b 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -500,6 +500,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

On 04/18/2014 09:47 AM, shaohef@linux.vnet.ibm.com wrote:
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 | 8 ++++++++ tests/test_rest.py | 8 ++++++++ 2 files changed, 16 insertions(+)
diff --git a/tests/test_model.py b/tests/test_model.py index 357d969..6603d9e 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -170,6 +170,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"]) +
Please, add a test to update vm iface in a running VM.
@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 a40ba93..35fa08b 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -500,6 +500,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')

On 04/23/2014 12:05 AM, Aline Manera wrote:
On 04/18/2014 09:47 AM, shaohef@linux.vnet.ibm.com wrote:
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 | 8 ++++++++ tests/test_rest.py | 8 ++++++++ 2 files changed, 16 insertions(+)
diff --git a/tests/test_model.py b/tests/test_model.py index 357d969..6603d9e 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -170,6 +170,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"]) +
Please, add a test to update vm iface in a running VM. Done. send a new patch set.
@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 a40ba93..35fa08b 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -500,6 +500,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')
-- Thanks and best regards! Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

On 04/18/2014 09:46 AM, shaohef@linux.vnet.ibm.com wrote:
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 716c983..26a4937 100644 --- a/docs/API.md +++ b/docs/API.md @@ -220,6 +220,14 @@ A interface represents available network interface on VM.
* **DELETE**: detach the network interface from VM
+* **PUT**: update the parameters of existed VM interface.
typo: s/existed/existing I can fix it before applying
+ * 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 3360a9c..9ad8e9d 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -288,6 +288,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 3fc3013..1a57bfd 100644 --- a/src/kimchi/i18n.py +++ b/src/kimchi/i18n.py @@ -94,6 +94,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"),
participants (3)
-
Aline Manera
-
shaohef@linux.vnet.ibm.com
-
Sheldon