1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
27 vimconn implement an Abstract class for the vim connector plugins
28 with the definition of the method to be implemented.
30 __author__
= "Alfonso Tierno, Leonardo Mirabal"
31 __date__
= "$16-oct-2015 11:09:29$"
36 HTTP_Bad_Request
= 400
37 HTTP_Unauthorized
= 401
39 HTTP_Method_Not_Allowed
= 405
40 HTTP_Request_Timeout
= 408
42 HTTP_Not_Implemented
= 501
43 HTTP_Service_Unavailable
= 503
44 HTTP_Internal_Server_Error
= 500
47 class OpenflowconnException(Exception):
48 """Common and base class Exception for all vimconnector exceptions"""
49 def __init__(self
, message
, http_code
=HTTP_Bad_Request
):
50 Exception.__init
__(self
, message
)
51 self
.http_code
= http_code
54 class OpenflowconnConnectionException(OpenflowconnException
):
55 """Connectivity error with the VIM"""
56 def __init__(self
, message
, http_code
=HTTP_Service_Unavailable
):
57 OpenflowconnException
.__init
__(self
, message
, http_code
)
60 class OpenflowconnUnexpectedResponse(OpenflowconnException
):
61 """Get an wrong response from VIM"""
62 def __init__(self
, message
, http_code
=HTTP_Internal_Server_Error
):
63 OpenflowconnException
.__init
__(self
, message
, http_code
)
66 class OpenflowconnAuthException(OpenflowconnException
):
67 """Invalid credentials or authorization to perform this action over the VIM"""
68 def __init__(self
, message
, http_code
=HTTP_Unauthorized
):
69 OpenflowconnException
.__init
__(self
, message
, http_code
)
72 class OpenflowconnNotFoundException(OpenflowconnException
):
73 """The item is not found at VIM"""
74 def __init__(self
, message
, http_code
=HTTP_Not_Found
):
75 OpenflowconnException
.__init
__(self
, message
, http_code
)
78 class OpenflowconnConflictException(OpenflowconnException
):
79 """There is a conflict, e.g. more item found than one"""
80 def __init__(self
, message
, http_code
=HTTP_Conflict
):
81 OpenflowconnException
.__init
__(self
, message
, http_code
)
84 class OpenflowconnNotSupportedException(OpenflowconnException
):
85 """The request is not supported by connector"""
86 def __init__(self
, message
, http_code
=HTTP_Service_Unavailable
):
87 OpenflowconnException
.__init
__(self
, message
, http_code
)
90 class OpenflowconnNotImplemented(OpenflowconnException
):
91 """The method is not implemented by the connected"""
92 def __init__(self
, message
, http_code
=HTTP_Not_Implemented
):
93 OpenflowconnException
.__init
__(self
, message
, http_code
)
98 Openflow controller connector abstract implementeation.
100 def __init__(self
, params
):
101 self
.name
= "openflow_conector"
102 self
.headers
= {'content-type': 'application/json', 'Accept': 'application/json'}
104 self
.pp2ofi
= {} # From Physical Port to OpenFlow Index
105 self
.ofi2pp
= {} # From OpenFlow Index to Physical Port
106 self
.dpid
= '00:01:02:03:04:05:06:07'
107 self
.id = 'openflow:00:01:02:03:04:05:06:07'
109 self
.url
= "http://%s:%s" % ('localhost', str(8081))
110 self
.auth
= base64
.b64encode('of_user:of_password')
111 self
.headers
['Authorization'] = 'Basic ' + self
.auth
112 self
.logger
= logging
.getLogger('openflow_conn')
113 self
.logger
.setLevel(getattr(logging
, params
.get("of_debug", "ERROR")))
114 self
.ip_address
= None
116 def get_of_switches(self
):
118 Obtain a a list of switches or DPID detected by this controller
119 :return: list length, and a list where each element a tuple pair (DPID, IP address), text_error: if fails
121 raise OpenflowconnNotImplemented("Should have implemented this")
123 def obtain_port_correspondence(self
):
125 Obtain the correspondence between physical and openflow port names
126 :return: dictionary: with physical name as key, openflow name as value, error_text: if fails
128 raise OpenflowconnNotImplemented("Should have implemented this")
130 def get_of_rules(self
, translate_of_ports
=True):
132 Obtain the rules inserted at openflow controller
133 :param translate_of_ports: if True it translates ports from openflow index to physical switch name
134 :return: dict if ok: with the rule name as key and value is another dictionary with the following content:
135 priority: rule priority
136 name: rule name (present also as the master dict key)
137 ingress_port: match input port of the rule
138 dst_mac: match destination mac address of the rule, can be missing or None if not apply
139 vlan_id: match vlan tag of the rule, can be missing or None if not apply
140 actions: list of actions, composed by a pair tuples:
141 (vlan, None/int): for stripping/setting a vlan tag
142 (out, port): send to this port
146 raise OpenflowconnNotImplemented("Should have implemented this")
148 def del_flow(self
, flow_name
):
150 Delete all existing rules
151 :param flow_name: flow_name, this is the rule name
152 :return: None if ok, text_error if fails
154 raise OpenflowconnNotImplemented("Should have implemented this")
156 def new_flow(self
, data
):
158 Insert a new static rule
159 :param data: dictionary with the following content:
160 priority: rule priority
162 ingress_port: match input port of the rule
163 dst_mac: match destination mac address of the rule, missing or None if not apply
164 vlan_id: match vlan tag of the rule, missing or None if not apply
165 actions: list of actions, composed by a pair tuples with these posibilities:
166 ('vlan', None/int): for stripping/setting a vlan tag
167 ('out', port): send to this port
168 :return: None if ok, text_error if fails
170 raise OpenflowconnNotImplemented("Should have implemented this")
172 def clear_all_flows(self
):
174 Delete all existing rules
175 :return: None if ok, text_error if fails
177 raise OpenflowconnNotImplemented("Should have implemented this")
180 class OfTestConnector(OpenflowConn
):
182 This is a fake openflow connector for testing.
183 It does nothing and it is used for running openvim without an openflow controller
186 def __init__(self
, params
):
187 OpenflowConn
.__init
__(self
, params
)
189 name
= params
.get("name", "test-ofc")
191 self
.dpid
= params
.get("dpid")
193 self
.logger
= logging
.getLogger('vim.OF.TEST')
194 self
.logger
.setLevel(getattr(logging
, params
.get("of_debug", "ERROR")))
197 def get_of_switches(self
):
200 def obtain_port_correspondence(self
):
203 def del_flow(self
, flow_name
):
204 if flow_name
in self
.rules
:
205 self
.logger
.debug("del_flow OK")
206 del self
.rules
[flow_name
]
209 self
.logger
.warning("del_flow not found")
210 raise OpenflowconnUnexpectedResponse("flow {} not found".format(flow_name
))
212 def new_flow(self
, data
):
213 self
.rules
[data
["name"]] = data
214 self
.logger
.debug("new_flow OK")
217 def get_of_rules(self
, translate_of_ports
=True):
220 def clear_all_flows(self
):
221 self
.logger
.debug("clear_all_flows OK")