diff options
author | Scott Moser <smoser@ubuntu.com> | 2014-02-13 06:27:22 -0500 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2014-02-13 06:27:22 -0500 |
commit | c722a6e9110b8a5dc33de8911cf5734e14dc523f (patch) | |
tree | 54acbaf93371fc42f2777f68e79768e45f47a0a7 /cloudinit/sources | |
parent | 5788cd903f6e4a9bab2ad32e9c1d2eb13b485ac3 (diff) | |
parent | f7ac086a434b511b076346839818de7cf34e18a2 (diff) | |
download | vyos-cloud-init-c722a6e9110b8a5dc33de8911cf5734e14dc523f.tar.gz vyos-cloud-init-c722a6e9110b8a5dc33de8911cf5734e14dc523f.zip |
merge from trunk
Diffstat (limited to 'cloudinit/sources')
-rw-r--r-- | cloudinit/sources/DataSourceAzure.py | 37 | ||||
-rw-r--r-- | cloudinit/sources/DataSourceCloudSigma.py | 91 | ||||
-rw-r--r-- | cloudinit/sources/DataSourceEc2.py | 7 |
3 files changed, 121 insertions, 14 deletions
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 97f151d6..c7331da5 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -34,6 +34,7 @@ DEFAULT_METADATA = {"instance-id": "iid-AZURE-NODE"} AGENT_START = ['service', 'walinuxagent', 'start'] BOUNCE_COMMAND = ['sh', '-xc', "i=$interface; x=0; ifdown $i || x=$?; ifup $i || x=$?; exit $x"] +DATA_DIR_CLEAN_LIST = ['SharedConfig.xml'] BUILTIN_DS_CONFIG = { 'agent_command': AGENT_START, @@ -101,7 +102,7 @@ class DataSourceAzureNet(sources.DataSource): except BrokenAzureDataSource as exc: raise exc except util.MountFailedError: - LOG.warn("%s was not mountable" % cdev) + LOG.warn("%s was not mountable", cdev) continue (md, self.userdata_raw, cfg, files) = ret @@ -128,10 +129,26 @@ class DataSourceAzureNet(sources.DataSource): user_ds_cfg = util.get_cfg_by_path(self.cfg, DS_CFG_PATH, {}) self.ds_cfg = util.mergemanydict([user_ds_cfg, self.ds_cfg]) mycfg = self.ds_cfg + ddir = mycfg['data_dir'] + + if found != ddir: + cached_ovfenv = util.load_file( + os.path.join(ddir, 'ovf-env.xml'), quiet=True) + if cached_ovfenv != files['ovf-env.xml']: + # source was not walinux-agent's datadir, so we have to clean + # up so 'wait_for_files' doesn't return early due to stale data + cleaned = [] + for f in [os.path.join(ddir, f) for f in DATA_DIR_CLEAN_LIST]: + if os.path.exists(f): + util.del_file(f) + cleaned.append(f) + if cleaned: + LOG.info("removed stale file(s) in '%s': %s", + ddir, str(cleaned)) # walinux agent writes files world readable, but expects # the directory to be protected. - write_files(mycfg['data_dir'], files, dirmode=0700) + write_files(ddir, files, dirmode=0700) # handle the hostname 'publishing' try: @@ -139,7 +156,7 @@ class DataSourceAzureNet(sources.DataSource): self.metadata.get('local-hostname'), mycfg['hostname_bounce']) except Exception as e: - LOG.warn("Failed publishing hostname: %s" % e) + LOG.warn("Failed publishing hostname: %s", e) util.logexc(LOG, "handling set_hostname failed") try: @@ -149,13 +166,13 @@ class DataSourceAzureNet(sources.DataSource): util.logexc(LOG, "agent command '%s' failed.", mycfg['agent_command']) - shcfgxml = os.path.join(mycfg['data_dir'], "SharedConfig.xml") + shcfgxml = os.path.join(ddir, "SharedConfig.xml") wait_for = [shcfgxml] fp_files = [] for pk in self.cfg.get('_pubkeys', []): bname = str(pk['fingerprint'] + ".crt") - fp_files += [os.path.join(mycfg['data_dir'], bname)] + fp_files += [os.path.join(ddir, bname)] missing = util.log_time(logfunc=LOG.debug, msg="waiting for files", func=wait_for_files, @@ -169,7 +186,7 @@ class DataSourceAzureNet(sources.DataSource): try: self.metadata['instance-id'] = iid_from_shared_config(shcfgxml) except ValueError as e: - LOG.warn("failed to get instance id in %s: %s" % (shcfgxml, e)) + LOG.warn("failed to get instance id in %s: %s", shcfgxml, e) pubkeys = pubkeys_from_crt_files(fp_files) @@ -250,7 +267,7 @@ def pubkeys_from_crt_files(flist): errors.append(fname) if errors: - LOG.warn("failed to convert the crt files to pubkey: %s" % errors) + LOG.warn("failed to convert the crt files to pubkey: %s", errors) return pubkeys @@ -281,7 +298,7 @@ def write_files(datadir, files, dirmode=None): def invoke_agent(cmd): # this is a function itself to simplify patching it for test if cmd: - LOG.debug("invoking agent: %s" % cmd) + LOG.debug("invoking agent: %s", cmd) util.subp(cmd, shell=(not isinstance(cmd, list))) else: LOG.debug("not invoking agent") @@ -328,7 +345,7 @@ def load_azure_ovf_pubkeys(sshnode): continue cur = {'fingerprint': "", 'path': ""} for child in pk_node.childNodes: - if (child.nodeType == text_node or not child.localName): + if child.nodeType == text_node or not child.localName: continue name = child.localName.lower() @@ -414,7 +431,7 @@ def read_azure_ovf(contents): # we accept either UserData or CustomData. If both are present # then behavior is undefined. - if (name == "userdata" or name == "customdata"): + if name == "userdata" or name == "customdata": if attrs.get('encoding') in (None, "base64"): ud = base64.b64decode(''.join(value.split())) else: diff --git a/cloudinit/sources/DataSourceCloudSigma.py b/cloudinit/sources/DataSourceCloudSigma.py new file mode 100644 index 00000000..78acd8a4 --- /dev/null +++ b/cloudinit/sources/DataSourceCloudSigma.py @@ -0,0 +1,91 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2014 CloudSigma +# +# Author: Kiril Vladimiroff <kiril.vladimiroff@cloudsigma.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 re + +from cloudinit import log as logging +from cloudinit import sources +from cloudinit import util +from cloudinit.cs_utils import Cepko + +LOG = logging.getLogger(__name__) + +VALID_DSMODES = ("local", "net", "disabled") + + +class DataSourceCloudSigma(sources.DataSource): + """ + Uses cepko in order to gather the server context from the VM. + + For more information about CloudSigma's Server Context: + http://cloudsigma-docs.readthedocs.org/en/latest/server_context.html + """ + def __init__(self, sys_cfg, distro, paths): + self.dsmode = 'local' + self.cepko = Cepko() + self.ssh_public_key = '' + sources.DataSource.__init__(self, sys_cfg, distro, paths) + + def get_data(self): + """ + Metadata is the whole server context and /meta/cloud-config is used + as userdata. + """ + try: + server_context = self.cepko.all().result + server_meta = server_context['meta'] + self.userdata_raw = server_meta.get('cloudinit-user-data', "") + self.metadata = server_context + self.ssh_public_key = server_meta['ssh_public_key'] + + if server_meta.get('cloudinit-dsmode') in VALID_DSMODES: + self.dsmode = server_meta['cloudinit-dsmode'] + except: + util.logexc(LOG, "Failed reading from the serial port") + return False + return True + + def get_hostname(self, fqdn=False, resolve_ip=False): + """ + Cleans up and uses the server's name if the latter is set. Otherwise + the first part from uuid is being used. + """ + if re.match(r'^[A-Za-z0-9 -_\.]+$', self.metadata['name']): + return self.metadata['name'][:61] + else: + return self.metadata['uuid'].split('-')[0] + + def get_public_ssh_keys(self): + return [self.ssh_public_key] + + def get_instance_id(self): + return self.metadata['uuid'] + + +# Used to match classes to dependencies. Since this datasource uses the serial +# port network is not really required, so it's okay to load without it, too. +datasources = [ + (DataSourceCloudSigma, (sources.DEP_FILESYSTEM)), + (DataSourceCloudSigma, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)), +] + + +def get_datasource_list(depends): + """ + Return a list of data sources that match this set of dependencies + """ + return sources.list_from_depends(depends, datasources) diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py index f010e640..1b20ecf3 100644 --- a/cloudinit/sources/DataSourceEc2.py +++ b/cloudinit/sources/DataSourceEc2.py @@ -92,12 +92,9 @@ class DataSourceEc2(sources.DataSource): except Exception: util.logexc(LOG, "Failed to get max wait. using %s", max_wait) - if max_wait == 0: - return False - timeout = 50 try: - timeout = int(mcfg.get("timeout", timeout)) + timeout = max(0, int(mcfg.get("timeout", timeout))) except Exception: util.logexc(LOG, "Failed to get timeout, using %s", timeout) @@ -109,6 +106,8 @@ class DataSourceEc2(sources.DataSource): mcfg = {} (max_wait, timeout) = self._get_url_settings() + if max_wait <= 0: + return False # Remove addresses from the list that wont resolve. mdurls = mcfg.get("metadata_urls", DEF_MD_URLS) |