← Back to team overview

cloud-init-dev team mailing list archive

[Merge] lp:~i-franz/cloud-init/cloud-init into lp:cloud-init

 

Franz Schwartau has proposed merging lp:~i-franz/cloud-init/cloud-init into lp:cloud-init.

Requested reviews:
  cloud init development team (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~i-franz/cloud-init/cloud-init/+merge/244309

Added support for retrieval of OVF XML via vmware-tools vmtoolsd or vmware-guestd.
Configure the network using custom properties of the OVF XML (ipv4.address, ipv4.netmask, ipv4.broadcast, ipv4.gateway, dns.server1 and dns.server2).

-- 
Your team cloud init development team is requested to review the proposed merge of lp:~i-franz/cloud-init/cloud-init into lp:cloud-init.
=== modified file 'cloudinit/sources/DataSourceOVF.py'
--- cloudinit/sources/DataSourceOVF.py	2014-09-22 18:35:03 +0000
+++ cloudinit/sources/DataSourceOVF.py	2014-12-10 15:50:41 +0000
@@ -25,6 +25,7 @@
 import base64
 import os
 import re
+import netifaces
 
 from cloudinit import log as logging
 from cloudinit import sources
@@ -64,7 +65,7 @@
             found.append(seed)
         else:
             np = {'iso': transport_iso9660,
-                  'vmware-guestd': transport_vmware_guestd, }
+                  'vmware-tools': transport_vmware_tools, }
             name = None
             for (name, transfunc) in np.iteritems():
                 (contents, _dev, _fname) = transfunc()
@@ -97,6 +98,12 @@
             md = util.mergemanydict([md, md_seed])
             found.append(seedfrom)
 
+        network_config = gen_network_config(md)
+
+        if network_config:
+            LOG.debug("Updating network interfaces from %s", self)
+            self.distro.apply_network(network_config)
+
         # Now that we have exhausted any other places merge in the defaults
         md = util.mergemanydict([md, defaults])
 
@@ -137,7 +144,7 @@
     cfg = {}
     ud = ""
     cfg_props = ['password']
-    md_props = ['seedfrom', 'local-hostname', 'public-keys', 'instance-id']
+    md_props = ['seedfrom', 'local-hostname', 'public-keys', 'instance-id', 'ipv4.address', 'ipv4.gateway', 'ipv4.netmask', 'ipv4.broadcast', 'dns.server1', 'dns.server2', 'macaddr']
     for (prop, val) in props.iteritems():
         if prop == 'hostname':
             prop = "local-hostname"
@@ -226,17 +233,16 @@
     return (False, None, None)
 
 
-def transport_vmware_guestd():
+def transport_vmware_tools():
     # http://blogs.vmware.com/vapp/2009/07/ \
     #    selfconfiguration-and-the-ovf-environment.html
-    # try:
-    #     cmd = ['vmware-guestd', '--cmd', 'info-get guestinfo.ovfEnv']
-    #     (out, err) = subp(cmd)
-    #     return(out, 'guestinfo.ovfEnv', 'vmware-guestd')
-    # except:
-    #     # would need to error check here and see why this failed
-    #     # to know if log/error should be raised
-    #     return(False, None, None)
+    for tool in ['vmtoolsd', 'vmware-guestd']:
+        try:
+            cmd = [tool, '--cmd', 'info-get guestinfo.ovfEnv']
+            (out, err) = util.subp(cmd)
+            return(out, 'guestinfo.ovfEnv', 'vmware-tools')
+        except util.ProcessExecutionError:
+            pass
     return (False, None, None)
 
 
@@ -260,6 +266,7 @@
         raise XmlError("No Child Nodes")
 
     envNsURI = "http://schemas.dmtf.org/ovf/environment/1";
+    ovfEnvNsURI = "http://www.vmware.com/schema/ovfenv";
 
     # could also check here that elem.namespaceURI ==
     #   "http://schemas.dmtf.org/ovf/environment/1";
@@ -278,8 +285,49 @@
         val = elem.attributes.getNamedItemNS(envNsURI, "value").value
         props[key] = val
 
+    ethernetAdapterSections = find_child(dom.documentElement,
+        lambda n: n.localName == "EthernetAdapterSection")
+
+    if len(ethernetAdapterSections) == 0:
+        raise XmlError("No 'EthernetAdapterSection's")
+
+    adapterElems = find_child(ethernetAdapterSections[0],
+                            (lambda n: n.localName == "Adapter"))
+
+    if len(adapterElems) == 0:
+        raise XmlError("No 'Adapter's")
+
+    val = adapterElems[0].attributes.getNamedItemNS(ovfEnvNsURI, "mac").value
+    props['macaddr'] = val
+
     return props
 
+def gen_network_config(md):
+    conf = []
+
+    dev = ''
+
+    for i in netifaces.interfaces():
+        addr = netifaces.ifaddresses(i)[netifaces.AF_LINK]
+        if addr[0]['addr'] == md['macaddr']:
+            dev = i
+            break
+
+    if dev != '':
+        conf.append('auto ' + dev)
+        conf.append('iface ' + dev + ' inet static')
+        conf.append('  address   ' + md['ipv4.address'])
+        conf.append('  netmask   ' + md['ipv4.netmask'])
+        conf.append('  broadcast ' + md['ipv4.broadcast'])
+        conf.append('  gateway   ' + md['ipv4.gateway'])
+        conf.append('  hwaddress ' + md['macaddr'])
+
+        if md['dns.server1'] or md['dns.server2']:
+            conf.append('  dns-nameservers ' + md['dns.server1'] + ' ' + md['dns.server2'])
+
+    conf.append('')
+
+    return "\n".join(conf)
 
 class XmlError(Exception):
     pass