summaryrefslogtreecommitdiff
path: root/cloudinit/sources/helpers/vmware/imc/config_nic.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/sources/helpers/vmware/imc/config_nic.py')
-rw-r--r--cloudinit/sources/helpers/vmware/imc/config_nic.py247
1 files changed, 247 insertions, 0 deletions
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..77098a05
--- /dev/null
+++ b/cloudinit/sources/helpers/vmware/imc/config_nic.py
@@ -0,0 +1,247 @@
+# 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')
+
+ # Ignore the return code 1.
+ util.subp(["pkill", "dhclient"], rcs=[0, 1])
+ 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()