#: Characters which don't need to be quoted for shell commands
_SHELL_UNQUOTED_RE = re.compile("^[-.,=:/_+@A-Za-z0-9]+$")
-#: MAC checker regexp
-_MAC_CHECK_RE = re.compile("^([0-9a-f]{2}:){5}[0-9a-f]{2}$", re.I)
-
#: Shell param checker regexp
_SHELLPARAM_REGEX = re.compile(r"^[-a-zA-Z0-9._+/:%@]+$")
#: ASCII equivalent of unicode character 'HORIZONTAL ELLIPSIS' (U+2026)
_ASCII_ELLIPSIS = "..."
+#: MAC address octet
+_MAC_ADDR_OCTET_RE = r"[0-9a-f]{2}"
+
def MatchNameComponent(key, name_list, case_sensitive=True):
"""Try to match a name against a list.
return os.urandom(numbytes).encode("hex")
-def NormalizeAndValidateMac(mac):
- """Normalizes and check if a MAC address is valid.
+def _MakeMacAddrRegexp(octets):
+ """Builds a regular expression for verifying MAC addresses.
- Checks whether the supplied MAC address is formally correct, only
- accepts colon separated format. Normalize it to all lower.
+ @type octets: integer
+ @param octets: How many octets to expect (1-6)
+ @return: Compiled regular expression
- @type mac: str
- @param mac: the MAC to be validated
- @rtype: str
- @return: returns the normalized and validated MAC.
+ """
+ assert octets > 0
+ assert octets <= 6
+
+ return re.compile("^%s$" % ":".join([_MAC_ADDR_OCTET_RE] * octets),
+ re.I)
+
+
+#: Regular expression for full MAC address
+_MAC_CHECK_RE = _MakeMacAddrRegexp(6)
+
+#: Regular expression for half a MAC address
+_MAC_PREFIX_CHECK_RE = _MakeMacAddrRegexp(3)
+
+
+def _MacAddressCheck(check_re, mac, msg):
+ """Checks a MAC address using a regular expression.
+
+ @param check_re: Compiled regular expression as returned by C{re.compile}
+ @type mac: string
+ @param mac: MAC address to be validated
+ @type msg: string
+ @param msg: Error message (%s will be replaced with MAC address)
+
+ """
+ if check_re.match(mac):
+ return mac.lower()
+
+ raise errors.OpPrereqError(msg % mac, errors.ECODE_INVAL)
- @raise errors.OpPrereqError: If the MAC isn't valid
+
+def NormalizeAndValidateMac(mac):
+ """Normalizes and check if a MAC address is valid and contains six octets.
+
+ Checks whether the supplied MAC address is formally correct. Accepts
+ colon-separated format only. Normalize it to all lower case.
+
+ @type mac: string
+ @param mac: MAC address to be validated
+ @rtype: string
+ @return: Normalized and validated MAC address
+ @raise errors.OpPrereqError: If the MAC address isn't valid
"""
- if not _MAC_CHECK_RE.match(mac):
- raise errors.OpPrereqError("Invalid MAC address '%s'" % mac,
- errors.ECODE_INVAL)
+ return _MacAddressCheck(_MAC_CHECK_RE, mac, "Invalid MAC address '%s'")
- return mac.lower()
+
+def NormalizeAndValidateThreeOctetMacPrefix(mac):
+ """Normalizes a potential MAC address prefix (three octets).
+
+ Checks whether the supplied string is a valid MAC address prefix consisting
+ of three colon-separated octets. The result is normalized to all lower case.
+
+ @type mac: string
+ @param mac: Prefix to be validated
+ @rtype: string
+ @return: Normalized and validated prefix
+ @raise errors.OpPrereqError: If the MAC address prefix isn't valid
+
+ """
+ return _MacAddressCheck(_MAC_PREFIX_CHECK_RE, mac,
+ "Invalid MAC address prefix '%s'")
def SafeEncode(text):
class TestNormalizeAndValidateMac(unittest.TestCase):
def testInvalid(self):
- self.assertRaises(errors.OpPrereqError,
- utils.NormalizeAndValidateMac, "xxx")
+ for i in ["xxx", "00:11:22:33:44:55:66", "zz:zz:zz:zz:zz:zz"]:
+ self.assertRaises(errors.OpPrereqError, utils.NormalizeAndValidateMac, i)
def testNormalization(self):
for mac in ["aa:bb:cc:dd:ee:ff", "00:AA:11:bB:22:cc"]:
self.assertEqual(utils.NormalizeAndValidateMac(mac), mac.lower())
+class TestNormalizeAndValidateThreeOctetMacPrefix(unittest.TestCase):
+ def testInvalid(self):
+ for i in ["xxx", "00:11:22:33:44:55:66", "zz:zz:zz:zz:zz:zz",
+ "aa:bb:cc:dd:ee:ff", "00:AA:11:bB:22:cc",
+ "00:11:"]:
+ self.assertRaises(errors.OpPrereqError,
+ utils.NormalizeAndValidateThreeOctetMacPrefix, i)
+
+ def testNormalization(self):
+ for mac in ["aa:bb:cc", "00:AA:11"]:
+ self.assertEqual(utils.NormalizeAndValidateThreeOctetMacPrefix(mac),
+ mac.lower())
+
+
class TestSafeEncode(unittest.TestCase):
"""Test case for SafeEncode"""