Signed-off-by: Jose Ricardo Ziviani <joserz(a)linux.vnet.ibm.com>
---
src/kimchi/API.json | 22 +++++++++----------
src/kimchi/i18n.py | 5 ++++-
src/kimchi/model/vmifaces.py | 52 +++++++++++++++++++++++++++++---------------
3 files changed, 50 insertions(+), 29 deletions(-)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json
index a6330ae..b9a41eb 100644
--- a/src/kimchi/API.json
+++ b/src/kimchi/API.json
@@ -393,6 +393,12 @@
"type": "string",
"pattern":
"^ne2k_pci|i82551|i82557b|i82559er|rtl8139|e1000|pcnet|virtio$",
"error": "KCHVMIF0006E"
+ },
+ "mac": {
+ "description": "Network Interface Card MAC
address",
+ "type": "string",
+ "pattern":
"(^$)|^(([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$)",
+ "error": "KCHVMIF0010E"
}
}
},
@@ -400,19 +406,13 @@
"type": "object",
"error": "KCHVMIF0008E",
"properties": {
- "network": {
- "description": "the name of one available
network",
- "minLength": 1,
+ "mac": {
+ "description": "Network Interface Card MAC
address",
"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"
+ "pattern":
"^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$",
+ "error": "KCHVMIF0010E"
}
- },
- "additionalProperties": false
+ }
},
"templates_create": {
"type": "object",
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 9f169ab..d5e93fa 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -126,7 +126,10 @@ 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": _("MAC Address must respect this format
FF:FF:FF:FF:FF:FF"),
+ "KCHVMIF0009E": _("MAC Address %(mac)s already exists in virtual
machine %(name)s"),
+ "KCHVMIF0010E": _("Invalid MAC Address"),
+ "KCHVMIF0011E": _("Cannot change MAC address of a running virtual
machine"),
"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..50edde2 100644
--- a/src/kimchi/model/vmifaces.py
+++ b/src/kimchi/model/vmifaces.py
@@ -22,7 +22,8 @@ import random
import libvirt
from lxml import etree, objectify
-from kimchi.exception import InvalidParameter, MissingParameter, NotFoundError
+from kimchi.exception import InvalidParameter, MissingParameter
+from kimchi.exception import NotFoundError, InvalidOperation
from kimchi.model.config import CapabilitiesModel
from kimchi.model.vms import DOM_STATE_MAP, VMModel
from kimchi.xmlutils.interface import get_iface_xml
@@ -57,10 +58,19 @@ 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']})
+
+ # 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 +157,30 @@ 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')
+
+ # new mac address must be unique
+ if self._get_vmiface(vm, params['mac']) is not None:
+ 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)
+ # cannot change mac address in a running system
+ if DOM_STATE_MAP[dom.info()[0]] != "shutoff":
+ raise InvalidOperation('KCHVMIF0011E')
- 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