4 # Licence statement goes here
7 import sys, glob, threading
10 #sys.path.append('gen-py')
11 #sys.path.insert(0, glob.glob('./lib/py/build/lib.*')[0])
12 sys.path.insert(0, glob.glob('./lib')[0])
14 from dominoRPC import Communication
15 from dominoRPC.ttypes import *
16 from dominoRPC.constants import *
18 from thrift import Thrift
19 from thrift.transport import TSocket
20 from thrift.transport import TTransport
21 from thrift.protocol import TBinaryProtocol
22 from thrift.server import TServer
29 DOMINO_SERVER_IP = 'localhost'
30 DOMINO_SERVER_PORT = 9090
33 LIST_SUPPORTED_TEMPLATES = ['tosca-nfv-v1.0']
34 #DEFAULT_TOSCA_PUBFILE = './tosca-templates/tosca_simpleVNF.yaml'
35 DEFAULT_TOSCA_PUBFILE = './tosca-templates/tosca_helloworld_nfv.yaml'
37 class CommunicationHandler:
41 def __init__(self, dominoclient):
42 global DOMINO_SERVER_IP, DOMINO_SERVER_PORT
44 self.dominoClient = dominoclient
47 transport = TSocket.TSocket(DOMINO_SERVER_IP, DOMINO_SERVER_PORT)
48 # Add buffering to compensate for slow raw sockets
49 self.transport = TTransport.TBufferedTransport(transport)
51 self.protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
52 # Create a client to use the protocol encoder
53 self.sender = Communication.Client(self.protocol)
54 except Thrift.TException, tx:
55 print '%s' % (tx.message)
57 # Template Push from Domino Server is received
59 # - Depending on Controller Domain, call API
60 # - Respond Back with Push Response
61 def d_push(self, push_msg):
62 print 'Received Template File'
63 # Retrieve the template file
67 # Any inspection code goes here
72 # If heat client, call heat command
74 # If ONOS client, run as shell script
79 # Marshall the response message for the Domino Server Fill
80 push_r = PushResponseMessage()
81 # Fill response message fields
82 push_r.domino_udid = self.dominoClient.UDID
83 push_r.seq_no = self.dominoClient.seqno
84 push_r.responseCode = SUCCESS
87 self.dominoClient.seqno = self.dominoClient.seqno + 1
92 def openconnection(self):
95 def closeconnection():
96 self.transport.close()
98 def read_templatefile(temp_filename):
99 f = open(temp_filename, 'r')
100 lines = f.read().splitlines()
104 class DominoClientCLIService(threading.Thread):
105 def __init__(self, dominoclient, communicationhandler):
106 threading.Thread.__init__(self)
107 self.dominoclient = dominoclient
108 self.communicationhandler = communicationhandler
111 global DEFAULT_TOSCA_PUBFILE
113 sys.stdout.write('>>')
114 input_string = raw_input()
115 args = input_string.split()
122 #process input arguments
124 sys.stdout.write('>>')
125 if args[0] == 'heartbeat':
126 print '\nSending heatbeat'
127 hbm = HeartBeatMessage()
128 hbm.domino_udid = self.dominoclient.UDID
129 hbm.seq_no = self.dominoclient.seqno
130 hbm_r = self.communicationhandler.sender.d_heartbeat(hbm)
131 print 'heart beat received from: %d ,sequence number: %d' % (hbm_r.domino_udid, hbm_r.seq_no)
132 self.dominoclient.seqno = self.dominoclient.seqno + 1
134 elif args[0] == 'publish':
135 opts, args = getopt.getopt(args[1:],"t:",["tosca-file="])
137 print '\nUsage: publish -t <toscafile>'
140 #toscafile = DEFAULT_TOSCA_PUBFILE
141 for opt, arg in opts:
142 if opt in ('-t', '--tosca-file'):
145 pub_msg = PublishMessage()
146 pub_msg.domino_udid = self.dominoclient.UDID
147 pub_msg.seq_no = self.dominoclient.seqno
148 pub_msg.template_type = 'tosca-nfv-v1.0'
150 pub_msg.template = read_templatefile(toscafile)
152 print "I/O error({0}): {1}".format(e.errno, e.strerror)
154 print '\nPublishing the template file: ' + toscafile
155 pub_msg_r = self.communicationhandler.sender.d_publish(pub_msg)
156 print 'Publish Response is received from: %d ,sequence number: %d' % (pub_msg_r.domino_udid, pub_msg_r.seq_no)
157 self.dominoclient.seqno = self.dominoclient.seqno + 1
159 elif args[0] == 'subscribe':
160 opts, args = getopt.getopt(args[1:],"l:t:",["labels=","ttype="])
161 for opt, arg in opts:
162 if opt in ('-l', '--labels'):
163 labels = labels + arg.split(',')
164 elif opt in ('-t', '--ttype'):
165 templateTypes = templateTypes + arg.split(',')
167 except getopt.GetoptError:
168 print 'Command is misentered or not supported!'
171 #check if labels or supported templates are nonempty
172 if labels != [] or templateTypes != []:
173 #send subscription message
174 sub_msg = SubscribeMessage()
175 sub_msg.domino_udid = self.dominoclient.UDID
176 sub_msg.seq_no = self.dominoclient.seqno
177 sub_msg.template_op = APPEND
178 sub_msg.supported_template_types = templateTypes
179 sub_msg.label_op = APPEND
180 sub_msg.labels = labels
181 print 'subscribing labels %s and templates %s' % (labels,templateTypes)
182 sub_msg_r = self.communicationhandler.sender.d_subscribe(sub_msg)
183 print 'Subscribe Response is received from: %d ,sequence number: %d' % (sub_msg_r.domino_udid,sub_msg_r.seq_no)
184 self.dominoclient.seqno = self.dominoclient.seqno + 1
189 self.communicationHandler = CommunicationHandler(self)
190 self.processor = None
191 self.transport = None
194 self.communicationServer = None
196 self.CLIservice = DominoClientCLIService(self, self.communicationHandler)
198 self.serviceport = 9091
199 self.dominoserver_IP = 'localhost'
201 #Start from UNREGISTERED STATE
202 #TO BE DONE: initialize from a saved state
203 self.state = 'UNREGISTERED'
207 def start_communicationService(self):
208 self.processor = Communication.Processor(self.communicationHandler)
209 self.transport = TSocket.TServerSocket(port=int(self.serviceport))
210 self.tfactory = TTransport.TBufferedTransportFactory()
211 self.pfactory = TBinaryProtocol.TBinaryProtocolFactory()
212 #Use TThreadedServer or TThreadPoolServer for a multithreaded server
213 #self.communicationServer = TServer.TThreadedServer(self.processor, self.transport, self.tfactory, self.pfactory)
214 self.communicationServer = TServer.TThreadPoolServer(self.processor, self.transport, self.tfactory, self.pfactory)
216 self.communicationServer.serve()
220 self.communicationHandler.openconnection()
221 except Thrift.TException, tx:
222 print '%s' % (tx.message)
224 if self.state == 'UNREGISTERED':
225 #prepare registration message
226 reg_msg = RegisterMessage()
227 reg_msg.domino_udid_desired = UDID_DESIRED
228 reg_msg.seq_no = self.seqno
229 reg_msg.ipaddr = netutil.get_ip()
230 reg_msg.tcpport = self.serviceport
231 reg_msg.supported_templates = LIST_SUPPORTED_TEMPLATES
233 reg_msg_r = self.sender().d_register(reg_msg)
234 print 'Registration Response:\n'
235 print 'Response Code: %d' % (reg_msg_r.responseCode)
236 print 'Response Comments:'
237 if reg_msg_r.comments:
238 print reg_msg_r.comments
240 if reg_msg_r.responseCode == SUCCESS:
241 self.state = 'REGISTERED'
242 self.UDID = reg_msg_r.domino_udid_assigned
244 #Handle registration failure here (possibly based on reponse comments)
247 self.seqno = self.seqno + 1
251 self.communicationHandler.closeconnection()
252 except Thrift.TException, tx:
253 print '%s' % (tx.message)
256 return self.communicationHandler.sender
259 print 'CLI Service is starting'
260 self.CLIservice.start()
261 #to wait until CLI service is finished
262 #self.CLIservice.join()
264 def set_serviceport(self, port):
265 self.serviceport = port
267 print self.serviceport
269 def set_dominoserver_ipaddr(self, ipaddr):
270 self.dominoserver_IP = ipaddr
272 print self.dominoserver_IP
275 client = DominoClient()
277 #process input arguments
279 opts, args = getopt.getopt(argv,"hc:p:i:",["conf=","port=","ipaddr="])
280 except getopt.GetoptError:
281 print 'DominoClient.py -c/--conf <configfile> -p/--port <socketport> -i/--ipaddr <IPaddr>'
283 for opt, arg in opts:
285 print 'DominoClient.py -c/--conf <configfile> -p/--port <socketport> -i/--ipaddr <IPaddr>'
287 elif opt in ("-c", "--conf"):
289 elif opt in ("-p", "--port"):
290 client.set_serviceport(int(arg))
291 elif opt in ("-i", "--ipaddr"):
292 client.set_dominoserver_ipaddr(arg)
294 #The client is starting
295 print 'Starting the client...'
298 client.start_communicationService()
300 if __name__ == "__main__":