X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=osm_openvim%2Fopenflow_conn.py;fp=osm_openvim%2Fopenflow_conn.py;h=f42f4dcc2fc37f82ce29733350449a624fcae8ba;hb=9f6571090b203922cabb0382226be0fa48d6e046;hp=0000000000000000000000000000000000000000;hpb=ee19576ffab403bf0218974ed96c98dc0375b507;p=osm%2Fopenvim.git diff --git a/osm_openvim/openflow_conn.py b/osm_openvim/openflow_conn.py new file mode 100644 index 0000000..f42f4dc --- /dev/null +++ b/osm_openvim/openflow_conn.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- + +## +# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# This file is part of openmano +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: nfvlabs@tid.es +## +import logging +import base64 + +""" +vimconn implement an Abstract class for the vim connector plugins + with the definition of the method to be implemented. +""" +__author__ = "Alfonso Tierno, Leonardo Mirabal" +__date__ = "$16-oct-2015 11:09:29$" + + + +# Error variables +HTTP_Bad_Request = 400 +HTTP_Unauthorized = 401 +HTTP_Not_Found = 404 +HTTP_Method_Not_Allowed = 405 +HTTP_Request_Timeout = 408 +HTTP_Conflict = 409 +HTTP_Not_Implemented = 501 +HTTP_Service_Unavailable = 503 +HTTP_Internal_Server_Error = 500 + + +class OpenflowconnException(Exception): + """Common and base class Exception for all vimconnector exceptions""" + def __init__(self, message, http_code=HTTP_Bad_Request): + Exception.__init__(self, message) + self.http_code = http_code + + +class OpenflowconnConnectionException(OpenflowconnException): + """Connectivity error with the VIM""" + def __init__(self, message, http_code=HTTP_Service_Unavailable): + OpenflowconnException.__init__(self, message, http_code) + + +class OpenflowconnUnexpectedResponse(OpenflowconnException): + """Get an wrong response from VIM""" + def __init__(self, message, http_code=HTTP_Internal_Server_Error): + OpenflowconnException.__init__(self, message, http_code) + + +class OpenflowconnAuthException(OpenflowconnException): + """Invalid credentials or authorization to perform this action over the VIM""" + def __init__(self, message, http_code=HTTP_Unauthorized): + OpenflowconnException.__init__(self, message, http_code) + + +class OpenflowconnNotFoundException(OpenflowconnException): + """The item is not found at VIM""" + def __init__(self, message, http_code=HTTP_Not_Found): + OpenflowconnException.__init__(self, message, http_code) + + +class OpenflowconnConflictException(OpenflowconnException): + """There is a conflict, e.g. more item found than one""" + def __init__(self, message, http_code=HTTP_Conflict): + OpenflowconnException.__init__(self, message, http_code) + + +class OpenflowconnNotSupportedException(OpenflowconnException): + """The request is not supported by connector""" + def __init__(self, message, http_code=HTTP_Service_Unavailable): + OpenflowconnException.__init__(self, message, http_code) + + +class OpenflowconnNotImplemented(OpenflowconnException): + """The method is not implemented by the connected""" + def __init__(self, message, http_code=HTTP_Not_Implemented): + OpenflowconnException.__init__(self, message, http_code) + + +class OpenflowConn: + """ + Openflow controller connector abstract implementeation. + """ + def __init__(self, params): + self.name = "openflow_conector" + self.headers = {'content-type': 'application/json', 'Accept': 'application/json'} + self.auth = None + self.pp2ofi = {} # From Physical Port to OpenFlow Index + self.ofi2pp = {} # From OpenFlow Index to Physical Port + self.dpid = '00:01:02:03:04:05:06:07' + self.id = 'openflow:00:01:02:03:04:05:06:07' + self.rules = {} + self.url = "http://%s:%s" % ('localhost', str(8081)) + self.auth = base64.b64encode('of_user:of_password') + self.headers['Authorization'] = 'Basic ' + self.auth + self.logger = logging.getLogger('openflow_conn') + self.logger.setLevel(getattr(logging, params.get("of_debug", "ERROR"))) + self.ip_address = None + + def get_of_switches(self): + """" + Obtain a a list of switches or DPID detected by this controller + :return: list length, and a list where each element a tuple pair (DPID, IP address), text_error: if fails + """ + raise OpenflowconnNotImplemented("Should have implemented this") + + def obtain_port_correspondence(self): + """ + Obtain the correspondence between physical and openflow port names + :return: dictionary: with physical name as key, openflow name as value, error_text: if fails + """ + raise OpenflowconnNotImplemented("Should have implemented this") + + def get_of_rules(self, translate_of_ports=True): + """ + Obtain the rules inserted at openflow controller + :param translate_of_ports: if True it translates ports from openflow index to physical switch name + :return: dict if ok: with the rule name as key and value is another dictionary with the following content: + priority: rule priority + name: rule name (present also as the master dict key) + ingress_port: match input port of the rule + dst_mac: match destination mac address of the rule, can be missing or None if not apply + vlan_id: match vlan tag of the rule, can be missing or None if not apply + actions: list of actions, composed by a pair tuples: + (vlan, None/int): for stripping/setting a vlan tag + (out, port): send to this port + switch: DPID, all + text_error if fails + """ + raise OpenflowconnNotImplemented("Should have implemented this") + + def del_flow(self, flow_name): + """ + Delete all existing rules + :param flow_name: flow_name, this is the rule name + :return: None if ok, text_error if fails + """ + raise OpenflowconnNotImplemented("Should have implemented this") + + def new_flow(self, data): + """ + Insert a new static rule + :param data: dictionary with the following content: + priority: rule priority + name: rule name + ingress_port: match input port of the rule + dst_mac: match destination mac address of the rule, missing or None if not apply + vlan_id: match vlan tag of the rule, missing or None if not apply + actions: list of actions, composed by a pair tuples with these posibilities: + ('vlan', None/int): for stripping/setting a vlan tag + ('out', port): send to this port + :return: None if ok, text_error if fails + """ + raise OpenflowconnNotImplemented("Should have implemented this") + + def clear_all_flows(self): + """" + Delete all existing rules + :return: None if ok, text_error if fails + """ + raise OpenflowconnNotImplemented("Should have implemented this") + + +class OfTestConnector(OpenflowConn): + """ + This is a fake openflow connector for testing. + It does nothing and it is used for running openvim without an openflow controller + """ + + def __init__(self, params): + OpenflowConn.__init__(self, params) + + name = params.get("name", "test-ofc") + self.name = name + self.dpid = params.get("dpid") + self.rules = {} + self.logger = logging.getLogger('vim.OF.TEST') + self.logger.setLevel(getattr(logging, params.get("of_debug", "ERROR"))) + self.pp2ofi = {} + + def get_of_switches(self): + return () + + def obtain_port_correspondence(self): + return () + + def del_flow(self, flow_name): + if flow_name in self.rules: + self.logger.debug("del_flow OK") + del self.rules[flow_name] + return None + else: + self.logger.warning("del_flow not found") + raise OpenflowconnUnexpectedResponse("flow {} not found".format(flow_name)) + + def new_flow(self, data): + self.rules[data["name"]] = data + self.logger.debug("new_flow OK") + return None + + def get_of_rules(self, translate_of_ports=True): + return self.rules + + def clear_all_flows(self): + self.logger.debug("clear_all_flows OK") + self.rules = {} + return None