blob: 4815fa7ab85b46f4f0a3177dcbfd47b0a3371b75 [file] [log] [blame]
peusterm9c252b62016-01-06 16:59:53 +01001"""
2Distributed Cloud Emulator (dcemulator)
3(c) 2015 by Manuel Peuster <manuel.peuster@upb.de>
4"""
5
6import logging
7import threading
8import zerorpc
9
stevenvanrossem307aa1f2016-05-06 10:35:15 +020010import paramiko
11import ipaddress
12
peustermbd44f4a2016-01-13 14:53:30 +010013logging.basicConfig(level=logging.INFO)
peusterm9c252b62016-01-06 16:59:53 +010014
15
16class ZeroRpcApiEndpoint(object):
peusterme4e89d32016-01-07 09:14:54 +010017 """
18 Simple API endpoint that offers a zerorpc-based
19 interface. This interface will be used by the
20 default command line client.
21 It can be used as a reference to implement
22 REST interfaces providing the same semantics,
23 like e.g. OpenStack compute API.
24 """
peusterm9c252b62016-01-06 16:59:53 +010025
26 def __init__(self, listenip, port):
27 self.dcs = {}
28 self.ip = listenip
29 self.port = port
30 logging.debug("Created API endpoint %s(%s:%d)" % (
31 self.__class__.__name__, self.ip, self.port))
32
33 def connectDatacenter(self, dc):
peusterma47db032016-02-04 14:55:29 +010034 self.dcs[dc.label] = dc
peusterm9c252b62016-01-06 16:59:53 +010035 logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % (
peusterma47db032016-02-04 14:55:29 +010036 dc.label, self.__class__.__name__, self.ip, self.port))
peusterm9c252b62016-01-06 16:59:53 +010037
38 def start(self):
39 thread = threading.Thread(target=self._api_server_thread, args=())
40 thread.daemon = True
41 thread.start()
42 logging.debug("Started API endpoint %s(%s:%d)" % (
43 self.__class__.__name__, self.ip, self.port))
44
45 def _api_server_thread(self):
46 s = zerorpc.Server(MultiDatacenterApi(self.dcs))
47 s.bind("tcp://%s:%d" % (self.ip, self.port))
48 s.run()
49
50
51class MultiDatacenterApi(object):
peusterme4e89d32016-01-07 09:14:54 +010052 """
53 Just pass through the corresponding request to the
54 selected data center. Do not implement provisioning
55 logic here because will will have multiple API
56 endpoint implementations at the end.
57 """
peusterm9c252b62016-01-06 16:59:53 +010058
59 def __init__(self, dcs):
60 self.dcs = dcs
61
stevenvanrossem994245b2016-05-04 12:36:57 +020062 def compute_action_start(self, dc_label, compute_name, image, network, command):
peusterm7f8e8402016-02-28 18:38:10 +010063 """
stevenvanrossem994245b2016-05-04 12:36:57 +020064 Start a new compute instance: A docker container (note: zerorpc does not support keyword arguments)
peusterm7f8e8402016-02-28 18:38:10 +010065 :param dc_label: name of the DC
66 :param compute_name: compute container name
67 :param image: image name
68 :param command: command to execute
stevenvanrossem14c89052016-04-10 23:49:59 +020069 :param network: list of all interface of the vnf, with their parameters (id=id1,ip=x.x.x.x/x),...
70 :return: networks list({"id":"input","ip": "10.0.0.254/8"}, {"id":"output","ip": "11.0.0.254/24"})
peusterm7f8e8402016-02-28 18:38:10 +010071 """
peusterm4e98b632016-01-12 14:08:07 +010072 # TODO what to return UUID / given name / internal name ?
peusterm70baaf82016-01-06 17:14:40 +010073 logging.debug("RPC CALL: compute start")
peusterm7aae6852016-01-12 14:53:18 +010074 try:
peusterm53504942016-02-04 16:09:28 +010075 c = self.dcs.get(dc_label).startCompute(
stevenvanrossem8fbf9782016-02-17 11:40:23 +010076 compute_name, image=image, command=command, network=network)
stevenvanrosseme66ef122016-05-03 11:22:54 +020077 #return str(c.name)
78 # return docker inspect dict
79 return c.getStatus()
peusterm7aae6852016-01-12 14:53:18 +010080 except Exception as ex:
81 logging.exception("RPC error.")
82 return ex.message
peusterm9c252b62016-01-06 16:59:53 +010083
peusterm53504942016-02-04 16:09:28 +010084 def compute_action_stop(self, dc_label, compute_name):
peustermbd44f4a2016-01-13 14:53:30 +010085 logging.debug("RPC CALL: compute stop")
peusterm7aae6852016-01-12 14:53:18 +010086 try:
peusterm53504942016-02-04 16:09:28 +010087 return self.dcs.get(dc_label).stopCompute(compute_name)
peusterm7aae6852016-01-12 14:53:18 +010088 except Exception as ex:
89 logging.exception("RPC error.")
90 return ex.message
peusterm9c252b62016-01-06 16:59:53 +010091
peusterm53504942016-02-04 16:09:28 +010092 def compute_list(self, dc_label):
peustermbd44f4a2016-01-13 14:53:30 +010093 logging.debug("RPC CALL: compute list")
peusterm7aae6852016-01-12 14:53:18 +010094 try:
peusterm53504942016-02-04 16:09:28 +010095 if dc_label is None:
peusterm2ec74e12016-01-13 11:17:53 +010096 # return list with all compute nodes in all DCs
97 all_containers = []
98 for dc in self.dcs.itervalues():
99 all_containers += dc.listCompute()
100 return [(c.name, c.getStatus())
101 for c in all_containers]
102 else:
103 # return list of compute nodes for specified DC
104 return [(c.name, c.getStatus())
peusterm53504942016-02-04 16:09:28 +0100105 for c in self.dcs.get(dc_label).listCompute()]
peusterm7aae6852016-01-12 14:53:18 +0100106 except Exception as ex:
107 logging.exception("RPC error.")
108 return ex.message
peusterm4e98b632016-01-12 14:08:07 +0100109
peusterm53504942016-02-04 16:09:28 +0100110 def compute_status(self, dc_label, compute_name):
peustermbd44f4a2016-01-13 14:53:30 +0100111 logging.debug("RPC CALL: compute status")
peusterm7aae6852016-01-12 14:53:18 +0100112 try:
113 return self.dcs.get(
peusterm53504942016-02-04 16:09:28 +0100114 dc_label).containers.get(compute_name).getStatus()
peusterm7aae6852016-01-12 14:53:18 +0100115 except Exception as ex:
116 logging.exception("RPC error.")
117 return ex.message
peustermd313dc12016-02-04 15:36:02 +0100118
stevenvanrossem994245b2016-05-04 12:36:57 +0200119 def compute_profile(self, dc_label, compute_name, image, kwargs):
120 # note: zerorpc does not support keyword arguments
121
stevenvanrossem5b376412016-05-04 15:34:49 +0200122 ## VIM/dummy gatekeeper's tasks:
stevenvanrossem994245b2016-05-04 12:36:57 +0200123 # start vnf
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200124 vnf_status = self.compute_action_start( dc_label, compute_name, image,
stevenvanrossem994245b2016-05-04 12:36:57 +0200125 kwargs.get('network'),
126 kwargs.get('command'))
stevenvanrossem994245b2016-05-04 12:36:57 +0200127 # start traffic source (with fixed ip addres, no use for now...)
stevenvanrossem307aa1f2016-05-06 10:35:15 +0200128 psrc_status = self.compute_action_start( dc_label, 'psrc', 'profile_source', [{'id':'output'}], None)
stevenvanrossem5b376412016-05-04 15:34:49 +0200129 # link vnf to traffic source
130 DCNetwork = self.dcs.get(dc_label).net
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200131 DCNetwork.setChain('psrc', compute_name,
132 vnf_src_interface='output',
133 vnf_dst_interface=kwargs.get('input'),
134 cmd='add-flow', weight=None)
stevenvanrossem5b376412016-05-04 15:34:49 +0200135
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200136 ## SSM/SP tasks:
stevenvanrossem307aa1f2016-05-06 10:35:15 +0200137 # start traffic generation
138 for nw in psrc_status.get('network'):
139 if nw.get('intf_name') == 'output':
140 psrc_output_ip = unicode(nw['ip'])
141 break
142 dummy_iperf_server_ip = ipaddress.IPv4Address(psrc_output_ip) + 1
143 iperf_cmd = 'iperf -c {0} -u -l18 -b10M -t1000 &'.format(dummy_iperf_server_ip)
144
145 psrc_mgmt_ip = psrc_status['docker_network']
146 psrc_user='root'
147 psrc_passw='root'
148
149 # use ssh login when starting command externally
150 ret = self.dcs.get(dc_label).containers.get('psrc').pexec(iperf_cmd)
151 logging.info(ret)
152 self.dcs.get(dc_label).containers.get('psrc').monitor()
153
154 #ssh does not work when exectuted via zerorpc command
155 #psrc_mgmt_ip = '172.17.0.3'
156 #ssh = paramiko.SSHClient()
157 #ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
158 #ssh.connect(psrc_mgmt_ip, username='steven', password='test')
159 #ssh.connect(psrc_mgmt_ip, username='root', password='root')
160
161 #iperf_cmd = 'iperf -c {0} -u -l18 -b10M -t1000'.format(dummy_iperf_server_ip)
162 #stdin, stdout, stderr = ssh.exec_command(iperf_cmd)
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200163 # get monitor data and analyze
stevenvanrossem994245b2016-05-04 12:36:57 +0200164
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200165 # create table
stevenvanrossem994245b2016-05-04 12:36:57 +0200166
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200167 ## VIM/dummy gatekeeper's tasks:
168 # remove vnfs and chain
stevenvanrossem994245b2016-05-04 12:36:57 +0200169
170
peustermd313dc12016-02-04 15:36:02 +0100171 def datacenter_list(self):
172 logging.debug("RPC CALL: datacenter list")
173 try:
174 return [d.getStatus() for d in self.dcs.itervalues()]
175 except Exception as ex:
176 logging.exception("RPC error.")
177 return ex.message
peusterm53504942016-02-04 16:09:28 +0100178
179 def datacenter_status(self, dc_label):
180 logging.debug("RPC CALL: datacenter status")
181 try:
182 return self.dcs.get(dc_label).getStatus()
183 except Exception as ex:
184 logging.exception("RPC error.")
185 return ex.message
stevenvanrossem994245b2016-05-04 12:36:57 +0200186
187'''
188if __name__ == "__main__":
189 test = MultiDatacenterApi({})
190 test.compute_profile('dc1','vnf1', 'image',network='',command='test',other='other')
191'''
192