diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 690053a28d46b359e42df71b9902f47da7f0f98e..02f8ebd51a2c12a6b805c304eb12e553850d079a 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -10120,7 +10120,7 @@ class LUInstanceCreate(LogicalUnit): # creation job will fail. for nic in self.nics: if nic.mac in (constants.VALUE_AUTO, constants.VALUE_GENERATE): - nic.mac = self.cfg.GenerateMAC(self.proc.GetECId()) + nic.mac = self.cfg.GenerateMAC(nic.network, self.proc.GetECId()) #### allocator run @@ -12846,7 +12846,7 @@ class LUInstanceSetParams(LogicalUnit): elif mac in (constants.VALUE_AUTO, constants.VALUE_GENERATE): # otherwise generate the MAC address params[constants.INIC_MAC] = \ - self.cfg.GenerateMAC(self.proc.GetECId()) + self.cfg.GenerateMAC(new_net, self.proc.GetECId()) else: # or validate/reserve the current one try: @@ -12867,7 +12867,7 @@ class LUInstanceSetParams(LogicalUnit): old_prefix = get_net_prefix(old_net) if old_prefix != new_prefix: params[constants.INIC_MAC] = \ - self.cfg.GenerateMAC(self.proc.GetECId()) + self.cfg.GenerateMAC(new_net, self.proc.GetECId()) #if there is a change in nic-network configuration new_ip = params.get(constants.INIC_IP, old_ip) @@ -15482,6 +15482,8 @@ class LUNetworkAdd(LogicalUnit): raise errors.OpPrereqError("Network '%s' already defined" % self.op.network, errors.ECODE_EXISTS) + if self.op.mac_prefix: + utils.NormalizeAndValidateMac(self.op.mac_prefix+":00:00:00") def BuildHooksEnv(self): """Build hooks env. @@ -15670,6 +15672,7 @@ class LUNetworkSetParams(LogicalUnit): if self.op.mac_prefix == constants.VALUE_NONE: self.mac_prefix = None else: + utils.NormalizeAndValidateMac(self.op.mac_prefix+":00:00:00") self.mac_prefix = self.op.mac_prefix if self.op.gateway6: diff --git a/lib/config.py b/lib/config.py index 2a70abf40efbaaf5af3f5d8cd469b3f0b4f7ac54..a98779ced7318832150ffef2974c78924d029460 100644 --- a/lib/config.py +++ b/lib/config.py @@ -39,6 +39,7 @@ import random import logging import time import itertools +from functools import wraps from ganeti import errors from ganeti import locking @@ -219,16 +220,30 @@ class ConfigWriter: """ return os.path.exists(pathutils.CLUSTER_CONF_FILE) - def _GenerateOneMAC(self): + def _GenerateMACPrefix(self, net=None): + def _get_mac_prefix(view_func): + def _decorator(*args, **kwargs): + prefix = self._config_data.cluster.mac_prefix + if net: + net_uuid = self._UnlockedLookupNetwork(net) + if net_uuid: + nobj = self._UnlockedGetNetwork(net_uuid) + if nobj.mac_prefix: + prefix = nobj.mac_prefix + suffix = view_func(*args, **kwargs) + return prefix+':'+suffix + return wraps(view_func)(_decorator) + return _get_mac_prefix + + def _GenerateMACSuffix(self): """Generate one mac address """ - prefix = self._config_data.cluster.mac_prefix byte1 = random.randrange(0, 256) byte2 = random.randrange(0, 256) byte3 = random.randrange(0, 256) - mac = "%s:%02x:%02x:%02x" % (prefix, byte1, byte2, byte3) - return mac + suffix = "%02x:%02x:%02x" % (byte1, byte2, byte3) + return suffix @locking.ssynchronized(_config_lock, shared=1) def GetNdParams(self, node): @@ -277,14 +292,15 @@ class ConfigWriter: return self._config_data.cluster.SimpleFillDP(group.diskparams) @locking.ssynchronized(_config_lock, shared=1) - def GenerateMAC(self, ec_id): + def GenerateMAC(self, net, ec_id): """Generate a MAC for an instance. This should check the current instances for duplicates. """ existing = self._AllMACs() - return self._temporary_ids.Generate(existing, self._GenerateOneMAC, ec_id) + gen_mac = self._GenerateMACPrefix(net)(self._GenerateMACSuffix) + return self._temporary_ids.Generate(existing, gen_mac, ec_id) @locking.ssynchronized(_config_lock, shared=1) def ReserveMAC(self, mac, ec_id):