diff options
Diffstat (limited to 'cloudinit')
| -rw-r--r-- | cloudinit/config/cc_seed_random.py | 61 | ||||
| -rw-r--r-- | cloudinit/sources/DataSourceAzure.py | 5 | ||||
| -rw-r--r-- | cloudinit/sources/DataSourceConfigDrive.py | 44 | 
3 files changed, 96 insertions, 14 deletions
| diff --git a/cloudinit/config/cc_seed_random.py b/cloudinit/config/cc_seed_random.py new file mode 100644 index 00000000..22a31f29 --- /dev/null +++ b/cloudinit/config/cc_seed_random.py @@ -0,0 +1,61 @@ +# vi: ts=4 expandtab +# +#    Copyright (C) 2013 Yahoo! Inc. +# +#    Author: Joshua Harlow <harlowja@yahoo-inc.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 base64 +from StringIO import StringIO + +from cloudinit.settings import PER_INSTANCE +from cloudinit import util + +frequency = PER_INSTANCE + + +def _decode(data, encoding=None): +    if not data: +        return '' +    if not encoding or encoding.lower() in ['raw']: +        return data +    elif encoding.lower() in ['base64', 'b64']: +        return base64.b64decode(data) +    elif encoding.lower() in ['gzip', 'gz']: +        return util.decomp_gzip(data, quiet=False) +    else: +        raise IOError("Unknown random_seed encoding: %s" % (encoding)) + + +def handle(name, cfg, cloud, log, _args): +    if not cfg or "random_seed" not in cfg: +        log.debug(("Skipping module named %s, " +                   "no 'random_seed' configuration found"), name) +        return + +    my_cfg = cfg['random_seed'] +    seed_path = my_cfg.get('file', '/dev/urandom') +    seed_buf = StringIO() +    seed_buf.write(_decode(my_cfg.get('data', ''), +                           encoding=my_cfg.get('encoding'))) + +    metadata = cloud.datasource.metadata +    if metadata and 'random_seed' in metadata: +        seed_buf.write(metadata['random_seed']) + +    seed_data = seed_buf.getvalue() +    if len(seed_data): +        log.debug("%s: adding %s bytes of random seed entrophy to %s", name, +                  len(seed_data), seed_path) +        util.append_file(seed_path, seed_data) diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 66d7728b..a77c3d9a 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -106,6 +106,11 @@ class DataSourceAzureNet(sources.DataSource):          if found == ddir:              LOG.debug("using files cached in %s", ddir) +        # azure / hyper-v provides random data here +        seed = util.load_file("/sys/firmware/acpi/tables/OEM0", quiet=True) +        if seed: +            self.metadata['random_seed'] = seed +          # now update ds_cfg to reflect contents pass in config          usercfg = util.get_cfg_by_path(self.cfg, DS_CFG_PATH, {})          self.ds_cfg = util.mergemanydict([usercfg, self.ds_cfg]) diff --git a/cloudinit/sources/DataSourceConfigDrive.py b/cloudinit/sources/DataSourceConfigDrive.py index 835f2a9a..4f437244 100644 --- a/cloudinit/sources/DataSourceConfigDrive.py +++ b/cloudinit/sources/DataSourceConfigDrive.py @@ -18,6 +18,7 @@  #    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 base64  import json  import os @@ -41,6 +42,25 @@ DEFAULT_METADATA = {  VALID_DSMODES = ("local", "net", "pass", "disabled") +class ConfigDriveHelper(object): +    def __init__(self, distro): +        self.distro = distro + +    def on_first_boot(self, data): +        if not data: +            data = {} +        if 'network_config' in data: +            LOG.debug("Updating network interfaces from config drive") +            self.distro.apply_network(data['network_config']) +        files = data.get('files') +        if files: +            LOG.debug("Writing %s injected files", len(files)) +            try: +                write_files(files) +            except IOError: +                util.logexc(LOG, "Failed writing files") + +  class DataSourceConfigDrive(sources.DataSource):      def __init__(self, sys_cfg, distro, paths):          sources.DataSource.__init__(self, sys_cfg, distro, paths) @@ -49,6 +69,7 @@ class DataSourceConfigDrive(sources.DataSource):          self.seed_dir = os.path.join(paths.seed_dir, 'config_drive')          self.version = None          self.ec2_metadata = None +        self.helper = ConfigDriveHelper(distro)      def __str__(self):          root = sources.DataSource.__str__(self) @@ -187,20 +208,8 @@ class DataSourceConfigDrive(sources.DataSource):          # instance-id          prev_iid = get_previous_iid(self.paths)          cur_iid = md['instance-id'] - -        if ('network_config' in results and self.dsmode == "local" and -            prev_iid != cur_iid): -            LOG.debug("Updating network interfaces from config drive (%s)", -                      dsmode) -            self.distro.apply_network(results['network_config']) - -        # file writing occurs in local mode (to be as early as possible) -        if self.dsmode == "local" and prev_iid != cur_iid and results['files']: -            LOG.debug("writing injected files") -            try: -                write_files(results['files']) -            except: -                util.logexc(LOG, "Failed writing files") +        if prev_iid != cur_iid and self.dsmode == "local": +            self.helper.on_first_boot(results)          # dsmode != self.dsmode here if:          #  * dsmode = "pass",  pass means it should only copy files and then @@ -338,6 +347,13 @@ def read_config_drive_dir_v2(source_dir, version="2012-08-10"):          except KeyError:              raise BrokenConfigDriveDir("No uuid entry in metadata") +    if 'random_seed' in results['metadata']: +        random_seed = results['metadata']['random_seed'] +        try: +            results['metadata']['random_seed'] = base64.b64decode(random_seed) +        except (ValueError, TypeError) as exc: +            raise BrokenConfigDriveDir("Badly formatted random_seed: %s" % exc) +      def read_content_path(item):          # do not use os.path.join here, as content_path starts with /          cpath = os.path.sep.join((source_dir, "openstack", | 
