summaryrefslogtreecommitdiff
path: root/cloudinit/sources/DataSourceOpenNebula.py
diff options
context:
space:
mode:
authorVlastimil Holer <vlastimil.holer@gmail.com>2013-09-05 17:55:53 +0200
committerVlastimil Holer <vlastimil.holer@gmail.com>2013-09-05 17:55:53 +0200
commitd0e7898d4d0aef452fbfdd9b51fa2da6437397ff (patch)
tree51cccff01ab8af5637ecf5a564491737c1a55b03 /cloudinit/sources/DataSourceOpenNebula.py
parent744c779182cba32314f8435660a61c2711cb9f54 (diff)
downloadvyos-cloud-init-d0e7898d4d0aef452fbfdd9b51fa2da6437397ff.tar.gz
vyos-cloud-init-d0e7898d4d0aef452fbfdd9b51fa2da6437397ff.zip
PEP8 and Pylint fixes. Move context.sh "parser" into separate
function. Fix fetching user specified dsmode (from context). Rename context_sh->context. Reuse unittests.helpers.populate_dir.
Diffstat (limited to 'cloudinit/sources/DataSourceOpenNebula.py')
-rw-r--r--cloudinit/sources/DataSourceOpenNebula.py163
1 files changed, 88 insertions, 75 deletions
diff --git a/cloudinit/sources/DataSourceOpenNebula.py b/cloudinit/sources/DataSourceOpenNebula.py
index fef7beac..87ec51bd 100644
--- a/cloudinit/sources/DataSourceOpenNebula.py
+++ b/cloudinit/sources/DataSourceOpenNebula.py
@@ -3,7 +3,7 @@
# Copyright (C) 2012 Canonical Ltd.
# Copyright (C) 2012 Yahoo! Inc.
# Copyright (C) 2012-2013 CERIT Scientific Cloud
-# Copyright (C) 2012 OpenNebula.org
+# Copyright (C) 2012-2013 OpenNebula.org
#
# Author: Scott Moser <scott.moser@canonical.com>
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
@@ -45,45 +45,47 @@ class DataSourceOpenNebula(sources.DataSource):
self.seed_dir = os.path.join(paths.seed_dir, 'opennebula')
def __str__(self):
- return "%s [seed=%s][dsmode=%s]" % \
- (util.obj_name(self), self.seed, self.dsmode)
+ root = sources.DataSource.__str__(self)
+ return "%s [seed=%s][dsmode=%s]" % (root, self.seed, self.dsmode)
def get_data(self):
defaults = {
"instance-id": DEFAULT_IID,
- "dsmode": self.dsmode}
+ "dsmode": self.dsmode
+ }
- found = None
- md = {}
+ seed = None
results = {}
+ # first try to read local seed_dir
if os.path.isdir(self.seed_dir):
try:
results = read_context_disk_dir(self.seed_dir)
- found = self.seed_dir
+ seed = self.seed_dir
except NonContextDiskDir:
- util.logexc(LOG, "Failed reading context disk from %s",
+ util.logexc(LOG, "Failed reading context from %s",
self.seed_dir)
- # find candidate devices, try to mount them and
- # read context script if present
- if not found:
+ if not seed:
+ # then try to detect and mount candidate devices and
+ # read contextualization if present
for dev in find_candidate_devs():
try:
results = util.mount_cb(dev, read_context_disk_dir)
- found = dev
+ seed = dev
break
except (NonContextDiskDir, util.MountFailedError):
pass
- if not found:
+ if not seed:
return False
+ # merge fetched metadata with datasource defaults
md = results['metadata']
- md = util.mergedict(md, defaults)
+ md = util.mergemanydict([md, defaults])
# check for valid user specified dsmode
- user_dsmode = results.get('dsmode', None)
+ user_dsmode = results['metadata'].get('dsmode', None)
if user_dsmode not in VALID_DSMODES + (None,):
LOG.warn("user specified invalid mode: %s", user_dsmode)
user_dsmode = None
@@ -109,10 +111,9 @@ class DataSourceOpenNebula(sources.DataSource):
LOG.debug("%s: not claiming datasource, dsmode=%s", self, dsmode)
return False
- self.seed = found
+ self.seed = seed
self.metadata = md
self.userdata_raw = results.get('userdata')
-
return True
def get_hostname(self, fqdn=False, resolve_ip=None):
@@ -139,9 +140,9 @@ class OpenNebulaNetwork(object):
r'^\d+: (eth\d+):.*?link\/ether (..:..:..:..:..:..) ?',
re.MULTILINE | re.DOTALL)
- def __init__(self, ip, context_sh):
+ def __init__(self, ip, context):
self.ip = ip
- self.context_sh = context_sh
+ self.context = context
self.ifaces = self.get_ifaces()
def get_ifaces(self):
@@ -153,50 +154,50 @@ class OpenNebulaNetwork(object):
def get_ip(self, dev, components):
var_name = dev + '_ip'
- if var_name in self.context_sh:
- return self.context_sh[var_name]
+ if var_name in self.context:
+ return self.context[var_name]
else:
return '.'.join(components)
def get_mask(self, dev):
var_name = dev + '_mask'
- if var_name in self.context_sh:
- return self.context_sh[var_name]
+ if var_name in self.context:
+ return self.context[var_name]
else:
return '255.255.255.0'
def get_network(self, dev, components):
var_name = dev + '_network'
- if var_name in self.context_sh:
- return self.context_sh[var_name]
+ if var_name in self.context:
+ return self.context[var_name]
else:
return '.'.join(components[:-1]) + '.0'
def get_gateway(self, dev):
var_name = dev + '_gateway'
- if var_name in self.context_sh:
- return self.context_sh[var_name]
+ if var_name in self.context:
+ return self.context[var_name]
else:
return None
def get_dns(self, dev):
var_name = dev + '_dns'
- if var_name in self.context_sh:
- return self.context_sh[var_name]
+ if var_name in self.context:
+ return self.context[var_name]
else:
return None
def get_domain(self, dev):
var_name = dev + '_domain'
- if var_name in self.context_sh:
- return self.context_sh[var_name]
+ if var_name in self.context:
+ return self.context[var_name]
else:
return None
def gen_conf(self):
global_dns = []
- if 'dns' in self.context_sh:
- global_dns.append(self.context_sh['dns'])
+ if 'dns' in self.context:
+ global_dns.append(self.context['dns'])
conf = []
conf.append('auto lo')
@@ -241,101 +242,113 @@ def find_candidate_devs():
"""
combined = []
for f in ('LABEL=CONTEXT', 'LABEL=CDROM', 'TYPE=iso9660'):
- for d in util.find_devs_with(f).sort():
+ devs = util.find_devs_with(f)
+ devs.sort()
+ for d in devs:
if d not in combined:
combined.append(d)
return combined
+def parse_context_data(data):
+ """
+ parse_context_data(data)
+ parse context.sh variables provided as a single string. Uses
+ very simple matching RE. Returns None if nothing is matched.
+ """
+ # RE groups:
+ # 1: key
+ # 2: single quoted value, respect '\''
+ # 3: old double quoted value, but doesn't end with \"
+ context_reg = re.compile(
+ r"^([\w_]+)=(?:'((?:[^']|'\\'')*?)'|\"(.*?[^\\])\")$",
+ re.MULTILINE | re.DOTALL)
+
+ found = context_reg.findall(data)
+ if not found:
+ return None
+
+ variables = {}
+ for k, v1, v2 in found:
+ k = k.lower()
+ if v1:
+ # take single quoted variable 'xyz'
+ # (ON>=4) and unquote '\'' -> '
+ variables[k] = v1.replace(r"'\''", r"'")
+ elif v2:
+ # take double quoted variable "xyz"
+ # (old ON<4) and unquote \" -> "
+ variables[k] = v2.replace(r'\"', r'"')
+
+ return variables
+
+
def read_context_disk_dir(source_dir):
"""
read_context_disk_dir(source_dir):
read source_dir and return a tuple with metadata dict and user-data
string populated. If not a valid dir, raise a NonContextDiskDir
"""
-
found = {}
for af in CONTEXT_DISK_FILES:
fn = os.path.join(source_dir, af)
if os.path.isfile(fn):
found[af] = fn
- if len(found) == 0:
+ if not found:
raise NonContextDiskDir("%s: %s" % (source_dir, "no files found"))
results = {'userdata': None, 'metadata': {}}
- context_sh = {}
+ context = {}
if "context.sh" in found:
try:
- f = open('%s/context.sh' % (source_dir), 'r')
- text = f.read()
- f.close()
-
- # lame matching:
- # 1. group = key
- # 2. group = single quoted value, respect '\''
- # 3. group = old double quoted value, but doesn't end with \"
- context_reg = re.compile(
- r"^([\w_]+)=(?:'((?:[^']|'\\'')*?)'|\"(.*?[^\\])\")$",
- re.MULTILINE | re.DOTALL)
-
- variables = context_reg.findall(text)
- if not variables:
+ with open(os.path.join(source_dir, 'context.sh'), 'r') as f:
+ context = parse_context_data(f.read())
+ f.close()
+ if not context:
raise NonContextDiskDir("No variables in context")
- for k, v1, v2 in variables:
- k = k.lower()
- if v1:
- # take single quoted variable 'xyz'
- # (ON>=4) and unquote '\'' -> '
- context_sh[k] = v1.replace(r"'\''", r"'")
- elif v2:
- # take double quoted variable "xyz"
- # (old ON<4) and unquote \" -> "
- context_sh[k] = v2.replace(r'\"', r'"')
-
except (IOError, NonContextDiskDir) as e:
raise NonContextDiskDir("Error reading context.sh: %s" % (e))
- results['metadata'] = context_sh
+ results['metadata'] = context
else:
raise NonContextDiskDir("Missing context.sh")
# process single or multiple SSH keys
ssh_key_var = None
-
- if "ssh_key" in context_sh:
+ if "ssh_key" in context:
ssh_key_var = "ssh_key"
- elif "ssh_public_key" in context_sh:
+ elif "ssh_public_key" in context:
ssh_key_var = "ssh_public_key"
if ssh_key_var:
- lines = context_sh.get(ssh_key_var).splitlines()
+ lines = context.get(ssh_key_var).splitlines()
results['metadata']['public-keys'] = [l for l in lines
if len(l) and not l.startswith("#")]
# custom hostname -- try hostname or leave cloud-init
# itself create hostname from IP address later
for k in ('hostname', 'public_ip', 'ip_public', 'eth0_ip'):
- if k in context_sh:
- results['metadata']['local-hostname'] = context_sh[k]
+ if k in context:
+ results['metadata']['local-hostname'] = context[k]
break
# raw user data
- if "user_data" in context_sh:
- results['userdata'] = context_sh["user_data"]
- elif "userdata" in context_sh:
- results['userdata'] = context_sh["userdata"]
+ if "user_data" in context:
+ results['userdata'] = context["user_data"]
+ elif "userdata" in context:
+ results['userdata'] = context["userdata"]
# generate static /etc/network/interfaces
# only if there are any required context variables
# http://opennebula.org/documentation:rel3.8:cong#network_configuration
- for k in context_sh.keys():
+ for k in context.keys():
if re.match(r'^eth\d+_ip$', k):
(out, _) = util.subp(['/sbin/ip', 'link'])
- net = OpenNebulaNetwork(out, context_sh)
+ net = OpenNebulaNetwork(out, context)
results['network-interfaces'] = net.gen_conf()
break