See the License for the specific language governing permissions and
limitations under the License.
-Neither the name of the SONATA-NFV [, ANY ADDITIONAL AFFILIATION]
+Neither the name of the SONATA-NFV, Paderborn University
nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
acknowledge the contributions of their colleagues of the SONATA
partner consortium (www.sonata-nfv.eu).
"""
-from mininet.node import Docker
+from mininet.node import Docker, OVSBridge
from mininet.link import Link
from emuvim.dcemulator.resourcemodel import NotEnoughResourcesAvailable
import logging
-import time
-import json
+
LOG = logging.getLogger("dcemulator.node")
LOG.setLevel(logging.DEBUG)
DCDPID_BASE = 1000 # start of switch dpid's used for data center switches
+EXTSAPDPID_BASE = 2000 # start of switch dpid's used for external SAP switches
class EmulatorCompute(Docker):
"""
vnf_interface = str(i)
dc_port_name = self.datacenter.net.find_connected_dc_interface(vnf_name, vnf_interface)
# format list of tuples (name, Ip, MAC, isUp, status, dc_portname)
- intf_dict = {'intf_name': str(i), 'ip': i.IP(), 'mac': i.MAC(), 'up': i.isUp(), 'status': i.status(), 'dc_portname': dc_port_name}
+ intf_dict = {'intf_name': str(i), 'ip': "{0}/{1}".format(i.IP(), i.prefixLen), 'netmask': i.prefixLen, 'mac': i.MAC(), 'up': i.isUp(), 'status': i.status(), 'dc_portname': dc_port_name}
networkStatusList.append(intf_dict)
return networkStatusList
return status
+class EmulatorExtSAP(object):
+ """
+ Emulator specific class that defines an external service access point (SAP) for the service.
+ Inherits from Containernet's OVSBridge class.
+ Represents a single OVS switch connected to a (logical)
+ data center.
+ We can add emulator specific helper functions to it.
+ """
+
+ def __init__(self, sap_name, sap_net, datacenter, **kwargs):
+
+ self.datacenter = datacenter # pointer to current DC
+ self.net = self.datacenter.net
+ self.name = sap_name
+
+ LOG.debug("Starting ext SAP instance %r in data center %r" % (sap_name, str(self.datacenter)))
+
+ # create SAP as separate OVS switch with an assigned ip address
+ self.ip = str(sap_net[1]) + '/' + str(sap_net.prefixlen)
+ self.subnet = sap_net
+ # allow connection to the external internet through the host
+ params = dict(NAT=True)
+ self.switch = self.net.addExtSAP(sap_name, self.ip, dpid=hex(self._get_next_extSAP_dpid())[2:], **params)
+ self.switch.start()
+
+ def _get_next_extSAP_dpid(self):
+ global EXTSAPDPID_BASE
+ EXTSAPDPID_BASE += 1
+ return EXTSAPDPID_BASE
+
+ def getNetworkStatus(self):
+ """
+ Helper method to receive information about the virtual networks
+ this compute instance is connected to.
+ """
+ # get all links and find dc switch interface
+ networkStatusList = []
+ for i in self.switch.intfList():
+ vnf_name = self.name
+ vnf_interface = str(i)
+ if vnf_interface == 'lo':
+ continue
+ dc_port_name = self.datacenter.net.find_connected_dc_interface(vnf_name, vnf_interface)
+ # format list of tuples (name, Ip, MAC, isUp, status, dc_portname)
+ intf_dict = {'intf_name': str(i), 'ip': self.ip, 'netmask': i.prefixLen, 'mac': i.MAC(), 'up': i.isUp(), 'status': i.status(), 'dc_portname': dc_port_name}
+ networkStatusList.append(intf_dict)
+
+ return networkStatusList
+
+ def getStatus(self):
+ return {
+ "name": self.switch.name,
+ "datacenter": self.datacenter.name,
+ "network": self.getNetworkStatus()
+ }
+
class Datacenter(object):
"""
Represents a logical data center to which compute resources
self.switch = None
# keep track of running containers
self.containers = {}
+ # keep track of attached external access points
+ self.extSAPs = {}
# pointer to assigned resource model
self._resource_model = None
def start(self):
pass
- def startCompute(self, name, image=None, command=None, network=None, flavor_name="tiny", **params):
+ def startCompute(self, name, image=None, command=None, network=None, flavor_name="tiny", properties=dict(), **params):
"""
Create a new container as compute resource and connect it to this
data center.
:param command: command (string)
:param network: networks list({"ip": "10.0.0.254/8"}, {"ip": "11.0.0.254/24"})
:param flavor_name: name of the flavor for this compute container
+ :param properties: dictionary of properties (key-value) that will be passed as environment variables
:return:
"""
assert name is not None
params['cpu_period'] = self.net.cpu_period
params['cpu_quota'] = self.net.cpu_period * float(cpu_percentage)
+ env = properties
+ properties['VNF_NAME'] = name
# create the container
d = self.net.addDocker(
"%s" % (name),
dcmd=command,
datacenter=self,
flavor_name=flavor_name,
- environment = {'VNF_NAME':name},
+ environment = env,
**params
)
self.net.addLink(d, self.switch, params1=nw, cls=Link, intfName1=nw.get('id'))
# do bookkeeping
self.containers[name] = d
+
return d # we might use UUIDs for naming later on
def stopCompute(self, name):
return True
- def attachExternalSAP(self, sap_name, sap_ip):
- # create SAP as OVS internal interface
- sap_intf = self.switch.attachInternalIntf(sap_name, sap_ip)
-
- # add this as a link to the DCnetwork graph, so it is available for routing
- attr_dict2 = {'src_port_id': sap_name, 'src_port_nr': None,
- 'src_port_name': sap_name,
- 'dst_port_id': self.switch.ports[sap_intf], 'dst_port_nr': self.switch.ports[sap_intf],
- 'dst_port_name': sap_intf.name}
- self.net.DCNetwork_graph.add_edge(sap_name, self.switch.name, attr_dict=attr_dict2)
-
- attr_dict2 = {'dst_port_id': sap_name, 'dst_port_nr': None,
- 'dst_port_name': sap_name,
- 'src_port_id': self.switch.ports[sap_intf], 'src_port_nr': self.switch.ports[sap_intf],
- 'src_port_name': sap_intf.name}
- self.net.DCNetwork_graph.add_edge(self.switch.name, sap_name, attr_dict=attr_dict2)
+ def attachExternalSAP(self, sap_name, sap_net, **params):
+ extSAP = EmulatorExtSAP(sap_name, sap_net, self, **params)
+ # link SAP to the DC switch
+ self.net.addLink(extSAP.switch, self.switch, cls=Link)
+ self.extSAPs[sap_name] = extSAP
+ def removeExternalSAP(self, sap_name):
+ sap_switch = self.extSAPs[sap_name].switch
+ #sap_switch = self.net.getNodeByName(sap_name)
+ # remove link of SAP to the DC switch
+ self.net.removeLink(link=None, node1=sap_switch, node2=self.switch)
+ self.net.removeExtSAP(sap_name)
+ del self.extSAPs[sap_name]
def listCompute(self):
"""
"""
return list(self.containers.itervalues())
+ def listExtSAPs(self):
+ """
+ Return a list of all external SAPs assigned to this
+ data center.
+ """
+ return list(self.extSAPs.itervalues())
+
def getStatus(self):
"""
Return a dict with status information about this DC.
"""
+ container_list = [name for name in self.containers]
+ ext_saplist = [sap_name for sap_name in self.extSAPs]
return {
"label": self.label,
"internalname": self.name,
"switch": self.switch.name,
"n_running_containers": len(self.containers),
- "metadata": self.metadata
+ "metadata": self.metadata,
+ "vnf_list" : container_list,
+ "ext SAP list" : ext_saplist
}
def assignResourceModel(self, rm):