diff options
author | Scott Moser <smoser@brickies.net> | 2016-08-23 16:48:41 -0400 |
---|---|---|
committer | Scott Moser <smoser@brickies.net> | 2016-08-23 16:48:41 -0400 |
commit | 7b925df28f84c824e9e4697723d879903a81e780 (patch) | |
tree | 2314e210f13cc5cc7bdc59971b9f4b657f755825 /cloudinit | |
parent | d0c794919d9a9bf176eb96e25e72836a65e841f1 (diff) | |
parent | a551cb080388c2016bcf23981f99a4a6aa0fe198 (diff) | |
download | vyos-cloud-init-7b925df28f84c824e9e4697723d879903a81e780.tar.gz vyos-cloud-init-7b925df28f84c824e9e4697723d879903a81e780.zip |
merge trunk at 0.7.7~bzr1208
Diffstat (limited to 'cloudinit')
-rw-r--r-- | cloudinit/config/cc_chef.py | 26 | ||||
-rw-r--r-- | cloudinit/config/cc_lxd.py | 121 | ||||
-rw-r--r-- | cloudinit/config/cc_phone_home.py | 7 | ||||
-rw-r--r-- | cloudinit/config/cc_rh_subscription.py | 14 | ||||
-rw-r--r-- | cloudinit/distros/rhel_util.py | 2 | ||||
-rw-r--r-- | cloudinit/net/__init__.py | 3 | ||||
-rw-r--r-- | cloudinit/sources/DataSourceCloudSigma.py | 2 | ||||
-rw-r--r-- | cloudinit/sources/DataSourceNoCloud.py | 7 | ||||
-rw-r--r-- | cloudinit/sources/DataSourceSmartOS.py | 2 |
9 files changed, 150 insertions, 34 deletions
diff --git a/cloudinit/config/cc_chef.py b/cloudinit/config/cc_chef.py index 28711a59..4c28be6a 100644 --- a/cloudinit/config/cc_chef.py +++ b/cloudinit/config/cc_chef.py @@ -38,8 +38,10 @@ It can be configured with the following option structure:: chef: directories: (defaulting to /etc/chef, /var/log/chef, /var/lib/chef, /var/cache/chef, /var/backups/chef, /var/run/chef) - validation_key or validation_cert: (optional string to be written to - /etc/chef/validation.pem) + validation_cert: (optional string to be written to file validation_key) + special value 'system' means set use existing file + validation_key: (optional the path for validation_cert. default + /etc/chef/validation.pem) firstboot_path: (path to write run_list and initial_attributes keys that should also be present in this configuration, defaults to /etc/chef/firstboot.json) @@ -64,6 +66,7 @@ It can be configured with the following option structure:: server_url: show_time: ssl_verify_mode: + validation_cert: validation_key: validation_name: """ @@ -105,6 +108,7 @@ CHEF_RB_TPL_DEFAULTS = { # These are not symbols... 'log_location': '/var/log/chef/client.log', 'validation_key': CHEF_VALIDATION_PEM_PATH, + 'validation_cert': None, 'client_key': "/etc/chef/client.pem", 'json_attribs': CHEF_FB_PATH, 'file_cache_path': "/var/cache/chef", @@ -201,13 +205,17 @@ def handle(name, cfg, cloud, log, _args): for d in itertools.chain(chef_dirs, REQUIRED_CHEF_DIRS): util.ensure_dir(d) - # Set the validation key based on the presence of either 'validation_key' - # or 'validation_cert'. In the case where both exist, 'validation_key' - # takes precedence - for key in ('validation_key', 'validation_cert'): - if key in chef_cfg and chef_cfg[key]: - util.write_file(CHEF_VALIDATION_PEM_PATH, chef_cfg[key]) - break + vkey_path = chef_cfg.get('validation_key', CHEF_VALIDATION_PEM_PATH) + vcert = chef_cfg.get('validation_cert') + # special value 'system' means do not overwrite the file + # but still render the template to contain 'validation_key' + if vcert: + if vcert != "system": + util.write_file(vkey_path, vcert) + elif not os.path.isfile(vkey_path): + log.warn("chef validation_cert provided as 'system', but " + "validation_key path '%s' does not exist.", + vkey_path) # Create the chef config from template template_fn = cloud.get_template_filename('chef_client.rb') diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py index 63b8fb63..bf735648 100644 --- a/cloudinit/config/cc_lxd.py +++ b/cloudinit/config/cc_lxd.py @@ -30,6 +30,19 @@ Example config: storage_create_loop: <size> storage_pool: <name> trust_password: <password> + bridge: + mode: <new, existing or none> + name: <name> + ipv4_address: <ip addr> + ipv4_netmask: <cidr> + ipv4_dhcp_first: <ip addr> + ipv4_dhcp_last: <ip addr> + ipv4_dhcp_leases: <size> + ipv4_nat: <bool> + ipv6_address: <ip addr> + ipv6_netmask: <cidr> + ipv6_nat: <bool> + domain: <domain> """ from cloudinit import util @@ -46,22 +59,24 @@ def handle(name, cfg, cloud, log, args): type(lxd_cfg)) return + # Grab the configuration init_cfg = lxd_cfg.get('init') if not isinstance(init_cfg, dict): log.warn("lxd/init config must be a dictionary. found a '%s'", type(init_cfg)) init_cfg = {} - if not init_cfg: - log.debug("no lxd/init config. disabled.") - return + bridge_cfg = lxd_cfg.get('bridge') + if not isinstance(bridge_cfg, dict): + log.warn("lxd/bridge config must be a dictionary. found a '%s'", + type(bridge_cfg)) + bridge_cfg = {} + # Install the needed packages packages = [] - # Ensure lxd is installed if not util.which("lxd"): packages.append('lxd') - # if using zfs, get the utils if init_cfg.get("storage_backend") == "zfs" and not util.which('zfs'): packages.append('zfs') @@ -73,13 +88,89 @@ def handle(name, cfg, cloud, log, args): return # Set up lxd if init config is given - init_keys = ( - 'network_address', 'network_port', 'storage_backend', - 'storage_create_device', 'storage_create_loop', - 'storage_pool', 'trust_password') - cmd = ['lxd', 'init', '--auto'] - for k in init_keys: - if init_cfg.get(k): - cmd.extend(["--%s=%s" % - (k.replace('_', '-'), str(init_cfg[k]))]) - util.subp(cmd) + if init_cfg: + init_keys = ( + 'network_address', 'network_port', 'storage_backend', + 'storage_create_device', 'storage_create_loop', + 'storage_pool', 'trust_password') + cmd = ['lxd', 'init', '--auto'] + for k in init_keys: + if init_cfg.get(k): + cmd.extend(["--%s=%s" % + (k.replace('_', '-'), str(init_cfg[k]))]) + util.subp(cmd) + + # Set up lxd-bridge if bridge config is given + dconf_comm = "debconf-communicate" + if bridge_cfg and util.which(dconf_comm): + debconf = bridge_to_debconf(bridge_cfg) + + # Update debconf database + try: + log.debug("Setting lxd debconf via " + dconf_comm) + data = "\n".join(["set %s %s" % (k, v) + for k, v in debconf.items()]) + "\n" + util.subp(['debconf-communicate'], data) + except: + util.logexc(log, "Failed to run '%s' for lxd with" % dconf_comm) + + # Remove the existing configuration file (forces re-generation) + util.del_file("/etc/default/lxd-bridge") + + # Run reconfigure + log.debug("Running dpkg-reconfigure for lxd") + util.subp(['dpkg-reconfigure', 'lxd', + '--frontend=noninteractive']) + elif bridge_cfg: + raise RuntimeError( + "Unable to configure lxd bridge without %s." + dconf_comm) + + +def bridge_to_debconf(bridge_cfg): + debconf = {} + + if bridge_cfg.get("mode") == "none": + debconf["lxd/setup-bridge"] = "false" + debconf["lxd/bridge-name"] = "" + + elif bridge_cfg.get("mode") == "existing": + debconf["lxd/setup-bridge"] = "false" + debconf["lxd/use-existing-bridge"] = "true" + debconf["lxd/bridge-name"] = bridge_cfg.get("name") + + elif bridge_cfg.get("mode") == "new": + debconf["lxd/setup-bridge"] = "true" + if bridge_cfg.get("name"): + debconf["lxd/bridge-name"] = bridge_cfg.get("name") + + if bridge_cfg.get("ipv4_address"): + debconf["lxd/bridge-ipv4"] = "true" + debconf["lxd/bridge-ipv4-address"] = \ + bridge_cfg.get("ipv4_address") + debconf["lxd/bridge-ipv4-netmask"] = \ + bridge_cfg.get("ipv4_netmask") + debconf["lxd/bridge-ipv4-dhcp-first"] = \ + bridge_cfg.get("ipv4_dhcp_first") + debconf["lxd/bridge-ipv4-dhcp-last"] = \ + bridge_cfg.get("ipv4_dhcp_last") + debconf["lxd/bridge-ipv4-dhcp-leases"] = \ + bridge_cfg.get("ipv4_dhcp_leases") + debconf["lxd/bridge-ipv4-nat"] = \ + bridge_cfg.get("ipv4_nat", "true") + + if bridge_cfg.get("ipv6_address"): + debconf["lxd/bridge-ipv6"] = "true" + debconf["lxd/bridge-ipv6-address"] = \ + bridge_cfg.get("ipv6_address") + debconf["lxd/bridge-ipv6-netmask"] = \ + bridge_cfg.get("ipv6_netmask") + debconf["lxd/bridge-ipv6-nat"] = \ + bridge_cfg.get("ipv6_nat", "false") + + if bridge_cfg.get("domain"): + debconf["lxd/bridge-domain"] = bridge_cfg.get("domain") + + else: + raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode")) + + return debconf diff --git a/cloudinit/config/cc_phone_home.py b/cloudinit/config/cc_phone_home.py index 18a7ddad..3dcc9459 100644 --- a/cloudinit/config/cc_phone_home.py +++ b/cloudinit/config/cc_phone_home.py @@ -30,7 +30,8 @@ POST_LIST_ALL = [ 'pub_key_rsa', 'pub_key_ecdsa', 'instance_id', - 'hostname' + 'hostname', + 'fdqn' ] @@ -41,7 +42,8 @@ POST_LIST_ALL = [ # # phone_home: # url: http://my.foo.bar/$INSTANCE_ID/ -# post: [ pub_key_dsa, pub_key_rsa, pub_key_ecdsa, instance_id +# post: [ pub_key_dsa, pub_key_rsa, pub_key_ecdsa, instance_id, hostname, +# fqdn ] # def handle(name, cfg, cloud, log, args): if len(args) != 0: @@ -74,6 +76,7 @@ def handle(name, cfg, cloud, log, args): all_keys = {} all_keys['instance_id'] = cloud.get_instance_id() all_keys['hostname'] = cloud.get_hostname() + all_keys['fqdn'] = cloud.get_hostname(fqdn=True) pubkeys = { 'pub_key_dsa': '/etc/ssh/ssh_host_dsa_key.pub', diff --git a/cloudinit/config/cc_rh_subscription.py b/cloudinit/config/cc_rh_subscription.py index 6087c45c..3a113aea 100644 --- a/cloudinit/config/cc_rh_subscription.py +++ b/cloudinit/config/cc_rh_subscription.py @@ -19,10 +19,14 @@ from cloudinit import util -def handle(_name, cfg, _cloud, log, _args): +def handle(name, cfg, _cloud, log, _args): sm = SubscriptionManager(cfg) sm.log = log - if not sm.is_registered: + if not sm.is_configured(): + log.debug("%s: module not configured.", name) + return None + + if not sm.is_registered(): try: verify, verify_msg = sm._verify_keys() if verify is not True: @@ -95,7 +99,6 @@ class SubscriptionManager(object): self.disable_repo = self.rhel_cfg.get('disable-repo') self.servicelevel = self.rhel_cfg.get('service-level') self.subman = ['subscription-manager'] - self.is_registered = self._is_registered() def log_success(self, msg): '''Simple wrapper for logging info messages. Useful for unittests''' @@ -134,7 +137,7 @@ class SubscriptionManager(object): return False, no_auto return True, None - def _is_registered(self): + def is_registered(self): ''' Checks if the system is already registered and returns True if so, else False @@ -400,3 +403,6 @@ class SubscriptionManager(object): self.log.debug("Disabled the following repos: %s" % (", ".join(disable_list)).replace('--disable=', '')) return True + + def is_configured(self): + return bool((self.userid and self.password) or self.activation_key) diff --git a/cloudinit/distros/rhel_util.py b/cloudinit/distros/rhel_util.py index 84aad623..903d7793 100644 --- a/cloudinit/distros/rhel_util.py +++ b/cloudinit/distros/rhel_util.py @@ -86,4 +86,4 @@ def update_resolve_conf_file(fn, dns_servers, search_servers): r_conf.add_search_domain(s) except ValueError: util.logexc(LOG, "Failed at adding search domain %s", s) - util.write_file(fn, r_conf, 0o644) + util.write_file(fn, str(r_conf), 0o644) diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index 40929c6e..31110292 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -646,6 +646,9 @@ def generate_fallback_config(): connected = [] possibly_connected = [] for interface in potential_interfaces: + if os.path.exists(sys_dev_path(interface, "bridge")): + # skip any bridges + continue try: carrier = int(sys_netdev_info(interface, 'carrier')) if carrier: diff --git a/cloudinit/sources/DataSourceCloudSigma.py b/cloudinit/sources/DataSourceCloudSigma.py index f8f94759..d7d4e844 100644 --- a/cloudinit/sources/DataSourceCloudSigma.py +++ b/cloudinit/sources/DataSourceCloudSigma.py @@ -56,7 +56,7 @@ class DataSourceCloudSigma(sources.DataSource): LOG.debug("determining hypervisor product name via dmi data") sys_product_name = util.read_dmi_data("system-product-name") if not sys_product_name: - LOG.warn("failed to get hypervisor product name via dmi data") + LOG.debug("system-product-name not available in dmi data") return False else: LOG.debug("detected hypervisor as %s", sys_product_name) diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py index c2fba4d2..74d0e5ec 100644 --- a/cloudinit/sources/DataSourceNoCloud.py +++ b/cloudinit/sources/DataSourceNoCloud.py @@ -216,8 +216,11 @@ class DataSourceNoCloud(sources.DataSource): if not current: return None + # LP: #1568150 need getattr in the case that an old class object + # has been loaded from a pickled file and now executing new source. + dirs = getattr(self, 'seed_dirs', [self.seed_dir]) quick_id = _quick_read_instance_id(cmdline_id=self.cmdline_id, - dirs=self.seed_dirs) + dirs=dirs) if not quick_id: return None return quick_id == current @@ -238,6 +241,8 @@ def _quick_read_instance_id(cmdline_id, dirs=None): return fill[iid_key] for d in dirs: + if d is None: + continue try: data = util.pathprefix2dict(d, required=['meta-data']) md = util.load_yaml(data['meta-data']) diff --git a/cloudinit/sources/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py index 5edab152..6cbd8dfa 100644 --- a/cloudinit/sources/DataSourceSmartOS.py +++ b/cloudinit/sources/DataSourceSmartOS.py @@ -242,7 +242,7 @@ class DataSourceSmartOS(sources.DataSource): # SDC KVM instances will provide dmi data, LX-brand does not if self.smartos_type == 'kvm': dmi_info = dmi_data() - if dmi_info is False: + if dmi_info is None: LOG.debug("No dmidata utility found") return False |