1
# Copyright 2012 NEC Corporation. All rights reserved.
3
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4
# not use this file except in compliance with the License. You may obtain
5
# a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
# License for the specific language governing permissions and limitations
17
from neutron.common import utils
18
from neutron.openstack.common import log as logging
19
from neutron.plugins.nec.common import config
20
from neutron.plugins.nec.common import exceptions as nexc
21
from neutron.plugins.nec.db import api as ndb
22
from neutron.plugins.nec import drivers
25
LOG = logging.getLogger(__name__)
28
class OFCManager(object):
29
"""This class manages an OpenFlow Controller and map resources.
31
This class manage an OpenFlow Controller (OFC) with a driver specified in
32
a configuration of this plugin. This keeps mappings between IDs on Neutron
33
and OFC for various entities such as Tenant, Network and Filter. A Port on
34
OFC is identified by a switch ID 'datapath_id' and a port number 'port_no'
35
of the switch. An ID named as 'ofc_*' is used to identify resource on OFC.
38
def __init__(self, plugin):
39
self.driver = drivers.get_driver(config.OFC.driver)(config.OFC)
42
def _get_ofc_id(self, context, resource, neutron_id):
43
return ndb.get_ofc_id(context.session, resource, neutron_id)
45
def _exists_ofc_item(self, context, resource, neutron_id):
46
return ndb.exists_ofc_item(context.session, resource, neutron_id)
48
def _add_ofc_item(self, context, resource, neutron_id, ofc_id):
49
# Ensure a new item is added to the new mapping table
50
ndb.add_ofc_item(context.session, resource, neutron_id, ofc_id)
52
def _del_ofc_item(self, context, resource, neutron_id):
53
ndb.del_ofc_item(context.session, resource, neutron_id)
55
def ensure_ofc_tenant(self, context, tenant_id):
56
if not self.exists_ofc_tenant(context, tenant_id):
57
self.create_ofc_tenant(context, tenant_id)
59
def create_ofc_tenant(self, context, tenant_id):
60
desc = "ID=%s at OpenStack." % tenant_id
61
ofc_tenant_id = self.driver.create_tenant(desc, tenant_id)
62
self._add_ofc_item(context, "ofc_tenant", tenant_id, ofc_tenant_id)
64
def exists_ofc_tenant(self, context, tenant_id):
65
return self._exists_ofc_item(context, "ofc_tenant", tenant_id)
67
def delete_ofc_tenant(self, context, tenant_id):
68
ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id)
69
self.driver.delete_tenant(ofc_tenant_id)
70
self._del_ofc_item(context, "ofc_tenant", tenant_id)
72
def create_ofc_network(self, context, tenant_id, network_id,
74
ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id)
75
desc = "ID=%s Name=%s at Neutron." % (network_id, network_name)
76
ofc_net_id = self.driver.create_network(ofc_tenant_id, desc,
78
self._add_ofc_item(context, "ofc_network", network_id, ofc_net_id)
80
def exists_ofc_network(self, context, network_id):
81
return self._exists_ofc_item(context, "ofc_network", network_id)
83
def delete_ofc_network(self, context, network_id, network):
84
ofc_net_id = self._get_ofc_id(context, "ofc_network", network_id)
85
self.driver.delete_network(ofc_net_id)
86
self._del_ofc_item(context, "ofc_network", network_id)
88
def create_ofc_port(self, context, port_id, port):
89
ofc_net_id = self._get_ofc_id(context, "ofc_network",
91
portinfo = ndb.get_portinfo(context.session, port_id)
93
raise nexc.PortInfoNotFound(id=port_id)
95
# Associate packet filters
96
filters = self.plugin.get_packet_filters_for_port(context, port)
97
if filters is not None:
98
params = {'filters': filters}
102
ofc_port_id = self.driver.create_port(ofc_net_id, portinfo, port_id,
104
self._add_ofc_item(context, "ofc_port", port_id, ofc_port_id)
106
def exists_ofc_port(self, context, port_id):
107
return self._exists_ofc_item(context, "ofc_port", port_id)
109
def delete_ofc_port(self, context, port_id, port):
110
ofc_port_id = self._get_ofc_id(context, "ofc_port", port_id)
111
self.driver.delete_port(ofc_port_id)
112
self._del_ofc_item(context, "ofc_port", port_id)
114
def create_ofc_packet_filter(self, context, filter_id, filter_dict):
115
ofc_pf_id = self.driver.create_filter(context, filter_dict, filter_id)
116
self._add_ofc_item(context, "ofc_packet_filter", filter_id, ofc_pf_id)
118
def update_ofc_packet_filter(self, context, filter_id, filter_dict):
119
ofc_pf_id = self._get_ofc_id(context, "ofc_packet_filter", filter_id)
120
self.driver.update_filter(ofc_pf_id, filter_dict)
122
def exists_ofc_packet_filter(self, context, filter_id):
123
return self._exists_ofc_item(context, "ofc_packet_filter", filter_id)
125
def delete_ofc_packet_filter(self, context, filter_id):
126
ofc_pf_id = self._get_ofc_id(context, "ofc_packet_filter", filter_id)
127
self.driver.delete_filter(ofc_pf_id)
128
self._del_ofc_item(context, "ofc_packet_filter", filter_id)
130
def create_ofc_router(self, context, tenant_id, router_id, name=None):
131
ofc_tenant_id = self._get_ofc_id(context, "ofc_tenant", tenant_id)
132
desc = "ID=%s Name=%s at Neutron." % (router_id, name)
133
ofc_router_id = self.driver.create_router(ofc_tenant_id, router_id,
135
self._add_ofc_item(context, "ofc_router", router_id, ofc_router_id)
137
def exists_ofc_router(self, context, router_id):
138
return self._exists_ofc_item(context, "ofc_router", router_id)
140
def delete_ofc_router(self, context, router_id, router):
141
ofc_router_id = self._get_ofc_id(context, "ofc_router", router_id)
142
self.driver.delete_router(ofc_router_id)
143
self._del_ofc_item(context, "ofc_router", router_id)
145
def add_ofc_router_interface(self, context, router_id, port_id, port):
146
# port must have the following fields:
147
# network_id, cidr, ip_address, mac_address
148
ofc_router_id = self._get_ofc_id(context, "ofc_router", router_id)
149
ofc_net_id = self._get_ofc_id(context, "ofc_network",
151
ip_address = '%s/%s' % (port['ip_address'],
152
netaddr.IPNetwork(port['cidr']).prefixlen)
153
mac_address = port['mac_address']
154
ofc_inf_id = self.driver.add_router_interface(
155
ofc_router_id, ofc_net_id, ip_address, mac_address)
156
# Use port mapping table to maintain an interface of OFC router
157
self._add_ofc_item(context, "ofc_port", port_id, ofc_inf_id)
159
def delete_ofc_router_interface(self, context, router_id, port_id):
160
# Use port mapping table to maintain an interface of OFC router
161
ofc_inf_id = self._get_ofc_id(context, "ofc_port", port_id)
162
self.driver.delete_router_interface(ofc_inf_id)
163
self._del_ofc_item(context, "ofc_port", port_id)
165
def update_ofc_router_route(self, context, router_id, new_routes):
166
ofc_router_id = self._get_ofc_id(context, "ofc_router", router_id)
167
ofc_routes = self.driver.list_router_routes(ofc_router_id)
171
key = ','.join((r['destination'], r['nexthop']))
172
route_dict[key] = r['id']
175
added, removed = utils.diff_list_of_dict(cur_routes, new_routes)
177
key = ','.join((r['destination'], r['nexthop']))
178
route_id = route_dict[key]
179
self.driver.delete_router_route(route_id)
181
self.driver.add_router_route(ofc_router_id, r['destination'],