diff options
Diffstat (limited to 'cloudinit/sources/helpers')
| -rw-r--r-- | cloudinit/sources/helpers/vmware/__init__.py | 13 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/__init__.py | 13 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/boot_proto.py | 25 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/config.py | 95 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/config_file.py | 129 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/config_namespace.py | 25 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/config_nic.py | 246 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/config_source.py | 23 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/ipv4_mode.py | 45 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/nic.py | 147 | ||||
| -rw-r--r-- | cloudinit/sources/helpers/vmware/imc/nic_base.py | 154 | 
11 files changed, 915 insertions, 0 deletions
| diff --git a/cloudinit/sources/helpers/vmware/__init__.py b/cloudinit/sources/helpers/vmware/__init__.py new file mode 100644 index 00000000..386225d5 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/__init__.py @@ -0,0 +1,13 @@ +# vi: ts=4 expandtab +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU General Public License version 3, as +#    published by the Free Software Foundation. +# +#    This program is distributed in the hope that it will be useful, +#    but WITHOUT ANY WARRANTY; without even the implied warranty of +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#    GNU General Public License for more details. +# +#    You should have received a copy of the GNU General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. diff --git a/cloudinit/sources/helpers/vmware/imc/__init__.py b/cloudinit/sources/helpers/vmware/imc/__init__.py new file mode 100644 index 00000000..386225d5 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/__init__.py @@ -0,0 +1,13 @@ +# vi: ts=4 expandtab +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU General Public License version 3, as +#    published by the Free Software Foundation. +# +#    This program is distributed in the hope that it will be useful, +#    but WITHOUT ANY WARRANTY; without even the implied warranty of +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#    GNU General Public License for more details. +# +#    You should have received a copy of the GNU General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. diff --git a/cloudinit/sources/helpers/vmware/imc/boot_proto.py b/cloudinit/sources/helpers/vmware/imc/boot_proto.py new file mode 100644 index 00000000..faba5887 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/boot_proto.py @@ -0,0 +1,25 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2015 Canonical Ltd.
 +#    Copyright (C) 2015 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +
 +class BootProtoEnum:
 +    """Specifies the NIC Boot Settings."""
 +
 +    DHCP = 'dhcp'
 +    STATIC = 'static'
 diff --git a/cloudinit/sources/helpers/vmware/imc/config.py b/cloudinit/sources/helpers/vmware/imc/config.py new file mode 100644 index 00000000..aebc12a0 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/config.py @@ -0,0 +1,95 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2015 Canonical Ltd.
 +#    Copyright (C) 2015 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +from .nic import Nic
 +
 +
 +class Config:
 +    """
 +    Stores the Contents specified in the Customization
 +    Specification file.
 +    """
 +
 +    DNS = 'DNS|NAMESERVER|'
 +    SUFFIX = 'DNS|SUFFIX|'
 +    PASS = 'PASSWORD|-PASS'
 +    TIMEZONE = 'DATETIME|TIMEZONE'
 +    UTC = 'DATETIME|UTC'
 +    HOSTNAME = 'NETWORK|HOSTNAME'
 +    DOMAINNAME = 'NETWORK|DOMAINNAME'
 +
 +    def __init__(self, configFile):
 +        self._configFile = configFile
 +
 +    @property
 +    def host_name(self):
 +        """Return the hostname."""
 +        return self._configFile.get(Config.HOSTNAME, None)
 +
 +    @property
 +    def domain_name(self):
 +        """Return the domain name."""
 +        return self._configFile.get(Config.DOMAINNAME, None)
 +
 +    @property
 +    def timezone(self):
 +        """Return the timezone."""
 +        return self._configFile.get(Config.TIMEZONE, None)
 +
 +    @property
 +    def utc(self):
 +        """Retrieves whether to set time to UTC or Local."""
 +        return self._configFile.get(Config.UTC, None)
 +
 +    @property
 +    def admin_password(self):
 +        """Return the root password to be set."""
 +        return self._configFile.get(Config.PASS, None)
 +
 +    @property
 +    def name_servers(self):
 +        """Return the list of DNS servers."""
 +        res = []
 +        cnt = self._configFile.get_count_with_prefix(Config.DNS)
 +        for i in range(1, cnt + 1):
 +            key = Config.DNS + str(i)
 +            res.append(self._configFile[key])
 +
 +        return res
 +
 +    @property
 +    def dns_suffixes(self):
 +        """Return the list of DNS Suffixes."""
 +        res = []
 +        cnt = self._configFile.get_count_with_prefix(Config.SUFFIX)
 +        for i in range(1, cnt + 1):
 +            key = Config.SUFFIX + str(i)
 +            res.append(self._configFile[key])
 +
 +        return res
 +
 +    @property
 +    def nics(self):
 +        """Return the list of associated NICs."""
 +        res = []
 +        nics = self._configFile['NIC-CONFIG|NICS']
 +        for nic in nics.split(','):
 +            res.append(Nic(nic, self._configFile))
 +
 +        return res
 diff --git a/cloudinit/sources/helpers/vmware/imc/config_file.py b/cloudinit/sources/helpers/vmware/imc/config_file.py new file mode 100644 index 00000000..bb9fb7dc --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/config_file.py @@ -0,0 +1,129 @@ +# vi: ts=4 expandtab +# +#    Copyright (C) 2015 Canonical Ltd. +#    Copyright (C) 2015 VMware Inc. +# +#    Author: Sankar Tanguturi <stanguturi@vmware.com> +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU General Public License version 3, as +#    published by the Free Software Foundation. +# +#    This program is distributed in the hope that it will be useful, +#    but WITHOUT ANY WARRANTY; without even the implied warranty of +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#    GNU General Public License for more details. +# +#    You should have received a copy of the GNU General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +import logging + +try: +    import configparser +except ImportError: +    import ConfigParser as configparser + +from .config_source import ConfigSource + +logger = logging.getLogger(__name__) + + +class ConfigFile(ConfigSource, dict): +    """ConfigFile module to load the content from a specified source.""" + +    def __init__(self, filename): +        self._loadConfigFile(filename) +        pass + +    def _insertKey(self, key, val): +        """ +        Inserts a Key Value pair. + +        Keyword arguments: +        key -- The key to insert +        val -- The value to insert for the key + +        """ +        key = key.strip() +        val = val.strip() + +        if key.startswith('-') or '|-' in key: +            canLog = False +        else: +            canLog = True + +        # "sensitive" settings shall not be logged +        if canLog: +            logger.debug("ADDED KEY-VAL :: '%s' = '%s'" % (key, val)) +        else: +            logger.debug("ADDED KEY-VAL :: '%s' = '*****************'" % key) + +        self[key] = val + +    def _loadConfigFile(self, filename): +        """ +        Parses properties from the specified config file. + +        Any previously available properties will be removed. +        Sensitive data will not be logged in case the key starts +        from '-'. + +        Keyword arguments: +        filename - The full path to the config file. +        """ +        logger.info('Parsing the config file %s.' % filename) + +        config = configparser.ConfigParser() +        config.optionxform = str +        config.read(filename) + +        self.clear() + +        for category in config.sections(): +            logger.debug("FOUND CATEGORY = '%s'" % category) + +            for (key, value) in config.items(category): +                self._insertKey(category + '|' + key, value) + +    def should_keep_current_value(self, key): +        """ +        Determines whether a value for a property must be kept. + +        If the propery is missing, it is treated as it should be not +        changed by the engine. + +        Keyword arguments: +        key -- The key to search for. +        """ +        # helps to distinguish from "empty" value which is used to indicate +        # "removal" +        return key not in self + +    def should_remove_current_value(self, key): +        """ +        Determines whether a value for the property must be removed. + +        If the specified key is empty, it is treated as it should be +        removed by the engine. + +        Return true if the value can be removed, false otherwise. + +        Keyword arguments: +        key -- The key to search for. +        """ +        # helps to distinguish from "missing" value which is used to indicate +        # "keeping unchanged" +        if key in self: +            return not bool(self[key]) +        else: +            return False + +    def get_count_with_prefix(self, prefix): +        """ +        Return the total count of keys that start with the specified prefix. + +        Keyword arguments: +        prefix -- prefix of the key +        """ +        return len([key for key in self if key.startswith(prefix)]) diff --git a/cloudinit/sources/helpers/vmware/imc/config_namespace.py b/cloudinit/sources/helpers/vmware/imc/config_namespace.py new file mode 100644 index 00000000..7266b699 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/config_namespace.py @@ -0,0 +1,25 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2015 Canonical Ltd.
 +#    Copyright (C) 2015 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +from .config_source import ConfigSource
 +
 +
 +class ConfigNamespace(ConfigSource):
 +    """Specifies the Config Namespace."""
 +    pass
 diff --git a/cloudinit/sources/helpers/vmware/imc/config_nic.py b/cloudinit/sources/helpers/vmware/imc/config_nic.py new file mode 100644 index 00000000..8c5c08cf --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/config_nic.py @@ -0,0 +1,246 @@ +# vi: ts=4 expandtab +# +#    Copyright (C) 2015 Canonical Ltd. +#    Copyright (C) 2016 VMware INC. +# +#    Author: Sankar Tanguturi <stanguturi@vmware.com> +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU General Public License version 3, as +#    published by the Free Software Foundation. +# +#    This program is distributed in the hope that it will be useful, +#    but WITHOUT ANY WARRANTY; without even the implied warranty of +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#    GNU General Public License for more details. +# +#    You should have received a copy of the GNU General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +import logging +import os +import re + +from cloudinit import util + +logger = logging.getLogger(__name__) + + +class NicConfigurator: +    def __init__(self, nics): +        """ +        Initialize the Nic Configurator +        @param nics (list) an array of nics to configure +        """ +        self.nics = nics +        self.mac2Name = {} +        self.ipv4PrimaryGateway = None +        self.ipv6PrimaryGateway = None +        self.find_devices() +        self._primaryNic = self.get_primary_nic() + +    def get_primary_nic(self): +        """ +        Retrieve the primary nic if it exists +        @return (NicBase): the primary nic if exists, None otherwise +        """ +        primary_nics = [nic for nic in self.nics if nic.primary] +        if not primary_nics: +            return None +        elif len(primary_nics) > 1: +            raise Exception('There can only be one primary nic', +                            [nic.mac for nic in primary_nics]) +        else: +            return primary_nics[0] + +    def find_devices(self): +        """ +        Create the mac2Name dictionary +        The mac address(es) are in the lower case +        """ +        cmd = ['ip', 'addr', 'show'] +        (output, err) = util.subp(cmd) +        sections = re.split(r'\n\d+: ', '\n' + output)[1:] + +        macPat = r'link/ether (([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))' +        for section in sections: +            match = re.search(macPat, section) +            if not match:  # Only keep info about nics +                continue +            mac = match.group(1).lower() +            name = section.split(':', 1)[0] +            self.mac2Name[mac] = name + +    def gen_one_nic(self, nic): +        """ +        Return the lines needed to configure a nic +        @return (str list): the string list to configure the nic +        @param nic (NicBase): the nic to configure +        """ +        lines = [] +        name = self.mac2Name.get(nic.mac.lower()) +        if not name: +            raise ValueError('No known device has MACADDR: %s' % nic.mac) + +        if nic.onboot: +            lines.append('auto %s' % name) + +        # Customize IPv4 +        lines.extend(self.gen_ipv4(name, nic)) + +        # Customize IPv6 +        lines.extend(self.gen_ipv6(name, nic)) + +        lines.append('') + +        return lines + +    def gen_ipv4(self, name, nic): +        """ +        Return the lines needed to configure the IPv4 setting of a nic +        @return (str list): the string list to configure the gateways +        @param name (str): name of the nic +        @param nic (NicBase): the nic to configure +        """ +        lines = [] + +        bootproto = nic.bootProto.lower() +        if nic.ipv4_mode.lower() == 'disabled': +            bootproto = 'manual' +        lines.append('iface %s inet %s' % (name, bootproto)) + +        if bootproto != 'static': +            return lines + +        # Static Ipv4 +        v4 = nic.staticIpv4 +        if v4.ip: +            lines.append('    address %s' % v4.ip) +        if v4.netmask: +            lines.append('    netmask %s' % v4.netmask) + +        # Add the primary gateway +        if nic.primary and v4.gateways: +            self.ipv4PrimaryGateway = v4.gateways[0] +            lines.append('    gateway %s metric 0' % self.ipv4PrimaryGateway) +            return lines + +        # Add routes if there is no primary nic +        if not self._primaryNic: +            lines.extend(self.gen_ipv4_route(nic, v4.gateways)) + +        return lines + +    def gen_ipv4_route(self, nic, gateways): +        """ +        Return the lines needed to configure additional Ipv4 route +        @return (str list): the string list to configure the gateways +        @param nic (NicBase): the nic to configure +        @param gateways (str list): the list of gateways +        """ +        lines = [] + +        for gateway in gateways: +            lines.append('    up route add default gw %s metric 10000' % +                         gateway) + +        return lines + +    def gen_ipv6(self, name, nic): +        """ +        Return the lines needed to configure the gateways for a nic +        @return (str list): the string list to configure the gateways +        @param name (str): name of the nic +        @param nic (NicBase): the nic to configure +        """ +        lines = [] + +        if not nic.staticIpv6: +            return lines + +        # Static Ipv6 +        addrs = nic.staticIpv6 +        lines.append('iface %s inet6 static' % name) +        lines.append('    address %s' % addrs[0].ip) +        lines.append('    netmask %s' % addrs[0].netmask) + +        for addr in addrs[1:]: +            lines.append('    up ifconfig %s inet6 add %s/%s' % (name, addr.ip, +                                                                 addr.netmask)) +        # Add the primary gateway +        if nic.primary: +            for addr in addrs: +                if addr.gateway: +                    self.ipv6PrimaryGateway = addr.gateway +                    lines.append('    gateway %s' % self.ipv6PrimaryGateway) +                    return lines + +        # Add routes if there is no primary nic +        if not self._primaryNic: +            lines.extend(self._genIpv6Route(name, nic, addrs)) + +        return lines + +    def _genIpv6Route(self, name, nic, addrs): +        lines = [] + +        for addr in addrs: +            lines.append('    up route -A inet6 add default gw ' +                         '%s metric 10000' % addr.gateway) + +        return lines + +    def generate(self): +        """Return the lines that is needed to configure the nics""" +        lines = [] +        lines.append('iface lo inet loopback') +        lines.append('auto lo') +        lines.append('') + +        for nic in self.nics: +            lines.extend(self.gen_one_nic(nic)) + +        return lines + +    def clear_dhcp(self): +        logger.info('Clearing DHCP leases') + +        util.subp(["pkill", "dhclient"]) +        util.subp(["rm", "-f", "/var/lib/dhcp/*"]) + +    def if_down_up(self): +        names = [] +        for nic in self.nics: +            name = self.mac2Name.get(nic.mac.lower()) +            names.append(name) + +        for name in names: +            logger.info('Bring down interface %s' % name) +            util.subp(["ifdown", "%s" % name]) + +        self.clear_dhcp() + +        for name in names: +            logger.info('Bring up interface %s' % name) +            util.subp(["ifup", "%s" % name]) + +    def configure(self): +        """ +        Configure the /etc/network/intefaces +        Make a back up of the original +        """ +        containingDir = '/etc/network' + +        interfaceFile = os.path.join(containingDir, 'interfaces') +        originalFile = os.path.join(containingDir, +                                    'interfaces.before_vmware_customization') + +        if not os.path.exists(originalFile) and os.path.exists(interfaceFile): +            os.rename(interfaceFile, originalFile) + +        lines = self.generate() +        with open(interfaceFile, 'w') as fp: +            for line in lines: +                fp.write('%s\n' % line) + +        self.if_down_up() diff --git a/cloudinit/sources/helpers/vmware/imc/config_source.py b/cloudinit/sources/helpers/vmware/imc/config_source.py new file mode 100644 index 00000000..a367e476 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/config_source.py @@ -0,0 +1,23 @@ +# vi: ts=4 expandtab
 +#
 +#    Copyright (C) 2015 Canonical Ltd.
 +#    Copyright (C) 2015 VMware Inc.
 +#
 +#    Author: Sankar Tanguturi <stanguturi@vmware.com>
 +#
 +#    This program is free software: you can redistribute it and/or modify
 +#    it under the terms of the GNU General Public License version 3, as
 +#    published by the Free Software Foundation.
 +#
 +#    This program is distributed in the hope that it will be useful,
 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +#    GNU General Public License for more details.
 +#
 +#    You should have received a copy of the GNU General Public License
 +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +
 +class ConfigSource:
 +    """Specifies a source for the Config Content."""
 +    pass
 diff --git a/cloudinit/sources/helpers/vmware/imc/ipv4_mode.py b/cloudinit/sources/helpers/vmware/imc/ipv4_mode.py new file mode 100644 index 00000000..33f88726 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/ipv4_mode.py @@ -0,0 +1,45 @@ +# vi: ts=4 expandtab +# +#    Copyright (C) 2015 Canonical Ltd. +#    Copyright (C) 2015 VMware Inc. +# +#    Author: Sankar Tanguturi <stanguturi@vmware.com> +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU General Public License version 3, as +#    published by the Free Software Foundation. +# +#    This program is distributed in the hope that it will be useful, +#    but WITHOUT ANY WARRANTY; without even the implied warranty of +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#    GNU General Public License for more details. +# +#    You should have received a copy of the GNU General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. + + +class Ipv4ModeEnum: +    """ +    The IPv4 configuration mode which directly represents the user's goal. + +    This mode effectively acts as a contract of the in-guest customization +    engine. It must be set based on what the user has requested and should +    not be changed by those layers. It's up to the in-guest engine to +    interpret and materialize the user's request. +    """ + +    # The legacy mode which only allows dhcp/static based on whether IPv4 +    # addresses list is empty or not +    IPV4_MODE_BACKWARDS_COMPATIBLE = 'BACKWARDS_COMPATIBLE' + +    # IPv4 must use static address. Reserved for future use +    IPV4_MODE_STATIC = 'STATIC' + +    # IPv4 must use DHCPv4. Reserved for future use +    IPV4_MODE_DHCP = 'DHCP' + +    # IPv4 must be disabled +    IPV4_MODE_DISABLED = 'DISABLED' + +    # IPv4 settings should be left untouched. Reserved for future use +    IPV4_MODE_AS_IS = 'AS_IS' diff --git a/cloudinit/sources/helpers/vmware/imc/nic.py b/cloudinit/sources/helpers/vmware/imc/nic.py new file mode 100644 index 00000000..b5d704ea --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/nic.py @@ -0,0 +1,147 @@ +# vi: ts=4 expandtab +# +#    Copyright (C) 2015 Canonical Ltd. +#    Copyright (C) 2015 VMware Inc. +# +#    Author: Sankar Tanguturi <stanguturi@vmware.com> +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU General Public License version 3, as +#    published by the Free Software Foundation. +# +#    This program is distributed in the hope that it will be useful, +#    but WITHOUT ANY WARRANTY; without even the implied warranty of +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#    GNU General Public License for more details. +# +#    You should have received a copy of the GNU General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +from .boot_proto import BootProtoEnum +from .nic_base import NicBase, StaticIpv4Base, StaticIpv6Base + + +class Nic(NicBase): +    """ +    Holds the information about each NIC specified +    in the customization specification file +    """ + +    def __init__(self, name, configFile): +        self._name = name +        self._configFile = configFile + +    def _get(self, what): +        return self._configFile.get(self.name + '|' + what, None) + +    def _get_count_with_prefix(self, prefix): +        return self._configFile.get_count_with_prefix(self.name + prefix) + +    @property +    def name(self): +        return self._name + +    @property +    def mac(self): +        return self._get('MACADDR').lower() + +    @property +    def primary(self): +        value = self._get('PRIMARY') +        if value: +            value = value.lower() +            return value == 'yes' or value == 'true' +        else: +            return False + +    @property +    def onboot(self): +        value = self._get('ONBOOT') +        if value: +            value = value.lower() +            return value == 'yes' or value == 'true' +        else: +            return False + +    @property +    def bootProto(self): +        value = self._get('BOOTPROTO') +        if value: +            return value.lower() +        else: +            return "" + +    @property +    def ipv4_mode(self): +        value = self._get('IPv4_MODE') +        if value: +            return value.lower() +        else: +            return "" + +    @property +    def staticIpv4(self): +        """ +        Checks the BOOTPROTO property and returns StaticIPv4Addr +        configuration object if STATIC configuration is set. +        """ +        if self.bootProto == BootProtoEnum.STATIC: +            return [StaticIpv4Addr(self)] +        else: +            return None + +    @property +    def staticIpv6(self): +        cnt = self._get_count_with_prefix('|IPv6ADDR|') + +        if not cnt: +            return None + +        result = [] +        for index in range(1, cnt + 1): +            result.append(StaticIpv6Addr(self, index)) + +        return result + + +class StaticIpv4Addr(StaticIpv4Base): +    """Static IPV4  Setting.""" + +    def __init__(self, nic): +        self._nic = nic + +    @property +    def ip(self): +        return self._nic._get('IPADDR') + +    @property +    def netmask(self): +        return self._nic._get('NETMASK') + +    @property +    def gateways(self): +        value = self._nic._get('GATEWAY') +        if value: +            return [x.strip() for x in value.split(',')] +        else: +            return None + + +class StaticIpv6Addr(StaticIpv6Base): +    """Static IPV6 Address.""" + +    def __init__(self, nic, index): +        self._nic = nic +        self._index = index + +    @property +    def ip(self): +        return self._nic._get('IPv6ADDR|' + str(self._index)) + +    @property +    def netmask(self): +        return self._nic._get('IPv6NETMASK|' + str(self._index)) + +    @property +    def gateway(self): +        return self._nic._get('IPv6GATEWAY|' + str(self._index)) diff --git a/cloudinit/sources/helpers/vmware/imc/nic_base.py b/cloudinit/sources/helpers/vmware/imc/nic_base.py new file mode 100644 index 00000000..030ba311 --- /dev/null +++ b/cloudinit/sources/helpers/vmware/imc/nic_base.py @@ -0,0 +1,154 @@ +# vi: ts=4 expandtab +# +#    Copyright (C) 2015 Canonical Ltd. +#    Copyright (C) 2015 VMware Inc. +# +#    Author: Sankar Tanguturi <stanguturi@vmware.com> +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU General Public License version 3, as +#    published by the Free Software Foundation. +# +#    This program is distributed in the hope that it will be useful, +#    but WITHOUT ANY WARRANTY; without even the implied warranty of +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#    GNU General Public License for more details. +# +#    You should have received a copy of the GNU General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. + + +class NicBase: +    """ +    Define what are expected of each nic. +    The following properties should be provided in an implementation class. +    """ + +    @property +    def mac(self): +        """ +        Retrieves the mac address of the nic +        @return (str) : the MACADDR setting +        """ +        raise NotImplementedError('MACADDR') + +    @property +    def primary(self): +        """ +        Retrieves whether the nic is the primary nic +        Indicates whether NIC will be used to define the default gateway. +        If none of the NICs is configured to be primary, default gateway won't +        be set. +        @return (bool): the PRIMARY setting +        """ +        raise NotImplementedError('PRIMARY') + +    @property +    def onboot(self): +        """ +        Retrieves whether the nic should be up at the boot time +        @return (bool) : the ONBOOT setting +        """ +        raise NotImplementedError('ONBOOT') + +    @property +    def bootProto(self): +        """ +        Retrieves the boot protocol of the nic +        @return (str): the BOOTPROTO setting, valid values: dhcp and static. +        """ +        raise NotImplementedError('BOOTPROTO') + +    @property +    def ipv4_mode(self): +        """ +        Retrieves the IPv4_MODE +        @return (str): the IPv4_MODE setting, valid values: +        backwards_compatible, static, dhcp, disabled, as_is +        """ +        raise NotImplementedError('IPv4_MODE') + +    @property +    def staticIpv4(self): +        """ +        Retrieves the static IPv4 configuration of the nic +        @return (StaticIpv4Base list): the static ipv4 setting +        """ +        raise NotImplementedError('Static IPv4') + +    @property +    def staticIpv6(self): +        """ +        Retrieves the IPv6 configuration of the nic +        @return (StaticIpv6Base list): the static ipv6 setting +        """ +        raise NotImplementedError('Static Ipv6') + +    def validate(self): +        """ +        Validate the object +        For example, the staticIpv4 property is required and should not be +        empty when ipv4Mode is STATIC +        """ +        raise NotImplementedError('Check constraints on properties') + + +class StaticIpv4Base: +    """ +    Define what are expected of a static IPv4 setting +    The following properties should be provided in an implementation class. +    """ + +    @property +    def ip(self): +        """ +        Retrieves the Ipv4 address +        @return (str): the IPADDR setting +        """ +        raise NotImplementedError('Ipv4 Address') + +    @property +    def netmask(self): +        """ +        Retrieves the Ipv4 NETMASK setting +        @return (str): the NETMASK setting +        """ +        raise NotImplementedError('Ipv4 NETMASK') + +    @property +    def gateways(self): +        """ +        Retrieves the gateways on this Ipv4 subnet +        @return (str list): the GATEWAY setting +        """ +        raise NotImplementedError('Ipv4 GATEWAY') + + +class StaticIpv6Base: +    """Define what are expected of a static IPv6 setting +    The following properties should be provided in an implementation class. +    """ + +    @property +    def ip(self): +        """ +        Retrieves the Ipv6 address +        @return (str): the IPv6ADDR setting +        """ +        raise NotImplementedError('Ipv6 Address') + +    @property +    def netmask(self): +        """ +        Retrieves the Ipv6 NETMASK setting +        @return (str): the IPv6NETMASK setting +        """ +        raise NotImplementedError('Ipv6 NETMASK') + +    @property +    def gateway(self): +        """ +        Retrieves the Ipv6 GATEWAY setting +        @return (str): the IPv6GATEWAY setting +        """ +        raise NotImplementedError('Ipv6 GATEWAY') | 
