[Kimchi-devel] [PATCH] issue #548: Hotplug network interfaces
Paulo Ricardo Paz Vital
pvital at gmail.com
Wed Apr 15 06:43:29 UTC 2015
$ qemu-system-x86_64 -device help
This command lists all devices drivers supported by QEMU.
Best regards,
Paulo Vital
On Tue, Apr 14, 2015 at 11:10 PM Crístian Viana <cristiandeives at gmail.com>
wrote:
> What exactly are the drivers that support it? I was able to hot plug
> interfaces using virtio, rtl8139 and e1000, at least.
>
>
> On Mon, Apr 13, 2015 at 11:12 AM Aline Manera <alinefm at linux.vnet.ibm.com>
> wrote:
>
>>
>>
>> On 08/04/2015 09:34, Crístian Deives wrote:
>> > Currently, network interfaces can only be added to shutoff VMs. However,
>> > the use might want to attach an interface to a running VM as well.
>> >
>> > Allow network interfaces to be attached also while the VM is running.
>> > The related test cases have been updated to perform the same operations
>> > on both a shutoff and a running VM.
>> >
>> > Fix issue #548 (Kimchi does not support NIC hot plug) - backend only.
>> >
>> > Signed-off-by: Crístian Deives <cristiandeives at gmail.com>
>> > ---
>> > src/kimchi/i18n.py | 1 -
>> > src/kimchi/model/vmifaces.py | 45 ++++++++++++++---------
>> > tests/test_model.py | 86
>> ++++++++++++++++++++++----------------------
>> > 3 files changed, 73 insertions(+), 59 deletions(-)
>> >
>> > diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
>> > index 46990a5..d4c1cc6 100644
>> > --- a/src/kimchi/i18n.py
>> > +++ b/src/kimchi/i18n.py
>> > @@ -118,7 +118,6 @@ messages = {
>> >
>> > "KCHVMIF0001E": _("Interface %(iface)s does not exist in virtual
>> machine %(name)s"),
>> > "KCHVMIF0002E": _("Network %(network)s specified for virtual
>> machine %(name)s does not exist"),
>> > - "KCHVMIF0003E": _("Do not support guest interface hot plug
>> attachment"),
>> > "KCHVMIF0004E": _("Supported virtual machine interfaces type is
>> only network"),
>> > "KCHVMIF0005E": _("Network name for virtual machine interface
>> must be a string"),
>> > "KCHVMIF0006E": _("Invalid network model card specified for
>> virtual machine interface"),
>> > diff --git a/src/kimchi/model/vmifaces.py b/src/kimchi/model/vmifaces.py
>> > index 0c10fa9..a64315d 100644
>> > --- a/src/kimchi/model/vmifaces.py
>> > +++ b/src/kimchi/model/vmifaces.py
>> > @@ -22,7 +22,7 @@ import random
>> > import libvirt
>> > from lxml import etree, objectify
>> >
>> > -from kimchi.exception import InvalidOperation, InvalidParameter,
>> NotFoundError
>> > +from kimchi.exception import InvalidParameter, NotFoundError
>> > from kimchi.model.config import CapabilitiesModel
>> > from kimchi.model.vms import DOM_STATE_MAP, VMModel
>> > from kimchi.xmlutils.interface import get_iface_xml
>> > @@ -48,10 +48,6 @@ class VMIfacesModel(object):
>> > raise InvalidParameter("KCHVMIF0002E",
>> > {'name': vm, 'network':
>> params["network"]})
>> >
>> > - dom = VMModel.get_vm(vm, self.conn)
>> > - if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
>> > - raise InvalidOperation("KCHVMIF0003E")
>> > -
>> > macs = (iface.mac.get('address')
>> > for iface in self.get_vmifaces(vm, self.conn))
>> >
>> > @@ -60,10 +56,19 @@ class VMIfacesModel(object):
>> > if params['mac'] not in macs:
>> > break
>> >
>> > + dom = VMModel.get_vm(vm, self.conn)
>> > +
>>
>> We need to restrict the hot plug operation to the drivers that supports
>> it.
>>
>> > os_data = VMModel.vm_get_os_metadata(dom,
>> self.caps.metadata_support)
>> > os_distro, os_version = os_data
>> > xml = get_iface_xml(params, conn.getInfo()[0], os_distro,
>> os_version)
>> > - dom.attachDeviceFlags(xml, libvirt.VIR_DOMAIN_AFFECT_CURRENT)
>> > +
>> > + flags = 0
>> > + if dom.isPersistent():
>> > + flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG
>> > + if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
>> > + flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE
>> > +
>> > + dom.attachDeviceFlags(xml, flags)
>> >
>> > return params['mac']
>> >
>> > @@ -118,14 +123,16 @@ class VMIfaceModel(object):
>> > dom = VMModel.get_vm(vm, self.conn)
>> > iface = self._get_vmiface(vm, mac)
>> >
>> > - if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
>> > - raise InvalidOperation("KCHVMIF0003E")
>> > -
>> > if iface is None:
>> > raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface':
>> mac})
>> >
>> > - dom.detachDeviceFlags(etree.tostring(iface),
>> > - libvirt.VIR_DOMAIN_AFFECT_CURRENT)
>> > + flags = 0
>> > + if dom.isPersistent():
>> > + flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG
>> > + if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
>> > + flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE
>> > +
>> > + dom.detachDeviceFlags(etree.tostring(iface), flags)
>> >
>> > def update(self, vm, mac, params):
>> > dom = VMModel.get_vm(vm, self.conn)
>> > @@ -134,16 +141,22 @@ class VMIfaceModel(object):
>> > if iface is None:
>> > raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface':
>> mac})
>> >
>> > - # FIXME we will support to change the live VM configuration
>> later.
>> > + flags = 0
>> > + if dom.isPersistent():
>> > + flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG
>> > + if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
>> > + flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE
>> > +
>> > 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():
>> > + dom.updateDeviceFlags(xml, flags=flags)
>> > +
>> > + if 'model' in params:
>> > iface.model.attrib["type"] = params['model']
>> > xml = etree.tostring(iface)
>> > - dom.updateDeviceFlags(xml,
>> flags=libvirt.VIR_DOMAIN_AFFECT_CONFIG)
>> > +
>> > + dom.updateDeviceFlags(xml, flags=flags)
>> >
>> > return mac
>> > diff --git a/tests/test_model.py b/tests/test_model.py
>> > index 63bd721..39e4fe6 100644
>> > --- a/tests/test_model.py
>> > +++ b/tests/test_model.py
>> > @@ -297,9 +297,6 @@ class ModelTests(unittest.TestCase):
>> > params = {'name': 'test', 'disks': [], 'cdrom':
>> UBUNTU_ISO}
>> > inst.templates_create(params)
>> > rollback.prependDefer(inst.template_delete, 'test')
>> > - params = {'name': 'kimchi-ifaces', 'template':
>> '/templates/test'}
>> > - inst.vms_create(params)
>> > - rollback.prependDefer(inst.vm_delete, 'kimchi-ifaces')
>> >
>> > # Create a network
>> > net_name = 'test-network'
>> > @@ -311,45 +308,50 @@ class ModelTests(unittest.TestCase):
>> > inst.network_activate(net_name)
>> > rollback.prependDefer(inst.network_deactivate, net_name)
>> >
>> > - ifaces = inst.vmifaces_get_list('kimchi-ifaces')
>> > - self.assertEquals(1, len(ifaces))
>> > -
>> > - iface = inst.vmiface_lookup('kimchi-ifaces', ifaces[0])
>> > - self.assertEquals(17, len(iface['mac']))
>> > - self.assertEquals("default", iface['network'])
>> > - self.assertIn("model", iface)
>> > -
>> > - # attach network interface to vm
>> > - iface_args = {"type": "network",
>> > - "network": "test-network",
>> > - "model": "virtio"}
>> > - mac = inst.vmifaces_create('kimchi-ifaces', iface_args)
>> > - # detach network interface from vm
>> > - rollback.prependDefer(inst.vmiface_delete,
>> 'kimchi-ifaces', mac)
>> > - self.assertEquals(17, len(mac))
>> > -
>> > - iface = inst.vmiface_lookup('kimchi-ifaces', mac)
>> > - self.assertEquals("network", iface["type"])
>> > - self.assertEquals("test-network", iface['network'])
>> > - self.assertEquals("virtio", iface["model"])
>> > -
>> > - # attach network interface to vm without providing model
>> > - iface_args = {"type": "network",
>> > - "network": "test-network"}
>> > - mac = inst.vmifaces_create('kimchi-ifaces', iface_args)
>> > - rollback.prependDefer(inst.vmiface_delete,
>> 'kimchi-ifaces', mac)
>> > -
>> > - iface = inst.vmiface_lookup('kimchi-ifaces', mac)
>> > - self.assertEquals("network", iface["type"])
>> > - self.assertEquals("test-network", iface['network'])
>> > -
>> > - # 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"])
>> > + for vm_name in ['kimchi-ifaces', 'kimchi-ifaces-running']:
>> > + params = {'name': vm_name, 'template':
>> '/templates/test'}
>> > + inst.vms_create(params)
>> > + rollback.prependDefer(inst.vm_delete, vm_name)
>> > +
>> > + ifaces = inst.vmifaces_get_list(vm_name)
>> > + self.assertEquals(1, len(ifaces))
>> > +
>> > + iface = inst.vmiface_lookup(vm_name, ifaces[0])
>> > + self.assertEquals(17, len(iface['mac']))
>> > + self.assertEquals("default", iface['network'])
>> > + self.assertIn("model", iface)
>> > +
>> > + # attach network interface to vm
>> > + iface_args = {"type": "network",
>> > + "network": "test-network",
>> > + "model": "virtio"}
>> > + mac = inst.vmifaces_create(vm_name, iface_args)
>> > + # detach network interface from vm
>> > + rollback.prependDefer(inst.vmiface_delete, vm_name,
>> mac)
>> > + self.assertEquals(17, len(mac))
>> > +
>> > + iface = inst.vmiface_lookup(vm_name, mac)
>> > + self.assertEquals("network", iface["type"])
>> > + self.assertEquals("test-network", iface['network'])
>> > + self.assertEquals("virtio", iface["model"])
>> > +
>> > + # attach network interface to vm without providing
>> model
>> > + iface_args = {"type": "network",
>> > + "network": "test-network"}
>> > + mac = inst.vmifaces_create(vm_name, iface_args)
>> > + rollback.prependDefer(inst.vmiface_delete, vm_name,
>> mac)
>> > +
>> > + iface = inst.vmiface_lookup(vm_name, mac)
>> > + self.assertEquals("network", iface["type"])
>> > + self.assertEquals("test-network", iface['network'])
>> > +
>> > + # update vm interface
>> > + iface_args = {"network": "default",
>> > + "model": "e1000"}
>> > + inst.vmiface_update(vm_name, mac, iface_args)
>> > + iface = inst.vmiface_lookup(vm_name, 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_disk(self):
>>
>> _______________________________________________
> Kimchi-devel mailing list
> Kimchi-devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20150415/b4c60c4a/attachment.html>
More information about the Kimchi-devel
mailing list