cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #00589
[Merge] lp:~i-franz/cloud-init/network-config-for-ovf into lp:cloud-init
Franz Schwartau has proposed merging lp:~i-franz/cloud-init/network-config-for-ovf 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/network-config-for-ovf/+merge/244467
Allow network configuration via OVF properties in DataSourceOVF.
Add handling for dhcphostname
--
Your team cloud init development team is requested to review the proposed merge of lp:~i-franz/cloud-init/network-config-for-ovf into lp:cloud-init.
=== modified file 'cloudinit/distros/net_util.py'
--- cloudinit/distros/net_util.py 2014-11-25 00:30:00 +0000
+++ cloudinit/distros/net_util.py 2014-12-11 16:27:59 +0000
@@ -133,6 +133,8 @@
# really care about
if proto_type in ['dhcp', 'static']:
iface_info['bootproto'] = proto_type
+ if proto_type == 'dhcp' and 'hostname' in info:
+ iface_info['dhcphostname'] = info['hostname']
# These can just be copied over
if use_ipv6:
for k in ['address', 'gateway']:
=== modified file 'cloudinit/distros/rhel.py'
--- cloudinit/distros/rhel.py 2014-11-25 19:46:10 +0000
+++ cloudinit/distros/rhel.py 2014-12-11 16:27:59 +0000
@@ -84,6 +84,7 @@
'BROADCAST': info.get('broadcast'),
'MACADDR': info.get('hwaddress'),
'ONBOOT': _make_sysconfig_bool(info.get('auto')),
+ 'DHCP_HOSTNAME': info.get('dhcphostname'),
}
if info.get('inet6'):
use_ipv6 = True
=== modified file 'cloudinit/sources/DataSourceOVF.py'
--- cloudinit/sources/DataSourceOVF.py 2014-09-22 18:35:03 +0000
+++ cloudinit/sources/DataSourceOVF.py 2014-12-11 16:27:59 +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,17 @@
md = util.mergemanydict([md, md_seed])
found.append(seedfrom)
+ try:
+ network_config = gen_network_config(md)
+
+ if network_config != '':
+ LOG.debug("Updating network interfaces from %s", self)
+ self.distro.apply_network(network_config)
+ else:
+ LOG.debug("network_config empty. Is ipv4.bootproto empty?")
+ except Exception as e:
+ util.logexc(LOG, 'NetworkConfigError: %s' % str(e))
+
# Now that we have exhausted any other places merge in the defaults
md = util.mergemanydict([md, defaults])
@@ -137,7 +149,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.bootproto', 'ipv4.dhcphostname', '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 +238,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 +271,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,12 +290,76 @@
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 = []
+
+ if 'ipv4.bootproto' not in md:
+ return ''
+
+ if 'macaddr' not in md:
+ raise NetworkConfigError('No macaddr in metadata')
+
+ dev = ''
+
+ for i in netifaces.interfaces():
+ addr = netifaces.ifaddresses(i)[netifaces.AF_LINK]
+ if addr[0]['addr'] == md['macaddr']:
+ dev = i
+ break
+
+ if dev == '':
+ raise NetworkConfigError('Could not find interface for macaddr ' + md['macaddr'])
+
+ if md['ipv4.bootproto'] == 'static':
+ if set(('ipv4.address', 'ipv4.netmask', 'ipv4.broadcast', 'ipv4.gateway')) > set(md):
+ raise NetworkConfigError('All of ipv4.address, ipv4.netmask, ipv4.broadcast, and ipv4.gateway have to be set.')
+
+ conf.append('auto ' + dev)
+ conf.append('iface ' + dev + ' inet ' + md['ipv4.bootproto'])
+ 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 'dns.server1' in md or 'dns.server2' in md:
+ conf.append(' dns-nameservers ' + ' '.join((md.get('dns.server1'), md.get('dns.server2'))))
+ elif md['ipv4.bootproto'] == 'dhcp':
+ conf.append('auto ' + dev)
+ conf.append('iface ' + dev + ' inet ' + md['ipv4.bootproto'])
+
+ if 'ipv4.dhcphostname' in md:
+ conf.append(' hostname ' + md['ipv4.dhcphostname'])
+ else:
+ raise NetworkConfigError('ipv4.bootproto has to be dhcp or static')
+
+ conf.append('')
+
+ return "\n".join(conf)
class XmlError(Exception):
pass
+class NetworkConfigError(Exception):
+ pass
+
# Used to match classes to dependencies
datasources = (
=== modified file 'requirements.txt'
--- requirements.txt 2014-03-05 23:05:59 +0000
+++ requirements.txt 2014-12-11 16:27:59 +0000
@@ -32,3 +32,6 @@
# For patching pieces of cloud-config together
jsonpatch
+
+# used in DataSourceOVF for mac addr -> interface lookup
+netifaces
Follow ups