diff --git a/diskimage_builder/block_device/blockdevice.py b/diskimage_builder/block_device/blockdevice.py index 661cd47ec..f869cb25a 100644 --- a/diskimage_builder/block_device/blockdevice.py +++ b/diskimage_builder/block_device/blockdevice.py @@ -17,6 +17,7 @@ import collections import json import logging import os +import pickle import pprint import shutil import sys @@ -217,6 +218,8 @@ class BlockDevice(object): = os.path.join(self.state_dir, "state.json") self.config_json_file_name \ = os.path.join(self.state_dir, "config.json") + self.node_pickle_file_name \ + = os.path.join(self.state_dir, "nodes.pickle") self.config = _load_json(self.config_json_file_name) @@ -379,7 +382,12 @@ class BlockDevice(object): rollback_cb() sys.exit(1) + # dump state and nodes, in order + # XXX: we only dump the call_order (i.e. nodes) not the whole + # graph here, because later calls do not need the graph + # at this stage. might they? state.save_state(self.state_json_file_name) + pickle.dump(call_order, open(self.node_pickle_file_name, 'wb')) logger.info("create() finished") return 0 @@ -397,11 +405,9 @@ class BlockDevice(object): return 0 # Deleting must be done in reverse order - dg, call_order = create_graph(self.config, self.params) + call_order = pickle.load(open(self.node_pickle_file_name, 'rb')) reverse_order = reversed(call_order) - if dg is None: - return 0 for node in reverse_order: node.umount(state) @@ -414,7 +420,7 @@ class BlockDevice(object): state = BlockDeviceState(self.state_json_file_name) # Deleting must be done in reverse order - dg, call_order = create_graph(self.config, self.params) + call_order = pickle.load(open(self.node_pickle_file_name, 'rb')) reverse_order = reversed(call_order) for node in reverse_order: @@ -432,7 +438,7 @@ class BlockDevice(object): state = BlockDeviceState(self.state_json_file_name) # Deleting must be done in reverse order - dg, call_order = create_graph(self.config, self.params) + call_order = pickle.load(open(self.node_pickle_file_name, 'rb')) reverse_order = reversed(call_order) for node in reverse_order: diff --git a/diskimage_builder/block_device/tests/plugin/test_a.py b/diskimage_builder/block_device/tests/plugin/test_a.py index 4075e8333..0890bbd62 100644 --- a/diskimage_builder/block_device/tests/plugin/test_a.py +++ b/diskimage_builder/block_device/tests/plugin/test_a.py @@ -38,6 +38,10 @@ class TestANode(NodeBase): state['test_a']['value2'] = 'bar' return + def umount(self, state): + # Umount is run in reverse. This key should exist from test_b + state['umount'].append('test_a') + class TestA(PluginBase): diff --git a/diskimage_builder/block_device/tests/plugin/test_b.py b/diskimage_builder/block_device/tests/plugin/test_b.py index bfcc226f2..da1307b6f 100644 --- a/diskimage_builder/block_device/tests/plugin/test_b.py +++ b/diskimage_builder/block_device/tests/plugin/test_b.py @@ -35,6 +35,12 @@ class TestBNode(NodeBase): state['test_b']['value'] = 'baz' return + def umount(self, state): + # umount run in reverse. this should run before test_a + assert 'umount' not in state + state['umount'] = [] + state['umount'].append('test_b') + class TestB(PluginBase): diff --git a/diskimage_builder/block_device/tests/test_state.py b/diskimage_builder/block_device/tests/test_state.py index 92a67a3dc..c855b6bba 100644 --- a/diskimage_builder/block_device/tests/test_state.py +++ b/diskimage_builder/block_device/tests/test_state.py @@ -62,9 +62,7 @@ class TestState(TestStateBase): bd_obj.cmd_create() # cmd_create should have persisted this to disk - state_file = os.path.join(self.build_dir.path, - 'states', 'block-device', - 'state.json') + state_file = bd_obj.state_json_file_name self.assertThat(state_file, FileExists()) # ensure we see the values put in by the test extensions @@ -76,6 +74,14 @@ class TestState(TestStateBase): 'value2': 'bar'}, 'test_b': {'value': 'baz'}}) + pickle_file = bd_obj.node_pickle_file_name + self.assertThat(pickle_file, FileExists()) + + # run umount, which should load the picked nodes and run in + # reverse. This will create some state in "test_b" that it + # added to by "test_a" ... ensuring it was run backwards. + bd_obj.cmd_umount() + # Test state going missing between phases def test_missing_state(self): params = {