summaryrefslogtreecommitdiff
path: root/cloudinit/sources/helpers/vmware
diff options
context:
space:
mode:
authorSankar Tanguturi <stanguturi@stanguturi-rhel>2016-02-09 17:54:07 -0800
committerSankar Tanguturi <stanguturi@stanguturi-rhel>2016-02-09 17:54:07 -0800
commit39f668e5db8d09c46eee3a5df73a69f8d85ba489 (patch)
tree98812b43a9fa3d4b712f56ab2ddd4a9068361398 /cloudinit/sources/helpers/vmware
parent9ba841efc4263fcd1ec8eb266a3afa83b525ba49 (diff)
downloadvyos-cloud-init-39f668e5db8d09c46eee3a5df73a69f8d85ba489.tar.gz
vyos-cloud-init-39f668e5db8d09c46eee3a5df73a69f8d85ba489.zip
- Added the code to configure the NICs.
- Added the code to detect VMware Virtual Platform and apply the customization based on the 'Customization Specification File' Pushed into the guest VM.
Diffstat (limited to 'cloudinit/sources/helpers/vmware')
-rw-r--r--cloudinit/sources/helpers/vmware/imc/config_nic.py246
-rw-r--r--cloudinit/sources/helpers/vmware/imc/nic.py28
2 files changed, 268 insertions, 6 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..8e2fc5d3
--- /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 subprocess
+import re
+
+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
+ """
+ primaryNic = None
+
+ for nic in self.nics:
+ if nic.primary:
+ if primaryNic:
+ raise Exception('There can only be one primary nic',
+ primaryNic.mac, nic.mac)
+ primaryNic = nic
+
+ return primaryNic
+
+ def find_devices(self):
+ """
+ Create the mac2Name dictionary
+ The mac address(es) are in the lower case
+ """
+ cmd = 'ip addr show'
+ outText = subprocess.check_output(cmd, shell=True).decode()
+ sections = re.split(r'\n\d+: ', '\n' + outText)[1:]
+
+ macPat = r'link/ether (([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))'
+ for section in sections:
+ matcher = re.search(macPat, section)
+ if not matcher: # Only keep info about nics
+ continue
+ mac = matcher.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')
+
+ subprocess.call('pkill dhclient', shell=True)
+ subprocess.check_call('rm -f /var/lib/dhcp/*', shell=True)
+
+ 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)
+ subprocess.check_call('ifdown %s' % name, shell=True)
+
+ self.clear_dhcp()
+
+ for name in names:
+ logger.info('Bring up interface %s' % name)
+ subprocess.check_call('ifup %s' % name, shell=True)
+
+ 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/nic.py b/cloudinit/sources/helpers/vmware/imc/nic.py
index a7594874..6628a3ec 100644
--- a/cloudinit/sources/helpers/vmware/imc/nic.py
+++ b/cloudinit/sources/helpers/vmware/imc/nic.py
@@ -47,21 +47,37 @@ class Nic(NicBase):
@property
def primary(self):
- value = self._get('PRIMARY').lower()
- return value == 'yes' or value == 'true'
+ 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').lower()
- return value == 'yes' or value == 'true'
+ value = self._get('ONBOOT')
+ if value:
+ value = value.lower()
+ return value == 'yes' or value == 'true'
+ else:
+ return False
@property
def bootProto(self):
- return self._get('BOOTPROTO').lower()
+ value = self._get('BOOTPROTO')
+ if value:
+ return value.lower()
+ else:
+ return ""
@property
def ipv4_mode(self):
- return self._get('IPv4_MODE').lower()
+ value = self._get('IPv4_MODE')
+ if value:
+ return value.lower()
+ else:
+ return ""
@property
def staticIpv4(self):