Commit 2a27239d authored by Julien Muchembled's avatar Julien Muchembled

tweak: add option to simulate

Initially, I wanted to do the simulation inside neoctl but it has no knowledge
of the topology (the master don't send devpath values of storage nodes).
Therefore, the work is delegated to the master node, which implies a change
of the protocol.
parent 3839d224
...@@ -1254,10 +1254,14 @@ class TweakPartitionTable(Packet): ...@@ -1254,10 +1254,14 @@ class TweakPartitionTable(Packet):
:nodes: ctl -> A -> M :nodes: ctl -> A -> M
""" """
_fmt = PStruct('tweak_partition_table', _fmt = PStruct('tweak_partition_table',
PBoolean('dry_run'),
PFUUIDList, PFUUIDList,
) )
_answer = Error _answer = PStruct('answer_tweak_partition_table',
PBoolean('changed'),
PFRowList,
)
class NotifyNodeInformation(Packet): class NotifyNodeInformation(Packet):
""" """
...@@ -1775,8 +1779,8 @@ class Packets(dict): ...@@ -1775,8 +1779,8 @@ class Packets(dict):
SetNodeState, ignore_when_closed=False) SetNodeState, ignore_when_closed=False)
AddPendingNodes = register( AddPendingNodes = register(
AddPendingNodes, ignore_when_closed=False) AddPendingNodes, ignore_when_closed=False)
TweakPartitionTable = register( TweakPartitionTable, AnswerTweakPartitionTable = register(
TweakPartitionTable, ignore_when_closed=False) TweakPartitionTable)
SetNumReplicas = register( SetNumReplicas = register(
SetNumReplicas, ignore_when_closed=False) SetNumReplicas, ignore_when_closed=False)
SetClusterState = register( SetClusterState = register(
......
...@@ -195,17 +195,28 @@ class AdministrationHandler(MasterHandler): ...@@ -195,17 +195,28 @@ class AdministrationHandler(MasterHandler):
conn.answer(Errors.Ack('')) conn.answer(Errors.Ack(''))
@__change_pt_rpc @__change_pt_rpc
def tweakPartitionTable(self, conn, uuid_list): def tweakPartitionTable(self, conn, dry_run, uuid_list):
app = self.app app = self.app
drop_list = [node for node in app.nm.getStorageList() drop_list = [node for node in app.nm.getStorageList()
if node.getUUID() in uuid_list or not node.isRunning()] if node.getUUID() in uuid_list or not node.isRunning()]
if dry_run:
pt = object.__new__(app.pt.__class__)
new_nodes = pt.load(app.pt.getID(), app.pt.getReplicas(),
app.pt.getRowList(), app.nm)
assert not new_nodes
pt.addNodeList(node
for node, count in app.pt.count_dict.iteritems()
if not count)
else:
pt = app.pt
try: try:
changed_list = app.pt.tweak(drop_list) changed_list = pt.tweak(drop_list)
except PartitionTableException, e: except PartitionTableException, e:
raise AnswerDenied(str(e)) raise AnswerDenied(str(e))
else: if not dry_run:
app.broadcastPartitionChanges(changed_list) app.broadcastPartitionChanges(changed_list)
conn.answer(Errors.Ack('')) conn.answer(Packets.AnswerTweakPartitionTable(
bool(changed_list), pt.getRowList()))
@check_state(ClusterStates.RUNNING) @check_state(ClusterStates.RUNNING)
def truncate(self, conn, tid): def truncate(self, conn, tid):
......
...@@ -183,9 +183,15 @@ class TerminalNeoCTL(object): ...@@ -183,9 +183,15 @@ class TerminalNeoCTL(object):
No change is done to the specified/down storage nodes and they don't No change is done to the specified/down storage nodes and they don't
count as replicas. The purpose of listing nodes is usually to drop count as replicas. The purpose of listing nodes is usually to drop
them once the data is replicated to other nodes. them once the data is replicated to other nodes.
Parameters: [node [...]] Parameters: [-n] [node [...]]
""" -n: dry run
return self.neoctl.tweakPartitionTable(map(self.asNode, params)) """
dry_run = params[0] == '-n'
changed, row_list = self.neoctl.tweakPartitionTable(
map(self.asNode, params[dry_run:]), dry_run)
if changed:
return self.formatRowList(enumerate(row_list))
return 'No change done.'
def killNode(self, params): def killNode(self, params):
""" """
......
...@@ -63,3 +63,4 @@ class CommandEventHandler(EventHandler): ...@@ -63,3 +63,4 @@ class CommandEventHandler(EventHandler):
answerLastIDs = __answer(Packets.AnswerLastIDs) answerLastIDs = __answer(Packets.AnswerLastIDs)
answerLastTransaction = __answer(Packets.AnswerLastTransaction) answerLastTransaction = __answer(Packets.AnswerLastTransaction)
answerRecovery = __answer(Packets.AnswerRecovery) answerRecovery = __answer(Packets.AnswerRecovery)
answerTweakPartitionTable = __answer(Packets.AnswerTweakPartitionTable)
...@@ -91,11 +91,11 @@ class NeoCTL(BaseApplication): ...@@ -91,11 +91,11 @@ class NeoCTL(BaseApplication):
raise RuntimeError(response) raise RuntimeError(response)
return response[2] return response[2]
def tweakPartitionTable(self, uuid_list=()): def tweakPartitionTable(self, uuid_list=(), dry_run=False):
response = self.__ask(Packets.TweakPartitionTable(uuid_list)) response = self.__ask(Packets.TweakPartitionTable(dry_run, uuid_list))
if response[0] != Packets.Error or response[1] != ErrorCodes.ACK: if response[0] != Packets.AnswerTweakPartitionTable:
raise RuntimeError(response) raise RuntimeError(response)
return response[2] return response[1:]
def setNumReplicas(self, nr): def setNumReplicas(self, nr):
response = self.__ask(Packets.SetNumReplicas(nr)) response = self.__ask(Packets.SetNumReplicas(nr))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment