Use picked nodes for later cmd_* calls
Currently the later cmd_* calls -- umount, cleanup, delete -- all recreate the node graph by parsing the config file using create_graph() There is some need, however, to have a sense of global state when building the node list. The problem is, this is a one time operation -- we do not want to rebuild that state for these later calls (see the "loaded" checks in proposed Ic3b805f9258128d5233b21ff25579c03487c7fcc). An insight here seems to be that these cmd_* calls do not actually want to re-parse the configuration file and rebuild the node list; they just want to walk the node list in reverse with the state as provided after cmd_create(). So, rather than re-creating the node list, we might as well just pickle it, save it to disk along side the state dictionary dump and reload it for cmd_*. After this, I think we can safely have PluginBase.__init__() be passed the state. We will now know that this will only be called once, during initial creation. Change-Id: I68840594a34af28d41d9522addcfd830bd203b97
This commit is contained in:
parent
9a8b135267
commit
e82e0097a9
@ -17,6 +17,7 @@ import collections
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import pickle
|
||||||
import pprint
|
import pprint
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
@ -217,6 +218,8 @@ class BlockDevice(object):
|
|||||||
= os.path.join(self.state_dir, "state.json")
|
= os.path.join(self.state_dir, "state.json")
|
||||||
self.config_json_file_name \
|
self.config_json_file_name \
|
||||||
= os.path.join(self.state_dir, "config.json")
|
= 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)
|
self.config = _load_json(self.config_json_file_name)
|
||||||
|
|
||||||
@ -379,7 +382,12 @@ class BlockDevice(object):
|
|||||||
rollback_cb()
|
rollback_cb()
|
||||||
sys.exit(1)
|
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)
|
state.save_state(self.state_json_file_name)
|
||||||
|
pickle.dump(call_order, open(self.node_pickle_file_name, 'wb'))
|
||||||
|
|
||||||
logger.info("create() finished")
|
logger.info("create() finished")
|
||||||
return 0
|
return 0
|
||||||
@ -397,11 +405,9 @@ class BlockDevice(object):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Deleting must be done in reverse order
|
# 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)
|
reverse_order = reversed(call_order)
|
||||||
|
|
||||||
if dg is None:
|
|
||||||
return 0
|
|
||||||
for node in reverse_order:
|
for node in reverse_order:
|
||||||
node.umount(state)
|
node.umount(state)
|
||||||
|
|
||||||
@ -414,7 +420,7 @@ class BlockDevice(object):
|
|||||||
state = BlockDeviceState(self.state_json_file_name)
|
state = BlockDeviceState(self.state_json_file_name)
|
||||||
|
|
||||||
# Deleting must be done in reverse order
|
# 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)
|
reverse_order = reversed(call_order)
|
||||||
|
|
||||||
for node in reverse_order:
|
for node in reverse_order:
|
||||||
@ -432,7 +438,7 @@ class BlockDevice(object):
|
|||||||
state = BlockDeviceState(self.state_json_file_name)
|
state = BlockDeviceState(self.state_json_file_name)
|
||||||
|
|
||||||
# Deleting must be done in reverse order
|
# 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)
|
reverse_order = reversed(call_order)
|
||||||
|
|
||||||
for node in reverse_order:
|
for node in reverse_order:
|
||||||
|
@ -38,6 +38,10 @@ class TestANode(NodeBase):
|
|||||||
state['test_a']['value2'] = 'bar'
|
state['test_a']['value2'] = 'bar'
|
||||||
return
|
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):
|
class TestA(PluginBase):
|
||||||
|
|
||||||
|
@ -35,6 +35,12 @@ class TestBNode(NodeBase):
|
|||||||
state['test_b']['value'] = 'baz'
|
state['test_b']['value'] = 'baz'
|
||||||
return
|
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):
|
class TestB(PluginBase):
|
||||||
|
|
||||||
|
@ -62,9 +62,7 @@ class TestState(TestStateBase):
|
|||||||
bd_obj.cmd_create()
|
bd_obj.cmd_create()
|
||||||
|
|
||||||
# cmd_create should have persisted this to disk
|
# cmd_create should have persisted this to disk
|
||||||
state_file = os.path.join(self.build_dir.path,
|
state_file = bd_obj.state_json_file_name
|
||||||
'states', 'block-device',
|
|
||||||
'state.json')
|
|
||||||
self.assertThat(state_file, FileExists())
|
self.assertThat(state_file, FileExists())
|
||||||
|
|
||||||
# ensure we see the values put in by the test extensions
|
# ensure we see the values put in by the test extensions
|
||||||
@ -76,6 +74,14 @@ class TestState(TestStateBase):
|
|||||||
'value2': 'bar'},
|
'value2': 'bar'},
|
||||||
'test_b': {'value': 'baz'}})
|
'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
|
# Test state going missing between phases
|
||||||
def test_missing_state(self):
|
def test_missing_state(self):
|
||||||
params = {
|
params = {
|
||||||
|
Loading…
Reference in New Issue
Block a user