setup.py fix for non py files during installation
[osm/openvim.git] / openflow_conn.py
1 # -*- coding: utf-8 -*-
2
3 ##
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
6 # All Rights Reserved.
7 #
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
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
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
18 # under the License.
19 #
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
22 ##
23 import logging
24 import base64
25
26 """
27 vimconn implement an Abstract class for the vim connector plugins
28 with the definition of the method to be implemented.
29 """
30 __author__ = "Alfonso Tierno, Leonardo Mirabal"
31 __date__ = "$16-oct-2015 11:09:29$"
32
33
34
35 # Error variables
36 HTTP_Bad_Request = 400
37 HTTP_Unauthorized = 401
38 HTTP_Not_Found = 404
39 HTTP_Method_Not_Allowed = 405
40 HTTP_Request_Timeout = 408
41 HTTP_Conflict = 409
42 HTTP_Not_Implemented = 501
43 HTTP_Service_Unavailable = 503
44 HTTP_Internal_Server_Error = 500
45
46
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
52
53
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)
58
59
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)
64
65
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)
70
71
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)
76
77
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)
82
83
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)
88
89
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)
94
95
96 class OpenflowConn:
97 """
98 Openflow controller connector abstract implementeation.
99 """
100 def __init__(self, params):
101 self.name = "openflow_conector"
102 self.headers = {'content-type': 'application/json', 'Accept': 'application/json'}
103 self.auth = None
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'
108 self.rules = {}
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
115
116 def get_of_switches(self):
117 """"
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
120 """
121 raise OpenflowconnNotImplemented("Should have implemented this")
122
123 def obtain_port_correspondence(self):
124 """
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
127 """
128 raise OpenflowconnNotImplemented("Should have implemented this")
129
130 def get_of_rules(self, translate_of_ports=True):
131 """
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
143 switch: DPID, all
144 text_error if fails
145 """
146 raise OpenflowconnNotImplemented("Should have implemented this")
147
148 def del_flow(self, flow_name):
149 """
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
153 """
154 raise OpenflowconnNotImplemented("Should have implemented this")
155
156 def new_flow(self, data):
157 """
158 Insert a new static rule
159 :param data: dictionary with the following content:
160 priority: rule priority
161 name: rule name
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
169 """
170 raise OpenflowconnNotImplemented("Should have implemented this")
171
172 def clear_all_flows(self):
173 """"
174 Delete all existing rules
175 :return: None if ok, text_error if fails
176 """
177 raise OpenflowconnNotImplemented("Should have implemented this")
178
179
180 class OfTestConnector(OpenflowConn):
181 """
182 This is a fake openflow connector for testing.
183 It does nothing and it is used for running openvim without an openflow controller
184 """
185
186 def __init__(self, params):
187 OpenflowConn.__init__(self, params)
188
189 name = params.get("name", "test-ofc")
190 self.name = name
191 self.dpid = params.get("dpid")
192 self.rules = {}
193 self.logger = logging.getLogger('vim.OF.TEST')
194 self.logger.setLevel(getattr(logging, params.get("of_debug", "ERROR")))
195 self.pp2ofi = {}
196
197 def get_of_switches(self):
198 return ()
199
200 def obtain_port_correspondence(self):
201 return ()
202
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]
207 return None
208 else:
209 self.logger.warning("del_flow not found")
210 raise OpenflowconnUnexpectedResponse("flow {} not found".format(flow_name))
211
212 def new_flow(self, data):
213 self.rules[data["name"]] = data
214 self.logger.debug("new_flow OK")
215 return None
216
217 def get_of_rules(self, translate_of_ports=True):
218 return self.rules
219
220 def clear_all_flows(self):
221 self.logger.debug("clear_all_flows OK")
222 self.rules = {}
223 return None