blob: 9d59183d641d83a97b47522dd735d1a078dff430 [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
peustermbd44f4a2016-01-13 14:53:30 +010010logging.basicConfig(level=logging.INFO)
peusterm9c252b62016-01-06 16:59:53 +010011
12
13class ZeroRpcApiEndpoint(object):
peusterme4e89d32016-01-07 09:14:54 +010014 """
15 Simple API endpoint that offers a zerorpc-based
16 interface. This interface will be used by the
17 default command line client.
18 It can be used as a reference to implement
19 REST interfaces providing the same semantics,
20 like e.g. OpenStack compute API.
21 """
peusterm9c252b62016-01-06 16:59:53 +010022
23 def __init__(self, listenip, port):
24 self.dcs = {}
25 self.ip = listenip
26 self.port = port
27 logging.debug("Created API endpoint %s(%s:%d)" % (
28 self.__class__.__name__, self.ip, self.port))
29
30 def connectDatacenter(self, dc):
peusterma47db032016-02-04 14:55:29 +010031 self.dcs[dc.label] = dc
peusterm9c252b62016-01-06 16:59:53 +010032 logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % (
peusterma47db032016-02-04 14:55:29 +010033 dc.label, self.__class__.__name__, self.ip, self.port))
peusterm9c252b62016-01-06 16:59:53 +010034
35 def start(self):
36 thread = threading.Thread(target=self._api_server_thread, args=())
37 thread.daemon = True
38 thread.start()
39 logging.debug("Started API endpoint %s(%s:%d)" % (
40 self.__class__.__name__, self.ip, self.port))
41
42 def _api_server_thread(self):
43 s = zerorpc.Server(MultiDatacenterApi(self.dcs))
44 s.bind("tcp://%s:%d" % (self.ip, self.port))
45 s.run()
46
47
48class MultiDatacenterApi(object):
peusterme4e89d32016-01-07 09:14:54 +010049 """
50 Just pass through the corresponding request to the
51 selected data center. Do not implement provisioning
52 logic here because will will have multiple API
53 endpoint implementations at the end.
54 """
peusterm9c252b62016-01-06 16:59:53 +010055
56 def __init__(self, dcs):
57 self.dcs = dcs
58
stevenvanrossem994245b2016-05-04 12:36:57 +020059 def compute_action_start(self, dc_label, compute_name, image, network, command):
peusterm7f8e8402016-02-28 18:38:10 +010060 """
stevenvanrossem994245b2016-05-04 12:36:57 +020061 Start a new compute instance: A docker container (note: zerorpc does not support keyword arguments)
peusterm7f8e8402016-02-28 18:38:10 +010062 :param dc_label: name of the DC
63 :param compute_name: compute container name
64 :param image: image name
65 :param command: command to execute
stevenvanrossem14c89052016-04-10 23:49:59 +020066 :param network: list of all interface of the vnf, with their parameters (id=id1,ip=x.x.x.x/x),...
67 :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 +010068 """
peusterm4e98b632016-01-12 14:08:07 +010069 # TODO what to return UUID / given name / internal name ?
peusterm70baaf82016-01-06 17:14:40 +010070 logging.debug("RPC CALL: compute start")
peusterm7aae6852016-01-12 14:53:18 +010071 try:
peusterm53504942016-02-04 16:09:28 +010072 c = self.dcs.get(dc_label).startCompute(
stevenvanrossem8fbf9782016-02-17 11:40:23 +010073 compute_name, image=image, command=command, network=network)
stevenvanrosseme66ef122016-05-03 11:22:54 +020074 #return str(c.name)
75 # return docker inspect dict
76 return c.getStatus()
peusterm7aae6852016-01-12 14:53:18 +010077 except Exception as ex:
78 logging.exception("RPC error.")
79 return ex.message
peusterm9c252b62016-01-06 16:59:53 +010080
peusterm53504942016-02-04 16:09:28 +010081 def compute_action_stop(self, dc_label, compute_name):
peustermbd44f4a2016-01-13 14:53:30 +010082 logging.debug("RPC CALL: compute stop")
peusterm7aae6852016-01-12 14:53:18 +010083 try:
peusterm53504942016-02-04 16:09:28 +010084 return self.dcs.get(dc_label).stopCompute(compute_name)
peusterm7aae6852016-01-12 14:53:18 +010085 except Exception as ex:
86 logging.exception("RPC error.")
87 return ex.message
peusterm9c252b62016-01-06 16:59:53 +010088
peusterm53504942016-02-04 16:09:28 +010089 def compute_list(self, dc_label):
peustermbd44f4a2016-01-13 14:53:30 +010090 logging.debug("RPC CALL: compute list")
peusterm7aae6852016-01-12 14:53:18 +010091 try:
peusterm53504942016-02-04 16:09:28 +010092 if dc_label is None:
peusterm2ec74e12016-01-13 11:17:53 +010093 # return list with all compute nodes in all DCs
94 all_containers = []
95 for dc in self.dcs.itervalues():
96 all_containers += dc.listCompute()
97 return [(c.name, c.getStatus())
98 for c in all_containers]
99 else:
100 # return list of compute nodes for specified DC
101 return [(c.name, c.getStatus())
peusterm53504942016-02-04 16:09:28 +0100102 for c in self.dcs.get(dc_label).listCompute()]
peusterm7aae6852016-01-12 14:53:18 +0100103 except Exception as ex:
104 logging.exception("RPC error.")
105 return ex.message
peusterm4e98b632016-01-12 14:08:07 +0100106
peusterm53504942016-02-04 16:09:28 +0100107 def compute_status(self, dc_label, compute_name):
peustermbd44f4a2016-01-13 14:53:30 +0100108 logging.debug("RPC CALL: compute status")
peusterm7aae6852016-01-12 14:53:18 +0100109 try:
110 return self.dcs.get(
peusterm53504942016-02-04 16:09:28 +0100111 dc_label).containers.get(compute_name).getStatus()
peusterm7aae6852016-01-12 14:53:18 +0100112 except Exception as ex:
113 logging.exception("RPC error.")
114 return ex.message
peustermd313dc12016-02-04 15:36:02 +0100115
stevenvanrossem994245b2016-05-04 12:36:57 +0200116 def compute_profile(self, dc_label, compute_name, image, kwargs):
117 # note: zerorpc does not support keyword arguments
118
stevenvanrossem5b376412016-05-04 15:34:49 +0200119 ## VIM/dummy gatekeeper's tasks:
stevenvanrossem994245b2016-05-04 12:36:57 +0200120 # start vnf
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200121 vnf_status = self.compute_action_start( dc_label, compute_name, image,
stevenvanrossem994245b2016-05-04 12:36:57 +0200122 kwargs.get('network'),
123 kwargs.get('command'))
stevenvanrossem994245b2016-05-04 12:36:57 +0200124 # start traffic source (with fixed ip addres, no use for now...)
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200125 self.compute_action_start( dc_label, 'psrc', 'profile_source', [{'id':'output'}], None)
stevenvanrossem5b376412016-05-04 15:34:49 +0200126 # link vnf to traffic source
127 DCNetwork = self.dcs.get(dc_label).net
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200128 DCNetwork.setChain('psrc', compute_name,
129 vnf_src_interface='output',
130 vnf_dst_interface=kwargs.get('input'),
131 cmd='add-flow', weight=None)
stevenvanrossem5b376412016-05-04 15:34:49 +0200132
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200133 ## SSM/SP tasks:
134 # get monitor data and analyze
stevenvanrossem994245b2016-05-04 12:36:57 +0200135
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200136 # create table
stevenvanrossem994245b2016-05-04 12:36:57 +0200137
stevenvanrossemedcbeeb2016-05-04 17:28:08 +0200138 ## VIM/dummy gatekeeper's tasks:
139 # remove vnfs and chain
stevenvanrossem994245b2016-05-04 12:36:57 +0200140
141
peustermd313dc12016-02-04 15:36:02 +0100142 def datacenter_list(self):
143 logging.debug("RPC CALL: datacenter list")
144 try:
145 return [d.getStatus() for d in self.dcs.itervalues()]
146 except Exception as ex:
147 logging.exception("RPC error.")
148 return ex.message
peusterm53504942016-02-04 16:09:28 +0100149
150 def datacenter_status(self, dc_label):
151 logging.debug("RPC CALL: datacenter status")
152 try:
153 return self.dcs.get(dc_label).getStatus()
154 except Exception as ex:
155 logging.exception("RPC error.")
156 return ex.message
stevenvanrossem994245b2016-05-04 12:36:57 +0200157
158'''
159if __name__ == "__main__":
160 test = MultiDatacenterApi({})
161 test.compute_profile('dc1','vnf1', 'image',network='',command='test',other='other')
162'''
163