components/openstack/neutron/files/evs/plugin.py
changeset 1944 56ac2df1785b
parent 1832 30ac428a2aaf
child 1959 ba86b21a837b
child 3196 4c06db2d9388
equal deleted inserted replaced
1943:1a27f000029f 1944:56ac2df1785b
    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