# # Copyright (C) 2006-2009 Nexedi SA # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from neo import logging from neo import protocol from neo.master.handlers import MasterHandler from neo.protocol import RUNNING_STATE, TEMPORARILY_DOWN_STATE, DOWN_STATE, \ HIDDEN_STATE, PENDING_STATE, RUNNING_CLUSTER_STATE from neo.util import dump class AdministrationHandler(MasterHandler): """This class deals with messages from the admin node only""" def connectionLost(self, conn, new_state): node = self.app.nm.getByUUID(conn.getUUID()) self.app.nm.remove(node) def handleAskPrimaryMaster(self, conn, packet): app = self.app # I'm the primary conn.answer(protocol.answerPrimaryMaster(app.uuid, []), packet.getId()) def handleSetClusterState(self, conn, packet, state): self.app.changeClusterState(state) p = protocol.noError('cluster state changed') conn.answer(p, packet.getId()) if state == protocol.STOPPING_CLUSTER_STATE: self.app.cluster_state = state self.app.shutdown() def handleSetNodeState(self, conn, packet, uuid, state, modify_partition_table): logging.info("set node state for %s-%s : %s" % (dump(uuid), state, modify_partition_table)) app = self.app node = app.nm.getByUUID(uuid) if node is None: raise protocol.ProtocolError('unknown node') if uuid == app.uuid: node.setState(state) # get message for self if state != RUNNING_STATE: p = protocol.noError('node state changed') conn.answer(p, packet.getId()) app.shutdown() if node.getState() == state: # no change, just notify admin node p = protocol.noError('node state changed') conn.answer(p, packet.getId()) return if state == protocol.RUNNING_STATE: # first make sure to have a connection to the node node_conn = None for node_conn in app.em.getConnectionList(): if node_conn.getUUID() == node.getUUID(): break else: # no connection to the node raise protocol.ProtocolError('no connection to the node') elif state == protocol.DOWN_STATE and node.isStorage(): # modify the partition table if required cell_list = [] if modify_partition_table: # remove from pt cell_list = app.pt.dropNode(node) else: # outdate node in partition table cell_list = app.pt.outdate() if len(cell_list) != 0: ptid = app.pt.setNextID() app.broadcastPartitionChanges(ptid, cell_list) # /!\ send the node information *after* the partition table change node.setState(state) p = protocol.noError('state changed') conn.answer(p, packet.getId()) app.broadcastNodeInformation(node) def handleAddPendingNodes(self, conn, packet, uuid_list): uuids = ', '.join([dump(uuid) for uuid in uuid_list]) logging.debug('Add nodes %s' % uuids) app, nm, em, pt = self.app, self.app.nm, self.app.em, self.app.pt cell_list = [] uuid_set = set() # take all pending nodes for node in nm.getStorageList(): if node.getState() == PENDING_STATE: uuid_set.add(node.getUUID()) # keep only selected nodes if uuid_list: uuid_set = uuid_set.intersection(set(uuid_list)) # nothing to do if not uuid_set: logging.warning('No nodes added') p = protocol.noError('no nodes added') conn.answer(p, packet.getId()) return uuids = ', '.join([dump(uuid) for uuid in uuid_set]) logging.info('Adding nodes %s' % uuids) # switch nodes to running state for uuid in uuid_set: node = nm.getByUUID(uuid) new_cells = pt.addNode(node) cell_list.extend(new_cells) node.setState(RUNNING_STATE) app.broadcastNodeInformation(node) # start nodes for s_conn in em.getConnectionList(): if s_conn.getUUID() in uuid_set: s_conn.notify(protocol.notifyLastOID(app.loid)) s_conn.notify(protocol.startOperation()) # broadcast the new partition table app.broadcastPartitionChanges(app.pt.setNextID(), cell_list) p = protocol.noError('node added') conn.answer(p, packet.getId())