Skip to content

Commit 249161c

Browse files
author
Yaniv Kaul
committed
Ensure consistent load order of domains and networks.
By processing JSON or YAML files via Ordered dicts., we ensure that domains are processed in the order they are specified in the relevant configuration files.
1 parent c577b8d commit 249161c

File tree

3 files changed

+33
-10
lines changed

3 files changed

+33
-10
lines changed

lago/utils.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,10 @@ def deepcopy(original_obj):
420420
"""
421421
if isinstance(original_obj, list):
422422
return list(deepcopy(item) for item in original_obj)
423+
elif isinstance(original_obj, collections.OrderedDict):
424+
return collections.OrderedDict(
425+
(key, deepcopy(val)) for key, val in original_obj.items()
426+
)
423427
elif isinstance(original_obj, dict):
424428
return dict((key, deepcopy(val)) for key, val in original_obj.items())
425429
else:
@@ -438,9 +442,21 @@ def load_virt_stream(virt_fd):
438442
dict: Loaded virt config
439443
"""
440444
try:
441-
virt_conf = json.load(virt_fd)
445+
virt_conf = json.load(
446+
virt_fd, object_pairs_hook=collections.OrderedDict
447+
)
442448
except ValueError:
443449
virt_fd.seek(0)
450+
451+
# Ensure ordered dict loading from YAML. Based on
452+
# http://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts
453+
_mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
454+
455+
def dict_constructor(loader, node):
456+
return collections.OrderedDict(loader.construct_pairs(node))
457+
458+
yaml.add_constructor(_mapping_tag, dict_constructor)
459+
444460
virt_conf = yaml.load(virt_fd)
445461

446462
return deepcopy(virt_conf)

lago/virt.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#
1818
# Refer to the README and COPYING files for full details of the license
1919
#
20+
import collections
2021
import functools
2122
import hashlib
2223
import json
@@ -86,11 +87,11 @@ def __init__(self, prefix, vm_specs, net_specs):
8687
with open(self.prefix.paths.uuid(), 'r') as uuid_fd:
8788
self.uuid = uuid_fd.read().strip()
8889

89-
self._nets = {}
90+
self._nets = collections.OrderedDict()
9091
for name, spec in net_specs.items():
9192
self._nets[name] = self._create_net(spec)
9293

93-
self._vms = {}
94+
self._vms = collections.OrderedDict()
9495
for name, spec in vm_specs.items():
9596
self._vms[name] = self._create_vm(spec)
9697

@@ -244,17 +245,21 @@ def from_prefix(cls, prefix):
244245
virt_path = functools.partial(prefix.paths.prefixed, 'virt')
245246

246247
with open(virt_path('env'), 'r') as f:
247-
env_dom = json.load(f)
248+
env_dom = json.load(f, object_pairs_hook=collections.OrderedDict)
248249

249-
net_specs = {}
250+
net_specs = collections.OrderedDict()
250251
for name in env_dom['nets']:
251252
with open(virt_path('net-%s' % name), 'r') as f:
252-
net_specs[name] = json.load(f)
253+
net_specs[name] = json.load(
254+
f, object_pairs_hook=collections.OrderedDict
255+
)
253256

254-
vm_specs = {}
257+
vm_specs = collections.OrderedDict()
255258
for name in env_dom['vms']:
256259
with open(virt_path('vm-%s' % name), 'r') as f:
257-
vm_specs[name] = json.load(f)
260+
vm_specs[name] = json.load(
261+
f, object_pairs_hook=collections.OrderedDict
262+
)
258263

259264
return cls(prefix, vm_specs, net_specs)
260265

tests/functional/fixtures/status/prefix_skel/expected.yaml

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ Prefix:
1313
eth1: {ip: !!python/unicode '192.168.202.2', network: !!python/unicode 'n1'}
1414
VNC port: null
1515
distro: !!python/unicode 'cirros'
16-
metadata: {}
16+
metadata: !!python/object/apply:collections.OrderedDict
17+
- []
1718
root password: !!python/unicode '123456'
1819
snapshots: ''
1920
status: down
@@ -23,7 +24,8 @@ Prefix:
2324
eth1: {ip: !!python/unicode '192.168.202.3', network: !!python/unicode 'n1'}
2425
VNC port: null
2526
distro: !!python/unicode 'cirros'
26-
metadata: {}
27+
metadata: !!python/object/apply:collections.OrderedDict
28+
- []
2729
root password: !!python/unicode 'cubswin:)'
2830
snapshots: ''
2931
status: down

0 commit comments

Comments
 (0)