diff --git a/etc/init.d/steth-agent b/etc/init.d/steth-agent new file mode 100644 index 0000000..5627cd9 --- /dev/null +++ b/etc/init.d/steth-agent @@ -0,0 +1,93 @@ +#!/bin/bash +# +# stetho OpenStack Software Defined Networking Debuging +# +# chkconfig: - 98 02 +# description: neutron provides an API to \ +# * request and configure virtual networks +# Just for CentOS 6.5 +### END INIT INFO + +. /etc/rc.d/init.d/functions + +prog=stetho +exec="/usr/bin/$prog-agent" +pidfile="/var/run/$prog/$prog.pid" +logfile="/var/log/$prog/server.log" + +[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog + +lockfile=/var/lock/subsys/$prog-agent + +start() { + [ -x $exec ] || exit 5 + echo -n $"Starting $prog: " + daemon --user neutron --pidfile $pidfile "$exec & echo \$! > $pidfile" + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + killproc -p $pidfile $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + status -p $pidfile $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/etc/init.d/stetho-agent.service b/etc/init.d/stetho-agent.service new file mode 100644 index 0000000..0e6ca79 --- /dev/null +++ b/etc/init.d/stetho-agent.service @@ -0,0 +1,13 @@ +# Just for CentOS 7 +[Unit] +Description=OpenStack Neutron Debug Service +After=network.target + +[Service] +Type=simple +User=root +ExecStart=/usr/bin/python /usr/bin/stetho-agent +Restart=on-abort + +[Install] +WantedBy=multi-user.target diff --git a/requirements.txt b/requirements.txt index 7d1af9d..3a92f0e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ jsonrpclib netaddr mock +cliff diff --git a/setup.py b/setup.py index 076397f..7a5f93f 100644 --- a/setup.py +++ b/setup.py @@ -13,8 +13,24 @@ # License for the specific language governing permissions and limitations # under the License. +import sys + from setuptools import setup, find_packages +# In CentOS6.5, the version of python is 2.6, and in CentOS7 the version of +# python is 2.7. So we can according by the python version to put the +# stetho-agent script to the right place. +# +# If in CentOS6.5, the init script should be placed in "/etc/init.d/" +# If in CentOS7, the init script should be placed in "/etc/systemd/system/" +CENTOS6 = '/etc/init.d/' +CENTOS7 = '/etc/systemd/system/' +CENTOS6_SCRIPT = 'etc/init.d/stetho-agent' +CENTOS7_SCRIPT = 'etc/init.d/stetho-agent.service' +PYTHON_VERSION = '2.6' if '2.6' in sys.version else '2.7' +AGENT_INIT_SCRIPT = CENTOS6 if PYTHON_VERSION == '2.6' else CENTOS7 +SCRIPT_LOCATION = CENTOS6_SCRIPT if PYTHON_VERSION == '2.6' else CENTOS7_SCRIPT + setup(name='stetho', version="0.1.0", packages = find_packages(), @@ -28,6 +44,8 @@ setup(name='stetho', url = "https://www.ustack.com", data_files=[ ('/etc/stetho', ['etc/stetho.conf']), + (AGENT_INIT_SCRIPT, [SCRIPT_LOCATION]), + ], entry_points={ 'console_scripts': [ diff --git a/stetho/stethoclient/README.rst b/stetho/stethoclient/README.rst deleted file mode 100644 index 0acf63c..0000000 --- a/stetho/stethoclient/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -====================== - Running Stethoclient -====================== - -This is a client library for stetho built on the Stetho API. It provides a Python API (the stethoclient module) and a command-line tool (stetho). diff --git a/stetho/stethoclient/stethoclient/__init__.py b/stetho/stethoclient/__init__.py similarity index 100% rename from stetho/stethoclient/stethoclient/__init__.py rename to stetho/stethoclient/__init__.py diff --git a/stetho/stethoclient/stethoclient/agent_api.py b/stetho/stethoclient/agent_api.py similarity index 65% rename from stetho/stethoclient/stethoclient/agent_api.py rename to stetho/stethoclient/agent_api.py index 7c791f7..14166da 100644 --- a/stetho/stethoclient/stethoclient/agent_api.py +++ b/stetho/stethoclient/agent_api.py @@ -24,6 +24,28 @@ from json import JSONDecoder from stetho.stethoclient.constants import AGENT_INFOS LISTEN_PORT = 9698 +SETUP_LINK_IP_PRE = "192.168.100." + + +class Logger(): + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + + @staticmethod + def log_normal(info): + print Logger.OKBLUE + info + Logger.ENDC + + @staticmethod + def log_high(info): + print Logger.OKGREEN + info + Logger.ENDC + + @staticmethod + def log_fail(info): + print Logger.FAIL + info + Logger.ENDC def setup_server(agent): @@ -90,6 +112,9 @@ class SetUpLink(Lister): # Get Link info res = server.get_interface(parsed_args.interface) self.log.debug('Response is %s' % res) + if res['code'] == 1: + Logger.log_fail(res['message']) + sys.exit() if res['code'] == 0: return (('Field', 'Value'), ((k, v) for k, v in res['data'].items())) @@ -117,6 +142,9 @@ class GetInterface(Lister): try: res = server.get_interface(parsed_args.interface) self.log.debug('Response is %s' % res) + if res['code'] == 1: + Logger.log_fail(res['message']) + sys.exit() if res['code'] == 0: return (('Field', 'Value'), ((k, v) for k, v in res['data'].items())) @@ -151,6 +179,9 @@ class AddVlanToInterface(Lister): new_interface = parsed_args.interface + '.' + parsed_args.vlan_id res = server.get_interface(new_interface) self.log.debug('Response is %s' % res) + if res['code'] == 1: + Logger.log_fail(res['message']) + sys.exit() if res['code'] == 0: return (('Field', 'Value'), ((k, v) for k, v in res['data'].items())) @@ -183,6 +214,9 @@ class AgentPing(Lister): timeout=parsed_args.timeout, interface=parsed_args.interface) self.log.debug('Response is %s' % res) + if res['code'] == 1: + Logger.log_fail(res['message']) + sys.exit() if res['code'] == 0: return (('Destination', 'Packet Loss (%)'), ((k, v) for k, v in res['data'].items())) @@ -210,9 +244,79 @@ class CheckPortsOnBr(Lister): res = server.check_ports_on_br(parsed_args.bridge, parsed_args.port) self.log.debug('Response is %s' % res) + if res['code'] == 1: + Logger.log_fail(res['message']) + sys.exit() if res['code'] == 0: return (('Port', 'Exists'), ((k, v) for k, v in res['data'].items())) except Exception as e: self.log.error('Agent %s return error: %s!' % parsed_args.agent, e) sys.exit() + + +class CheckVlanInterface(Lister): + """Check vlan if exists in switch""" + log = logging.getLogger(__name__) + + def get_parser(self, prog_name): + parser = super(CheckVlanInterface, self).get_parser(prog_name) + parser.add_argument('agentA', default='bad') + parser.add_argument('agentB', default='bad') + parser.add_argument('interface', default='eth0') + parser.add_argument('vlan_id', default='1124') + return parser + + def take_action(self, parsed_args): + self.log.debug('Get parsed_args: %s' % parsed_args) + serverA = setup_server(parsed_args.agentA) + serverB = setup_server(parsed_args.agentB) + try: + interface = parsed_args.interface + '.' + parsed_args.vlan_id + # First of all, check the interface if exists + resA = serverA.get_interface(interface) + resB = serverB.get_interface(interface) + if resA['code'] == 1: + msg = "Agent: %s has no interface named %s!" % ( + parsed_args.agentA, interface) + Logger.log_fail(msg) + sys.exit() + if resB['code'] == 1: + msg = "Agent: %s has no interface named %s!" % ( + parsed_args.agentB, interface) + Logger.log_fail(msg) + sys.exit() + # add vlan interface in each agent + resA = serverA.add_vlan_to_interface(parsed_args.interface, + parsed_args.vlan_id) + self.log.debug('Response is %s' % resA) + resB = serverB.add_vlan_to_interface(parsed_args.interface, + parsed_args.vlan_id) + self.log.debug('Response is %s' % resB) + Logger.log_normal(('AgentA and agentB has already added the ' + 'interface %s ') % (interface)) + # setup link in each agent + ipA = SETUP_LINK_IP_PRE + parsed_args.agentA.split('-')[1] + '/24' + resA = serverA.setup_link(interface, ipA) + self.log.debug('Response is %s' % resA) + ipB = SETUP_LINK_IP_PRE + parsed_args.agentB.split('-')[1] + '/24' + resB = serverB.setup_link(interface, ipB) + self.log.debug('Response is %s' % resB) + Logger.log_normal(('AgentA and agentB has already setup the ' + 'IP %s and IP %s') % (ipA, ipB)) + # ping a agent from exists IP to check connectivity + res = serverA.ping(ips=[ipB]) + # teardown the interface in each agent to clean all resources + resA = serverA.teardown_link(interface) + self.log.debug('Response is %s' % resA) + resB = serverB.teardown_link(interface) + self.log.debug('Response is %s' % resB) + Logger.log_normal(('AgentA and agentB has already deleted the' + 'vlan %s in %s') % (parsed_args.vlan_id, + parsed_args.interface)) + if res['code'] == 0: + return (('Destination', 'Packet Loss (%)'), + ((k, v) for k, v in res['data'].items())) + except Exception as e: + self.log.error('Agent %s return error: %s!' % parsed_args.agent, e) + sys.exit() diff --git a/stetho/stethoclient/stethoclient/constants.py b/stetho/stethoclient/constants.py similarity index 100% rename from stetho/stethoclient/stethoclient/constants.py rename to stetho/stethoclient/constants.py diff --git a/stetho/stethoclient/stethoclient/shell.py b/stetho/stethoclient/shell.py similarity index 97% rename from stetho/stethoclient/stethoclient/shell.py rename to stetho/stethoclient/shell.py index 2affd8c..785e378 100644 --- a/stetho/stethoclient/stethoclient/shell.py +++ b/stetho/stethoclient/shell.py @@ -35,6 +35,7 @@ COMMAND_V1 = { 'ping': agent_api.AgentPing, 'check-ports-on-br': agent_api.CheckPortsOnBr, 'get-interface': agent_api.GetInterface, + 'check-vlan-interface': agent_api.CheckVlanInterface, } COMMANDS = {'0.1': COMMAND_V1} diff --git a/stetho/stethoclient/stethoclient/strutils.py b/stetho/stethoclient/strutils.py similarity index 100% rename from stetho/stethoclient/stethoclient/strutils.py rename to stetho/stethoclient/strutils.py