/usr/lib/python3/dist-packages/provisioningserver/import_images/boot_image_mapping.py is in python3-maas-provisioningserver 2.0.0~beta3+bzr4941-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | # Copyright 2014-2016 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""The `BootImageMapping` class."""
__all__ = [
'BootImageMapping',
]
import json
from provisioningserver.import_images.helpers import ImageSpec
from provisioningserver.utils import dict_depth
def gen_image_spec_with_resource(os, data):
"""Generate image and resource for given operating system and data."""
for arch in data:
for subarch in data[arch]:
for release in data[arch][subarch]:
for label in data[arch][subarch][release]:
image = ImageSpec(
os=os, arch=arch, subarch=subarch,
release=release, label=label)
resource = data[arch][subarch][release][label]
yield image, resource
class BootImageMapping:
"""Mapping of boot-image data.
Maps `ImageSpec` tuples to metadata for Simplestreams products.
This class is deliberately a bit more restrictive and less ad-hoc than a
dict. It helps keep a clear view of the data structures in this module.
"""
def __init__(self):
self.mapping = {}
def items(self):
"""Iterate over `ImageSpec` keys, and their stored values."""
for image_spec, item in sorted(self.mapping.items()):
yield image_spec, item
def is_empty(self):
"""Is this mapping empty?"""
return len(self.mapping) == 0
def setdefault(self, image_spec, item):
"""Set metadata for `image_spec` to item, if not already set."""
assert isinstance(image_spec, ImageSpec)
self.mapping.setdefault(image_spec, item)
def set(self, image_spec, item):
""""Set metadata for `image_spec` to item, even if already set."""
assert isinstance(image_spec, ImageSpec)
self.mapping[image_spec] = item
def dump_json(self):
"""Produce JSON representing the mapped boot images.
Tries to keep the output deterministic, so that identical data is
likely to produce identical JSON.
:return: A Unicode string (`str`) containing JSON using only ASCII
characters.
"""
# The meta files represent the mapping as a nested hierarchy of dicts.
# Keep that format.
data = {}
for image, resource in self.items():
os, arch, subarch, release, label = image
data.setdefault(os, {})
data[os].setdefault(arch, {})
data[os][arch].setdefault(subarch, {})
data[os][arch][subarch].setdefault(release, {})
data[os][arch][subarch][release][label] = resource
return json.dumps(data, sort_keys=True)
@staticmethod
def load_json(json_data):
"""Take a JSON representation and deserialize into an object.
:param json_data: string produced by dump_json(), above.
:return: A BootImageMapping
If the json data is invalid, an empty BootImageMapping is returned.
"""
mapping = BootImageMapping()
try:
data = json.loads(json_data)
except ValueError:
return mapping
depth = dict_depth(data)
if depth == 5:
# Support for older data. This has no operating system, then
# it is ubuntu.
for image, resource in gen_image_spec_with_resource(
"ubuntu", data):
mapping.setdefault(image, resource)
elif depth == 6:
for os in data:
for image, resource in gen_image_spec_with_resource(
os, data[os]):
mapping.setdefault(image, resource)
return mapping
def get_image_arches(self):
"""Set of arches this BootImageMapping has an ImageSpec for."""
return {item[0].arch for item in self.items()}
|