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 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:
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user