From: peusterm Date: Tue, 8 Mar 2016 09:11:48 +0000 (+0100) Subject: Re-structured API modules. Now prepared to have different kinds of cloud APIs. Added... X-Git-Tag: v3.1~165^2~3 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=53337bc9b5cd5b6c613453b04c4f9cd703a61344;p=osm%2Fvim-emu.git Re-structured API modules. Now prepared to have different kinds of cloud APIs. Added empty module for SONATA fake gatekeeper for y1 demo. --- diff --git a/src/emuvim/api/openstack/README.md b/src/emuvim/api/openstack/README.md new file mode 100644 index 0000000..596390e --- /dev/null +++ b/src/emuvim/api/openstack/README.md @@ -0,0 +1 @@ +This is a placeholder. This folder will contain a OpenStack/HEAT like interface to the emulator. \ No newline at end of file diff --git a/src/emuvim/api/sonata/__init__.py b/src/emuvim/api/sonata/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/emuvim/api/sonata/dummygatekeeper.py b/src/emuvim/api/sonata/dummygatekeeper.py new file mode 100644 index 0000000..e69de29 diff --git a/src/emuvim/api/zerorpc/__init__.py b/src/emuvim/api/zerorpc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/emuvim/api/zerorpc/compute.py b/src/emuvim/api/zerorpc/compute.py new file mode 100644 index 0000000..59b960c --- /dev/null +++ b/src/emuvim/api/zerorpc/compute.py @@ -0,0 +1,128 @@ +""" +Distributed Cloud Emulator (dcemulator) +(c) 2015 by Manuel Peuster +""" + +import logging +import threading +import zerorpc + +logging.basicConfig(level=logging.INFO) + + +class ZeroRpcApiEndpoint(object): + """ + Simple API endpoint that offers a zerorpc-based + interface. This interface will be used by the + default command line client. + It can be used as a reference to implement + REST interfaces providing the same semantics, + like e.g. OpenStack compute API. + """ + + def __init__(self, listenip, port): + self.dcs = {} + self.ip = listenip + self.port = port + logging.debug("Created API endpoint %s(%s:%d)" % ( + self.__class__.__name__, self.ip, self.port)) + + def connectDatacenter(self, dc): + self.dcs[dc.label] = dc + logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % ( + dc.label, self.__class__.__name__, self.ip, self.port)) + + def start(self): + thread = threading.Thread(target=self._api_server_thread, args=()) + thread.daemon = True + thread.start() + logging.debug("Started API endpoint %s(%s:%d)" % ( + self.__class__.__name__, self.ip, self.port)) + + def _api_server_thread(self): + s = zerorpc.Server(MultiDatacenterApi(self.dcs)) + s.bind("tcp://%s:%d" % (self.ip, self.port)) + s.run() + + +class MultiDatacenterApi(object): + """ + Just pass through the corresponding request to the + selected data center. Do not implement provisioning + logic here because will will have multiple API + endpoint implementations at the end. + """ + + def __init__(self, dcs): + self.dcs = dcs + + def compute_action_start(self, dc_label, compute_name, image, command, network): + """ + Start a new compute instance: A docker container + :param dc_label: name of the DC + :param compute_name: compute container name + :param image: image name + :param command: command to execute + :param network: + :return: networks list({"ip": "10.0.0.254/8"}, {"ip": "11.0.0.254/24"}) + """ + # TODO what to return UUID / given name / internal name ? + logging.debug("RPC CALL: compute start") + try: + c = self.dcs.get(dc_label).startCompute( + compute_name, image=image, command=command, network=network) + return str(c.name) + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + def compute_action_stop(self, dc_label, compute_name): + logging.debug("RPC CALL: compute stop") + try: + return self.dcs.get(dc_label).stopCompute(compute_name) + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + def compute_list(self, dc_label): + logging.debug("RPC CALL: compute list") + try: + if dc_label is None: + # return list with all compute nodes in all DCs + all_containers = [] + for dc in self.dcs.itervalues(): + all_containers += dc.listCompute() + return [(c.name, c.getStatus()) + for c in all_containers] + else: + # return list of compute nodes for specified DC + return [(c.name, c.getStatus()) + for c in self.dcs.get(dc_label).listCompute()] + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + def compute_status(self, dc_label, compute_name): + logging.debug("RPC CALL: compute status") + try: + return self.dcs.get( + dc_label).containers.get(compute_name).getStatus() + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + def datacenter_list(self): + logging.debug("RPC CALL: datacenter list") + try: + return [d.getStatus() for d in self.dcs.itervalues()] + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + def datacenter_status(self, dc_label): + logging.debug("RPC CALL: datacenter status") + try: + return self.dcs.get(dc_label).getStatus() + except Exception as ex: + logging.exception("RPC error.") + return ex.message diff --git a/src/emuvim/api/zerorpc/network.py b/src/emuvim/api/zerorpc/network.py new file mode 100644 index 0000000..f232166 --- /dev/null +++ b/src/emuvim/api/zerorpc/network.py @@ -0,0 +1,103 @@ +""" +Distributed Cloud Emulator (dcemulator) +""" + +import logging +import threading +import zerorpc + + +logging.basicConfig(level=logging.INFO) + + +class ZeroRpcApiEndpointDCNetwork(object): + """ + Simple API endpoint that offers a zerorpc-based + interface. This interface will be used by the + default command line client. + It can be used as a reference to implement + REST interfaces providing the same semantics, + like e.g. OpenStack compute API. + """ + + def __init__(self, listenip, port, DCNetwork=None): + if DCNetwork : + self.connectDCNetwork(DCNetwork) + self.ip = listenip + self.port = port + logging.debug("Created monitoring API endpoint %s(%s:%d)" % ( + self.__class__.__name__, self.ip, self.port)) + + def connectDCNetwork(self, net): + self.net = net + logging.info("Connected DCNetwork to API endpoint %s(%s:%d)" % ( + self.__class__.__name__, self.ip, self.port)) + + def start(self): + thread = threading.Thread(target=self._api_server_thread, args=()) + thread.daemon = True + thread.start() + logging.debug("Started API endpoint %s(%s:%d)" % ( + self.__class__.__name__, self.ip, self.port)) + + def _api_server_thread(self): + s = zerorpc.Server(DCNetworkApi(self.net)) + s.bind("tcp://%s:%d" % (self.ip, self.port)) + s.run() + + def stop(self): + logging.info("Stop the monitoring API endpoint") + return + + +class DCNetworkApi(object): + """ + The networking and monitoring commands need the scope of the + whole DC network to find the requested vnf. So this API is intended + to work with a DCNetwork. + Just pass through the corresponding request to the + selected data center network. Do not implement provisioning + logic here because will will have multiple API + endpoint implementations at the end. + """ + + def __init__(self, net): + self.net = net + + def network_action_start(self, vnf_src_name, vnf_dst_name): + # call DCNetwork method, not really datacenter specific API for now... + # provided dc name needs to be part of API endpoint + # no check if vnfs are really connected to this datacenter... + logging.debug("RPC CALL: network chain start") + try: + c = self.net.setChain( + vnf_src_name, vnf_dst_name) + return str(c) + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + def network_action_stop(self, vnf_src_name, vnf_dst_name): + # call DCNetwork method, not really datacenter specific API for now... + # provided dc name needs to be part of API endpoint + # no check if vnfs are really connected to this datacenter... + logging.debug("RPC CALL: network chain stop") + try: + c = self.net.setChain( + vnf_src_name, vnf_dst_name, cmd='del-flows') + return c + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + # get egress(default) or ingress rate of a vnf + def monitor_get_rate(self, vnf_name, direction): + logging.debug("RPC CALL: get rate") + try: + c = self.net.monitor_agent.get_rate(vnf_name, direction) + return c + except Exception as ex: + logging.exception("RPC error.") + return ex.message + + diff --git a/src/emuvim/api/zerorpcapi.py b/src/emuvim/api/zerorpcapi.py deleted file mode 100755 index 59b960c..0000000 --- a/src/emuvim/api/zerorpcapi.py +++ /dev/null @@ -1,128 +0,0 @@ -""" -Distributed Cloud Emulator (dcemulator) -(c) 2015 by Manuel Peuster -""" - -import logging -import threading -import zerorpc - -logging.basicConfig(level=logging.INFO) - - -class ZeroRpcApiEndpoint(object): - """ - Simple API endpoint that offers a zerorpc-based - interface. This interface will be used by the - default command line client. - It can be used as a reference to implement - REST interfaces providing the same semantics, - like e.g. OpenStack compute API. - """ - - def __init__(self, listenip, port): - self.dcs = {} - self.ip = listenip - self.port = port - logging.debug("Created API endpoint %s(%s:%d)" % ( - self.__class__.__name__, self.ip, self.port)) - - def connectDatacenter(self, dc): - self.dcs[dc.label] = dc - logging.info("Connected DC(%s) to API endpoint %s(%s:%d)" % ( - dc.label, self.__class__.__name__, self.ip, self.port)) - - def start(self): - thread = threading.Thread(target=self._api_server_thread, args=()) - thread.daemon = True - thread.start() - logging.debug("Started API endpoint %s(%s:%d)" % ( - self.__class__.__name__, self.ip, self.port)) - - def _api_server_thread(self): - s = zerorpc.Server(MultiDatacenterApi(self.dcs)) - s.bind("tcp://%s:%d" % (self.ip, self.port)) - s.run() - - -class MultiDatacenterApi(object): - """ - Just pass through the corresponding request to the - selected data center. Do not implement provisioning - logic here because will will have multiple API - endpoint implementations at the end. - """ - - def __init__(self, dcs): - self.dcs = dcs - - def compute_action_start(self, dc_label, compute_name, image, command, network): - """ - Start a new compute instance: A docker container - :param dc_label: name of the DC - :param compute_name: compute container name - :param image: image name - :param command: command to execute - :param network: - :return: networks list({"ip": "10.0.0.254/8"}, {"ip": "11.0.0.254/24"}) - """ - # TODO what to return UUID / given name / internal name ? - logging.debug("RPC CALL: compute start") - try: - c = self.dcs.get(dc_label).startCompute( - compute_name, image=image, command=command, network=network) - return str(c.name) - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - def compute_action_stop(self, dc_label, compute_name): - logging.debug("RPC CALL: compute stop") - try: - return self.dcs.get(dc_label).stopCompute(compute_name) - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - def compute_list(self, dc_label): - logging.debug("RPC CALL: compute list") - try: - if dc_label is None: - # return list with all compute nodes in all DCs - all_containers = [] - for dc in self.dcs.itervalues(): - all_containers += dc.listCompute() - return [(c.name, c.getStatus()) - for c in all_containers] - else: - # return list of compute nodes for specified DC - return [(c.name, c.getStatus()) - for c in self.dcs.get(dc_label).listCompute()] - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - def compute_status(self, dc_label, compute_name): - logging.debug("RPC CALL: compute status") - try: - return self.dcs.get( - dc_label).containers.get(compute_name).getStatus() - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - def datacenter_list(self): - logging.debug("RPC CALL: datacenter list") - try: - return [d.getStatus() for d in self.dcs.itervalues()] - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - def datacenter_status(self, dc_label): - logging.debug("RPC CALL: datacenter status") - try: - return self.dcs.get(dc_label).getStatus() - except Exception as ex: - logging.exception("RPC error.") - return ex.message diff --git a/src/emuvim/api/zerorpcapi_DCNetwork.py b/src/emuvim/api/zerorpcapi_DCNetwork.py deleted file mode 100755 index 27527aa..0000000 --- a/src/emuvim/api/zerorpcapi_DCNetwork.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -Distributed Cloud Emulator (dcemulator) -(c) 2015 by Manuel Peuster -""" - -import logging -import threading -import zerorpc - - -logging.basicConfig(level=logging.INFO) - - -class ZeroRpcApiEndpointDCNetwork(object): - """ - Simple API endpoint that offers a zerorpc-based - interface. This interface will be used by the - default command line client. - It can be used as a reference to implement - REST interfaces providing the same semantics, - like e.g. OpenStack compute API. - """ - - def __init__(self, listenip, port, DCNetwork=None): - if DCNetwork : - self.connectDCNetwork(DCNetwork) - self.ip = listenip - self.port = port - logging.debug("Created monitoring API endpoint %s(%s:%d)" % ( - self.__class__.__name__, self.ip, self.port)) - - def connectDCNetwork(self, net): - self.net = net - logging.info("Connected DCNetwork to API endpoint %s(%s:%d)" % ( - self.__class__.__name__, self.ip, self.port)) - - def start(self): - thread = threading.Thread(target=self._api_server_thread, args=()) - thread.daemon = True - thread.start() - logging.debug("Started API endpoint %s(%s:%d)" % ( - self.__class__.__name__, self.ip, self.port)) - - def _api_server_thread(self): - s = zerorpc.Server(DCNetworkApi(self.net)) - s.bind("tcp://%s:%d" % (self.ip, self.port)) - s.run() - - def stop(self): - logging.info("Stop the monitoring API endpoint") - return - - -class DCNetworkApi(object): - """ - The networking and monitoring commands need the scope of the - whole DC network to find the requested vnf. So this API is intended - to work with a DCNetwork. - Just pass through the corresponding request to the - selected data center network. Do not implement provisioning - logic here because will will have multiple API - endpoint implementations at the end. - """ - - def __init__(self, net): - self.net = net - - def network_action_start(self, vnf_src_name, vnf_dst_name): - # call DCNetwork method, not really datacenter specific API for now... - # provided dc name needs to be part of API endpoint - # no check if vnfs are really connected to this datacenter... - logging.debug("RPC CALL: network chain start") - try: - c = self.net.setChain( - vnf_src_name, vnf_dst_name) - return str(c) - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - def network_action_stop(self, vnf_src_name, vnf_dst_name): - # call DCNetwork method, not really datacenter specific API for now... - # provided dc name needs to be part of API endpoint - # no check if vnfs are really connected to this datacenter... - logging.debug("RPC CALL: network chain stop") - try: - c = self.net.setChain( - vnf_src_name, vnf_dst_name, cmd='del-flows') - return c - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - # get egress(default) or ingress rate of a vnf - def monitor_get_rate(self, vnf_name, direction): - logging.debug("RPC CALL: get rate") - try: - c = self.net.monitor_agent.get_rate(vnf_name, direction) - return c - except Exception as ex: - logging.exception("RPC error.") - return ex.message - - diff --git a/src/emuvim/examples/simple_topology.py b/src/emuvim/examples/simple_topology.py index 8f14b69..eb52cb1 100755 --- a/src/emuvim/examples/simple_topology.py +++ b/src/emuvim/examples/simple_topology.py @@ -19,8 +19,8 @@ script. import logging from mininet.log import setLogLevel from emuvim.dcemulator.net import DCNetwork -from emuvim.api.zerorpcapi import ZeroRpcApiEndpoint -from emuvim.api.zerorpcapi_DCNetwork import ZeroRpcApiEndpointDCNetwork +from emuvim.api.zerorpc.compute import ZeroRpcApiEndpoint +from emuvim.api.zerorpc.network import ZeroRpcApiEndpointDCNetwork logging.basicConfig(level=logging.INFO) diff --git a/src/emuvim/examples/sonata_y1_demo_topology_1.py b/src/emuvim/examples/sonata_y1_demo_topology_1.py index 1588190..5145543 100644 --- a/src/emuvim/examples/sonata_y1_demo_topology_1.py +++ b/src/emuvim/examples/sonata_y1_demo_topology_1.py @@ -7,7 +7,7 @@ A simple topology with two PoPs for the y1 demo story board. import logging from mininet.log import setLogLevel from emuvim.dcemulator.net import DCNetwork -from emuvim.api.zerorpcapi import ZeroRpcApiEndpoint +from emuvim.api.zerorpc.compute import ZeroRpcApiEndpoint logging.basicConfig(level=logging.INFO)