21 import rad.connect as radcon |
21 import rad.connect as radcon |
22 import rad.bindings.com.oracle.solaris.rad.evscntl_1 as evsbind |
22 import rad.bindings.com.oracle.solaris.rad.evscntl_1 as evsbind |
23 |
23 |
24 from oslo.config import cfg |
24 from oslo.config import cfg |
25 |
25 |
26 from quantum.api.rpc.agentnotifiers import dhcp_rpc_agent_api |
26 from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api |
27 from quantum.api.rpc.agentnotifiers import l3_rpc_agent_api |
27 from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api |
28 from quantum.api.v2 import attributes |
28 from neutron.api.v2 import attributes |
29 from quantum.common import constants as l3_constants |
29 from neutron.common import constants as l3_constants |
30 from quantum.common import exceptions |
30 from neutron.common import exceptions |
31 from quantum.common import rpc as q_rpc |
31 from neutron.common import rpc as q_rpc |
32 from quantum.common import topics |
32 from neutron.common import topics |
33 from quantum.db import dhcp_rpc_base |
33 from neutron.db import db_base_plugin_v2 |
34 from quantum.db import l3_rpc_base |
34 from neutron.db import dhcp_rpc_base |
35 from quantum.extensions import l3 |
35 from neutron.db import external_net_db |
36 from quantum.extensions import providernet |
36 from neutron.db import l3_rpc_base |
37 from quantum.openstack.common import log as logging |
37 from neutron.extensions import external_net |
38 from quantum.openstack.common import rpc |
38 from neutron.extensions import providernet |
39 from quantum.plugins.evs.db import api as evs_db |
39 from neutron.openstack.common import lockutils |
40 from quantum.plugins.evs.db import l3nat as evs_l3nat |
40 from neutron.openstack.common import log as logging |
41 from quantum import quantum_plugin_base_v2 |
41 from neutron.openstack.common import rpc |
|
42 from neutron.plugins.common import constants as svc_constants |
|
43 from neutron.plugins.evs.db import api as evs_db |
|
44 from neutron.plugins.evs.db import l3nat as evs_l3nat |
|
45 from neutron.plugins.evs.db import quotas_db |
42 |
46 |
43 |
47 |
44 LOG = logging.getLogger(__name__) |
48 LOG = logging.getLogger(__name__) |
45 |
49 |
46 evs_controller_opts = [ |
50 evs_controller_opts = [ |
47 cfg.StrOpt('evs_controller', default='ssh://evsuser@localhost', |
51 cfg.StrOpt('evs_controller', default='ssh://evsuser@localhost', |
48 help=_("An URI that specifies an EVS controller")) |
52 help=_("An URI that specifies an EVS controller")) |
49 ] |
53 ] |
50 |
54 |
|
55 evs_database_opts = [ |
|
56 cfg.StrOpt('sql_connection', |
|
57 default='sqlite:////var/lib/neutron/neutron.sqlite', |
|
58 help=_("An URI that specifies SQL connectionr")), |
|
59 ] |
|
60 |
51 cfg.CONF.register_opts(evs_controller_opts, "EVS") |
61 cfg.CONF.register_opts(evs_controller_opts, "EVS") |
|
62 cfg.CONF.register_opts(evs_database_opts, "DATABASE") |
52 |
63 |
53 # Maps OpenStack network resource attributes to EVS properties |
64 # Maps OpenStack network resource attributes to EVS properties |
54 NETWORK_EVS_ATTRIBUTE_MAP = { |
65 NETWORK_EVS_ATTRIBUTE_MAP = { |
55 'tenant_id': 'tenant', |
66 'tenant_id': 'tenant', |
56 'network_id': 'evs', |
67 'network_id': 'evs', |
57 'id': 'evs', |
68 'id': 'evs', |
58 'name': 'evs', |
69 'name': 'evs', |
59 l3.EXTERNAL: 'OpenStack:' + l3.EXTERNAL, |
70 external_net.EXTERNAL: 'OpenStack:' + external_net.EXTERNAL, |
60 } |
71 } |
61 |
72 |
62 # Maps OpenStack subnet resource attributes to EVS' IPnet properties |
73 # Maps OpenStack subnet resource attributes to EVS' IPnet properties |
63 SUBNET_IPNET_ATTRIBUTE_MAP = { |
74 SUBNET_IPNET_ATTRIBUTE_MAP = { |
64 'tenant_id': 'tenant', |
75 'tenant_id': 'tenant', |
79 'device_id': 'OpenStack:device_id', |
90 'device_id': 'OpenStack:device_id', |
80 'device_owner': 'OpenStack:device_owner', |
91 'device_owner': 'OpenStack:device_owner', |
81 } |
92 } |
82 |
93 |
83 |
94 |
84 class EVSControllerError(exceptions.QuantumException): |
95 class EVSControllerError(exceptions.NeutronException): |
85 message = _("EVS controller: %(errmsg)s") |
96 message = _("EVS controller: %(errmsg)s") |
86 |
97 |
87 def __init__(self, evs_errmsg): |
98 def __init__(self, evs_errmsg): |
88 super(EVSControllerError, self).__init__(errmsg=evs_errmsg) |
99 super(EVSControllerError, self).__init__(errmsg=evs_errmsg) |
89 |
100 |
90 |
101 |
91 class EVSOpNotSupported(exceptions.QuantumException): |
102 class EVSOpNotSupported(exceptions.NeutronException): |
92 message = _("Operation not supported by EVS plugin: %(opname)s") |
103 message = _("Operation not supported by EVS plugin: %(opname)s") |
93 |
104 |
94 def __init__(self, evs_errmsg): |
105 def __init__(self, evs_errmsg): |
95 super(EVSOpNotSupported, self).__init__(opname=evs_errmsg) |
106 super(EVSOpNotSupported, self).__init__(opname=evs_errmsg) |
96 |
107 |
97 |
108 |
98 class EVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin, |
109 class EVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin, |
99 l3_rpc_base.L3RpcCallbackMixin): |
110 l3_rpc_base.L3RpcCallbackMixin): |
100 RPC_API_VERSION = '1.0' |
111 RPC_API_VERSION = '1.1' |
101 |
112 |
102 def create_rpc_dispatcher(self): |
113 def create_rpc_dispatcher(self): |
103 '''Get the rpc dispatcher for this manager. |
114 '''Get the rpc dispatcher for this manager. |
104 |
115 |
105 If a manager would like to set an rpc API version, or support more than |
116 If a manager would like to set an rpc API version, or support more than |
106 one class as the target of rpc messages, override this method. |
117 one class as the target of rpc messages, override this method. |
107 ''' |
118 ''' |
108 return q_rpc.PluginRpcDispatcher([self]) |
119 return q_rpc.PluginRpcDispatcher([self]) |
109 |
120 |
110 |
121 |
111 class EVSQuantumPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2, |
122 class EVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2, |
|
123 external_net_db.External_net_db_mixin, |
112 evs_l3nat.EVS_L3_NAT_db_mixin): |
124 evs_l3nat.EVS_L3_NAT_db_mixin): |
113 """Implements v2 Neutron Plug-in API specification. |
125 """Implements v2 Neutron Plug-in API specification. |
114 |
126 |
115 All the quantum API calls to create/delete/retrieve Network/Subnet/Port |
127 All the neutron API calls to create/delete/retrieve Network/Subnet/Port |
116 are forwarded to EVS controller through Solaris RAD. The RAD connection |
128 are forwarded to EVS controller through Solaris RAD. The RAD connection |
117 to EVS Controller is over SSH. In order that this plugin can communicate |
129 to EVS Controller is over SSH. In order that this plugin can communicate |
118 with EVS Controller non-interactively and securely, one should setup SSH |
130 with EVS Controller non-interactively and securely, one should setup SSH |
119 authentication with pre-shared keys between the host running neutron-server |
131 authentication with pre-shared keys between the host running neutron-server |
120 and the host running EVS controller. |
132 and the host running EVS controller. |
169 | -- security_groups | -- Not Supported | | |
181 | -- security_groups | -- Not Supported | | |
170 | -- admin_state_up | Always UP | | |
182 | -- admin_state_up | Always UP | | |
171 |---------------------+------------------+------------------------------| |
183 |---------------------+------------------+------------------------------| |
172 """ |
184 """ |
173 |
185 |
174 _supported_extension_aliases = ["provider", "router", "quotas"] |
186 # These attribute specifies whether the plugin supports or not |
|
187 # bulk/pagination/sorting operations. |
|
188 __native_bulk_support = False |
|
189 __native_pagination_support = False |
|
190 __native_sorting_support = False |
|
191 |
|
192 _supported_extension_aliases = ["provider", "external-net", "router", |
|
193 "quotas"] |
175 |
194 |
176 def __init__(self): |
195 def __init__(self): |
177 # Since EVS Framework does not support router and floatingip |
196 # Since EVS Framework does not support router and floatingip |
178 # resources, the plugin itself will maintain a DB for these |
197 # resources, the plugin itself will maintain a DB for these |
179 # two resources |
198 # two resources |
194 self._evsc = self._rc.get_object(evsbind.EVSController()) |
213 self._evsc = self._rc.get_object(evsbind.EVSController()) |
195 self._setup_rpc() |
214 self._setup_rpc() |
196 |
215 |
197 def _setup_rpc(self): |
216 def _setup_rpc(self): |
198 # RPC support |
217 # RPC support |
199 self.topic = topics.PLUGIN |
218 self.service_topics = {svc_constants.CORE: topics.PLUGIN, |
|
219 svc_constants.L3_ROUTER_NAT: topics.L3PLUGIN} |
200 self.conn = rpc.create_connection(new=True) |
220 self.conn = rpc.create_connection(new=True) |
201 self.callbacks = EVSRpcCallbacks() |
221 self.callbacks = EVSRpcCallbacks() |
202 self.dispatcher = self.callbacks.create_rpc_dispatcher() |
222 self.dispatcher = self.callbacks.create_rpc_dispatcher() |
203 self.conn.create_consumer(self.topic, self.dispatcher, fanout=False) |
223 for svc_topic in self.service_topics.values(): |
|
224 self.conn.create_consumer(svc_topic, self.dispatcher, fanout=False) |
204 # Consume from all consumers in a thread |
225 # Consume from all consumers in a thread |
205 self.conn.consume_in_thread() |
226 self.conn.consume_in_thread() |
206 self.dhcp_agent_notifier = dhcp_rpc_agent_api.DhcpAgentNotifyAPI() |
227 self.dhcp_agent_notifier = dhcp_rpc_agent_api.DhcpAgentNotifyAPI() |
207 |
228 |
208 @property |
229 @property |
209 def supported_extension_aliases(self): |
230 def supported_extension_aliases(self): |
210 return self._supported_extension_aliases |
231 return self._supported_extension_aliases |
211 |
|
212 def _fields(self, resource, fields): |
|
213 if fields: |
|
214 return dict(((key, item) for key, item in resource.iteritems() |
|
215 if key in fields)) |
|
216 return resource |
|
217 |
232 |
218 def _convert_evs_to_network(self, evs): |
233 def _convert_evs_to_network(self, evs): |
219 """Converts an EVS structure into Neutron Network structure.""" |
234 """Converts an EVS structure into Neutron Network structure.""" |
220 |
235 |
221 networkdict = dict() |
236 networkdict = dict() |
222 networkdict['name'] = evs.name |
237 networkdict['name'] = evs.name |
223 networkdict['id'] = evs.uuid |
238 networkdict['id'] = evs.uuid |
224 networkdict['subnets'] = ([ipnet.uuid for ipnet in evs.ipnets] |
239 networkdict['subnets'] = ([ipnet.uuid for ipnet in evs.ipnets] |
225 if evs.ipnets else []) |
240 if evs.ipnets else []) |
226 networkdict['tenant_id'] = evs.tenantname |
241 networkdict['tenant_id'] = evs.tenantname |
227 networkdict[l3.EXTERNAL] = False |
242 networkdict[external_net.EXTERNAL] = False |
228 for prop in evs.props: |
243 for prop in evs.props: |
229 if prop.name == 'l2-type': |
244 if prop.name == 'l2-type': |
230 networkdict[providernet.NETWORK_TYPE] = prop.value |
245 networkdict[providernet.NETWORK_TYPE] = prop.value |
231 if prop.name == 'vlanid' or prop.name == 'vni': |
246 if prop.name == 'vlanid' or prop.name == 'vni': |
232 networkdict[providernet.SEGMENTATION_ID] = int(prop.value) |
247 networkdict[providernet.SEGMENTATION_ID] = int(prop.value) |
233 if prop.name == NETWORK_EVS_ATTRIBUTE_MAP[l3.EXTERNAL]: |
248 if prop.name == NETWORK_EVS_ATTRIBUTE_MAP[external_net.EXTERNAL]: |
234 networkdict[l3.EXTERNAL] = \ |
249 networkdict[external_net.EXTERNAL] = \ |
235 (True if prop.value == 'True' else False) |
250 (True if prop.value == 'True' else False) |
236 # fixed values as EVS framework doesn't support this |
251 # fixed values as EVS framework doesn't support this |
237 networkdict['admin_state_up'] = True |
252 networkdict['admin_state_up'] = True |
238 networkdict['status'] = 'ACTIVE' |
253 networkdict['status'] = 'ACTIVE' |
239 networkdict['shared'] = False |
254 networkdict['shared'] = False |
277 start_ip = netaddr.IPAddress(ipnet.start) |
292 start_ip = netaddr.IPAddress(ipnet.start) |
278 end_ip = netaddr.IPAddress(ipnet.end) |
293 end_ip = netaddr.IPAddress(ipnet.end) |
279 gw_ip = netaddr.IPAddress(subnetdict['gateway_ip']) |
294 gw_ip = netaddr.IPAddress(subnetdict['gateway_ip']) |
280 pools = [] |
295 pools = [] |
281 if gw_ip == start_ip: |
296 if gw_ip == start_ip: |
282 pools.append({'start' : str(netaddr.IPAddress(start_ip + 1)), |
297 pools.append({'start': str(netaddr.IPAddress(start_ip + 1)), |
283 'end': str(netaddr.IPAddress(end_ip))}) |
298 'end': str(netaddr.IPAddress(end_ip))}) |
284 elif gw_ip == end_ip: |
299 elif gw_ip == end_ip: |
285 pools.append({'start' : str(netaddr.IPAddress(start_ip)), |
300 pools.append({'start': str(netaddr.IPAddress(start_ip)), |
286 'end': str(netaddr.IPAddress(end_ip - 1))}) |
301 'end': str(netaddr.IPAddress(end_ip - 1))}) |
287 else: |
302 else: |
288 pools.append({'start': str(netaddr.IPAddress(start_ip)), |
303 pools.append({'start': str(netaddr.IPAddress(start_ip)), |
289 'end' : str(netaddr.IPAddress(gw_ip - 1))}) |
304 'end': str(netaddr.IPAddress(gw_ip - 1))}) |
290 pools.append({'start': str(netaddr.IPAddress(gw_ip + 1)), |
305 pools.append({'start': str(netaddr.IPAddress(gw_ip + 1)), |
291 'end' : str(netaddr.IPAddress(end_ip))}) |
306 'end': str(netaddr.IPAddress(end_ip))}) |
292 |
307 |
293 subnetdict['allocation_pools'] = pools |
308 subnetdict['allocation_pools'] = pools |
294 subnetdict['shared'] = False |
309 subnetdict['shared'] = False |
295 |
310 |
296 return subnetdict |
311 return subnetdict |
301 portdict = dict() |
316 portdict = dict() |
302 portdict['admin_state_up'] = True |
317 portdict['admin_state_up'] = True |
303 portdict['id'] = vport.uuid |
318 portdict['id'] = vport.uuid |
304 portdict['name'] = vport.name |
319 portdict['name'] = vport.name |
305 portdict['network_id'] = vport.evsuuid |
320 portdict['network_id'] = vport.evsuuid |
306 #TODO(gmoodalb): set to host/zonename/vnicname? |
321 # TODO(gmoodalb): set to host/zonename/vnicname? |
307 portdict['device_id'] = '' |
322 portdict['device_id'] = '' |
308 portdict['device_owner'] = '' |
323 portdict['device_owner'] = '' |
309 for prop in vport.props: |
324 for prop in vport.props: |
310 if (prop.name == 'macaddr'): |
325 if (prop.name == 'macaddr'): |
311 portdict['mac_address'] = prop.value |
326 portdict['mac_address'] = prop.value |
351 break |
366 break |
352 |
367 |
353 for rsrc in rsrc_to_remove: |
368 for rsrc in rsrc_to_remove: |
354 rsrclist.remove(rsrc) |
369 rsrclist.remove(rsrc) |
355 |
370 |
|
371 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
372 def evs_controller_addIPnet(self, tenantname, evsname, ipnetname, propstr): |
|
373 try: |
|
374 pat = radcli.ADRGlobPattern( |
|
375 {'name': evsname, 'tenant': tenantname}) |
|
376 evs = self._rc.get_object(evsbind.EVS(), pat) |
|
377 ipnet = evs.addIPnet(propstr, ipnetname) |
|
378 except radcli.ObjectError as oe: |
|
379 raise EVSControllerError(oe.get_payload().errmsg) |
|
380 return ipnet |
|
381 |
356 def create_subnet(self, context, subnet): |
382 def create_subnet(self, context, subnet): |
357 """Creates a subnet(IPnet) for a given network(EVS). |
383 """Creates a subnet(IPnet) for a given network(EVS). |
358 |
384 |
359 An IP network represents a block of either IPv4 or IPv6 addresses |
385 An IP network represents a block of either IPv4 or IPv6 addresses |
360 (i.e., subnet) along with a default router for the block. Only one |
386 (i.e., subnet) along with a default router for the block. Only one |
361 IPnet can be associated with an EVS. All the zones/VNICs that |
387 IPnet can be associated with an EVS. All the zones/VNICs that |
362 connect to the EVS, through a VPort, will get an IP address from the |
388 connect to the EVS, through a VPort, will get an IP address from the |
363 IPnet associated with the EVS. |
389 IPnet associated with the EVS. |
364 """ |
390 """ |
|
391 if (subnet['subnet']['allocation_pools'] is not |
|
392 attributes.ATTR_NOT_SPECIFIED): |
|
393 # user specified --allocation-pool and we don't support it |
|
394 raise EVSOpNotSupported(_("cannot use --allocation-pool")) |
365 ipnetname = subnet['subnet']['name'] |
395 ipnetname = subnet['subnet']['name'] |
366 if not ipnetname: |
396 if not ipnetname: |
367 ipnetname = None |
397 ipnetname = None |
368 |
398 |
369 proplist = ['subnet=%s' % (subnet['subnet']['cidr'])] |
399 proplist = ['subnet=%s' % (subnet['subnet']['cidr'])] |
370 |
400 |
371 # obtain the optional default router |
401 # obtain the optional default router |
372 defrouter = subnet['subnet']['gateway_ip'] |
402 defrouter = subnet['subnet']['gateway_ip'] |
373 if defrouter is None: |
403 if defrouter is None: |
374 # user specified --no-gateway, we don't support it |
404 # user specified --no-gateway and we don't support it |
375 raise EVSOpNotSupported(_("cannot use --no-gateway")) |
405 raise EVSOpNotSupported(_("cannot use --no-gateway")) |
|
406 |
376 if defrouter is not attributes.ATTR_NOT_SPECIFIED: |
407 if defrouter is not attributes.ATTR_NOT_SPECIFIED: |
377 proplist.append('defrouter=%s' % (defrouter)) |
408 proplist.append('defrouter=%s' % (defrouter)) |
378 |
409 |
379 # obtain the optional DNS nameservers |
410 # obtain the optional DNS nameservers |
380 nameservers = subnet['subnet']['dns_nameservers'] |
411 nameservers = subnet['subnet']['dns_nameservers'] |
381 if attributes.is_attr_set(nameservers): |
412 if attributes.is_attr_set(nameservers): |
382 proplist.append('%s=%s' % |
413 proplist.append('%s=%s' % |
383 (SUBNET_IPNET_ATTRIBUTE_MAP['dns_nameservers'], |
414 (SUBNET_IPNET_ATTRIBUTE_MAP['dns_nameservers'], |
384 ','.join(nameservers))) |
415 ','.join(nameservers))) |
385 |
416 |
386 # obtain the host routes |
417 # obtain the host routes |
387 hostroutes = subnet['subnet']['host_routes'] |
418 hostroutes = subnet['subnet']['host_routes'] |
388 if attributes.is_attr_set(hostroutes): |
419 if attributes.is_attr_set(hostroutes): |
389 hrlist = ['%s,%s' % (destination, nexthop) |
420 hrlist = ['%s,%s' % (destination, nexthop) |
401 if proplist: |
432 if proplist: |
402 propstr = ",".join(proplist) |
433 propstr = ",".join(proplist) |
403 |
434 |
404 # TODO(gmoodalb): extract the tenant id if an admin is creating for |
435 # TODO(gmoodalb): extract the tenant id if an admin is creating for |
405 # someone else |
436 # someone else |
406 try: |
437 evsname = subnet['subnet']['network_id'] |
407 evsuuid = subnet['subnet']['network_id'] |
438 tenantname = subnet['subnet']['tenant_id'] |
408 tenantname = subnet['subnet']['tenant_id'] |
439 ipnet = self.evs_controller_addIPnet(tenantname, evsname, ipnetname, |
409 pat = radcli.ADRGlobPattern( |
440 propstr) |
410 {'name': evsuuid, 'tenant': tenantname}) |
|
411 evs = self._rc.get_object(evsbind.EVS(), pat) |
|
412 ipnet = evs.addIPnet(propstr, ipnetname) |
|
413 except radcli.ObjectError as oe: |
|
414 raise EVSControllerError(oe.get_payload().errmsg) |
|
415 |
|
416 retval = self._convert_ipnet_to_subnet(ipnet) |
441 retval = self._convert_ipnet_to_subnet(ipnet) |
417 |
442 |
418 # notify dhcp agent of subnet creation |
443 # notify dhcp agent of subnet creation |
419 self.dhcp_agent_notifier.notify(context, {'subnet': retval}, |
444 self.dhcp_agent_notifier.notify(context, {'subnet': retval}, |
420 'subnet.create.end') |
445 'subnet.create.end') |
421 return retval |
446 return retval |
422 |
447 |
423 def update_subnet(self, context, id, subnet): |
448 @lockutils.synchronized('evs-plugin', 'neutron-') |
424 evs_rpccall_sync = subnet.pop('evs_rpccall_sync', False) |
449 def evs_controller_updateIPnet(self, ipnetuuid, propstr): |
425 if not (set(subnet['subnet'].keys()) == set(('enable_dhcp',))): |
450 try: |
426 raise EVSOpNotSupported(_("only enable_dhcp can be updated")) |
451 pat = radcli.ADRGlobPattern({'uuid': ipnetuuid}) |
427 |
|
428 propstr = "%s=%s" % (SUBNET_IPNET_ATTRIBUTE_MAP['enable_dhcp'], |
|
429 subnet['subnet']['enable_dhcp']) |
|
430 try: |
|
431 pat = radcli.ADRGlobPattern({'uuid': id}) |
|
432 ipnetlist = self._rc.list_objects(evsbind.IPnet(), pat) |
452 ipnetlist = self._rc.list_objects(evsbind.IPnet(), pat) |
433 assert len(ipnetlist) == 1 |
453 assert len(ipnetlist) == 1 |
434 ipnet = self._rc.get_object(ipnetlist[0]) |
454 ipnet = self._rc.get_object(ipnetlist[0]) |
435 ipnet.setProperty(propstr) |
455 ipnet.setProperty(propstr) |
436 except radcli.ObjectError as oe: |
456 except radcli.ObjectError as oe: |
437 raise EVSControllerError(oe.get_payload().errmsg) |
457 raise EVSControllerError(oe.get_payload().errmsg) |
438 |
458 |
|
459 def update_subnet(self, context, id, subnet): |
|
460 evs_rpccall_sync = subnet.pop('evs_rpccall_sync', False) |
|
461 if not (set(subnet['subnet'].keys()) == set(('enable_dhcp',))): |
|
462 raise EVSOpNotSupported(_("only subnets with enable_dhcp " |
|
463 "set can be updated")) |
|
464 |
|
465 propstr = "%s=%s" % (SUBNET_IPNET_ATTRIBUTE_MAP['enable_dhcp'], |
|
466 subnet['subnet']['enable_dhcp']) |
|
467 self.evs_controller_updateIPnet(id, propstr) |
439 retval = self.get_subnet(context, id) |
468 retval = self.get_subnet(context, id) |
440 |
469 |
441 # notify dhcp agent of subnet update |
470 # notify dhcp agent of subnet update |
442 methodname = 'subnet.update.end' |
471 methodname = 'subnet.update.end' |
443 payload = {'subnet': retval} |
472 payload = {'subnet': retval} |
448 methodname.replace(".", "_"), payload=payload) |
477 methodname.replace(".", "_"), payload=payload) |
449 self.dhcp_agent_notifier.call(context, msg, |
478 self.dhcp_agent_notifier.call(context, msg, |
450 topic=topics.DHCP_AGENT) |
479 topic=topics.DHCP_AGENT) |
451 return retval |
480 return retval |
452 |
481 |
|
482 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
483 def evs_controller_getIPnet(self, ipnetuuid): |
|
484 try: |
|
485 ipnetlist = self._evsc.getIPnetInfo('ipnet=%s' % (ipnetuuid)) |
|
486 except radcli.ObjectError as oe: |
|
487 raise EVSControllerError(oe.get_payload().errmsg) |
|
488 return (ipnetlist[0] if ipnetlist else None) |
|
489 |
453 def get_subnet(self, context, id, fields=None): |
490 def get_subnet(self, context, id, fields=None): |
454 try: |
491 ipnet = self.evs_controller_getIPnet(id) |
455 ipnetlist = self._evsc.getIPnetInfo('ipnet=%s' % (id)) |
492 if not ipnet: |
456 except radcli.ObjectError as oe: |
493 return {} |
457 raise EVSControllerError(oe.get_payload().errmsg) |
494 subnetdict = self._convert_ipnet_to_subnet(ipnet) |
458 |
495 return self._fields(subnetdict, fields) |
459 if ipnetlist: |
496 |
460 subnetdict = self._convert_ipnet_to_subnet(ipnetlist[0]) |
497 @lockutils.synchronized('evs-plugin', 'neutron-') |
461 return self._fields(subnetdict, fields) |
498 def evs_controller_getIPnetList(self, filterstr): |
462 return {} |
499 try: |
|
500 ipnetlist = self._evsc.getIPnetInfo(filterstr) |
|
501 except radcli.ObjectError as oe: |
|
502 raise EVSControllerError(oe.get_payload().errmsg) |
|
503 return ipnetlist |
463 |
504 |
464 def get_subnets(self, context, filters=None, fields=None, |
505 def get_subnets(self, context, filters=None, fields=None, |
465 sorts=None, limit=None, marker=None, page_reverse=False): |
506 sorts=None, limit=None, marker=None, page_reverse=False): |
466 |
507 |
467 filterstr = None |
508 filterstr = None |
481 ipnet_props[SUBNET_IPNET_ATTRIBUTE_MAP[key]] = value |
522 ipnet_props[SUBNET_IPNET_ATTRIBUTE_MAP[key]] = value |
482 continue |
523 continue |
483 key = SUBNET_IPNET_ATTRIBUTE_MAP.get(key, key) |
524 key = SUBNET_IPNET_ATTRIBUTE_MAP.get(key, key) |
484 if isinstance(value, list): |
525 if isinstance(value, list): |
485 value = ",".join([str(val) for val in value]) |
526 value = ",".join([str(val) for val in value]) |
|
527 if not value: |
|
528 continue |
486 filterlist.append("%s=%s" % (key, value)) |
529 filterlist.append("%s=%s" % (key, value)) |
487 |
530 |
488 if filterlist: |
531 if filterlist: |
489 filterstr = ",".join(filterlist) |
532 filterstr = ",".join(filterlist) |
490 |
533 |
491 LOG.debug(_("calling ListIPnet from get_subnets() filterstr: '%s'") |
534 LOG.debug(_("calling ListIPnet from get_subnets() filterstr: '%s'") |
492 % (filterstr)) |
535 % (filterstr)) |
493 try: |
536 |
494 ipnetlist = self._evsc.getIPnetInfo(filterstr) |
537 ipnetlist = self.evs_controller_getIPnetList(filterstr) |
495 except radcli.ObjectError as oe: |
|
496 raise EVSControllerError(oe.get_payload().errmsg) |
|
497 |
|
498 self._apply_rsrc_props_filter(ipnetlist, ipnet_props) |
538 self._apply_rsrc_props_filter(ipnetlist, ipnet_props) |
499 |
539 |
500 retme = [] |
540 retme = [] |
501 for ipnet in ipnetlist: |
541 for ipnet in ipnetlist: |
502 subnetdict = self._convert_ipnet_to_subnet(ipnet) |
542 subnetdict = self._convert_ipnet_to_subnet(ipnet) |
503 retme.append(self._fields(subnetdict, fields)) |
543 retme.append(self._fields(subnetdict, fields)) |
504 |
544 |
505 return retme |
545 return retme |
506 |
546 |
507 def get_subnets_count(self, context, filters=None): |
547 def get_subnets_count(self, context, filters=None): |
508 return len(self.get_ipnets(context, filters)) |
548 return len(self.get_subnets(context, filters)) |
509 |
549 |
510 def _release_subnet_dhcp_port(self, context, subnet, delete_network): |
550 def _release_subnet_dhcp_port(self, context, subnet, delete_network): |
511 """Release any dhcp port associated with the subnet""" |
551 """Release any dhcp port associated with the subnet""" |
512 filters = dict(evs=subnet['network_id']) |
552 filters = dict(evs=subnet['network_id']) |
513 portlist = self.get_ports(context, filters) |
553 portlist = self.get_ports(context, filters) |
524 update_subnet = len(portlist) == 1 |
564 update_subnet = len(portlist) == 1 |
525 if update_subnet: |
565 if update_subnet: |
526 # the lone port is a dhcp port created by dhcp agent |
566 # the lone port is a dhcp port created by dhcp agent |
527 # it must be released before we can delete the subnet |
567 # it must be released before we can delete the subnet |
528 subnet_update = {'subnet': {'enable_dhcp': False}, |
568 subnet_update = {'subnet': {'enable_dhcp': False}, |
529 'evs_rpccall_sync': True} |
569 'evs_rpccall_sync': True} |
530 self.update_subnet(context, subnet['id'], subnet_update) |
570 self.update_subnet(context, subnet['id'], subnet_update) |
531 |
571 |
|
572 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
573 def evs_controller_removeIPnet(self, tenantname, evsname, ipnetuuid): |
|
574 pat = radcli.ADRGlobPattern({'name': evsname, 'tenant': tenantname}) |
|
575 try: |
|
576 evs = self._rc.get_object(evsbind.EVS(), pat) |
|
577 evs.removeIPnet(ipnetuuid) |
|
578 except radcli.ObjectError as oe: |
|
579 raise EVSControllerError(oe.get_payload().errmsg) |
|
580 |
532 def delete_subnet(self, context, id): |
581 def delete_subnet(self, context, id): |
533 try: |
582 subnet = self.get_subnet(context, id) |
534 subnet = self.get_subnet(context, id) |
583 if not subnet: |
535 if not subnet: |
584 return |
536 return |
585 |
537 pat = radcli.ADRGlobPattern({'name': subnet['network_id'], |
586 # If the subnet is dhcp_enabled, then the dhcp agent would have |
538 'tenant': subnet['tenant_id']}) |
587 # created a port connected to this subnet. We need to remove |
539 evs = self._rc.get_object(evsbind.EVS(), pat) |
588 # that port before we can proceed with subnet delete operation. |
540 # If the subnet is dhcp_enabled, then the dhcp agent would have |
589 # Since, there is no subnet.delete.start event, we use an another |
541 # created a port connected to this subnet. We need to remove |
590 # approach of updating the subnet's enable_dhcp attribute to |
542 # that port before we can proceed with subnet delete operation. |
591 # False that in turn sends a subnet.udpate notification. This |
543 # Since, there is no subnet.delete.start event, we use an another |
592 # results in DHCP agent releasing the port. |
544 # approach of updating the subnet's enable_dhcp attribute to |
593 if subnet['enable_dhcp']: |
545 # False that in turn sends a subnet.udpate notification. This |
|
546 # results in DHCP agent releasing the port. |
|
547 if subnet['enable_dhcp']: |
|
548 self._release_subnet_dhcp_port(context, subnet, False) |
594 self._release_subnet_dhcp_port(context, subnet, False) |
549 evs.removeIPnet(id) |
595 self.evs_controller_removeIPnet(subnet['tenant_id'], |
550 except radcli.ObjectError as oe: |
596 subnet['network_id'], id) |
551 raise EVSControllerError(oe.get_payload().errmsg) |
|
552 |
597 |
553 # notify dhcp agent |
598 # notify dhcp agent |
554 payload = { |
599 payload = { |
555 'subnet': { |
600 'subnet': { |
556 'network_id': subnet['network_id'], |
601 'network_id': subnet['network_id'], |
557 'id': id, |
602 'id': id, |
558 } |
603 } |
559 } |
604 } |
560 self.dhcp_agent_notifier.notify(context, payload, 'subnet.delete.end') |
605 self.dhcp_agent_notifier.notify(context, payload, 'subnet.delete.end') |
|
606 |
|
607 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
608 def evs_controller_createEVS(self, tenantname, evsname, propstr): |
|
609 try: |
|
610 evs = self._evsc.createEVS(propstr, tenantname, evsname) |
|
611 except radcli.ObjectError as oe: |
|
612 raise EVSControllerError(oe.get_payload().errmsg) |
|
613 return evs |
561 |
614 |
562 def create_network(self, context, network): |
615 def create_network(self, context, network): |
563 """Creates a network(EVS) for a given tenant. |
616 """Creates a network(EVS) for a given tenant. |
564 |
617 |
565 An Elastic Virtual Switch (EVS) is a virtual switch that spans |
618 An Elastic Virtual Switch (EVS) is a virtual switch that spans |
594 else: |
647 else: |
595 raise EVSControllerError(_("specified " |
648 raise EVSControllerError(_("specified " |
596 "provider:network_type '%s' not " |
649 "provider:network_type '%s' not " |
597 "supported") % network_type) |
650 "supported") % network_type) |
598 |
651 |
599 router_external = network['network'][l3.EXTERNAL] |
652 router_external = network['network'][external_net.EXTERNAL] |
600 if attributes.is_attr_set(router_external): |
653 if attributes.is_attr_set(router_external): |
601 proplist.append("%s=%s" % (NETWORK_EVS_ATTRIBUTE_MAP[l3.EXTERNAL], |
654 proplist.append("%s=%s" % |
602 router_external)) |
655 (NETWORK_EVS_ATTRIBUTE_MAP[external_net.EXTERNAL], |
|
656 router_external)) |
603 |
657 |
604 propstr = None |
658 propstr = None |
605 if proplist: |
659 if proplist: |
606 propstr = ",".join(proplist) |
660 propstr = ",".join(proplist) |
607 |
661 |
608 try: |
662 evs = self.evs_controller_createEVS(tenantname, evsname, propstr) |
609 evs = self._evsc.createEVS(propstr, tenantname, evsname) |
|
610 except radcli.ObjectError as oe: |
|
611 raise EVSControllerError(oe.get_payload().errmsg) |
|
612 |
|
613 return self._convert_evs_to_network(evs) |
663 return self._convert_evs_to_network(evs) |
614 |
664 |
615 def update_network(self, context, id, network): |
665 def update_network(self, context, id, network): |
616 raise EVSOpNotSupported(_("net-update")) |
666 raise EVSOpNotSupported(_("net-update")) |
617 |
667 |
|
668 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
669 def evs_controller_getEVS(self, evsuuid): |
|
670 try: |
|
671 evslist = self._evsc.getEVSInfo('evs=%s' % evsuuid) |
|
672 except radcli.ObjectError as oe: |
|
673 raise EVSControllerError(oe.getpayload().errmsg) |
|
674 return (evslist[0] if evslist else None) |
|
675 |
618 def get_network(self, context, id, fields=None): |
676 def get_network(self, context, id, fields=None): |
619 try: |
677 evs = self.evs_controller_getEVS(id) |
620 evslist = self._evsc.getEVSInfo('evs=%s' % id) |
678 if not evs: |
621 except radcli.ObjectError as oe: |
679 return {} |
622 raise EVSControllerError(oe.getpayload().errmsg) |
680 networkdict = self._convert_evs_to_network(evs) |
623 |
681 return self._fields(networkdict, fields) |
624 if evslist: |
682 |
625 networkdict = self._convert_evs_to_network(evslist[0]) |
683 @lockutils.synchronized('evs-plugin', 'neutron-') |
626 return self._fields(networkdict, fields) |
684 def evs_controller_getEVSList(self, filterstr): |
627 return {} |
685 try: |
|
686 evslist = self._evsc.getEVSInfo(filterstr) |
|
687 except radcli.ObjectError as oe: |
|
688 raise EVSControllerError(oe.get_payload().errmsg) |
|
689 return evslist |
628 |
690 |
629 def get_networks(self, context, filters=None, fields=None, |
691 def get_networks(self, context, filters=None, fields=None, |
630 sorts=None, limit=None, marker=None, page_reverse=False): |
692 sorts=None, limit=None, marker=None, page_reverse=False): |
631 |
693 |
632 filterstr = None |
694 filterstr = None |
647 evs_props[NETWORK_EVS_ATTRIBUTE_MAP[key]] = value |
709 evs_props[NETWORK_EVS_ATTRIBUTE_MAP[key]] = value |
648 continue |
710 continue |
649 key = NETWORK_EVS_ATTRIBUTE_MAP.get(key, key) |
711 key = NETWORK_EVS_ATTRIBUTE_MAP.get(key, key) |
650 if isinstance(value, list): |
712 if isinstance(value, list): |
651 value = ",".join([str(val) for val in value]) |
713 value = ",".join([str(val) for val in value]) |
|
714 if not value: |
|
715 continue |
652 filterlist.append("%s=%s" % (key, value)) |
716 filterlist.append("%s=%s" % (key, value)) |
653 |
717 |
654 if filterlist: |
718 if filterlist: |
655 filterstr = ",".join(filterlist) |
719 filterstr = ",".join(filterlist) |
656 |
720 |
657 LOG.debug(_("calling ListEVswitch from get_networks(): '%s'") |
721 LOG.debug(_("calling ListEVswitch from get_networks(): '%s'") |
658 % (filterstr)) |
722 % (filterstr)) |
659 try: |
723 evslist = self.evs_controller_getEVSList(filterstr) |
660 evslist = self._evsc.getEVSInfo(filterstr) |
|
661 except radcli.ObjectError as oe: |
|
662 raise EVSControllerError(oe.get_payload().errmsg) |
|
663 |
|
664 self._apply_rsrc_props_filter(evslist, evs_props) |
724 self._apply_rsrc_props_filter(evslist, evs_props) |
665 |
725 |
666 retme = [] |
726 retme = [] |
667 for evs in evslist: |
727 for evs in evslist: |
668 networkdict = self._convert_evs_to_network(evs) |
728 networkdict = self._convert_evs_to_network(evs) |
671 return retme |
731 return retme |
672 |
732 |
673 def get_networks_count(self, context, filters=None): |
733 def get_networks_count(self, context, filters=None): |
674 return len(self.get_networks(context, filters)) |
734 return len(self.get_networks(context, filters)) |
675 |
735 |
|
736 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
737 def evs_controller_deleteEVS(self, tenantname, evsuuid): |
|
738 try: |
|
739 self._evsc.deleteEVS(evsuuid, tenantname) |
|
740 except radcli.ObjectError as oe: |
|
741 raise EVSControllerError(oe.get_payload().errmsg) |
|
742 |
676 def delete_network(self, context, id): |
743 def delete_network(self, context, id): |
677 try: |
744 # Check if it is an external network and whether addresses in that |
678 filters = dict(network_id=id) |
745 # network are being used for floating ips |
679 subnets = self.get_subnets(context, filters=filters) |
746 evs = self.get_network(context, id) |
680 dhcp_subnets = [s for s in subnets if s['enable_dhcp']] |
747 if evs[external_net.EXTERNAL]: |
681 for subnet in dhcp_subnets: |
748 filters = dict(evs=id) |
682 self._release_subnet_dhcp_port(context, subnet, True) |
749 portlist = self.get_ports(context, filters) |
683 self._evsc.deleteEVS(id, context.tenant_id) |
750 ports_with_deviceid = [port for port in portlist |
684 except radcli.ObjectError as oe: |
751 if port['device_id'] != ''] |
685 raise EVSControllerError(oe.get_payload().errmsg) |
752 if ports_with_deviceid: |
|
753 raise exceptions.NetworkInUse(net_id=id) |
|
754 filters = dict(network_id=id) |
|
755 subnets = self.get_subnets(context, filters=filters) |
|
756 dhcp_subnets = [s for s in subnets if s['enable_dhcp']] |
|
757 for subnet in dhcp_subnets: |
|
758 self._release_subnet_dhcp_port(context, subnet, True) |
|
759 self.evs_controller_deleteEVS(context.tenant_id, id) |
686 |
760 |
687 # notify dhcp agent of network deletion |
761 # notify dhcp agent of network deletion |
688 self.dhcp_agent_notifier.notify(context, {'network': {'id': id}}, |
762 self.dhcp_agent_notifier.notify(context, {'network': {'id': id}}, |
689 'network.delete.end') |
763 'network.delete.end') |
|
764 |
|
765 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
766 def evs_controller_addVPort(self, tenantname, evsname, vportname, propstr): |
|
767 try: |
|
768 pat = radcli.ADRGlobPattern({'name': evsname, |
|
769 'tenant': tenantname}) |
|
770 evs = self._rc.get_object(evsbind.EVS(), pat) |
|
771 vport = evs.addVPort(propstr, vportname) |
|
772 except radcli.ObjectError as oe: |
|
773 raise EVSControllerError(oe.get_payload().errmsg) |
|
774 return vport |
690 |
775 |
691 def create_port(self, context, port): |
776 def create_port(self, context, port): |
692 """Creates a port(VPort) for a given network(EVS). |
777 """Creates a port(VPort) for a given network(EVS). |
693 |
778 |
694 A VPort represents the point of attachment between the VNIC and an |
779 A VPort represents the point of attachment between the VNIC and an |
723 |
808 |
724 device_owner = port['port']['device_owner'] |
809 device_owner = port['port']['device_owner'] |
725 if attributes.is_attr_set(device_owner) and device_owner: |
810 if attributes.is_attr_set(device_owner) and device_owner: |
726 proplist.append("%s=%s" % |
811 proplist.append("%s=%s" % |
727 (PORT_VPORT_ATTRIBUTE_MAP['device_owner'], |
812 (PORT_VPORT_ATTRIBUTE_MAP['device_owner'], |
728 device_owner)) |
813 device_owner)) |
729 |
814 |
730 propstr = None |
815 propstr = None |
731 if proplist: |
816 if proplist: |
732 propstr = ",".join(proplist) |
817 propstr = ",".join(proplist) |
733 |
818 |
734 try: |
819 evsname = port['port']['network_id'] |
735 evsuuid = port['port']['network_id'] |
820 tenantname = port['port']['tenant_id'] |
736 tenantname = port['port']['tenant_id'] |
821 # TODO(gmoodalb): -- pull it from the network_id!! |
737 # TODO(gmoodalb): -- pull it from the network_id!! |
822 if not tenantname: |
738 if not tenantname: |
823 tenantname = context.tenant_id |
739 tenantname = context.tenant_id |
824 vport = self.evs_controller_addVPort(tenantname, evsname, vportname, |
740 pat = radcli.ADRGlobPattern({'name': evsuuid, |
825 propstr) |
741 'tenant': tenantname}) |
|
742 evs = self._rc.get_object(evsbind.EVS(), pat) |
|
743 vport = evs.addVPort(propstr, vportname) |
|
744 except radcli.ObjectError as oe: |
|
745 raise EVSControllerError(oe.get_payload().errmsg) |
|
746 |
|
747 retval = self._convert_vport_to_port(context, vport) |
826 retval = self._convert_vport_to_port(context, vport) |
748 |
827 |
749 # notify dhcp agent of port creation |
828 # notify dhcp agent of port creation |
750 self.dhcp_agent_notifier.notify(context, {'port': retval}, |
829 self.dhcp_agent_notifier.notify(context, {'port': retval}, |
751 'port.create.end') |
830 'port.create.end') |
752 return retval |
831 return retval |
|
832 |
|
833 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
834 def evs_controller_updateVPort(self, vportuuid, proplist): |
|
835 try: |
|
836 pat = radcli.ADRGlobPattern({'uuid': vportuuid}) |
|
837 vportlist = self._rc.list_objects(evsbind.VPort(), pat) |
|
838 assert len(vportlist) == 1 |
|
839 vport = self._rc.get_object(vportlist[0]) |
|
840 for prop in proplist: |
|
841 vport.setProperty(prop) |
|
842 except radcli.ObjectError as oe: |
|
843 raise EVSControllerError(oe.get_payload().errmsg) |
753 |
844 |
754 def update_port(self, context, id, port): |
845 def update_port(self, context, id, port): |
755 # EVS does not allow updating certain attributes |
846 # EVS does not allow updating certain attributes |
756 if not (set(port['port'].keys()) <= |
847 if not (set(port['port'].keys()) <= |
757 set(('device_id', 'device_owner'))): |
848 set(('device_id', 'device_owner'))): |
771 if device_owner is not None: |
862 if device_owner is not None: |
772 if len(device_owner) == 0: |
863 if len(device_owner) == 0: |
773 device_owner = " " |
864 device_owner = " " |
774 proplist.append("%s=%s" % |
865 proplist.append("%s=%s" % |
775 (PORT_VPORT_ATTRIBUTE_MAP['device_owner'], |
866 (PORT_VPORT_ATTRIBUTE_MAP['device_owner'], |
776 device_owner)) |
867 device_owner)) |
777 |
868 |
778 if not proplist: |
869 if not proplist: |
779 return dict() |
870 return dict() |
780 |
871 |
781 try: |
872 self.evs_controller_updateVPort(id, proplist) |
782 pat = radcli.ADRGlobPattern({'uuid': id}) |
|
783 vportlist = self._rc.list_objects(evsbind.VPort(), pat) |
|
784 assert len(vportlist) == 1 |
|
785 vport = self._rc.get_object(vportlist[0]) |
|
786 for prop in proplist: |
|
787 vport.setProperty(prop) |
|
788 except radcli.ObjectError as oe: |
|
789 raise EVSControllerError(oe.get_payload().errmsg) |
|
790 |
|
791 retval = self.get_port(context, id) |
873 retval = self.get_port(context, id) |
792 |
874 |
793 # notify dhcp agent of port update |
875 # notify dhcp agent of port update |
794 self.dhcp_agent_notifier.notify(context, {'port': retval}, |
876 self.dhcp_agent_notifier.notify(context, {'port': retval}, |
795 'port.update.end') |
877 'port.update.end') |
796 return retval |
878 return retval |
797 |
879 |
|
880 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
881 def evs_controller_getVPort(self, vportuuid): |
|
882 try: |
|
883 vportlist = self._evsc.getVPortInfo('vport=%s' % (vportuuid)) |
|
884 except radcli.ObjectError as oe: |
|
885 raise EVSControllerError(oe.get_payload().errmsg) |
|
886 return (vportlist[0] if vportlist else None) |
|
887 |
798 def get_port(self, context, id, fields=None): |
888 def get_port(self, context, id, fields=None): |
799 try: |
889 vport = self.evs_controller_getVPort(id) |
800 vportlist = self._evsc.getVPortInfo('vport=%s' % (id)) |
890 if not vport: |
801 except radcli.ObjectError as oe: |
891 return {} |
802 raise EVSControllerError(oe.get_payload().errmsg) |
892 portdict = self._convert_vport_to_port(context, vport) |
803 |
893 return self._fields(portdict, fields) |
804 if vportlist: |
894 |
805 portdict = self._convert_vport_to_port(context, vportlist[0]) |
895 @lockutils.synchronized('evs-plugin', 'neutron-') |
806 return self._fields(portdict, fields) |
896 def evs_controller_getVPortList(self, filterstr): |
807 return {} |
897 try: |
|
898 vportlist = self._evsc.getVPortInfo(filterstr) |
|
899 except radcli.ObjectError as oe: |
|
900 raise EVSControllerError(oe.get_payload().errmsg) |
|
901 return vportlist |
808 |
902 |
809 def get_ports(self, context, filters=None, fields=None, |
903 def get_ports(self, context, filters=None, fields=None, |
810 sorts=None, limit=None, marker=None, page_reverse=False): |
904 sorts=None, limit=None, marker=None, page_reverse=False): |
811 LOG.debug(_("inside the get_ports() method: filters: '%s'") % |
905 LOG.debug(_("inside the get_ports() method: filters: '%s'") % |
812 str(filters)) |
906 str(filters)) |
829 vport_props[PORT_VPORT_ATTRIBUTE_MAP[key]] = value |
923 vport_props[PORT_VPORT_ATTRIBUTE_MAP[key]] = value |
830 continue |
924 continue |
831 key = PORT_VPORT_ATTRIBUTE_MAP.get(key, key) |
925 key = PORT_VPORT_ATTRIBUTE_MAP.get(key, key) |
832 if isinstance(value, list): |
926 if isinstance(value, list): |
833 value = ",".join([str(val) for val in value]) |
927 value = ",".join([str(val) for val in value]) |
|
928 if not value: |
|
929 continue |
834 filterlist.append("%s=%s" % (key, value)) |
930 filterlist.append("%s=%s" % (key, value)) |
835 |
931 |
836 if filterlist: |
932 if filterlist: |
837 filterstr = ",".join(filterlist) |
933 filterstr = ",".join(filterlist) |
838 |
934 |
839 LOG.debug(_("calling getVPortInfo from get_ports(): '%s'") % |
935 LOG.debug(_("calling getVPortInfo from get_ports(): '%s'") % |
840 (filterstr)) |
936 (filterstr)) |
841 try: |
937 vportlist = self.evs_controller_getVPortList(filterstr) |
842 vportlist = self._evsc.getVPortInfo(filterstr) |
|
843 except radcli.ObjectError as oe: |
|
844 raise EVSControllerError(oe.get_payload().errmsg) |
|
845 |
|
846 self._apply_rsrc_props_filter(vportlist, vport_props) |
938 self._apply_rsrc_props_filter(vportlist, vport_props) |
847 |
939 |
848 retme = [] |
940 retme = [] |
849 for vport in vportlist: |
941 for vport in vportlist: |
850 portdict = self._convert_vport_to_port(context, vport) |
942 portdict = self._convert_vport_to_port(context, vport) |
870 'device_id': '', |
962 'device_id': '', |
871 'device_owner': '' |
963 'device_owner': '' |
872 } |
964 } |
873 } |
965 } |
874 self.update_port(context, port['id'], port_update) |
966 self.update_port(context, port['id'], port_update) |
875 routers = self.get_sync_data(context.elevated(), [router_id]) |
|
876 msg = l3_rpc_agent_api.L3AgentNotify.make_msg("routers_updated", |
967 msg = l3_rpc_agent_api.L3AgentNotify.make_msg("routers_updated", |
877 routers=routers) |
968 routers=[router_id]) |
878 l3_rpc_agent_api.L3AgentNotify.call(context, msg, |
969 l3_rpc_agent_api.L3AgentNotify.call(context, msg, |
879 topic=topics.L3_AGENT) |
970 topic=topics.L3_AGENT) |
|
971 |
|
972 @lockutils.synchronized('evs-plugin', 'neutron-') |
|
973 def evs_controller_removeVPort(self, tenantname, evsname, vportuuid): |
|
974 try: |
|
975 pat = radcli.ADRGlobPattern({'name': evsname, |
|
976 'tenant': tenantname}) |
|
977 evs = self._rc.get_object(evsbind.EVS(), pat) |
|
978 evs.removeVPort(vportuuid) |
|
979 except radcli.ObjectError as oe: |
|
980 raise EVSControllerError(oe.get_payload().errmsg) |
880 |
981 |
881 def delete_port(self, context, id, l3_port_check=True): |
982 def delete_port(self, context, id, l3_port_check=True): |
882 if l3_port_check: |
983 if l3_port_check: |
883 self.prevent_l3_port_deletion(context, id) |
984 self.prevent_l3_port_deletion(context, id) |
884 try: |
985 self.disassociate_floatingips(context, id) |
885 self.disassociate_floatingips(context, id) |
986 port = self.get_port(context, id) |
886 port = self.get_port(context, id) |
987 if not port: |
887 if not port: |
988 return |
888 return |
989 if not l3_port_check: |
889 if not l3_port_check: |
990 self._release_l3agent_internal_port(context, port) |
890 self._release_l3agent_internal_port(context, port) |
991 self.evs_controller_removeVPort(port['tenant_id'], port['network_id'], |
891 pat = radcli.ADRGlobPattern({'name': port['network_id'], |
992 id) |
892 'tenant': port['tenant_id']}) |
|
893 evs = self._rc.get_object(evsbind.EVS(), pat) |
|
894 evs.removeVPort(id) |
|
895 except radcli.ObjectError as oe: |
|
896 raise EVSControllerError(oe.get_payload().errmsg) |
|
897 |
993 |
898 # notify dhcp agent of port deletion |
994 # notify dhcp agent of port deletion |
899 payload = { |
995 payload = { |
900 'port': { |
996 'port': { |
901 'network_id': port['network_id'], |
997 'network_id': port['network_id'], |
906 |
1002 |
907 # needed for DHCP agent support |
1003 # needed for DHCP agent support |
908 def update_fixed_ip_lease_expiration(self, context, network_id, |
1004 def update_fixed_ip_lease_expiration(self, context, network_id, |
909 ip_address, lease_remaining): |
1005 ip_address, lease_remaining): |
910 pass |
1006 pass |
|
1007 |
|
1008 # needed for L3 agent support |
|
1009 def _get_network(self, context, network_id): |
|
1010 return self.get_network(context, network_id) |
|
1011 |
|
1012 def _get_subnet(self, context, subnet_id): |
|
1013 return self.get_subnet(context, subnet_id) |
|
1014 |
|
1015 def _get_port(self, context, port_id): |
|
1016 return self.get_port(context, port_id) |
|
1017 |
|
1018 def _delete_port(self, context, port_id): |
|
1019 return self.delete_port(context, port_id) |
|
1020 |
|
1021 def _get_subnets_by_network(self, context, network_id): |
|
1022 return self.get_subnets(context, filters={'network_id': network_id}) |
|
1023 |
|
1024 def _network_is_external(self, context, net_id): |
|
1025 try: |
|
1026 evs = self.get_network(context, net_id) |
|
1027 return evs[external_net.EXTERNAL] |
|
1028 except: |
|
1029 return False |