# example of non-default provider:
# service_provider=FIREWALL:name2:firewall_driver_path
# --- Reference implementations ---
-service_provider=LOADBALANCER:Haproxy:neutron.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
-service_provider=VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
+service_provider=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
+service_provider=VPN:openswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
# In order to activate Radware's lbaas driver you need to uncomment the next line.
# If you want to keep the HA Proxy as the default lbaas driver, remove the attribute default from the line below.
# Otherwise comment the HA Proxy line
-# service_provider = LOADBALANCER:Radware:neutron.services.loadbalancer.drivers.radware.driver.LoadBalancerDriver:default
+# service_provider = LOADBALANCER:Radware:neutron_lbaas.services.loadbalancer.drivers.radware.driver.LoadBalancerDriver:default
# uncomment the following line to make the 'netscaler' LBaaS provider available.
-# service_provider=LOADBALANCER:NetScaler:neutron.services.loadbalancer.drivers.netscaler.netscaler_driver.NetScalerPluginDriver
+# service_provider=LOADBALANCER:NetScaler:neutron_lbaas.services.loadbalancer.drivers.netscaler.netscaler_driver.NetScalerPluginDriver
# Uncomment the following line (and comment out the OpenSwan VPN line) to enable Cisco's VPN driver.
-# service_provider=VPN:cisco:neutron.services.vpn.service_drivers.cisco_ipsec.CiscoCsrIPsecVPNDriver:default
+# service_provider=VPN:cisco:neutron_vpnaas.services.vpn.service_drivers.cisco_ipsec.CiscoCsrIPsecVPNDriver:default
# Uncomment the line below to use Embrane heleos as Load Balancer service provider.
-# service_provider=LOADBALANCER:Embrane:neutron.services.loadbalancer.drivers.embrane.driver.EmbraneLbaas:default
+# service_provider=LOADBALANCER:Embrane:neutron_lbaas.services.loadbalancer.drivers.embrane.driver.EmbraneLbaas:default
# Uncomment the line below to use the A10 Networks LBaaS driver. Requires 'pip install a10-neutron-lbaas'.
-#service_provider = LOADBALANCER:A10Networks:neutron.services.loadbalancer.drivers.a10networks.driver_v1.ThunderDriver:default
+# service_provider = LOADBALANCER:A10Networks:neutron_lbaas.services.loadbalancer.drivers.a10networks.driver_v1.ThunderDriver:default
# Uncomment the following line to test the LBaaS v2 API _WITHOUT_ a real backend
-# service_provider = LOADBALANCER:LoggingNoop:neutron.services.loadbalancer.drivers.logging_noop.driver.LoggingNoopLoadBalancerDriver:default
+# service_provider = LOADBALANCER:LoggingNoop:neutron_lbaas.services.loadbalancer.drivers.logging_noop.driver.LoggingNoopLoadBalancerDriver:default
+++ /dev/null
-# Copyright 2013 Big Switch Networks, Inc.
-# All Rights Reserved.
-#
-# 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
-
-import sqlalchemy as sa
-from sqlalchemy.ext.orderinglist import ordering_list
-from sqlalchemy import orm
-from sqlalchemy.orm import exc
-
-from neutron.db import common_db_mixin as base_db
-from neutron.db import model_base
-from neutron.db import models_v2
-from neutron.extensions import firewall
-from neutron import manager
-from neutron.openstack.common import log as logging
-from neutron.openstack.common import uuidutils
-from neutron.plugins.common import constants as const
-
-
-LOG = logging.getLogger(__name__)
-
-
-class FirewallRule(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a Firewall rule."""
- __tablename__ = 'firewall_rules'
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(1024))
- firewall_policy_id = sa.Column(sa.String(36),
- sa.ForeignKey('firewall_policies.id'),
- nullable=True)
- shared = sa.Column(sa.Boolean)
- protocol = sa.Column(sa.String(40))
- ip_version = sa.Column(sa.Integer, nullable=False)
- source_ip_address = sa.Column(sa.String(46))
- destination_ip_address = sa.Column(sa.String(46))
- source_port_range_min = sa.Column(sa.Integer)
- source_port_range_max = sa.Column(sa.Integer)
- destination_port_range_min = sa.Column(sa.Integer)
- destination_port_range_max = sa.Column(sa.Integer)
- action = sa.Column(sa.Enum('allow', 'deny', name='firewallrules_action'))
- enabled = sa.Column(sa.Boolean)
- position = sa.Column(sa.Integer)
-
-
-class Firewall(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a Firewall resource."""
- __tablename__ = 'firewalls'
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(1024))
- shared = sa.Column(sa.Boolean)
- admin_state_up = sa.Column(sa.Boolean)
- status = sa.Column(sa.String(16))
- firewall_policy_id = sa.Column(sa.String(36),
- sa.ForeignKey('firewall_policies.id'),
- nullable=True)
-
-
-class FirewallPolicy(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a Firewall Policy resource."""
- __tablename__ = 'firewall_policies'
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(1024))
- shared = sa.Column(sa.Boolean)
- firewall_rules = orm.relationship(
- FirewallRule,
- backref=orm.backref('firewall_policies', cascade='all, delete'),
- order_by='FirewallRule.position',
- collection_class=ordering_list('position', count_from=1))
- audited = sa.Column(sa.Boolean)
- firewalls = orm.relationship(Firewall, backref='firewall_policies')
-
-
-class Firewall_db_mixin(firewall.FirewallPluginBase, base_db.CommonDbMixin):
- """Mixin class for Firewall DB implementation."""
-
- @property
- def _core_plugin(self):
- return manager.NeutronManager.get_plugin()
-
- def _get_firewall(self, context, id):
- try:
- return self._get_by_id(context, Firewall, id)
- except exc.NoResultFound:
- raise firewall.FirewallNotFound(firewall_id=id)
-
- def _get_firewall_policy(self, context, id):
- try:
- return self._get_by_id(context, FirewallPolicy, id)
- except exc.NoResultFound:
- raise firewall.FirewallPolicyNotFound(firewall_policy_id=id)
-
- def _get_firewall_rule(self, context, id):
- try:
- return self._get_by_id(context, FirewallRule, id)
- except exc.NoResultFound:
- raise firewall.FirewallRuleNotFound(firewall_rule_id=id)
-
- def _make_firewall_dict(self, fw, fields=None):
- res = {'id': fw['id'],
- 'tenant_id': fw['tenant_id'],
- 'name': fw['name'],
- 'description': fw['description'],
- 'shared': fw['shared'],
- 'admin_state_up': fw['admin_state_up'],
- 'status': fw['status'],
- 'firewall_policy_id': fw['firewall_policy_id']}
- return self._fields(res, fields)
-
- def _make_firewall_policy_dict(self, firewall_policy, fields=None):
- fw_rules = [rule['id'] for rule in firewall_policy['firewall_rules']]
- firewalls = [fw['id'] for fw in firewall_policy['firewalls']]
- res = {'id': firewall_policy['id'],
- 'tenant_id': firewall_policy['tenant_id'],
- 'name': firewall_policy['name'],
- 'description': firewall_policy['description'],
- 'shared': firewall_policy['shared'],
- 'audited': firewall_policy['audited'],
- 'firewall_rules': fw_rules,
- 'firewall_list': firewalls}
- return self._fields(res, fields)
-
- def _make_firewall_rule_dict(self, firewall_rule, fields=None):
- position = None
- # We return the position only if the firewall_rule is bound to a
- # firewall_policy.
- if firewall_rule['firewall_policy_id']:
- position = firewall_rule['position']
- src_port_range = self._get_port_range_from_min_max_ports(
- firewall_rule['source_port_range_min'],
- firewall_rule['source_port_range_max'])
- dst_port_range = self._get_port_range_from_min_max_ports(
- firewall_rule['destination_port_range_min'],
- firewall_rule['destination_port_range_max'])
- res = {'id': firewall_rule['id'],
- 'tenant_id': firewall_rule['tenant_id'],
- 'name': firewall_rule['name'],
- 'description': firewall_rule['description'],
- 'firewall_policy_id': firewall_rule['firewall_policy_id'],
- 'shared': firewall_rule['shared'],
- 'protocol': firewall_rule['protocol'],
- 'ip_version': firewall_rule['ip_version'],
- 'source_ip_address': firewall_rule['source_ip_address'],
- 'destination_ip_address':
- firewall_rule['destination_ip_address'],
- 'source_port': src_port_range,
- 'destination_port': dst_port_range,
- 'action': firewall_rule['action'],
- 'position': position,
- 'enabled': firewall_rule['enabled']}
- return self._fields(res, fields)
-
- def _check_firewall_rule_conflict(self, fwr_db, fwp_db):
- if not fwr_db['shared']:
- if fwr_db['tenant_id'] != fwp_db['tenant_id']:
- raise firewall.FirewallRuleConflict(
- firewall_rule_id=fwr_db['id'],
- tenant_id=fwr_db['tenant_id'])
-
- def _set_rules_for_policy(self, context, firewall_policy_db, fwp):
- rule_id_list = fwp['firewall_rules']
- fwp_db = firewall_policy_db
- with context.session.begin(subtransactions=True):
- if not rule_id_list:
- fwp_db.firewall_rules = []
- fwp_db.audited = False
- return
- # We will first check if the new list of rules is valid
- filters = {'id': [r_id for r_id in rule_id_list]}
- rules_in_db = self._get_collection_query(context, FirewallRule,
- filters=filters)
- rules_dict = dict((fwr_db['id'], fwr_db) for fwr_db in rules_in_db)
- for fwrule_id in rule_id_list:
- if fwrule_id not in rules_dict:
- # If we find an invalid rule in the list we
- # do not perform the update since this breaks
- # the integrity of this list.
- raise firewall.FirewallRuleNotFound(
- firewall_rule_id=fwrule_id)
- elif rules_dict[fwrule_id]['firewall_policy_id']:
- if (rules_dict[fwrule_id]['firewall_policy_id'] !=
- fwp_db['id']):
- raise firewall.FirewallRuleInUse(
- firewall_rule_id=fwrule_id)
- if 'shared' in fwp:
- if fwp['shared'] and not rules_dict[fwrule_id]['shared']:
- raise firewall.FirewallRuleSharingConflict(
- firewall_rule_id=fwrule_id,
- firewall_policy_id=fwp_db['id'])
- elif fwp_db['shared'] and not rules_dict[fwrule_id]['shared']:
- raise firewall.FirewallRuleSharingConflict(
- firewall_rule_id=fwrule_id,
- firewall_policy_id=fwp_db['id'])
- for fwr_db in rules_in_db:
- self._check_firewall_rule_conflict(fwr_db, fwp_db)
- # New list of rules is valid so we will first reset the existing
- # list and then add each rule in order.
- # Note that the list could be empty in which case we interpret
- # it as clearing existing rules.
- fwp_db.firewall_rules = []
- for fwrule_id in rule_id_list:
- fwp_db.firewall_rules.append(rules_dict[fwrule_id])
- fwp_db.firewall_rules.reorder()
- fwp_db.audited = False
-
- def _check_unshared_rules_for_policy(self, fwp_db, fwp):
- if fwp['shared']:
- rules_in_db = fwp_db['firewall_rules']
- for fwr_db in rules_in_db:
- if not fwr_db['shared']:
- raise firewall.FirewallPolicySharingConflict(
- firewall_rule_id=fwr_db['id'],
- firewall_policy_id=fwp_db['id'])
-
- def _process_rule_for_policy(self, context, firewall_policy_id,
- firewall_rule_db, position):
- with context.session.begin(subtransactions=True):
- fwp_query = context.session.query(
- FirewallPolicy).with_lockmode('update')
- fwp_db = fwp_query.filter_by(id=firewall_policy_id).one()
- if position:
- # Note that although position numbering starts at 1,
- # internal ordering of the list starts at 0, so we compensate.
- fwp_db.firewall_rules.insert(position - 1, firewall_rule_db)
- else:
- fwp_db.firewall_rules.remove(firewall_rule_db)
- fwp_db.firewall_rules.reorder()
- fwp_db.audited = False
- return self._make_firewall_policy_dict(fwp_db)
-
- def _get_min_max_ports_from_range(self, port_range):
- if not port_range:
- return [None, None]
- min_port, sep, max_port = port_range.partition(":")
- if not max_port:
- max_port = min_port
- return [int(min_port), int(max_port)]
-
- def _get_port_range_from_min_max_ports(self, min_port, max_port):
- if not min_port:
- return None
- if min_port == max_port:
- return str(min_port)
- else:
- return '%d:%d' % (min_port, max_port)
-
- def _validate_fwr_protocol_parameters(self, fwr):
- protocol = fwr['protocol']
- if protocol not in (const.TCP, const.UDP):
- if fwr['source_port'] or fwr['destination_port']:
- raise firewall.FirewallRuleInvalidICMPParameter(
- param="Source, destination port")
-
- def create_firewall(self, context, firewall):
- LOG.debug("create_firewall() called")
- fw = firewall['firewall']
- tenant_id = self._get_tenant_id_for_create(context, fw)
- # distributed routers may required a more complex state machine;
- # the introduction of a new 'CREATED' state allows this, whilst
- # keeping a backward compatible behavior of the logical resource.
- status = (const.CREATED
- if cfg.CONF.router_distributed else const.PENDING_CREATE)
- with context.session.begin(subtransactions=True):
- firewall_db = Firewall(
- id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=fw['name'],
- description=fw['description'],
- firewall_policy_id=fw['firewall_policy_id'],
- admin_state_up=fw['admin_state_up'],
- status=status)
- context.session.add(firewall_db)
- return self._make_firewall_dict(firewall_db)
-
- def update_firewall(self, context, id, firewall):
- LOG.debug("update_firewall() called")
- fw = firewall['firewall']
- with context.session.begin(subtransactions=True):
- count = context.session.query(Firewall).filter_by(id=id).update(fw)
- if not count:
- raise firewall.FirewallNotFound(firewall_id=id)
- return self.get_firewall(context, id)
-
- def delete_firewall(self, context, id):
- LOG.debug("delete_firewall() called")
- with context.session.begin(subtransactions=True):
- # Note: Plugin should ensure that it's okay to delete if the
- # firewall is active
- count = context.session.query(Firewall).filter_by(id=id).delete()
- if not count:
- raise firewall.FirewallNotFound(firewall_id=id)
-
- def get_firewall(self, context, id, fields=None):
- LOG.debug("get_firewall() called")
- fw = self._get_firewall(context, id)
- return self._make_firewall_dict(fw, fields)
-
- def get_firewalls(self, context, filters=None, fields=None):
- LOG.debug("get_firewalls() called")
- return self._get_collection(context, Firewall,
- self._make_firewall_dict,
- filters=filters, fields=fields)
-
- def get_firewalls_count(self, context, filters=None):
- LOG.debug("get_firewalls_count() called")
- return self._get_collection_count(context, Firewall,
- filters=filters)
-
- def create_firewall_policy(self, context, firewall_policy):
- LOG.debug("create_firewall_policy() called")
- fwp = firewall_policy['firewall_policy']
- tenant_id = self._get_tenant_id_for_create(context, fwp)
- with context.session.begin(subtransactions=True):
- fwp_db = FirewallPolicy(id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=fwp['name'],
- description=fwp['description'],
- shared=fwp['shared'])
- context.session.add(fwp_db)
- self._set_rules_for_policy(context, fwp_db, fwp)
- fwp_db.audited = fwp['audited']
- return self._make_firewall_policy_dict(fwp_db)
-
- def update_firewall_policy(self, context, id, firewall_policy):
- LOG.debug("update_firewall_policy() called")
- fwp = firewall_policy['firewall_policy']
- with context.session.begin(subtransactions=True):
- fwp_db = self._get_firewall_policy(context, id)
- # check tenant ids are same for fw and fwp or not
- if not fwp.get('shared', True) and fwp_db.firewalls:
- for fw in fwp_db['firewalls']:
- if fwp_db['tenant_id'] != fw['tenant_id']:
- raise firewall.FirewallPolicyInUse(
- firewall_policy_id=id)
- # check any existing rules are not shared
- if 'shared' in fwp and 'firewall_rules' not in fwp:
- self._check_unshared_rules_for_policy(fwp_db, fwp)
- elif 'firewall_rules' in fwp:
- self._set_rules_for_policy(context, fwp_db, fwp)
- del fwp['firewall_rules']
- if 'audited' not in fwp or fwp['audited']:
- fwp['audited'] = False
- fwp_db.update(fwp)
- return self._make_firewall_policy_dict(fwp_db)
-
- def delete_firewall_policy(self, context, id):
- LOG.debug("delete_firewall_policy() called")
- with context.session.begin(subtransactions=True):
- fwp = self._get_firewall_policy(context, id)
- # Ensure that the firewall_policy is not
- # being used
- qry = context.session.query(Firewall)
- if qry.filter_by(firewall_policy_id=id).first():
- raise firewall.FirewallPolicyInUse(firewall_policy_id=id)
- else:
- context.session.delete(fwp)
-
- def get_firewall_policy(self, context, id, fields=None):
- LOG.debug("get_firewall_policy() called")
- fwp = self._get_firewall_policy(context, id)
- return self._make_firewall_policy_dict(fwp, fields)
-
- def get_firewall_policies(self, context, filters=None, fields=None):
- LOG.debug("get_firewall_policies() called")
- return self._get_collection(context, FirewallPolicy,
- self._make_firewall_policy_dict,
- filters=filters, fields=fields)
-
- def get_firewalls_policies_count(self, context, filters=None):
- LOG.debug("get_firewall_policies_count() called")
- return self._get_collection_count(context, FirewallPolicy,
- filters=filters)
-
- def create_firewall_rule(self, context, firewall_rule):
- LOG.debug("create_firewall_rule() called")
- fwr = firewall_rule['firewall_rule']
- self._validate_fwr_protocol_parameters(fwr)
- tenant_id = self._get_tenant_id_for_create(context, fwr)
- if not fwr['protocol'] and (fwr['source_port'] or
- fwr['destination_port']):
- raise firewall.FirewallRuleWithPortWithoutProtocolInvalid()
- src_port_min, src_port_max = self._get_min_max_ports_from_range(
- fwr['source_port'])
- dst_port_min, dst_port_max = self._get_min_max_ports_from_range(
- fwr['destination_port'])
- with context.session.begin(subtransactions=True):
- fwr_db = FirewallRule(
- id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=fwr['name'],
- description=fwr['description'],
- shared=fwr['shared'],
- protocol=fwr['protocol'],
- ip_version=fwr['ip_version'],
- source_ip_address=fwr['source_ip_address'],
- destination_ip_address=fwr['destination_ip_address'],
- source_port_range_min=src_port_min,
- source_port_range_max=src_port_max,
- destination_port_range_min=dst_port_min,
- destination_port_range_max=dst_port_max,
- action=fwr['action'],
- enabled=fwr['enabled'])
- context.session.add(fwr_db)
- return self._make_firewall_rule_dict(fwr_db)
-
- def update_firewall_rule(self, context, id, firewall_rule):
- LOG.debug("update_firewall_rule() called")
- fwr = firewall_rule['firewall_rule']
- fwr_db = self._get_firewall_rule(context, id)
- if fwr_db.firewall_policy_id:
- fwp_db = self._get_firewall_policy(context,
- fwr_db.firewall_policy_id)
- if 'shared' in fwr and not fwr['shared']:
- if fwr_db['tenant_id'] != fwp_db['tenant_id']:
- raise firewall.FirewallRuleInUse(firewall_rule_id=id)
- if 'source_port' in fwr:
- src_port_min, src_port_max = self._get_min_max_ports_from_range(
- fwr['source_port'])
- fwr['source_port_range_min'] = src_port_min
- fwr['source_port_range_max'] = src_port_max
- del fwr['source_port']
- if 'destination_port' in fwr:
- dst_port_min, dst_port_max = self._get_min_max_ports_from_range(
- fwr['destination_port'])
- fwr['destination_port_range_min'] = dst_port_min
- fwr['destination_port_range_max'] = dst_port_max
- del fwr['destination_port']
- with context.session.begin(subtransactions=True):
- protocol = fwr.get('protocol', fwr_db['protocol'])
- if not protocol:
- sport = fwr.get('source_port_range_min',
- fwr_db['source_port_range_min'])
- dport = fwr.get('destination_port_range_min',
- fwr_db['destination_port_range_min'])
- if sport or dport:
- raise firewall.FirewallRuleWithPortWithoutProtocolInvalid()
- fwr_db.update(fwr)
- if fwr_db.firewall_policy_id:
- fwp_db.audited = False
- return self._make_firewall_rule_dict(fwr_db)
-
- def delete_firewall_rule(self, context, id):
- LOG.debug("delete_firewall_rule() called")
- with context.session.begin(subtransactions=True):
- fwr = self._get_firewall_rule(context, id)
- if fwr.firewall_policy_id:
- raise firewall.FirewallRuleInUse(firewall_rule_id=id)
- context.session.delete(fwr)
-
- def get_firewall_rule(self, context, id, fields=None):
- LOG.debug("get_firewall_rule() called")
- fwr = self._get_firewall_rule(context, id)
- return self._make_firewall_rule_dict(fwr, fields)
-
- def get_firewall_rules(self, context, filters=None, fields=None):
- LOG.debug("get_firewall_rules() called")
- return self._get_collection(context, FirewallRule,
- self._make_firewall_rule_dict,
- filters=filters, fields=fields)
-
- def get_firewalls_rules_count(self, context, filters=None):
- LOG.debug("get_firewall_rules_count() called")
- return self._get_collection_count(context, FirewallRule,
- filters=filters)
-
- def _validate_insert_remove_rule_request(self, id, rule_info):
- if not rule_info or 'firewall_rule_id' not in rule_info:
- raise firewall.FirewallRuleInfoMissing()
-
- def insert_rule(self, context, id, rule_info):
- LOG.debug("insert_rule() called")
- self._validate_insert_remove_rule_request(id, rule_info)
- firewall_rule_id = rule_info['firewall_rule_id']
- insert_before = True
- ref_firewall_rule_id = None
- if not firewall_rule_id:
- raise firewall.FirewallRuleNotFound(firewall_rule_id=None)
- if 'insert_before' in rule_info:
- ref_firewall_rule_id = rule_info['insert_before']
- if not ref_firewall_rule_id and 'insert_after' in rule_info:
- # If insert_before is set, we will ignore insert_after.
- ref_firewall_rule_id = rule_info['insert_after']
- insert_before = False
- with context.session.begin(subtransactions=True):
- fwr_db = self._get_firewall_rule(context, firewall_rule_id)
- fwp_db = self._get_firewall_policy(context, id)
- if fwr_db.firewall_policy_id:
- raise firewall.FirewallRuleInUse(firewall_rule_id=fwr_db['id'])
- self._check_firewall_rule_conflict(fwr_db, fwp_db)
- if ref_firewall_rule_id:
- # If reference_firewall_rule_id is set, the new rule
- # is inserted depending on the value of insert_before.
- # If insert_before is set, the new rule is inserted before
- # reference_firewall_rule_id, and if it is not set the new
- # rule is inserted after reference_firewall_rule_id.
- ref_fwr_db = self._get_firewall_rule(
- context, ref_firewall_rule_id)
- if ref_fwr_db.firewall_policy_id != id:
- raise firewall.FirewallRuleNotAssociatedWithPolicy(
- firewall_rule_id=ref_fwr_db['id'],
- firewall_policy_id=id)
- if insert_before:
- position = ref_fwr_db.position
- else:
- position = ref_fwr_db.position + 1
- else:
- # If reference_firewall_rule_id is not set, it is assumed
- # that the new rule needs to be inserted at the top.
- # insert_before field is ignored.
- # So default insertion is always at the top.
- # Also note that position numbering starts at 1.
- position = 1
- return self._process_rule_for_policy(context, id, fwr_db,
- position)
-
- def remove_rule(self, context, id, rule_info):
- LOG.debug("remove_rule() called")
- self._validate_insert_remove_rule_request(id, rule_info)
- firewall_rule_id = rule_info['firewall_rule_id']
- if not firewall_rule_id:
- raise firewall.FirewallRuleNotFound(firewall_rule_id=None)
- with context.session.begin(subtransactions=True):
- fwr_db = self._get_firewall_rule(context, firewall_rule_id)
- if fwr_db.firewall_policy_id != id:
- raise firewall.FirewallRuleNotAssociatedWithPolicy(
- firewall_rule_id=fwr_db['id'],
- firewall_policy_id=id)
- return self._process_rule_for_policy(context, id, fwr_db, None)
+++ /dev/null
-# Copyright 2013 OpenStack Foundation. All rights reserved
-#
-# 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.db import exception
-from oslo.utils import excutils
-import sqlalchemy as sa
-from sqlalchemy import orm
-from sqlalchemy.orm import exc
-from sqlalchemy.orm import validates
-
-from neutron.api.v2 import attributes
-from neutron.common import exceptions as n_exc
-from neutron.db import common_db_mixin as base_db
-from neutron.db import model_base
-from neutron.db import models_v2
-from neutron.db import servicetype_db as st_db
-from neutron.extensions import loadbalancer
-from neutron import manager
-from neutron.openstack.common import log as logging
-from neutron.openstack.common import uuidutils
-from neutron.plugins.common import constants
-from neutron.services.loadbalancer import constants as lb_const
-
-
-LOG = logging.getLogger(__name__)
-
-
-class SessionPersistence(model_base.BASEV2):
-
- vip_id = sa.Column(sa.String(36),
- sa.ForeignKey("vips.id"),
- primary_key=True)
- type = sa.Column(sa.Enum("SOURCE_IP",
- "HTTP_COOKIE",
- "APP_COOKIE",
- name="sesssionpersistences_type"),
- nullable=False)
- cookie_name = sa.Column(sa.String(1024))
-
-
-class PoolStatistics(model_base.BASEV2):
- """Represents pool statistics."""
-
- pool_id = sa.Column(sa.String(36), sa.ForeignKey("pools.id"),
- primary_key=True)
- bytes_in = sa.Column(sa.BigInteger, nullable=False)
- bytes_out = sa.Column(sa.BigInteger, nullable=False)
- active_connections = sa.Column(sa.BigInteger, nullable=False)
- total_connections = sa.Column(sa.BigInteger, nullable=False)
-
- @validates('bytes_in', 'bytes_out',
- 'active_connections', 'total_connections')
- def validate_non_negative_int(self, key, value):
- if value < 0:
- data = {'key': key, 'value': value}
- raise ValueError(_('The %(key)s field can not have '
- 'negative value. '
- 'Current value is %(value)d.') % data)
- return value
-
-
-class Vip(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant,
- models_v2.HasStatusDescription):
- """Represents a v2 neutron loadbalancer vip."""
-
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(255))
- port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id'))
- protocol_port = sa.Column(sa.Integer, nullable=False)
- protocol = sa.Column(sa.Enum("HTTP", "HTTPS", "TCP", name="lb_protocols"),
- nullable=False)
- pool_id = sa.Column(sa.String(36), nullable=False, unique=True)
- session_persistence = orm.relationship(SessionPersistence,
- uselist=False,
- backref="vips",
- cascade="all, delete-orphan")
- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
- connection_limit = sa.Column(sa.Integer)
- port = orm.relationship(models_v2.Port)
-
-
-class Member(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant,
- models_v2.HasStatusDescription):
- """Represents a v2 neutron loadbalancer member."""
-
- __table_args__ = (
- sa.schema.UniqueConstraint('pool_id', 'address', 'protocol_port',
- name='uniq_member0pool_id0address0port'),
- )
- pool_id = sa.Column(sa.String(36), sa.ForeignKey("pools.id"),
- nullable=False)
- address = sa.Column(sa.String(64), nullable=False)
- protocol_port = sa.Column(sa.Integer, nullable=False)
- weight = sa.Column(sa.Integer, nullable=False)
- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
-
-
-class Pool(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant,
- models_v2.HasStatusDescription):
- """Represents a v2 neutron loadbalancer pool."""
-
- vip_id = sa.Column(sa.String(36), sa.ForeignKey("vips.id"))
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(255))
- subnet_id = sa.Column(sa.String(36), nullable=False)
- protocol = sa.Column(sa.Enum("HTTP", "HTTPS", "TCP", name="lb_protocols"),
- nullable=False)
- lb_method = sa.Column(sa.Enum("ROUND_ROBIN",
- "LEAST_CONNECTIONS",
- "SOURCE_IP",
- name="pools_lb_method"),
- nullable=False)
- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
- stats = orm.relationship(PoolStatistics,
- uselist=False,
- backref="pools",
- cascade="all, delete-orphan")
- members = orm.relationship(Member, backref="pools",
- cascade="all, delete-orphan")
- monitors = orm.relationship("PoolMonitorAssociation", backref="pools",
- cascade="all, delete-orphan")
- vip = orm.relationship(Vip, backref='pool')
-
- provider = orm.relationship(
- st_db.ProviderResourceAssociation,
- uselist=False,
- lazy="joined",
- primaryjoin="Pool.id==ProviderResourceAssociation.resource_id",
- foreign_keys=[st_db.ProviderResourceAssociation.resource_id]
- )
-
-
-class HealthMonitor(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a v2 neutron loadbalancer healthmonitor."""
-
- type = sa.Column(sa.Enum("PING", "TCP", "HTTP", "HTTPS",
- name="healthmontiors_type"),
- nullable=False)
- delay = sa.Column(sa.Integer, nullable=False)
- timeout = sa.Column(sa.Integer, nullable=False)
- max_retries = sa.Column(sa.Integer, nullable=False)
- http_method = sa.Column(sa.String(16))
- url_path = sa.Column(sa.String(255))
- expected_codes = sa.Column(sa.String(64))
- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
-
- pools = orm.relationship(
- "PoolMonitorAssociation", backref="healthmonitor",
- cascade="all", lazy="joined"
- )
-
-
-class PoolMonitorAssociation(model_base.BASEV2,
- models_v2.HasStatusDescription):
- """Many-to-many association between pool and healthMonitor classes."""
-
- pool_id = sa.Column(sa.String(36),
- sa.ForeignKey("pools.id"),
- primary_key=True)
- monitor_id = sa.Column(sa.String(36),
- sa.ForeignKey("healthmonitors.id"),
- primary_key=True)
-
-
-class LoadBalancerPluginDb(loadbalancer.LoadBalancerPluginBase,
- base_db.CommonDbMixin):
- """Wraps loadbalancer with SQLAlchemy models.
-
- A class that wraps the implementation of the Neutron loadbalancer
- plugin database access interface using SQLAlchemy models.
- """
-
- @property
- def _core_plugin(self):
- return manager.NeutronManager.get_plugin()
-
- def update_status(self, context, model, id, status,
- status_description=None):
- with context.session.begin(subtransactions=True):
- if issubclass(model, Vip):
- try:
- v_db = (self._model_query(context, model).
- filter(model.id == id).
- options(orm.noload('port')).
- one())
- except exc.NoResultFound:
- raise loadbalancer.VipNotFound(vip_id=id)
- else:
- v_db = self._get_resource(context, model, id)
- if v_db.status != status:
- v_db.status = status
- # update status_description in two cases:
- # - new value is passed
- # - old value is not None (needs to be updated anyway)
- if status_description or v_db['status_description']:
- v_db.status_description = status_description
-
- def _get_resource(self, context, model, id):
- try:
- r = self._get_by_id(context, model, id)
- except exc.NoResultFound:
- with excutils.save_and_reraise_exception(reraise=False) as ctx:
- if issubclass(model, Vip):
- raise loadbalancer.VipNotFound(vip_id=id)
- elif issubclass(model, Pool):
- raise loadbalancer.PoolNotFound(pool_id=id)
- elif issubclass(model, Member):
- raise loadbalancer.MemberNotFound(member_id=id)
- elif issubclass(model, HealthMonitor):
- raise loadbalancer.HealthMonitorNotFound(monitor_id=id)
- ctx.reraise = True
- return r
-
- def assert_modification_allowed(self, obj):
- status = getattr(obj, 'status', None)
-
- if status == constants.PENDING_DELETE:
- raise loadbalancer.StateInvalid(id=id, state=status)
-
- ########################################################
- # VIP DB access
- def _make_vip_dict(self, vip, fields=None):
- fixed_ip = {}
- # it's possible that vip doesn't have created port yet
- if vip.port:
- fixed_ip = (vip.port.fixed_ips or [{}])[0]
-
- res = {'id': vip['id'],
- 'tenant_id': vip['tenant_id'],
- 'name': vip['name'],
- 'description': vip['description'],
- 'subnet_id': fixed_ip.get('subnet_id'),
- 'address': fixed_ip.get('ip_address'),
- 'port_id': vip['port_id'],
- 'protocol_port': vip['protocol_port'],
- 'protocol': vip['protocol'],
- 'pool_id': vip['pool_id'],
- 'session_persistence': None,
- 'connection_limit': vip['connection_limit'],
- 'admin_state_up': vip['admin_state_up'],
- 'status': vip['status'],
- 'status_description': vip['status_description']}
-
- if vip['session_persistence']:
- s_p = {
- 'type': vip['session_persistence']['type']
- }
-
- if vip['session_persistence']['type'] == 'APP_COOKIE':
- s_p['cookie_name'] = vip['session_persistence']['cookie_name']
-
- res['session_persistence'] = s_p
-
- return self._fields(res, fields)
-
- def _check_session_persistence_info(self, info):
- """Performs sanity check on session persistence info.
-
- :param info: Session persistence info
- """
- if info['type'] == 'APP_COOKIE':
- if not info.get('cookie_name'):
- raise ValueError(_("'cookie_name' should be specified for this"
- " type of session persistence."))
- else:
- if 'cookie_name' in info:
- raise ValueError(_("'cookie_name' is not allowed for this type"
- " of session persistence"))
-
- def _create_session_persistence_db(self, session_info, vip_id):
- self._check_session_persistence_info(session_info)
-
- sesspersist_db = SessionPersistence(
- type=session_info['type'],
- cookie_name=session_info.get('cookie_name'),
- vip_id=vip_id)
- return sesspersist_db
-
- def _update_vip_session_persistence(self, context, vip_id, info):
- self._check_session_persistence_info(info)
-
- vip = self._get_resource(context, Vip, vip_id)
-
- with context.session.begin(subtransactions=True):
- # Update sessionPersistence table
- sess_qry = context.session.query(SessionPersistence)
- sesspersist_db = sess_qry.filter_by(vip_id=vip_id).first()
-
- # Insert a None cookie_info if it is not present to overwrite an
- # an existing value in the database.
- if 'cookie_name' not in info:
- info['cookie_name'] = None
-
- if sesspersist_db:
- sesspersist_db.update(info)
- else:
- sesspersist_db = SessionPersistence(
- type=info['type'],
- cookie_name=info['cookie_name'],
- vip_id=vip_id)
- context.session.add(sesspersist_db)
- # Update vip table
- vip.session_persistence = sesspersist_db
- context.session.add(vip)
-
- def _delete_session_persistence(self, context, vip_id):
- with context.session.begin(subtransactions=True):
- sess_qry = context.session.query(SessionPersistence)
- sess_qry.filter_by(vip_id=vip_id).delete()
-
- def _create_port_for_vip(self, context, vip_db, subnet_id, ip_address):
- # resolve subnet and create port
- subnet = self._core_plugin.get_subnet(context, subnet_id)
- fixed_ip = {'subnet_id': subnet['id']}
- if ip_address and ip_address != attributes.ATTR_NOT_SPECIFIED:
- fixed_ip['ip_address'] = ip_address
-
- port_data = {
- 'tenant_id': vip_db.tenant_id,
- 'name': 'vip-' + vip_db.id,
- 'network_id': subnet['network_id'],
- 'mac_address': attributes.ATTR_NOT_SPECIFIED,
- 'admin_state_up': False,
- 'device_id': '',
- 'device_owner': '',
- 'fixed_ips': [fixed_ip]
- }
-
- port = self._core_plugin.create_port(context, {'port': port_data})
- vip_db.port_id = port['id']
- # explicitly sync session with db
- context.session.flush()
-
- def create_vip(self, context, vip):
- v = vip['vip']
- tenant_id = self._get_tenant_id_for_create(context, v)
-
- with context.session.begin(subtransactions=True):
- if v['pool_id']:
- pool = self._get_resource(context, Pool, v['pool_id'])
- # validate that the pool has same tenant
- if pool['tenant_id'] != tenant_id:
- raise n_exc.NotAuthorized()
- # validate that the pool has same protocol
- if pool['protocol'] != v['protocol']:
- raise loadbalancer.ProtocolMismatch(
- vip_proto=v['protocol'],
- pool_proto=pool['protocol'])
- if pool['status'] == constants.PENDING_DELETE:
- raise loadbalancer.StateInvalid(state=pool['status'],
- id=pool['id'])
- vip_db = Vip(id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=v['name'],
- description=v['description'],
- port_id=None,
- protocol_port=v['protocol_port'],
- protocol=v['protocol'],
- pool_id=v['pool_id'],
- connection_limit=v['connection_limit'],
- admin_state_up=v['admin_state_up'],
- status=constants.PENDING_CREATE)
-
- session_info = v['session_persistence']
-
- if session_info:
- s_p = self._create_session_persistence_db(
- session_info,
- vip_db['id'])
- vip_db.session_persistence = s_p
-
- try:
- context.session.add(vip_db)
- context.session.flush()
- except exception.DBDuplicateEntry:
- raise loadbalancer.VipExists(pool_id=v['pool_id'])
-
- try:
- # create a port to reserve address for IPAM
- # do it outside the transaction to avoid rpc calls
- self._create_port_for_vip(
- context, vip_db, v['subnet_id'], v.get('address'))
- except Exception:
- # catch any kind of exceptions
- with excutils.save_and_reraise_exception():
- context.session.delete(vip_db)
- context.session.flush()
-
- if v['pool_id']:
- # fetching pool again
- pool = self._get_resource(context, Pool, v['pool_id'])
- # (NOTE): we rely on the fact that pool didn't change between
- # above block and here
- vip_db['pool_id'] = v['pool_id']
- pool['vip_id'] = vip_db['id']
- # explicitly flush changes as we're outside any transaction
- context.session.flush()
-
- return self._make_vip_dict(vip_db)
-
- def update_vip(self, context, id, vip):
- v = vip['vip']
-
- sess_persist = v.pop('session_persistence', None)
- with context.session.begin(subtransactions=True):
- vip_db = self._get_resource(context, Vip, id)
-
- self.assert_modification_allowed(vip_db)
-
- if sess_persist:
- self._update_vip_session_persistence(context, id, sess_persist)
- else:
- self._delete_session_persistence(context, id)
-
- if v:
- try:
- # in case new pool already has a vip
- # update will raise integrity error at first query
- old_pool_id = vip_db['pool_id']
- vip_db.update(v)
- # If the pool_id is changed, we need to update
- # the associated pools
- if 'pool_id' in v:
- new_pool = self._get_resource(context, Pool,
- v['pool_id'])
- self.assert_modification_allowed(new_pool)
-
- # check that the pool matches the tenant_id
- if new_pool['tenant_id'] != vip_db['tenant_id']:
- raise n_exc.NotAuthorized()
- # validate that the pool has same protocol
- if new_pool['protocol'] != vip_db['protocol']:
- raise loadbalancer.ProtocolMismatch(
- vip_proto=vip_db['protocol'],
- pool_proto=new_pool['protocol'])
- if new_pool['status'] == constants.PENDING_DELETE:
- raise loadbalancer.StateInvalid(
- state=new_pool['status'],
- id=new_pool['id'])
-
- if old_pool_id:
- old_pool = self._get_resource(
- context,
- Pool,
- old_pool_id
- )
- old_pool['vip_id'] = None
-
- new_pool['vip_id'] = vip_db['id']
- except exception.DBDuplicateEntry:
- raise loadbalancer.VipExists(pool_id=v['pool_id'])
-
- return self._make_vip_dict(vip_db)
-
- def delete_vip(self, context, id):
- with context.session.begin(subtransactions=True):
- vip = self._get_resource(context, Vip, id)
- qry = context.session.query(Pool)
- for pool in qry.filter_by(vip_id=id):
- pool.update({"vip_id": None})
-
- context.session.delete(vip)
- if vip.port: # this is a Neutron port
- self._core_plugin.delete_port(context, vip.port.id)
-
- def get_vip(self, context, id, fields=None):
- vip = self._get_resource(context, Vip, id)
- return self._make_vip_dict(vip, fields)
-
- def get_vips(self, context, filters=None, fields=None):
- return self._get_collection(context, Vip,
- self._make_vip_dict,
- filters=filters, fields=fields)
-
- ########################################################
- # Pool DB access
- def _make_pool_dict(self, pool, fields=None):
- res = {'id': pool['id'],
- 'tenant_id': pool['tenant_id'],
- 'name': pool['name'],
- 'description': pool['description'],
- 'subnet_id': pool['subnet_id'],
- 'protocol': pool['protocol'],
- 'vip_id': pool['vip_id'],
- 'lb_method': pool['lb_method'],
- 'admin_state_up': pool['admin_state_up'],
- 'status': pool['status'],
- 'status_description': pool['status_description'],
- 'provider': ''
- }
-
- if pool.provider:
- res['provider'] = pool.provider.provider_name
-
- # Get the associated members
- res['members'] = [member['id'] for member in pool['members']]
-
- # Get the associated health_monitors
- res['health_monitors'] = [
- monitor['monitor_id'] for monitor in pool['monitors']]
- res['health_monitors_status'] = [
- {'monitor_id': monitor['monitor_id'],
- 'status': monitor['status'],
- 'status_description': monitor['status_description']}
- for monitor in pool['monitors']]
- return self._fields(res, fields)
-
- def update_pool_stats(self, context, pool_id, data=None):
- """Update a pool with new stats structure."""
- data = data or {}
- with context.session.begin(subtransactions=True):
- pool_db = self._get_resource(context, Pool, pool_id)
- self.assert_modification_allowed(pool_db)
- pool_db.stats = self._create_pool_stats(context, pool_id, data)
-
- for member, stats in data.get('members', {}).items():
- stats_status = stats.get(lb_const.STATS_STATUS)
- if stats_status:
- self.update_status(context, Member, member, stats_status)
-
- def _create_pool_stats(self, context, pool_id, data=None):
- # This is internal method to add pool statistics. It won't
- # be exposed to API
- if not data:
- data = {}
- stats_db = PoolStatistics(
- pool_id=pool_id,
- bytes_in=data.get(lb_const.STATS_IN_BYTES, 0),
- bytes_out=data.get(lb_const.STATS_OUT_BYTES, 0),
- active_connections=data.get(lb_const.STATS_ACTIVE_CONNECTIONS, 0),
- total_connections=data.get(lb_const.STATS_TOTAL_CONNECTIONS, 0)
- )
- return stats_db
-
- def _delete_pool_stats(self, context, pool_id):
- # This is internal method to delete pool statistics. It won't
- # be exposed to API
- with context.session.begin(subtransactions=True):
- stats_qry = context.session.query(PoolStatistics)
- try:
- stats = stats_qry.filter_by(pool_id=pool_id).one()
- except exc.NoResultFound:
- raise loadbalancer.PoolStatsNotFound(pool_id=pool_id)
- context.session.delete(stats)
-
- def create_pool(self, context, pool):
- v = pool['pool']
-
- tenant_id = self._get_tenant_id_for_create(context, v)
- with context.session.begin(subtransactions=True):
- pool_db = Pool(id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=v['name'],
- description=v['description'],
- subnet_id=v['subnet_id'],
- protocol=v['protocol'],
- lb_method=v['lb_method'],
- admin_state_up=v['admin_state_up'],
- status=constants.PENDING_CREATE)
- pool_db.stats = self._create_pool_stats(context, pool_db['id'])
- context.session.add(pool_db)
-
- return self._make_pool_dict(pool_db)
-
- def update_pool(self, context, id, pool):
- p = pool['pool']
- with context.session.begin(subtransactions=True):
- pool_db = self._get_resource(context, Pool, id)
- self.assert_modification_allowed(pool_db)
- if p:
- pool_db.update(p)
-
- return self._make_pool_dict(pool_db)
-
- def _ensure_pool_delete_conditions(self, context, pool_id):
- if context.session.query(Vip).filter_by(pool_id=pool_id).first():
- raise loadbalancer.PoolInUse(pool_id=pool_id)
-
- def delete_pool(self, context, pool_id):
- # Check if the pool is in use
- self._ensure_pool_delete_conditions(context, pool_id)
-
- with context.session.begin(subtransactions=True):
- self._delete_pool_stats(context, pool_id)
- pool_db = self._get_resource(context, Pool, pool_id)
- context.session.delete(pool_db)
-
- def get_pool(self, context, id, fields=None):
- pool = self._get_resource(context, Pool, id)
- return self._make_pool_dict(pool, fields)
-
- def get_pools(self, context, filters=None, fields=None):
- collection = self._model_query(context, Pool)
- collection = self._apply_filters_to_query(collection, Pool, filters)
- return [self._make_pool_dict(c, fields)
- for c in collection]
-
- def stats(self, context, pool_id):
- with context.session.begin(subtransactions=True):
- pool = self._get_resource(context, Pool, pool_id)
- stats = pool['stats']
-
- res = {lb_const.STATS_IN_BYTES: stats['bytes_in'],
- lb_const.STATS_OUT_BYTES: stats['bytes_out'],
- lb_const.STATS_ACTIVE_CONNECTIONS: stats['active_connections'],
- lb_const.STATS_TOTAL_CONNECTIONS: stats['total_connections']}
- return {'stats': res}
-
- def create_pool_health_monitor(self, context, health_monitor, pool_id):
- monitor_id = health_monitor['health_monitor']['id']
- with context.session.begin(subtransactions=True):
- assoc_qry = context.session.query(PoolMonitorAssociation)
- assoc = assoc_qry.filter_by(pool_id=pool_id,
- monitor_id=monitor_id).first()
- if assoc:
- raise loadbalancer.PoolMonitorAssociationExists(
- monitor_id=monitor_id, pool_id=pool_id)
-
- pool = self._get_resource(context, Pool, pool_id)
-
- assoc = PoolMonitorAssociation(pool_id=pool_id,
- monitor_id=monitor_id,
- status=constants.PENDING_CREATE)
- pool.monitors.append(assoc)
- monitors = [monitor['monitor_id'] for monitor in pool['monitors']]
-
- res = {"health_monitor": monitors}
- return res
-
- def delete_pool_health_monitor(self, context, id, pool_id):
- with context.session.begin(subtransactions=True):
- assoc = self._get_pool_health_monitor(context, id, pool_id)
- pool = self._get_resource(context, Pool, pool_id)
- pool.monitors.remove(assoc)
-
- def _get_pool_health_monitor(self, context, id, pool_id):
- try:
- assoc_qry = context.session.query(PoolMonitorAssociation)
- return assoc_qry.filter_by(monitor_id=id, pool_id=pool_id).one()
- except exc.NoResultFound:
- raise loadbalancer.PoolMonitorAssociationNotFound(
- monitor_id=id, pool_id=pool_id)
-
- def get_pool_health_monitor(self, context, id, pool_id, fields=None):
- pool_hm = self._get_pool_health_monitor(context, id, pool_id)
- # need to add tenant_id for admin_or_owner policy check to pass
- hm = self.get_health_monitor(context, id)
- res = {'pool_id': pool_id,
- 'monitor_id': id,
- 'status': pool_hm['status'],
- 'status_description': pool_hm['status_description'],
- 'tenant_id': hm['tenant_id']}
- return self._fields(res, fields)
-
- def update_pool_health_monitor(self, context, id, pool_id,
- status, status_description=None):
- with context.session.begin(subtransactions=True):
- assoc = self._get_pool_health_monitor(context, id, pool_id)
- self.assert_modification_allowed(assoc)
- assoc.status = status
- assoc.status_description = status_description
-
- ########################################################
- # Member DB access
- def _make_member_dict(self, member, fields=None):
- res = {'id': member['id'],
- 'tenant_id': member['tenant_id'],
- 'pool_id': member['pool_id'],
- 'address': member['address'],
- 'protocol_port': member['protocol_port'],
- 'weight': member['weight'],
- 'admin_state_up': member['admin_state_up'],
- 'status': member['status'],
- 'status_description': member['status_description']}
-
- return self._fields(res, fields)
-
- def create_member(self, context, member):
- v = member['member']
- tenant_id = self._get_tenant_id_for_create(context, v)
-
- try:
- with context.session.begin(subtransactions=True):
- # ensuring that pool exists
- self._get_resource(context, Pool, v['pool_id'])
- member_db = Member(id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- pool_id=v['pool_id'],
- address=v['address'],
- protocol_port=v['protocol_port'],
- weight=v['weight'],
- admin_state_up=v['admin_state_up'],
- status=constants.PENDING_CREATE)
- context.session.add(member_db)
- return self._make_member_dict(member_db)
- except exception.DBDuplicateEntry:
- raise loadbalancer.MemberExists(
- address=v['address'],
- port=v['protocol_port'],
- pool=v['pool_id'])
-
- def update_member(self, context, id, member):
- v = member['member']
- try:
- with context.session.begin(subtransactions=True):
- member_db = self._get_resource(context, Member, id)
- self.assert_modification_allowed(member_db)
- if v:
- member_db.update(v)
- return self._make_member_dict(member_db)
- except exception.DBDuplicateEntry:
- raise loadbalancer.MemberExists(
- address=member_db['address'],
- port=member_db['protocol_port'],
- pool=member_db['pool_id'])
-
- def delete_member(self, context, id):
- with context.session.begin(subtransactions=True):
- member_db = self._get_resource(context, Member, id)
- context.session.delete(member_db)
-
- def get_member(self, context, id, fields=None):
- member = self._get_resource(context, Member, id)
- return self._make_member_dict(member, fields)
-
- def get_members(self, context, filters=None, fields=None):
- return self._get_collection(context, Member,
- self._make_member_dict,
- filters=filters, fields=fields)
-
- ########################################################
- # HealthMonitor DB access
- def _make_health_monitor_dict(self, health_monitor, fields=None):
- res = {'id': health_monitor['id'],
- 'tenant_id': health_monitor['tenant_id'],
- 'type': health_monitor['type'],
- 'delay': health_monitor['delay'],
- 'timeout': health_monitor['timeout'],
- 'max_retries': health_monitor['max_retries'],
- 'admin_state_up': health_monitor['admin_state_up']}
- # no point to add the values below to
- # the result if the 'type' is not HTTP/S
- if res['type'] in ['HTTP', 'HTTPS']:
- for attr in ['url_path', 'http_method', 'expected_codes']:
- res[attr] = health_monitor[attr]
- res['pools'] = [{'pool_id': p['pool_id'],
- 'status': p['status'],
- 'status_description': p['status_description']}
- for p in health_monitor.pools]
- return self._fields(res, fields)
-
- def create_health_monitor(self, context, health_monitor):
- v = health_monitor['health_monitor']
- tenant_id = self._get_tenant_id_for_create(context, v)
- with context.session.begin(subtransactions=True):
- # setting ACTIVE status since healthmon is shared DB object
- monitor_db = HealthMonitor(id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- type=v['type'],
- delay=v['delay'],
- timeout=v['timeout'],
- max_retries=v['max_retries'],
- http_method=v['http_method'],
- url_path=v['url_path'],
- expected_codes=v['expected_codes'],
- admin_state_up=v['admin_state_up'])
- context.session.add(monitor_db)
- return self._make_health_monitor_dict(monitor_db)
-
- def update_health_monitor(self, context, id, health_monitor):
- v = health_monitor['health_monitor']
- with context.session.begin(subtransactions=True):
- monitor_db = self._get_resource(context, HealthMonitor, id)
- self.assert_modification_allowed(monitor_db)
- if v:
- monitor_db.update(v)
- return self._make_health_monitor_dict(monitor_db)
-
- def delete_health_monitor(self, context, id):
- """Delete health monitor object from DB
-
- Raises an error if the monitor has associations with pools
- """
- query = self._model_query(context, PoolMonitorAssociation)
- has_associations = query.filter_by(monitor_id=id).first()
- if has_associations:
- raise loadbalancer.HealthMonitorInUse(monitor_id=id)
-
- with context.session.begin(subtransactions=True):
- monitor_db = self._get_resource(context, HealthMonitor, id)
- context.session.delete(monitor_db)
-
- def get_health_monitor(self, context, id, fields=None):
- healthmonitor = self._get_resource(context, HealthMonitor, id)
- return self._make_health_monitor_dict(healthmonitor, fields)
-
- def get_health_monitors(self, context, filters=None, fields=None):
- return self._get_collection(context, HealthMonitor,
- self._make_health_monitor_dict,
- filters=filters, fields=fields)
from neutron.db import external_net_db # noqa
from neutron.db import extradhcpopt_db # noqa
from neutron.db import extraroute_db # noqa
-# TODO(dougw) - services split, need to complete alembic fixes
-from neutron.db.firewall import firewall_db # noqa
from neutron.db import l3_agentschedulers_db # noqa
from neutron.db import l3_attrs_db # noqa
from neutron.db import l3_db # noqa
from neutron.db import l3_dvrscheduler_db # noqa
from neutron.db import l3_gwmode_db # noqa
from neutron.db import l3_hamode_db # noqa
-# TODO(dougw) - services split, need to complete alembic fixes
-from neutron.db.loadbalancer import loadbalancer_db # noqa
from neutron.db.metering import metering_db # noqa
from neutron.db import model_base
from neutron.db import models_v2 # noqa
from neutron.db import routerservicetype_db # noqa
from neutron.db import securitygroups_db # noqa
from neutron.db import servicetype_db # noqa
-# TODO(dougw) - services split, need to complete alembic fixes
-from neutron.db.vpn import vpn_db # noqa
from neutron.plugins.bigswitch.db import consistency_db # noqa
from neutron.plugins.bigswitch import routerrule_db # noqa
from neutron.plugins.brocade.db import models as brocade_models # noqa
from neutron.plugins.vmware.dbexts import networkgw_db # noqa
from neutron.plugins.vmware.dbexts import qos_db # noqa
from neutron.plugins.vmware.dbexts import vcns_models # noqa
-# TODO(dougw) - services split, need to complete alembic fixes
-from neutron.services.loadbalancer import agent_scheduler # noqa
-# TODO(dougw) - services split, need to complete alembic fixes
-from neutron.services.loadbalancer.drivers.embrane import ( # noqa
- models as embrane_models)
-# TODO(dougw) - services split, need to complete alembic fixes
-from neutron.services.vpn.service_drivers import cisco_csr_db # noqa
def get_metadata():
+++ /dev/null
-# (c) Copyright 2013 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# 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 netaddr
-from oslo.utils import excutils
-import sqlalchemy as sa
-from sqlalchemy import orm
-from sqlalchemy.orm import exc
-
-from neutron.common import constants as n_constants
-from neutron.db import common_db_mixin as base_db
-from neutron.db import l3_agentschedulers_db as l3_agent_db
-from neutron.db import l3_db
-from neutron.db import model_base
-from neutron.db import models_v2
-from neutron.db.vpn import vpn_validator
-from neutron.extensions import vpnaas
-from neutron.i18n import _LW
-from neutron import manager
-from neutron.openstack.common import log as logging
-from neutron.openstack.common import uuidutils
-from neutron.plugins.common import constants
-from neutron.plugins.common import utils
-
-LOG = logging.getLogger(__name__)
-
-
-class IPsecPeerCidr(model_base.BASEV2):
- """Internal representation of a IPsec Peer Cidrs."""
-
- cidr = sa.Column(sa.String(32), nullable=False, primary_key=True)
- ipsec_site_connection_id = sa.Column(
- sa.String(36),
- sa.ForeignKey('ipsec_site_connections.id',
- ondelete="CASCADE"),
- primary_key=True)
-
-
-class IPsecPolicy(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a v2 IPsecPolicy Object."""
- __tablename__ = 'ipsecpolicies'
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(255))
- transform_protocol = sa.Column(sa.Enum("esp", "ah", "ah-esp",
- name="ipsec_transform_protocols"),
- nullable=False)
- auth_algorithm = sa.Column(sa.Enum("sha1",
- name="vpn_auth_algorithms"),
- nullable=False)
- encryption_algorithm = sa.Column(sa.Enum("3des", "aes-128",
- "aes-256", "aes-192",
- name="vpn_encrypt_algorithms"),
- nullable=False)
- encapsulation_mode = sa.Column(sa.Enum("tunnel", "transport",
- name="ipsec_encapsulations"),
- nullable=False)
- lifetime_units = sa.Column(sa.Enum("seconds", "kilobytes",
- name="vpn_lifetime_units"),
- nullable=False)
- lifetime_value = sa.Column(sa.Integer, nullable=False)
- pfs = sa.Column(sa.Enum("group2", "group5", "group14",
- name="vpn_pfs"), nullable=False)
-
-
-class IKEPolicy(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a v2 IKEPolicy Object."""
- __tablename__ = 'ikepolicies'
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(255))
- auth_algorithm = sa.Column(sa.Enum("sha1",
- name="vpn_auth_algorithms"),
- nullable=False)
- encryption_algorithm = sa.Column(sa.Enum("3des", "aes-128",
- "aes-256", "aes-192",
- name="vpn_encrypt_algorithms"),
- nullable=False)
- phase1_negotiation_mode = sa.Column(sa.Enum("main",
- name="ike_phase1_mode"),
- nullable=False)
- lifetime_units = sa.Column(sa.Enum("seconds", "kilobytes",
- name="vpn_lifetime_units"),
- nullable=False)
- lifetime_value = sa.Column(sa.Integer, nullable=False)
- ike_version = sa.Column(sa.Enum("v1", "v2", name="ike_versions"),
- nullable=False)
- pfs = sa.Column(sa.Enum("group2", "group5", "group14",
- name="vpn_pfs"), nullable=False)
-
-
-class IPsecSiteConnection(model_base.BASEV2,
- models_v2.HasId, models_v2.HasTenant):
- """Represents a IPsecSiteConnection Object."""
- __tablename__ = 'ipsec_site_connections'
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(255))
- peer_address = sa.Column(sa.String(255), nullable=False)
- peer_id = sa.Column(sa.String(255), nullable=False)
- route_mode = sa.Column(sa.String(8), nullable=False)
- mtu = sa.Column(sa.Integer, nullable=False)
- initiator = sa.Column(sa.Enum("bi-directional", "response-only",
- name="vpn_initiators"), nullable=False)
- auth_mode = sa.Column(sa.String(16), nullable=False)
- psk = sa.Column(sa.String(255), nullable=False)
- dpd_action = sa.Column(sa.Enum("hold", "clear",
- "restart", "disabled",
- "restart-by-peer", name="vpn_dpd_actions"),
- nullable=False)
- dpd_interval = sa.Column(sa.Integer, nullable=False)
- dpd_timeout = sa.Column(sa.Integer, nullable=False)
- status = sa.Column(sa.String(16), nullable=False)
- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
- vpnservice_id = sa.Column(sa.String(36),
- sa.ForeignKey('vpnservices.id'),
- nullable=False)
- ipsecpolicy_id = sa.Column(sa.String(36),
- sa.ForeignKey('ipsecpolicies.id'),
- nullable=False)
- ikepolicy_id = sa.Column(sa.String(36),
- sa.ForeignKey('ikepolicies.id'),
- nullable=False)
- ipsecpolicy = orm.relationship(
- IPsecPolicy, backref='ipsec_site_connection')
- ikepolicy = orm.relationship(IKEPolicy, backref='ipsec_site_connection')
- peer_cidrs = orm.relationship(IPsecPeerCidr,
- backref='ipsec_site_connection',
- lazy='joined',
- cascade='all, delete, delete-orphan')
-
-
-class VPNService(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a v2 VPNService Object."""
- name = sa.Column(sa.String(255))
- description = sa.Column(sa.String(255))
- status = sa.Column(sa.String(16), nullable=False)
- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
- subnet_id = sa.Column(sa.String(36), sa.ForeignKey('subnets.id'),
- nullable=False)
- router_id = sa.Column(sa.String(36), sa.ForeignKey('routers.id'),
- nullable=False)
- subnet = orm.relationship(models_v2.Subnet)
- router = orm.relationship(l3_db.Router)
- ipsec_site_connections = orm.relationship(
- IPsecSiteConnection,
- backref='vpnservice',
- cascade="all, delete-orphan")
-
-
-class VPNPluginDb(vpnaas.VPNPluginBase, base_db.CommonDbMixin):
- """VPN plugin database class using SQLAlchemy models."""
-
- def _get_validator(self):
- """Obtain validator to use for attribute validation.
-
- Subclasses may override this with a different valdiator, as needed.
- Note: some UTs will directly create a VPNPluginDb object and then
- call its methods, instead of creating a VPNDriverPlugin, which
- will have a service driver associated that will provide a
- validator object. As a result, we use the reference validator here.
- """
- return vpn_validator.VpnReferenceValidator()
-
- def update_status(self, context, model, v_id, status):
- with context.session.begin(subtransactions=True):
- v_db = self._get_resource(context, model, v_id)
- v_db.update({'status': status})
-
- def _get_resource(self, context, model, v_id):
- try:
- r = self._get_by_id(context, model, v_id)
- except exc.NoResultFound:
- with excutils.save_and_reraise_exception(reraise=False) as ctx:
- if issubclass(model, IPsecSiteConnection):
- raise vpnaas.IPsecSiteConnectionNotFound(
- ipsec_site_conn_id=v_id
- )
- elif issubclass(model, IKEPolicy):
- raise vpnaas.IKEPolicyNotFound(ikepolicy_id=v_id)
- elif issubclass(model, IPsecPolicy):
- raise vpnaas.IPsecPolicyNotFound(ipsecpolicy_id=v_id)
- elif issubclass(model, VPNService):
- raise vpnaas.VPNServiceNotFound(vpnservice_id=v_id)
- ctx.reraise = True
- return r
-
- def assert_update_allowed(self, obj):
- status = getattr(obj, 'status', None)
- _id = getattr(obj, 'id', None)
- if utils.in_pending_status(status):
- raise vpnaas.VPNStateInvalidToUpdate(id=_id, state=status)
-
- def _make_ipsec_site_connection_dict(self, ipsec_site_conn, fields=None):
-
- res = {'id': ipsec_site_conn['id'],
- 'tenant_id': ipsec_site_conn['tenant_id'],
- 'name': ipsec_site_conn['name'],
- 'description': ipsec_site_conn['description'],
- 'peer_address': ipsec_site_conn['peer_address'],
- 'peer_id': ipsec_site_conn['peer_id'],
- 'route_mode': ipsec_site_conn['route_mode'],
- 'mtu': ipsec_site_conn['mtu'],
- 'auth_mode': ipsec_site_conn['auth_mode'],
- 'psk': ipsec_site_conn['psk'],
- 'initiator': ipsec_site_conn['initiator'],
- 'dpd': {
- 'action': ipsec_site_conn['dpd_action'],
- 'interval': ipsec_site_conn['dpd_interval'],
- 'timeout': ipsec_site_conn['dpd_timeout']
- },
- 'admin_state_up': ipsec_site_conn['admin_state_up'],
- 'status': ipsec_site_conn['status'],
- 'vpnservice_id': ipsec_site_conn['vpnservice_id'],
- 'ikepolicy_id': ipsec_site_conn['ikepolicy_id'],
- 'ipsecpolicy_id': ipsec_site_conn['ipsecpolicy_id'],
- 'peer_cidrs': [pcidr['cidr']
- for pcidr in ipsec_site_conn['peer_cidrs']]
- }
-
- return self._fields(res, fields)
-
- def _get_subnet_ip_version(self, context, vpnservice_id):
- vpn_service_db = self._get_vpnservice(context, vpnservice_id)
- subnet = vpn_service_db.subnet['cidr']
- ip_version = netaddr.IPNetwork(subnet).version
- return ip_version
-
- def create_ipsec_site_connection(self, context, ipsec_site_connection):
- ipsec_sitecon = ipsec_site_connection['ipsec_site_connection']
- validator = self._get_validator()
- validator.assign_sensible_ipsec_sitecon_defaults(ipsec_sitecon)
- tenant_id = self._get_tenant_id_for_create(context, ipsec_sitecon)
- with context.session.begin(subtransactions=True):
- #Check permissions
- self._get_resource(context,
- VPNService,
- ipsec_sitecon['vpnservice_id'])
- self._get_resource(context,
- IKEPolicy,
- ipsec_sitecon['ikepolicy_id'])
- self._get_resource(context,
- IPsecPolicy,
- ipsec_sitecon['ipsecpolicy_id'])
- vpnservice_id = ipsec_sitecon['vpnservice_id']
- ip_version = self._get_subnet_ip_version(context, vpnservice_id)
- validator.validate_ipsec_site_connection(context,
- ipsec_sitecon,
- ip_version)
- ipsec_site_conn_db = IPsecSiteConnection(
- id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=ipsec_sitecon['name'],
- description=ipsec_sitecon['description'],
- peer_address=ipsec_sitecon['peer_address'],
- peer_id=ipsec_sitecon['peer_id'],
- route_mode='static',
- mtu=ipsec_sitecon['mtu'],
- auth_mode='psk',
- psk=ipsec_sitecon['psk'],
- initiator=ipsec_sitecon['initiator'],
- dpd_action=ipsec_sitecon['dpd_action'],
- dpd_interval=ipsec_sitecon['dpd_interval'],
- dpd_timeout=ipsec_sitecon['dpd_timeout'],
- admin_state_up=ipsec_sitecon['admin_state_up'],
- status=constants.PENDING_CREATE,
- vpnservice_id=vpnservice_id,
- ikepolicy_id=ipsec_sitecon['ikepolicy_id'],
- ipsecpolicy_id=ipsec_sitecon['ipsecpolicy_id']
- )
- context.session.add(ipsec_site_conn_db)
- for cidr in ipsec_sitecon['peer_cidrs']:
- peer_cidr_db = IPsecPeerCidr(
- cidr=cidr,
- ipsec_site_connection_id=ipsec_site_conn_db['id']
- )
- context.session.add(peer_cidr_db)
- return self._make_ipsec_site_connection_dict(ipsec_site_conn_db)
-
- def update_ipsec_site_connection(
- self, context,
- ipsec_site_conn_id, ipsec_site_connection):
- ipsec_sitecon = ipsec_site_connection['ipsec_site_connection']
- changed_peer_cidrs = False
- validator = self._get_validator()
- with context.session.begin(subtransactions=True):
- ipsec_site_conn_db = self._get_resource(
- context,
- IPsecSiteConnection,
- ipsec_site_conn_id)
- vpnservice_id = ipsec_site_conn_db['vpnservice_id']
- ip_version = self._get_subnet_ip_version(context, vpnservice_id)
- validator.assign_sensible_ipsec_sitecon_defaults(
- ipsec_sitecon, ipsec_site_conn_db)
- validator.validate_ipsec_site_connection(
- context,
- ipsec_sitecon,
- ip_version)
- self.assert_update_allowed(ipsec_site_conn_db)
-
- if "peer_cidrs" in ipsec_sitecon:
- changed_peer_cidrs = True
- old_peer_cidr_list = ipsec_site_conn_db['peer_cidrs']
- old_peer_cidr_dict = dict(
- (peer_cidr['cidr'], peer_cidr)
- for peer_cidr in old_peer_cidr_list)
- new_peer_cidr_set = set(ipsec_sitecon["peer_cidrs"])
- old_peer_cidr_set = set(old_peer_cidr_dict)
-
- new_peer_cidrs = list(new_peer_cidr_set)
- for peer_cidr in old_peer_cidr_set - new_peer_cidr_set:
- context.session.delete(old_peer_cidr_dict[peer_cidr])
- for peer_cidr in new_peer_cidr_set - old_peer_cidr_set:
- pcidr = IPsecPeerCidr(
- cidr=peer_cidr,
- ipsec_site_connection_id=ipsec_site_conn_id)
- context.session.add(pcidr)
- del ipsec_sitecon["peer_cidrs"]
- if ipsec_sitecon:
- ipsec_site_conn_db.update(ipsec_sitecon)
- result = self._make_ipsec_site_connection_dict(ipsec_site_conn_db)
- if changed_peer_cidrs:
- result['peer_cidrs'] = new_peer_cidrs
- return result
-
- def delete_ipsec_site_connection(self, context, ipsec_site_conn_id):
- with context.session.begin(subtransactions=True):
- ipsec_site_conn_db = self._get_resource(
- context, IPsecSiteConnection, ipsec_site_conn_id
- )
- context.session.delete(ipsec_site_conn_db)
-
- def _get_ipsec_site_connection(
- self, context, ipsec_site_conn_id):
- return self._get_resource(
- context, IPsecSiteConnection, ipsec_site_conn_id)
-
- def get_ipsec_site_connection(self, context,
- ipsec_site_conn_id, fields=None):
- ipsec_site_conn_db = self._get_ipsec_site_connection(
- context, ipsec_site_conn_id)
- return self._make_ipsec_site_connection_dict(
- ipsec_site_conn_db, fields)
-
- def get_ipsec_site_connections(self, context, filters=None, fields=None):
- return self._get_collection(context, IPsecSiteConnection,
- self._make_ipsec_site_connection_dict,
- filters=filters, fields=fields)
-
- def update_ipsec_site_conn_status(self, context, conn_id, new_status):
- with context.session.begin():
- self._update_connection_status(context, conn_id, new_status, True)
-
- def _update_connection_status(self, context, conn_id, new_status,
- updated_pending):
- """Update the connection status, if changed.
-
- If the connection is not in a pending state, unconditionally update
- the status. Likewise, if in a pending state, and have an indication
- that the status has changed, then update the database.
- """
- try:
- conn_db = self._get_ipsec_site_connection(context, conn_id)
- except vpnaas.IPsecSiteConnectionNotFound:
- return
- if not utils.in_pending_status(conn_db.status) or updated_pending:
- conn_db.status = new_status
-
- def _make_ikepolicy_dict(self, ikepolicy, fields=None):
- res = {'id': ikepolicy['id'],
- 'tenant_id': ikepolicy['tenant_id'],
- 'name': ikepolicy['name'],
- 'description': ikepolicy['description'],
- 'auth_algorithm': ikepolicy['auth_algorithm'],
- 'encryption_algorithm': ikepolicy['encryption_algorithm'],
- 'phase1_negotiation_mode': ikepolicy['phase1_negotiation_mode'],
- 'lifetime': {
- 'units': ikepolicy['lifetime_units'],
- 'value': ikepolicy['lifetime_value'],
- },
- 'ike_version': ikepolicy['ike_version'],
- 'pfs': ikepolicy['pfs']
- }
-
- return self._fields(res, fields)
-
- def create_ikepolicy(self, context, ikepolicy):
- ike = ikepolicy['ikepolicy']
- tenant_id = self._get_tenant_id_for_create(context, ike)
- lifetime_info = ike.get('lifetime', [])
- lifetime_units = lifetime_info.get('units', 'seconds')
- lifetime_value = lifetime_info.get('value', 3600)
-
- with context.session.begin(subtransactions=True):
- ike_db = IKEPolicy(
- id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=ike['name'],
- description=ike['description'],
- auth_algorithm=ike['auth_algorithm'],
- encryption_algorithm=ike['encryption_algorithm'],
- phase1_negotiation_mode=ike['phase1_negotiation_mode'],
- lifetime_units=lifetime_units,
- lifetime_value=lifetime_value,
- ike_version=ike['ike_version'],
- pfs=ike['pfs']
- )
-
- context.session.add(ike_db)
- return self._make_ikepolicy_dict(ike_db)
-
- def update_ikepolicy(self, context, ikepolicy_id, ikepolicy):
- ike = ikepolicy['ikepolicy']
- with context.session.begin(subtransactions=True):
- ikepolicy = context.session.query(IPsecSiteConnection).filter_by(
- ikepolicy_id=ikepolicy_id).first()
- if ikepolicy:
- raise vpnaas.IKEPolicyInUse(ikepolicy_id=ikepolicy_id)
- ike_db = self._get_resource(context, IKEPolicy, ikepolicy_id)
- if ike:
- lifetime_info = ike.get('lifetime')
- if lifetime_info:
- if lifetime_info.get('units'):
- ike['lifetime_units'] = lifetime_info['units']
- if lifetime_info.get('value'):
- ike['lifetime_value'] = lifetime_info['value']
- ike_db.update(ike)
- return self._make_ikepolicy_dict(ike_db)
-
- def delete_ikepolicy(self, context, ikepolicy_id):
- with context.session.begin(subtransactions=True):
- ikepolicy = context.session.query(IPsecSiteConnection).filter_by(
- ikepolicy_id=ikepolicy_id).first()
- if ikepolicy:
- raise vpnaas.IKEPolicyInUse(ikepolicy_id=ikepolicy_id)
- ike_db = self._get_resource(context, IKEPolicy, ikepolicy_id)
- context.session.delete(ike_db)
-
- def get_ikepolicy(self, context, ikepolicy_id, fields=None):
- ike_db = self._get_resource(context, IKEPolicy, ikepolicy_id)
- return self._make_ikepolicy_dict(ike_db, fields)
-
- def get_ikepolicies(self, context, filters=None, fields=None):
- return self._get_collection(context, IKEPolicy,
- self._make_ikepolicy_dict,
- filters=filters, fields=fields)
-
- def _make_ipsecpolicy_dict(self, ipsecpolicy, fields=None):
-
- res = {'id': ipsecpolicy['id'],
- 'tenant_id': ipsecpolicy['tenant_id'],
- 'name': ipsecpolicy['name'],
- 'description': ipsecpolicy['description'],
- 'transform_protocol': ipsecpolicy['transform_protocol'],
- 'auth_algorithm': ipsecpolicy['auth_algorithm'],
- 'encryption_algorithm': ipsecpolicy['encryption_algorithm'],
- 'encapsulation_mode': ipsecpolicy['encapsulation_mode'],
- 'lifetime': {
- 'units': ipsecpolicy['lifetime_units'],
- 'value': ipsecpolicy['lifetime_value'],
- },
- 'pfs': ipsecpolicy['pfs']
- }
-
- return self._fields(res, fields)
-
- def create_ipsecpolicy(self, context, ipsecpolicy):
- ipsecp = ipsecpolicy['ipsecpolicy']
- tenant_id = self._get_tenant_id_for_create(context, ipsecp)
- lifetime_info = ipsecp['lifetime']
- lifetime_units = lifetime_info.get('units', 'seconds')
- lifetime_value = lifetime_info.get('value', 3600)
-
- with context.session.begin(subtransactions=True):
- ipsecp_db = IPsecPolicy(id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=ipsecp['name'],
- description=ipsecp['description'],
- transform_protocol=ipsecp['transform_'
- 'protocol'],
- auth_algorithm=ipsecp['auth_algorithm'],
- encryption_algorithm=ipsecp['encryption_'
- 'algorithm'],
- encapsulation_mode=ipsecp['encapsulation_'
- 'mode'],
- lifetime_units=lifetime_units,
- lifetime_value=lifetime_value,
- pfs=ipsecp['pfs'])
- context.session.add(ipsecp_db)
- return self._make_ipsecpolicy_dict(ipsecp_db)
-
- def update_ipsecpolicy(self, context, ipsecpolicy_id, ipsecpolicy):
- ipsecp = ipsecpolicy['ipsecpolicy']
- with context.session.begin(subtransactions=True):
- ipsecpolicy = context.session.query(IPsecSiteConnection).filter_by(
- ipsecpolicy_id=ipsecpolicy_id).first()
- if ipsecpolicy:
- raise vpnaas.IPsecPolicyInUse(ipsecpolicy_id=ipsecpolicy_id)
- ipsecp_db = self._get_resource(context,
- IPsecPolicy,
- ipsecpolicy_id)
- if ipsecp:
- lifetime_info = ipsecp.get('lifetime')
- if lifetime_info:
- if lifetime_info.get('units'):
- ipsecp['lifetime_units'] = lifetime_info['units']
- if lifetime_info.get('value'):
- ipsecp['lifetime_value'] = lifetime_info['value']
- ipsecp_db.update(ipsecp)
- return self._make_ipsecpolicy_dict(ipsecp_db)
-
- def delete_ipsecpolicy(self, context, ipsecpolicy_id):
- with context.session.begin(subtransactions=True):
- ipsecpolicy = context.session.query(IPsecSiteConnection).filter_by(
- ipsecpolicy_id=ipsecpolicy_id).first()
- if ipsecpolicy:
- raise vpnaas.IPsecPolicyInUse(ipsecpolicy_id=ipsecpolicy_id)
- ipsec_db = self._get_resource(context, IPsecPolicy, ipsecpolicy_id)
- context.session.delete(ipsec_db)
-
- def get_ipsecpolicy(self, context, ipsecpolicy_id, fields=None):
- ipsec_db = self._get_resource(context, IPsecPolicy, ipsecpolicy_id)
- return self._make_ipsecpolicy_dict(ipsec_db, fields)
-
- def get_ipsecpolicies(self, context, filters=None, fields=None):
- return self._get_collection(context, IPsecPolicy,
- self._make_ipsecpolicy_dict,
- filters=filters, fields=fields)
-
- def _make_vpnservice_dict(self, vpnservice, fields=None):
- res = {'id': vpnservice['id'],
- 'name': vpnservice['name'],
- 'description': vpnservice['description'],
- 'tenant_id': vpnservice['tenant_id'],
- 'subnet_id': vpnservice['subnet_id'],
- 'router_id': vpnservice['router_id'],
- 'admin_state_up': vpnservice['admin_state_up'],
- 'status': vpnservice['status']}
- return self._fields(res, fields)
-
- def create_vpnservice(self, context, vpnservice):
- vpns = vpnservice['vpnservice']
- tenant_id = self._get_tenant_id_for_create(context, vpns)
- validator = self._get_validator()
- with context.session.begin(subtransactions=True):
- validator.validate_vpnservice(context, vpns)
- vpnservice_db = VPNService(id=uuidutils.generate_uuid(),
- tenant_id=tenant_id,
- name=vpns['name'],
- description=vpns['description'],
- subnet_id=vpns['subnet_id'],
- router_id=vpns['router_id'],
- admin_state_up=vpns['admin_state_up'],
- status=constants.PENDING_CREATE)
- context.session.add(vpnservice_db)
- return self._make_vpnservice_dict(vpnservice_db)
-
- def update_vpnservice(self, context, vpnservice_id, vpnservice):
- vpns = vpnservice['vpnservice']
- with context.session.begin(subtransactions=True):
- vpns_db = self._get_resource(context, VPNService, vpnservice_id)
- self.assert_update_allowed(vpns_db)
- if vpns:
- vpns_db.update(vpns)
- return self._make_vpnservice_dict(vpns_db)
-
- def delete_vpnservice(self, context, vpnservice_id):
- with context.session.begin(subtransactions=True):
- if context.session.query(IPsecSiteConnection).filter_by(
- vpnservice_id=vpnservice_id
- ).first():
- raise vpnaas.VPNServiceInUse(vpnservice_id=vpnservice_id)
- vpns_db = self._get_resource(context, VPNService, vpnservice_id)
- context.session.delete(vpns_db)
-
- def _get_vpnservice(self, context, vpnservice_id):
- return self._get_resource(context, VPNService, vpnservice_id)
-
- def get_vpnservice(self, context, vpnservice_id, fields=None):
- vpns_db = self._get_resource(context, VPNService, vpnservice_id)
- return self._make_vpnservice_dict(vpns_db, fields)
-
- def get_vpnservices(self, context, filters=None, fields=None):
- return self._get_collection(context, VPNService,
- self._make_vpnservice_dict,
- filters=filters, fields=fields)
-
- def check_router_in_use(self, context, router_id):
- vpnservices = self.get_vpnservices(
- context, filters={'router_id': [router_id]})
- if vpnservices:
- raise vpnaas.RouterInUseByVPNService(
- router_id=router_id,
- vpnservice_id=vpnservices[0]['id'])
-
- def check_subnet_in_use(self, context, subnet_id):
- with context.session.begin(subtransactions=True):
- vpnservices = context.session.query(VPNService).filter_by(
- subnet_id=subnet_id
- ).first()
- if vpnservices:
- raise vpnaas.SubnetInUseByVPNService(
- subnet_id=subnet_id,
- vpnservice_id=vpnservices['id'])
-
-
-class VPNPluginRpcDbMixin():
- def _get_agent_hosting_vpn_services(self, context, host):
-
- plugin = manager.NeutronManager.get_plugin()
- agent = plugin._get_agent_by_type_and_host(
- context, n_constants.AGENT_TYPE_L3, host)
- if not agent.admin_state_up:
- return []
- query = context.session.query(VPNService)
- query = query.join(IPsecSiteConnection)
- query = query.join(IKEPolicy)
- query = query.join(IPsecPolicy)
- query = query.join(IPsecPeerCidr)
- query = query.join(l3_agent_db.RouterL3AgentBinding,
- l3_agent_db.RouterL3AgentBinding.router_id ==
- VPNService.router_id)
- query = query.filter(
- l3_agent_db.RouterL3AgentBinding.l3_agent_id == agent.id)
- return query
-
- def update_status_by_agent(self, context, service_status_info_list):
- """Updating vpnservice and vpnconnection status.
-
- :param context: context variable
- :param service_status_info_list: list of status
- The structure is
- [{id: vpnservice_id,
- status: ACTIVE|DOWN|ERROR,
- updated_pending_status: True|False
- ipsec_site_connections: {
- ipsec_site_connection_id: {
- status: ACTIVE|DOWN|ERROR,
- updated_pending_status: True|False
- }
- }]
- The agent will set updated_pending_status as True,
- when agent update any pending status.
- """
- with context.session.begin(subtransactions=True):
- for vpnservice in service_status_info_list:
- try:
- vpnservice_db = self._get_vpnservice(
- context, vpnservice['id'])
- except vpnaas.VPNServiceNotFound:
- LOG.warn(_LW('vpnservice %s in db is already deleted'),
- vpnservice['id'])
- continue
-
- if (not utils.in_pending_status(vpnservice_db.status)
- or vpnservice['updated_pending_status']):
- vpnservice_db.status = vpnservice['status']
- for conn_id, conn in vpnservice[
- 'ipsec_site_connections'].items():
- self._update_connection_status(
- context, conn_id, conn['status'],
- conn['updated_pending_status'])
+++ /dev/null
-# Copyright 2014 Cisco Systems, Inc. All rights reserved.
-#
-# 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.db import l3_db
-from neutron.extensions import vpnaas
-from neutron import manager
-from neutron.plugins.common import constants
-
-
-class VpnReferenceValidator(object):
-
- """Baseline validation routines for VPN resources."""
-
- IP_MIN_MTU = {4: 68, 6: 1280}
-
- @property
- def l3_plugin(self):
- try:
- return self._l3_plugin
- except AttributeError:
- self._l3_plugin = manager.NeutronManager.get_service_plugins().get(
- constants.L3_ROUTER_NAT)
- return self._l3_plugin
-
- @property
- def core_plugin(self):
- try:
- return self._core_plugin
- except AttributeError:
- self._core_plugin = manager.NeutronManager.get_plugin()
- return self._core_plugin
-
- def _check_dpd(self, ipsec_sitecon):
- """Ensure that DPD timeout is greater than DPD interval."""
- if ipsec_sitecon['dpd_timeout'] <= ipsec_sitecon['dpd_interval']:
- raise vpnaas.IPsecSiteConnectionDpdIntervalValueError(
- attr='dpd_timeout')
-
- def _check_mtu(self, context, mtu, ip_version):
- if mtu < VpnReferenceValidator.IP_MIN_MTU[ip_version]:
- raise vpnaas.IPsecSiteConnectionMtuError(mtu=mtu,
- version=ip_version)
-
- def assign_sensible_ipsec_sitecon_defaults(self, ipsec_sitecon,
- prev_conn=None):
- """Provide defaults for optional items, if missing.
-
- Flatten the nested DPD information, and set default values for
- any missing information. For connection updates, the previous
- values will be used as defaults for any missing items.
- """
- if not prev_conn:
- prev_conn = {'dpd_action': 'hold',
- 'dpd_interval': 30,
- 'dpd_timeout': 120}
- dpd = ipsec_sitecon.get('dpd', {})
- ipsec_sitecon['dpd_action'] = dpd.get('action',
- prev_conn['dpd_action'])
- ipsec_sitecon['dpd_interval'] = dpd.get('interval',
- prev_conn['dpd_interval'])
- ipsec_sitecon['dpd_timeout'] = dpd.get('timeout',
- prev_conn['dpd_timeout'])
-
- def validate_ipsec_site_connection(self, context, ipsec_sitecon,
- ip_version):
- """Reference implementation of validation for IPSec connection."""
- self._check_dpd(ipsec_sitecon)
- mtu = ipsec_sitecon.get('mtu')
- if mtu:
- self._check_mtu(context, mtu, ip_version)
-
- def _check_router(self, context, router_id):
- router = self.l3_plugin.get_router(context, router_id)
- if not router.get(l3_db.EXTERNAL_GW_INFO):
- raise vpnaas.RouterIsNotExternal(router_id=router_id)
-
- def _check_subnet_id(self, context, router_id, subnet_id):
- ports = self.core_plugin.get_ports(
- context,
- filters={
- 'fixed_ips': {'subnet_id': [subnet_id]},
- 'device_id': [router_id]})
- if not ports:
- raise vpnaas.SubnetIsNotConnectedToRouter(
- subnet_id=subnet_id,
- router_id=router_id)
-
- def validate_vpnservice(self, context, vpnservice):
- self._check_router(context, vpnservice['router_id'])
- self._check_subnet_id(context, vpnservice['router_id'],
- vpnservice['subnet_id'])
__tablename__ = 'vcns_firewall_rule_bindings'
rule_id = sa.Column(sa.String(36),
- sa.ForeignKey("firewall_rules.id"),
+ # TODO(dougw) unbreak this link
+ #sa.ForeignKey("firewall_rules.id"),
primary_key=True)
edge_id = sa.Column(sa.String(36), primary_key=True)
rule_vseid = sa.Column(sa.String(36))
__tablename__ = 'vcns_edge_pool_bindings'
pool_id = sa.Column(sa.String(36),
- sa.ForeignKey("pools.id", ondelete="CASCADE"),
+ # TODO(dougw) unbreak this link
+ #sa.ForeignKey("pools.id", ondelete="CASCADE"),
primary_key=True)
edge_id = sa.Column(sa.String(36), primary_key=True)
pool_vseid = sa.Column(sa.String(36))
__tablename__ = 'vcns_edge_vip_bindings'
vip_id = sa.Column(sa.String(36),
- sa.ForeignKey("vips.id", ondelete="CASCADE"),
+ # TODO(dougw) unbreak this link
+ #sa.ForeignKey("vips.id", ondelete="CASCADE"),
primary_key=True)
edge_id = sa.Column(sa.String(36))
vip_vseid = sa.Column(sa.String(36))
__tablename__ = 'vcns_edge_monitor_bindings'
monitor_id = sa.Column(sa.String(36),
- sa.ForeignKey("healthmonitors.id",
- ondelete="CASCADE"),
+ # TODO(dougw) unbreak this link
+ #sa.ForeignKey("healthmonitors.id",
+ # ondelete="CASCADE"),
primary_key=True)
edge_id = sa.Column(sa.String(36), primary_key=True)
monitor_vseid = sa.Column(sa.String(36))
from neutron_fwaas.db.firewall import firewall_db
except Exception:
print("WARNING: missing neutron-fwaas package")
- # TODO(dougw) - temporary, this is going away
- from neutron.db.firewall import firewall_db
from neutron.db import l3_db
try:
from neutron_lbaas.db.loadbalancer import loadbalancer_db
except Exception:
print("WARNING: missing neutron-lbaas package")
- # TODO(dougw) - temporary, this is going away
- from neutron.db.loadbalancer import loadbalancer_db
from neutron.db import routedserviceinsertion_db as rsi_db
try:
from neutron_vpnaas.db.vpn import vpn_db
except Exception:
print("WARNING: missing neutron-vpnaas package")
- # TODO(dougw) - temporary, this is going away
- from neutron.db.vpn import vpn_db
from neutron.extensions import firewall as fw_ext
from neutron.extensions import l3
from neutron.extensions import routedserviceinsertion as rsi
from neutron_lbaas.services.loadbalancer import constants as lb_constants
except Exception:
print("WARNING: missing neutron-lbaas package")
- # TODO(dougw) - this is going away
- from neutron.services.loadbalancer import constants as lb_constants
LOG = logging.getLogger(__name__)
-# Copyright 2014 Embrane, Inc.
+# Copyright 2014 A10 Networks, Inc
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# License for the specific language governing permissions and limitations
# under the License.
-import sqlalchemy as sql
+from neutron.i18n import _LE
+from neutron.openstack.common import log as logging
-from neutron.db import model_base
+LOG = logging.getLogger(__name__)
+try:
+ from neutron_fwaas.services.firewall import fwaas_plugin
+except Exception as e:
+ LOG.error(_LE("Firewall service plugin requires neutron-fwaas module"))
+ raise e
-class PoolPort(model_base.BASEV2):
- """Represents the connection between pools and ports."""
- __tablename__ = 'embrane_pool_port'
- pool_id = sql.Column(sql.String(36), sql.ForeignKey('pools.id'),
- primary_key=True)
- port_id = sql.Column(sql.String(36), sql.ForeignKey('ports.id'),
- nullable=False)
+class FirewallPlugin(fwaas_plugin.FirewallPlugin):
+ pass
+++ /dev/null
-# Copyright (c) 2013 OpenStack Foundation.
-# All Rights Reserved.
-#
-# 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 random
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-from sqlalchemy.orm import joinedload
-
-from neutron.common import constants
-from neutron.db import agents_db
-from neutron.db import agentschedulers_db
-from neutron.db import model_base
-from neutron.extensions import lbaas_agentscheduler
-from neutron.i18n import _LW
-from neutron.openstack.common import log as logging
-
-LOG = logging.getLogger(__name__)
-
-
-class PoolLoadbalancerAgentBinding(model_base.BASEV2):
- """Represents binding between neutron loadbalancer pools and agents."""
-
- pool_id = sa.Column(sa.String(36),
- sa.ForeignKey("pools.id", ondelete='CASCADE'),
- primary_key=True)
- agent = orm.relation(agents_db.Agent)
- agent_id = sa.Column(sa.String(36), sa.ForeignKey("agents.id",
- ondelete='CASCADE'),
- nullable=False)
-
-
-class LbaasAgentSchedulerDbMixin(agentschedulers_db.AgentSchedulerDbMixin,
- lbaas_agentscheduler
- .LbaasAgentSchedulerPluginBase):
-
- def get_lbaas_agent_hosting_pool(self, context, pool_id, active=None):
- query = context.session.query(PoolLoadbalancerAgentBinding)
- query = query.options(joinedload('agent'))
- binding = query.get(pool_id)
-
- if (binding and self.is_eligible_agent(
- active, binding.agent)):
- return {'agent': self._make_agent_dict(binding.agent)}
-
- def get_lbaas_agents(self, context, active=None, filters=None):
- query = context.session.query(agents_db.Agent)
- query = query.filter_by(agent_type=constants.AGENT_TYPE_LOADBALANCER)
- if active is not None:
- query = query.filter_by(admin_state_up=active)
- if filters:
- for key, value in filters.iteritems():
- column = getattr(agents_db.Agent, key, None)
- if column:
- query = query.filter(column.in_(value))
-
- return [agent
- for agent in query
- if self.is_eligible_agent(active, agent)]
-
- def list_pools_on_lbaas_agent(self, context, id):
- query = context.session.query(PoolLoadbalancerAgentBinding.pool_id)
- query = query.filter_by(agent_id=id)
- pool_ids = [item[0] for item in query]
- if pool_ids:
- return {'pools': self.get_pools(context, filters={'id': pool_ids})}
- else:
- return {'pools': []}
-
- def get_lbaas_agent_candidates(self, device_driver, active_agents):
- candidates = []
- for agent in active_agents:
- agent_conf = self.get_configuration_dict(agent)
- if device_driver in agent_conf['device_drivers']:
- candidates.append(agent)
- return candidates
-
-
-class ChanceScheduler(object):
- """Allocate a loadbalancer agent for a vip in a random way."""
-
- def schedule(self, plugin, context, pool, device_driver):
- """Schedule the pool to an active loadbalancer agent if there
- is no enabled agent hosting it.
- """
- with context.session.begin(subtransactions=True):
- lbaas_agent = plugin.get_lbaas_agent_hosting_pool(
- context, pool['id'])
- if lbaas_agent:
- LOG.debug('Pool %(pool_id)s has already been hosted'
- ' by lbaas agent %(agent_id)s',
- {'pool_id': pool['id'],
- 'agent_id': lbaas_agent['id']})
- return
-
- active_agents = plugin.get_lbaas_agents(context, active=True)
- if not active_agents:
- LOG.warn(_LW('No active lbaas agents for pool %s'), pool['id'])
- return
-
- candidates = plugin.get_lbaas_agent_candidates(device_driver,
- active_agents)
- if not candidates:
- LOG.warn(_LW('No lbaas agent supporting device driver %s'),
- device_driver)
- return
-
- chosen_agent = random.choice(candidates)
- binding = PoolLoadbalancerAgentBinding()
- binding.agent = chosen_agent
- binding.pool_id = pool['id']
- context.session.add(binding)
- LOG.debug('Pool %(pool_id)s is scheduled to lbaas agent '
- '%(agent_id)s',
- {'pool_id': pool['id'],
- 'agent_id': chosen_agent['id']})
- return chosen_agent
+++ /dev/null
-# Copyright 2013 Mirantis, Inc.
-# All Rights Reserved.
-#
-# 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.
-
-LB_METHOD_ROUND_ROBIN = 'ROUND_ROBIN'
-LB_METHOD_LEAST_CONNECTIONS = 'LEAST_CONNECTIONS'
-LB_METHOD_SOURCE_IP = 'SOURCE_IP'
-
-PROTOCOL_TCP = 'TCP'
-PROTOCOL_HTTP = 'HTTP'
-PROTOCOL_HTTPS = 'HTTPS'
-
-HEALTH_MONITOR_PING = 'PING'
-HEALTH_MONITOR_TCP = 'TCP'
-HEALTH_MONITOR_HTTP = 'HTTP'
-HEALTH_MONITOR_HTTPS = 'HTTPS'
-
-SESSION_PERSISTENCE_SOURCE_IP = 'SOURCE_IP'
-SESSION_PERSISTENCE_HTTP_COOKIE = 'HTTP_COOKIE'
-SESSION_PERSISTENCE_APP_COOKIE = 'APP_COOKIE'
-
-STATS_ACTIVE_CONNECTIONS = 'active_connections'
-STATS_MAX_CONNECTIONS = 'max_connections'
-STATS_TOTAL_CONNECTIONS = 'total_connections'
-STATS_CURRENT_SESSIONS = 'current_sessions'
-STATS_MAX_SESSIONS = 'max_sessions'
-STATS_TOTAL_SESSIONS = 'total_sessions'
-STATS_IN_BYTES = 'bytes_in'
-STATS_OUT_BYTES = 'bytes_out'
-STATS_CONNECTION_ERRORS = 'connection_errors'
-STATS_RESPONSE_ERRORS = 'response_errors'
-STATS_STATUS = 'status'
-STATS_HEALTH = 'health'
-STATS_FAILED_CHECKS = 'failed_checks'
+++ /dev/null
-# Copyright 2013 Radware LTD.
-#
-# 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 abc
-
-import six
-
-#
-# DEPRECATION WARNING. THIS ABSTRACT DRIVER IS FOR THE LBAAS V1 OBJECT
-# MODEL AND SHOULD NO LONGER BE USED TO CREATE DRIVERS.
-#
-# PLEASE REFER TO driver_base.py and driver_mixins.py for the newest
-# lbaas driver base classes.
-#
-
-
-@six.add_metaclass(abc.ABCMeta)
-class LoadBalancerAbstractDriver(object):
- """Abstract lbaas driver that expose ~same API as lbaas plugin.
-
- The configuration elements (Vip,Member,etc) are the dicts that
- are returned to the tenant.
- Get operations are not part of the API - it will be handled
- by the lbaas plugin.
- """
-
- @abc.abstractmethod
- def create_vip(self, context, vip):
- """A real driver would invoke a call to his backend
- and set the Vip status to ACTIVE/ERROR according
- to the backend call result
- self.plugin.update_status(context, Vip, vip["id"],
- constants.ACTIVE)
- """
- pass
-
- @abc.abstractmethod
- def update_vip(self, context, old_vip, vip):
- """Driver may call the code below in order to update the status.
- self.plugin.update_status(context, Vip, id, constants.ACTIVE)
- """
- pass
-
- @abc.abstractmethod
- def delete_vip(self, context, vip):
- """A real driver would invoke a call to his backend
- and try to delete the Vip.
- if the deletion was successful, delete the record from the database.
- if the deletion has failed, set the Vip status to ERROR.
- """
- pass
-
- @abc.abstractmethod
- def create_pool(self, context, pool):
- """Driver may call the code below in order to update the status.
- self.plugin.update_status(context, Pool, pool["id"],
- constants.ACTIVE)
- """
- pass
-
- @abc.abstractmethod
- def update_pool(self, context, old_pool, pool):
- """Driver may call the code below in order to update the status.
- self.plugin.update_status(context,
- Pool,
- pool["id"], constants.ACTIVE)
- """
- pass
-
- @abc.abstractmethod
- def delete_pool(self, context, pool):
- """Driver can call the code below in order to delete the pool.
- self.plugin._delete_db_pool(context, pool["id"])
- or set the status to ERROR if deletion failed
- """
- pass
-
- @abc.abstractmethod
- def stats(self, context, pool_id):
- pass
-
- @abc.abstractmethod
- def create_member(self, context, member):
- """Driver may call the code below in order to update the status.
- self.plugin.update_status(context, Member, member["id"],
- constants.ACTIVE)
- """
- pass
-
- @abc.abstractmethod
- def update_member(self, context, old_member, member):
- """Driver may call the code below in order to update the status.
- self.plugin.update_status(context, Member,
- member["id"], constants.ACTIVE)
- """
- pass
-
- @abc.abstractmethod
- def delete_member(self, context, member):
- pass
-
- @abc.abstractmethod
- def update_pool_health_monitor(self, context,
- old_health_monitor,
- health_monitor,
- pool_id):
- pass
-
- @abc.abstractmethod
- def create_pool_health_monitor(self, context,
- health_monitor,
- pool_id):
- """Driver may call the code below in order to update the status.
- self.plugin.update_pool_health_monitor(context,
- health_monitor["id"],
- pool_id,
- constants.ACTIVE)
- """
- pass
-
- @abc.abstractmethod
- def delete_pool_health_monitor(self, context, health_monitor, pool_id):
- pass
+++ /dev/null
-Embrane LBaaS Driver
-
-This DRIVER interfaces OpenStack Neutron with Embrane's heleos platform,
-Load Balancing appliances for cloud environments.
-
-L2 connectivity is leveraged by one of the supported existing plugins.
-
-For more details on use, configuration and implementation please refer to:
-https://wiki.openstack.org/wiki/Neutron/LBaaS/EmbraneDriver
\ No newline at end of file
+++ /dev/null
-# Copyright 2014 Embrane, Inc.
-# All Rights Reserved.
-#
-# 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 eventlet import greenthread
-from eventlet import queue
-from heleosapi import exceptions as h_exc
-
-from neutron.i18n import _LE
-from neutron.openstack.common import log as logging
-from neutron.plugins.embrane.common import contexts as ctx
-from neutron.services.loadbalancer.drivers.embrane.agent import lb_operations
-from neutron.services.loadbalancer.drivers.embrane import constants as econ
-
-LOG = logging.getLogger(__name__)
-
-
-class Dispatcher(object):
- def __init__(self, driver, async=True):
- self._async = async
- self._driver = driver
- self.sync_items = dict()
- self.handlers = lb_operations.handlers
-
- def dispatch_lb(self, d_context, *args, **kwargs):
- item = d_context.item
- event = d_context.event
- n_context = d_context.n_context
- chain = d_context.chain
-
- item_id = item["id"]
- if event in self.handlers:
- for f in self.handlers[event]:
- first_run = False
- if item_id not in self.sync_items:
- self.sync_items[item_id] = [queue.Queue()]
- first_run = True
- self.sync_items[item_id][0].put(
- ctx.OperationContext(event, n_context, item, chain, f,
- args, kwargs))
- if first_run:
- t = greenthread.spawn(self._consume_lb,
- item_id,
- self.sync_items[item_id][0],
- self._driver,
- self._async)
- self.sync_items[item_id].append(t)
- if not self._async:
- t = self.sync_items[item_id][1]
- t.wait()
-
- def _consume_lb(self, sync_item, sync_queue, driver, a_sync):
- current_state = None
- while True:
- try:
- if current_state == econ.DELETED:
- del self.sync_items[sync_item]
- return
- try:
- operation_context = sync_queue.get(
- block=a_sync,
- timeout=econ.QUEUE_TIMEOUT)
- except queue.Empty:
- del self.sync_items[sync_item]
- return
-
- (operation_context.chain and
- operation_context.chain.execute_all())
-
- transient_state = None
- try:
- transient_state = operation_context.function(
- driver, operation_context.n_context,
- operation_context.item, *operation_context.args,
- **operation_context.kwargs)
- except (h_exc.PendingDva, h_exc.DvaNotFound,
- h_exc.BrokenInterface, h_exc.DvaCreationFailed,
- h_exc.BrokenDva, h_exc.ConfigurationFailed) as ex:
- LOG.warning(econ.error_map[type(ex)], ex.message)
- except h_exc.DvaDeleteFailed as ex:
- LOG.warning(econ.error_map[type(ex)], ex.message)
- transient_state = econ.DELETED
- finally:
- # if the returned transient state is None, no operations
- # are required on the DVA status
- if transient_state == econ.DELETED:
- current_state = driver._delete_vip(
- operation_context.n_context,
- operation_context.item)
- # Error state cannot be reverted
- else:
- driver._update_vip_graph_state(
- operation_context.n_context,
- operation_context.item)
- except Exception:
- LOG.exception(_LE('Unhandled exception occurred'))
+++ /dev/null
-# Copyright 2014 Embrane, Inc.
-# All Rights Reserved.
-#
-# 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 functools
-
-from heleosapi import exceptions as h_exc
-
-from neutron.i18n import _LW
-from neutron.openstack.common import log as logging
-from neutron.services.loadbalancer import constants as lcon
-from neutron.services.loadbalancer.drivers.embrane import constants as econ
-
-LOG = logging.getLogger(__name__)
-handlers = {}
-
-
-def handler(event, handler):
- def wrap(f):
- if event not in handler.keys():
- handler[event] = [f]
- else:
- handler[event].append(f)
-
- @functools.wraps(f)
- def wrapped_f(*args, **kwargs):
- return f(*args, **kwargs)
-
- return wrapped_f
-
- return wrap
-
-
-@handler(econ.Events.CREATE_VIP, handlers)
-def _provision_load_balancer(driver, context, vip, flavor,
- vip_utif_info, vip_ip_allocation_info,
- pool_utif_info=None,
- pool_ip_allocation_info=None,
- pool=None, members=None,
- monitors=None):
- api = driver._heleos_api
- tenant_id = context.tenant_id
- admin_state = vip["admin_state_up"]
- # Architectural configuration
- api.create_load_balancer(tenant_id=tenant_id,
- router_id=vip["id"],
- name=vip["name"],
- flavor=flavor,
- up=False)
- api.grow_interface(vip_utif_info, False, tenant_id, vip["id"])
- if pool:
- api.grow_interface(pool_utif_info, False, tenant_id,
- vip["id"])
-
- # Logical configuration
- api.allocate_address(vip["id"], True, vip_ip_allocation_info)
- if pool:
- api.allocate_address(vip["id"], True, pool_ip_allocation_info)
- dva = api.configure_load_balancer(vip["id"], admin_state,
- vip, pool,
- monitors, members)
- return api.extract_dva_state(dva)
-
-
-@handler(econ.Events.UPDATE_VIP, handlers)
-def _update_load_balancer(driver, context, vip,
- old_pool_id=None, old_port_id=None,
- removed_ip=None, pool_utif_info=None,
- pool_ip_allocation_info=None,
- new_pool=None, members=None,
- monitors=None):
- api = driver._heleos_api
- tenant_id = context.tenant_id
- admin_state = vip["admin_state_up"]
-
- if old_pool_id:
- # Architectural Changes
- api.de_allocate_address(vip['id'], False, old_port_id, removed_ip)
- api.shrink_interface(tenant_id, vip["id"], False, old_port_id)
- api.grow_interface(pool_utif_info, False, tenant_id, vip["id"])
- # Configuration Changes
- api.allocate_address(vip["id"], True, pool_ip_allocation_info)
- api.replace_pool(vip["id"], True, vip, old_pool_id,
- new_pool, monitors, members)
-
- api.update_vservice(vip["id"], True, vip)
- # Dva update
- dva = api.update_dva(tenant_id, vip["id"], vip["name"],
- admin_state, description=vip["description"])
-
- return api.extract_dva_state(dva)
-
-
-@handler(econ.Events.DELETE_VIP, handlers)
-def _delete_load_balancer(driver, context, vip):
- try:
- driver._heleos_api.delete_dva(context.tenant_id, vip['id'])
- except h_exc.DvaNotFound:
- LOG.warning(_LW('The load balancer %s had no physical representation, '
- 'likely already deleted'), vip['id'])
- return econ.DELETED
-
-
-@handler(econ.Events.UPDATE_POOL, handlers)
-def _update_server_pool(driver, context, vip, pool,
- monitors=None):
- api = driver._heleos_api
- cookie = ((vip.get('session_persistence') or {}).get('type') ==
- lcon.SESSION_PERSISTENCE_HTTP_COOKIE)
- return api.extract_dva_state(api.update_pool(vip['id'],
- vip['admin_state_up'],
- pool, cookie, monitors))
-
-
-@handler(econ.Events.ADD_OR_UPDATE_MEMBER, handlers)
-def _add_or_update_pool_member(driver, context, vip, member, protocol):
- api = driver._heleos_api
- return api.extract_dva_state(api.update_backend_server(
- vip['id'], vip['admin_state_up'], member, protocol))
-
-
-@handler(econ.Events.REMOVE_MEMBER, handlers)
-def _remove_member_from_pool(driver, context, vip, member):
- api = driver._heleos_api
- return api.extract_dva_state(api.remove_pool_member(vip['id'],
- vip['admin_state_up'],
- member))
-
-
-@handler(econ.Events.DELETE_MEMBER, handlers)
-def _delete_member(driver, context, vip, member):
- with context.session.begin(subtransactions=True):
- api = driver._heleos_api
- dva = api.delete_backend_server(vip['id'], vip['admin_state_up'],
- member)
- driver._delete_member(context, member)
- return api.extract_dva_state(dva)
-
-
-@handler(econ.Events.ADD_POOL_HM, handlers)
-def _create_pool_hm(driver, context, vip, hm, pool_id):
- api = driver._heleos_api
- return api.extract_dva_state(api.add_pool_monitor(
- vip['id'], vip['admin_state_up'], hm, pool_id))
-
-
-@handler(econ.Events.UPDATE_POOL_HM, handlers)
-def _update_pool_hm(driver, context, vip, hm, pool_id):
- api = driver._heleos_api
- return api.extract_dva_state(api.update_pool_monitor(
- vip['id'], vip['admin_state_up'], hm, pool_id))
-
-
-@handler(econ.Events.DELETE_POOL_HM, handlers)
-def _delete_pool_hm(driver, context, vip, hm, pool_id):
- with context.session.begin(subtransactions=True):
- api = driver._heleos_api
- dva = api.add_pool_monitor(vip['id'], vip['admin_state_up'],
- hm, pool_id)
- driver._delete_pool_hm(context, hm, pool_id)
- return api.extract_dva_state(dva)
-
-
-@handler(econ.Events.POLL_GRAPH, handlers)
-def _poll_graph(driver, context, vip):
- api = driver._heleos_api
- return api.extract_dva_state(api.get_dva(vip['id']))
+++ /dev/null
-# Copyright 2014 Embrane, Inc.
-# All Rights Reserved.
-#
-# 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
-
-# User may want to use LB service together with the L3 plugin, but using
-# different resources. The service will inherit the configuration from the
-# L3 heleos plugin if present and not overridden.
-heleos_opts = [
- cfg.StrOpt('esm_mgmt',
- help=_('ESM management root address')),
- cfg.StrOpt('admin_username',
- help=_('ESM admin username.')),
- cfg.StrOpt('admin_password',
- secret=True,
- help=_('ESM admin password.')),
- cfg.StrOpt('lb_image',
- help=_('Load Balancer image id (Embrane LB)')),
- cfg.StrOpt('inband_id',
- help=_('In band Security Zone id for LBs')),
- cfg.StrOpt('oob_id',
- help=_('Out of band Security Zone id for LBs')),
- cfg.StrOpt('mgmt_id',
- help=_('Management Security Zone id for LBs')),
- cfg.StrOpt('dummy_utif_id',
- help=_('Dummy user traffic Security Zone id for LBs')),
- cfg.StrOpt('resource_pool_id',
- help=_('Shared resource pool id')),
- cfg.StrOpt('lb_flavor', default="small",
- help=_('choose LB image flavor to use, accepted values: small, '
- 'medium')),
- cfg.IntOpt('sync_interval', default=60,
- help=_('resource synchronization interval in seconds')),
- cfg.BoolOpt('async_requests',
- help=_('Define if the requests have '
- 'run asynchronously or not')),
-]
-
-cfg.CONF.register_opts(heleos_opts, 'heleoslb')
+++ /dev/null
-# Copyright 2014 Embrane, Inc.
-# All Rights Reserved.
-#
-# 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 heleosapi import constants as h_con
-from heleosapi import exceptions as h_exc
-
-from neutron.plugins.common import constants as ccon
-
-DELETED = 'DELETED' # not visible status
-QUEUE_TIMEOUT = 300
-BACK_SUB_LIMIT = 6
-
-
-class BackendActions:
- UPDATE = 'update'
- GROW = 'grow'
- REMOVE = 'remove'
- SHRINK = 'shrink'
-
-
-class Events:
- CREATE_VIP = 'create_vip'
- UPDATE_VIP = 'update_vip'
- DELETE_VIP = 'delete_vip'
- UPDATE_POOL = 'update_pool'
- UPDATE_MEMBER = 'update_member'
- ADD_OR_UPDATE_MEMBER = 'add_or_update_member'
- REMOVE_MEMBER = 'remove_member'
- DELETE_MEMBER = 'delete_member'
- POLL_GRAPH = 'poll_graph'
- ADD_POOL_HM = "create_pool_hm"
- UPDATE_POOL_HM = "update_pool_hm"
- DELETE_POOL_HM = "delete_pool_hm"
-
-
-_DVA_PENDING_ERROR_MSG = _('Dva is pending for the following reason: %s')
-_DVA_NOT_FOUNT_ERROR_MSG = _('%s, '
- 'probably was cancelled through the heleos UI')
-_DVA_BROKEN_ERROR_MSG = _('Dva seems to be broken for reason %s')
-_DVA_CREATION_FAILED_ERROR_MSG = _('Dva creation failed reason %s')
-_DVA_CREATION_PENDING_ERROR_MSG = _('Dva creation is in pending state '
- 'for reason %s')
-_CFG_FAILED_ERROR_MSG = _('Dva configuration failed for reason %s')
-_DVA_DEL_FAILED_ERROR_MSG = _('Failed to delete the backend '
- 'load balancer for reason %s. Please remove '
- 'it manually through the heleos UI')
-NO_MEMBER_SUBNET_WARN = _('No subnet is associated to member %s (required '
- 'to identify the proper load balancer port)')
-
-error_map = {h_exc.PendingDva: _DVA_PENDING_ERROR_MSG,
- h_exc.DvaNotFound: _DVA_NOT_FOUNT_ERROR_MSG,
- h_exc.BrokenDva: _DVA_BROKEN_ERROR_MSG,
- h_exc.DvaCreationFailed: _DVA_CREATION_FAILED_ERROR_MSG,
- h_exc.DvaCreationPending: _DVA_CREATION_PENDING_ERROR_MSG,
- h_exc.ConfigurationFailed: _CFG_FAILED_ERROR_MSG,
- h_exc.DvaDeleteFailed: _DVA_DEL_FAILED_ERROR_MSG}
-
-state_map = {h_con.DvaState.POWER_ON: ccon.ACTIVE,
- None: ccon.ERROR,
- DELETED: DELETED}
+++ /dev/null
-# Copyright 2014 Embrane, Inc.
-# All Rights Reserved.
-#
-# 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.db import models_v2 as nmodel
-from neutron.services.loadbalancer.drivers.embrane import models
-
-
-def add_pool_port(context, pool_id, port_id):
- session = context.session
- with session.begin(subtransactions=True):
- pool_port = models.PoolPort()
- pool_port.pool_id = pool_id
- pool_port.port_id = port_id
- session.add(pool_port)
-
-
-def get_pool_port(context, pool_id):
- return (context.session.query(models.PoolPort).filter_by(pool_id=pool_id).
- first())
-
-
-def delete_pool_backend(context, pool_id):
- session = context.session
- backend = (session.query(models.PoolPort).filter_by(
- pool_id=pool_id))
- for b in backend:
- delete_pool_port(context, b)
-
-
-def delete_pool_port(context, backend_port):
- session = context.session
- with session.begin(subtransactions=True):
- port = (session.query(nmodel.Port).filter_by(
- id=backend_port['port_id'])).first()
- if port:
- session.delete(backend_port)
- session.delete(port)
+++ /dev/null
-# Copyright 2014 Embrane, Inc.
-# All Rights Reserved.
-#
-# 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 heleosapi import backend_operations as h_op
-from heleosapi import constants as h_con
-from heleosapi import info as h_info
-from oslo.config import cfg
-
-from neutron.api.v2 import attributes
-from neutron.common import exceptions as n_exc
-from neutron.db.loadbalancer import loadbalancer_db as ldb
-from neutron.extensions import loadbalancer as lb_ext
-from neutron.i18n import _LW
-from neutron.openstack.common import log as logging
-from neutron.plugins.common import constants as pcon
-from neutron.plugins.embrane.common import contexts as embrane_ctx
-from neutron.plugins.embrane.common import exceptions as h_exc
-from neutron.plugins.embrane.common import utils
-from neutron.services.loadbalancer import constants as lbcon
-from neutron.services.loadbalancer.drivers import abstract_driver
-from neutron.services.loadbalancer.drivers.embrane.agent import dispatcher
-from neutron.services.loadbalancer.drivers.embrane import config # noqa
-from neutron.services.loadbalancer.drivers.embrane import constants as econ
-from neutron.services.loadbalancer.drivers.embrane import db as edb
-from neutron.services.loadbalancer.drivers.embrane import poller
-
-LOG = logging.getLogger(__name__)
-conf = cfg.CONF.heleoslb
-confh = {}
-
-try:
- confh = cfg.CONF.heleos
-except cfg.NoSuchOptError:
- pass
-
-
-def get_conf(x):
- try:
- return conf.get(x) or confh.get(x)
- except cfg.NoSuchOptError:
- return
-
-
-class EmbraneLbaas(abstract_driver.LoadBalancerAbstractDriver):
- def __init__(self, plugin):
- config_esm_mgmt = get_conf('esm_mgmt')
- config_admin_username = get_conf('admin_username')
- config_admin_password = get_conf('admin_password')
- config_lb_image_id = get_conf('lb_image')
- config_security_zones = {h_con.SzType.IB: get_conf('inband_id'),
- h_con.SzType.OOB: get_conf('oob_id'),
- h_con.SzType.MGMT: get_conf('mgmt_id'),
- h_con.SzType.DUMMY: get_conf('dummy_utif_id')}
- config_resource_pool = get_conf('resource_pool_id')
- self._heleos_api = h_op.BackendOperations(
- esm_mgmt=config_esm_mgmt,
- admin_username=config_admin_username,
- admin_password=config_admin_password,
- lb_image_id=config_lb_image_id,
- security_zones=config_security_zones,
- resource_pool=config_resource_pool)
- self._dispatcher = dispatcher.Dispatcher(
- self, get_conf("async_requests"))
- self.plugin = plugin
- poll_interval = conf.get('sync_interval')
- if poll_interval > 0:
- self._loop_call = poller.Poller(self)
- self._loop_call.start_polling(conf.get('sync_interval'))
- self._flavor = get_conf('lb_flavor')
-
- def _validate_vip(self, vip):
- if vip.get('connection_limit') and vip['connection_limit'] != -1:
- raise h_exc.UnsupportedException(
- err_msg=_('Connection limit is not supported by Embrane LB'))
- persistence = vip.get('session_persistence')
- if (persistence and persistence.get('type') ==
- lbcon.SESSION_PERSISTENCE_APP_COOKIE):
- p_type = vip['session_persistence']['type']
- raise h_exc.UnsupportedException(
- err_msg=_('Session persistence %s '
- 'not supported by Embrane LBaaS') % p_type)
-
- def _delete_vip(self, context, vip):
- with context.session.begin(subtransactions=True):
- self.plugin._delete_db_vip(context, vip['id'])
- return econ.DELETED
-
- def _delete_member(self, context, member):
- self.plugin._delete_db_member(context, member['id'])
-
- def _delete_pool_hm(self, context, health_monitor, pool_id):
- self.plugin._delete_db_pool_health_monitor(context,
- health_monitor['id'],
- pool_id)
-
- def _update_vip_graph_state(self, context, vip):
- self._heleos_api.update_vip_status(vip)
- self.plugin.update_status(context, ldb.Vip, vip['id'],
- vip['status'])
- if vip['status'] != pcon.ERROR:
- pool = self.plugin.get_pool(context, vip['pool_id'])
- pool_members = pool['members']
- # Manages possible manual changes and monitor actions
- self._heleos_api.update_pool_status(vip['id'], pool)
- self._heleos_api.update_members_status(vip['id'], pool['id'],
- pool_members)
- self.plugin.update_status(context, ldb.Pool, pool['id'],
- pool['status'])
- for member in pool_members:
- self.plugin.update_status(context, ldb.Member,
- member['id'], member['status'])
-
- def _create_backend_port(self, context, db_pool):
- try:
- subnet = self.plugin._core_plugin.get_subnet(context,
- db_pool["subnet_id"])
- except n_exc.SubnetNotFound:
- LOG.warning(_LW("Subnet assigned to pool %s doesn't exist, "
- "backend port can't be created"), db_pool['id'])
- return
-
- fixed_ip = {'subnet_id': subnet['id'],
- 'fixed_ips': attributes.ATTR_NOT_SPECIFIED}
-
- port_data = {
- 'tenant_id': db_pool['tenant_id'],
- 'name': 'pool-' + db_pool['id'],
- 'network_id': subnet['network_id'],
- 'mac_address': attributes.ATTR_NOT_SPECIFIED,
- 'admin_state_up': False,
- 'device_id': '',
- 'device_owner': '',
- 'fixed_ips': [fixed_ip]
- }
-
- port = self.plugin._core_plugin.create_port(context,
- {'port': port_data})
- return edb.add_pool_port(context, db_pool['id'], port['id'])
-
- def _retrieve_utif_info(self, context, neutron_port):
- network = self.plugin._core_plugin.get_network(
- context, neutron_port['network_id'])
- result = h_info.UtifInfo(network.get('provider:segmentation_id'),
- network['name'],
- network['id'],
- False,
- network['tenant_id'],
- neutron_port['id'],
- neutron_port['mac_address'],
- network.get('provider:network_type'))
- return result
-
- def create_vip(self, context, vip):
- self._validate_vip(vip)
- db_vip = self.plugin.populate_vip_graph(context, vip)
- vip_port = self.plugin._core_plugin._get_port(context,
- db_vip['port_id'])
- vip_utif_info = self._retrieve_utif_info(context, vip_port)
- vip_ip_allocation_info = utils.retrieve_ip_allocation_info(
- context, vip_port)
- vip_ip_allocation_info.is_gw = True
- db_pool = pool_utif_info = pool_ip_allocation_info = None
- members = monitors = []
- if db_vip['pool_id']:
- db_pool = self.plugin.get_pool(
- context, db_vip['pool_id'])
- pool_port = edb.get_pool_port(context, db_pool["id"])
- if pool_port:
- db_port = self.plugin._core_plugin._get_port(
- context, pool_port["port_id"])
- pool_utif_info = self._retrieve_utif_info(context, db_port)
- pool_ip_allocation_info = utils.retrieve_ip_allocation_info(
- context, db_port)
- members = self.plugin.get_members(
- context, filters={'id': db_pool['members']})
- monitors = self.plugin.get_members(
- context, filters={'id': db_pool['health_monitors']})
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(econ.Events.CREATE_VIP,
- db_vip, context, None),
- self._flavor, vip_utif_info, vip_ip_allocation_info,
- pool_utif_info, pool_ip_allocation_info, db_pool, members,
- monitors)
-
- def update_vip(self, context, old_vip, vip):
- new_pool = old_port_id = removed_ip = None
- new_pool_utif = new_pool_ip_allocation = None
- old_pool = {}
- members = monitors = []
- if old_vip['pool_id'] != vip['pool_id']:
- new_pool = self.plugin.get_pool(
- context, vip['pool_id'])
- members = self.plugin.get_members(
- context, filters={'id': new_pool['members']})
- monitors = self.plugin.get_members(
- context, filters={'id': new_pool['health_monitors']})
- new_pool_port = edb.get_pool_port(context, new_pool["id"])
- if new_pool_port:
- db_port = self.plugin._core_plugin._get_port(
- context, new_pool_port["port_id"])
- new_pool_utif = self._retrieve_utif_info(context, db_port)
- new_pool_ip_allocation = utils.retrieve_ip_allocation_info(
- context, db_port)
- old_pool = self.plugin.get_pool(
- context, old_vip['pool_id'])
- old_pool_port = edb.get_pool_port(context, old_pool["id"])
- if old_pool_port:
- old_port = self.plugin._core_plugin._get_port(
- context, old_pool_port['port_id'])
- # remove that subnet ip
- removed_ip = old_port['fixed_ips'][0]['ip_address']
- old_port_id = old_port['id']
-
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(econ.Events.UPDATE_VIP, vip,
- context, None),
- old_pool.get('id'), old_port_id, removed_ip, new_pool_utif,
- new_pool_ip_allocation, new_pool, members, monitors)
-
- def delete_vip(self, context, vip):
- db_vip = self.plugin.populate_vip_graph(context, vip)
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.DELETE_VIP, db_vip, context, None))
-
- def create_pool(self, context, pool):
- if pool['subnet_id']:
- self._create_backend_port(context, pool)
-
- def update_pool(self, context, old_pool, pool):
- with context.session.begin(subtransactions=True):
- if old_pool['vip_id']:
- try:
- db_vip = self.plugin._get_resource(
- context, ldb.Vip, old_pool['vip_id'])
- except lb_ext.VipNotFound:
- return
- monitors = self.plugin.get_members(
- context, filters={'id': old_pool['health_monitors']})
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(econ.Events.UPDATE_POOL,
- db_vip, context, None),
- pool, monitors)
-
- def delete_pool(self, context, pool):
- edb.delete_pool_backend(context, pool['id'])
- self.plugin._delete_db_pool(context, pool['id'])
-
- def create_member(self, context, member):
- db_pool = self.plugin.get_pool(context, member['pool_id'])
- if db_pool['vip_id']:
- db_vip = self.plugin._get_resource(context, ldb.Vip,
- db_pool['vip_id'])
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.ADD_OR_UPDATE_MEMBER, db_vip, context, None),
- member, db_pool['protocol'])
-
- def update_member(self, context, old_member, member):
- db_pool = self.plugin.get_pool(context, member['pool_id'])
- if member['pool_id'] != old_member['pool_id']:
- old_pool = self.plugin.get_pool(context, old_member['pool_id'])
- if old_pool['vip_id']:
- db_vip = self.plugin._get_resource(context, ldb.Vip,
- old_pool['vip_id'])
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.REMOVE_MEMBER, db_vip, context, None),
- old_member)
- if db_pool['vip_id']:
- db_vip = self.plugin._get_resource(
- context, ldb.Vip, db_pool['vip_id'])
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.ADD_OR_UPDATE_MEMBER, db_vip, context, None),
- member, db_pool['protocol'])
-
- def delete_member(self, context, member):
- db_pool = self.plugin.get_pool(context, member['pool_id'])
- if db_pool['vip_id']:
- db_vip = self.plugin._get_resource(context, ldb.Vip,
- db_pool['vip_id'])
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.DELETE_MEMBER, db_vip, context, None),
- member)
- else:
- self._delete_member(context, member)
-
- def stats(self, context, pool_id):
- return {'bytes_in': 0,
- 'bytes_out': 0,
- 'active_connections': 0,
- 'total_connections': 0}
-
- def create_pool_health_monitor(self, context, health_monitor, pool_id):
- db_pool = self.plugin.get_pool(context, pool_id)
- # API call only if vip exists
- if db_pool['vip_id']:
- db_vip = self.plugin._get_resource(context, ldb.Vip,
- db_pool['vip_id'])
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.ADD_POOL_HM, db_vip, context, None),
- health_monitor, pool_id)
-
- def update_pool_health_monitor(self, context, old_health_monitor,
- health_monitor, pool_id):
- db_pool = self.plugin.get_pool(context, pool_id)
- if db_pool['vip_id']:
- db_vip = self.plugin._get_resource(context, ldb.Vip,
- db_pool['vip_id'])
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.UPDATE_POOL_HM, db_vip, context, None),
- health_monitor, pool_id)
-
- def delete_pool_health_monitor(self, context, health_monitor, pool_id):
- db_pool = self.plugin.get_pool(context, pool_id)
- if db_pool['vip_id']:
- db_vip = self.plugin._get_resource(context, ldb.Vip,
- db_pool['vip_id'])
- self._dispatcher.dispatch_lb(
- embrane_ctx.DispatcherContext(
- econ.Events.DELETE_POOL_HM, db_vip, context, None),
- health_monitor, pool_id)
- else:
- self._delete_pool_hm(context, health_monitor, pool_id)
+++ /dev/null
-# Copyright 2014 Embrane, Inc.
-# All Rights Reserved.
-#
-# 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 heleosapi import exceptions as h_exc
-
-from neutron import context
-from neutron.db.loadbalancer import loadbalancer_db as ldb
-from neutron.db import servicetype_db as sdb
-from neutron.i18n import _LE
-from neutron.openstack.common import log as logging
-from neutron.openstack.common import loopingcall
-from neutron.plugins.common import constants as ccon
-from neutron.plugins.embrane.common import contexts as embrane_ctx
-from neutron.services.loadbalancer.drivers.embrane import constants as econ
-
-LOG = logging.getLogger(__name__)
-skip_states = [ccon.PENDING_CREATE,
- ccon.PENDING_DELETE,
- ccon.PENDING_UPDATE,
- ccon.ERROR]
-
-
-class Poller(object):
- def __init__(self, driver):
- self.dispatcher = driver._dispatcher
- service_type_manager = sdb.ServiceTypeManager.get_instance()
- self.provider = (service_type_manager.get_service_providers(
- None, filters={
- 'service_type': [ccon.LOADBALANCER],
- 'driver': ['neutron.services.loadbalancer.drivers.'
- 'embrane.driver.EmbraneLbaas']}))[0]['name']
-
- def start_polling(self, interval):
- loop_call = loopingcall.FixedIntervalLoopingCall(self._run)
- loop_call.start(interval=interval)
- return loop_call
-
- def _run(self):
- ctx = context.get_admin_context()
- try:
- self.synchronize_vips(ctx)
- except h_exc.PollingException as e:
- LOG.exception(_LE('Unhandled exception occurred'), e)
-
- def synchronize_vips(self, ctx):
- session = ctx.session
- vips = session.query(ldb.Vip).join(
- sdb.ProviderResourceAssociation,
- sdb.ProviderResourceAssociation.resource_id ==
- ldb.Vip.pool_id).filter(
- sdb.ProviderResourceAssociation.provider_name == self.provider)
- # No need to check pending states
- for vip in vips:
- if vip['status'] not in skip_states:
- self.dispatcher.dispatch_lb(
- d_context=embrane_ctx.DispatcherContext(
- econ.Events.POLL_GRAPH, vip, ctx, None),
- args=())
--- /dev/null
+# Copyright 2014 A10 Networks, Inc
+# All Rights Reserved.
+#
+# 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.i18n import _LE
+from neutron.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+try:
+ from neutron_lbaas.services.loadbalancer import plugin
+except Exception as e:
+ LOG.error(_LE("Loadbalancer service plugin requires neutron-lbaas module"))
+ raise e
+
+
+class LoadBalancerPlugin(plugin.LoadBalancerPlugin):
+ pass
--- /dev/null
+# Copyright 2014 A10 Networks, Inc
+# All Rights Reserved.
+#
+# 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.i18n import _LE
+from neutron.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+try:
+ from neutron_vpnaas.services.vpn import plugin
+except Exception as e:
+ LOG.error(_LE("VPN service plugin requires neutron-vpnaas module"))
+ raise e
+
+
+class VPNDriverPlugin(plugin.VPNDriverPlugin):
+ pass
+++ /dev/null
-# Copyright 2014 Cisco Systems, Inc. All rights reserved.
-#
-# 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.db import exception as db_exc
-import sqlalchemy as sa
-from sqlalchemy.orm import exc as sql_exc
-
-from neutron.common import exceptions
-from neutron.db import model_base
-from neutron.db import models_v2
-from neutron.db.vpn import vpn_db
-from neutron.i18n import _LI
-from neutron.openstack.common import log as logging
-
-LOG = logging.getLogger(__name__)
-
-# Note: Artificially limit these to reduce mapping table size and performance
-# Tunnel can be 0..7FFFFFFF, IKE policy can be 1..10000, IPSec policy can be
-# 1..31 characters long.
-MAX_CSR_TUNNELS = 10000
-MAX_CSR_IKE_POLICIES = 2000
-MAX_CSR_IPSEC_POLICIES = 2000
-
-TUNNEL = 'Tunnel'
-IKE_POLICY = 'IKE Policy'
-IPSEC_POLICY = 'IPSec Policy'
-
-MAPPING_LIMITS = {TUNNEL: (0, MAX_CSR_TUNNELS),
- IKE_POLICY: (1, MAX_CSR_IKE_POLICIES),
- IPSEC_POLICY: (1, MAX_CSR_IPSEC_POLICIES)}
-
-
-class CsrInternalError(exceptions.NeutronException):
- message = _("Fatal - %(reason)s")
-
-
-class IdentifierMap(model_base.BASEV2, models_v2.HasTenant):
-
- """Maps OpenStack IDs to compatible numbers for Cisco CSR."""
-
- __tablename__ = 'cisco_csr_identifier_map'
-
- ipsec_site_conn_id = sa.Column(sa.String(64),
- sa.ForeignKey('ipsec_site_connections.id',
- ondelete="CASCADE"),
- primary_key=True)
- csr_tunnel_id = sa.Column(sa.Integer, nullable=False)
- csr_ike_policy_id = sa.Column(sa.Integer, nullable=False)
- csr_ipsec_policy_id = sa.Column(sa.Integer, nullable=False)
-
-
-def get_next_available_id(session, table_field, id_type):
- """Find first unused id for the specified field in IdentifierMap table.
-
- As entries are removed, find the first "hole" and return that as the
- next available ID. To improve performance, artificially limit
- the number of entries to a smaller range. Currently, these IDs are
- globally unique. Could enhance in the future to be unique per router
- (CSR).
- """
- min_value = MAPPING_LIMITS[id_type][0]
- max_value = MAPPING_LIMITS[id_type][1]
- rows = session.query(table_field).order_by(table_field)
- used_ids = set([row[0] for row in rows])
- all_ids = set(range(min_value, max_value + min_value))
- available_ids = all_ids - used_ids
- if not available_ids:
- msg = _("No available Cisco CSR %(type)s IDs from "
- "%(min)d..%(max)d") % {'type': id_type,
- 'min': min_value,
- 'max': max_value}
- LOG.error(msg)
- raise IndexError(msg)
- return available_ids.pop()
-
-
-def get_next_available_tunnel_id(session):
- """Find first available tunnel ID from 0..MAX_CSR_TUNNELS-1."""
- return get_next_available_id(session, IdentifierMap.csr_tunnel_id,
- TUNNEL)
-
-
-def get_next_available_ike_policy_id(session):
- """Find first available IKE Policy ID from 1..MAX_CSR_IKE_POLICIES."""
- return get_next_available_id(session, IdentifierMap.csr_ike_policy_id,
- IKE_POLICY)
-
-
-def get_next_available_ipsec_policy_id(session):
- """Find first available IPSec Policy ID from 1..MAX_CSR_IKE_POLICIES."""
- return get_next_available_id(session, IdentifierMap.csr_ipsec_policy_id,
- IPSEC_POLICY)
-
-
-def find_conn_with_policy(policy_field, policy_id, conn_id, session):
- """Return ID of another conneciton (if any) that uses same policy ID."""
- qry = session.query(vpn_db.IPsecSiteConnection.id)
- match = qry.filter_request(
- policy_field == policy_id,
- vpn_db.IPsecSiteConnection.id != conn_id).first()
- if match:
- return match[0]
-
-
-def find_connection_using_ike_policy(ike_policy_id, conn_id, session):
- """Return ID of another connection that uses same IKE policy ID."""
- return find_conn_with_policy(vpn_db.IPsecSiteConnection.ikepolicy_id,
- ike_policy_id, conn_id, session)
-
-
-def find_connection_using_ipsec_policy(ipsec_policy_id, conn_id, session):
- """Return ID of another connection that uses same IPSec policy ID."""
- return find_conn_with_policy(vpn_db.IPsecSiteConnection.ipsecpolicy_id,
- ipsec_policy_id, conn_id, session)
-
-
-def lookup_policy(policy_type, policy_field, conn_id, session):
- """Obtain specified policy's mapping from other connection."""
- try:
- return session.query(policy_field).filter_by(
- ipsec_site_conn_id=conn_id).one()[0]
- except sql_exc.NoResultFound:
- msg = _("Database inconsistency between IPSec connection and "
- "Cisco CSR mapping table (%s)") % policy_type
- raise CsrInternalError(reason=msg)
-
-
-def lookup_ike_policy_id_for(conn_id, session):
- """Obtain existing Cisco CSR IKE policy ID from another connection."""
- return lookup_policy(IKE_POLICY, IdentifierMap.csr_ike_policy_id,
- conn_id, session)
-
-
-def lookup_ipsec_policy_id_for(conn_id, session):
- """Obtain existing Cisco CSR IPSec policy ID from another connection."""
- return lookup_policy(IPSEC_POLICY, IdentifierMap.csr_ipsec_policy_id,
- conn_id, session)
-
-
-def determine_csr_policy_id(policy_type, conn_policy_field, map_policy_field,
- policy_id, conn_id, session):
- """Use existing or reserve a new policy ID for Cisco CSR use.
-
- TODO(pcm) FUTURE: Once device driver adds support for IKE/IPSec policy
- ID sharing, add call to find_conn_with_policy() to find used ID and
- then call lookup_policy() to find the current mapping for that ID.
- """
- csr_id = get_next_available_id(session, map_policy_field, policy_type)
- LOG.debug("Reserved new CSR ID %(csr_id)d for %(policy)s "
- "ID %(policy_id)s", {'csr_id': csr_id,
- 'policy': policy_type,
- 'policy_id': policy_id})
- return csr_id
-
-
-def determine_csr_ike_policy_id(ike_policy_id, conn_id, session):
- """Use existing, or reserve a new IKE policy ID for Cisco CSR."""
- return determine_csr_policy_id(IKE_POLICY,
- vpn_db.IPsecSiteConnection.ikepolicy_id,
- IdentifierMap.csr_ike_policy_id,
- ike_policy_id, conn_id, session)
-
-
-def determine_csr_ipsec_policy_id(ipsec_policy_id, conn_id, session):
- """Use existing, or reserve a new IPSec policy ID for Cisco CSR."""
- return determine_csr_policy_id(IPSEC_POLICY,
- vpn_db.IPsecSiteConnection.ipsecpolicy_id,
- IdentifierMap.csr_ipsec_policy_id,
- ipsec_policy_id, conn_id, session)
-
-
-def get_tunnel_mapping_for(conn_id, session):
- try:
- entry = session.query(IdentifierMap).filter_by(
- ipsec_site_conn_id=conn_id).one()
- LOG.debug("Mappings for IPSec connection %(conn)s - "
- "tunnel=%(tunnel)s ike_policy=%(csr_ike)d "
- "ipsec_policy=%(csr_ipsec)d",
- {'conn': conn_id, 'tunnel': entry.csr_tunnel_id,
- 'csr_ike': entry.csr_ike_policy_id,
- 'csr_ipsec': entry.csr_ipsec_policy_id})
- return (entry.csr_tunnel_id, entry.csr_ike_policy_id,
- entry.csr_ipsec_policy_id)
- except sql_exc.NoResultFound:
- msg = _("Existing entry for IPSec connection %s not found in Cisco "
- "CSR mapping table") % conn_id
- raise CsrInternalError(reason=msg)
-
-
-def create_tunnel_mapping(context, conn_info):
- """Create Cisco CSR IDs, using mapping table and OpenStack UUIDs."""
- conn_id = conn_info['id']
- ike_policy_id = conn_info['ikepolicy_id']
- ipsec_policy_id = conn_info['ipsecpolicy_id']
- tenant_id = conn_info['tenant_id']
- with context.session.begin():
- csr_tunnel_id = get_next_available_tunnel_id(context.session)
- csr_ike_id = determine_csr_ike_policy_id(ike_policy_id, conn_id,
- context.session)
- csr_ipsec_id = determine_csr_ipsec_policy_id(ipsec_policy_id, conn_id,
- context.session)
- map_entry = IdentifierMap(tenant_id=tenant_id,
- ipsec_site_conn_id=conn_id,
- csr_tunnel_id=csr_tunnel_id,
- csr_ike_policy_id=csr_ike_id,
- csr_ipsec_policy_id=csr_ipsec_id)
- try:
- context.session.add(map_entry)
- # Force committing to database
- context.session.flush()
- except db_exc.DBDuplicateEntry:
- msg = _("Attempt to create duplicate entry in Cisco CSR "
- "mapping table for connection %s") % conn_id
- raise CsrInternalError(reason=msg)
- LOG.info(_LI("Mapped connection %(conn_id)s to Tunnel%(tunnel_id)d "
- "using IKE policy ID %(ike_id)d and IPSec policy "
- "ID %(ipsec_id)d"),
- {'conn_id': conn_id, 'tunnel_id': csr_tunnel_id,
- 'ike_id': csr_ike_id, 'ipsec_id': csr_ipsec_id})
-
-
-def delete_tunnel_mapping(context, conn_info):
- conn_id = conn_info['id']
- with context.session.begin():
- sess_qry = context.session.query(IdentifierMap)
- sess_qry.filter_by(ipsec_site_conn_id=conn_id).delete()
- LOG.info(_LI("Removed mapping for connection %s"), conn_id)
return insp_def != "'%s'::character varying" % meta_def.arg
def test_models_sync(self):
+ # TODO(dougw) - re-enable, with exclusion list
+ self.skipTest("Temporarily disabled during services split")
+
# drop all tables after a test run
self.addCleanup(self._cleanup)
--- /dev/null
+# Copyright 2012 OpenStack Foundation.
+# All Rights Reserved.
+#
+# 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.tests import base
+
+
+class TestPluginShim(base.BaseTestCase):
+
+ def test_plugin_shim(self):
+ try:
+ from neutron.services.firewall import fwaas_plugin as plugin
+ plugin.FirewallPlugin()
+ except ImportError:
+ pass
--- /dev/null
+# Copyright 2012 OpenStack Foundation.
+# All Rights Reserved.
+#
+# 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.tests import base
+
+
+class TestPluginShim(base.BaseTestCase):
+
+ def test_plugin_shim(self):
+ try:
+ from neutron.services.loadbalancer import plugin
+ plugin.LoadBalancerPlugin()
+ except ImportError:
+ pass
--- /dev/null
+# Copyright 2012 OpenStack Foundation.
+# All Rights Reserved.
+#
+# 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.tests import base
+
+
+class TestPluginShim(base.BaseTestCase):
+
+ def test_plugin_shim(self):
+ try:
+ from neutron.services.vpn import plugin
+ plugin.VPNDriverPlugin()
+ except ImportError:
+ pass
+++ /dev/null
-# Copyright 2013 VMware, Inc. All Rights Reserved.
-#
-# 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
-import webob.exc as webexc
-
-import neutron
-from neutron.api import extensions
-from neutron.api.v2 import attributes
-from neutron.api.v2 import router
-from neutron.common import config
-from neutron import context as q_context
-from neutron.db import db_base_plugin_v2
-from neutron.db import l3_db
-from neutron.db.loadbalancer import loadbalancer_db as lb_db
-from neutron.db import routedserviceinsertion_db as rsi_db
-from neutron.db import routerservicetype_db as rst_db
-from neutron.db import servicetype_db as st_db
-from neutron.extensions import routedserviceinsertion as rsi
-from neutron.extensions import routerservicetype as rst
-from neutron.plugins.common import constants
-from neutron.tests.unit import test_api_v2
-from neutron.tests.unit import testlib_api
-from neutron.tests.unit import testlib_plugin
-from neutron import wsgi
-
-_uuid = test_api_v2._uuid
-_get_path = test_api_v2._get_path
-extensions_path = ':'.join(neutron.extensions.__path__)
-
-
-class RouterServiceInsertionTestPlugin(
- rst_db.RouterServiceTypeDbMixin,
- rsi_db.RoutedServiceInsertionDbMixin,
- st_db.ServiceTypeManager,
- lb_db.LoadBalancerPluginDb,
- l3_db.L3_NAT_db_mixin,
- db_base_plugin_v2.NeutronDbPluginV2):
-
- supported_extension_aliases = [
- "router", "router-service-type", "routed-service-insertion",
- "service-type", "lbaas"
- ]
-
- def create_router(self, context, router):
- with context.session.begin(subtransactions=True):
- r = super(RouterServiceInsertionTestPlugin, self).create_router(
- context, router)
- service_type_id = router['router'].get(rst.SERVICE_TYPE_ID)
- if service_type_id is not None:
- r[rst.SERVICE_TYPE_ID] = service_type_id
- self._process_create_router_service_type_id(
- context, r)
- return r
-
- def get_router(self, context, id, fields=None):
- with context.session.begin(subtransactions=True):
- r = super(RouterServiceInsertionTestPlugin, self).get_router(
- context, id, fields)
- rsbind = self._get_router_service_type_id_binding(context, id)
- if rsbind:
- r[rst.SERVICE_TYPE_ID] = rsbind['service_type_id']
- return r
-
- def delete_router(self, context, id):
- with context.session.begin(subtransactions=True):
- super(RouterServiceInsertionTestPlugin, self).delete_router(
- context, id)
- rsbind = self._get_router_service_type_id_binding(context, id)
- if rsbind:
- raise Exception('Router service-type binding is not deleted')
-
- def create_resource(self, res, context, resource, model):
- with context.session.begin(subtransactions=True):
- method_name = "create_{0}".format(res)
- method = getattr(super(RouterServiceInsertionTestPlugin, self),
- method_name)
- o = method(context, resource)
- router_id = resource[res].get(rsi.ROUTER_ID)
- if router_id is not None:
- o[rsi.ROUTER_ID] = router_id
- self._process_create_resource_router_id(
- context, o, model)
- return o
-
- def get_resource(self, res, context, id, fields, model):
- method_name = "get_{0}".format(res)
- method = getattr(super(RouterServiceInsertionTestPlugin, self),
- method_name)
- o = method(context, id, fields)
- if fields is None or rsi.ROUTER_ID in fields:
- rsbind = self._get_resource_router_id_binding(
- context, model, id)
- if rsbind:
- o[rsi.ROUTER_ID] = rsbind['router_id']
- return o
-
- def delete_resource(self, res, context, id, model):
- method_name = "delete_{0}".format(res)
- with context.session.begin(subtransactions=True):
- method = getattr(super(RouterServiceInsertionTestPlugin, self),
- method_name)
- method(context, id)
- self._delete_resource_router_id_binding(context, id, model)
- if self._get_resource_router_id_binding(context, model, id):
- raise Exception("{0}-router binding is not deleted".format(res))
-
- def create_pool(self, context, pool):
- return self.create_resource('pool', context, pool, lb_db.Pool)
-
- def get_pool(self, context, id, fields=None):
- return self.get_resource('pool', context, id, fields, lb_db.Pool)
-
- def delete_pool(self, context, id):
- return self.delete_resource('pool', context, id, lb_db.Pool)
-
- def create_health_monitor(self, context, health_monitor):
- return self.create_resource('health_monitor', context, health_monitor,
- lb_db.HealthMonitor)
-
- def get_health_monitor(self, context, id, fields=None):
- return self.get_resource('health_monitor', context, id, fields,
- lb_db.HealthMonitor)
-
- def delete_health_monitor(self, context, id):
- return self.delete_resource('health_monitor', context, id,
- lb_db.HealthMonitor)
-
- def create_vip(self, context, vip):
- return self.create_resource('vip', context, vip, lb_db.Vip)
-
- def get_vip(self, context, id, fields=None):
- return self.get_resource(
- 'vip', context, id, fields, lb_db.Vip)
-
- def delete_vip(self, context, id):
- return self.delete_resource('vip', context, id, lb_db.Vip)
-
- def stats(self, context, pool_id):
- pass
-
-
-class RouterServiceInsertionTestCase(testlib_api.SqlTestCase,
- testlib_plugin.PluginSetupHelper):
- def setUp(self):
- super(RouterServiceInsertionTestCase, self).setUp()
- plugin = (
- "neutron.tests.unit.test_routerserviceinsertion."
- "RouterServiceInsertionTestPlugin"
- )
-
- # point config file to: neutron/tests/etc/neutron.conf.test
- self.config_parse()
-
- #just stubbing core plugin with LoadBalancer plugin
- self.setup_coreplugin(plugin)
- cfg.CONF.set_override('service_plugins', [])
- cfg.CONF.set_override('quota_router', -1, group='QUOTAS')
-
- # Ensure existing ExtensionManager is not used
-
- ext_mgr = extensions.PluginAwareExtensionManager(
- extensions_path,
- {constants.LOADBALANCER: RouterServiceInsertionTestPlugin()}
- )
- extensions.PluginAwareExtensionManager._instance = ext_mgr
- router.APIRouter()
-
- app = config.load_paste_app('extensions_test_app')
- self._api = extensions.ExtensionMiddleware(app, ext_mgr=ext_mgr)
-
- self._tenant_id = "8c70909f-b081-452d-872b-df48e6c355d1"
-
- self._service_type_id = _uuid()
-
- self._setup_core_resources()
-
- # FIXME (markmcclain): The test setup makes it difficult to add core
- # via the api. In the interim we'll create directly using the plugin with
- # the side effect of polluting the fixture database until tearDown.
-
- def tearDown(self):
- self.api = None
- super(RouterServiceInsertionTestCase, self).tearDown()
-
- def _setup_core_resources(self):
- core_plugin = neutron.manager.NeutronManager.get_plugin()
-
- self._network = core_plugin.create_network(
- q_context.get_admin_context(),
- {
- 'network':
- {
- 'tenant_id': self._tenant_id,
- 'name': 'test net',
- 'admin_state_up': True,
- 'shared': False,
- }
- }
- )
-
- self._subnet = core_plugin.create_subnet(
- q_context.get_admin_context(),
- {
- 'subnet':
- {
- 'network_id': self._network['id'],
- 'name': 'test subnet',
- 'cidr': '192.168.1.0/24',
- 'ip_version': 4,
- 'gateway_ip': '192.168.1.1',
- 'allocation_pools': attributes.ATTR_NOT_SPECIFIED,
- 'dns_nameservers': attributes.ATTR_NOT_SPECIFIED,
- 'host_routes': attributes.ATTR_NOT_SPECIFIED,
- 'enable_dhcp': True,
- }
- }
- )
-
- self._subnet_id = self._subnet['id']
-
- def _do_request(self, method, path, data=None, params=None, action=None):
- content_type = 'application/json'
- body = None
- if data is not None: # empty dict is valid
- body = wsgi.Serializer().serialize(data, content_type)
-
- req = testlib_api.create_request(
- path, body, content_type,
- method, query_string=params)
- res = req.get_response(self._api)
- if res.status_code >= 400:
- raise webexc.HTTPClientError(detail=res.body, code=res.status_code)
- if res.status_code != webexc.HTTPNoContent.code:
- return res.json
-
- def _router_create(self, service_type_id=None):
- data = {
- "router": {
- "tenant_id": self._tenant_id,
- "name": "test",
- "admin_state_up": True,
- "service_type_id": service_type_id,
- }
- }
-
- res = self._do_request('POST', _get_path('routers'), data)
- return res['router']
-
- def test_router_create_no_service_type_id(self):
- router = self._router_create()
- self.assertIsNone(router.get('service_type_id'))
-
- def test_router_create_with_service_type_id(self):
- router = self._router_create(self._service_type_id)
- self.assertEqual(router['service_type_id'], self._service_type_id)
-
- def test_router_get(self):
- router = self._router_create(self._service_type_id)
- res = self._do_request('GET',
- _get_path('routers/{0}'.format(router['id'])))
- self.assertEqual(res['router']['service_type_id'],
- self._service_type_id)
-
- def _test_router_update(self, update_service_type_id):
- router = self._router_create(self._service_type_id)
- router_id = router['id']
- new_name = _uuid()
- data = {
- "router": {
- "name": new_name,
- "admin_state_up": router['admin_state_up'],
- }
- }
- if update_service_type_id:
- data["router"]["service_type_id"] = _uuid()
- with testlib_api.ExpectedException(
- webexc.HTTPClientError) as ctx_manager:
- res = self._do_request(
- 'PUT', _get_path('routers/{0}'.format(router_id)), data)
- self.assertEqual(ctx_manager.exception.code, 400)
- else:
- res = self._do_request(
- 'PUT', _get_path('routers/{0}'.format(router_id)), data)
- res = self._do_request(
- 'GET', _get_path('routers/{0}'.format(router['id'])))
- self.assertEqual(res['router']['name'], new_name)
-
- def test_router_update_with_service_type_id(self):
- self._test_router_update(True)
-
- def test_router_update_without_service_type_id(self):
- self._test_router_update(False)
-
- def test_router_delete(self):
- router = self._router_create(self._service_type_id)
- self._do_request(
- 'DELETE', _get_path('routers/{0}'.format(router['id'])))
-
- def _test_lb_setup(self):
- router = self._router_create(self._service_type_id)
- self._router_id = router['id']
-
- def _test_pool_setup(self):
- self._test_lb_setup()
-
- def _test_health_monitor_setup(self):
- self._test_lb_setup()
-
- def _test_vip_setup(self):
- self._test_pool_setup()
- pool = self._pool_create(self._router_id)
- self._pool_id = pool['id']
-
- def _create_resource(self, res, data):
- resp = self._do_request('POST', _get_path('lb/{0}s'.format(res)), data)
- return resp[res]
-
- def _pool_create(self, router_id=None):
- data = {
- "pool": {
- "tenant_id": self._tenant_id,
- "name": "test",
- "protocol": "HTTP",
- "subnet_id": self._subnet_id,
- "lb_method": "ROUND_ROBIN",
- "router_id": router_id
- }
- }
-
- return self._create_resource('pool', data)
-
- def _pool_update_attrs(self, pool):
- uattr = {}
- fields = [
- 'name', 'description', 'lb_method',
- 'health_monitors', 'admin_state_up'
- ]
- for field in fields:
- uattr[field] = pool[field]
- return uattr
-
- def _health_monitor_create(self, router_id=None):
- data = {
- "health_monitor": {
- "tenant_id": self._tenant_id,
- "type": "HTTP",
- "delay": 1,
- "timeout": 1,
- "max_retries": 1,
- "router_id": router_id
- }
- }
-
- return self._create_resource('health_monitor', data)
-
- def _health_monitor_update_attrs(self, hm):
- uattr = {}
- fields = ['delay', 'timeout', 'max_retries']
- for field in fields:
- uattr[field] = hm[field]
- return uattr
-
- def _vip_create(self, router_id=None):
- data = {
- "vip": {
- "tenant_id": self._tenant_id,
- "name": "test",
- "protocol": "HTTP",
- "protocol_port": 80,
- "subnet_id": self._subnet_id,
- "pool_id": self._pool_id,
- "address": "192.168.1.102",
- "connection_limit": 100,
- "admin_state_up": True,
- "router_id": router_id
- }
- }
-
- return self._create_resource('vip', data)
-
- def _vip_update_attrs(self, vip):
- uattr = {}
- fields = [
- 'name', 'description', 'pool_id', 'connection_limit',
- 'admin_state_up'
- ]
- for field in fields:
- uattr[field] = vip[field]
- return uattr
-
- def _test_resource_create(self, res):
- getattr(self, "_test_{0}_setup".format(res))()
- obj = getattr(self, "_{0}_create".format(res))(self._router_id)
- self.assertEqual(obj['router_id'], self._router_id)
-
- def _test_resource_update(self, res, update_router_id,
- update_attr, update_value):
- getattr(self, "_test_{0}_setup".format(res))()
- obj = getattr(self, "_{0}_create".format(res))(self._router_id)
- uattrs = getattr(self, "_{0}_update_attrs".format(res))(obj)
- uattrs[update_attr] = update_value
- data = {res: uattrs}
- if update_router_id:
- uattrs['router_id'] = self._router_id
- with testlib_api.ExpectedException(
- webexc.HTTPClientError) as ctx_manager:
- self._do_request(
- 'PUT',
- _get_path('lb/{0}s/{1}'.format(res, obj['id'])), data)
- self.assertEqual(ctx_manager.exception.code, 400)
- else:
- self._do_request(
- 'PUT',
- _get_path('lb/{0}s/{1}'.format(res, obj['id'])), data)
- updated = self._do_request(
- 'GET',
- _get_path('lb/{0}s/{1}'.format(res, obj['id'])))
- self.assertEqual(updated[res][update_attr], update_value)
-
- def _test_resource_delete(self, res, with_router_id):
- getattr(self, "_test_{0}_setup".format(res))()
-
- func = getattr(self, "_{0}_create".format(res))
-
- if with_router_id:
- obj = func(self._router_id)
- else:
- obj = func()
- self._do_request(
- 'DELETE', _get_path('lb/{0}s/{1}'.format(res, obj['id'])))
-
- def test_pool_create(self):
- self._test_resource_create('pool')
-
- def test_pool_update_with_router_id(self):
- self._test_resource_update('pool', True, 'name', _uuid())
-
- def test_pool_update_without_router_id(self):
- self._test_resource_update('pool', False, 'name', _uuid())
-
- def test_pool_delete_with_router_id(self):
- self._test_resource_delete('pool', True)
-
- def test_pool_delete_without_router_id(self):
- self._test_resource_delete('pool', False)
-
- def test_health_monitor_create(self):
- self._test_resource_create('health_monitor')
-
- def test_health_monitor_update_with_router_id(self):
- self._test_resource_update('health_monitor', True, 'timeout', 2)
-
- def test_health_monitor_update_without_router_id(self):
- self._test_resource_update('health_monitor', False, 'timeout', 2)
-
- def test_health_monitor_delete_with_router_id(self):
- self._test_resource_delete('health_monitor', True)
-
- def test_health_monitor_delete_without_router_id(self):
- self._test_resource_delete('health_monitor', False)
-
- def test_vip_create(self):
- self._test_resource_create('vip')
-
- def test_vip_update_with_router_id(self):
- self._test_resource_update('vip', True, 'name', _uuid())
-
- def test_vip_update_without_router_id(self):
- self._test_resource_update('vip', False, 'name', _uuid())
-
- def test_vip_delete_with_router_id(self):
- self._test_resource_delete('vip', True)
-
- def test_vip_delete_without_router_id(self):
- self._test_resource_delete('vip', False)
from neutron.plugins.vmware.dbexts import vcns_db
from neutron.plugins.vmware.vshield.common import exceptions as vcns_exc
from neutron.plugins.vmware.vshield import vcns_driver
-from neutron.services.loadbalancer import constants as lb_constants
-from neutron.tests.unit.db.loadbalancer import test_db_loadbalancer
from neutron.tests.unit import vmware
from neutron.tests.unit.vmware.vshield import fake_vcns
+from neutron_lbaas.services.loadbalancer import constants as lb_constants
+from neutron_lbaas.tests.unit.db.loadbalancer import test_db_loadbalancer
_uuid = uuidutils.generate_uuid
ignore = E125,E126,E128,E129,E265,H305,H307,H402,H404,H405,H904
show-source = true
builtins = _
-exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,.ropeproject,rally-scenarios
+# TODO(dougw) neutron/tests/unit/vmware exclusion is a temporary services split hack
+exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,.ropeproject,rally-scenarios,neutron/tests/unit/vmware*
[testenv:pylint]
deps =