blob: 51a4ca49e16d68c8d498e4be780f9950ed46ab74 [file] [log] [blame]
Jonathan Hart9dbb9962013-02-06 11:18:48 -08001#!/usr/bin/python
2
3import os
4import sys
5import time
6import socket
7import argparse
8import paramiko
9import subprocess
10
11CASSANDRA_DIR = "/home/ubuntu/apache-cassandra-1.1.4"
12CASSANDRA_NODETOOL = CASSANDRA_DIR + "/bin/nodetool"
13CASSANDRA_CMD = CASSANDRA_DIR + "/bin/cassandra"
14
15class RemoteOnosNode:
16
17 def __init__(self, ip):
18 #self.hostname = hostname
19 self.ip = ip
20
21 self.ssh = paramiko.SSHClient()
22 self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
23 self.ssh.connect(self.ip, key_filename='/home/ubuntu/.ssh/onlabkey.pem')
24
25 def get_pids(self, process_search_string):
26 stdin, stdout, stderr = self.ssh.exec_command('pgrep -f %s' % process_search_string)
27 pid_list = stdout.readlines()
28
29 return ([x.strip() for x in pid_list])
30
31 #takes a list of pids to kill
32 def kill_all(self, pid_list):
33 for pid in pid_list:
34 stdin, stdout, stderr = self.ssh.exec_command('kill %s' % pid)
35
36 if stderr.read() != '':
37 print "Killing %s failed" % pid
38 else:
39 print "%s killed" % pid
40
41 def clean(self):
42 processes = ['floodlight.jar', 'CassandraDaemon']
43
44 for process in processes:
45 self.kill_all(self.get_pids(process))
46
47 def start_onos(self, embedded=False):
48 print "*** Starting ONOS:"
49
50 if embedded:
51 onos_script = ('nohup /home/ubuntu/ONOS/onos-embedded.sh > '
52 '/dev/null 2>&1 &')
53 else:
54 onos_script = 'nohup /home/ubuntu/ONOS/onos.sh > /dev/null 2>&1 &'
55
56 self.ssh.exec_command(onos_script)
57
58
59 def start_cassandra(self):
60
61 print "*** Starting Cassandra:"
62
63 stdin, stdout, stderr = self.ssh.exec_command(CASSANDRA_CMD)
64 if stderr.read() != '':
65 print "Error starting Casssanda"
66 return
67
68 print "*** Waiting while Cassandra bootstaps:"
69
70 node_bootstrapped = False
71 while not node_bootstrapped:
72 stdin, stdout, stderr = self.ssh.exec_command(CASSANDRA_NODETOOL + ' ring')
73 for line in stdout.readlines():
74 if (self.ip in line) and ('Up' in line):
75 node_bootstrapped = True
76
77 time.sleep(1)
78
79 def check_status(self):
80 #self.check_process('floodlight.jar')
81
82 onos_pids = self.get_pids('floodlight.jar')
83 onos_ok = len(onos_pids) == 1
84
85 cassandra_pids = self.get_pids('CassandraDaemon')
86 cassandra_ok = len(cassandra_pids) == 1
87
88 controller_port = self.check_port_listening(self.ip, '6633')
89
90 in_ring = self.check_in_ring()
91
92 if onos_ok and (not cassandra_ok) and in_ring:
93 print "ONOS and Cassandra running in EMBEDDED mode"
94 elif onos_ok and cassandra_ok and in_ring and controller_port:
95 print "ONOS and Cassandra running in SEPARATE mode"
96 elif not (onos_ok or cassandra_ok or in_ring or controller_port):
97 print "Node is DOWN"
98 else:
99 print "Node is not fully operational:"
100 print "ONOS process pid %s" % onos_pids
101 print "Cassandra process pids %s" % cassandra_pids
102 print "Controller port open: %s" % controller_port
103 print "Node in Cassandra ring: %s" % in_ring
104
105 def check_in_ring(self):
106 stdin, stdout, stderr = self.ssh.exec_command(CASSANDRA_NODETOOL + ' ring')
107
108 for line in stdout.readlines():
109 if (self.ip in line) and ('Up' in line):
110 return True
111
112 return False
113
114 def check_port_listening(self, host, port):
115 command = 'telnet -e A %s %s' % (host, port)
116 process = subprocess.Popen(command.split(), stdin=subprocess.PIPE,
117 stdout=subprocess.PIPE,
118 stderr=subprocess.STDOUT)
119 output = process.communicate(input='A quit')[0]
120
121 if 'Unable' in output:
122 return False
123
124 return True
125
126def start_mininet(mn_host):
127 ssh = paramiko.SSHClient()
128 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
129
130 ssh.connect(mn_host, key_filename='/home/ubuntu/.ssh/onlabkey.pem')
131
132 stdin, stdout, stderr = ssh.exec_command('sudo mn -c')
133
134 #print (stdout.read())
135 #print (stderr.read())
136 if not '*** Cleanup complete.' in stderr.read():
137 print ("Mininet didn't clean up properly")
138
139 network_file = '/home/ubuntu/sdn2/onos-nw.py'
140 stdin, stdout, stderr = ssh.exec_command('sudo python %s > /dev/null 2>&1 &' % network_file)
141
142 print "OUT\n"
143 print stdout.read()
144 print "ERR\n"
145 print stderr.read()
146
147 ssh.close()
148
149def add(args):
150 (onos_ip, onos_hostname) = get_ip_hostname(args.hostname)
151
152 pr_hostname = "" if onos_ip == onos_hostname else onos_hostname
153 print "Starting up ONOS node %s with IP %s" % (pr_hostname, onos_ip)
154
155 remote_node = RemoteOnosNode(onos_ip)
156 remote_node.clean()
157
158 #wait a few seconds to let cassandra fully shutdown
159 time.sleep(2)
160
161 if args.embedded:
162 remote_node.start_onos(embedded=True)
163 else:
164 remote_node.start_cassandra()
165 remote_node.start_onos()
166
167
168def get_ip_hostname(node):
169 """ Takes in either a hostname or an IP address and returns
170 (ip, hostname).
171 Note if IP is given both values will be the same, i.e. we don't
172 actually care about finding the hostname if user specified an IP"""
173
174 if '.' in node:
175 return (node, node)
176 else:
177 return (socket.gethostbyname(node), node)
178
179
180def status(args):
181 for node in args.cluster_nodes.split(','):
182 (ip, hostname) = get_ip_hostname(node)
183
184 print "Status of %s:" % hostname
185
186 remote_node = RemoteOnosNode(ip)
187 remote_node.check_status()
188
189 print
190
191def remove(args):
192 remote_node = RemoteOnosNode(args.hostname)
193 remote_node.clean()
194
195def parse_args():
196 commands = ['add', 'remove', 'status']
197
198 parser = argparse.ArgumentParser(description='Add node to ONOS cluster')
199 ##add command
200 subparsers = parser.add_subparsers(help='command')
201 parser_add = subparsers.add_parser('add',
202 help='Add a node to ONOS cluster')
203 parser_add.add_argument('hostname',
204 help='hostname of new ONOS node')
205 parser_add.add_argument('-e', '--embedded', action='store_true',
206 help='run Cassandra in embedded mode in the same '
207 'JVM as ONOS')
208 parser_add.set_defaults(func=add)
209
210 ##status command
211 parser_status = subparsers.add_parser('status',
212 help='Check status of ONOS nodes')
213 parser_status.add_argument('cluster_nodes',
214 help='comma-delimited list IP addresses for '
215 'existing cluster nodes')
216 parser_status.set_defaults(func=status)
217
218 ##remove command
219 parser_remove = subparsers.add_parser('remove', help='Remove an ONOS node '
220 'from the cluster')
221 parser_remove.add_argument('hostname', help='ONOS node to remove')
222 parser_remove.set_defaults(func=remove)
223
224
225 return parser.parse_args()
226
227
228if __name__ == '__main__':
229 args = parse_args()
230
231 args.func(args)
232 """
233 if args.mininet:
234 start_mininet(args.mininet)
235 else:
236 print('Assuming mininet host is the same as ONOS host')
237 start_mininet(args.onos)
238 """
239
240
241 sys.exit(0)