Commit 452c1ca0 authored by Vincent Pelletier's avatar Vincent Pelletier

Rewrite of neoctl to split it into 2 parts:

- reusable library (neoctl.py)
- console front-end (app.py)


git-svn-id: https://svn.erp5.org/repos/neo/branches/prototype3@1015 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 80f94b31
This diff is collapsed.
......@@ -16,71 +16,55 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from neo.handler import EventHandler
from neo.protocol import UnexpectedPacketError
from neo.exception import OperationFailure
from neo.util import dump
from neo import protocol
class CommandEventHandler(EventHandler):
""" Base handler for command """
def connectionAccepted(self, conn, s, addr):
"""Called when a connection is accepted."""
raise UnexpectedPacketError
def connectionCompleted(self, conn):
# connected to admin node
self.app.trying_admin_node = False
self.app.connected = True
EventHandler.connectionCompleted(self, conn)
def connectionFailed(self, conn):
EventHandler.connectionFailed(self, conn)
raise OperationFailure, "impossible to connect to admin node %s:%d" % conn.getAddress()
def __disconnected(self):
app = self.app
app.connected = False
app.connection = None
def timeoutExpired(self, conn):
EventHandler.timeoutExpired(self, conn)
raise OperationFailure, "connection to admin node %s:%d timeout" % conn.getAddress()
def __respond(self, response):
self.app.response_queue.append(response)
def connectionClosed(self, conn):
if self.app.trying_admin_node:
raise OperationFailure, "cannot connect to admin node %s:%d" % conn.getAddress()
EventHandler.connectionClosed(self, conn)
super(CommandEventHandler, self).connectionClosed(conn)
self.__disconnected()
def connectionFailed(self, conn):
super(CommandEventHandler, self).connectionFailed(conn)
self.__disconnected()
def timeoutExpired(self, conn):
super(CommandEventHandler, self).timeoutExpired(conn)
self.__disconnected()
def peerBroken(self, conn):
EventHandler.peerBroken(self, conn)
raise OperationFailure, "connect to admin node %s:%d broken" % conn.getAddress()
super(CommandEventHandler, self).peerBroken(conn)
self.__disconnected()
def handleAnswerPartitionList(self, conn, packet, ptid, row_list):
data = ""
if len(row_list) == 0:
data = "No partition"
else:
for offset, cell_list in row_list:
data += "\n%s | " % offset
for uuid, state in cell_list:
data += "%s - %s |" % (dump(uuid), state)
self.app.result = data
self.__respond((packet.getType(), ptid, row_list))
def handleAnswerNodeList(self, conn, packet, node_list):
data = ""
if len(node_list) == 0:
data = "No Node"
else:
for node_type, address, uuid, state in node_list:
if address is None:
address = (None, None)
ip, port = address
data += "\n%s - %s - %s:%s - %s" % (node_type, dump(uuid), ip, port, state)
self.app.result = data
self.__respond((packet.getType(), node_list))
def handleAnswerNodeState(self, conn, packet, uuid, state):
self.app.result = "Node %s set to state %s" % (dump(uuid), state)
self.__respond((packet.getType(), uuid, state))
def handleAnswerClusterState(self, conn, packet, state):
self.app.result = "Cluster state : %s" % state
self.__respond((packet.getType(), state))
def handleAnswerNewNodes(self, conn, packet, uuid_list):
uuids = ', '.join([dump(uuid) for uuid in uuid_list])
self.app.result = 'New storage nodes : %s' % uuids
self.__respond((packet.getType(), uuid_list))
def handleNoError(self, conn, packet, msg):
self.app.result = msg
self.__respond((packet.getType(), protocol.NO_ERROR_CODE, msg))
#
# 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.connector import getConnectorHandler
from neo.connection import ClientConnection
from neo.event import EventManager
from neo.neoctl.handler import CommandEventHandler
from neo import protocol
class NeoCTL(object):
connection = None
connected = False
def __init__(self, ip, port, handler):
self.connector_handler = getConnectorHandler(handler)
self.server = (ip, port)
self.em = EventManager()
self.handler = CommandEventHandler(self)
self.response_queue = []
def __getConnection(self):
while not self.connected:
self.connection = ClientConnection(
self.em, self.handler, addr=self.server,
connector_handler=self.connector_handler)
while not self.connected and self.connection is not None:
self.em.poll(0)
return self.connection
def __ask(self, packet):
# TODO: make thread-safe
connection = self.__getConnection()
connection.ask(packet)
response_queue = self.response_queue
assert len(response_queue) == 0
while len(response_queue) == 0:
self.em.poll(0)
if not self.connected:
raise Exception, 'Connection closed'
return response_queue.pop()
def enableStorageList(self, node_list):
"""
Put all given storage nodes in "running" state.
"""
packet = protocol.addPendingNodes(node_list)
response = self.__ask(packet)
assert response[0] == protocol.ERROR
assert response[1] == protocol.NO_ERROR_CODE
def setClusterState(self, state):
"""
Set cluster state.
"""
packet = protocol.setClusterState(state)
response = self.__ask(packet)
assert response[0] == protocol.ANSWER_CLUSTER_STATE
assert state == response[1]
def setNodeState(self, node, state, update_partition_table=False):
"""
Set node state, and allow (or not) updating partition table.
"""
if update_partition_table:
update_partition_table = 1
else:
update_partition_table = 0
packet = protocol.setNodeState(node, state, update_partition_table)
response = self.__ask(packet)
assert response[0] == protocol.ANSWER_NODE_STATE
assert node == response[1]
assert state == response[2]
def getClusterState(self):
"""
Get cluster state.
"""
packet = protocol.askClusterState()
response = self.__ask(packet)
assert response[0] == protocol.ANSWER_CLUSTER_STATE
return response[1]
def getNodeList(self, node_type=None):
"""
Get a list of nodes, filtering with given type.
"""
packet = protocol.askNodeList(node_type)
response = self.__ask(packet)
assert response[0] == protocol.ANSWER_NODE_LIST
return response[1]
def getPartitionRowList(self, min_offset=0, max_offset=0, node=None):
"""
Get a list of partition rows, bounded by min & max and involving
given node.
"""
packet = protocol.askPartitionList(min_offset, max_offset, node)
response = self.__ask(packet)
assert response[0] == protocol.ANSWER_PARTITION_LIST
return (response[1], response[2])
def startCluster(self):
"""
Set cluster into "verifying" state.
"""
self.setClusterState(protocol.VERIFYING)
def dropNode(self, node):
"""
Set node into "down" state and remove it from partition table.
"""
self.setNodeState(node, protocol.DOWN_STATE, update_partition_table=1)
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