|
Packit Service |
a04d08 |
# Copyright (C) 2012 Canonical Ltd.
|
|
Packit Service |
a04d08 |
# Copyright (C) 2012, 2013 Hewlett-Packard Development Company, L.P.
|
|
Packit Service |
a04d08 |
# Copyright (C) 2012 Yahoo! Inc.
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# Author: Scott Moser <scott.moser@canonical.com>
|
|
Packit Service |
a04d08 |
# Author: Juerg Haefliger <juerg.haefliger@hp.com>
|
|
Packit Service |
a04d08 |
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# This file is part of cloud-init. See LICENSE file for license information.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from time import time
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
import contextlib
|
|
Packit Service |
a04d08 |
import os
|
|
Packit Service |
a04d08 |
from configparser import NoSectionError, NoOptionError, RawConfigParser
|
|
Packit Service |
a04d08 |
from io import StringIO
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE,
|
|
Packit Service |
a04d08 |
CFG_ENV_NAME)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit import log as logging
|
|
Packit Service |
a04d08 |
from cloudinit import type_utils
|
|
Packit Service |
a04d08 |
from cloudinit import util
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
LOG = logging.getLogger(__name__)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class LockFailure(Exception):
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class DummyLock(object):
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class DummySemaphores(object):
|
|
Packit Service |
a04d08 |
def __init__(self):
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
@contextlib.contextmanager
|
|
Packit Service |
a04d08 |
def lock(self, _name, _freq, _clear_on_fail=False):
|
|
Packit Service |
a04d08 |
yield DummyLock()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def has_run(self, _name, _freq):
|
|
Packit Service |
a04d08 |
return False
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def clear(self, _name, _freq):
|
|
Packit Service |
a04d08 |
return True
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def clear_all(self):
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class FileLock(object):
|
|
Packit Service |
a04d08 |
def __init__(self, fn):
|
|
Packit Service |
a04d08 |
self.fn = fn
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def __str__(self):
|
|
Packit Service |
a04d08 |
return "<%s using file %r>" % (type_utils.obj_name(self), self.fn)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def canon_sem_name(name):
|
|
Packit Service |
a04d08 |
return name.replace("-", "_")
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class FileSemaphores(object):
|
|
Packit Service |
a04d08 |
def __init__(self, sem_path):
|
|
Packit Service |
a04d08 |
self.sem_path = sem_path
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
@contextlib.contextmanager
|
|
Packit Service |
a04d08 |
def lock(self, name, freq, clear_on_fail=False):
|
|
Packit Service |
a04d08 |
name = canon_sem_name(name)
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
yield self._acquire(name, freq)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
if clear_on_fail:
|
|
Packit Service |
a04d08 |
self.clear(name, freq)
|
|
Packit Service |
a04d08 |
raise
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def clear(self, name, freq):
|
|
Packit Service |
a04d08 |
name = canon_sem_name(name)
|
|
Packit Service |
a04d08 |
sem_file = self._get_path(name, freq)
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
util.del_file(sem_file)
|
|
Packit Service |
a04d08 |
except (IOError, OSError):
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed deleting semaphore %s", sem_file)
|
|
Packit Service |
a04d08 |
return False
|
|
Packit Service |
a04d08 |
return True
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def clear_all(self):
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
util.del_dir(self.sem_path)
|
|
Packit Service |
a04d08 |
except (IOError, OSError):
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed deleting semaphore directory %s",
|
|
Packit Service |
a04d08 |
self.sem_path)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _acquire(self, name, freq):
|
|
Packit Service |
a04d08 |
# Check again if its been already gotten
|
|
Packit Service |
a04d08 |
if self.has_run(name, freq):
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
# This is a race condition since nothing atomic is happening
|
|
Packit Service |
a04d08 |
# here, but this should be ok due to the nature of when
|
|
Packit Service |
a04d08 |
# and where cloud-init runs... (file writing is not a lock...)
|
|
Packit Service |
a04d08 |
sem_file = self._get_path(name, freq)
|
|
Packit Service |
a04d08 |
contents = "%s: %s\n" % (os.getpid(), time())
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
util.write_file(sem_file, contents)
|
|
Packit Service |
a04d08 |
except (IOError, OSError):
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed writing semaphore file %s", sem_file)
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
return FileLock(sem_file)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def has_run(self, name, freq):
|
|
Packit Service |
a04d08 |
if not freq or freq == PER_ALWAYS:
|
|
Packit Service |
a04d08 |
return False
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
cname = canon_sem_name(name)
|
|
Packit Service |
a04d08 |
sem_file = self._get_path(cname, freq)
|
|
Packit Service |
a04d08 |
# This isn't really a good atomic check
|
|
Packit Service |
a04d08 |
# but it suffices for where and when cloudinit runs
|
|
Packit Service |
a04d08 |
if os.path.exists(sem_file):
|
|
Packit Service |
a04d08 |
return True
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# this case could happen if the migrator module hadn't run yet
|
|
Packit Service |
a04d08 |
# but the item had run before we did canon_sem_name.
|
|
Packit Service |
a04d08 |
if cname != name and os.path.exists(self._get_path(name, freq)):
|
|
Packit Service |
a04d08 |
LOG.warning("%s has run without canonicalized name [%s].\n"
|
|
Packit Service |
a04d08 |
"likely the migrator has not yet run. "
|
|
Packit Service |
a04d08 |
"It will run next boot.\n"
|
|
Packit Service |
a04d08 |
"run manually with: cloud-init single --name=migrator",
|
|
Packit Service |
a04d08 |
name, cname)
|
|
Packit Service |
a04d08 |
return True
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
return False
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _get_path(self, name, freq):
|
|
Packit Service |
a04d08 |
sem_path = self.sem_path
|
|
Packit Service |
a04d08 |
if not freq or freq == PER_INSTANCE:
|
|
Packit Service |
a04d08 |
return os.path.join(sem_path, name)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
return os.path.join(sem_path, "%s.%s" % (name, freq))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class Runners(object):
|
|
Packit Service |
a04d08 |
def __init__(self, paths):
|
|
Packit Service |
a04d08 |
self.paths = paths
|
|
Packit Service |
a04d08 |
self.sems = {}
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _get_sem(self, freq):
|
|
Packit Service |
a04d08 |
if freq == PER_ALWAYS or not freq:
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
sem_path = None
|
|
Packit Service |
a04d08 |
if freq == PER_INSTANCE:
|
|
Packit Service |
a04d08 |
# This may not exist,
|
|
Packit Service |
a04d08 |
# so thats why we still check for none
|
|
Packit Service |
a04d08 |
# below if say the paths object
|
|
Packit Service |
a04d08 |
# doesn't have a datasource that can
|
|
Packit Service |
a04d08 |
# provide this instance path...
|
|
Packit Service |
a04d08 |
sem_path = self.paths.get_ipath("sem")
|
|
Packit Service |
a04d08 |
elif freq == PER_ONCE:
|
|
Packit Service |
a04d08 |
sem_path = self.paths.get_cpath("sem")
|
|
Packit Service |
a04d08 |
if not sem_path:
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
if sem_path not in self.sems:
|
|
Packit Service |
a04d08 |
self.sems[sem_path] = FileSemaphores(sem_path)
|
|
Packit Service |
a04d08 |
return self.sems[sem_path]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def run(self, name, functor, args, freq=None, clear_on_fail=False):
|
|
Packit Service |
a04d08 |
sem = self._get_sem(freq)
|
|
Packit Service |
a04d08 |
if not sem:
|
|
Packit Service |
a04d08 |
sem = DummySemaphores()
|
|
Packit Service |
a04d08 |
if not args:
|
|
Packit Service |
a04d08 |
args = []
|
|
Packit Service |
a04d08 |
if sem.has_run(name, freq):
|
|
Packit Service |
a04d08 |
LOG.debug("%s already ran (freq=%s)", name, freq)
|
|
Packit Service |
a04d08 |
return (False, None)
|
|
Packit Service |
a04d08 |
with sem.lock(name, freq, clear_on_fail) as lk:
|
|
Packit Service |
a04d08 |
if not lk:
|
|
Packit Service |
a04d08 |
raise LockFailure("Failed to acquire lock for %s" % name)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
LOG.debug("Running %s using lock (%s)", name, lk)
|
|
Packit Service |
a04d08 |
if isinstance(args, (dict)):
|
|
Packit Service |
a04d08 |
results = functor(**args)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
results = functor(*args)
|
|
Packit Service |
a04d08 |
return (True, results)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class ConfigMerger(object):
|
|
Packit Service |
a04d08 |
def __init__(self, paths=None, datasource=None,
|
|
Packit Service |
a04d08 |
additional_fns=None, base_cfg=None,
|
|
Packit Service |
a04d08 |
include_vendor=True):
|
|
Packit Service |
a04d08 |
self._paths = paths
|
|
Packit Service |
a04d08 |
self._ds = datasource
|
|
Packit Service |
a04d08 |
self._fns = additional_fns
|
|
Packit Service |
a04d08 |
self._base_cfg = base_cfg
|
|
Packit Service |
a04d08 |
self._include_vendor = include_vendor
|
|
Packit Service |
a04d08 |
# Created on first use
|
|
Packit Service |
a04d08 |
self._cfg = None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _get_datasource_configs(self):
|
|
Packit Service |
a04d08 |
d_cfgs = []
|
|
Packit Service |
a04d08 |
if self._ds:
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
ds_cfg = self._ds.get_config_obj()
|
|
Packit Service |
a04d08 |
if ds_cfg and isinstance(ds_cfg, (dict)):
|
|
Packit Service |
a04d08 |
d_cfgs.append(ds_cfg)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed loading of datasource config object "
|
|
Packit Service |
a04d08 |
"from %s", self._ds)
|
|
Packit Service |
a04d08 |
return d_cfgs
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _get_env_configs(self):
|
|
Packit Service |
a04d08 |
e_cfgs = []
|
|
Packit Service |
a04d08 |
if CFG_ENV_NAME in os.environ:
|
|
Packit Service |
a04d08 |
e_fn = os.environ[CFG_ENV_NAME]
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
e_cfgs.append(util.read_conf(e_fn))
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, 'Failed loading of env. config from %s',
|
|
Packit Service |
a04d08 |
e_fn)
|
|
Packit Service |
a04d08 |
return e_cfgs
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _get_instance_configs(self):
|
|
Packit Service |
a04d08 |
i_cfgs = []
|
|
Packit Service |
a04d08 |
# If cloud-config was written, pick it up as
|
|
Packit Service |
a04d08 |
# a configuration file to use when running...
|
|
Packit Service |
a04d08 |
if not self._paths:
|
|
Packit Service |
a04d08 |
return i_cfgs
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
cc_paths = ['cloud_config']
|
|
Packit Service |
a04d08 |
if self._include_vendor:
|
|
Packit Service |
a04d08 |
cc_paths.append('vendor_cloud_config')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
for cc_p in cc_paths:
|
|
Packit Service |
a04d08 |
cc_fn = self._paths.get_ipath_cur(cc_p)
|
|
Packit Service |
a04d08 |
if cc_fn and os.path.isfile(cc_fn):
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
i_cfgs.append(util.read_conf(cc_fn))
|
|
Packit Service |
a04d08 |
except PermissionError:
|
|
Packit Service |
a04d08 |
LOG.debug(
|
|
Packit Service |
a04d08 |
'Skipped loading cloud-config from %s due to'
|
|
Packit Service |
a04d08 |
' non-root.', cc_fn)
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, 'Failed loading of cloud-config from %s',
|
|
Packit Service |
a04d08 |
cc_fn)
|
|
Packit Service |
a04d08 |
return i_cfgs
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _read_cfg(self):
|
|
Packit Service |
a04d08 |
# Input config files override
|
|
Packit Service |
a04d08 |
# env config files which
|
|
Packit Service |
a04d08 |
# override instance configs
|
|
Packit Service |
a04d08 |
# which override datasource
|
|
Packit Service |
a04d08 |
# configs which override
|
|
Packit Service |
a04d08 |
# base configuration
|
|
Packit Service |
a04d08 |
cfgs = []
|
|
Packit Service |
a04d08 |
if self._fns:
|
|
Packit Service |
a04d08 |
for c_fn in self._fns:
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
cfgs.append(util.read_conf(c_fn))
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
util.logexc(LOG, "Failed loading of configuration from %s",
|
|
Packit Service |
a04d08 |
c_fn)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
cfgs.extend(self._get_env_configs())
|
|
Packit Service |
a04d08 |
cfgs.extend(self._get_instance_configs())
|
|
Packit Service |
a04d08 |
cfgs.extend(self._get_datasource_configs())
|
|
Packit Service |
a04d08 |
if self._base_cfg:
|
|
Packit Service |
a04d08 |
cfgs.append(self._base_cfg)
|
|
Packit Service |
a04d08 |
return util.mergemanydict(cfgs)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
@property
|
|
Packit Service |
a04d08 |
def cfg(self):
|
|
Packit Service |
a04d08 |
# None check to avoid empty case causing re-reading
|
|
Packit Service |
a04d08 |
if self._cfg is None:
|
|
Packit Service |
a04d08 |
self._cfg = self._read_cfg()
|
|
Packit Service |
a04d08 |
return self._cfg
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class ContentHandlers(object):
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def __init__(self):
|
|
Packit Service |
a04d08 |
self.registered = {}
|
|
Packit Service |
a04d08 |
self.initialized = []
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def __contains__(self, item):
|
|
Packit Service |
a04d08 |
return self.is_registered(item)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def __getitem__(self, key):
|
|
Packit Service |
a04d08 |
return self._get_handler(key)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def is_registered(self, content_type):
|
|
Packit Service |
a04d08 |
return content_type in self.registered
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def register(self, mod, initialized=False, overwrite=True):
|
|
Packit Service |
a04d08 |
types = set()
|
|
Packit Service |
a04d08 |
for t in mod.list_types():
|
|
Packit Service |
a04d08 |
if overwrite:
|
|
Packit Service |
a04d08 |
types.add(t)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
if not self.is_registered(t):
|
|
Packit Service |
a04d08 |
types.add(t)
|
|
Packit Service |
a04d08 |
for t in types:
|
|
Packit Service |
a04d08 |
self.registered[t] = mod
|
|
Packit Service |
a04d08 |
if initialized and mod not in self.initialized:
|
|
Packit Service |
a04d08 |
self.initialized.append(mod)
|
|
Packit Service |
a04d08 |
return types
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _get_handler(self, content_type):
|
|
Packit Service |
a04d08 |
return self.registered[content_type]
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def items(self):
|
|
Packit Service |
a04d08 |
return list(self.registered.items())
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class Paths(object):
|
|
Packit Service |
a04d08 |
def __init__(self, path_cfgs, ds=None):
|
|
Packit Service |
a04d08 |
self.cfgs = path_cfgs
|
|
Packit Service |
a04d08 |
# Populate all the initial paths
|
|
Packit Service |
a04d08 |
self.cloud_dir = path_cfgs.get('cloud_dir', '/var/lib/cloud')
|
|
Packit Service |
a04d08 |
self.run_dir = path_cfgs.get('run_dir', '/run/cloud-init')
|
|
Packit Service |
a04d08 |
self.instance_link = os.path.join(self.cloud_dir, 'instance')
|
|
Packit Service |
a04d08 |
self.boot_finished = os.path.join(self.instance_link, "boot-finished")
|
|
Packit Service |
a04d08 |
self.upstart_conf_d = path_cfgs.get('upstart_dir')
|
|
Packit Service |
a04d08 |
self.seed_dir = os.path.join(self.cloud_dir, 'seed')
|
|
Packit Service |
a04d08 |
# This one isn't joined, since it should just be read-only
|
|
Packit Service |
a04d08 |
template_dir = path_cfgs.get('templates_dir', '/etc/cloud/templates/')
|
|
Packit Service |
a04d08 |
self.template_tpl = os.path.join(template_dir, '%s.tmpl')
|
|
Packit Service |
a04d08 |
self.lookups = {
|
|
Packit Service |
a04d08 |
"handlers": "handlers",
|
|
Packit Service |
a04d08 |
"scripts": "scripts",
|
|
Packit Service |
a04d08 |
"vendor_scripts": "scripts/vendor",
|
|
Packit Service |
a04d08 |
"sem": "sem",
|
|
Packit Service |
a04d08 |
"boothooks": "boothooks",
|
|
Packit Service |
a04d08 |
"userdata_raw": "user-data.txt",
|
|
Packit Service |
a04d08 |
"userdata": "user-data.txt.i",
|
|
Packit Service |
a04d08 |
"obj_pkl": "obj.pkl",
|
|
Packit Service |
a04d08 |
"cloud_config": "cloud-config.txt",
|
|
Packit Service |
a04d08 |
"vendor_cloud_config": "vendor-cloud-config.txt",
|
|
Packit Service |
a04d08 |
"data": "data",
|
|
Packit Service |
a04d08 |
"vendordata_raw": "vendor-data.txt",
|
|
Packit Service |
a04d08 |
"vendordata": "vendor-data.txt.i",
|
|
Packit Service |
a04d08 |
"instance_id": ".instance-id",
|
|
Packit Service |
a04d08 |
"manual_clean_marker": "manual-clean",
|
|
Packit Service |
a04d08 |
"warnings": "warnings",
|
|
Packit Service |
a04d08 |
}
|
|
Packit Service |
a04d08 |
# Set when a datasource becomes active
|
|
Packit Service |
a04d08 |
self.datasource = ds
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# get_ipath_cur: get the current instance path for an item
|
|
Packit Service |
a04d08 |
def get_ipath_cur(self, name=None):
|
|
Packit Service |
a04d08 |
return self._get_path(self.instance_link, name)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# get_cpath : get the "clouddir" (/var/lib/cloud/<name>)
|
|
Packit Service |
a04d08 |
# for a name in dirmap
|
|
Packit Service |
a04d08 |
def get_cpath(self, name=None):
|
|
Packit Service |
a04d08 |
return self._get_path(self.cloud_dir, name)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# _get_ipath : get the instance path for a name in pathmap
|
|
Packit Service |
a04d08 |
# (/var/lib/cloud/instances/<instance>/<name>)
|
|
Packit Service |
a04d08 |
def _get_ipath(self, name=None):
|
|
Packit Service |
a04d08 |
if not self.datasource:
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
iid = self.datasource.get_instance_id()
|
|
Packit Service |
a04d08 |
if iid is None:
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
path_safe_iid = str(iid).replace(os.sep, '_')
|
|
Packit Service |
a04d08 |
ipath = os.path.join(self.cloud_dir, 'instances', path_safe_iid)
|
|
Packit Service |
a04d08 |
add_on = self.lookups.get(name)
|
|
Packit Service |
a04d08 |
if add_on:
|
|
Packit Service |
a04d08 |
ipath = os.path.join(ipath, add_on)
|
|
Packit Service |
a04d08 |
return ipath
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# get_ipath : get the instance path for a name in pathmap
|
|
Packit Service |
a04d08 |
# (/var/lib/cloud/instances/<instance>/<name>)
|
|
Packit Service |
a04d08 |
# returns None + warns if no active datasource....
|
|
Packit Service |
a04d08 |
def get_ipath(self, name=None):
|
|
Packit Service |
a04d08 |
ipath = self._get_ipath(name)
|
|
Packit Service |
a04d08 |
if not ipath:
|
|
Packit Service |
a04d08 |
LOG.warning(("No per instance data available, "
|
|
Packit Service |
a04d08 |
"is there an datasource/iid set?"))
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
return ipath
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _get_path(self, base, name=None):
|
|
Packit Service |
a04d08 |
if name is None:
|
|
Packit Service |
a04d08 |
return base
|
|
Packit Service |
a04d08 |
return os.path.join(base, self.lookups[name])
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def get_runpath(self, name=None):
|
|
Packit Service |
a04d08 |
return self._get_path(self.run_dir, name)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# This config parser will not throw when sections don't exist
|
|
Packit Service |
a04d08 |
# and you are setting values on those sections which is useful
|
|
Packit Service |
a04d08 |
# when writing to new options that may not have corresponding
|
|
Packit Service |
a04d08 |
# sections. Also it can default other values when doing gets
|
|
Packit Service |
a04d08 |
# so that if those sections/options do not exist you will
|
|
Packit Service |
a04d08 |
# get a default instead of an error. Another useful case where
|
|
Packit Service |
a04d08 |
# you can avoid catching exceptions that you typically don't
|
|
Packit Service |
a04d08 |
# care about...
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class DefaultingConfigParser(RawConfigParser):
|
|
Packit Service |
a04d08 |
DEF_INT = 0
|
|
Packit Service |
a04d08 |
DEF_FLOAT = 0.0
|
|
Packit Service |
a04d08 |
DEF_BOOLEAN = False
|
|
Packit Service |
a04d08 |
DEF_BASE = None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def get(self, section, option):
|
|
Packit Service |
a04d08 |
value = self.DEF_BASE
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
value = RawConfigParser.get(self, section, option)
|
|
Packit Service |
a04d08 |
except NoSectionError:
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
except NoOptionError:
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
return value
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def set(self, section, option, value=None):
|
|
Packit Service |
a04d08 |
if not self.has_section(section) and section.lower() != 'default':
|
|
Packit Service |
a04d08 |
self.add_section(section)
|
|
Packit Service |
a04d08 |
RawConfigParser.set(self, section, option, value)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def remove_option(self, section, option):
|
|
Packit Service |
a04d08 |
if self.has_option(section, option):
|
|
Packit Service |
a04d08 |
RawConfigParser.remove_option(self, section, option)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def getboolean(self, section, option):
|
|
Packit Service |
a04d08 |
if not self.has_option(section, option):
|
|
Packit Service |
a04d08 |
return self.DEF_BOOLEAN
|
|
Packit Service |
a04d08 |
return RawConfigParser.getboolean(self, section, option)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def getfloat(self, section, option):
|
|
Packit Service |
a04d08 |
if not self.has_option(section, option):
|
|
Packit Service |
a04d08 |
return self.DEF_FLOAT
|
|
Packit Service |
a04d08 |
return RawConfigParser.getfloat(self, section, option)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def getint(self, section, option):
|
|
Packit Service |
a04d08 |
if not self.has_option(section, option):
|
|
Packit Service |
a04d08 |
return self.DEF_INT
|
|
Packit Service |
a04d08 |
return RawConfigParser.getint(self, section, option)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def stringify(self, header=None):
|
|
Packit Service |
a04d08 |
contents = ''
|
|
Packit Service |
a04d08 |
outputstream = StringIO()
|
|
Packit Service |
a04d08 |
self.write(outputstream)
|
|
Packit Service |
a04d08 |
outputstream.flush()
|
|
Packit Service |
a04d08 |
contents = outputstream.getvalue()
|
|
Packit Service |
a04d08 |
if header:
|
|
Packit Service |
a04d08 |
contents = '\n'.join([header, contents, ''])
|
|
Packit Service |
a04d08 |
return contents
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# vi: ts=4 expandtab
|