summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@gmail.com>2013-09-06 23:46:27 -0700
committerJoshua Harlow <harlowja@gmail.com>2013-09-06 23:46:27 -0700
commite058913486519c2a9e036aad95f6e029dbc89966 (patch)
treede61cb4024d9d9359f91090684684c15a077e84b
parentc3e070de802ebc0f44722d4238f5447b93cc9fac (diff)
downloadvyos-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--Requires4
-rw-r--r--cloudinit/config/cc_seed_random.py94
-rw-r--r--cloudinit/distros/__init__.py10
-rw-r--r--cloudinit/exceptions.py21
4 files changed, 107 insertions, 22 deletions
diff --git a/Requires b/Requires
index f19c9691..b00dd58e 100644
--- a/Requires
+++ b/Requires
@@ -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