diff -rupN cloud-init-0.7.9/cloudinit/distros/photon.py cloud-init-0.7.9-new/cloudinit/distros/photon.py --- cloud-init-0.7.9/cloudinit/distros/photon.py 1969-12-31 16:00:00.000000000 -0800 +++ cloud-init-0.7.9-new/cloudinit/distros/photon.py 2017-05-15 05:13:49.156848344 -0700 @@ -0,0 +1,320 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2017 VMware Inc. +# Author: Mahmoud Bassiouny +# + +import os + +from cloudinit import distros +from cloudinit import helpers +from cloudinit import log as logging +from cloudinit import util +from cloudinit.distros import net_util +from cloudinit.distros.parsers.hostname import HostnameConf + +from cloudinit.settings import PER_INSTANCE + +LOG = logging.getLogger(__name__) + +class Distro(distros.Distro): + hostname_conf_fn = "/etc/hostname" + locale_conf_fn = "/etc/default/locale" + network_conf_dir = "/etc/systemd/network/" + resolve_conf_fn = "/etc/systemd/resolved.conf" + init_cmd = ['systemctl'] # init scripts + + def __init__(self, name, cfg, paths): + distros.Distro.__init__(self, name, cfg, paths) + # This will be used to restrict certain + # calls from repeatly happening (when they + # should only happen say once per instance...) + self._runner = helpers.Runners(paths) + self.osfamily = 'photon' + + def apply_locale(self, locale, out_fn=None): + if not out_fn: + out_fn = self.locale_conf_fn + util.subp(['locale-gen', locale], capture=False) + util.subp(['update-locale', locale], capture=False) + # "" provides trailing newline during join + lines = [ + util.make_header(), + 'LANG="%s"' % (locale), + "", + ] + util.write_file(out_fn, "\n".join(lines)) + + def install_packages(self, pkglist): + #self.update_package_sources() + self.package_command('install', pkgs=pkglist) + + def _write_network(self, settings): + entries = net_util.translate_network(settings) + LOG.debug("Translated ubuntu style network settings %s into %s", + settings, entries) + route_entries = [] + route_entries = translate_routes(settings) + dev_names = entries.keys() + dev_index = 10; + nameservers = [] + searchdomains = [] + # Format for systemd + for (dev, info) in entries.items(): + if dev == 'lo': + continue + net_fn = self.network_conf_dir + str(dev_index) + '-' + dev + '.network' + dhcp_enabled = 'no' + if info.get('bootproto') == 'dhcp': + dhcp_enabled = 'yes' + net_cfg = { + 'Name': dev, + 'DHCP': dhcp_enabled, + } + if info.get('hwaddress'): + net_cfg['MACAddress'] = info.get('hwaddress') + if info.get('address'): + net_cfg['Address'] = "%s" % (info.get('address')) + if info.get('netmask'): + net_cfg['Address'] += "/%s" % (info.get('netmask')) + if info.get('gateway'): + net_cfg['Gateway'] = info.get('gateway') + if info.get('dns-nameservers'): + net_cfg['DNS'] = str(tuple(info.get('dns-nameservers'))).replace(',', '') + if info.get('dns-search'): + net_cfg['Domains'] = str(tuple(info.get('dns-search'))).replace(',', '') + route_entry = [] + if dev in route_entries: + route_entry = route_entries[dev] + route_index = 0 + found = True + while found: + route_name = 'routes.' + str(route_index) + if route_name in route_entries[dev]: + val = str(tuple(route_entries[dev][route_name])).replace(',', '') + if val: + net_cfg[route_name] = val + else: + found = False + route_index += 1 + + if info.get('auto'): + util.delete_dir_contents(self.network_conf_dir) + self._write_interface_file(net_fn, net_cfg, route_entry) + if 'dns-nameservers' in info: + nameservers.extend(info['dns-nameservers']) + if 'dns-search' in info: + searchdomains.extend(info['dns-search']) + dev_index = dev_index + 1; + + resolve_data = [] + new_resolve_data = [] + with open(self.resolve_conf_fn, "r") as rf: + resolve_data = rf.readlines() + LOG.debug("Old Resolve Data\n") + LOG.debug("%s",resolve_data) + for item in resolve_data: + if (nameservers and ('DNS=' in item)) or (searchdomains and ('Domains=' in item)): + continue + else: + new_resolve_data.append(item) + + new_resolve_data = new_resolve_data + convert_resolv_conf(nameservers, searchdomains) + LOG.debug("New resolve data\n") + LOG.debug("%s",new_resolve_data) + if nameservers or searchdomains: + util.write_file(self.resolve_conf_fn, ''.join(new_resolve_data)) + + return dev_names + + def _write_interface_file(self, net_fn, net_cfg, route_entry): + if not net_cfg['Name']: + return + content = "[Match]\n" + content += "Name=%s\n" % (net_cfg['Name']) + if 'MACAddress' in net_cfg: + content += "MACAddress=%s\n" % (net_cfg['MACAddress']) + content += "[Network]\n" + if 'DHCP' in net_cfg and net_cfg['DHCP'] == 'yes': + content += "DHCP=%s\n" % (net_cfg['DHCP']) + else: + if 'Address' in net_cfg: + content += "Address=%s\n" % (net_cfg['Address']) + if 'Gateway' in net_cfg: + content += "Gateway=%s\n" % (net_cfg['Gateway']) + route_index = 0 + found = True + if route_entry: + while found: + route_name = 'routes.' + str(route_index) + if route_name in route_entry: + content += "[Route]\n" + if len(route_entry[route_name]) != 2: + continue + content += "Gateway=%s\n" % (route_entry[route_name][0]) + content += "Destination=%s\n" % (route_entry[route_name][1]) + else: + found = False + route_index += 1 + + util.write_file(net_fn, content) + + + def _bring_up_interfaces(self, device_names): + cmd = ['systemctl', 'restart', 'systemd-networkd', 'systemd-resolved'] + LOG.debug("Attempting to run bring up interfaces using command %s", + cmd) + try: + (_out, err) = util.subp(cmd) + if len(err): + LOG.warn("Running %s resulted in stderr output: %s", cmd, err) + return True + except util.ProcessExecutionError: + util.logexc(LOG, "Running network bringup command %s failed", cmd) + return False + + def _select_hostname(self, hostname, fqdn): + # Prefer the short hostname over the long + # fully qualified domain name + if not hostname: + return fqdn + return hostname + + def _write_hostname(self, your_hostname, out_fn): + conf = None + try: + # Try to update the previous one + # so lets see if we can read it first. + conf = self._read_hostname_conf(out_fn) + except IOError: + pass + if not conf: + conf = HostnameConf('') + conf.set_hostname(your_hostname) + util.write_file(out_fn, str(conf), mode=0o644) + + def _read_system_hostname(self): + sys_hostname = self._read_hostname(self.hostname_conf_fn) + return (self.hostname_conf_fn, sys_hostname) + + def _read_hostname_conf(self, filename): + conf = HostnameConf(util.load_file(filename)) + conf.parse() + return conf + + def _read_hostname(self, filename, default=None): + hostname = None + try: + conf = self._read_hostname_conf(filename) + hostname = conf.hostname + except IOError: + pass + if not hostname: + return default + return hostname + + def _get_localhost_ip(self): + return "127.0.1.1" + + def set_timezone(self, tz): + distros.set_etc_timezone(tz=tz, tz_file=self._find_tz_file(tz)) + + def package_command(self, command, args=None, pkgs=None): + if pkgs is None: + pkgs = [] + + cmd = ['tdnf'] + # Determines whether or not tdnf prompts for confirmation + # of critical actions. We don't want to prompt... + cmd.append("-y") + + if args and isinstance(args, str): + cmd.append(args) + elif args and isinstance(args, list): + cmd.extend(args) + + cmd.append(command) + + pkglist = util.expand_package_list('%s-%s', pkgs) + cmd.extend(pkglist) + + # Allow the output of this to flow outwards (ie not be captured) + util.subp(cmd, capture=False) + + def update_package_sources(self): + self._runner.run("update-sources", self.package_command, + ["makecache"], freq=PER_INSTANCE) + +def convert_resolv_conf(nameservers, searchdomains): + """Returns a string formatted for resolv.conf.""" + result = [] + if nameservers: + nslist = "DNS=" + for ns in nameservers: + nslist = nslist + '%s ' % ns + nslist = nslist + '\n' + result.append(str(nslist)) + if searchdomains: + sdlist = "Domains=" + for sd in searchdomains: + sdlist = sdlist + '%s ' % sd + sdlist = sdlist + '\n' + result.append(str(sdlist)) + return result + +def translate_routes(settings): + entries = [] + for line in settings.splitlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + split_up = line.split(None, 1) + if len(split_up) <= 1: + continue + entries.append(split_up) + consume = {} + ifaces = [] + for (cmd, args) in entries: + if cmd == 'iface': + if consume: + ifaces.append(consume) + consume = {} + consume[cmd] = args + else: + consume[cmd] = args + + absorb = False + for (cmd, args) in consume.items(): + if cmd == 'iface': + absorb = True + if absorb: + ifaces.append(consume) + out_ifaces = {} + for info in ifaces: + if 'iface' not in info: + continue + iface_details = info['iface'].split(None) + dev_name = None + if len(iface_details) >= 1: + dev = iface_details[0].strip().lower() + if dev: + dev_name = dev + if not dev_name: + continue + route_info = {} + route_index = 0 + found = True + while found: + route_name = 'routes.' + str(route_index) + if route_name in info: + val = info[route_name].split() + if val: + route_info[route_name] = val + else: + found = False + route_index += 1 + if dev_name in out_ifaces: + out_ifaces[dev_name].update(route_info) + else: + out_ifaces[dev_name] = route_info + return out_ifaces