summaryrefslogtreecommitdiff
path: root/cloudinit/config/cc_seed_random.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/config/cc_seed_random.py')
-rw-r--r--cloudinit/config/cc_seed_random.py94
1 files changed, 82 insertions, 12 deletions
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)