[Kimchi-devel] [PATCH 3/5] Implement backend code to edit MAC address of a guest

Jose Ricardo Ziviani joserz at linux.vnet.ibm.com
Mon May 11 17:19:31 UTC 2015


Signed-off-by: Jose Ricardo Ziviani <joserz at linux.vnet.ibm.com>
---
 src/kimchi/API.json          | 13 ++++++++++
 src/kimchi/i18n.py           |  4 ++-
 src/kimchi/model/vmifaces.py | 60 +++++++++++++++++++++++++++++++-------------
 3 files changed, 59 insertions(+), 18 deletions(-)

diff --git a/src/kimchi/API.json b/src/kimchi/API.json
index 474661c..71d7a72 100644
--- a/src/kimchi/API.json
+++ b/src/kimchi/API.json
@@ -382,12 +382,25 @@
                     "description": "the name of one available network",
                     "minLength": 1,
                     "type": "string",
+                    "required": true,
                     "error": "KCHVMIF0005E"
                 },
+                "type": {
+                    "description": "The type of VM network interface that libvirt supports",
+                    "type": "string",
+                    "pattern": "^network$",
+                    "required": true,
+                    "error": "KCHVMIF0004E"
+                },
                 "model": {
                     "description": "model of emulated network interface card",
                     "enum": ["ne2k_pci", "i82551", "i82557b", "i82559er", "rtl8139", "e1000", "pcnet", "virtio", "spapr-vlan"],
                     "error": "KCHVMIF0006E"
+                },
+                "mac": {
+                    "description": "Network Interface Card MAC address",
+                    "type": "string",
+                    "error": "KCHVMIF0005E"
                 }
             },
             "additionalProperties": false
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 18e84bc..f04f54e 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -126,7 +126,9 @@ 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"),
+    "KCHVMIF0008E": _("Specify MAC Address to update a virtual machine interface"),
+    "KCHVMIF0009E": _("MAC Address %(mac)s already exists in virtual machine %(name)s"),
+    "KCHVMIF0010E": _("Invalid MAC Address %(mac)s"),
 
     "KCHTMPL0001E": _("Template %(name)s already exists"),
     "KCHTMPL0003E": _("Network '%(network)s' specified for template %(template)s does not exist"),
diff --git a/src/kimchi/model/vmifaces.py b/src/kimchi/model/vmifaces.py
index 8bf6b3d..4c0a2a9 100644
--- a/src/kimchi/model/vmifaces.py
+++ b/src/kimchi/model/vmifaces.py
@@ -20,6 +20,7 @@
 import random
 
 import libvirt
+import re
 from lxml import etree, objectify
 
 from kimchi.exception import InvalidParameter, MissingParameter, NotFoundError
@@ -27,6 +28,8 @@ from kimchi.model.config import CapabilitiesModel
 from kimchi.model.vms import DOM_STATE_MAP, VMModel
 from kimchi.xmlutils.interface import get_iface_xml
 
+RE_MACADDR = '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'
+
 
 class VMIfacesModel(object):
     def __init__(self, **kargs):
@@ -57,10 +60,24 @@ class VMIfacesModel(object):
         macs = (iface.mac.get('address')
                 for iface in self.get_vmifaces(vm, self.conn))
 
-        while True:
-            params['mac'] = VMIfacesModel.random_mac()
-            if params['mac'] not in macs:
-                break
+        # user defined customized mac address
+        if 'mac' in params and params['mac']:
+            # make sure it is unique
+            if params['mac'] in macs:
+                raise InvalidParameter('KCHVMIF0009E',
+                                       {'name': vm, 'mac': params['mac']})
+
+            # invalid mac address
+            if not re.match(RE_MACADDR, params['mac']):
+                raise InvalidParameter('KCHVMIF0010E',
+                                       {'name': vm, 'mac': params['mac']})
+
+        # otherwise choose a random mac address
+        else:
+            while True:
+                params['mac'] = VMIfacesModel.random_mac()
+                if params['mac'] not in macs:
+                    break
 
         dom = VMModel.get_vm(vm, self.conn)
 
@@ -147,22 +164,31 @@ class VMIfaceModel(object):
         if iface is None:
             raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac})
 
+        # mac address is a required parameter
+        if 'mac' not in params:
+            raise MissingParameter('KCHVMIF0008E')
+
+        # invalid mac address
+        if not re.match(RE_MACADDR, params['mac']):
+            raise InvalidParameter('KCHVMIF0010E',
+                                   {'name': vm, 'mac': params['mac']})
+
+        # new mac address must be unique
+        if self._get_vmiface(vm, params['mac']):
+            raise InvalidParameter('KCHVMIF0009E',
+                                   {'name': vm, 'mac': params['mac']})
+
         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=flags)
 
-        if 'model' in params:
-            iface.model.attrib["type"] = params['model']
-            xml = etree.tostring(iface)
+        # remove the current nic
+        xml = etree.tostring(iface)
+        dom.detachDeviceFlags(xml, flags=flags)
 
-            dom.updateDeviceFlags(xml, flags=flags)
+        # add the nic with the desired mac address
+        iface.mac.attrib['address'] = params['mac']
+        xml = etree.tostring(iface)
+        dom.attachDeviceFlags(xml, flags=flags)
 
-        return mac
+        return [vm, params['mac']]
-- 
1.9.1




More information about the Kimchi-devel mailing list