diff options
author | Joshua Harlow <harlowja@gmail.com> | 2013-09-06 23:46:27 -0700 |
---|---|---|
committer | Joshua Harlow <harlowja@gmail.com> | 2013-09-06 23:46:27 -0700 |
commit | e058913486519c2a9e036aad95f6e029dbc89966 (patch) | |
tree | de61cb4024d9d9359f91090684684c15a077e84b | |
parent | c3e070de802ebc0f44722d4238f5447b93cc9fac (diff) | |
download | vyos-cloud-init-e058913486519c2a9e036aad95f6e029dbc89966.tar.gz vyos-cloud-init-e058913486519c2a9e036aad95f6e029dbc89966.zip |
Add jsonschema for namespaced and verifiable module
configuration checking as well as make most of the
module logic happen in the module itself instead of
interacting with the distro object.
-rw-r--r-- | Requires | 4 | ||||
-rw-r--r-- | cloudinit/config/cc_seed_random.py | 94 | ||||
-rw-r--r-- | cloudinit/distros/__init__.py | 10 | ||||
-rw-r--r-- | cloudinit/exceptions.py | 21 |
4 files changed, 107 insertions, 22 deletions
@@ -34,3 +34,7 @@ boto # For patching pieces of cloud-config together jsonpatch + +# For validating that a config modules needed configuration specified +# in a correct format that the module can understand +jsonschema diff --git a/cloudinit/config/cc_seed_random.py b/cloudinit/config/cc_seed_random.py index 5d9890d5..acacb8f7 100644 --- a/cloudinit/config/cc_seed_random.py +++ b/cloudinit/config/cc_seed_random.py @@ -16,21 +16,91 @@ # 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 + +import jsonschema +from jsonschema import exceptions as js_exc + +from cloudinit import exceptions as exc from cloudinit.settings import PER_INSTANCE +from cloudinit import util frequency = PER_INSTANCE +schema = { + 'type': 'object', + 'properties': { + "random_seed": { + "type": "object", + "oneOf": [ + {"$ref": "#/definitions/random_seed"}, + ], + }, + }, + "required": ["random_seed"], + "additionalProperties": True, + "definitions": { + 'random_seed': { + 'type': 'object', + "properties" : { + 'data': { + 'type': "string", + }, + 'file': { + 'type': 'string', + }, + 'encoding': { + "enum": ["base64", 'gzip', 'b64', 'gz', ''], + }, + }, + "additionalProperties": True, + }, + }, +} + + +def validate(cfg): + """Method that can be used to ask if the given configuration will be + accepted as valid by this module, without having to actually activate this + module.""" + try: + jsonschema.validate(cfg, schema) + except js_exc.ValidationError as e: + raise exc.FormatValidationError("Invalid configuration: %s" % str(e)) + + +def _decode(data, encoding=None): + if not encoding: + return data + if not data: + return '' + if 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): - random_seed = None - # Prefer metadata over cfg for random_seed - for src in (cloud.datasource.metadata, cfg): - if not src: - continue - tmp_random_seed = src.get('random_seed') - if tmp_random_seed and isinstance(tmp_random_seed, (str, basestring)): - random_seed = tmp_random_seed - break - if random_seed: - log.debug("%s: setting random seed", name) - cloud.distro.set_random_seed(random_seed) + if not cfg or "random_seed" not in cfg: + log.debug(("Skipping module named %s, " + "no 'random_seed' configuration found"), name) + return + + validate(cfg) + 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/distros/__init__.py b/cloudinit/distros/__init__.py index 5642b529..74e95797 100644 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py @@ -52,7 +52,6 @@ class Distro(object): ci_sudoers_fn = "/etc/sudoers.d/90-cloud-init-users" hostname_conf_fn = "/etc/hostname" tz_zone_dir = "/usr/share/zoneinfo" - random_seed_fn = '/dev/urandom' def __init__(self, name, cfg, paths): self._paths = paths @@ -170,15 +169,6 @@ class Distro(object): distros.extend(OSFAMILIES[family]) return distros - def set_random_seed(self, seed): - if not self.random_seed_fn or not os.path.exists(self.random_seed_fn): - raise IOError("No random seed filename provided for %s" - % (self.name)) - if not seed: - raise IOError("Unable to set empty random seed") - # Ensure we only write 512 bytes worth - util.append_file(self.random_seed_fn, seed[0:512]) - def update_hostname(self, hostname, fqdn, prev_hostname_fn): applying_hostname = hostname diff --git a/cloudinit/exceptions.py b/cloudinit/exceptions.py new file mode 100644 index 00000000..c09d15b1 --- /dev/null +++ b/cloudinit/exceptions.py @@ -0,0 +1,21 @@ +# 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/>. + + +class FormatValidationError(Exception): + pass |