Remove unused drivers and related code

Change-Id: I5306ceec11aa77f582eeb4a8e9666001667864f4
(cherry picked from commit 3087262c56)
This commit is contained in:
Sumit Naiksatam 2017-04-03 11:40:10 -07:00
parent 441bb72fcd
commit 47158fe945
11 changed files with 0 additions and 2729 deletions

View File

@ -1,47 +0,0 @@
# Copyright 2014 Alcatel-Lucent USA Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.plugins.ml2 import driver_api as api
from gbpservice.neutron.services.grouppolicy.drivers.nuage import driver
NOVA_PORT_OWNER_PREF = 'compute:'
class NuageMechanismGBPDriver(api.MechanismDriver):
def initialize(self):
self._nuage_gbp = None
@property
def nuage_gbp(self):
if not self._nuage_gbp:
self._nuage_gbp = (driver.NuageGBPDriver.
get_initialized_instance())
return self._nuage_gbp
def update_port_postcommit(self, context):
port = context.current
port_prefix = NOVA_PORT_OWNER_PREF
# Check two things prior to proceeding with
# talking to backend.
# 1) binding has happened successfully.
# 2) Its a VM port.
if ((not context.original_bound_segment and
context.bound_segment) and
port['device_owner'].startswith(port_prefix)):
self.nuage_gbp.create_nuage_policy_target(
context._plugin_context, context.current)

View File

@ -1,76 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.common import constants as n_constants
from neutron.extensions import portbindings
from neutron.plugins.common import constants
from neutron.plugins.ml2 import driver_api as api
from oslo_log import log as log
from gbpservice.neutron.services.grouppolicy.drivers.odl import odl_mapping
LOG = log.getLogger(__name__)
class OdlMechanismGBPDriver(api.MechanismDriver):
def initialize(self):
self._odl_gbp = None
self.vif_type = portbindings.VIF_TYPE_OVS
self.vif_details = {portbindings.CAP_PORT_FILTER: True}
@property
def odl_gbp(self):
if not self._odl_gbp:
self._odl_gbp = (odl_mapping.OdlMappingDriver.
get_initialized_instance())
return self._odl_gbp
def create_port_postcommit(self, context):
# DHCP Ports are created implicitly by Neutron, need to inform GBP
if (context.current.get('device_owner') ==
n_constants.DEVICE_OWNER_DHCP):
self.odl_gbp.create_dhcp_policy_target_if_needed(
context._plugin_context, context.current
)
def bind_port(self, context):
LOG.debug("Attempting to bind port %(port)s on "
"network %(network)s",
{'port': context.current['id'],
'network': context.network.current['id']})
for segment in context.network.network_segments:
if self._check_segment(segment):
context.set_binding(segment[api.ID],
self.vif_type,
self.vif_details,
status=n_constants.PORT_STATUS_ACTIVE)
LOG.debug("Bound using segment: %s", segment)
return
else:
LOG.debug("Refusing to bind port for segment ID %(id)s, "
"segment %(seg)s, phys net %(physnet)s, and "
"network type %(nettype)s",
{'id': segment[api.ID],
'seg': segment[api.SEGMENTATION_ID],
'physnet': segment[api.PHYSICAL_NETWORK],
'nettype': segment[api.NETWORK_TYPE]})
def _check_segment(self, segment):
"""Verify a segment is valid for the OpenDaylight MechanismDriver.
Verify the requested segment is supported by ODL and return True or
False to indicate this to callers.
"""
network_type = segment[api.NETWORK_TYPE]
return network_type in [constants.TYPE_VXLAN, ]

View File

@ -1,32 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
od_driver_opts = [
cfg.StrOpt('odl_username',
default='admin',
help=_("OpenDaylight Controller Username")),
cfg.StrOpt('odl_password',
default='admin',
help=_("OpenDaylight Controller Password")),
cfg.StrOpt('odl_host',
default='127.0.0.1',
help=_("OpenDaylight Controller host ip address")),
cfg.StrOpt('odl_port',
default='8080',
help=_("OpenDaylight Controller Rest API port number")),
]
cfg.CONF.register_opts(od_driver_opts, "odl_driver")

View File

@ -1,288 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import requests
from requests import auth
from neutron._i18n import _LI
from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
LOG = logging.getLogger(__name__)
cfg.CONF.import_opt(
'odl_username',
'gbpservice.neutron.services.grouppolicy.drivers.odl.config',
group='odl_driver'
)
cfg.CONF.import_opt(
'odl_password',
'gbpservice.neutron.services.grouppolicy.drivers.odl.config',
group='odl_driver'
)
cfg.CONF.import_opt(
'odl_host',
'gbpservice.neutron.services.grouppolicy.drivers.odl.config',
group='odl_driver'
)
cfg.CONF.import_opt(
'odl_port',
'gbpservice.neutron.services.grouppolicy.drivers.odl.config',
group='odl_driver'
)
class OdlManager(object):
"""Class to manage ODL translations and workflow.
This class manages translation from Neutron objects to APIC
managed objects and contains workflows to implement these
translations.
"""
def __init__(self):
LOG.info(_LI("Configured ODL username: %s"),
cfg.CONF.odl_driver.odl_username)
LOG.info(_LI("Configured ODL password: %s"),
cfg.CONF.odl_driver.odl_password)
LOG.info(_LI("Configured ODL host: %s"),
cfg.CONF.odl_driver.odl_host)
LOG.info(_LI("Configured ODL port: %s"),
cfg.CONF.odl_driver.odl_port)
self._username = cfg.CONF.odl_driver.odl_username
self._password = cfg.CONF.odl_driver.odl_password
self._host = cfg.CONF.odl_driver.odl_host
self._port = cfg.CONF.odl_driver.odl_port
self._headers = {
'Content-type': 'application/yang.data+json',
'Accept': 'application/yang.data+json',
}
self._base_url = (
"http://%(host)s:%(port)s/restconf" %
{'host': self._host, 'port': self._port}
)
self._reg_ep_url = (
self._base_url +
'/operations/endpoint:register-endpoint'
)
self._unreg_ep_url = (
self._base_url +
'/operations/endpoint:unregister-endpoint'
)
self._policy_url = (
self._base_url +
'/config/policy:tenants/policy:tenant/%(tenant_id)s'
)
self._action_url = (
self._policy_url +
'/subject-feature-instances/action-instance/%(action)s'
)
self._classifier_url = (
self._policy_url +
'/subject-feature-instances/classifier-instance/%(classifier)s'
)
self._l3ctx_url = (
self._policy_url +
'/l3-context/%(l3ctx)s'
)
self._l2bd_url = (
self._policy_url +
'/l2-bridge-domain/%(l2bd)s'
)
self._l2fd_url = (
self._policy_url +
'/l2-flood-domain/%(l2fd)s'
)
self._epg_url = (
self._policy_url +
'/policy:endpoint-group/%(epg)s'
)
self._subnet_url = (
self._policy_url +
'/subnet/%(subnet)s'
)
self._contract_url = (
self._policy_url +
'/policy:contract/%(contract)s'
)
def _convert2ascii(self, obj):
if isinstance(obj, dict):
return {self._convert2ascii(key): self._convert2ascii(value) for
key, value in obj.iteritems()}
elif isinstance(obj, list):
return [self._convert2ascii(element) for element in obj]
elif isinstance(obj, unicode):
return obj.encode('ascii', 'ignore')
else:
return obj
def _sendjson(self, method, url, headers, obj=None):
"""Send json to the ODL controller."""
medium = self._convert2ascii(obj) if obj else None
url = self._convert2ascii(url)
data = (
jsonutils.dumps(medium, indent=4, sort_keys=True) if medium
else None
)
LOG.debug("=========================================================")
LOG.debug("Sending METHOD (%(method)s) URL (%(url)s)",
{'method': method, 'url': url})
LOG.debug("(%(data)s)", {'data': data})
LOG.debug("=========================================================")
r = requests.request(
method,
url=url,
headers=headers,
data=data,
auth=auth.HTTPBasicAuth(self._username,
self._password)
)
r.raise_for_status()
def _is_tenant_created(self, tenant_id):
url = self._convert2ascii(self._policy_url % {'tenant_id': tenant_id})
r = requests.request(
'get',
url=url,
headers=self._headers,
auth=auth.HTTPBasicAuth(self._username,
self._password)
)
if r.status_code == 200:
return True
elif r.status_code == 404:
return False
else:
r.raise_for_status()
def register_endpoints(self, endpoints):
for ep in endpoints:
data = {"input": ep}
self._sendjson('post', self._reg_ep_url, self._headers, data)
def unregister_endpoints(self, endpoints):
for ep in endpoints:
data = {"input": ep}
self._sendjson('post', self._unreg_ep_url, self._headers, data)
def create_update_tenant(self, tenant_id, tenant):
url = (self._policy_url % {'tenant_id': tenant_id})
data = {"tenant": tenant}
self._sendjson('put', url, self._headers, data)
def create_action(self, tenant_id, action):
"""Create policy action"""
self._touch_tenant(tenant_id)
url = (self._action_url %
{'tenant_id': tenant_id, 'action': action['name']})
data = {"action-instance": action}
self._sendjson('put', url, self._headers, data)
def delete_action(self, tenant_id, action):
"""Delete policy action"""
url = (self._action_url %
{'tenant_id': tenant_id, 'action': action['name']})
self._sendjson('delete', url, self._headers)
def create_classifier(self, tenant_id, classifier):
"""Create policy classifier"""
self._touch_tenant(tenant_id)
url = (self._classifier_url %
{'tenant_id': tenant_id, 'classifier': classifier['name']})
data = {"classifier-instance": classifier}
self._sendjson('put', url, self._headers, data)
def delete_classifier(self, tenant_id, classifier):
"""Delete policy classifier"""
url = (self._classifier_url %
{'tenant_id': tenant_id, 'classifier': classifier['name']})
self._sendjson('delete', url, self._headers)
def create_update_l3_context(self, tenant_id, l3ctx):
self._touch_tenant(tenant_id)
url = (self._l3ctx_url %
{'tenant_id': tenant_id, 'l3ctx': l3ctx['id']})
data = {"l3-context": l3ctx}
self._sendjson('put', url, self._headers, data)
def delete_l3_context(self, tenant_id, l3ctx):
url = (self._l3ctx_url %
{'tenant_id': tenant_id, 'l3ctx': l3ctx['id']})
self._sendjson('delete', url, self._headers)
def create_update_l2_bridge_domain(self, tenant_id, l2bd):
self._touch_tenant(tenant_id)
url = (self._l2bd_url %
{'tenant_id': tenant_id, 'l2bd': l2bd['id']})
data = {"l2-bridge-domain": l2bd}
self._sendjson('put', url, self._headers, data)
def delete_l2_bridge_domain(self, tenant_id, l2bd):
url = (self._l2bd_url %
{'tenant_id': tenant_id, 'l2bd': l2bd['id']})
self._sendjson('delete', url, self._headers)
def create_update_l2_flood_domain(self, tenant_id, l2fd):
self._touch_tenant(tenant_id)
url = (self._l2fd_url %
{'tenant_id': tenant_id, 'l2fd': l2fd['id']})
data = {"l2-flood-domain": l2fd}
self._sendjson('put', url, self._headers, data)
def delete_l2_flood_domain(self, tenant_id, l2fd):
url = (self._l2fd_url %
{'tenant_id': tenant_id, 'l2fd': l2fd['id']})
self._sendjson('delete', url, self._headers)
def create_update_endpoint_group(self, tenant_id, epg):
self._touch_tenant(tenant_id)
url = (self._epg_url %
{'tenant_id': tenant_id, 'epg': epg['id']})
data = {"endpoint-group": epg}
self._sendjson('put', url, self._headers, data)
def delete_endpoint_group(self, tenant_id, epg):
url = (self._epg_url %
{'tenant_id': tenant_id, 'epg': epg['id']})
self._sendjson('delete', url, self._headers)
def create_update_subnet(self, tenant_id, subnet):
self._touch_tenant(tenant_id)
url = (self._subnet_url %
{'tenant_id': tenant_id, 'subnet': subnet['id']})
data = {"subnet": subnet}
self._sendjson('put', url, self._headers, data)
def delete_subnet(self, tenant_id, subnet):
url = (self._subnet_url %
{'tenant_id': tenant_id, 'subnet': subnet['id']})
self._sendjson('delete', url, self._headers)
def create_update_contract(self, tenant_id, contract):
url = (self._contract_url %
{'tenant_id': tenant_id, 'contract': contract['id']})
data = {"contract": contract}
self._sendjson('put', url, self._headers, data)
def _touch_tenant(self, tenant_id):
tenant = {
"id": tenant_id
}
if not self._is_tenant_created(tenant_id):
self.create_update_tenant(tenant_id, tenant)

View File

@ -1,636 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
from neutron.common import constants
from neutron import manager
from oslo_concurrency import lockutils # noqa
from oslo_log import log as logging
from gbpservice.neutron.db.grouppolicy import group_policy_mapping_db as gpdb
from gbpservice.neutron.services.grouppolicy.common import constants as g_const
from gbpservice.neutron.services.grouppolicy.common import exceptions as gpexc
from gbpservice.neutron.services.grouppolicy.drivers import (
resource_mapping as api)
from gbpservice.neutron.services.grouppolicy.drivers.odl import odl_manager
LOG = logging.getLogger(__name__)
class ExternalSegmentNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("External Segment currently not supported on ODL GBP "
"driver.")
class UpdateL3PolicyNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Update L3 Policy currently not supported on ODL GBP "
"driver.")
class UpdateL2PolicyNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Update L2 Policy currently not supported on ODL GBP "
"driver.")
class UpdatePTNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Update Policy Target currently not supported on ODL GBP "
"driver.")
class UpdatePTGNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Update Policy Target Group currently not supported on ODL "
"GBP driver.")
class L2PolicyMultiplePolicyTargetGroupNotSupportedOnOdlDriver(
gpexc.GroupPolicyBadRequest):
message = _("An L2 policy can't have multiple policy target groups on "
"ODL GBP driver.")
class UpdatePolicyActionNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Update Policy Action currently not supported on ODL GBP "
"driver.")
class RedirectActionNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Redirect action is currently not supported for ODL GBP "
"driver.")
class OnlyAllowActionSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Currently only allow action is supported for ODL GBP "
"driver.")
class UpdateClassifierNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Update Policy Classifier currently not supported on ODL GBP "
"driver.")
class PolicyRuleUpdateNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Policy rule update is not supported on for ODL GBP "
"driver.")
class PolicyRuleSetUpdateNotSupportedOnOdlDriver(gpexc.GroupPolicyBadRequest):
message = _("Policy rule set update is not supported on for ODL GBP "
"driver.")
class ExactlyOneActionPerRuleIsSupportedOnOdlDriver(
gpexc.GroupPolicyBadRequest):
message = _("Exactly one action per rule is supported on ODL GBP driver.")
class ClassifierTcpUdpPortRangeNotSupportedOnOdlDriver(
gpexc.GroupPolicyBadRequest):
message = _("Tcp or Udp port range is not supported on ODL GBP driver.")
class ClassifierUnknownIPProtocolNotSupportedOnOdlDriver(
gpexc.GroupPolicyBadRequest):
message = _("Unknown IP Protocol is not supported on ODL GBP driver.")
class OdlMappingDriver(api.ResourceMappingDriver):
"""ODL Mapping driver for Group Policy plugin.
This driver implements group policy semantics by mapping group
policy resources to various other neutron resources, and leverages
ODL backend for enforcing the policies.
"""
me = None
manager = None
@staticmethod
def get_odl_manager():
if not OdlMappingDriver.manager:
OdlMappingDriver.manager = odl_manager.OdlManager()
return OdlMappingDriver.manager
def initialize(self):
super(OdlMappingDriver, self).initialize()
self.odl_manager = OdlMappingDriver.get_odl_manager()
self._gbp_plugin = None
OdlMappingDriver.me = self
@property
def gbp_plugin(self):
if not self._gbp_plugin:
self._gbp_plugin = (manager.NeutronManager.get_service_plugins()
.get("GROUP_POLICY"))
return self._gbp_plugin
@staticmethod
def get_initialized_instance():
return OdlMappingDriver.me
def create_dhcp_policy_target_if_needed(self, plugin_context, port):
session = plugin_context.session
if (self._port_is_owned(session, port['id'])):
# Nothing to do
return
# Retrieve PTG
# TODO(ywu): optimize later
subnets = self._core_plugin._get_subnets_by_network(
plugin_context, port['network_id']
)
ptg = (plugin_context.session.query(gpdb.PolicyTargetGroupMapping).
join(gpdb.PolicyTargetGroupMapping.subnets).
filter(gpdb.PTGToSubnetAssociation.subnet_id ==
subnets[0]['id']).
first())
# Create PolicyTarget
attrs = {'policy_target':
{'tenant_id': port['tenant_id'],
'name': 'dhcp-%s' % ptg['id'],
'description': ("Implicitly created DHCP policy "
"target"),
'policy_target_group_id': ptg['id'],
'port_id': port['id']}}
self.gbp_plugin.create_policy_target(plugin_context, attrs)
# TODO(ODL): security group is not required
# sg_id = self._ensure_default_security_group(plugin_context,
# port['tenant_id'])
# data = {'port': {'security_groups': [sg_id]}}
# self._core_plugin.update_port(plugin_context, port['id'], data)
def create_external_segment_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def update_external_segment_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def delete_external_segment_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def create_external_policy_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def update_external_policy_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def delete_external_policy_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def create_nat_pool_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def update_nat_pool_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def delete_nat_pool_precommit(self, context):
raise ExternalSegmentNotSupportedOnOdlDriver()
def create_policy_target_postcommit(self, context):
super(OdlMappingDriver, self).create_policy_target_postcommit(context)
pt = self._get_pt_detail(context)
ep = {
"endpoint-group": pt['ptg_id'],
"l2-context": pt['l2ctx_id'],
"l3-address": pt['l3_list'],
"mac-address": pt['mac_address'],
"port-name": pt['neutron_port_id'],
"tenant": pt['tenant_id']
}
self.odl_manager.register_endpoints([ep])
def update_policy_target_precommit(self, context):
raise UpdatePTNotSupportedOnOdlDriver()
def delete_policy_target_postcommit(self, context):
pt = self._get_pt_detail(context)
ep = {
"l2": pt['l2_list'],
"l3": pt['l3_list']
}
self.odl_manager.unregister_endpoints([ep])
# Delete Neutron's port
super(OdlMappingDriver, self).delete_policy_target_postcommit(context)
def create_l3_policy_postcommit(self, context):
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
l3ctx = {
"id": context.current['id'],
"name": context.current['name'],
"description": context.current['description']
}
self.odl_manager.create_update_l3_context(tenant_id, l3ctx)
def update_l3_policy_precommit(self, context):
raise UpdateL3PolicyNotSupportedOnOdlDriver()
def delete_l3_policy_postcommit(self, context):
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
l3ctx = {
"id": context.current['id']
}
self.odl_manager.delete_l3_context(tenant_id, l3ctx)
def create_l2_policy_postcommit(self, context):
super(OdlMappingDriver, self).create_l2_policy_postcommit(context)
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
# l2_policy mapped to l2_bridge_domain in ODL
l2bd = {
"id": context.current['id'],
"name": context.current['name'],
"description": context.current['description'],
"parent": context.current['l3_policy_id']
}
self.odl_manager.create_update_l2_bridge_domain(tenant_id, l2bd)
# Implicit network within l2 policy mapped to l2 FD in ODL
net_id = context.current['network_id']
network = self._core_plugin.get_network(context._plugin_context,
net_id)
l2fd = {
"id": net_id,
"name": network['name'],
"parent": context.current['id']
}
self.odl_manager.create_update_l2_flood_domain(tenant_id, l2fd)
def update_l2_policy_precommit(self, context):
raise UpdateL2PolicyNotSupportedOnOdlDriver()
def delete_l2_policy_postcommit(self, context):
super(OdlMappingDriver, self).delete_l2_policy_postcommit(context)
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
# l2_policy mapped to l2_bridge_domain in ODL
l2bd = {
"id": context.current['id']
}
self.odl_manager.delete_l2_bridge_domain(tenant_id, l2bd)
# Implicit network within l2 policy mapped to l2 FD in ODL
net_id = context.current['network_id']
l2fd = {
"id": net_id,
}
self.odl_manager.delete_l2_flood_domain(tenant_id, l2fd)
def create_policy_target_group_postcommit(self, context):
super(OdlMappingDriver, self).create_policy_target_group_postcommit(
context)
# consumed_policy_rule_sets mapped to consumer_named_selectors
consumer_named_selectors = []
for prs_id in context.current['consumed_policy_rule_sets']:
prs = context._plugin.get_policy_rule_set(
context._plugin_context, prs_id
)
consumer_named_selectors.append(
{
"name": prs['name'],
"contract": prs_id
}
)
# provided_policy_rule_sets mapped to provider_named_selectors
provider_named_selectors = []
for prs_id in context.current['provided_policy_rule_sets']:
prs = context._plugin.get_policy_rule_set(
context._plugin_context, prs_id
)
provider_named_selectors.append(
{
"name": prs['name'],
"contract": prs_id
}
)
# PTG mapped to EPG in ODL
subnets = context.current['subnets']
epg = {
"id": context.current['id'],
"name": context.current['name'],
"description": context.current['description'],
"network-domain": subnets[0],
"consumer-named-selector": consumer_named_selectors,
"provider-named-selector": provider_named_selectors
}
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
self.odl_manager.create_update_endpoint_group(tenant_id, epg)
# Implicit subnet within policy target group mapped to subnet in ODL
for subnet_id in subnets:
neutron_subnet = self._core_plugin.get_subnet(
context._plugin_context, subnet_id
)
odl_subnet = {
"id": subnet_id,
"ip-prefix": neutron_subnet['cidr'],
"parent": neutron_subnet['network_id'],
"virtual-router-ip": neutron_subnet['gateway_ip']
}
self.odl_manager.create_update_subnet(tenant_id, odl_subnet)
def update_policy_target_group_precommit(self, context):
raise UpdatePTGNotSupportedOnOdlDriver()
def delete_policy_target_group_postcommit(self, context):
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
subnets = context.current['subnets']
# delete mapped subnets in ODL, and clean them up from neutron
for subnet_id in subnets:
self._cleanup_subnet(context._plugin_context, subnet_id, None)
odl_subnet = {
"id": subnet_id
}
self.odl_manager.delete_subnet(tenant_id, odl_subnet)
# delete mapped EPG in ODL
epg = {
"id": context.current['id'],
}
self.odl_manager.delete_endpoint_group(tenant_id, epg)
def create_policy_action_precommit(self, context):
# TODO(odl): allow redirect for service chaining
if context.current['action_type'] == g_const.GP_ACTION_REDIRECT:
raise RedirectActionNotSupportedOnOdlDriver()
def create_policy_action_postcommit(self, context):
super(OdlMappingDriver, self).create_policy_action_postcommit(context)
# TODO(ODL): remove comment out after PoC
# tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
# fill in action instance data
if context.current['action_type'] == g_const.GP_ACTION_ALLOW:
# TODO(ODL): remove the return and comment out after POC
return
# action_definition_id = "f942e8fd-e957-42b7-bd18-f73d11266d17"
# action_instance = {
# "action-definition-id": action_definition_id,
# "name": context.current['name'],
# "parameter-value": [
# {
# "name": context.current['name'],
# "string-value": context.current['action_type'],
# }
# ]
# }
# self.odl_manager.create_action(tenant_id, action_instance)
else:
raise OnlyAllowActionSupportedOnOdlDriver()
def update_policy_action_precommit(self, context):
raise UpdatePolicyActionNotSupportedOnOdlDriver()
def delete_policy_action_postcommit(self, context):
super(OdlMappingDriver, self).delete_policy_action_postcommit(context)
# TODO(ODL): remove comment out after PoC
# tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
#
# # fill in action instance data
# action_instance = {
# "name": context.current['name']
# }
# self.odl_manager.delete_action(tenant_id, action_instance)
def create_policy_classifier_postcommit(self, context):
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
classifiers = self._make_odl_classifiers(context.current)
for classifier in classifiers:
classifier_instance = {
"classifier-definition-id":
classifier['classifier-definition-id'],
"name": classifier['name'],
"parameter-value": classifier['parameter-value']
}
self.odl_manager.create_classifier(tenant_id, classifier_instance)
def _make_odl_classifiers(self, stack_classifier):
classifiers = []
if stack_classifier['protocol'] == constants.PROTO_NAME_ICMP:
direction = stack_classifier['direction']
if direction == 'bi':
direction = "bidirectional"
classifier = {
# Use hard coded value based on current ODL implementation
"classifier-definition-id":
'79c6fdb2-1e1a-4832-af57-c65baf5c2335',
"name": stack_classifier['name'],
"parameter-value": [
{
"name": "proto",
# TODO(yapeng): change the hard code value
"int-value": 1,
}
],
"direction": direction
}
classifiers.append(classifier)
else:
# For TCP and UDP protoocol create two classifier (in and out)
for port in ['sourceport', 'destport']:
if stack_classifier['direction'] == 'in':
if port == 'destport':
direction = 'in'
else:
direction = 'out'
elif stack_classifier['direction'] == 'out':
if port == 'destport':
direction = 'out'
else:
direction = 'in'
else:
direction = 'bidirectional'
classifier = {
# Use hard coded value based on current ODL implementation
"classifier-definition-id":
'4250ab32-e8b8-445a-aebb-e1bd2cdd291f',
"direction": direction,
"name": stack_classifier['name'] + '-' + port,
"parameter-value": [
{
"name": "type",
"string-value": stack_classifier['protocol'],
},
{
"name": port,
"int-value": stack_classifier['port_range'],
}
]
}
classifiers.append(classifier)
return classifiers
def update_policy_classifier_precommit(self, context):
raise UpdateClassifierNotSupportedOnOdlDriver()
def delete_policy_classifier_postcommit(self, context):
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
if context.current['protocol'] == constants.PROTO_NAME_ICMP:
# fill in classifier instance data
classifier_instance = {
"name": context.current['name']
}
self.odl_manager.delete_classifier(tenant_id, classifier_instance)
return
# fill in classifier instance data
for port in ['sourceport', 'destport']:
classifier_instance = {
"name": context.current['name'] + '-' + port,
}
self.odl_manager.delete_classifier(tenant_id, classifier_instance)
def create_policy_rule_precommit(self, context):
if ('policy_actions' in context.current and
len(context.current['policy_actions']) != 1):
# TODO(odl): to be fixed when redirect is supported
raise ExactlyOneActionPerRuleIsSupportedOnOdlDriver()
def update_policy_rule_precommit(self, context):
# TODO(ivar): add support for action update on policy rules
raise PolicyRuleUpdateNotSupportedOnOdlDriver()
def create_policy_rule_set_postcommit(self, context):
"""Each Policy Rule Set is mapped to a contract, with a single clause
Each included Policy Rule will be mapped to one subject, which includes
one rule.
The clause has no matcher, but refers to all the subjects
"""
subjects = []
subject_names = []
for rule_id in context.current['policy_rules']:
subject = self._make_odl_subject(context, rule_id)
subjects.append(subject)
subject_names.append(subject['name'])
clauses = [
{
"name": context.current['name'],
"subject-refs": subject_names
}
]
contract_id = context.current['id']
contract_desc = context.current['name']
contract = {
"id": contract_id,
"description": contract_desc,
"clause": clauses,
"subject": subjects
}
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
self.odl_manager.create_update_contract(tenant_id, contract)
def _make_odl_subject(self, context, rule_id):
gbp_rule = context._plugin.get_policy_rule(
context._plugin_context, rule_id
)
odl_rules = []
odl_rule = self._make_odl_rule(context, rule_id)
odl_rules.append(odl_rule)
return {
"name": gbp_rule['name'],
"rule": odl_rules
}
def _make_odl_rule(self, context, rule_id):
rule = context._plugin.get_policy_rule(
context._plugin_context, rule_id
)
stack_classifier = context._plugin.get_policy_classifier(
context._plugin_context, rule['policy_classifier_id']
)
# while openstack supports only one classifier per rule, the classifier
# may mapped to multi classifier in ODL
classifier_refs = []
classifiers = self._make_odl_classifiers(stack_classifier)
for classifier in classifiers:
classifier_ref = {
"name": classifier['name']
}
if classifier['direction'] != "bidirectional":
classifier_ref['direction'] = classifier['direction']
classifier_refs.append(classifier_ref)
action_refs = []
for action_id in rule['policy_actions']:
action = context._plugin.get_policy_action(
context._plugin_context, action_id
)
action_refs.append(
{
"name": action['name']
}
)
# TODO(ODL): send action_refs later but not for PoC
return {
"name": rule['name'],
"classifier-ref": classifier_refs,
}
def update_policy_rule_set_precommit(self, context):
# TODO(Yi): add support for action update on policy rule sets
raise PolicyRuleSetUpdateNotSupportedOnOdlDriver()
def _get_pt_detail(self, context):
port_id = context.current['port_id']
port = self._core_plugin.get_port(context._plugin_context, port_id)
tenant_id = uuid.UUID(context.current['tenant_id']).urn[9:]
ptg_id = context.current['policy_target_group_id']
ptg = self.gbp_plugin.get_policy_target_group(context._plugin_context,
ptg_id)
l2ctx_id = ptg['l2_policy_id']
l2ctx = self.gbp_plugin.get_l2_policy(context._plugin_context,
l2ctx_id)
l3ctx_id = l2ctx['l3_policy_id']
mac_address = port['mac_address']
neutron_port_id = 'tap' + port_id[:11]
l3_list = []
for fixed_ip in port['fixed_ips']:
l3_list.append(
{
"ip-address": fixed_ip['ip_address'],
"l3-context": l3ctx_id
}
)
l2_list = [
{
"l2-context": l2ctx_id,
"mac-address": mac_address
}
]
return {
"port_id": port_id,
"tenant_id": tenant_id,
"ptg_id": ptg_id,
"l2ctx_id": l2ctx_id,
"l3ctx_id": l3ctx_id,
"mac_address": mac_address,
"neutron_port_id": neutron_port_id,
"l3_list": l3_list,
"l2_list": l2_list,
}

View File

@ -1,463 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import requests
import unittest
import mock
from oslo_serialization import jsonutils
from gbpservice.neutron.services.grouppolicy import config
from gbpservice.neutron.services.grouppolicy.drivers.odl import odl_manager
HOST = 'fake_host'
PORT = 'fake_port'
USERNAME = 'fake_username'
PASSWORD = 'fake_password'
HEADER = {
'Content-type': 'application/yang.data+json',
'Accept': 'application/yang.data+json',
}
VALUE = 'fake_value'
TENANT_ID = 'fake_tenant_id'
TENANT = {
'id': TENANT_ID,
'value': VALUE
}
ENDPOINT = 'fake_endpoint'
ACTION_NAME = 'fake_action_name'
ACTION = {
'name': ACTION_NAME,
'value': VALUE
}
CLASSIFIER_NAME = 'fake_classifier_name'
CLASSIFIER = {
'name': CLASSIFIER_NAME,
'value': VALUE
}
L3CTX_ID = 'fake_l3ctx_id'
L3CTX = {
'id': L3CTX_ID,
'value': VALUE
}
L2BD_ID = 'fake_l2bd_id'
L2BD = {
'id': L2BD_ID,
'value': VALUE
}
L2FD_ID = 'fake_l2bd_id'
L2FD = {
'id': L2FD_ID,
'value': VALUE
}
EPG_ID = 'fake_epg_id'
EPG = {
'id': EPG_ID,
'value': VALUE
}
SUBNET_ID = 'fake_subnet_id'
SUBNET = {
'id': SUBNET_ID,
'value': VALUE
}
CONTRACT_ID = 'fake_contract_id'
CONTRACT = {
'id': CONTRACT_ID,
'value': VALUE
}
URL_BASE = ("http://%(host)s:%(port)s/restconf" %
{'host': HOST, 'port': PORT})
URL_REG_EP = (URL_BASE +
'/operations/endpoint:register-endpoint')
URL_UNREG_EP = (URL_BASE +
'/operations/endpoint:unregister-endpoint')
URL_TENANT = (URL_BASE +
'/config/policy:tenants/policy:tenant/%s' %
TENANT_ID)
URL_ACTION = (URL_TENANT +
'/subject-feature-instances/action-instance/%s' %
ACTION_NAME)
URL_CLASSIFIER = (URL_TENANT +
'/subject-feature-instances/classifier-instance/%s' %
CLASSIFIER_NAME)
URL_L3CTX = (URL_TENANT + '/l3-context/%s' % L3CTX_ID)
URL_L2BD = (URL_TENANT + '/l2-bridge-domain/%s' % L2BD_ID)
URL_L2FD = (URL_TENANT + '/l2-flood-domain/%s' % L2FD_ID)
URL_EPG = (URL_TENANT + '/policy:endpoint-group/%s' % EPG_ID)
URL_SUBNET = (URL_TENANT + '/subnet/%s' % SUBNET_ID)
URL_CONTRACT = (URL_TENANT + '/policy:contract/%s' % CONTRACT_ID)
class AuthMatcher(object):
""" A customized class to check if authentication object is matched or not
AS authentication is passed as an object reference, we cannot test the
object directly, instead, we check if the correct username and password
is used
"""
def __eq__(self, obj):
return (obj.username == USERNAME and obj.password == PASSWORD)
class DataMatcher(object):
""" A customized class to check if data is matched or not
As data is passed as a string for HTTP request in ODL manager, we cannot
directly test the data object. Instead, we have to convert the data to
the string in the same format
"""
def __init__(self, obj):
self._data = jsonutils.dumps(
obj,
indent=4,
sort_keys=True
)
def __eq__(self, obj):
return (self._data == obj)
class OdlManagerTestCase(unittest.TestCase):
""" Test case for ODL manager testing
Set up the testing environment
"""
def setUp(self):
config.cfg.CONF.set_override('odl_username',
USERNAME,
group='odl_driver')
config.cfg.CONF.set_override('odl_password',
PASSWORD,
group='odl_driver')
config.cfg.CONF.set_override('odl_host',
HOST,
group='odl_driver')
config.cfg.CONF.set_override('odl_port',
PORT,
group='odl_driver')
self.manager = odl_manager.OdlManager()
# test a single HTTP request
def _test_single_request_operation(
self,
http_method,
tested_method,
*args,
**kwargs
):
with mock.patch('requests.request') as mock_request:
tested_method(*args)
mock_request.assert_called_once_with(
http_method,
**kwargs
)
# In some ODL manager operations, ODL manager needs to check if a tenant
# is existing or not, if not, the ODL manager needs to create the tenant
# first -- such a scenario needs to be tested with this method
def _test_multi_request_operations(
self,
http_method,
tested_method,
*args,
**kwargs
):
with mock.patch.object(odl_manager.OdlManager,
'_is_tenant_created') as mock_is_tenant_created:
with mock.patch('requests.request') as mock_request:
mock_is_tenant_created.return_value = True
tested_method(*args)
mock_request.assert_called_once_with(
http_method,
**kwargs
)
mock_is_tenant_created.return_value = False
mock_request.reset_mock()
tested_method(*args)
mock_request.assert_any_call(
'put',
url=URL_TENANT,
headers=HEADER,
data=DataMatcher({'tenant': {'id': TENANT_ID}}),
auth=AuthMatcher()
)
mock_request.assert_any_call(
http_method,
**kwargs
)
@mock.patch.object(requests, 'request')
def test_is_tenant_created(self, mock_request):
mock_request.return_value = mock.Mock(
status_code=200
)
assert self.manager._is_tenant_created(TENANT_ID)
mock_request.assert_called_once_with(
'get',
url=URL_TENANT,
headers=HEADER,
auth=AuthMatcher()
)
mock_request.reset_mock()
mock_request.return_value = mock.Mock(
status_code=404
)
assert not self.manager._is_tenant_created(TENANT_ID)
mock_request.assert_called_once_with(
'get',
url=URL_TENANT,
headers=HEADER,
auth=AuthMatcher()
)
def test_register_endpoints(self):
method = getattr(self.manager, 'register_endpoints')
self._test_single_request_operation(
'post',
method,
[ENDPOINT],
url=URL_REG_EP,
headers=HEADER,
data=DataMatcher({'input': ENDPOINT}),
auth=AuthMatcher()
)
def test_unregister_endpoints(self):
method = getattr(self.manager, 'unregister_endpoints')
self._test_single_request_operation(
'post',
method,
[ENDPOINT],
url=URL_UNREG_EP,
headers=HEADER,
data=DataMatcher({'input': ENDPOINT}),
auth=AuthMatcher()
)
def test_create_update_tenant(self):
method = getattr(self.manager, 'create_update_tenant')
self._test_single_request_operation(
'put',
method,
TENANT_ID,
TENANT,
url=URL_TENANT,
headers=HEADER,
data=DataMatcher({'tenant': TENANT}),
auth=AuthMatcher()
)
def test_create_action(self):
method = getattr(self.manager, 'create_action')
self._test_multi_request_operations(
'put',
method,
TENANT_ID,
ACTION,
url=URL_ACTION,
headers=HEADER,
data=DataMatcher({'action-instance': ACTION}),
auth=AuthMatcher()
)
def test_delete_action(self):
method = getattr(self.manager, 'delete_action')
self._test_single_request_operation(
'delete',
method,
TENANT_ID,
ACTION,
url=URL_ACTION,
headers=HEADER,
data=None,
auth=AuthMatcher()
)
def test_create_classifier(self):
method = getattr(self.manager, 'create_classifier')
self._test_multi_request_operations(
'put',
method,
TENANT_ID,
CLASSIFIER,
url=URL_CLASSIFIER,
headers=HEADER,
data=DataMatcher({'classifier-instance': CLASSIFIER}),
auth=AuthMatcher()
)
def test_delete_classifier(self):
method = getattr(self.manager, 'delete_classifier')
self._test_single_request_operation(
'delete',
method,
TENANT_ID,
CLASSIFIER,
url=URL_CLASSIFIER,
headers=HEADER,
data=None,
auth=AuthMatcher()
)
def test_create_update_l3_context(self):
method = getattr(self.manager, 'create_update_l3_context')
self._test_multi_request_operations(
'put',
method,
TENANT_ID,
L3CTX,
url=URL_L3CTX,
headers=HEADER,
data=DataMatcher({'l3-context': L3CTX}),
auth=AuthMatcher()
)
def test_delete_l3_context(self):
method = getattr(self.manager, 'delete_l3_context')
self._test_single_request_operation(
'delete',
method,
TENANT_ID,
L3CTX,
url=URL_L3CTX,
headers=HEADER,
data=None,
auth=AuthMatcher()
)
def test_create_update_l2_bridge_domain(self):
method = getattr(self.manager, 'create_update_l2_bridge_domain')
self._test_multi_request_operations(
'put',
method,
TENANT_ID,
L2BD,
url=URL_L2BD,
headers=HEADER,
data=DataMatcher({'l2-bridge-domain': L2BD}),
auth=AuthMatcher()
)
def test_delete_l2_bridge_domain(self):
method = getattr(self.manager, 'delete_l2_bridge_domain')
self._test_single_request_operation(
'delete',
method,
TENANT_ID,
L2BD,
url=URL_L2BD,
headers=HEADER,
data=None,
auth=AuthMatcher()
)
def test_create_update_l2_flood_domain(self):
method = getattr(self.manager, 'create_update_l2_flood_domain')
self._test_multi_request_operations(
'put',
method,
TENANT_ID,
L2FD,
url=URL_L2FD,
headers=HEADER,
data=DataMatcher({'l2-flood-domain': L2FD}),
auth=AuthMatcher()
)
def test_delete_l2_flood_domain(self):
method = getattr(self.manager, 'delete_l2_flood_domain')
self._test_single_request_operation(
'delete',
method,
TENANT_ID,
L2FD,
url=URL_L2FD,
headers=HEADER,
data=None,
auth=AuthMatcher()
)
def test_create_update_endpoint_group(self):
method = getattr(self.manager, 'create_update_endpoint_group')
self._test_multi_request_operations(
'put',
method,
TENANT_ID,
EPG,
url=URL_EPG,
headers=HEADER,
data=DataMatcher({'endpoint-group': EPG}),
auth=AuthMatcher()
)
def test_delete_endpoint_group(self):
method = getattr(self.manager, 'delete_endpoint_group')
self._test_single_request_operation(
'delete',
method,
TENANT_ID,
EPG,
url=URL_EPG,
headers=HEADER,
data=None,
auth=AuthMatcher()
)
def test_create_update_subnet(self):
method = getattr(self.manager, 'create_update_subnet')
self._test_multi_request_operations(
'put',
method,
TENANT_ID,
SUBNET,
url=URL_SUBNET,
headers=HEADER,
data=DataMatcher({'subnet': SUBNET}),
auth=AuthMatcher()
)
def test_delete_subnet(self):
method = getattr(self.manager, 'delete_subnet')
self._test_single_request_operation(
'delete',
method,
TENANT_ID,
SUBNET,
url=URL_SUBNET,
headers=HEADER,
data=None,
auth=AuthMatcher()
)
def test_create_update_contract(self):
method = getattr(self.manager, 'create_update_contract')
self._test_single_request_operation(
'put',
method,
TENANT_ID,
CONTRACT,
url=URL_CONTRACT,
headers=HEADER,
data=DataMatcher({'contract': CONTRACT}),
auth=AuthMatcher()
)

View File

@ -68,15 +68,10 @@ gbpservice.neutron.group_policy.policy_drivers =
chain_mapping = gbpservice.neutron.services.grouppolicy.drivers.chain_mapping:ChainMappingDriver
aim_mapping = gbpservice.neutron.services.grouppolicy.drivers.cisco.apic.aim_mapping:AIMMappingDriver
apic = gbpservice.neutron.services.grouppolicy.drivers.cisco.apic.apic_mapping:ApicMappingDriver
odl = gbpservice.neutron.services.grouppolicy.drivers.odl.odl_mapping:OdlMappingDriver
oneconvergence_gbp_driver = gbpservice.neutron.services.grouppolicy.drivers.oneconvergence.nvsd_gbp_driver:NvsdGbpDriver
nuage_gbp_driver = gbpservice.neutron.services.grouppolicy.drivers.nuage.driver:NuageGBPDriver
neutron.ml2.mechanism_drivers =
logger_plus = gbpservice.neutron.tests.unit.plugins.ml2plus.drivers.mechanism_logger:LoggerPlusMechanismDriver
apic_aim = gbpservice.neutron.plugins.ml2plus.drivers.apic_aim.mechanism_driver:ApicMechanismDriver
apic_gbp = gbpservice.neutron.plugins.ml2.drivers.grouppolicy.apic.driver:APICMechanismGBPDriver
nuage_gbp = gbpservice.neutron.plugins.ml2.drivers.grouppolicy.nuage.driver:NuageMechanismGBPDriver
odl_gbp = gbpservice.neutron.plugins.ml2.drivers.grouppolicy.odl.driver:OdlMechanismGBPDriver
stitching_gbp = gbpservice.neutron.plugins.ml2.drivers.grouppolicy.stitching.driver:TrafficStitchingMechanismGBPDriver
neutron.ml2.extension_drivers =
apic_aim = gbpservice.neutron.plugins.ml2plus.drivers.apic_aim.extension_driver:ApicExtensionDriver
@ -85,7 +80,6 @@ neutron.ml2.extension_drivers =
gbpservice.neutron.servicechain.servicechain_drivers =
dummy = gbpservice.neutron.services.servicechain.plugins.msc.drivers.dummy_driver:NoopDriver
simplechain_driver = gbpservice.neutron.services.servicechain.plugins.msc.drivers.simplechain_driver:SimpleChainDriver
oneconvergence_servicechain_driver = gbpservice.neutron.services.servicechain.plugins.msc.drivers.oneconvergence_servicechain_driver:OneconvergenceServiceChainDriver
gbpservice.neutron.servicechain.ncp_drivers =
node_dummy = gbpservice.neutron.services.servicechain.plugins.ncp.node_drivers.dummy_driver:NoopNodeDriver
heat_node_driver = gbpservice.neutron.services.servicechain.plugins.ncp.node_drivers.heat_node_driver:HeatNodeDriver