Merge "Implements a plugable backend driver"
This commit is contained in:
commit
9346ced4b0
@ -43,6 +43,9 @@ function configure_fwaas_v1() {
|
|||||||
function configure_fwaas_v2() {
|
function configure_fwaas_v2() {
|
||||||
# Add conf file
|
# Add conf file
|
||||||
cp $NEUTRON_FWAAS_DIR/etc/neutron_fwaas.conf.sample $NEUTRON_FWAAS_CONF
|
cp $NEUTRON_FWAAS_DIR/etc/neutron_fwaas.conf.sample $NEUTRON_FWAAS_CONF
|
||||||
|
inicomment $NEUTRON_FWAAS_CONF service_providers service_provider
|
||||||
|
iniadd $NEUTRON_FWAAS_CONF service_providers service_provider $NEUTRON_FWAAS_SERVICE_PROVIDERV2
|
||||||
|
|
||||||
neutron_fwaas_configure_driver fwaas_v2
|
neutron_fwaas_configure_driver fwaas_v2
|
||||||
iniset_multiline $Q_L3_CONF_FILE fwaas agent_version v2
|
iniset_multiline $Q_L3_CONF_FILE fwaas agent_version v2
|
||||||
iniset_multiline $Q_L3_CONF_FILE fwaas driver $FWAAS_DRIVER_V2
|
iniset_multiline $Q_L3_CONF_FILE fwaas driver $FWAAS_DRIVER_V2
|
||||||
|
@ -8,4 +8,5 @@ NEUTRON_FWAAS_DIR=$DEST/neutron-fwaas
|
|||||||
NEUTRON_FWAAS_CONF_FILE=neutron_fwaas.conf
|
NEUTRON_FWAAS_CONF_FILE=neutron_fwaas.conf
|
||||||
|
|
||||||
NEUTRON_FWAAS_CONF=$NEUTRON_CONF_DIR/$NEUTRON_FWAAS_CONF_FILE
|
NEUTRON_FWAAS_CONF=$NEUTRON_CONF_DIR/$NEUTRON_FWAAS_CONF_FILE
|
||||||
neutron_server_config_add $NEUTRON_FWAAS_CONF
|
|
||||||
|
NEUTRON_FWAAS_SERVICE_PROVIDERV2=${NEUTRON_FWAAS_SERVICE_PROVIDERV2:-FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default}
|
||||||
|
@ -16,16 +16,16 @@
|
|||||||
import copy
|
import copy
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
|
from neutron.db import _model_query as model_query
|
||||||
from neutron.db import api as db_api
|
from neutron.db import api as db_api
|
||||||
from neutron.db import common_db_mixin as base_db
|
from neutron.db import common_db_mixin
|
||||||
from neutron_lib.api.definitions import constants as fw_const
|
from neutron_lib.api.definitions import constants as fw_const
|
||||||
from neutron_lib.api import validators
|
|
||||||
from neutron_lib import constants as nl_constants
|
from neutron_lib import constants as nl_constants
|
||||||
from neutron_lib.db import constants as db_constants
|
from neutron_lib.db import constants as db_constants
|
||||||
from neutron_lib.db import model_base
|
from neutron_lib.db import model_base
|
||||||
from neutron_lib import exceptions
|
from neutron_lib import exceptions
|
||||||
from neutron_lib.exceptions import firewall_v2 as f_exc
|
from neutron_lib.exceptions import firewall_v2 as f_exc
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_db import exception as db_exc
|
from oslo_db import exception as db_exc
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
@ -36,7 +36,6 @@ from sqlalchemy import orm
|
|||||||
from sqlalchemy.orm import exc
|
from sqlalchemy.orm import exc
|
||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants as const
|
from neutron_fwaas.common import fwaas_constants as const
|
||||||
from neutron_fwaas.extensions import firewall_v2 as fw_ext
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -86,7 +85,7 @@ class FirewallRuleV2(model_base.BASEV2, model_base.HasId, HasName,
|
|||||||
class FirewallGroup(model_base.BASEV2, model_base.HasId, HasName,
|
class FirewallGroup(model_base.BASEV2, model_base.HasId, HasName,
|
||||||
HasDescription, model_base.HasProject):
|
HasDescription, model_base.HasProject):
|
||||||
__tablename__ = 'firewall_groups_v2'
|
__tablename__ = 'firewall_groups_v2'
|
||||||
ports = orm.relationship(
|
port_associations = orm.relationship(
|
||||||
'FirewallGroupPortAssociation',
|
'FirewallGroupPortAssociation',
|
||||||
backref=orm.backref('firewall_group_port_associations_v2',
|
backref=orm.backref('firewall_group_port_associations_v2',
|
||||||
cascade='all, delete'))
|
cascade='all, delete'))
|
||||||
@ -162,7 +161,42 @@ class FirewallPolicy(model_base.BASEV2, model_base.HasId, HasName,
|
|||||||
shared = sa.Column(sa.Boolean)
|
shared = sa.Column(sa.Boolean)
|
||||||
|
|
||||||
|
|
||||||
class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
def _list_firewall_groups_result_filter_hook(query, filters):
|
||||||
|
values = filters and filters.get('ports', [])
|
||||||
|
if values:
|
||||||
|
query = query.join(FirewallGroupPortAssociation)
|
||||||
|
query = query.filter(FirewallGroupPortAssociation.port_id.in_(values))
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
def _list_firewall_policies_result_filter_hook(query, filters):
|
||||||
|
values = filters and filters.get('firewall_rules', [])
|
||||||
|
if values:
|
||||||
|
query = query.join(FirewallPolicyRuleAssociation)
|
||||||
|
query = query.filter(
|
||||||
|
FirewallPolicyRuleAssociation.firewall_rule_id.in_(values))
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
class FirewallPluginDb(common_db_mixin.CommonDbMixin):
|
||||||
|
|
||||||
|
def __new__(cls, *args, **kwargs):
|
||||||
|
model_query.register_hook(
|
||||||
|
FirewallGroup,
|
||||||
|
"firewall_group_v2_filter_by_port_association",
|
||||||
|
query_hook=None,
|
||||||
|
filter_hook=None,
|
||||||
|
result_filters=_list_firewall_groups_result_filter_hook)
|
||||||
|
|
||||||
|
model_query.register_hook(
|
||||||
|
FirewallPolicy,
|
||||||
|
"firewall_policy_v2_filter_by_firewall_rule_association",
|
||||||
|
query_hook=None,
|
||||||
|
filter_hook=None,
|
||||||
|
result_filters=_list_firewall_policies_result_filter_hook)
|
||||||
|
return super(FirewallPluginDb, cls).__new__(cls, *args, **kwargs)
|
||||||
|
|
||||||
def _get_firewall_group(self, context, id):
|
def _get_firewall_group(self, context, id):
|
||||||
try:
|
try:
|
||||||
@ -267,22 +301,21 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
'shared': firewall_policy['shared']}
|
'shared': firewall_policy['shared']}
|
||||||
return self._fields(res, fields)
|
return self._fields(res, fields)
|
||||||
|
|
||||||
def _make_firewall_group_dict(self, firewall_group, fields=None):
|
def _make_firewall_group_dict(self, firewall_group_db, fields=None):
|
||||||
fwg_ports = [
|
fwg_ports = [port_assoc.port_id for port_assoc in
|
||||||
port_assoc.port_id for port_assoc in firewall_group['ports']
|
firewall_group_db.port_associations]
|
||||||
]
|
res = {'id': firewall_group_db['id'],
|
||||||
res = {'id': firewall_group['id'],
|
'tenant_id': firewall_group_db['tenant_id'],
|
||||||
'tenant_id': firewall_group['tenant_id'],
|
'name': firewall_group_db['name'],
|
||||||
'name': firewall_group['name'],
|
'description': firewall_group_db['description'],
|
||||||
'description': firewall_group['description'],
|
|
||||||
'ingress_firewall_policy_id':
|
'ingress_firewall_policy_id':
|
||||||
firewall_group['ingress_firewall_policy_id'],
|
firewall_group_db['ingress_firewall_policy_id'],
|
||||||
'egress_firewall_policy_id':
|
'egress_firewall_policy_id':
|
||||||
firewall_group['egress_firewall_policy_id'],
|
firewall_group_db['egress_firewall_policy_id'],
|
||||||
'admin_state_up': firewall_group['admin_state_up'],
|
'admin_state_up': firewall_group_db['admin_state_up'],
|
||||||
'ports': fwg_ports,
|
'ports': fwg_ports,
|
||||||
'status': firewall_group['status'],
|
'status': firewall_group_db['status'],
|
||||||
'shared': firewall_group['shared']}
|
'shared': firewall_group_db['shared']}
|
||||||
return self._fields(res, fields)
|
return self._fields(res, fields)
|
||||||
|
|
||||||
def _get_policy_ordered_rules(self, context, policy_id):
|
def _get_policy_ordered_rules(self, context, policy_id):
|
||||||
@ -292,7 +325,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
.order_by(FirewallPolicyRuleAssociation.position))
|
.order_by(FirewallPolicyRuleAssociation.position))
|
||||||
return [self._make_firewall_rule_dict(rule) for rule in query]
|
return [self._make_firewall_rule_dict(rule) for rule in query]
|
||||||
|
|
||||||
def _make_firewall_group_dict_with_rules(self, context, firewall_group_id):
|
def make_firewall_group_dict_with_rules(self, context, firewall_group_id):
|
||||||
firewall_group = self.get_firewall_group(context, firewall_group_id)
|
firewall_group = self.get_firewall_group(context, firewall_group_id)
|
||||||
ingress_policy_id = firewall_group['ingress_firewall_policy_id']
|
ingress_policy_id = firewall_group['ingress_firewall_policy_id']
|
||||||
if ingress_policy_id:
|
if ingress_policy_id:
|
||||||
@ -359,7 +392,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
def _get_policy_rule_association(self, context, firewall_policy_id,
|
def _get_policy_rule_association(self, context, firewall_policy_id,
|
||||||
firewall_rule_id):
|
firewall_rule_id):
|
||||||
"""Returns the association between a firewall rule and a firewall
|
"""Returns the association between a firewall rule and a firewall
|
||||||
policy. Throws an exception if the assocaition does not exist.
|
policy. Throws an exception if the assocition does not exist.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self._get_policy_rule_association_query(
|
return self._get_policy_rule_association_query(
|
||||||
@ -374,7 +407,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
# configuration file makes sense. Can be done some time later
|
# configuration file makes sense. Can be done some time later
|
||||||
|
|
||||||
# 1. Drop any IPv4 packets for ingress traffic
|
# 1. Drop any IPv4 packets for ingress traffic
|
||||||
in_fwr_v4 = {'firewall_rule': {
|
in_fwr_v4 = {
|
||||||
'description': 'default ingress rule for IPv4',
|
'description': 'default ingress rule for IPv4',
|
||||||
'name': 'default ingress ipv4 (deny all)',
|
'name': 'default ingress ipv4 (deny all)',
|
||||||
'shared': False,
|
'shared': False,
|
||||||
@ -387,28 +420,25 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
'source_ip_address': None,
|
'source_ip_address': None,
|
||||||
'destination_port': None,
|
'destination_port': None,
|
||||||
'destination_ip_address': None,
|
'destination_ip_address': None,
|
||||||
}}
|
}
|
||||||
|
|
||||||
# 2. Drop any IPv6 packets for ingress traffic
|
# 2. Drop any IPv6 packets for ingress traffic
|
||||||
in_fwr_v6 = copy.deepcopy(in_fwr_v4)
|
in_fwr_v6 = copy.deepcopy(in_fwr_v4)
|
||||||
in_fwr_v6[
|
in_fwr_v6['description'] = 'default ingress rule for IPv6'
|
||||||
'firewall_rule']['description'] = 'default ingress rule for IPv6'
|
in_fwr_v6['name'] = 'default ingress ipv6 (deny all)'
|
||||||
in_fwr_v6['firewall_rule']['name'] = 'default ingress ipv6 (deny all)'
|
in_fwr_v6['ip_version'] = nl_constants.IP_VERSION_6
|
||||||
in_fwr_v6['firewall_rule']['ip_version'] = nl_constants.IP_VERSION_6
|
|
||||||
|
|
||||||
# 3. Allow any IPv4 packets for egress traffic
|
# 3. Allow any IPv4 packets for egress traffic
|
||||||
eg_fwr_v4 = copy.deepcopy(in_fwr_v4)
|
eg_fwr_v4 = copy.deepcopy(in_fwr_v4)
|
||||||
eg_fwr_v4[
|
eg_fwr_v4['description'] = 'default egress rule for IPv4'
|
||||||
'firewall_rule']['description'] = 'default egress rule for IPv4'
|
eg_fwr_v4['action'] = fw_const.FWAAS_ALLOW
|
||||||
eg_fwr_v4['firewall_rule']['action'] = fw_const.FWAAS_ALLOW
|
eg_fwr_v4['name'] = 'default egress ipv4 (allow all)'
|
||||||
eg_fwr_v4['firewall_rule']['name'] = 'default egress ipv4 (allow all)'
|
|
||||||
|
|
||||||
# 4. Allow any IPv6 packets for egress traffic
|
# 4. Allow any IPv6 packets for egress traffic
|
||||||
eg_fwr_v6 = copy.deepcopy(in_fwr_v6)
|
eg_fwr_v6 = copy.deepcopy(in_fwr_v6)
|
||||||
eg_fwr_v6[
|
eg_fwr_v6['description'] = 'default egress rule for IPv6'
|
||||||
'firewall_rule']['description'] = 'default egress rule for IPv6'
|
eg_fwr_v6['name'] = 'default egress ipv6 (allow all)'
|
||||||
eg_fwr_v6['firewall_rule']['name'] = 'default egress ipv6 (allow all)'
|
eg_fwr_v6['action'] = fw_const.FWAAS_ALLOW
|
||||||
eg_fwr_v6['firewall_rule']['action'] = fw_const.FWAAS_ALLOW
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'in_ipv4': self.create_firewall_rule(context, in_fwr_v4)['id'],
|
'in_ipv4': self.create_firewall_rule(context, in_fwr_v4)['id'],
|
||||||
@ -418,8 +448,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def create_firewall_rule(self, context, firewall_rule):
|
def create_firewall_rule(self, context, firewall_rule):
|
||||||
LOG.debug("create_firewall_rule() called")
|
fwr = firewall_rule
|
||||||
fwr = firewall_rule['firewall_rule']
|
|
||||||
self._validate_fwr_protocol_parameters(fwr)
|
self._validate_fwr_protocol_parameters(fwr)
|
||||||
self._validate_fwr_src_dst_ip_version(fwr)
|
self._validate_fwr_src_dst_ip_version(fwr)
|
||||||
if not fwr['protocol'] and (fwr['source_port'] or
|
if not fwr['protocol'] and (fwr['source_port'] or
|
||||||
@ -450,8 +479,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
return self._make_firewall_rule_dict(fwr_db)
|
return self._make_firewall_rule_dict(fwr_db)
|
||||||
|
|
||||||
def update_firewall_rule(self, context, id, firewall_rule):
|
def update_firewall_rule(self, context, id, firewall_rule):
|
||||||
LOG.debug("update_firewall_rule() called")
|
fwr = firewall_rule
|
||||||
fwr = firewall_rule['firewall_rule']
|
|
||||||
fwr_db = self._get_firewall_rule(context, id)
|
fwr_db = self._get_firewall_rule(context, id)
|
||||||
self._validate_fwr_protocol_parameters(fwr, fwr_db=fwr_db)
|
self._validate_fwr_protocol_parameters(fwr, fwr_db=fwr_db)
|
||||||
self._validate_fwr_src_dst_ip_version(fwr, fwr_db=fwr_db)
|
self._validate_fwr_src_dst_ip_version(fwr, fwr_db=fwr_db)
|
||||||
@ -478,24 +506,21 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
raise f_exc.FirewallRuleWithPortWithoutProtocolInvalid()
|
raise f_exc.FirewallRuleWithPortWithoutProtocolInvalid()
|
||||||
fwr_db.update(fwr)
|
fwr_db.update(fwr)
|
||||||
# if the rule on a policy, fix audited flag
|
# if the rule on a policy, fix audited flag
|
||||||
fwp_ids = self._get_policies_with_rule(context, id)
|
fwp_ids = self.get_policies_with_rule(context, id)
|
||||||
for fwp_id in fwp_ids:
|
for fwp_id in fwp_ids:
|
||||||
fwp_db = self._get_firewall_policy(context, fwp_id)
|
fwp_db = self._get_firewall_policy(context, fwp_id)
|
||||||
fwp_db['audited'] = False
|
fwp_db['audited'] = False
|
||||||
return self._make_firewall_rule_dict(fwr_db)
|
return self._make_firewall_rule_dict(fwr_db)
|
||||||
|
|
||||||
def delete_firewall_rule(self, context, id):
|
def delete_firewall_rule(self, context, id):
|
||||||
LOG.debug("delete_firewall_rule() called")
|
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fwr = self._get_firewall_rule(context, id)
|
fwr = self._get_firewall_rule(context, id)
|
||||||
# make sure rule is not associated with any policy
|
# make sure rule is not associated with any policy
|
||||||
if self._get_policies_with_rule(context, id):
|
if self.get_policies_with_rule(context, id):
|
||||||
raise f_exc.FirewallRuleInUse(firewall_rule_id=id)
|
raise f_exc.FirewallRuleInUse(firewall_rule_id=id)
|
||||||
context.session.delete(fwr)
|
context.session.delete(fwr)
|
||||||
|
|
||||||
def insert_rule(self, context, id, rule_info):
|
def insert_rule(self, context, id, rule_info):
|
||||||
LOG.debug("insert_rule() called")
|
|
||||||
self._validate_insert_remove_rule_request(rule_info)
|
|
||||||
firewall_rule_id = rule_info['firewall_rule_id']
|
firewall_rule_id = rule_info['firewall_rule_id']
|
||||||
# ensure rule is not already assigned to the policy
|
# ensure rule is not already assigned to the policy
|
||||||
self._ensure_rule_not_already_associated(context, id, firewall_rule_id)
|
self._ensure_rule_not_already_associated(context, id, firewall_rule_id)
|
||||||
@ -534,8 +559,6 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
position, None)
|
position, None)
|
||||||
|
|
||||||
def remove_rule(self, context, id, rule_info):
|
def remove_rule(self, context, id, rule_info):
|
||||||
LOG.debug("remove_rule() called")
|
|
||||||
self._validate_insert_remove_rule_request(rule_info)
|
|
||||||
firewall_rule_id = rule_info['firewall_rule_id']
|
firewall_rule_id = rule_info['firewall_rule_id']
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
self._get_firewall_rule(context, firewall_rule_id)
|
self._get_firewall_rule(context, firewall_rule_id)
|
||||||
@ -545,30 +568,15 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
None, fwpra_db)
|
None, fwpra_db)
|
||||||
|
|
||||||
def get_firewall_rule(self, context, id, fields=None):
|
def get_firewall_rule(self, context, id, fields=None):
|
||||||
LOG.debug("get_firewall_rule() called")
|
|
||||||
fwr = self._get_firewall_rule(context, id)
|
fwr = self._get_firewall_rule(context, id)
|
||||||
policies = self._get_policies_with_rule(context, id) or None
|
policies = self.get_policies_with_rule(context, id) or None
|
||||||
return self._make_firewall_rule_dict(fwr, fields, policies=policies)
|
return self._make_firewall_rule_dict(fwr, fields, policies=policies)
|
||||||
|
|
||||||
def get_firewall_rules(self, context, filters=None, fields=None):
|
def get_firewall_rules(self, context, filters=None, fields=None):
|
||||||
LOG.debug("get_firewall_rules() called")
|
|
||||||
return self._get_collection(context, FirewallRuleV2,
|
return self._get_collection(context, FirewallRuleV2,
|
||||||
self._make_firewall_rule_dict,
|
self._make_firewall_rule_dict,
|
||||||
filters=filters, fields=fields)
|
filters=filters, fields=fields)
|
||||||
|
|
||||||
def _validate_insert_remove_rule_request(self, rule_info):
|
|
||||||
"""Validate rule_info dict
|
|
||||||
|
|
||||||
Check that all mandatory fields are present, otherwise raise
|
|
||||||
proper exception.
|
|
||||||
"""
|
|
||||||
if not rule_info or 'firewall_rule_id' not in rule_info:
|
|
||||||
raise f_exc.FirewallRuleInfoMissing()
|
|
||||||
# Validator doesn't return anything if the check passes
|
|
||||||
if validators.validate_uuid(rule_info['firewall_rule_id']):
|
|
||||||
raise f_exc.FirewallRuleNotFound(
|
|
||||||
firewall_rule_id=rule_info['firewall_rule_id'])
|
|
||||||
|
|
||||||
def _get_rules_in_policy(self, context, fwpid):
|
def _get_rules_in_policy(self, context, fwpid):
|
||||||
"""Gets rules in a firewall policy"""
|
"""Gets rules in a firewall policy"""
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
@ -578,7 +586,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
fwp_rules = [entry.firewall_rule_id for entry in fw_pol_rule_qry]
|
fwp_rules = [entry.firewall_rule_id for entry in fw_pol_rule_qry]
|
||||||
return fwp_rules
|
return fwp_rules
|
||||||
|
|
||||||
def _get_policies_with_rule(self, context, fwrid):
|
def get_policies_with_rule(self, context, fwrid):
|
||||||
"""Gets rules in a firewall policy"""
|
"""Gets rules in a firewall policy"""
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fw_pol_rule_qry = context.session.query(
|
fw_pol_rule_qry = context.session.query(
|
||||||
@ -644,7 +652,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
firewall_rule_id=fwr_db['id'],
|
firewall_rule_id=fwr_db['id'],
|
||||||
firewall_policy_id=fwp_db['id'])
|
firewall_policy_id=fwp_db['id'])
|
||||||
|
|
||||||
def _get_fwgs_with_policy(self, context, fwp_id):
|
def get_fwgs_with_policy(self, context, fwp_id):
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fwg_ing_pol_qry = context.session.query(
|
fwg_ing_pol_qry = context.session.query(
|
||||||
FirewallGroup).filter_by(
|
FirewallGroup).filter_by(
|
||||||
@ -719,18 +727,18 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
description = kwargs.get('description', '')
|
description = kwargs.get('description', '')
|
||||||
name = (const.DEFAULT_FWP_INGRESS
|
name = (const.DEFAULT_FWP_INGRESS
|
||||||
if policy_type == 'ingress' else const.DEFAULT_FWP_EGRESS)
|
if policy_type == 'ingress' else const.DEFAULT_FWP_EGRESS)
|
||||||
firewall_policy = {'firewall_policy': {
|
firewall_policy = {
|
||||||
'name': name,
|
'name': name,
|
||||||
'description': description,
|
'description': description,
|
||||||
'audited': False,
|
'audited': False,
|
||||||
'shared': False,
|
'shared': False,
|
||||||
'firewall_rules': fwrs,
|
'firewall_rules': fwrs,
|
||||||
'tenant_id': tenant_id,
|
'tenant_id': tenant_id,
|
||||||
}}
|
}
|
||||||
return self._do_create_firewall_policy(context, firewall_policy)
|
return self._do_create_firewall_policy(context, firewall_policy)
|
||||||
|
|
||||||
def _do_create_firewall_policy(self, context, firewall_policy):
|
def _do_create_firewall_policy(self, context, firewall_policy):
|
||||||
fwp = firewall_policy['firewall_policy']
|
fwp = firewall_policy
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fwp_db = FirewallPolicy(
|
fwp_db = FirewallPolicy(
|
||||||
id=uuidutils.generate_uuid(),
|
id=uuidutils.generate_uuid(),
|
||||||
@ -744,13 +752,11 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
return self._make_firewall_policy_dict(fwp_db)
|
return self._make_firewall_policy_dict(fwp_db)
|
||||||
|
|
||||||
def create_firewall_policy(self, context, firewall_policy):
|
def create_firewall_policy(self, context, firewall_policy):
|
||||||
LOG.debug("create_firewall_policy() called")
|
|
||||||
self._ensure_not_default_resource(firewall_policy, 'firewall_policy')
|
self._ensure_not_default_resource(firewall_policy, 'firewall_policy')
|
||||||
return self._do_create_firewall_policy(context, firewall_policy)
|
return self._do_create_firewall_policy(context, firewall_policy)
|
||||||
|
|
||||||
def update_firewall_policy(self, context, id, firewall_policy):
|
def update_firewall_policy(self, context, id, firewall_policy):
|
||||||
LOG.debug("update_firewall_policy() called")
|
fwp = firewall_policy
|
||||||
fwp = firewall_policy['firewall_policy']
|
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fwp_db = self._get_firewall_policy(context, id)
|
fwp_db = self._get_firewall_policy(context, id)
|
||||||
self._ensure_not_default_resource(fwp_db, 'firewall_policy',
|
self._ensure_not_default_resource(fwp_db, 'firewall_policy',
|
||||||
@ -772,7 +778,6 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
return self._make_firewall_policy_dict(fwp_db)
|
return self._make_firewall_policy_dict(fwp_db)
|
||||||
|
|
||||||
def delete_firewall_policy(self, context, id):
|
def delete_firewall_policy(self, context, id):
|
||||||
LOG.debug("delete_firewall_policy() called")
|
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fwp_db = self._get_firewall_policy(context, id)
|
fwp_db = self._get_firewall_policy(context, id)
|
||||||
# check if policy in use
|
# check if policy in use
|
||||||
@ -786,35 +791,14 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
context.session.delete(fwp_db)
|
context.session.delete(fwp_db)
|
||||||
|
|
||||||
def get_firewall_policy(self, context, id, fields=None):
|
def get_firewall_policy(self, context, id, fields=None):
|
||||||
LOG.debug("get_firewall_policy() called")
|
|
||||||
fwp = self._get_firewall_policy(context, id)
|
fwp = self._get_firewall_policy(context, id)
|
||||||
return self._make_firewall_policy_dict(fwp, fields)
|
return self._make_firewall_policy_dict(fwp, fields)
|
||||||
|
|
||||||
def get_firewall_policies(self, context, filters=None, fields=None):
|
def get_firewall_policies(self, context, filters=None, fields=None):
|
||||||
LOG.debug("get_firewall_policies() called")
|
|
||||||
return self._get_collection(context, FirewallPolicy,
|
return self._get_collection(context, FirewallPolicy,
|
||||||
self._make_firewall_policy_dict,
|
self._make_firewall_policy_dict,
|
||||||
filters=filters, fields=fields)
|
filters=filters, fields=fields)
|
||||||
|
|
||||||
def _validate_tenant_for_fwg_policies(self, context, fwg, fwg_tenant_id):
|
|
||||||
# On updates, all keys will not be present so fetch and validate.
|
|
||||||
if 'ingress_firewall_policy_id' in fwg:
|
|
||||||
fwp_id = fwg['ingress_firewall_policy_id']
|
|
||||||
if fwp_id is not None:
|
|
||||||
fwp = self._get_firewall_policy(context, fwp_id)
|
|
||||||
if fwg_tenant_id != fwp['tenant_id'] and not fwp['shared']:
|
|
||||||
raise f_exc.FirewallPolicyConflict(
|
|
||||||
firewall_policy_id=fwp_id)
|
|
||||||
|
|
||||||
if 'egress_firewall_policy_id' in fwg:
|
|
||||||
fwp_id = fwg['egress_firewall_policy_id']
|
|
||||||
if fwp_id is not None:
|
|
||||||
fwp = self._get_firewall_policy(context, fwp_id)
|
|
||||||
if fwg_tenant_id != fwp['tenant_id'] and not fwp['shared']:
|
|
||||||
raise f_exc.FirewallPolicyConflict(
|
|
||||||
firewall_policy_id=fwp_id)
|
|
||||||
return
|
|
||||||
|
|
||||||
def _set_ports_for_firewall_group(self, context, fwg_db, fwg):
|
def _set_ports_for_firewall_group(self, context, fwg_db, fwg):
|
||||||
port_id_list = fwg['ports']
|
port_id_list = fwg['ports']
|
||||||
if not port_id_list:
|
if not port_id_list:
|
||||||
@ -833,7 +817,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
if exc_ports:
|
if exc_ports:
|
||||||
raise f_exc.FirewallGroupPortInUse(port_ids=exc_ports)
|
raise f_exc.FirewallGroupPortInUse(port_ids=exc_ports)
|
||||||
|
|
||||||
def _get_ports_in_firewall_group(self, context, firewall_group_id):
|
def get_ports_in_firewall_group(self, context, firewall_group_id):
|
||||||
"""Get the Ports associated with the firewall group."""
|
"""Get the Ports associated with the firewall group."""
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fw_group_port_qry = context.session.query(
|
fw_group_port_qry = context.session.query(
|
||||||
@ -852,27 +836,13 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
firewall_group_id=firewall_group_id).delete()
|
firewall_group_id=firewall_group_id).delete()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _validate_if_firewall_group_on_ports(
|
|
||||||
self, context, port_ids, fwg_id=None):
|
|
||||||
"""Validate if ports are not associated with any firewall_group.
|
|
||||||
If any of the ports in the list is already associated with
|
|
||||||
a firewall_group, raise an exception else just return.
|
|
||||||
"""
|
|
||||||
fwg_port_qry = context.session.query(
|
|
||||||
FirewallGroupPortAssociation.port_id)
|
|
||||||
fwg_ports = fwg_port_qry.filter(
|
|
||||||
FirewallGroupPortAssociation.port_id.in_(port_ids),
|
|
||||||
FirewallGroupPortAssociation.firewall_group_id != fwg_id).all()
|
|
||||||
if fwg_ports:
|
|
||||||
port_ids = [entry.port_id for entry in fwg_ports]
|
|
||||||
raise f_exc.FirewallGroupPortInUse(port_ids=port_ids)
|
|
||||||
|
|
||||||
def _get_default_fwg_id(self, context, tenant_id):
|
def _get_default_fwg_id(self, context, tenant_id):
|
||||||
"""Returns an id of default firewall group for given tenant or None"""
|
"""Returns an id of default firewall group for given tenant or None"""
|
||||||
default_fwg = self._model_query(context, FirewallGroup).filter_by(
|
default_fwg = self._model_query(context, FirewallGroup).filter_by(
|
||||||
project_id=tenant_id, name=const.DEFAULT_FWG).first()
|
project_id=tenant_id, name=const.DEFAULT_FWG).first()
|
||||||
if default_fwg:
|
if default_fwg:
|
||||||
return default_fwg.id
|
return default_fwg.id
|
||||||
|
return None
|
||||||
|
|
||||||
def _ensure_default_firewall_group(self, context, tenant_id):
|
def _ensure_default_firewall_group(self, context, tenant_id):
|
||||||
"""Create a default firewall group if one doesn't exist for a tenant
|
"""Create a default firewall group if one doesn't exist for a tenant
|
||||||
@ -905,19 +875,18 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
context, tenant_id, 'egress', **egress_fwp)
|
context, tenant_id, 'egress', **egress_fwp)
|
||||||
|
|
||||||
fwg = {
|
fwg = {
|
||||||
'firewall_group':
|
'name': const.DEFAULT_FWG,
|
||||||
{'name': const.DEFAULT_FWG,
|
'tenant_id': tenant_id,
|
||||||
'tenant_id': tenant_id,
|
'ingress_firewall_policy_id': ingress_fwp_db['id'],
|
||||||
'ingress_firewall_policy_id': ingress_fwp_db['id'],
|
'egress_firewall_policy_id': egress_fwp_db['id'],
|
||||||
'egress_firewall_policy_id': egress_fwp_db['id'],
|
'ports': [],
|
||||||
'ports': [],
|
'shared': False,
|
||||||
'shared': False,
|
'status': nl_constants.INACTIVE,
|
||||||
'admin_state_up': True,
|
'admin_state_up': True,
|
||||||
'description': 'Default firewall group'}
|
'description': 'Default firewall group',
|
||||||
}
|
}
|
||||||
fwg_db = self._create_firewall_group(
|
fwg_db = self._create_firewall_group(
|
||||||
context, fwg, status=nl_constants.INACTIVE,
|
context, fwg, default_fwg=True)
|
||||||
default_fwg=True)
|
|
||||||
context.session.add(DefaultFirewallGroup(
|
context.session.add(DefaultFirewallGroup(
|
||||||
firewall_group_id=fwg_db['id'],
|
firewall_group_id=fwg_db['id'],
|
||||||
project_id=tenant_id))
|
project_id=tenant_id))
|
||||||
@ -928,37 +897,36 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
LOG.debug("Default FWG was concurrently created")
|
LOG.debug("Default FWG was concurrently created")
|
||||||
return self._get_default_fwg_id(context, tenant_id)
|
return self._get_default_fwg_id(context, tenant_id)
|
||||||
|
|
||||||
def _create_firewall_group(self, context, firewall_group, status=None,
|
def _create_firewall_group(self, context, firewall_group,
|
||||||
default_fwg=False):
|
default_fwg=False):
|
||||||
"""Create a firewall group
|
"""Create a firewall group
|
||||||
|
|
||||||
If default_fwg is True then a default firewall group is being created
|
If default_fwg is True then a default firewall group is being created
|
||||||
for a given tenant.
|
for a given tenant.
|
||||||
"""
|
"""
|
||||||
fwg = firewall_group['firewall_group']
|
fwg = firewall_group
|
||||||
tenant_id = fwg['tenant_id']
|
tenant_id = fwg['tenant_id']
|
||||||
if not status:
|
if firewall_group.get('status') is None:
|
||||||
status = (nl_constants.CREATED if cfg.CONF.router_distributed
|
fwg['status'] = nl_constants.CREATED
|
||||||
else nl_constants.PENDING_CREATE)
|
|
||||||
if default_fwg:
|
if default_fwg:
|
||||||
# A default firewall group is being created.
|
# A default firewall group is being created.
|
||||||
default_fwg_id = self._get_default_fwg_id(context, tenant_id)
|
default_fwg_id = self._get_default_fwg_id(context, tenant_id)
|
||||||
if default_fwg_id is not None:
|
if default_fwg_id is not None:
|
||||||
# Default fwg for a given tenant exists, fetch it and return
|
# Default fwg for a given tenant exists, fetch it and return
|
||||||
return self.get_firewall_group(default_fwg_id)
|
return self.get_firewall_group(context, default_fwg_id)
|
||||||
else:
|
else:
|
||||||
# An ordinary firewall group is being created BUT let's make sure
|
# An ordinary firewall group is being created BUT let's make sure
|
||||||
# that a default firewall group for given tenant exists
|
# that a default firewall group for given tenant exists
|
||||||
self._ensure_default_firewall_group(context, tenant_id)
|
self._ensure_default_firewall_group(context, tenant_id)
|
||||||
|
|
||||||
self._validate_tenant_for_fwg_policies(context, fwg, tenant_id)
|
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fwg_db = FirewallGroup(
|
fwg_db = FirewallGroup(
|
||||||
id=uuidutils.generate_uuid(),
|
id=uuidutils.generate_uuid(),
|
||||||
tenant_id=tenant_id,
|
tenant_id=tenant_id,
|
||||||
name=fwg['name'],
|
name=fwg['name'],
|
||||||
description=fwg['description'],
|
description=fwg['description'],
|
||||||
status=status,
|
status=fwg['status'],
|
||||||
ingress_firewall_policy_id=fwg['ingress_firewall_policy_id'],
|
ingress_firewall_policy_id=fwg['ingress_firewall_policy_id'],
|
||||||
egress_firewall_policy_id=fwg['egress_firewall_policy_id'],
|
egress_firewall_policy_id=fwg['egress_firewall_policy_id'],
|
||||||
admin_state_up=fwg['admin_state_up'],
|
admin_state_up=fwg['admin_state_up'],
|
||||||
@ -967,15 +935,14 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
self._set_ports_for_firewall_group(context, fwg_db, fwg)
|
self._set_ports_for_firewall_group(context, fwg_db, fwg)
|
||||||
return self._make_firewall_group_dict(fwg_db)
|
return self._make_firewall_group_dict(fwg_db)
|
||||||
|
|
||||||
def create_firewall_group(self, context, firewall_group, status=None):
|
def create_firewall_group(self, context, firewall_group):
|
||||||
self._ensure_not_default_resource(firewall_group, 'firewall_group')
|
self._ensure_not_default_resource(firewall_group, 'firewall_group')
|
||||||
return self._create_firewall_group(context, firewall_group, status)
|
return self._create_firewall_group(context, firewall_group)
|
||||||
|
|
||||||
def update_firewall_group(self, context, id, firewall_group):
|
def update_firewall_group(self, context, id, firewall_group):
|
||||||
LOG.debug("update_firewall_group() called")
|
fwg = firewall_group
|
||||||
fwg = firewall_group['firewall_group']
|
|
||||||
# make sure that no group can be updated to have name=default
|
# make sure that no group can be updated to have name=default
|
||||||
self._ensure_not_default_resource(firewall_group, 'firewall_group')
|
self._ensure_not_default_resource(fwg, 'firewall_group')
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
fwg_db = self.get_firewall_group(context, id)
|
fwg_db = self.get_firewall_group(context, id)
|
||||||
if _is_default(fwg_db):
|
if _is_default(fwg_db):
|
||||||
@ -990,8 +957,6 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
raise FirewallDefaultObjectUpdateRestricted(
|
raise FirewallDefaultObjectUpdateRestricted(
|
||||||
resource_type='Firewall Group',
|
resource_type='Firewall Group',
|
||||||
resource_id=fwg_db['id'])
|
resource_id=fwg_db['id'])
|
||||||
self._validate_tenant_for_fwg_policies(context,
|
|
||||||
fwg, fwg_db['tenant_id'])
|
|
||||||
if 'ports' in fwg:
|
if 'ports' in fwg:
|
||||||
LOG.debug("Ports are updated in Firewall Group")
|
LOG.debug("Ports are updated in Firewall Group")
|
||||||
self._delete_ports_in_firewall_group(context, id)
|
self._delete_ports_in_firewall_group(context, id)
|
||||||
@ -1021,7 +986,6 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
def delete_firewall_group(self, context, id):
|
def delete_firewall_group(self, context, id):
|
||||||
# Note: Plugin should ensure that it's okay to delete if the
|
# Note: Plugin should ensure that it's okay to delete if the
|
||||||
# firewall is active
|
# firewall is active
|
||||||
LOG.debug("delete_firewall_group() called")
|
|
||||||
|
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
# if no such group exists -> don't raise an exception according to
|
# if no such group exists -> don't raise an exception according to
|
||||||
@ -1077,12 +1041,10 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
resource_type='Firewall Policy', name=resource['name'])
|
resource_type='Firewall Policy', name=resource['name'])
|
||||||
|
|
||||||
def get_firewall_group(self, context, id, fields=None):
|
def get_firewall_group(self, context, id, fields=None):
|
||||||
LOG.debug("get_firewall_group() called")
|
|
||||||
fw = self._get_firewall_group(context, id)
|
fw = self._get_firewall_group(context, id)
|
||||||
return self._make_firewall_group_dict(fw, fields)
|
return self._make_firewall_group_dict(fw, fields)
|
||||||
|
|
||||||
def get_firewall_groups(self, context, filters=None, fields=None):
|
def get_firewall_groups(self, context, filters=None, fields=None):
|
||||||
LOG.debug("get_firewall_groups() called")
|
|
||||||
if context.tenant_id:
|
if context.tenant_id:
|
||||||
tenant_id = filters.get('tenant_id') if filters else None
|
tenant_id = filters.get('tenant_id') if filters else None
|
||||||
tenant_id = tenant_id[0] if tenant_id else context.tenant_id
|
tenant_id = tenant_id[0] if tenant_id else context.tenant_id
|
||||||
@ -1091,48 +1053,6 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
|
|||||||
self._make_firewall_group_dict,
|
self._make_firewall_group_dict,
|
||||||
filters=filters, fields=fields)
|
filters=filters, fields=fields)
|
||||||
|
|
||||||
def get_firewall_group_for_port(self, context, port_id):
|
|
||||||
"""Get firewall group is associated with a port
|
|
||||||
|
|
||||||
:param context: context object
|
|
||||||
:param port_id: Port ID.
|
|
||||||
"""
|
|
||||||
filters = {'port_id': [port_id]}
|
|
||||||
fwg_port_binding = self._get_collection_query(
|
|
||||||
context, FirewallGroupPortAssociation, filters=filters).first()
|
|
||||||
if fwg_port_binding:
|
|
||||||
fwg_id = fwg_port_binding['firewall_group_id']
|
|
||||||
return self._make_firewall_group_dict_with_rules(context, fwg_id)
|
|
||||||
|
|
||||||
def _get_default_fwg(self, context, project_id):
|
|
||||||
query = self._model_query(context, DefaultFirewallGroup)
|
|
||||||
def_fwg_id = query.filter_by(
|
|
||||||
project_id=project_id).one().firewall_group_id
|
|
||||||
return self.get_firewall_group(context, def_fwg_id)
|
|
||||||
|
|
||||||
def set_port_for_default_firewall_group(self, context, port_id,
|
|
||||||
project_id):
|
|
||||||
"""Set a port into default firewall group
|
|
||||||
|
|
||||||
:param context: Context object
|
|
||||||
:param port_id: Port ID
|
|
||||||
:param project_id: ProjectID
|
|
||||||
"""
|
|
||||||
with context.session.begin(subtransactions=True):
|
|
||||||
def_fwg_db = self._get_default_fwg(context, project_id)
|
|
||||||
try:
|
|
||||||
self._set_ports_for_firewall_group(
|
|
||||||
context, def_fwg_db, {'ports': [port_id]})
|
|
||||||
except f_exc.FirewallGroupPortInUse:
|
|
||||||
LOG.warning("Port %s has been already associated with default "
|
|
||||||
"firewall group %s and skip association", port_id,
|
|
||||||
def_fwg_db['id'])
|
|
||||||
else:
|
|
||||||
# Update default fwg status to PENDING_UPDATE to wait updating
|
|
||||||
# from agent
|
|
||||||
self.update_firewall_group_status(
|
|
||||||
context, def_fwg_db['id'], nl_constants.PENDING_UPDATE)
|
|
||||||
|
|
||||||
|
|
||||||
def _is_default(fwg_db):
|
def _is_default(fwg_db):
|
||||||
return fwg_db['name'] == const.DEFAULT_FWG
|
return fwg_db['name'] == const.DEFAULT_FWG
|
||||||
|
@ -126,6 +126,7 @@ class Firewallv2PluginBase(service_base.ServicePluginBase):
|
|||||||
def get_plugin_description(self):
|
def get_plugin_description(self):
|
||||||
return 'Firewall Service v2 Plugin'
|
return 'Firewall Service v2 Plugin'
|
||||||
|
|
||||||
|
# Firewall Group
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def create_firewall_group(self, context, firewall_group):
|
def create_firewall_group(self, context, firewall_group):
|
||||||
pass
|
pass
|
||||||
@ -135,7 +136,7 @@ class Firewallv2PluginBase(service_base.ServicePluginBase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_firewall_group(self, context, id):
|
def get_firewall_group(self, context, id, fields=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@ -146,24 +147,13 @@ class Firewallv2PluginBase(service_base.ServicePluginBase):
|
|||||||
def update_firewall_group(self, context, id, firewall_group):
|
def update_firewall_group(self, context, id, firewall_group):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Firewall Policy
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_firewall_rules(self, context, filters=None, fields=None):
|
def create_firewall_policy(self, context, firewall_policy):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_firewall_rule(self, context, id, fields=None):
|
def delete_firewall_policy(self, context, id):
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def create_firewall_rule(self, context, firewall_rule):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def update_firewall_rule(self, context, id, firewall_rule):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def delete_firewall_rule(self, context, id):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@ -174,16 +164,29 @@ class Firewallv2PluginBase(service_base.ServicePluginBase):
|
|||||||
def get_firewall_policies(self, context, filters=None, fields=None):
|
def get_firewall_policies(self, context, filters=None, fields=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def create_firewall_policy(self, context, firewall_policy):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def update_firewall_policy(self, context, id, firewall_policy):
|
def update_firewall_policy(self, context, id, firewall_policy):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Firewall Rule
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def delete_firewall_policy(self, context, id):
|
def create_firewall_rule(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_rule(self, context, id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_rule(self, context, id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_rules(self, context, filters=None, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_rule(self, context, id, firewall_rule):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -10,19 +10,25 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import neutron.conf.services.provider_configuration
|
||||||
|
|
||||||
|
import neutron_fwaas.services.firewall.service_drivers.agents.\
|
||||||
|
firewall_agent_api
|
||||||
import neutron_fwaas.extensions.firewall
|
import neutron_fwaas.extensions.firewall
|
||||||
import neutron_fwaas.services.firewall.agents.firewall_agent_api
|
|
||||||
|
|
||||||
|
|
||||||
def list_agent_opts():
|
def list_agent_opts():
|
||||||
return [
|
return [
|
||||||
('fwaas',
|
('fwaas',
|
||||||
neutron_fwaas.services.firewall.agents.firewall_agent_api.FWaaSOpts)
|
neutron_fwaas.services.firewall.service_drivers.agents.
|
||||||
|
firewall_agent_api.FWaaSOpts),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def list_opts():
|
def list_opts():
|
||||||
return [
|
return [
|
||||||
('quotas',
|
('quotas',
|
||||||
neutron_fwaas.extensions.firewall.firewall_quota_opts)
|
neutron_fwaas.extensions.firewall.firewall_quota_opts),
|
||||||
|
('service_providers',
|
||||||
|
neutron.conf.services.provider_configuration.serviceprovider_opts),
|
||||||
]
|
]
|
||||||
|
@ -12,238 +12,138 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutron.common import rpc as n_rpc
|
|
||||||
from neutron.db import servicetype_db as st_db
|
from neutron.db import servicetype_db as st_db
|
||||||
from neutron.services import provider_configuration as provider_conf
|
from neutron.services import provider_configuration as provider_conf
|
||||||
|
from neutron.services import service_base
|
||||||
from neutron_lib.api.definitions import firewall_v2
|
from neutron_lib.api.definitions import firewall_v2
|
||||||
from neutron_lib.api.definitions import portbindings as pb_def
|
from neutron_lib.api.definitions import portbindings as pb_def
|
||||||
|
from neutron_lib.api import validators
|
||||||
from neutron_lib.callbacks import events
|
from neutron_lib.callbacks import events
|
||||||
from neutron_lib.callbacks import registry
|
from neutron_lib.callbacks import registry
|
||||||
from neutron_lib.callbacks import resources
|
from neutron_lib.callbacks import resources
|
||||||
from neutron_lib import constants as nl_constants
|
from neutron_lib import constants as nl_constants
|
||||||
from neutron_lib import context as neutron_context
|
|
||||||
from neutron_lib.exceptions import firewall_v2 as f_exc
|
from neutron_lib.exceptions import firewall_v2 as f_exc
|
||||||
from neutron_lib.plugins import constants as plugin_const
|
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
from oslo_config import cfg
|
from oslo_log import helpers as log_helpers
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import oslo_messaging
|
|
||||||
|
|
||||||
from neutron_fwaas.common import exceptions
|
from neutron_fwaas.common import exceptions
|
||||||
from neutron_fwaas.common import fwaas_constants
|
from neutron_fwaas.common import fwaas_constants
|
||||||
from neutron_fwaas.db.firewall.v2 import firewall_db_v2
|
from neutron_fwaas.extensions.firewall_v2 import Firewallv2PluginBase
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def add_provider_configuration(type_manager, service_type):
|
|
||||||
type_manager.add_provider_configuration(
|
|
||||||
service_type,
|
|
||||||
provider_conf.ProviderConfiguration('neutron_fwaas'))
|
|
||||||
|
|
||||||
|
|
||||||
class FirewallAgentApi(object):
|
|
||||||
"""Plugin side of plugin to agent RPC API."""
|
|
||||||
|
|
||||||
def __init__(self, topic, host):
|
|
||||||
self.host = host
|
|
||||||
target = oslo_messaging.Target(topic=topic, version='1.0')
|
|
||||||
self.client = n_rpc.get_client(target)
|
|
||||||
|
|
||||||
def create_firewall_group(self, context, firewall_group):
|
|
||||||
cctxt = self.client.prepare(fanout=True)
|
|
||||||
cctxt.cast(context, 'create_firewall_group',
|
|
||||||
firewall_group=firewall_group,
|
|
||||||
host=self.host)
|
|
||||||
|
|
||||||
def update_firewall_group(self, context, firewall_group):
|
|
||||||
cctxt = self.client.prepare(fanout=True)
|
|
||||||
cctxt.cast(context, 'update_firewall_group',
|
|
||||||
firewall_group=firewall_group,
|
|
||||||
host=self.host)
|
|
||||||
|
|
||||||
def delete_firewall_group(self, context, firewall_group):
|
|
||||||
cctxt = self.client.prepare(fanout=True)
|
|
||||||
cctxt.cast(context, 'delete_firewall_group',
|
|
||||||
firewall_group=firewall_group,
|
|
||||||
host=self.host)
|
|
||||||
|
|
||||||
|
|
||||||
class FirewallCallbacks(object):
|
|
||||||
target = oslo_messaging.Target(version='1.0')
|
|
||||||
|
|
||||||
def __init__(self, plugin):
|
|
||||||
super(FirewallCallbacks, self).__init__()
|
|
||||||
self.plugin = plugin
|
|
||||||
|
|
||||||
def set_firewall_group_status(self, context, fwg_id, status, **kwargs):
|
|
||||||
"""Agent uses this to set a firewall_group's status."""
|
|
||||||
LOG.debug("Setting firewall_group %s to status: %s",
|
|
||||||
fwg_id, status)
|
|
||||||
# Sanitize status first
|
|
||||||
if status in (nl_constants.ACTIVE, nl_constants.DOWN,
|
|
||||||
nl_constants.INACTIVE):
|
|
||||||
to_update = status
|
|
||||||
else:
|
|
||||||
to_update = nl_constants.ERROR
|
|
||||||
# ignore changing status if firewall_group expects to be deleted
|
|
||||||
# That case means that while some pending operation has been
|
|
||||||
# performed on the backend, neutron server received delete request
|
|
||||||
# and changed firewall status to PENDING_DELETE
|
|
||||||
updated = self.plugin.update_firewall_group_status(
|
|
||||||
context, fwg_id, to_update, not_in=(nl_constants.PENDING_DELETE,))
|
|
||||||
if updated:
|
|
||||||
LOG.debug("firewall %s status set: %s", fwg_id, to_update)
|
|
||||||
return updated and to_update != nl_constants.ERROR
|
|
||||||
|
|
||||||
def firewall_group_deleted(self, context, fwg_id, **kwargs):
|
|
||||||
"""Agent uses this to indicate firewall is deleted."""
|
|
||||||
LOG.debug("firewall_group_deleted() called")
|
|
||||||
try:
|
|
||||||
with context.session.begin(subtransactions=True):
|
|
||||||
fwg_db = self.plugin._get_firewall_group(context, fwg_id)
|
|
||||||
# allow to delete firewalls in ERROR state
|
|
||||||
if fwg_db.status in (nl_constants.PENDING_DELETE,
|
|
||||||
nl_constants.ERROR):
|
|
||||||
self.plugin.delete_db_firewall_group_object(context,
|
|
||||||
fwg_id)
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
LOG.warning(('Firewall %(fwg)s unexpectedly deleted by '
|
|
||||||
'agent, status was %(status)s'),
|
|
||||||
{'fwg': fwg_id, 'status': fwg_db.status})
|
|
||||||
fwg_db.update({"status": nl_constants.ERROR})
|
|
||||||
return False
|
|
||||||
except f_exc.FirewallGroupNotFound:
|
|
||||||
LOG.info('Firewall group %s already deleted', fwg_id)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_firewall_groups_for_project(self, context, **kwargs):
|
|
||||||
"""Gets all firewall_groups and rules on a project."""
|
|
||||||
LOG.debug("get_firewall_groups_for_project() called")
|
|
||||||
fwg_list = []
|
|
||||||
for fwg in self.plugin.get_firewall_groups(context):
|
|
||||||
fwg_with_rules = self.plugin._make_firewall_group_dict_with_rules(
|
|
||||||
context, fwg['id'])
|
|
||||||
if fwg['status'] == nl_constants.PENDING_DELETE:
|
|
||||||
fwg_with_rules['add-port-ids'] = []
|
|
||||||
fwg_with_rules['del-port-ids'] = (
|
|
||||||
self.plugin._get_ports_in_firewall_group(context,
|
|
||||||
fwg['id']))
|
|
||||||
else:
|
|
||||||
fwg_with_rules['add-port-ids'] = (
|
|
||||||
self.plugin._get_ports_in_firewall_group(context,
|
|
||||||
fwg['id']))
|
|
||||||
fwg_with_rules['del-port-ids'] = []
|
|
||||||
fwg_list.append(fwg_with_rules)
|
|
||||||
return fwg_list
|
|
||||||
|
|
||||||
def get_projects_with_firewall_groups(self, context, **kwargs):
|
|
||||||
"""Get all projects that have firewall_groups."""
|
|
||||||
LOG.debug("get_projects_with_firewall_groups() called")
|
|
||||||
ctx = neutron_context.get_admin_context()
|
|
||||||
fwg_list = self.plugin.get_firewall_groups(ctx)
|
|
||||||
fwg_project_list = list(set(fwg['tenant_id'] for fwg in fwg_list))
|
|
||||||
return fwg_project_list
|
|
||||||
|
|
||||||
def get_firewall_group_for_port(self, context, **kwargs):
|
|
||||||
"""Get firewall_group is associated with a port."""
|
|
||||||
LOG.debug("get_firewall_group_for_port() called")
|
|
||||||
ctx = context.elevated()
|
|
||||||
return self.plugin.get_firewall_group_for_port(
|
|
||||||
ctx, kwargs.get('port_id'))
|
|
||||||
|
|
||||||
|
|
||||||
@registry.has_registry_receivers
|
@registry.has_registry_receivers
|
||||||
class FirewallPluginV2(
|
class FirewallPluginV2(Firewallv2PluginBase):
|
||||||
firewall_db_v2.Firewall_db_mixin_v2):
|
"""Firewall v2 Neutron service plugin class"""
|
||||||
"""Implementation of the Neutron Firewall Service Plugin.
|
|
||||||
|
|
||||||
This class manages the workflow of FWaaS request/response.
|
supported_extension_aliases = [firewall_v2.ALIAS]
|
||||||
Most DB related works are implemented in class
|
|
||||||
firewall_db_v2.Firewall_db_mixin_v2.
|
|
||||||
"""
|
|
||||||
supported_extension_aliases = ["fwaas_v2"]
|
|
||||||
path_prefix = firewall_v2.API_PREFIX
|
path_prefix = firewall_v2.API_PREFIX
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
super(FirewallPluginV2, self).__init__()
|
||||||
"""Do the initialization for the firewall service plugin here."""
|
"""Do the initialization for the firewall service plugin here."""
|
||||||
self.service_type_manager = st_db.ServiceTypeManager.get_instance()
|
# Initialize the Firewall v2 service plugin
|
||||||
add_provider_configuration(
|
service_type_manager = st_db.ServiceTypeManager.get_instance()
|
||||||
self.service_type_manager, plugin_const.FIREWALL)
|
service_type_manager.add_provider_configuration(
|
||||||
self.start_rpc_listeners()
|
fwaas_constants.FIREWALL_V2,
|
||||||
|
provider_conf.ProviderConfiguration('neutron_fwaas'))
|
||||||
|
|
||||||
self.agent_rpc = FirewallAgentApi(
|
# Load the default driver
|
||||||
fwaas_constants.FW_AGENT,
|
drivers, default_provider = service_base.load_drivers(
|
||||||
cfg.CONF.host
|
fwaas_constants.FIREWALL_V2, self)
|
||||||
)
|
LOG.info("Firewall v2 Service Plugin using Service Driver: %s",
|
||||||
|
default_provider)
|
||||||
|
|
||||||
|
if len(drivers) > 1:
|
||||||
|
LOG.warning("Multiple drivers configured for Firewall v2, "
|
||||||
|
"although running multiple drivers in parallel is "
|
||||||
|
"not yet supported")
|
||||||
|
|
||||||
|
self.driver = drivers[default_provider]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _core_plugin(self):
|
def _core_plugin(self):
|
||||||
return directory.get_plugin()
|
return directory.get_plugin()
|
||||||
|
|
||||||
def start_rpc_listeners(self):
|
|
||||||
self.endpoints = [FirewallCallbacks(self)]
|
|
||||||
|
|
||||||
self.conn = n_rpc.Connection()
|
|
||||||
self.conn.create_consumer(
|
|
||||||
fwaas_constants.FIREWALL_PLUGIN, self.endpoints, fanout=False)
|
|
||||||
return self.conn.consume_in_threads()
|
|
||||||
|
|
||||||
def _rpc_update_firewall_group(self, context, fwg_id):
|
|
||||||
status_update = {"firewall_group": {"status":
|
|
||||||
nl_constants.PENDING_UPDATE}}
|
|
||||||
super(FirewallPluginV2, self).update_firewall_group(
|
|
||||||
context, fwg_id, status_update)
|
|
||||||
fwg_with_rules = self._make_firewall_group_dict_with_rules(context,
|
|
||||||
fwg_id)
|
|
||||||
# this is triggered on an update to fwg rule or policy, no
|
|
||||||
# change in associated ports.
|
|
||||||
fwg_with_rules['add-port-ids'] = self._get_ports_in_firewall_group(
|
|
||||||
context, fwg_id)
|
|
||||||
fwg_with_rules['del-port-ids'] = []
|
|
||||||
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
|
||||||
context, fwg_with_rules['add-port-ids'])
|
|
||||||
self.agent_rpc.update_firewall_group(context, fwg_with_rules)
|
|
||||||
|
|
||||||
def _rpc_update_firewall_policy(self, context, firewall_policy_id):
|
|
||||||
firewall_policy = self.get_firewall_policy(context, firewall_policy_id)
|
|
||||||
if firewall_policy:
|
|
||||||
ing_fwg_ids, eg_fwg_ids = self._get_fwgs_with_policy(context,
|
|
||||||
firewall_policy_id)
|
|
||||||
for fwg_id in list(set(ing_fwg_ids + eg_fwg_ids)):
|
|
||||||
self._rpc_update_firewall_group(context, fwg_id)
|
|
||||||
|
|
||||||
def _ensure_update_firewall_group(self, context, fwg_id):
|
def _ensure_update_firewall_group(self, context, fwg_id):
|
||||||
|
"""Checks if the firewall group can be updated
|
||||||
|
|
||||||
|
Raises FirewallGroupInPendingState if the firewall group is in pending
|
||||||
|
state.
|
||||||
|
:param context: neutron context
|
||||||
|
:param fwg_id: firewall group ID to check
|
||||||
|
:return: Firewall group dict
|
||||||
|
"""
|
||||||
fwg = self.get_firewall_group(context, fwg_id)
|
fwg = self.get_firewall_group(context, fwg_id)
|
||||||
if fwg['status'] in [nl_constants.PENDING_CREATE,
|
if fwg['status'] in [nl_constants.PENDING_CREATE,
|
||||||
nl_constants.PENDING_UPDATE,
|
nl_constants.PENDING_UPDATE,
|
||||||
nl_constants.PENDING_DELETE]:
|
nl_constants.PENDING_DELETE]:
|
||||||
raise f_exc.FirewallGroupInPendingState(firewall_id=fwg_id,
|
raise f_exc.FirewallGroupInPendingState(
|
||||||
pending_state=fwg['status'])
|
firewall_id=fwg_id, pending_state=fwg['status'])
|
||||||
|
return fwg
|
||||||
|
|
||||||
def _ensure_update_firewall_policy(self, context, firewall_policy_id):
|
def _ensure_update_firewall_policy(self, context, fwp_id):
|
||||||
firewall_policy = self.get_firewall_policy(context, firewall_policy_id)
|
"""Checks if the firewall policy can be updated
|
||||||
if firewall_policy:
|
|
||||||
ing_fwg_ids, eg_fwg_ids = self._get_fwgs_with_policy(
|
Fetch firewall group associated to the policy and checks if they can be
|
||||||
context, firewall_policy_id)
|
updated.
|
||||||
for fwg_id in list(set(ing_fwg_ids + eg_fwg_ids)):
|
:param context: neutron context
|
||||||
self._ensure_update_firewall_group(context, fwg_id)
|
:param fwp_id: firewall policy ID to check
|
||||||
|
"""
|
||||||
|
fwp = self.get_firewall_policy(context, fwp_id)
|
||||||
|
ing_fwg_ids, eg_fwg_ids = self._get_fwgs_with_policy(context, fwp)
|
||||||
|
for fwg_id in list(set(ing_fwg_ids + eg_fwg_ids)):
|
||||||
|
self._ensure_update_firewall_group(context, fwg_id)
|
||||||
|
|
||||||
def _ensure_update_firewall_rule(self, context, fwr_id):
|
def _ensure_update_firewall_rule(self, context, fwr_id):
|
||||||
fwp_ids = self._get_policies_with_rule(context, fwr_id)
|
"""Checks if the firewall rule can be updated
|
||||||
|
|
||||||
|
Fetch firewall policy associated to the rule and checks if they can be
|
||||||
|
updated.
|
||||||
|
:param context: neutron context
|
||||||
|
:param fwr_id: firewall policy ID to check
|
||||||
|
"""
|
||||||
|
fwr = self.get_firewall_rule(context, fwr_id)
|
||||||
|
fwp_ids = self._get_policies_with_rule(context, fwr)
|
||||||
for fwp_id in fwp_ids:
|
for fwp_id in fwp_ids:
|
||||||
self._ensure_update_firewall_policy(context, fwp_id)
|
self._ensure_update_firewall_policy(context, fwp_id)
|
||||||
|
|
||||||
|
def _validate_firewall_policies_for_firewall_group(self, context, fwg):
|
||||||
|
"""Validate firewall group and policy owner
|
||||||
|
|
||||||
|
Check if the firewall policy is not shared, it have the same project
|
||||||
|
owner than the friewall group.
|
||||||
|
:param context: neutron context
|
||||||
|
:param fwg: firewall group to validate
|
||||||
|
"""
|
||||||
|
for policy_type in ['ingress_firewall_policy_id',
|
||||||
|
'egress_firewall_policy_id']:
|
||||||
|
if fwg.get(policy_type):
|
||||||
|
fwp = self.get_firewall_policy(context, fwg[policy_type])
|
||||||
|
if fwg['tenant_id'] != fwp['tenant_id'] and not fwp['shared']:
|
||||||
|
raise f_exc.FirewallPolicyConflict(
|
||||||
|
firewall_policy_id=fwg[policy_type])
|
||||||
|
|
||||||
def _validate_ports_for_firewall_group(self, context, tenant_id,
|
def _validate_ports_for_firewall_group(self, context, tenant_id,
|
||||||
fwg_ports):
|
fwg_ports):
|
||||||
|
"""Validate firewall group associated ports
|
||||||
|
|
||||||
|
Check if the firewall group associated ports have the same project
|
||||||
|
owner and is router interface type or a compute layer 2.
|
||||||
|
:param context: neutron context
|
||||||
|
:param tenant_id: firewall group project ID
|
||||||
|
:param fwg_ports: firewall group associated ports
|
||||||
|
"""
|
||||||
# TODO(sridar): elevated context and do we want to use public ?
|
# TODO(sridar): elevated context and do we want to use public ?
|
||||||
for port_id in fwg_ports:
|
for port_id in fwg_ports:
|
||||||
port_db = self._core_plugin._get_port(context, port_id)
|
port = self._core_plugin.get_port(context, port_id)
|
||||||
if port_db['tenant_id'] != tenant_id:
|
|
||||||
|
if port['tenant_id'] != tenant_id:
|
||||||
raise f_exc.FirewallGroupPortInvalidProject(
|
raise f_exc.FirewallGroupPortInvalidProject(
|
||||||
port_id=port_id, project_id=port_db['tenant_id'])
|
port_id=port_id, project_id=port['tenant_id'])
|
||||||
device_owner = port_db.get('device_owner', '')
|
device_owner = port.get('device_owner', '')
|
||||||
if (device_owner not in [nl_constants.DEVICE_OWNER_ROUTER_INTF] and
|
if (device_owner not in [nl_constants.DEVICE_OWNER_ROUTER_INTF] and
|
||||||
not device_owner.startswith(
|
not device_owner.startswith(
|
||||||
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX)):
|
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX)):
|
||||||
@ -253,6 +153,8 @@ class FirewallPluginV2(
|
|||||||
self._is_supported_by_fw_l2_driver(context, port_id)):
|
self._is_supported_by_fw_l2_driver(context, port_id)):
|
||||||
raise exceptions.FirewallGroupPortNotSupported(port_id=port_id)
|
raise exceptions.FirewallGroupPortNotSupported(port_id=port_id)
|
||||||
|
|
||||||
|
# TODO(ethuleau): move that check in the driver. Each driver can have
|
||||||
|
# different support
|
||||||
def _is_supported_by_fw_l2_driver(self, context, port_id):
|
def _is_supported_by_fw_l2_driver(self, context, port_id):
|
||||||
"""Whether this port is supported by firewall l2 driver"""
|
"""Whether this port is supported by firewall l2 driver"""
|
||||||
|
|
||||||
@ -277,49 +179,80 @@ class FirewallPluginV2(
|
|||||||
LOG.warning("Doesn't support vif type %s", port[pb_def.VIF_TYPE])
|
LOG.warning("Doesn't support vif type %s", port[pb_def.VIF_TYPE])
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _check_no_need_pending(self, context, fwg_id, fwg_body):
|
def _validate_if_firewall_group_on_ports(self, context, firewall_group,
|
||||||
fwg_db = self._get_firewall_group(context, fwg_id)
|
id=None):
|
||||||
fwp_req_in = fwg_body.get('ingress_firewall_policy_id', None)
|
"""Validate if ports are not associated with any firewall_group.
|
||||||
fwp_req_eg = fwg_body.get('egress_firewall_policy_id', None)
|
|
||||||
|
|
||||||
if ((not fwg_db.ingress_firewall_policy_id and
|
If any of the ports in the list is already associated with
|
||||||
fwp_req_in is fwg_db.ingress_firewall_policy_id) and
|
a firewall group, raise an exception else just return.
|
||||||
(not fwg_db.egress_firewall_policy_id and
|
:param context: neutron context
|
||||||
fwp_req_eg is fwg_db.ingress_firewall_policy_id)):
|
:param fwg: firewall group to validate
|
||||||
return True
|
"""
|
||||||
return False
|
if 'ports' not in firewall_group or not firewall_group['ports']:
|
||||||
|
return
|
||||||
|
|
||||||
def _get_fwg_port_details(self, context, fwg_ports):
|
filters = {
|
||||||
"""Returns a dictionary list of port details. """
|
'tenant_id': [firewall_group['tenant_id']],
|
||||||
port_details = {}
|
'ports': firewall_group['ports'],
|
||||||
for port_id in fwg_ports:
|
}
|
||||||
port_db = self._core_plugin.get_port(context, port_id)
|
ports_in_use = set()
|
||||||
# Add more parameters below based on requirement.
|
for fwg in self.get_firewall_groups(context, filters=filters):
|
||||||
device_owner = port_db['device_owner']
|
if id is not None and fwg['id'] == id:
|
||||||
port_details[port_id] = {
|
continue
|
||||||
'device_owner': device_owner,
|
ports_in_use |= set(fwg.get('ports', [])) & \
|
||||||
'device': port_db['id'],
|
set(firewall_group['ports'])
|
||||||
'network_id': port_db['network_id'],
|
if ports_in_use:
|
||||||
'fixed_ips': port_db['fixed_ips'],
|
raise f_exc.FirewallGroupPortInUse(port_ids=list(ports_in_use))
|
||||||
'allowed_address_pairs':
|
|
||||||
port_db.get('allowed_address_pairs', []),
|
|
||||||
'port_security_enabled':
|
|
||||||
port_db.get('port_security_enabled', True),
|
|
||||||
'id': port_db['id']
|
|
||||||
}
|
|
||||||
if device_owner.startswith(
|
|
||||||
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX):
|
|
||||||
port_details[port_id].update(
|
|
||||||
{'host': port_db[pb_def.HOST_ID]})
|
|
||||||
return port_details
|
|
||||||
|
|
||||||
def get_project_id_from_port_id(self, context, port_id):
|
def _get_fwgs_with_policy(self, context, firewall_policy):
|
||||||
"""Returns an ID of project for specified port_id. """
|
"""List firewall group IDs which use a firewall policy
|
||||||
return self._core_plugin.get_port(context, port_id)['project_id']
|
|
||||||
|
List all firewall group IDs which have the given firewall policy as
|
||||||
|
ingress or egress.
|
||||||
|
:param context: neutron context
|
||||||
|
:param firewall_policy: firewall policy to filter
|
||||||
|
"""
|
||||||
|
filters = {
|
||||||
|
'tenant_id': [firewall_policy['tenant_id']],
|
||||||
|
'ingress_firewall_policy_id': [firewall_policy['id']],
|
||||||
|
}
|
||||||
|
ingress_fwp_ids = [fwg['id']
|
||||||
|
for fwg in self.get_firewall_groups(
|
||||||
|
context, filters=filters)]
|
||||||
|
|
||||||
|
filters = {
|
||||||
|
'tenant_id': [firewall_policy['tenant_id']],
|
||||||
|
'egress_firewall_policy_id': [firewall_policy['id']],
|
||||||
|
}
|
||||||
|
egress_fwp_ids = [fwg['id']
|
||||||
|
for fwg in self.get_firewall_groups(
|
||||||
|
context, filters=filters)]
|
||||||
|
|
||||||
|
return ingress_fwp_ids, egress_fwp_ids
|
||||||
|
|
||||||
|
def _get_policies_with_rule(self, context, firewall_rule):
|
||||||
|
filters = {
|
||||||
|
'tenant_id': [firewall_rule['tenant_id']],
|
||||||
|
'firewall_rules': [firewall_rule['id']],
|
||||||
|
}
|
||||||
|
return [fwp['id'] for fwp in self.get_firewall_policies(
|
||||||
|
context, filters=filters)]
|
||||||
|
|
||||||
|
def _validate_insert_remove_rule_request(self, rule_info):
|
||||||
|
"""Validate rule_info dict
|
||||||
|
|
||||||
|
Check that all mandatory fields are present, otherwise raise
|
||||||
|
proper exception.
|
||||||
|
"""
|
||||||
|
if not rule_info or 'firewall_rule_id' not in rule_info:
|
||||||
|
raise f_exc.FirewallRuleInfoMissing()
|
||||||
|
# Validator doesn't return anything if the check passes
|
||||||
|
if validators.validate_uuid(rule_info['firewall_rule_id']):
|
||||||
|
raise f_exc.FirewallRuleNotFound(
|
||||||
|
firewall_rule_id=rule_info['firewall_rule_id'])
|
||||||
|
|
||||||
@registry.receives(resources.PORT, [events.AFTER_UPDATE])
|
@registry.receives(resources.PORT, [events.AFTER_UPDATE])
|
||||||
def handle_update_port(self, resource, event, trigger, **kwargs):
|
def handle_update_port(self, resource, event, trigger, **kwargs):
|
||||||
|
|
||||||
updated_port = kwargs['port']
|
updated_port = kwargs['port']
|
||||||
if not updated_port['device_owner'].startswith(
|
if not updated_port['device_owner'].startswith(
|
||||||
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX):
|
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX):
|
||||||
@ -340,169 +273,145 @@ class FirewallPluginV2(
|
|||||||
return
|
return
|
||||||
|
|
||||||
project_id = updated_port['project_id']
|
project_id = updated_port['project_id']
|
||||||
LOG.debug("Try to associate port %s at %s", port_id, project_id)
|
fwgs = self.get_firewall_groups(
|
||||||
self.set_port_for_default_firewall_group(context, port_id, project_id)
|
context,
|
||||||
|
filters={
|
||||||
|
'tenant_id': [project_id],
|
||||||
|
'name': [fwaas_constants.DEFAULT_FWG],
|
||||||
|
},
|
||||||
|
fields=['id', 'ports'],
|
||||||
|
)
|
||||||
|
if len(fwgs) != 1:
|
||||||
|
# Cannot found default Firewall Group, abandon
|
||||||
|
LOG.warning("Cannot found default firewall group of project %s",
|
||||||
|
project_id)
|
||||||
|
return
|
||||||
|
default_fwg = fwgs[0]
|
||||||
|
|
||||||
|
# Add default firewall group to the port
|
||||||
|
port_ids = default_fwg.get('ports', []) + [port_id]
|
||||||
|
try:
|
||||||
|
self.update_firewall_group(context, default_fwg['id'],
|
||||||
|
{'firewall_group': {'ports': port_ids}})
|
||||||
|
except f_exc.FirewallGroupPortInUse:
|
||||||
|
LOG.warning("Port %s has been already associated with default "
|
||||||
|
"firewall group %s and skip association", port_id,
|
||||||
|
default_fwg['id'])
|
||||||
|
|
||||||
|
# Firewall Group
|
||||||
|
@log_helpers.log_method_call
|
||||||
def create_firewall_group(self, context, firewall_group):
|
def create_firewall_group(self, context, firewall_group):
|
||||||
LOG.debug("create_firewall_group() called")
|
firewall_group = firewall_group['firewall_group']
|
||||||
fwgrp = firewall_group['firewall_group']
|
ports = firewall_group.get('ports', [])
|
||||||
fwg_ports = fwgrp['ports']
|
|
||||||
|
|
||||||
if not fwg_ports:
|
self._validate_firewall_policies_for_firewall_group(context,
|
||||||
# no messaging to agent needed, and fw needs to go
|
firewall_group)
|
||||||
# to INACTIVE(no associated ports) state.
|
# Validate ports owner type and project
|
||||||
status = nl_constants.INACTIVE
|
self._validate_ports_for_firewall_group(context,
|
||||||
fwg = super(FirewallPluginV2, self).create_firewall_group(
|
firewall_group['tenant_id'],
|
||||||
context, firewall_group, status)
|
ports)
|
||||||
fwg['ports'] = []
|
|
||||||
return fwg
|
|
||||||
else:
|
|
||||||
# Validate ports
|
|
||||||
self._validate_ports_for_firewall_group(context,
|
|
||||||
firewall_group['firewall_group']['tenant_id'], fwg_ports)
|
|
||||||
|
|
||||||
if (not fwgrp['ingress_firewall_policy_id'] and
|
self._validate_if_firewall_group_on_ports(context, firewall_group)
|
||||||
not fwgrp['egress_firewall_policy_id']):
|
|
||||||
# No policy configured
|
|
||||||
status = nl_constants.INACTIVE
|
|
||||||
fwg = super(FirewallPluginV2, self).create_firewall_group(
|
|
||||||
context, firewall_group, status)
|
|
||||||
return fwg
|
|
||||||
|
|
||||||
fwg = super(FirewallPluginV2, self).create_firewall_group(
|
return self.driver.create_firewall_group(context, firewall_group)
|
||||||
context, firewall_group)
|
|
||||||
fwg['ports'] = fwg_ports
|
|
||||||
|
|
||||||
fwg_with_rules = (
|
|
||||||
self._make_firewall_group_dict_with_rules(context, fwg['id']))
|
|
||||||
|
|
||||||
fwg_with_rules['add-port-ids'] = fwg_ports
|
|
||||||
fwg_with_rules['del-port-ids'] = []
|
|
||||||
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
|
||||||
context, fwg_ports)
|
|
||||||
|
|
||||||
self.agent_rpc.create_firewall_group(context, fwg_with_rules)
|
|
||||||
|
|
||||||
return fwg
|
|
||||||
|
|
||||||
def update_firewall_group(self, context, id, firewall_group):
|
|
||||||
LOG.debug("update_firewall_group() called on firewall_group %s", id)
|
|
||||||
|
|
||||||
self._ensure_update_firewall_group(context, id)
|
|
||||||
|
|
||||||
# TODO(sridar): need closure on status when no policy associated.
|
|
||||||
fwg_current_ports = fwg_new_ports = self._get_ports_in_firewall_group(
|
|
||||||
context, id)
|
|
||||||
if 'ports' in firewall_group['firewall_group']:
|
|
||||||
fwg_new_ports = firewall_group['firewall_group']['ports']
|
|
||||||
if len(fwg_new_ports) > 0:
|
|
||||||
self._validate_ports_for_firewall_group(
|
|
||||||
context, context.project_id, fwg_new_ports)
|
|
||||||
|
|
||||||
if ((not fwg_new_ports and not fwg_current_ports) or
|
|
||||||
self._check_no_need_pending(context,
|
|
||||||
id, firewall_group['firewall_group'])):
|
|
||||||
# no messaging to agent needed, and we need to continue
|
|
||||||
# in INACTIVE state
|
|
||||||
firewall_group['firewall_group']['status'] = nl_constants.INACTIVE
|
|
||||||
fwg = super(FirewallPluginV2, self).update_firewall_group(
|
|
||||||
context, id, firewall_group)
|
|
||||||
if fwg_new_ports:
|
|
||||||
fwg['ports'] = fwg_new_ports
|
|
||||||
elif not fwg_new_ports and fwg_current_ports:
|
|
||||||
fwg['ports'] = fwg_current_ports
|
|
||||||
else:
|
|
||||||
fwg['ports'] = []
|
|
||||||
return fwg
|
|
||||||
else:
|
|
||||||
firewall_group['firewall_group']['status'] = (nl_constants.
|
|
||||||
PENDING_UPDATE)
|
|
||||||
fwg = super(FirewallPluginV2, self).update_firewall_group(
|
|
||||||
context, id, firewall_group)
|
|
||||||
fwg['ports'] = fwg_new_ports
|
|
||||||
|
|
||||||
fwg_with_rules = (
|
|
||||||
self._make_firewall_group_dict_with_rules(context, fwg['id']))
|
|
||||||
|
|
||||||
# determine ports to add fw to and del from
|
|
||||||
fwg_with_rules['add-port-ids'] = fwg_new_ports
|
|
||||||
fwg_with_rules['del-port-ids'] = list(
|
|
||||||
set(fwg_current_ports).difference(set(fwg_new_ports)))
|
|
||||||
|
|
||||||
# last-port drives agent to ack with status to set state to INACTIVE
|
|
||||||
fwg_with_rules['last-port'] = not fwg_new_ports
|
|
||||||
|
|
||||||
LOG.debug("update_firewall_group %s: Add Ports: %s, Del Ports: %s",
|
|
||||||
fwg['id'],
|
|
||||||
fwg_with_rules['add-port-ids'],
|
|
||||||
fwg_with_rules['del-port-ids'])
|
|
||||||
|
|
||||||
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
|
||||||
context, fwg_with_rules['del-port-ids'])
|
|
||||||
fwg_with_rules['port_details'].update(self._get_fwg_port_details(
|
|
||||||
context, fwg_with_rules['add-port-ids']))
|
|
||||||
self.agent_rpc.update_firewall_group(context, fwg_with_rules)
|
|
||||||
|
|
||||||
return fwg
|
|
||||||
|
|
||||||
def delete_db_firewall_group_object(self, context, id):
|
|
||||||
super(FirewallPluginV2, self).delete_firewall_group(context, id)
|
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
def delete_firewall_group(self, context, id):
|
def delete_firewall_group(self, context, id):
|
||||||
LOG.debug("delete_firewall_group() called on firewall_group %s", id)
|
# if no such group exists -> don't raise an exception according to
|
||||||
|
# 80fe2ba1, return None
|
||||||
|
try:
|
||||||
|
fwg = self.get_firewall_group(context, id)
|
||||||
|
except f_exc.FirewallGroupNotFound:
|
||||||
|
return
|
||||||
|
|
||||||
fwg_db = self._get_firewall_group(context, id)
|
if fwg['status'] == nl_constants.ACTIVE:
|
||||||
|
|
||||||
if fwg_db['status'] == nl_constants.ACTIVE:
|
|
||||||
raise f_exc.FirewallGroupInUse(firewall_id=id)
|
raise f_exc.FirewallGroupInUse(firewall_id=id)
|
||||||
|
|
||||||
fwg_with_rules = (
|
self.driver.delete_firewall_group(context, id)
|
||||||
self._make_firewall_group_dict_with_rules(context, id))
|
|
||||||
fwg_with_rules['del-port-ids'] = self._get_ports_in_firewall_group(
|
|
||||||
context, id)
|
|
||||||
fwg_with_rules['add-port-ids'] = []
|
|
||||||
if not fwg_with_rules['del-port-ids']:
|
|
||||||
# no ports, no need to talk to the agent
|
|
||||||
self.delete_db_firewall_group_object(context, id)
|
|
||||||
else:
|
|
||||||
status = {"firewall_group": {"status":
|
|
||||||
nl_constants.PENDING_DELETE}}
|
|
||||||
super(FirewallPluginV2, self).update_firewall_group(
|
|
||||||
context, id, status)
|
|
||||||
# Reflect state change in fwg_with_rules
|
|
||||||
fwg_with_rules['status'] = status['firewall_group']['status']
|
|
||||||
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
|
||||||
context, fwg_with_rules['del-port-ids'])
|
|
||||||
self.agent_rpc.delete_firewall_group(context, fwg_with_rules)
|
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_group(self, context, id, fields=None):
|
||||||
|
return self.driver.get_firewall_group(context, id, fields=fields)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_groups(self, context, filters=None, fields=None):
|
||||||
|
return self.driver.get_firewall_groups(context, filters, fields)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def update_firewall_group(self, context, id, firewall_group):
|
||||||
|
firewall_group = firewall_group['firewall_group']
|
||||||
|
ports = firewall_group.get('ports', [])
|
||||||
|
|
||||||
|
old_firewall_group = self._ensure_update_firewall_group(context, id)
|
||||||
|
firewall_group['tenant_id'] = old_firewall_group['tenant_id']
|
||||||
|
|
||||||
|
self._validate_firewall_policies_for_firewall_group(context,
|
||||||
|
firewall_group)
|
||||||
|
# Validate ports owner type and project
|
||||||
|
self._validate_ports_for_firewall_group(context,
|
||||||
|
firewall_group['tenant_id'],
|
||||||
|
ports)
|
||||||
|
self._validate_if_firewall_group_on_ports(context, firewall_group,
|
||||||
|
id=id)
|
||||||
|
|
||||||
|
return self.driver.update_firewall_group(context, id, firewall_group)
|
||||||
|
|
||||||
|
# Firewall Policy
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def create_firewall_policy(self, context, firewall_policy):
|
||||||
|
firewall_policy = firewall_policy['firewall_policy']
|
||||||
|
return self.driver.create_firewall_policy(context, firewall_policy)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def delete_firewall_policy(self, context, id):
|
||||||
|
self.driver.delete_firewall_policy(context, id)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_policy(self, context, id, fields=None):
|
||||||
|
return self.driver.get_firewall_policy(context, id, fields)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_policies(self, context, filters=None, fields=None):
|
||||||
|
return self.driver.get_firewall_policies(context, filters, fields)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
def update_firewall_policy(self, context, id, firewall_policy):
|
def update_firewall_policy(self, context, id, firewall_policy):
|
||||||
LOG.debug("update_firewall_policy() called")
|
firewall_policy = firewall_policy['firewall_policy']
|
||||||
self._ensure_update_firewall_policy(context, id)
|
self._ensure_update_firewall_policy(context, id)
|
||||||
fwp = super(FirewallPluginV2,
|
return self.driver.update_firewall_policy(context, id, firewall_policy)
|
||||||
self).update_firewall_policy(context, id, firewall_policy)
|
|
||||||
self._rpc_update_firewall_policy(context, id)
|
|
||||||
return fwp
|
|
||||||
|
|
||||||
|
# Firewall Rule
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def create_firewall_rule(self, context, firewall_rule):
|
||||||
|
firewall_rule = firewall_rule['firewall_rule']
|
||||||
|
return self.driver.create_firewall_rule(context, firewall_rule)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def delete_firewall_rule(self, context, id):
|
||||||
|
self.driver.delete_firewall_rule(context, id)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_rule(self, context, id, fields=None):
|
||||||
|
return self.driver.get_firewall_rule(context, id, fields)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_rules(self, context, filters=None, fields=None):
|
||||||
|
return self.driver.get_firewall_rules(context, filters, fields)
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
def update_firewall_rule(self, context, id, firewall_rule):
|
def update_firewall_rule(self, context, id, firewall_rule):
|
||||||
LOG.debug("update_firewall_rule() called")
|
firewall_rule = firewall_rule['firewall_rule']
|
||||||
self._ensure_update_firewall_rule(context, id)
|
self._ensure_update_firewall_rule(context, id)
|
||||||
fwr = super(FirewallPluginV2,
|
return self.driver.update_firewall_rule(context, id, firewall_rule)
|
||||||
self).update_firewall_rule(context, id, firewall_rule)
|
|
||||||
fwp_ids = self._get_policies_with_rule(context, id)
|
|
||||||
for fwp_id in fwp_ids:
|
|
||||||
self._rpc_update_firewall_policy(context, fwp_id)
|
|
||||||
return fwr
|
|
||||||
|
|
||||||
def insert_rule(self, context, id, rule_info):
|
@log_helpers.log_method_call
|
||||||
LOG.debug("insert_rule() called")
|
def insert_rule(self, context, policy_id, rule_info):
|
||||||
self._ensure_update_firewall_policy(context, id)
|
self._ensure_update_firewall_policy(context, policy_id)
|
||||||
fwp = super(FirewallPluginV2, self).insert_rule(context, id, rule_info)
|
self._validate_insert_remove_rule_request(rule_info)
|
||||||
self._rpc_update_firewall_policy(context, id)
|
return self.driver.insert_rule(context, policy_id, rule_info)
|
||||||
return fwp
|
|
||||||
|
|
||||||
def remove_rule(self, context, id, rule_info):
|
@log_helpers.log_method_call
|
||||||
LOG.debug("remove_rule() called")
|
def remove_rule(self, context, policy_id, rule_info):
|
||||||
self._ensure_update_firewall_policy(context, id)
|
self._ensure_update_firewall_policy(context, policy_id)
|
||||||
fwp = super(FirewallPluginV2, self).remove_rule(context, id, rule_info)
|
self._validate_insert_remove_rule_request(rule_info)
|
||||||
self._rpc_update_firewall_policy(context, id)
|
return self.driver.remove_rule(context, policy_id, rule_info)
|
||||||
return fwp
|
|
||||||
|
355
neutron_fwaas/services/firewall/service_drivers/agents/agents.py
Normal file
355
neutron_fwaas/services/firewall/service_drivers/agents/agents.py
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from neutron.common import rpc as neutron_rpc
|
||||||
|
from neutron_lib.api.definitions import portbindings as pb_def
|
||||||
|
from neutron_lib import constants as nl_constants
|
||||||
|
from neutron_lib import context as neutron_context
|
||||||
|
from neutron_lib.exceptions import firewall_v2 as f_exc
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import helpers as log_helpers
|
||||||
|
from oslo_log import log as logging
|
||||||
|
import oslo_messaging
|
||||||
|
|
||||||
|
from neutron_fwaas.common import fwaas_constants as constants
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers import driver_api
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class FirewallAgentCallbacks(object):
|
||||||
|
target = oslo_messaging.Target(version='1.0')
|
||||||
|
|
||||||
|
def __init__(self, firewall_db):
|
||||||
|
self.firewall_db = firewall_db
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def set_firewall_group_status(self, context, fwg_id, status, **kwargs):
|
||||||
|
"""Agent uses this to set a firewall_group's status."""
|
||||||
|
# Sanitize status first
|
||||||
|
if status in (nl_constants.ACTIVE, nl_constants.DOWN,
|
||||||
|
nl_constants.INACTIVE):
|
||||||
|
to_update = status
|
||||||
|
else:
|
||||||
|
to_update = nl_constants.ERROR
|
||||||
|
# ignore changing status if firewall_group expects to be deleted
|
||||||
|
# That case means that while some pending operation has been
|
||||||
|
# performed on the backend, neutron server received delete request
|
||||||
|
# and changed firewall status to PENDING_DELETE
|
||||||
|
updated = self.firewall_db.update_firewall_group_status(
|
||||||
|
context, fwg_id, to_update, not_in=(nl_constants.PENDING_DELETE,))
|
||||||
|
if updated:
|
||||||
|
LOG.debug("firewall %s status set: %s", fwg_id, to_update)
|
||||||
|
return updated and to_update != nl_constants.ERROR
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def firewall_group_deleted(self, context, fwg_id, **kwargs):
|
||||||
|
"""Agent uses this to indicate firewall is deleted."""
|
||||||
|
try:
|
||||||
|
fwg = self.firewall_db.get_firewall_group(context, fwg_id)
|
||||||
|
# allow to delete firewalls in ERROR state
|
||||||
|
if fwg['status'] in (nl_constants.PENDING_DELETE,
|
||||||
|
nl_constants.ERROR):
|
||||||
|
self.firewall_db.delete_firewall_group(context, fwg_id)
|
||||||
|
return True
|
||||||
|
LOG.warning('Firewall %(fwg)s unexpectedly deleted by agent, '
|
||||||
|
'status was %(status)s',
|
||||||
|
{'fwg': fwg_id, 'status': fwg['status']})
|
||||||
|
fwg['status'] = nl_constants.ERROR
|
||||||
|
self.firewall_db.update_firewall_group(context, fwg_id, fwg)
|
||||||
|
return False
|
||||||
|
except f_exc.FirewallGroupNotFound:
|
||||||
|
LOG.info('Firewall group %s already deleted', fwg_id)
|
||||||
|
return True
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_groups_for_project(self, context, **kwargs):
|
||||||
|
"""Gets all firewall_groups and rules on a project."""
|
||||||
|
fwg_list = []
|
||||||
|
for fwg in self.firewall_db.get_firewall_groups(context):
|
||||||
|
fwg_with_rules =\
|
||||||
|
self.firewall_db.make_firewall_group_dict_with_rules(
|
||||||
|
context, fwg['id'])
|
||||||
|
if fwg['status'] == nl_constants.PENDING_DELETE:
|
||||||
|
fwg_with_rules['add-port-ids'] = []
|
||||||
|
fwg_with_rules['del-port-ids'] = (
|
||||||
|
self.firewall_db.get_ports_in_firewall_group(
|
||||||
|
context, fwg['id']))
|
||||||
|
else:
|
||||||
|
fwg_with_rules['add-port-ids'] = (
|
||||||
|
self.firewall_db.get_ports_in_firewall_group(
|
||||||
|
context, fwg['id']))
|
||||||
|
fwg_with_rules['del-port-ids'] = []
|
||||||
|
fwg_list.append(fwg_with_rules)
|
||||||
|
return fwg_list
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_projects_with_firewall_groups(self, context, **kwargs):
|
||||||
|
"""Get all projects that have firewall_groups."""
|
||||||
|
ctx = neutron_context.get_admin_context()
|
||||||
|
fwg_list = self.firewall_db.get_firewall_groups(ctx)
|
||||||
|
fwg_project_list = list(set(fwg['tenant_id'] for fwg in fwg_list))
|
||||||
|
return fwg_project_list
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def get_firewall_group_for_port(self, context, **kwargs):
|
||||||
|
"""Get firewall_group is associated with a port."""
|
||||||
|
ctx = context.elevated()
|
||||||
|
# Only one Firewall Group can be associated to a port at a time
|
||||||
|
fwg_port_binding = self.firewall_db.get_firewall_groups(
|
||||||
|
ctx, filters={'ports': [kwargs.get('port_id')]})
|
||||||
|
if len(fwg_port_binding) != 1:
|
||||||
|
return
|
||||||
|
fwg = fwg_port_binding[0]
|
||||||
|
|
||||||
|
fwg['ingress_rule_list'] = []
|
||||||
|
for rule_id in self.firewall_db.get_firewall_policy(
|
||||||
|
context, fwg['ingress_firewall_policy_id'],
|
||||||
|
fields=['firewall_rules'])['firewall_rules']:
|
||||||
|
fwg['ingress_rule_list'].append(
|
||||||
|
self.firewall_db.get_firewall_rule(context, rule_id))
|
||||||
|
fwg['egress_rule_list'] = []
|
||||||
|
for rule_id in self.firewall_db.get_firewall_policy(
|
||||||
|
context, fwg['egress_firewall_policy_id'],
|
||||||
|
fields=['firewall_rules'])['firewall_rules']:
|
||||||
|
fwg['egress_rule_list'].append(
|
||||||
|
self.firewall_db.get_firewall_rule(context, rule_id))
|
||||||
|
return fwg
|
||||||
|
|
||||||
|
|
||||||
|
class FirewallAgentApi(object):
|
||||||
|
"""Plugin side of plugin to agent RPC API"""
|
||||||
|
|
||||||
|
def __init__(self, topic, host):
|
||||||
|
self.host = host
|
||||||
|
target = oslo_messaging.Target(topic=topic, version='1.0')
|
||||||
|
self.client = neutron_rpc.get_client(target)
|
||||||
|
|
||||||
|
def create_firewall_group(self, context, firewall_group):
|
||||||
|
cctxt = self.client.prepare(fanout=True)
|
||||||
|
cctxt.cast(context, 'create_firewall_group',
|
||||||
|
firewall_group=firewall_group, host=self.host)
|
||||||
|
|
||||||
|
def update_firewall_group(self, context, firewall_group):
|
||||||
|
cctxt = self.client.prepare(fanout=True)
|
||||||
|
cctxt.cast(context, 'update_firewall_group',
|
||||||
|
firewall_group=firewall_group, host=self.host)
|
||||||
|
|
||||||
|
def delete_firewall_group(self, context, firewall_group):
|
||||||
|
cctxt = self.client.prepare(fanout=True)
|
||||||
|
cctxt.cast(context, 'delete_firewall_group',
|
||||||
|
firewall_group=firewall_group, host=self.host)
|
||||||
|
|
||||||
|
|
||||||
|
class FirewallAgentDriver(driver_api.FirewallDriverDB):
|
||||||
|
"""Firewall driver to implement agent messages and callback methods
|
||||||
|
|
||||||
|
Implement RPC Firewall v2 API and callback methods for agents based on
|
||||||
|
Neutron DB model.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, service_plugin):
|
||||||
|
super(FirewallAgentDriver, self).__init__(service_plugin)
|
||||||
|
self.agent_rpc = FirewallAgentApi(constants.FW_AGENT, cfg.CONF.host)
|
||||||
|
self.start_rpc_listeners()
|
||||||
|
|
||||||
|
def start_rpc_listeners(self):
|
||||||
|
self.endpoints = [FirewallAgentCallbacks(self.firewall_db)]
|
||||||
|
|
||||||
|
self.rpc_connection = neutron_rpc.Connection()
|
||||||
|
self.rpc_connection.create_consumer(constants.FIREWALL_PLUGIN,
|
||||||
|
self.endpoints, fanout=False)
|
||||||
|
self.rpc_connection.consume_in_threads()
|
||||||
|
|
||||||
|
def _rpc_update_firewall_group(self, context, fwg_id):
|
||||||
|
status_update = {"status": nl_constants.PENDING_UPDATE}
|
||||||
|
self.update_firewall_group(context, fwg_id, status_update)
|
||||||
|
fwg_with_rules = self.firewall_db.make_firewall_group_dict_with_rules(
|
||||||
|
context, fwg_id)
|
||||||
|
# this is triggered on an update to fwg rule or policy, no
|
||||||
|
# change in associated ports.
|
||||||
|
fwg_with_rules['add-port-ids'] = \
|
||||||
|
self.firewall_db.get_ports_in_firewall_group(context, fwg_id)
|
||||||
|
fwg_with_rules['del-port-ids'] = []
|
||||||
|
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
||||||
|
context, fwg_with_rules['add-port-ids'])
|
||||||
|
self.agent_rpc.update_firewall_group(context, fwg_with_rules)
|
||||||
|
|
||||||
|
def _rpc_update_firewall_policy(self, context, firewall_policy_id):
|
||||||
|
firewall_policy = self.get_firewall_policy(context, firewall_policy_id)
|
||||||
|
if firewall_policy:
|
||||||
|
ing_fwg_ids, eg_fwg_ids = self.firewall_db.get_fwgs_with_policy(
|
||||||
|
context, firewall_policy_id)
|
||||||
|
for fwg_id in list(set(ing_fwg_ids + eg_fwg_ids)):
|
||||||
|
self._rpc_update_firewall_group(context, fwg_id)
|
||||||
|
|
||||||
|
def _get_fwg_port_details(self, context, fwg_ports):
|
||||||
|
"""Returns a dictionary list of port details. """
|
||||||
|
port_details = {}
|
||||||
|
for port_id in fwg_ports:
|
||||||
|
port_db = self._core_plugin.get_port(context, port_id)
|
||||||
|
# Add more parameters below based on requirement.
|
||||||
|
device_owner = port_db['device_owner']
|
||||||
|
port_details[port_id] = {
|
||||||
|
'device_owner': device_owner,
|
||||||
|
'device': port_db['id'],
|
||||||
|
'network_id': port_db['network_id'],
|
||||||
|
'fixed_ips': port_db['fixed_ips'],
|
||||||
|
'allowed_address_pairs':
|
||||||
|
port_db.get('allowed_address_pairs', []),
|
||||||
|
'port_security_enabled':
|
||||||
|
port_db.get('port_security_enabled', True),
|
||||||
|
'id': port_db['id'],
|
||||||
|
'status': port_db['status'],
|
||||||
|
}
|
||||||
|
if device_owner.startswith(
|
||||||
|
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX):
|
||||||
|
port_details[port_id].update(
|
||||||
|
{'host': port_db[pb_def.HOST_ID]})
|
||||||
|
return port_details
|
||||||
|
|
||||||
|
def create_firewall_group_precommit(self, context, firewall_group):
|
||||||
|
ports = firewall_group['ports']
|
||||||
|
|
||||||
|
if (not ports or (not firewall_group['ingress_firewall_policy_id'] and
|
||||||
|
not firewall_group['egress_firewall_policy_id'])):
|
||||||
|
# no messaging to agent needed and fw needs to go to INACTIVE state
|
||||||
|
# as no associated ports and/or no policy configured.
|
||||||
|
status = nl_constants.INACTIVE
|
||||||
|
else:
|
||||||
|
status = (nl_constants.CREATED if cfg.CONF.router_distributed
|
||||||
|
else nl_constants.PENDING_CREATE)
|
||||||
|
firewall_group['status'] = status
|
||||||
|
|
||||||
|
def create_firewall_group_postcommit(self, context, firewall_group):
|
||||||
|
if firewall_group['status'] != nl_constants.INACTIVE:
|
||||||
|
fwg_with_rules =\
|
||||||
|
self.firewall_db.make_firewall_group_dict_with_rules(
|
||||||
|
context, firewall_group['id'])
|
||||||
|
fwg_with_rules['add-port-ids'] = firewall_group['ports']
|
||||||
|
fwg_with_rules['del-ports-id'] = []
|
||||||
|
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
||||||
|
context, firewall_group['ports'])
|
||||||
|
self.agent_rpc.create_firewall_group(context, fwg_with_rules)
|
||||||
|
|
||||||
|
def delete_firewall_group_precommit(self, context, firewall_group):
|
||||||
|
if firewall_group['status'] == nl_constants.ACTIVE:
|
||||||
|
raise f_exc.FirewallGroupInUse(firewall_id=firewall_group['id'])
|
||||||
|
elif firewall_group['status'] != nl_constants.INACTIVE:
|
||||||
|
# Firewall group is in inconsistent state, remove it
|
||||||
|
return
|
||||||
|
if not firewall_group['ports']:
|
||||||
|
# No associated port, can safety remove it
|
||||||
|
return
|
||||||
|
|
||||||
|
# Need to prevent agent to delete the firewall group before delete it
|
||||||
|
self.firewall_db.update_firewall_group_status(
|
||||||
|
context, firewall_group['id'], nl_constants.PENDING_DELETE)
|
||||||
|
firewall_group['status'] = nl_constants.PENDING_DELETE
|
||||||
|
|
||||||
|
fwg_with_rules = self.firewall_db.make_firewall_group_dict_with_rules(
|
||||||
|
context, firewall_group['id'])
|
||||||
|
fwg_with_rules['del-port-ids'] = firewall_group['ports']
|
||||||
|
fwg_with_rules['add-port-ids'] = []
|
||||||
|
# Reflect state change in fwg_with_rules
|
||||||
|
fwg_with_rules['status'] = nl_constants.PENDING_DELETE
|
||||||
|
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
||||||
|
context, fwg_with_rules['del-port-ids'])
|
||||||
|
self.agent_rpc.delete_firewall_group(context, fwg_with_rules)
|
||||||
|
|
||||||
|
def _need_pending_update(self, old_firewall_group, new_firewall_group):
|
||||||
|
port_updated = (set(new_firewall_group['ports']) !=
|
||||||
|
set(old_firewall_group['ports']))
|
||||||
|
policies_updated = (
|
||||||
|
new_firewall_group['ingress_firewall_policy_id'] !=
|
||||||
|
old_firewall_group['ingress_firewall_policy_id'] or
|
||||||
|
new_firewall_group['egress_firewall_policy_id'] !=
|
||||||
|
old_firewall_group['egress_firewall_policy_id']
|
||||||
|
)
|
||||||
|
if (port_updated and
|
||||||
|
(new_firewall_group['ingress_firewall_policy_id'] or
|
||||||
|
new_firewall_group['egress_firewall_policy_id'])):
|
||||||
|
return True
|
||||||
|
if policies_updated and new_firewall_group['ports']:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def update_firewall_group_precommit(self, context, old_firewall_group,
|
||||||
|
new_firewall_group):
|
||||||
|
if self._need_pending_update(old_firewall_group, new_firewall_group):
|
||||||
|
new_firewall_group['status'] = nl_constants.PENDING_UPDATE
|
||||||
|
|
||||||
|
def update_firewall_group_postcommit(self, context, old_firewall_group,
|
||||||
|
new_firewall_group):
|
||||||
|
if not self._need_pending_update(old_firewall_group,
|
||||||
|
new_firewall_group):
|
||||||
|
return
|
||||||
|
|
||||||
|
fwg_with_rules = self.firewall_db.make_firewall_group_dict_with_rules(
|
||||||
|
context, new_firewall_group['id'])
|
||||||
|
|
||||||
|
# determine ports to add fw to and del from
|
||||||
|
fwg_with_rules['add-port-ids'] = list(
|
||||||
|
set(new_firewall_group['ports']) - set(old_firewall_group['ports'])
|
||||||
|
)
|
||||||
|
fwg_with_rules['del-port-ids'] = list(
|
||||||
|
set(old_firewall_group['ports']) - set(new_firewall_group['ports'])
|
||||||
|
)
|
||||||
|
|
||||||
|
# last-port drives agent to ack with status to set state to INACTIVE
|
||||||
|
fwg_with_rules['last-port'] = not (
|
||||||
|
set(new_firewall_group['ports']) - set(old_firewall_group['ports'])
|
||||||
|
)
|
||||||
|
|
||||||
|
LOG.debug("update_firewall_group %s: Add Ports: %s, Del Ports: %s",
|
||||||
|
new_firewall_group['id'],
|
||||||
|
fwg_with_rules['add-port-ids'],
|
||||||
|
fwg_with_rules['del-port-ids'])
|
||||||
|
|
||||||
|
fwg_with_rules['port_details'] = self._get_fwg_port_details(
|
||||||
|
context, fwg_with_rules['del-port-ids'])
|
||||||
|
fwg_with_rules['port_details'].update(self._get_fwg_port_details(
|
||||||
|
context, fwg_with_rules['add-port-ids']))
|
||||||
|
|
||||||
|
if (new_firewall_group['name'] == constants.DEFAULT_FWG and
|
||||||
|
len(fwg_with_rules['add-port-ids']) == 1 and
|
||||||
|
not fwg_with_rules['del-port-ids']):
|
||||||
|
port_id = fwg_with_rules['add-port-ids'][0]
|
||||||
|
if (fwg_with_rules['port_details'][port_id].get('status') !=
|
||||||
|
nl_constants.ACTIVE):
|
||||||
|
# If port not yet active, just associate to default firewall
|
||||||
|
# group. When agent will set it to UP, it'll found FG
|
||||||
|
# association and enforce default policies
|
||||||
|
return
|
||||||
|
# Warn agents Firewall Group port list updated
|
||||||
|
self.agent_rpc.update_firewall_group(context, fwg_with_rules)
|
||||||
|
|
||||||
|
def update_firewall_policy_postcommit(self, context, old_firewall_policy,
|
||||||
|
new_firewall_group):
|
||||||
|
self._rpc_update_firewall_policy(context, new_firewall_group['id'])
|
||||||
|
|
||||||
|
def update_firewall_rule_postcommit(self, context, old_firewall_rule,
|
||||||
|
new_firewall_rule):
|
||||||
|
firewall_policy_ids = self.firewall_db.get_policies_with_rule(
|
||||||
|
context, new_firewall_rule['id'])
|
||||||
|
for firewall_policy_id in firewall_policy_ids:
|
||||||
|
self._rpc_update_firewall_policy(context, firewall_policy_id)
|
||||||
|
|
||||||
|
def insert_rule_postcommit(self, context, policy_id, rule_info):
|
||||||
|
self._rpc_update_firewall_policy(context, policy_id)
|
||||||
|
|
||||||
|
def remove_rule_postcommit(self, context, policy_id, rule_info):
|
||||||
|
self._rpc_update_firewall_policy(context, policy_id)
|
@ -29,7 +29,7 @@ def load_and_init_conntrack_driver(*args, **kwargs):
|
|||||||
driver = cfg.CONF.fwaas.conntrack_driver
|
driver = cfg.CONF.fwaas.conntrack_driver
|
||||||
try:
|
try:
|
||||||
conntrack_driver_cls = runtime.load_class_by_alias_or_classname(
|
conntrack_driver_cls = runtime.load_class_by_alias_or_classname(
|
||||||
'neutron_fwaas.services.firewall.drivers.linux', driver)
|
'neutron.agent.l3.firewall_drivers', driver)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
LOG.exception("Driver '%s' not found.", driver)
|
LOG.exception("Driver '%s' not found.", driver)
|
@ -20,8 +20,10 @@ from neutron_lib.exceptions import firewall_v1 as f_exc
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants as f_const
|
from neutron_fwaas.common import fwaas_constants as f_const
|
||||||
from neutron_fwaas.services.firewall.drivers import conntrack_base
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
|
||||||
from neutron_fwaas.services.firewall.drivers import fwaas_base
|
conntrack_base
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
|
||||||
|
fwaas_base
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
@ -19,8 +19,10 @@ from neutron_lib import constants
|
|||||||
from neutron_lib.exceptions import firewall_v2 as fw_ext
|
from neutron_lib.exceptions import firewall_v2 as fw_ext
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers import conntrack_base
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
|
||||||
from neutron_fwaas.services.firewall.drivers import fwaas_base_v2
|
conntrack_base
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
|
||||||
|
fwaas_base_v2
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
FWAAS_DRIVER_NAME = 'Fwaas iptables driver'
|
FWAAS_DRIVER_NAME = 'Fwaas iptables driver'
|
@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
from oslo_log import helpers as log_helpers
|
from oslo_log import helpers as log_helpers
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2 import driver_base
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2\
|
||||||
|
import driver_base
|
||||||
|
|
||||||
|
|
||||||
class NoopFirewallL2Driver(driver_base.FirewallL2DriverBase):
|
class NoopFirewallL2Driver(driver_base.FirewallL2DriverBase):
|
@ -13,7 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
import firewall
|
openvswitch_firewall import firewall
|
||||||
|
|
||||||
OVSFirewallDriver = firewall.OVSFirewallDriver
|
OVSFirewallDriver = firewall.OVSFirewallDriver
|
@ -24,13 +24,14 @@ from neutron.common import constants
|
|||||||
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \
|
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \
|
||||||
as ovs_consts
|
as ovs_consts
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2 import driver_base
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2\
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
import driver_base
|
||||||
import constants as fwaas_ovs_consts
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
openvswitch_firewall import constants as fwaas_ovs_consts
|
||||||
import exceptions
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
openvswitch_firewall import exceptions
|
||||||
import rules
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
|
openvswitch_firewall import rules
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -14,14 +14,15 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
from neutron_lib import constants as n_consts
|
|
||||||
from oslo_log import log as logging
|
|
||||||
|
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \
|
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \
|
||||||
as ovs_consts
|
as ovs_consts
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_lib import constants as n_consts
|
||||||
import constants as fwaas_ovs_consts
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
|
openvswitch_firewall import constants as fwaas_ovs_consts
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
@ -17,8 +17,8 @@ from neutron.agent.linux import utils as linux_utils
|
|||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers import conntrack_base
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
|
||||||
|
conntrack_base
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -17,7 +17,8 @@ from neutron_lib import constants
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron_fwaas.privileged import netlink_lib as nl_lib
|
from neutron_fwaas.privileged import netlink_lib as nl_lib
|
||||||
from neutron_fwaas.services.firewall.drivers import conntrack_base
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
|
||||||
|
conntrack_base
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -28,7 +28,8 @@ from neutron_lib.utils import net as nl_net
|
|||||||
|
|
||||||
from neutron_fwaas._i18n import _
|
from neutron_fwaas._i18n import _
|
||||||
from neutron_fwaas.common import fwaas_constants as consts
|
from neutron_fwaas.common import fwaas_constants as consts
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
from neutron_fwaas.services.firewall.service_drivers.agents import\
|
||||||
|
firewall_agent_api as api
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -24,8 +24,10 @@ from oslo_log import log as logging
|
|||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants
|
from neutron_fwaas.common import fwaas_constants
|
||||||
from neutron_fwaas.common import resources as f_resources
|
from neutron_fwaas.common import resources as f_resources
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
from neutron_fwaas.services.firewall.service_drivers.agents \
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_service
|
import firewall_agent_api as api
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents \
|
||||||
|
import firewall_service
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -25,8 +25,10 @@ from oslo_log import log as logging
|
|||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants
|
from neutron_fwaas.common import fwaas_constants
|
||||||
from neutron_fwaas.common import resources as f_resources
|
from neutron_fwaas.common import resources as f_resources
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
from neutron_fwaas.services.firewall.service_drivers.agents import\
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_service
|
firewall_agent_api as api
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents import\
|
||||||
|
firewall_service
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
435
neutron_fwaas/services/firewall/service_drivers/driver_api.py
Normal file
435
neutron_fwaas/services/firewall/service_drivers/driver_api.py
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
# Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
|
||||||
|
# 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 abc
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
from neutron_lib import constants as nl_constants
|
||||||
|
from neutron_lib.plugins import directory
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from neutron_fwaas.db.firewall.v2 import firewall_db_v2
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class FirewallDriver(object):
|
||||||
|
"""Firewall v2 interface for driver
|
||||||
|
|
||||||
|
That driver interface does not persist Firewall v2 data in any database.
|
||||||
|
The driver needs to do it by itself.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, service_plugin):
|
||||||
|
self.service_plugin = service_plugin
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _core_plugin(self):
|
||||||
|
return directory.get_plugin()
|
||||||
|
|
||||||
|
# Firewall Group
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_group(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_group(self, context, id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_group(self, context, id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_groups(self, context, filters=None, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_group(self, context, id, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Firewall Policy
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_policy(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_policy(self, context, id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_policy(self, context, id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_policies(self, context, filters=None, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_policy(self, context, id, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Firewall Rule
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_rule(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_rule(self, context, id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_rule(self, context, id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_firewall_rules(self, context, filters=None, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_rule(self, context, id, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def insert_rule(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def remove_rule(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class FirewallDriverDBMixin(FirewallDriver):
|
||||||
|
"""FirewallDriverDB mixin to provision the database on behalf of the driver
|
||||||
|
|
||||||
|
That driver interface persists Firewall data in its database and forwards
|
||||||
|
the result to pre and post commit methods.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(FirewallDriverDBMixin, self).__init__(*args, **kwargs)
|
||||||
|
self.firewall_db = firewall_db_v2.FirewallPluginDb()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _update_resource_status(context, resource_type, resource_dict):
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
context.session.query(resource_type).\
|
||||||
|
filter_by(id=resource_dict['id']).\
|
||||||
|
update({'status': resource_dict['status']})
|
||||||
|
|
||||||
|
# Firewall Group
|
||||||
|
def create_firewall_group(self, context, firewall_group):
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
firewall_group = self.firewall_db.create_firewall_group(
|
||||||
|
context, firewall_group)
|
||||||
|
self.create_firewall_group_precommit(context, firewall_group)
|
||||||
|
self._update_resource_status(context, firewall_db_v2.FirewallGroup,
|
||||||
|
firewall_group)
|
||||||
|
self.create_firewall_group_postcommit(context, firewall_group)
|
||||||
|
return firewall_group
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_group_precommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_group_postcommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_group(self, context, id):
|
||||||
|
firewall_group = self.firewall_db.get_firewall_group(context, id)
|
||||||
|
if firewall_group['status'] == nl_constants.PENDING_DELETE:
|
||||||
|
firewall_group['status'] = nl_constants.ERROR
|
||||||
|
self.delete_firewall_group_precommit(context, firewall_group)
|
||||||
|
if firewall_group['status'] != nl_constants.PENDING_DELETE:
|
||||||
|
# lets driver deleting firewall group later
|
||||||
|
self.firewall_db.delete_firewall_group(context, id)
|
||||||
|
self.delete_firewall_group_postcommit(context, firewall_group)
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_group_precommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_group_postcommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_firewall_group(self, context, id, fields=None):
|
||||||
|
return self.firewall_db.get_firewall_group(context, id, fields=fields)
|
||||||
|
|
||||||
|
def get_firewall_groups(self, context, filters=None, fields=None):
|
||||||
|
return self.firewall_db.get_firewall_groups(context, filters, fields)
|
||||||
|
|
||||||
|
def update_firewall_group(self, context, id, firewall_group_delta):
|
||||||
|
old_firewall_group = self.firewall_db.get_firewall_group(context, id)
|
||||||
|
new_firewall_group = copy.deepcopy(old_firewall_group)
|
||||||
|
new_firewall_group.update(firewall_group_delta)
|
||||||
|
self.update_firewall_group_precommit(context, old_firewall_group,
|
||||||
|
new_firewall_group)
|
||||||
|
firewall_group_delta['status'] = new_firewall_group['status']
|
||||||
|
firewall_group = self.firewall_db.update_firewall_group(
|
||||||
|
context, id, firewall_group_delta)
|
||||||
|
self.update_firewall_group_postcommit(context, old_firewall_group,
|
||||||
|
firewall_group)
|
||||||
|
return firewall_group
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_group_precommit(self, context, old_firewall_group,
|
||||||
|
new_firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_group_postcommit(self, context, old_firewall_group,
|
||||||
|
new_firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Firewall Policy
|
||||||
|
def create_firewall_policy(self, context, firewall_policy):
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
firewall_policy = self.firewall_db.create_firewall_policy(
|
||||||
|
context, firewall_policy)
|
||||||
|
self.create_firewall_policy_precommit(context, firewall_policy)
|
||||||
|
self.create_firewall_policy_postcommit(context, firewall_policy)
|
||||||
|
return firewall_policy
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_policy_precommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_policy_postcommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_policy(self, context, id):
|
||||||
|
firewall_policy = self.firewall_db.get_firewall_policy(context, id)
|
||||||
|
self.delete_firewall_policy_precommit(context, firewall_policy)
|
||||||
|
self.firewall_db.delete_firewall_policy(context, id)
|
||||||
|
self.delete_firewall_policy_postcommit(context, firewall_policy)
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_policy_precommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_policy_postcommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_firewall_policy(self, context, id, fields=None):
|
||||||
|
return self.firewall_db.get_firewall_policy(context, id, fields)
|
||||||
|
|
||||||
|
def get_firewall_policies(self, context, filters=None, fields=None):
|
||||||
|
return self.firewall_db.get_firewall_policies(context, filters, fields)
|
||||||
|
|
||||||
|
def update_firewall_policy(self, context, id, firewall_policy_delta):
|
||||||
|
old_firewall_policy = self.firewall_db.get_firewall_policy(context, id)
|
||||||
|
new_firewall_policy = copy.deepcopy(old_firewall_policy)
|
||||||
|
new_firewall_policy.update(firewall_policy_delta)
|
||||||
|
self.update_firewall_policy_precommit(context, old_firewall_policy,
|
||||||
|
new_firewall_policy)
|
||||||
|
firewall_policy = self.firewall_db.update_firewall_policy(
|
||||||
|
context, id, firewall_policy_delta)
|
||||||
|
self.update_firewall_policy_postcommit(context, old_firewall_policy,
|
||||||
|
firewall_policy)
|
||||||
|
return firewall_policy
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_policy_precommit(self, context, old_firewall_policy,
|
||||||
|
new_firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_policy_postcommit(self, context, old_firewall_policy,
|
||||||
|
new_firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Firewall Rule
|
||||||
|
def create_firewall_rule(self, context, firewall_rule):
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
firewall_rule = self.firewall_db.create_firewall_rule(
|
||||||
|
context, firewall_rule)
|
||||||
|
self.create_firewall_rule_precommit(context, firewall_rule)
|
||||||
|
self.create_firewall_rule_postcommit(context, firewall_rule)
|
||||||
|
return firewall_rule
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_rule_precommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_firewall_rule_postcommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_rule(self, context, id):
|
||||||
|
firewall_rule = self.firewall_db.get_firewall_rule(context, id)
|
||||||
|
self.delete_firewall_rule_precommit(context, firewall_rule)
|
||||||
|
self.firewall_db.delete_firewall_rule(context, id)
|
||||||
|
self.delete_firewall_rule_postcommit(context, firewall_rule)
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_rule_precommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_firewall_rule_postcommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_firewall_rule(self, context, id, fields=None):
|
||||||
|
return self.firewall_db.get_firewall_rule(context, id, fields)
|
||||||
|
|
||||||
|
def get_firewall_rules(self, context, filters=None, fields=None):
|
||||||
|
return self.firewall_db.get_firewall_rules(context, filters, fields)
|
||||||
|
|
||||||
|
def update_firewall_rule(self, context, id, firewall_rule_delta):
|
||||||
|
old_firewall_rule = self.firewall_db.get_firewall_rule(context, id)
|
||||||
|
new_firewall_rule = copy.deepcopy(old_firewall_rule)
|
||||||
|
new_firewall_rule.update(firewall_rule_delta)
|
||||||
|
self.update_firewall_rule_precommit(context, old_firewall_rule,
|
||||||
|
new_firewall_rule)
|
||||||
|
firewall_rule = self.firewall_db.update_firewall_rule(
|
||||||
|
context, id, firewall_rule_delta)
|
||||||
|
self.update_firewall_rule_postcommit(context, old_firewall_rule,
|
||||||
|
firewall_rule)
|
||||||
|
return firewall_rule
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_rule_precommit(self, context, old_firewall_rule,
|
||||||
|
new_firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_firewall_rule_postcommit(self, context, old_firewall_rule,
|
||||||
|
new_firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def insert_rule(self, context, policy_id, rule_info):
|
||||||
|
self.insert_rule_precommit(context, policy_id, rule_info)
|
||||||
|
firewall_policy = self.firewall_db.insert_rule(context, policy_id,
|
||||||
|
rule_info)
|
||||||
|
self.insert_rule_postcommit(context, policy_id, rule_info)
|
||||||
|
return firewall_policy
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def insert_rule_precommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def insert_rule_postcommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_rule(self, context, policy_id, rule_info):
|
||||||
|
self.remove_rule_precommit(context, policy_id, rule_info)
|
||||||
|
firewall_policy = self.firewall_db.remove_rule(context, policy_id,
|
||||||
|
rule_info)
|
||||||
|
self.remove_rule_postcommit(context, policy_id, rule_info)
|
||||||
|
return firewall_policy
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def remove_rule_precommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def remove_rule_postcommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FirewallDriverDB(FirewallDriverDBMixin):
|
||||||
|
"""FirewallDriverDBMixin interface for driver with database.
|
||||||
|
|
||||||
|
Each firewall backend driver that needs a database persistency should
|
||||||
|
inherit from this driver.
|
||||||
|
It can overload needed methods from the following pre/postcommit methods.
|
||||||
|
Any exception raised during a precommit method will result in not having
|
||||||
|
related records in the databases.
|
||||||
|
"""
|
||||||
|
|
||||||
|
#Firewal Group
|
||||||
|
def create_firewall_group_precommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_firewall_group_postcommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_firewall_group_precommit(self, context, old_firewall_group,
|
||||||
|
new_firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_firewall_group_postcommit(self, context, old_firewall_group,
|
||||||
|
new_firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_group_precommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_group_postcommit(self, context, firewall_group):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#Firewall Policy
|
||||||
|
def create_firewall_policy_precommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_firewall_policy_postcommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_firewall_policy_precommit(self, context, old_firewall_policy,
|
||||||
|
new_firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_firewall_policy_postcommit(self, context, old_firewall_policy,
|
||||||
|
new_firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_policy_precommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_policy_postcommit(self, context, firewall_policy):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#Firewall Rule
|
||||||
|
def create_firewall_rule_precommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_firewall_rule_postcommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_firewall_rule_precommit(self, context, old_firewall_rule,
|
||||||
|
new_firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_firewall_rule_postcommit(self, context, old_firewall_rule,
|
||||||
|
new_firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_rule_precommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_rule_postcommit(self, context, firewall_rule):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def insert_rule_precommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def insert_rule_postcommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_rule_precommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_rule_postcommit(self, context, policy_id, rule_info):
|
||||||
|
pass
|
@ -13,387 +13,26 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import contextlib
|
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
from neutron.api import extensions as api_ext
|
|
||||||
from neutron.common import config
|
|
||||||
from neutron_lib.api.definitions import firewall_v2
|
|
||||||
from neutron_lib import constants as nl_constants
|
|
||||||
from neutron_lib import context
|
|
||||||
from neutron_lib.exceptions import firewall_v2 as f_exc
|
|
||||||
from neutron_lib.plugins import directory
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_utils import importutils
|
|
||||||
from oslo_utils import uuidutils
|
|
||||||
import six
|
import six
|
||||||
import testtools
|
import testtools
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
|
from neutron_lib import constants as nl_constants
|
||||||
|
from neutron_lib.exceptions import firewall_v2 as f_exc
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants as constants
|
from neutron_fwaas.common import fwaas_constants as constants
|
||||||
from neutron_fwaas.db.firewall.v2 import firewall_db_v2 as fdb
|
from neutron_fwaas.tests.unit.services.firewall import test_fwaas_plugin_v2
|
||||||
from neutron_fwaas import extensions
|
|
||||||
from neutron_fwaas.services.firewall import fwaas_plugin_v2
|
|
||||||
from neutron_fwaas.tests import base
|
|
||||||
|
|
||||||
|
|
||||||
DB_FW_PLUGIN_KLASS = (
|
class TestFirewallDBPluginV2(test_fwaas_plugin_v2.FirewallPluginV2TestCase):
|
||||||
"neutron_fwaas.db.firewall.v2.firewall_db_v2.Firewall_db_mixin_v2"
|
|
||||||
)
|
|
||||||
FWAAS_PLUGIN = 'neutron_fwaas.services.firewall.fwaas_plugin_v2'
|
|
||||||
DELETEFW_PATH = FWAAS_PLUGIN + '.FirewallAgentApi.delete_firewall_group'
|
|
||||||
extensions_path = ':'.join(extensions.__path__)
|
|
||||||
DESCRIPTION = 'default description'
|
|
||||||
PROTOCOL = 'tcp'
|
|
||||||
IP_VERSION = 4
|
|
||||||
SOURCE_IP_ADDRESS_RAW = '1.1.1.1'
|
|
||||||
DESTINATION_IP_ADDRESS_RAW = '2.2.2.2'
|
|
||||||
SOURCE_PORT = '55000:56000'
|
|
||||||
DESTINATION_PORT = '56000:57000'
|
|
||||||
ACTION = 'allow'
|
|
||||||
AUDITED = True
|
|
||||||
ENABLED = True
|
|
||||||
ADMIN_STATE_UP = True
|
|
||||||
SHARED = True
|
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
class FakeAgentApi(fwaas_plugin_v2.FirewallCallbacks):
|
provider = ('neutron_fwaas.services.firewall.service_drivers.'
|
||||||
"""
|
'driver_api.FirewallDriverDB')
|
||||||
This class used to mock the AgentAPI delete method inherits from
|
super(TestFirewallDBPluginV2, self).setUp(service_provider=provider)
|
||||||
FirewallCallbacks because it needs access to the firewall_deleted method.
|
self.db = self.plugin.driver.firewall_db
|
||||||
The delete_firewall method belongs to the FirewallAgentApi, which has
|
|
||||||
no access to the firewall_deleted method normally because it's not
|
|
||||||
responsible for deleting the firewall from the DB. However, it needs
|
|
||||||
to in the unit tests since there is no agent to call back.
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def delete_firewall_group(self, context, firewall_group, **kwargs):
|
|
||||||
self.plugin = directory.get_plugin('FIREWALL_V2')
|
|
||||||
self.firewall_group_deleted(context, firewall_group['id'], **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class FirewallPluginV2DbTestCase(base.NeutronDbPluginV2TestCase):
|
|
||||||
resource_prefix_map = dict(
|
|
||||||
(k, firewall_v2.API_PREFIX)
|
|
||||||
for k in firewall_v2.RESOURCE_ATTRIBUTE_MAP.keys()
|
|
||||||
)
|
|
||||||
|
|
||||||
def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None):
|
|
||||||
self.agentapi_delf_p = mock.patch(
|
|
||||||
DELETEFW_PATH, create=True,
|
|
||||||
new=FakeAgentApi().delete_firewall_group)
|
|
||||||
self.agentapi_delf_p.start()
|
|
||||||
if not fw_plugin:
|
|
||||||
fw_plugin = DB_FW_PLUGIN_KLASS
|
|
||||||
service_plugins = {'fw_plugin_name': fw_plugin}
|
|
||||||
|
|
||||||
fdb.Firewall_db_mixin_v2.supported_extension_aliases = ["fwaas_v2"]
|
|
||||||
fdb.Firewall_db_mixin_v2.path_prefix = firewall_v2.API_PREFIX
|
|
||||||
super(FirewallPluginV2DbTestCase, self).setUp(
|
|
||||||
ext_mgr=ext_mgr,
|
|
||||||
service_plugins=service_plugins
|
|
||||||
)
|
|
||||||
|
|
||||||
if not ext_mgr:
|
|
||||||
self.plugin = importutils.import_object(fw_plugin)
|
|
||||||
ext_mgr = api_ext.PluginAwareExtensionManager(
|
|
||||||
extensions_path,
|
|
||||||
{'FIREWALL': self.plugin}
|
|
||||||
)
|
|
||||||
app = config.load_paste_app('extensions_test_app')
|
|
||||||
self.ext_api = api_ext.ExtensionMiddleware(app, ext_mgr=ext_mgr)
|
|
||||||
router_distributed_opts = [
|
|
||||||
cfg.BoolOpt(
|
|
||||||
'router_distributed',
|
|
||||||
default=False,
|
|
||||||
help=("System-wide flag to determine the type of router "
|
|
||||||
"that tenants can create. Only admin can override.")),
|
|
||||||
]
|
|
||||||
cfg.CONF.register_opts(router_distributed_opts)
|
|
||||||
|
|
||||||
def _get_admin_context(self):
|
|
||||||
# FIXME NOTE(ivasilevskaya) seems that test framework treats context
|
|
||||||
# with user_id=None/tenant_id=None (return value of
|
|
||||||
# context._get_admin_context() method) in a somewhat special way.
|
|
||||||
# So as a workaround to have the framework behave properly right now
|
|
||||||
# let's implement our own _get_admin_context method and look into the
|
|
||||||
# matter some other time.
|
|
||||||
return context.Context(user_id='admin',
|
|
||||||
tenant_id='admin-tenant',
|
|
||||||
is_admin=True)
|
|
||||||
|
|
||||||
def _get_nonadmin_context(self, user_id=None, tenant_id=None):
|
|
||||||
return context.Context(user_id=user_id or 'non-admin',
|
|
||||||
tenant_id=tenant_id or 'tenant1')
|
|
||||||
|
|
||||||
def _test_list_resources(self, resource, items,
|
|
||||||
neutron_context=None,
|
|
||||||
query_params=None):
|
|
||||||
if resource.endswith('y'):
|
|
||||||
resource_plural = resource.replace('y', 'ies')
|
|
||||||
else:
|
|
||||||
resource_plural = resource + 's'
|
|
||||||
|
|
||||||
res = self._list(resource_plural,
|
|
||||||
neutron_context=neutron_context,
|
|
||||||
query_params=query_params)
|
|
||||||
resource = resource.replace('-', '_')
|
|
||||||
self.assertEqual(
|
|
||||||
sorted([i[resource]['id'] for i in items]),
|
|
||||||
sorted([i['id'] for i in res[resource_plural]]))
|
|
||||||
|
|
||||||
def _list_req(self, resource_plural, ctx=None):
|
|
||||||
if not ctx:
|
|
||||||
ctx = self._get_admin_context()
|
|
||||||
req = self.new_list_request(resource_plural)
|
|
||||||
req.environ['neutron.context'] = ctx
|
|
||||||
return self.deserialize(
|
|
||||||
self.fmt, req.get_response(self.ext_api))[resource_plural]
|
|
||||||
|
|
||||||
def _show_req(self, resource_plural, obj_id, ctx=None):
|
|
||||||
req = self.new_show_request(resource_plural, obj_id, fmt=self.fmt)
|
|
||||||
if not ctx:
|
|
||||||
ctx = self._get_admin_context()
|
|
||||||
req.environ['neutron.context'] = ctx
|
|
||||||
res = self.deserialize(
|
|
||||||
self.fmt, req.get_response(self.ext_api))
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _build_default_fwg(self, ctx=None, is_one=True):
|
|
||||||
res = self._list_req('firewall_groups', ctx=ctx)
|
|
||||||
if is_one:
|
|
||||||
self.assertEqual(1, len(res))
|
|
||||||
return res[0]
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _get_test_firewall_rule_attrs(self, name='firewall_rule1'):
|
|
||||||
attrs = {'name': name,
|
|
||||||
'tenant_id': self._tenant_id,
|
|
||||||
'project_id': self._tenant_id,
|
|
||||||
'protocol': PROTOCOL,
|
|
||||||
'ip_version': IP_VERSION,
|
|
||||||
'source_ip_address': SOURCE_IP_ADDRESS_RAW,
|
|
||||||
'destination_ip_address': DESTINATION_IP_ADDRESS_RAW,
|
|
||||||
'source_port': SOURCE_PORT,
|
|
||||||
'destination_port': DESTINATION_PORT,
|
|
||||||
'action': ACTION,
|
|
||||||
'enabled': ENABLED,
|
|
||||||
'shared': SHARED}
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
def _get_test_firewall_policy_attrs(self, name='firewall_policy1',
|
|
||||||
audited=AUDITED):
|
|
||||||
attrs = {'name': name,
|
|
||||||
'description': DESCRIPTION,
|
|
||||||
'tenant_id': self._tenant_id,
|
|
||||||
'project_id': self._tenant_id,
|
|
||||||
'firewall_rules': [],
|
|
||||||
'audited': audited,
|
|
||||||
'shared': SHARED}
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
def _get_test_firewall_group_attrs(self, name='firewall_1',
|
|
||||||
status='PENDING_CREATE'):
|
|
||||||
attrs = {'name': name,
|
|
||||||
'tenant_id': self._tenant_id,
|
|
||||||
'project_id': self._tenant_id,
|
|
||||||
'admin_state_up': ADMIN_STATE_UP,
|
|
||||||
'status': status}
|
|
||||||
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
def _create_firewall_policy(self, fmt, name, description, shared,
|
|
||||||
firewall_rules, audited,
|
|
||||||
expected_res_status=None, **kwargs):
|
|
||||||
tenant_id = kwargs.get('tenant_id', self._tenant_id)
|
|
||||||
data = {'firewall_policy': {'name': name,
|
|
||||||
'description': description,
|
|
||||||
'tenant_id': tenant_id,
|
|
||||||
'project_id': tenant_id,
|
|
||||||
'firewall_rules': firewall_rules,
|
|
||||||
'audited': audited,
|
|
||||||
'shared': shared}}
|
|
||||||
|
|
||||||
fw_policy_req = self.new_create_request('firewall_policies', data, fmt)
|
|
||||||
fw_policy_res = fw_policy_req.get_response(self.ext_api)
|
|
||||||
if expected_res_status:
|
|
||||||
self.assertEqual(expected_res_status, fw_policy_res.status_int)
|
|
||||||
|
|
||||||
return fw_policy_res
|
|
||||||
|
|
||||||
def _replace_firewall_status(self, attrs, old_status, new_status):
|
|
||||||
if attrs['status'] is old_status:
|
|
||||||
attrs['status'] = new_status
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def firewall_policy(self, fmt=None, name='firewall_policy1',
|
|
||||||
description=DESCRIPTION, shared=SHARED,
|
|
||||||
firewall_rules=None, audited=True,
|
|
||||||
do_delete=True, **kwargs):
|
|
||||||
if firewall_rules is None:
|
|
||||||
firewall_rules = []
|
|
||||||
if not fmt:
|
|
||||||
fmt = self.fmt
|
|
||||||
res = self._create_firewall_policy(fmt, name, description, shared,
|
|
||||||
firewall_rules, audited, **kwargs)
|
|
||||||
if res.status_int >= 400:
|
|
||||||
raise webob.exc.HTTPClientError(code=res.status_int)
|
|
||||||
firewall_policy = self.deserialize(fmt or self.fmt, res)
|
|
||||||
yield firewall_policy
|
|
||||||
if do_delete:
|
|
||||||
self._delete('firewall_policies',
|
|
||||||
firewall_policy['firewall_policy']['id'])
|
|
||||||
|
|
||||||
def _create_firewall_rule(self, fmt, name, shared, protocol,
|
|
||||||
ip_version, source_ip_address,
|
|
||||||
destination_ip_address, source_port,
|
|
||||||
destination_port, action, enabled,
|
|
||||||
expected_res_status=None, **kwargs):
|
|
||||||
tenant_id = kwargs.get('tenant_id', self._tenant_id)
|
|
||||||
data = {'firewall_rule': {'name': name,
|
|
||||||
'tenant_id': tenant_id,
|
|
||||||
'project_id': tenant_id,
|
|
||||||
'protocol': protocol,
|
|
||||||
'ip_version': ip_version,
|
|
||||||
'source_ip_address': source_ip_address,
|
|
||||||
'destination_ip_address':
|
|
||||||
destination_ip_address,
|
|
||||||
'source_port': source_port,
|
|
||||||
'destination_port': destination_port,
|
|
||||||
'action': action,
|
|
||||||
'enabled': enabled,
|
|
||||||
'shared': shared}}
|
|
||||||
|
|
||||||
fw_rule_req = self.new_create_request('firewall_rules', data, fmt)
|
|
||||||
fw_rule_res = fw_rule_req.get_response(self.ext_api)
|
|
||||||
if expected_res_status:
|
|
||||||
self.assertEqual(expected_res_status, fw_rule_res.status_int)
|
|
||||||
|
|
||||||
return fw_rule_res
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def firewall_rule(self, fmt=None, name='firewall_rule1',
|
|
||||||
shared=SHARED, protocol=PROTOCOL, ip_version=IP_VERSION,
|
|
||||||
source_ip_address=SOURCE_IP_ADDRESS_RAW,
|
|
||||||
destination_ip_address=DESTINATION_IP_ADDRESS_RAW,
|
|
||||||
source_port=SOURCE_PORT,
|
|
||||||
destination_port=DESTINATION_PORT,
|
|
||||||
action=ACTION, enabled=ENABLED,
|
|
||||||
do_delete=True, **kwargs):
|
|
||||||
if not fmt:
|
|
||||||
fmt = self.fmt
|
|
||||||
res = self._create_firewall_rule(fmt, name, shared, protocol,
|
|
||||||
ip_version, source_ip_address,
|
|
||||||
destination_ip_address,
|
|
||||||
source_port, destination_port,
|
|
||||||
action, enabled, **kwargs)
|
|
||||||
if res.status_int >= 400:
|
|
||||||
raise webob.exc.HTTPClientError(code=res.status_int)
|
|
||||||
firewall_rule = self.deserialize(fmt or self.fmt, res)
|
|
||||||
yield firewall_rule
|
|
||||||
if do_delete:
|
|
||||||
self._delete('firewall_rules',
|
|
||||||
firewall_rule['firewall_rule']['id'])
|
|
||||||
|
|
||||||
def _create_firewall_group(self, fmt, name, description,
|
|
||||||
ingress_firewall_policy_id,
|
|
||||||
egress_firewall_policy_id,
|
|
||||||
ports=None, admin_state_up=True,
|
|
||||||
expected_res_status=None, **kwargs):
|
|
||||||
tenant_id = kwargs.get('tenant_id', self._tenant_id)
|
|
||||||
if ingress_firewall_policy_id is None:
|
|
||||||
default_policy = kwargs.get('default_policy', True)
|
|
||||||
if default_policy:
|
|
||||||
res = self._create_firewall_policy(fmt, 'fwp',
|
|
||||||
description=DESCRIPTION,
|
|
||||||
shared=SHARED,
|
|
||||||
firewall_rules=[],
|
|
||||||
audited=AUDITED)
|
|
||||||
firewall_policy = self.deserialize(fmt or self.fmt, res)
|
|
||||||
fwp_id = firewall_policy["firewall_policy"]["id"]
|
|
||||||
ingress_firewall_policy_id = fwp_id
|
|
||||||
data = {'firewall_group': {'name': name,
|
|
||||||
'description': description,
|
|
||||||
'ingress_firewall_policy_id': ingress_firewall_policy_id,
|
|
||||||
'egress_firewall_policy_id': egress_firewall_policy_id,
|
|
||||||
'admin_state_up': admin_state_up}}
|
|
||||||
ctx = kwargs.get('context', None)
|
|
||||||
if ctx is None or ctx.is_admin:
|
|
||||||
data['firewall_group'].update({'tenant_id': tenant_id})
|
|
||||||
data['firewall_group'].update({'project_id': tenant_id})
|
|
||||||
if ports is not None:
|
|
||||||
data['firewall_group'].update({'ports': ports})
|
|
||||||
|
|
||||||
firewall_req = self.new_create_request('firewall_groups', data, fmt,
|
|
||||||
context=ctx)
|
|
||||||
firewall_res = firewall_req.get_response(self.ext_api)
|
|
||||||
if expected_res_status:
|
|
||||||
self.assertEqual(expected_res_status, firewall_res.status_int)
|
|
||||||
|
|
||||||
return firewall_res
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def firewall_group(self, fmt=None, name='firewall_1',
|
|
||||||
description=DESCRIPTION,
|
|
||||||
ingress_firewall_policy_id=None,
|
|
||||||
egress_firewall_policy_id=None,
|
|
||||||
ports=None, admin_state_up=True,
|
|
||||||
do_delete=True, **kwargs):
|
|
||||||
if not fmt:
|
|
||||||
fmt = self.fmt
|
|
||||||
res = self._create_firewall_group(fmt, name, description,
|
|
||||||
ingress_firewall_policy_id,
|
|
||||||
egress_firewall_policy_id,
|
|
||||||
ports=ports,
|
|
||||||
admin_state_up=admin_state_up,
|
|
||||||
**kwargs)
|
|
||||||
if res.status_int >= 400:
|
|
||||||
raise webob.exc.HTTPClientError(code=res.status_int)
|
|
||||||
firewall_group = self.deserialize(fmt or self.fmt, res)
|
|
||||||
yield firewall_group
|
|
||||||
if do_delete:
|
|
||||||
self._delete('firewall_groups',
|
|
||||||
firewall_group['firewall_group']['id'])
|
|
||||||
|
|
||||||
def _rule_action(self, action, id, firewall_rule_id, insert_before=None,
|
|
||||||
insert_after=None, expected_code=webob.exc.HTTPOk.code,
|
|
||||||
expected_body=None, body_data=None):
|
|
||||||
# We intentionally do this check for None since we want to distinguish
|
|
||||||
# from empty dictionary
|
|
||||||
if body_data is None:
|
|
||||||
if action == 'insert':
|
|
||||||
body_data = {'firewall_rule_id': firewall_rule_id,
|
|
||||||
'insert_before': insert_before,
|
|
||||||
'insert_after': insert_after}
|
|
||||||
else:
|
|
||||||
body_data = {'firewall_rule_id': firewall_rule_id}
|
|
||||||
|
|
||||||
req = self.new_action_request('firewall_policies',
|
|
||||||
body_data, id,
|
|
||||||
"%s_rule" % action)
|
|
||||||
res = req.get_response(self.ext_api)
|
|
||||||
self.assertEqual(expected_code, res.status_int)
|
|
||||||
response = self.deserialize(self.fmt, res)
|
|
||||||
if expected_body:
|
|
||||||
self.assertEqual(expected_body, response)
|
|
||||||
return response
|
|
||||||
|
|
||||||
def _compare_firewall_rule_lists(self, firewall_policy_id,
|
|
||||||
observed_list, expected_list):
|
|
||||||
position = 0
|
|
||||||
for r1, r2 in zip(observed_list, expected_list):
|
|
||||||
rule = r1['firewall_rule']
|
|
||||||
rule['firewall_policy_id'] = firewall_policy_id
|
|
||||||
position += 1
|
|
||||||
rule['position'] = position
|
|
||||||
for k in rule:
|
|
||||||
self.assertEqual(r2[k], rule[k])
|
|
||||||
|
|
||||||
|
|
||||||
class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|
||||||
|
|
||||||
def test_get_policy_ordered_rules(self):
|
def test_get_policy_ordered_rules(self):
|
||||||
with self.firewall_rule(name='alone'), \
|
with self.firewall_rule(name='alone'), \
|
||||||
@ -405,7 +44,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
with self.firewall_policy(firewall_rules=expected_ids) as fwp:
|
with self.firewall_policy(firewall_rules=expected_ids) as fwp:
|
||||||
ctx = self._get_admin_context()
|
ctx = self._get_admin_context()
|
||||||
fwp_id = fwp['firewall_policy']['id']
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
observeds = self.plugin._get_policy_ordered_rules(ctx, fwp_id)
|
observeds = self.db._get_policy_ordered_rules(ctx, fwp_id)
|
||||||
observed_ids = [r['id'] for r in observeds]
|
observed_ids = [r['id'] for r in observeds]
|
||||||
self.assertEqual(expected_ids, observed_ids)
|
self.assertEqual(expected_ids, observed_ids)
|
||||||
|
|
||||||
@ -413,8 +52,8 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
name = "firewall_policy1"
|
name = "firewall_policy1"
|
||||||
attrs = self._get_test_firewall_policy_attrs(name)
|
attrs = self._get_test_firewall_policy_attrs(name)
|
||||||
|
|
||||||
with self.firewall_policy(name=name, shared=SHARED,
|
with self.firewall_policy(name=name, shared=self.SHARED,
|
||||||
firewall_rules=None, audited=AUDITED
|
firewall_rules=None, audited=self.AUDITED
|
||||||
) as firewall_policy:
|
) as firewall_policy:
|
||||||
for k, v in six.iteritems(attrs):
|
for k, v in six.iteritems(attrs):
|
||||||
self.assertEqual(v, firewall_policy['firewall_policy'][k])
|
self.assertEqual(v, firewall_policy['firewall_policy'][k])
|
||||||
@ -429,49 +68,29 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
fr = [fwr1, fwr2, fwr3]
|
fr = [fwr1, fwr2, fwr3]
|
||||||
fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
|
fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
|
||||||
attrs['firewall_rules'] = fw_rule_ids
|
attrs['firewall_rules'] = fw_rule_ids
|
||||||
with self.firewall_policy(name=name, shared=SHARED,
|
with self.firewall_policy(name=name, shared=self.SHARED,
|
||||||
firewall_rules=fw_rule_ids,
|
firewall_rules=fw_rule_ids,
|
||||||
audited=AUDITED) as fwp:
|
audited=self.AUDITED) as fwp:
|
||||||
for k, v in six.iteritems(attrs):
|
for k, v in six.iteritems(attrs):
|
||||||
self.assertEqual(v, fwp['firewall_policy'][k])
|
self.assertEqual(v, fwp['firewall_policy'][k])
|
||||||
|
|
||||||
def test_create_admin_firewall_policy_with_other_tenant_rules(self):
|
|
||||||
with self.firewall_rule(shared=False) as fr:
|
|
||||||
fw_rule_ids = [fr['firewall_rule']['id']]
|
|
||||||
res = self._create_firewall_policy(None, 'firewall_policy1',
|
|
||||||
description=DESCRIPTION,
|
|
||||||
shared=SHARED,
|
|
||||||
firewall_rules=fw_rule_ids,
|
|
||||||
audited=AUDITED,
|
|
||||||
tenant_id='admin-tenant')
|
|
||||||
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
|
||||||
|
|
||||||
def test_create_firewall_policy_with_previously_associated_rule(self):
|
def test_create_firewall_policy_with_previously_associated_rule(self):
|
||||||
with self.firewall_rule() as fwr:
|
with self.firewall_rule() as fwr:
|
||||||
fw_rule_ids = [fwr['firewall_rule']['id']]
|
fw_rule_ids = [fwr['firewall_rule']['id']]
|
||||||
with self.firewall_policy(firewall_rules=fw_rule_ids):
|
with self.firewall_policy(firewall_rules=fw_rule_ids):
|
||||||
with self.firewall_policy(shared=SHARED,
|
with self.firewall_policy(shared=self.SHARED,
|
||||||
firewall_rules=fw_rule_ids) as fwp2:
|
firewall_rules=fw_rule_ids) as fwp2:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fwr['firewall_rule']['id'],
|
fwr['firewall_rule']['id'],
|
||||||
fwp2['firewall_policy']['firewall_rules'][0])
|
fwp2['firewall_policy']['firewall_rules'][0])
|
||||||
|
|
||||||
def test_create_shared_firewall_policy_with_nonshared_rule(self):
|
|
||||||
with self.firewall_rule(shared=False) as fwr:
|
|
||||||
fw_rule_ids = [fwr['firewall_rule']['id']]
|
|
||||||
res = self._create_firewall_policy(None, 'firewall_policy1',
|
|
||||||
description=DESCRIPTION,
|
|
||||||
shared=SHARED,
|
|
||||||
firewall_rules=fw_rule_ids,
|
|
||||||
audited=AUDITED)
|
|
||||||
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
|
||||||
|
|
||||||
def test_show_firewall_policy(self):
|
def test_show_firewall_policy(self):
|
||||||
name = "firewall_policy1"
|
name = "firewall_policy1"
|
||||||
attrs = self._get_test_firewall_policy_attrs(name)
|
attrs = self._get_test_firewall_policy_attrs(name)
|
||||||
|
|
||||||
with self.firewall_policy(name=name, shared=SHARED,
|
with self.firewall_policy(name=name, shared=self.SHARED,
|
||||||
firewall_rules=None, audited=AUDITED) as fwp:
|
firewall_rules=None,
|
||||||
|
audited=self.AUDITED) as fwp:
|
||||||
res = self._show_req('firewall_policies',
|
res = self._show_req('firewall_policies',
|
||||||
fwp['firewall_policy']['id'])
|
fwp['firewall_policy']['id'])
|
||||||
for k, v in six.iteritems(attrs):
|
for k, v in six.iteritems(attrs):
|
||||||
@ -490,8 +109,8 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
name = "new_firewall_policy1"
|
name = "new_firewall_policy1"
|
||||||
attrs = self._get_test_firewall_policy_attrs(name, audited=False)
|
attrs = self._get_test_firewall_policy_attrs(name, audited=False)
|
||||||
|
|
||||||
with self.firewall_policy(shared=SHARED, firewall_rules=None,
|
with self.firewall_policy(shared=self.SHARED, firewall_rules=None,
|
||||||
audited=AUDITED) as fwp:
|
audited=self.AUDITED) as fwp:
|
||||||
data = {'firewall_policy': {'name': name}}
|
data = {'firewall_policy': {'name': name}}
|
||||||
req = self.new_update_request('firewall_policies', data,
|
req = self.new_update_request('firewall_policies', data,
|
||||||
fwp['firewall_policy']['id'])
|
fwp['firewall_policy']['id'])
|
||||||
@ -501,7 +120,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
|
|
||||||
def _test_update_firewall_policy(self, with_audited):
|
def _test_update_firewall_policy(self, with_audited):
|
||||||
with self.firewall_policy(name='firewall_policy1', description='fwp',
|
with self.firewall_policy(name='firewall_policy1', description='fwp',
|
||||||
audited=AUDITED) as fwp:
|
audited=self.AUDITED) as fwp:
|
||||||
attrs = self._get_test_firewall_policy_attrs(audited=with_audited)
|
attrs = self._get_test_firewall_policy_attrs(audited=with_audited)
|
||||||
data = {'firewall_policy':
|
data = {'firewall_policy':
|
||||||
{'description': 'fw_p1'}}
|
{'description': 'fw_p1'}}
|
||||||
@ -658,7 +277,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
with self.firewall_policy(shared=False) as fwp:
|
with self.firewall_policy(shared=False) as fwp:
|
||||||
fw_rule_ids = [fr['firewall_rule']['id']]
|
fw_rule_ids = [fr['firewall_rule']['id']]
|
||||||
# update shared policy with shared attr and nonshared rule
|
# update shared policy with shared attr and nonshared rule
|
||||||
data = {'firewall_policy': {'shared': SHARED,
|
data = {'firewall_policy': {'shared': self.SHARED,
|
||||||
'firewall_rules': fw_rule_ids}}
|
'firewall_rules': fw_rule_ids}}
|
||||||
req = self.new_update_request('firewall_policies', data,
|
req = self.new_update_request('firewall_policies', data,
|
||||||
fwp['firewall_policy']['id'])
|
fwp['firewall_policy']['id'])
|
||||||
@ -671,14 +290,15 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
with self.firewall_policy(shared=False,
|
with self.firewall_policy(shared=False,
|
||||||
firewall_rules=fw_rule_ids) as fwp:
|
firewall_rules=fw_rule_ids) as fwp:
|
||||||
# update policy with shared attr
|
# update policy with shared attr
|
||||||
data = {'firewall_policy': {'shared': SHARED}}
|
data = {'firewall_policy': {'shared': self.SHARED}}
|
||||||
req = self.new_update_request('firewall_policies', data,
|
req = self.new_update_request('firewall_policies', data,
|
||||||
fwp['firewall_policy']['id'])
|
fwp['firewall_policy']['id'])
|
||||||
res = req.get_response(self.ext_api)
|
res = req.get_response(self.ext_api)
|
||||||
self.assertEqual(webob.exc.HTTPConflict.code, res.status_int)
|
self.assertEqual(webob.exc.HTTPConflict.code, res.status_int)
|
||||||
|
|
||||||
def test_update_firewall_policy_assoc_with_other_tenant_firewall(self):
|
def test_update_firewall_policy_assoc_with_other_tenant_firewall(self):
|
||||||
with self.firewall_policy(shared=SHARED, tenant_id='tenant1') as fwp:
|
with self.firewall_policy(shared=self.SHARED,
|
||||||
|
tenant_id='tenant1') as fwp:
|
||||||
fwp_id = fwp['firewall_policy']['id']
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
with self.firewall_group(ingress_firewall_policy_id=fwp_id,
|
with self.firewall_group(ingress_firewall_policy_id=fwp_id,
|
||||||
egress_firewall_policy_id=fwp_id):
|
egress_firewall_policy_id=fwp_id):
|
||||||
@ -790,13 +410,11 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
self.assertIsNone(fw_rule['ingress_firewall_policy_id'])
|
self.assertIsNone(fw_rule['ingress_firewall_policy_id'])
|
||||||
|
|
||||||
def test_delete_firewall_policy_with_firewall_group_association(self):
|
def test_delete_firewall_policy_with_firewall_group_association(self):
|
||||||
attrs = self._get_test_firewall_group_attrs()
|
|
||||||
with self.firewall_policy() as fwp:
|
with self.firewall_policy() as fwp:
|
||||||
fwp_id = fwp['firewall_policy']['id']
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
attrs['firewall_policy_id'] = fwp_id
|
|
||||||
with self.firewall_group(
|
with self.firewall_group(
|
||||||
ingress_firewall_policy_id=fwp_id,
|
ingress_firewall_policy_id=fwp_id,
|
||||||
admin_state_up=ADMIN_STATE_UP):
|
admin_state_up=self.ADMIN_STATE_UP):
|
||||||
req = self.new_delete_request('firewall_policies', fwp_id)
|
req = self.new_delete_request('firewall_policies', fwp_id)
|
||||||
res = req.get_response(self.ext_api)
|
res = req.get_response(self.ext_api)
|
||||||
self.assertEqual(409, res.status_int)
|
self.assertEqual(409, res.status_int)
|
||||||
@ -832,20 +450,20 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
def test_create_firewall_src_port_illegal_range(self):
|
def test_create_firewall_src_port_illegal_range(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['source_port'] = '65535:1024'
|
attrs['source_port'] = '65535:1024'
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_create_firewall_dest_port_illegal_range(self):
|
def test_create_firewall_dest_port_illegal_range(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['destination_port'] = '65535:1024'
|
attrs['destination_port'] = '65535:1024'
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_create_firewall_rule_icmp_with_port(self):
|
def test_create_firewall_rule_icmp_with_port(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['protocol'] = 'icmp'
|
attrs['protocol'] = 'icmp'
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_create_firewall_rule_icmp_without_port(self):
|
def test_create_firewall_rule_icmp_without_port(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
@ -862,28 +480,28 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
def test_create_firewall_without_source(self):
|
def test_create_firewall_without_source(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['source_ip_address'] = None
|
attrs['source_ip_address'] = None
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 201
|
||||||
self.assertEqual(201, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_create_firewall_rule_without_destination(self):
|
def test_create_firewall_rule_without_destination(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['destination_ip_address'] = None
|
attrs['destination_ip_address'] = None
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 201
|
||||||
self.assertEqual(201, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_create_firewall_rule_without_protocol_with_dport(self):
|
def test_create_firewall_rule_without_protocol_with_dport(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['protocol'] = None
|
attrs['protocol'] = None
|
||||||
attrs['source_port'] = None
|
attrs['source_port'] = None
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_create_firewall_rule_without_protocol_with_sport(self):
|
def test_create_firewall_rule_without_protocol_with_sport(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['protocol'] = None
|
attrs['protocol'] = None
|
||||||
attrs['destination_port'] = None
|
attrs['destination_port'] = None
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_show_firewall_rule_with_fw_policy_not_associated(self):
|
def test_show_firewall_rule_with_fw_policy_not_associated(self):
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
@ -916,22 +534,22 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
attrs['source_ip_address'] = '::/0'
|
attrs['source_ip_address'] = '::/0'
|
||||||
attrs['destination_ip_address'] = '2001:db8:3::/64'
|
attrs['destination_ip_address'] = '2001:db8:3::/64'
|
||||||
attrs['ip_version'] = 4
|
attrs['ip_version'] = 4
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['source_ip_address'] = None
|
attrs['source_ip_address'] = None
|
||||||
attrs['destination_ip_address'] = '2001:db8:3::/64'
|
attrs['destination_ip_address'] = '2001:db8:3::/64'
|
||||||
attrs['ip_version'] = 4
|
attrs['ip_version'] = 4
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
attrs = self._get_test_firewall_rule_attrs()
|
attrs = self._get_test_firewall_rule_attrs()
|
||||||
attrs['source_ip_address'] = '::/0'
|
attrs['source_ip_address'] = '::/0'
|
||||||
attrs['destination_ip_address'] = None
|
attrs['destination_ip_address'] = None
|
||||||
attrs['ip_version'] = 4
|
attrs['ip_version'] = 4
|
||||||
res = self._create_firewall_rule(self.fmt, **attrs)
|
attrs['expected_res_status'] = 400
|
||||||
self.assertEqual(400, res.status_int)
|
self._create_firewall_rule(self.fmt, **attrs)
|
||||||
|
|
||||||
def test_list_firewall_rules(self):
|
def test_list_firewall_rules(self):
|
||||||
with self.firewall_rule(name='fwr1') as fwr1, \
|
with self.firewall_rule(name='fwr1') as fwr1, \
|
||||||
@ -950,7 +568,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
attrs['destination_port'] = '30:40'
|
attrs['destination_port'] = '30:40'
|
||||||
with self.firewall_rule() as fwr:
|
with self.firewall_rule() as fwr:
|
||||||
data = {'firewall_rule': {'name': name,
|
data = {'firewall_rule': {'name': name,
|
||||||
'protocol': PROTOCOL,
|
'protocol': self.PROTOCOL,
|
||||||
'source_port': '10:20',
|
'source_port': '10:20',
|
||||||
'destination_port': '30:40'}}
|
'destination_port': '30:40'}}
|
||||||
req = self.new_update_request('firewall_rules', data,
|
req = self.new_update_request('firewall_rules', data,
|
||||||
@ -964,7 +582,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
attrs['destination_port'] = '80'
|
attrs['destination_port'] = '80'
|
||||||
with self.firewall_rule() as fwr:
|
with self.firewall_rule() as fwr:
|
||||||
data = {'firewall_rule': {'name': name,
|
data = {'firewall_rule': {'name': name,
|
||||||
'protocol': PROTOCOL,
|
'protocol': self.PROTOCOL,
|
||||||
'source_port': 10000,
|
'source_port': 10000,
|
||||||
'destination_port': 80}}
|
'destination_port': 80}}
|
||||||
req = self.new_update_request('firewall_rules', data,
|
req = self.new_update_request('firewall_rules', data,
|
||||||
@ -978,7 +596,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
attrs['destination_port'] = '80'
|
attrs['destination_port'] = '80'
|
||||||
with self.firewall_rule() as fwr:
|
with self.firewall_rule() as fwr:
|
||||||
data = {'firewall_rule': {'name': name,
|
data = {'firewall_rule': {'name': name,
|
||||||
'protocol': PROTOCOL,
|
'protocol': self.PROTOCOL,
|
||||||
'source_port': '10000',
|
'source_port': '10000',
|
||||||
'destination_port': '80'}}
|
'destination_port': '80'}}
|
||||||
req = self.new_update_request('firewall_rules', data,
|
req = self.new_update_request('firewall_rules', data,
|
||||||
@ -1095,7 +713,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
|
|
||||||
@testtools.skip('bug/1614680')
|
@testtools.skip('bug/1614680')
|
||||||
def test_update_firewall_rule_associated_with_other_tenant_policy(self):
|
def test_update_firewall_rule_associated_with_other_tenant_policy(self):
|
||||||
with self.firewall_rule(shared=SHARED, tenant_id='tenant1') as fwr:
|
with self.firewall_rule(shared=self, tenant_id='tenant1') as fwr:
|
||||||
fwr_id = [fwr['firewall_rule']['id']]
|
fwr_id = [fwr['firewall_rule']['id']]
|
||||||
with self.firewall_policy(shared=False, firewall_rules=fwr_id):
|
with self.firewall_policy(shared=False, firewall_rules=fwr_id):
|
||||||
data = {'firewall_rule': {'shared': False}}
|
data = {'firewall_rule': {'shared': False}}
|
||||||
@ -1138,21 +756,6 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
res = req.get_response(self.ext_api)
|
res = req.get_response(self.ext_api)
|
||||||
self.assertEqual(409, res.status_int)
|
self.assertEqual(409, res.status_int)
|
||||||
|
|
||||||
def _test_create_firewall_group(self, attrs):
|
|
||||||
with self.firewall_policy() as fwp:
|
|
||||||
fwp_id = fwp['firewall_policy']['id']
|
|
||||||
attrs['ingress_firewall_policy_id'] = fwp_id
|
|
||||||
attrs['egress_firewall_policy_id'] = fwp_id
|
|
||||||
with self.firewall_group(
|
|
||||||
name=attrs['name'],
|
|
||||||
ingress_firewall_policy_id=fwp_id,
|
|
||||||
egress_firewall_policy_id=fwp_id,
|
|
||||||
admin_state_up=ADMIN_STATE_UP,
|
|
||||||
ports=attrs['ports'] if 'ports' in attrs else None,
|
|
||||||
) as firewall_group:
|
|
||||||
for k, v in six.iteritems(attrs):
|
|
||||||
self.assertEqual(v, firewall_group['firewall_group'][k])
|
|
||||||
|
|
||||||
def test_create_firewall_group(self):
|
def test_create_firewall_group(self):
|
||||||
attrs = self._get_test_firewall_group_attrs("firewall1")
|
attrs = self._get_test_firewall_group_attrs("firewall1")
|
||||||
self._test_create_firewall_group(attrs)
|
self._test_create_firewall_group(attrs)
|
||||||
@ -1247,11 +850,6 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
attrs = self._get_test_firewall_group_attrs("firewall1")
|
attrs = self._get_test_firewall_group_attrs("firewall1")
|
||||||
self._test_create_firewall_group(attrs)
|
self._test_create_firewall_group(attrs)
|
||||||
|
|
||||||
def test_create_firewall_group_with_dvr(self):
|
|
||||||
cfg.CONF.set_override('router_distributed', True)
|
|
||||||
attrs = self._get_test_firewall_group_attrs("firewall1", "CREATED")
|
|
||||||
self._test_create_firewall_group(attrs)
|
|
||||||
|
|
||||||
def test_create_firewall_group_with_fwp_does_not_exist(self):
|
def test_create_firewall_group_with_fwp_does_not_exist(self):
|
||||||
fmt = self.fmt
|
fmt = self.fmt
|
||||||
fwg_name = "firewall1"
|
fwg_name = "firewall1"
|
||||||
@ -1260,7 +858,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
self._create_firewall_group(fmt, fwg_name,
|
self._create_firewall_group(fmt, fwg_name,
|
||||||
description, not_found_fwp_id,
|
description, not_found_fwp_id,
|
||||||
not_found_fwp_id, ports=None,
|
not_found_fwp_id, ports=None,
|
||||||
admin_state_up=ADMIN_STATE_UP,
|
admin_state_up=self.ADMIN_STATE_UP,
|
||||||
expected_res_status=404)
|
expected_res_status=404)
|
||||||
|
|
||||||
def test_create_firewall_group_with_fwp_on_different_tenant(self):
|
def test_create_firewall_group_with_fwp_on_different_tenant(self):
|
||||||
@ -1296,10 +894,12 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
fwp_id = fwp['firewall_policy']['id']
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
ctx = self._get_admin_context()
|
ctx = self._get_admin_context()
|
||||||
target_tenant = 'tenant1'
|
target_tenant = 'tenant1'
|
||||||
with self.firewall_group(name=fwg_name,
|
with self.firewall_group(
|
||||||
ingress_firewall_policy_id=fwp_id,
|
name=fwg_name,
|
||||||
tenant_id=target_tenant, context=ctx,
|
ingress_firewall_policy_id=fwp_id,
|
||||||
admin_state_up=ADMIN_STATE_UP) as fwg:
|
tenant_id=target_tenant,
|
||||||
|
context=ctx,
|
||||||
|
admin_state_up=self.ADMIN_STATE_UP) as fwg:
|
||||||
self.assertEqual(target_tenant,
|
self.assertEqual(target_tenant,
|
||||||
fwg['firewall_group']['tenant_id'])
|
fwg['firewall_group']['tenant_id'])
|
||||||
|
|
||||||
@ -1308,13 +908,12 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
fwp_id = fwp['firewall_policy']['id']
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
attrs['ingress_firewall_policy_id'] = fwp_id
|
attrs['ingress_firewall_policy_id'] = fwp_id
|
||||||
attrs['egress_firewall_policy_id'] = fwp_id
|
attrs['egress_firewall_policy_id'] = fwp_id
|
||||||
attrs['status'] = 'PENDING_CREATE'
|
|
||||||
with self.firewall_group(
|
with self.firewall_group(
|
||||||
name=attrs['name'],
|
name=attrs['name'],
|
||||||
ports=attrs['ports'] if 'ports' in attrs else None,
|
ports=attrs['ports'] if 'ports' in attrs else None,
|
||||||
ingress_firewall_policy_id=fwp_id,
|
ingress_firewall_policy_id=fwp_id,
|
||||||
egress_firewall_policy_id=fwp_id,
|
egress_firewall_policy_id=fwp_id,
|
||||||
admin_state_up=ADMIN_STATE_UP) as firewall_group:
|
admin_state_up=self.ADMIN_STATE_UP) as firewall_group:
|
||||||
res = self._show_req('firewall_groups',
|
res = self._show_req('firewall_groups',
|
||||||
firewall_group['firewall_group']['id'])
|
firewall_group['firewall_group']['id'])
|
||||||
for k, v in six.iteritems(attrs):
|
for k, v in six.iteritems(attrs):
|
||||||
@ -1362,7 +961,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
fwp_id = fwp['firewall_policy']['id']
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
with self.firewall_group(
|
with self.firewall_group(
|
||||||
ingress_firewall_policy_id=fwp_id,
|
ingress_firewall_policy_id=fwp_id,
|
||||||
admin_state_up=ADMIN_STATE_UP) as firewall:
|
admin_state_up=self.ADMIN_STATE_UP) as firewall:
|
||||||
data = {'firewall_group': {'name': name}}
|
data = {'firewall_group': {'name': name}}
|
||||||
req = self.new_update_request('firewall_groups', data,
|
req = self.new_update_request('firewall_groups', data,
|
||||||
firewall['firewall_group']['id'])
|
firewall['firewall_group']['id'])
|
||||||
@ -1385,7 +984,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
||||||
with self.port(
|
with self.port(
|
||||||
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
||||||
ctx=ctx) as dummy_port:
|
tenant_id=ctx.project_id) as dummy_port:
|
||||||
port_id = dummy_port['port']['id']
|
port_id = dummy_port['port']['id']
|
||||||
success_cases = [
|
success_cases = [
|
||||||
{'ports': [port_id]},
|
{'ports': [port_id]},
|
||||||
@ -1406,7 +1005,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
||||||
with self.port(
|
with self.port(
|
||||||
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
||||||
ctx=ctx) as dummy_port:
|
tenant_id=ctx.project_id) as dummy_port:
|
||||||
port_id = dummy_port['port']['id']
|
port_id = dummy_port['port']['id']
|
||||||
conflict_cases = [
|
conflict_cases = [
|
||||||
{'name': ''},
|
{'name': ''},
|
||||||
@ -1432,7 +1031,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
ctx = self._get_admin_context()
|
ctx = self._get_admin_context()
|
||||||
with self.port(
|
with self.port(
|
||||||
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
||||||
ctx=ctx) as dummy_port:
|
tenant_id=ctx.project_id) as dummy_port:
|
||||||
port_id = dummy_port['port']['id']
|
port_id = dummy_port['port']['id']
|
||||||
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
||||||
success_cases = [
|
success_cases = [
|
||||||
@ -1457,7 +1056,7 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
ctx = self._get_admin_context()
|
ctx = self._get_admin_context()
|
||||||
with self.port(
|
with self.port(
|
||||||
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
device_owner=nl_constants.DEVICE_OWNER_ROUTER_INTF,
|
||||||
ctx=ctx) as dummy_port:
|
tenant_id=ctx.project_id) as dummy_port:
|
||||||
port_id = dummy_port['port']['id']
|
port_id = dummy_port['port']['id']
|
||||||
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
def_fwg_id = self._build_default_fwg(ctx=ctx)['id']
|
||||||
conflict_cases = [
|
conflict_cases = [
|
||||||
@ -1547,26 +1146,29 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
|
||||||
def test_update_firewall_group_fwp_not_found_on_different_tenant(self):
|
def test_update_firewall_group_fwp_not_found_on_different_tenant(self):
|
||||||
with self.firewall_policy(name='fwp1', tenant_id='tenant1',
|
ctx_tenant1 = self._get_nonadmin_context(tenant_id='tenant1')
|
||||||
do_delete=False) as fwp1, \
|
ctx_tenant2 = self._get_nonadmin_context(tenant_id='tenant2')
|
||||||
self.firewall_policy(name='fwp2', shared=False,
|
|
||||||
tenant_id='tenant2') as fwp2:
|
|
||||||
|
|
||||||
fwps = [fwp1, fwp2]
|
with self.firewall_policy(name='fwp1', context=ctx_tenant1,
|
||||||
# create firewall using fwp1 exists the same tenant.
|
shared=False, do_delete=False) as fwp1, \
|
||||||
fwp1_id = fwps[0]['firewall_policy']['id']
|
self.firewall_group(
|
||||||
fwp2_id = fwps[1]['firewall_policy']['id']
|
ingress_firewall_policy_id=fwp1['firewall_policy']['id'],
|
||||||
ctx = self._get_nonadmin_context()
|
context=ctx_tenant1, do_delete=False) as fwg:
|
||||||
with self.firewall_group(ingress_firewall_policy_id=fwp1_id,
|
fwg_id = fwg['firewall_group']['id']
|
||||||
context=ctx) as firewall:
|
# fw_db = self.db._get_firewall_group(ctx_tenant1, fwg_id)
|
||||||
fw_id = firewall['firewall_group']['id']
|
# fw_db['status'] = nl_constants.ACTIVE
|
||||||
fw_db = self.plugin._get_firewall_group(ctx, fw_id)
|
|
||||||
fw_db['status'] = nl_constants.ACTIVE
|
# update firewall from fwp1 to fwp2 (different tenant)
|
||||||
# update firewall from fwp1 to fwp2(different tenant)
|
with self.firewall_policy(name='fwp2', context=ctx_tenant2,
|
||||||
data = {'firewall_group':
|
shared=False) as fwp2:
|
||||||
{'ingress_firewall_policy_id': fwp2_id}}
|
data = {
|
||||||
req = self.new_update_request('firewall_groups', data, fw_id,
|
'firewall_group': {
|
||||||
context=ctx)
|
'ingress_firewall_policy_id':
|
||||||
|
fwp2['firewall_policy']['id'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
req = self.new_update_request('firewall_groups', data, fwg_id,
|
||||||
|
context=ctx_tenant1)
|
||||||
res = req.get_response(self.ext_api)
|
res = req.get_response(self.ext_api)
|
||||||
self.assertEqual(404, res.status_int)
|
self.assertEqual(404, res.status_int)
|
||||||
|
|
||||||
@ -1586,11 +1188,11 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
|
|
||||||
def test_delete_firewall_group_already_deleted(self):
|
def test_delete_firewall_group_already_deleted(self):
|
||||||
ctx = self._get_admin_context()
|
ctx = self._get_admin_context()
|
||||||
deleted_id = uuidutils.generate_uuid()
|
with self.firewall_group(do_delete=False, context=ctx) as fwg:
|
||||||
with self.firewall_group(do_delete=False) as fwg:
|
|
||||||
fwg_id = fwg['firewall_group']['id']
|
fwg_id = fwg['firewall_group']['id']
|
||||||
self.assertIsNone(self.plugin.delete_firewall_group(ctx, fwg_id))
|
self.assertIsNone(self.plugin.delete_firewall_group(ctx, fwg_id))
|
||||||
self.assertIsNone(self.plugin.delete_firewall_group(ctx, deleted_id))
|
# No error raise is fwg not found on delete
|
||||||
|
self.assertIsNone(self.plugin.delete_firewall_group(ctx, fwg_id))
|
||||||
|
|
||||||
def test_delete_default_firewall_group_with_admin(self):
|
def test_delete_default_firewall_group_with_admin(self):
|
||||||
ctx_a = self._get_admin_context()
|
ctx_a = self._get_admin_context()
|
||||||
@ -1980,45 +1582,36 @@ class TestFirewallDBPluginV2(FirewallPluginV2DbTestCase):
|
|||||||
def test_set_port_in_use_for_firewall_group(self):
|
def test_set_port_in_use_for_firewall_group(self):
|
||||||
fwg_db = {'id': 'fake_id'}
|
fwg_db = {'id': 'fake_id'}
|
||||||
new_ports = {'ports': ['fake_port1', 'fake_port2']}
|
new_ports = {'ports': ['fake_port1', 'fake_port2']}
|
||||||
m_context = context.get_admin_context()
|
m_context = self._get_admin_context()
|
||||||
with mock.patch.object(m_context.session, 'add',
|
with mock.patch.object(m_context.session, 'add',
|
||||||
side_effect=[None, f_exc.FirewallGroupPortInUse(
|
side_effect=[None, f_exc.FirewallGroupPortInUse(
|
||||||
port_ids=['fake_port2'])]):
|
port_ids=['fake_port2'])]):
|
||||||
self.assertRaises(f_exc.FirewallGroupPortInUse,
|
self.assertRaises(f_exc.FirewallGroupPortInUse,
|
||||||
self.plugin._set_ports_for_firewall_group,
|
self.db._set_ports_for_firewall_group,
|
||||||
m_context,
|
m_context,
|
||||||
fwg_db,
|
fwg_db,
|
||||||
new_ports)
|
new_ports)
|
||||||
|
|
||||||
def test_set_port_for_default_firewall_group(self):
|
def test_set_port_for_default_firewall_group(self):
|
||||||
ctx = self._get_nonadmin_context()
|
ctx = self._get_nonadmin_context()
|
||||||
self._build_default_fwg(ctx=ctx)
|
default_fwg = self._build_default_fwg(ctx=ctx)
|
||||||
with self.port(project_id=ctx.tenant_id) as port1, \
|
port_args = {
|
||||||
self.port(project_id=ctx.tenant_id) as port2:
|
'tenant_id': ctx.tenant_id,
|
||||||
|
'device_owner': 'compute:nova',
|
||||||
|
'binding:vif_type': 'ovs',
|
||||||
|
}
|
||||||
|
self.plugin._is_supported_by_fw_l2_driver = mock.Mock(
|
||||||
|
return_value=True)
|
||||||
|
with self.port(**port_args) as port1, self.port(**port_args) as port2:
|
||||||
port1_id = port1['port']['id']
|
port1_id = port1['port']['id']
|
||||||
port2_id = port2['port']['id']
|
port2_id = port2['port']['id']
|
||||||
port_ids = [port1_id, port2_id]
|
port_ids = [port1_id, port2_id]
|
||||||
project_id = ctx.tenant_id
|
|
||||||
|
|
||||||
self.plugin.set_port_for_default_firewall_group(
|
self.plugin.update_firewall_group(
|
||||||
ctx, port1_id, project_id)
|
ctx,
|
||||||
self.plugin.set_port_for_default_firewall_group(
|
default_fwg['id'],
|
||||||
ctx, port2_id, project_id)
|
{'firewall_group': {'ports': port_ids}},
|
||||||
def_fwg_db = self.plugin._get_default_fwg(ctx, project_id)
|
)
|
||||||
self.assertEqual('PENDING_UPDATE', def_fwg_db['status'])
|
default_fwg = self.plugin.get_firewall_group(ctx,
|
||||||
self.assertEqual(sorted(port_ids), sorted(def_fwg_db['ports']))
|
default_fwg['id'])
|
||||||
|
self.assertEqual(sorted(port_ids), sorted(default_fwg['ports']))
|
||||||
def test_set_port_for_default_firewall_group_raised_port_in_use(self):
|
|
||||||
ctx = self._get_nonadmin_context()
|
|
||||||
self._build_default_fwg(ctx=ctx)
|
|
||||||
self.plugin.update_firewall_group_status = mock.Mock()
|
|
||||||
with self.port(project_id=ctx.tenant_id) as port1:
|
|
||||||
port1_id = port1['port']['id']
|
|
||||||
port_ids = [port1_id]
|
|
||||||
self.plugin._set_ports_for_firewall_group = mock.Mock(
|
|
||||||
side_effect=f_exc.FirewallGroupPortInUse(port_ids=port_ids))
|
|
||||||
project_id = ctx.tenant_id
|
|
||||||
|
|
||||||
self.plugin.set_port_for_default_firewall_group(
|
|
||||||
ctx, port1_id, project_id)
|
|
||||||
self.plugin.update_firewall_group_status.assert_not_called()
|
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from neutron import manager
|
from neutron import manager
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.noop import noop_driver
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
|
noop import noop_driver
|
||||||
from neutron_fwaas.tests import base
|
from neutron_fwaas.tests import base
|
||||||
|
|
||||||
|
|
@ -24,12 +24,12 @@ from neutron.plugins.ml2.drivers.openvswitch.agent import \
|
|||||||
ovs_agent_extension_api as ovs_ext_api
|
ovs_agent_extension_api as ovs_ext_api
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
import constants as fwaas_ovs_consts
|
openvswitch_firewall import constants as fwaas_ovs_consts
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
import exceptions
|
openvswitch_firewall import exceptions
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
import firewall as ovsfw
|
openvswitch_firewall import firewall as ovsfw
|
||||||
|
|
||||||
TESTING_VLAN_TAG = 1
|
TESTING_VLAN_TAG = 1
|
||||||
|
|
@ -20,12 +20,12 @@ from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \
|
|||||||
as ovs_consts
|
as ovs_consts
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
import constants as fwaas_ovs_consts
|
openvswitch_firewall import constants as fwaas_ovs_consts
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
import firewall as ovsfw
|
openvswitch_firewall import firewall as ovsfw
|
||||||
from neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall \
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.\
|
||||||
import rules
|
openvswitch_firewall import rules
|
||||||
|
|
||||||
TESTING_VLAN_TAG = 1
|
TESTING_VLAN_TAG = 1
|
||||||
|
|
@ -19,7 +19,8 @@ import mock
|
|||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
from neutron.tests.unit.api.v2 import test_base as test_api_v2
|
from neutron.tests.unit.api.v2 import test_base as test_api_v2
|
||||||
|
|
||||||
import neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas as fwaas
|
import neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.\
|
||||||
|
iptables_fwaas as fwaas
|
||||||
|
|
||||||
|
|
||||||
_uuid = test_api_v2._uuid
|
_uuid = test_api_v2._uuid
|
@ -19,7 +19,8 @@ import mock
|
|||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
from neutron.tests.unit.api.v2 import test_base as test_api_v2
|
from neutron.tests.unit.api.v2 import test_base as test_api_v2
|
||||||
|
|
||||||
import neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas_v2 as fwaas
|
import neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.\
|
||||||
|
iptables_fwaas_v2 as fwaas
|
||||||
|
|
||||||
|
|
||||||
_uuid = test_api_v2._uuid
|
_uuid = test_api_v2._uuid
|
@ -17,7 +17,8 @@ import mock
|
|||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
from neutron_fwaas.services.firewall.drivers.linux import legacy_conntrack
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux \
|
||||||
|
import legacy_conntrack
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
|
|
||||||
|
|
||||||
@ -128,8 +129,8 @@ class ConntrackLegacyTestCase(base.BaseTestCase):
|
|||||||
|
|
||||||
def test_delete_entries(self):
|
def test_delete_entries(self):
|
||||||
list_entries_mock = mock.patch(
|
list_entries_mock = mock.patch(
|
||||||
'neutron_fwaas.services.firewall.drivers.linux'
|
'neutron_fwaas.services.firewall.service_drivers.agents.drivers.'
|
||||||
'.legacy_conntrack.ConntrackLegacy.list_entries')
|
'linux.legacy_conntrack.ConntrackLegacy.list_entries')
|
||||||
self.list_entries = list_entries_mock.start()
|
self.list_entries = list_entries_mock.start()
|
||||||
|
|
||||||
self.conntrack_driver.list_entries.return_value = [
|
self.conntrack_driver.list_entries.return_value = [
|
@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.drivers.linux import netlink_conntrack
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux \
|
||||||
|
import netlink_conntrack
|
||||||
from neutron_fwaas.tests import base
|
from neutron_fwaas.tests import base
|
||||||
|
|
||||||
FW_RULES = [
|
FW_RULES = [
|
@ -21,9 +21,10 @@ from neutron_lib.exceptions import firewall_v2 as f_exc
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants as consts
|
from neutron_fwaas.common import fwaas_constants as consts
|
||||||
from neutron_fwaas.services.firewall.agents.l2 import fwaas_v2
|
from neutron_fwaas.services.firewall.service_drivers.agents.l2 import fwaas_v2
|
||||||
from neutron_fwaas.tests import base
|
from neutron_fwaas.tests import base
|
||||||
from neutron_fwaas.tests.unit.services.firewall.agents.l2 import fake_data
|
from neutron_fwaas.tests.unit.services.firewall.service_drivers.agents.l2\
|
||||||
|
import fake_data
|
||||||
|
|
||||||
|
|
||||||
class TestFWaasV2AgentExtensionBase(base.BaseTestCase):
|
class TestFWaasV2AgentExtensionBase(base.BaseTestCase):
|
@ -24,11 +24,12 @@ from oslo_utils import uuidutils
|
|||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants
|
from neutron_fwaas.common import fwaas_constants
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api
|
from neutron_fwaas.services.firewall.service_drivers.agents \
|
||||||
from neutron_fwaas.services.firewall.agents.l3reference \
|
import firewall_agent_api
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents.l3reference \
|
||||||
import firewall_l3_agent
|
import firewall_l3_agent
|
||||||
from neutron_fwaas.tests import base
|
from neutron_fwaas.tests import base
|
||||||
from neutron_fwaas.tests.unit.services.firewall.agents \
|
from neutron_fwaas.tests.unit.services.firewall.service_drivers.agents \
|
||||||
import test_firewall_agent_api
|
import test_firewall_agent_api
|
||||||
|
|
||||||
|
|
@ -23,13 +23,14 @@ from oslo_config import cfg
|
|||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
from neutron_fwaas.common import fwaas_constants
|
from neutron_fwaas.common import fwaas_constants
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux \
|
||||||
from neutron_fwaas.services.firewall.agents.l3reference \
|
|
||||||
import firewall_l3_agent_v2
|
|
||||||
from neutron_fwaas.services.firewall.drivers.linux \
|
|
||||||
import iptables_fwaas_v2
|
import iptables_fwaas_v2
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents \
|
||||||
|
import firewall_agent_api
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents.l3reference \
|
||||||
|
import firewall_l3_agent_v2
|
||||||
from neutron_fwaas.tests import base
|
from neutron_fwaas.tests import base
|
||||||
from neutron_fwaas.tests.unit.services.firewall.agents \
|
from neutron_fwaas.tests.unit.services.firewall.service_drivers.agents \
|
||||||
import test_firewall_agent_api
|
import test_firewall_agent_api
|
||||||
|
|
||||||
|
|
@ -0,0 +1,654 @@
|
|||||||
|
# Copyright 2016
|
||||||
|
# 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 mock
|
||||||
|
import six
|
||||||
|
|
||||||
|
from neutron import extensions as neutron_extensions
|
||||||
|
from neutron.tests.unit.extensions import test_l3
|
||||||
|
from neutron_lib import constants as nl_constants
|
||||||
|
from neutron_lib import context
|
||||||
|
from neutron_lib.exceptions import firewall_v2 as f_exc
|
||||||
|
from neutron_lib.plugins import directory
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from neutron_fwaas._i18n import _
|
||||||
|
from neutron_fwaas.db.firewall.v2.firewall_db_v2 import FirewallGroup
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents import agents
|
||||||
|
from neutron_fwaas.tests import base
|
||||||
|
from neutron_fwaas.tests.unit.services.firewall import test_fwaas_plugin_v2
|
||||||
|
|
||||||
|
|
||||||
|
FIREWALL_AGENT_PLUGIN = ('neutron_fwaas.services.firewall.service_drivers.'
|
||||||
|
'agents.agents')
|
||||||
|
FIREWALL_AGENT_PLUGIN_KLASS = FIREWALL_AGENT_PLUGIN + '.FirewallAgentDriver'
|
||||||
|
DELETEFW_PATH = (FIREWALL_AGENT_PLUGIN + '.FirewallAgentApi.'
|
||||||
|
'delete_firewall_group')
|
||||||
|
|
||||||
|
|
||||||
|
class FakeAgentApi(agents.FirewallAgentCallbacks):
|
||||||
|
"""
|
||||||
|
This class used to mock the AgentAPI delete method inherits from
|
||||||
|
FirewallCallbacks because it needs access to the firewall_deleted method.
|
||||||
|
The delete_firewall method belongs to the FirewallAgentApi, which has
|
||||||
|
no access to the firewall_deleted method normally because it's not
|
||||||
|
responsible for deleting the firewall from the DB. However, it needs
|
||||||
|
to in the unit tests since there is no agent to call back.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def delete_firewall_group(self, context, firewall_group, **kwargs):
|
||||||
|
self.plugin = directory.get_plugin('FIREWALL_V2')
|
||||||
|
self.firewall_db = self.plugin.driver.firewall_db
|
||||||
|
self.firewall_group_deleted(context, firewall_group['id'], **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TestFirewallAgentApi(base.BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestFirewallAgentApi, self).setUp()
|
||||||
|
|
||||||
|
self.api = agents.FirewallAgentApi('topic', 'host')
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
self.assertEqual('topic', self.api.client.target.topic)
|
||||||
|
self.assertEqual('host', self.api.host)
|
||||||
|
|
||||||
|
def _call_test_helper(self, method_name):
|
||||||
|
with mock.patch.object(self.api.client, 'cast') as rpc_mock, \
|
||||||
|
mock.patch.object(self.api.client, 'prepare') as prepare_mock:
|
||||||
|
prepare_mock.return_value = self.api.client
|
||||||
|
getattr(self.api, method_name)(mock.sentinel.context, 'test')
|
||||||
|
|
||||||
|
prepare_args = {'fanout': True}
|
||||||
|
prepare_mock.assert_called_once_with(**prepare_args)
|
||||||
|
|
||||||
|
rpc_mock.assert_called_once_with(mock.sentinel.context, method_name,
|
||||||
|
firewall_group='test', host='host')
|
||||||
|
|
||||||
|
def test_create_firewall_group(self):
|
||||||
|
self._call_test_helper('create_firewall_group')
|
||||||
|
|
||||||
|
def test_update_firewall_group(self):
|
||||||
|
self._call_test_helper('update_firewall_group')
|
||||||
|
|
||||||
|
def test_delete_firewall_group(self):
|
||||||
|
self._call_test_helper('delete_firewall_group')
|
||||||
|
|
||||||
|
|
||||||
|
class TestAgentDriver(test_fwaas_plugin_v2.FirewallPluginV2TestCase,
|
||||||
|
test_l3.L3NatTestCaseMixin):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.agentapi_del_fw_p = mock.patch(
|
||||||
|
DELETEFW_PATH, create=True,
|
||||||
|
new=FakeAgentApi().delete_firewall_group,
|
||||||
|
).start()
|
||||||
|
mock.patch.object(agents.neutron_rpc, 'get_client').start()
|
||||||
|
mock.patch.object(agents.neutron_rpc, 'Connection').start()
|
||||||
|
|
||||||
|
l3_plugin_str = ('neutron.tests.unit.extensions.test_l3.'
|
||||||
|
'TestL3NatServicePlugin')
|
||||||
|
l3_plugin = {'l3_plugin_name': l3_plugin_str}
|
||||||
|
super(TestAgentDriver, self).setUp(
|
||||||
|
service_provider=FIREWALL_AGENT_PLUGIN_KLASS,
|
||||||
|
extra_service_plugins=l3_plugin,
|
||||||
|
extra_extension_paths=neutron_extensions.__path__)
|
||||||
|
|
||||||
|
self.callbacks = self.plugin.driver.endpoints[0]
|
||||||
|
self.db = self.plugin.driver.firewall_db
|
||||||
|
|
||||||
|
router_distributed_opts = [
|
||||||
|
cfg.BoolOpt(
|
||||||
|
'router_distributed',
|
||||||
|
default=False,
|
||||||
|
help=_("System-wide flag to determine the type of router "
|
||||||
|
"that tenants can create. Only admin can override.")),
|
||||||
|
]
|
||||||
|
cfg.CONF.register_opts(router_distributed_opts)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _self_context(self):
|
||||||
|
return context.Context('', self._tenant_id)
|
||||||
|
|
||||||
|
def _get_test_firewall_group_attrs(self, name,
|
||||||
|
status=nl_constants.INACTIVE):
|
||||||
|
return super(TestAgentDriver, self)._get_test_firewall_group_attrs(
|
||||||
|
name, status=status)
|
||||||
|
|
||||||
|
def test_set_firewall_group_status(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
admin_state_up=self.ADMIN_STATE_UP
|
||||||
|
) as fwg:
|
||||||
|
fwg_id = fwg['firewall_group']['id']
|
||||||
|
res = self.callbacks.set_firewall_group_status(ctx, fwg_id,
|
||||||
|
nl_constants.ACTIVE)
|
||||||
|
fwg_db = self.plugin.get_firewall_group(ctx, fwg_id)
|
||||||
|
self.assertEqual(nl_constants.ACTIVE, fwg_db['status'])
|
||||||
|
self.assertTrue(res)
|
||||||
|
res = self.callbacks.set_firewall_group_status(ctx, fwg_id,
|
||||||
|
nl_constants.ERROR)
|
||||||
|
fwg_db = self.plugin.get_firewall_group(ctx, fwg_id)
|
||||||
|
self.assertEqual(nl_constants.ERROR, fwg_db['status'])
|
||||||
|
self.assertFalse(res)
|
||||||
|
|
||||||
|
def test_firewall_group_deleted(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
admin_state_up=self.ADMIN_STATE_UP,
|
||||||
|
do_delete=False
|
||||||
|
) as fwg:
|
||||||
|
fwg_id = fwg['firewall_group']['id']
|
||||||
|
with ctx.session.begin(subtransactions=True):
|
||||||
|
fwg_db = self.db._get_firewall_group(ctx, fwg_id)
|
||||||
|
fwg_db['status'] = nl_constants.PENDING_DELETE
|
||||||
|
|
||||||
|
observed = self.callbacks.firewall_group_deleted(ctx, fwg_id)
|
||||||
|
self.assertTrue(observed)
|
||||||
|
|
||||||
|
self.assertRaises(f_exc.FirewallGroupNotFound,
|
||||||
|
self.plugin.get_firewall_group,
|
||||||
|
ctx, fwg_id)
|
||||||
|
|
||||||
|
def test_firewall_group_deleted_concurrently(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
alt_ctx = context.get_admin_context()
|
||||||
|
|
||||||
|
_get_firewall_group = self.db._get_firewall_group
|
||||||
|
|
||||||
|
def getdelete(context, fwg_id):
|
||||||
|
fwg_db = _get_firewall_group(context, fwg_id)
|
||||||
|
# NOTE(cby): Use a different session to simulate a concurrent del
|
||||||
|
with alt_ctx.session.begin(subtransactions=True):
|
||||||
|
alt_ctx.session.query(FirewallGroup).filter_by(
|
||||||
|
id=fwg_id).delete()
|
||||||
|
return fwg_db
|
||||||
|
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
firewall_policy_id=fwp_id,
|
||||||
|
admin_state_up=self.ADMIN_STATE_UP,
|
||||||
|
do_delete=False
|
||||||
|
) as fwg:
|
||||||
|
fwg_id = fwg['firewall_group']['id']
|
||||||
|
with ctx.session.begin(subtransactions=True):
|
||||||
|
fwg_db = self.db._get_firewall_group(ctx, fwg_id)
|
||||||
|
fwg_db['status'] = nl_constants.PENDING_DELETE
|
||||||
|
ctx.session.flush()
|
||||||
|
|
||||||
|
with mock.patch.object(
|
||||||
|
self.db, '_get_firewall_group', side_effect=getdelete
|
||||||
|
):
|
||||||
|
observed = self.callbacks.firewall_group_deleted(
|
||||||
|
ctx, fwg_id)
|
||||||
|
self.assertTrue(observed)
|
||||||
|
|
||||||
|
self.assertRaises(f_exc.FirewallGroupNotFound,
|
||||||
|
self.plugin.get_firewall_group,
|
||||||
|
ctx, fwg_id)
|
||||||
|
|
||||||
|
def test_firewall_group_deleted_not_found(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
observed = self.callbacks.firewall_group_deleted(
|
||||||
|
ctx, 'notfound')
|
||||||
|
self.assertTrue(observed)
|
||||||
|
|
||||||
|
def test_firewall_group_deleted_error(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
firewall_policy_id=fwp_id,
|
||||||
|
admin_state_up=self.ADMIN_STATE_UP,
|
||||||
|
) as fwg:
|
||||||
|
fwg_id = fwg['firewall_group']['id']
|
||||||
|
observed = self.callbacks.firewall_group_deleted(
|
||||||
|
ctx, fwg_id)
|
||||||
|
self.assertFalse(observed)
|
||||||
|
fwg_db = self.db._get_firewall_group(ctx, fwg_id)
|
||||||
|
self.assertEqual(nl_constants.ERROR, fwg_db['status'])
|
||||||
|
|
||||||
|
def test_create_firewall_group_ports_not_specified(self):
|
||||||
|
"""neutron firewall-create test-policy """
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
egress_firewall_policy_id=fwp_id,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.INACTIVE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
|
||||||
|
def test_create_firewall_group_with_ports(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1, \
|
||||||
|
self.subnet(cidr='20.0.0.0/24') as s2:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s2['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id2 = body['port_id']
|
||||||
|
fwg_ports = [port_id1, port_id2]
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
egress_firewall_policy_id=fwp_id, ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.PENDING_CREATE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
|
||||||
|
def test_create_firewall_group_with_ports_on_diff_routers(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1, \
|
||||||
|
self.subnet(cidr='20.0.0.0/24') as s2:
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s2['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id2 = body['port_id']
|
||||||
|
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r2, \
|
||||||
|
self.subnet() as s3:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r2['router']['id'],
|
||||||
|
s3['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id3 = body['port_id']
|
||||||
|
|
||||||
|
fwg_ports = [port_id1, port_id2, port_id3]
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
egress_firewall_policy_id=fwp_id,
|
||||||
|
ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.PENDING_CREATE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
|
||||||
|
def test_create_firewall_group_with_ports_no_policy(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1, \
|
||||||
|
self.subnet(cidr='20.0.0.0/24') as s2:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s2['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id2 = body['port_id']
|
||||||
|
fwg_ports = [port_id1, port_id2]
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
default_policy=False,
|
||||||
|
ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.INACTIVE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
|
||||||
|
def test_update_firewall_group_with_new_ports_no_policy(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1, \
|
||||||
|
self.subnet(cidr='20.0.0.0/24') as s2, \
|
||||||
|
self.subnet(cidr='30.0.0.0/24') as s3:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s2['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id2 = body['port_id']
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s3['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id3 = body['port_id']
|
||||||
|
|
||||||
|
fwg_ports = [port_id1, port_id2]
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
default_policy=False,
|
||||||
|
ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.INACTIVE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
data = {'firewall_group': {'ports': [port_id2, port_id3]}}
|
||||||
|
req = self.new_update_request('firewall_groups', data,
|
||||||
|
fwg1['firewall_group']['id'],
|
||||||
|
context=self._self_context)
|
||||||
|
res = self.deserialize(self.fmt,
|
||||||
|
req.get_response(self.ext_api))
|
||||||
|
|
||||||
|
self.assertEqual(sorted([port_id2, port_id3]),
|
||||||
|
sorted(res['firewall_group']['ports']))
|
||||||
|
|
||||||
|
self.assertEqual(nl_constants.INACTIVE,
|
||||||
|
res['firewall_group']['status'])
|
||||||
|
|
||||||
|
def test_update_firewall_group_with_new_ports_status_pending(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1, \
|
||||||
|
self.subnet(cidr='20.0.0.0/24') as s2, \
|
||||||
|
self.subnet(cidr='30.0.0.0/24') as s3:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s2['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id2 = body['port_id']
|
||||||
|
fwg_ports = [port_id1, port_id2]
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s3['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id3 = body['port_id']
|
||||||
|
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
egress_firewall_policy_id=fwp_id, ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.PENDING_CREATE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
data = {'firewall_group': {'ports': [port_id2, port_id3]}}
|
||||||
|
req = self.new_update_request('firewall_groups', data,
|
||||||
|
fwg1['firewall_group']['id'])
|
||||||
|
res = req.get_response(self.ext_api)
|
||||||
|
self.assertEqual(409, res.status_int)
|
||||||
|
|
||||||
|
def test_update_firewall_group_with_new_ports_status_active(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1, \
|
||||||
|
self.subnet(cidr='20.0.0.0/24') as s2, \
|
||||||
|
self.subnet(cidr='30.0.0.0/24') as s3:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s2['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id2 = body['port_id']
|
||||||
|
fwg_ports = [port_id1, port_id2]
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s3['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id3 = body['port_id']
|
||||||
|
|
||||||
|
with self.firewall_policy() as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
egress_firewall_policy_id=fwp_id, ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.PENDING_CREATE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
self.callbacks.set_firewall_group_status(ctx,
|
||||||
|
fwg1['firewall_group']['id'], nl_constants.ACTIVE)
|
||||||
|
data = {'firewall_group': {'ports': [port_id2, port_id3]}}
|
||||||
|
req = self.new_update_request('firewall_groups', data,
|
||||||
|
fwg1['firewall_group']['id'],
|
||||||
|
context=self._self_context)
|
||||||
|
res = self.deserialize(self.fmt,
|
||||||
|
req.get_response(self.ext_api))
|
||||||
|
self.assertEqual(sorted([port_id2, port_id3]),
|
||||||
|
sorted(res['firewall_group']['ports']))
|
||||||
|
|
||||||
|
def test_update_firewall_rule_on_active_fwg(self):
|
||||||
|
name = "new_firewall_rule1"
|
||||||
|
attrs = self._get_test_firewall_rule_attrs(name)
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
with self.firewall_rule() as fwr:
|
||||||
|
with self.firewall_policy(
|
||||||
|
firewall_rules=[fwr['firewall_rule']['id']]) as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
egress_firewall_policy_id=fwp_id, ports=[port_id1],
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.PENDING_CREATE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
self.callbacks.set_firewall_group_status(ctx,
|
||||||
|
fwg1['firewall_group']['id'], nl_constants.ACTIVE)
|
||||||
|
data = {'firewall_rule': {'name': name}}
|
||||||
|
req = self.new_update_request('firewall_rules', data,
|
||||||
|
fwr['firewall_rule']['id'])
|
||||||
|
res = self.deserialize(self.fmt,
|
||||||
|
req.get_response(self.ext_api))
|
||||||
|
for k, v in six.iteritems(attrs):
|
||||||
|
self.assertEqual(v, res['firewall_rule'][k])
|
||||||
|
|
||||||
|
def test_update_firewall_rule_on_pending_create_fwg(self):
|
||||||
|
"""update should fail"""
|
||||||
|
name = "new_firewall_rule1"
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet() as s1:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
with self.firewall_rule() as fwr:
|
||||||
|
with self.firewall_policy(
|
||||||
|
firewall_rules=[fwr['firewall_rule']['id']]) as fwp:
|
||||||
|
fwp_id = fwp['firewall_policy']['id']
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
ingress_firewall_policy_id=fwp_id,
|
||||||
|
egress_firewall_policy_id=fwp_id, ports=[port_id1],
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.PENDING_CREATE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
|
||||||
|
data = {'firewall_rule': {'name': name}}
|
||||||
|
req = self.new_update_request('firewall_rules', data,
|
||||||
|
fwr['firewall_rule']['id'])
|
||||||
|
res = req.get_response(self.ext_api)
|
||||||
|
self.assertEqual(409, res.status_int)
|
||||||
|
|
||||||
|
def test_update_firewall_group_with_non_exist_ports(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r, \
|
||||||
|
self.subnet(cidr='30.0.0.0/24') as s:
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
foo_port_id = 'caef152d-b118-4b9b-bc77-800661bf082d'
|
||||||
|
fwg_ports = [port_id1]
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
default_policy=False,
|
||||||
|
ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.INACTIVE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
data = {'firewall_group': {'ports': [foo_port_id]}}
|
||||||
|
req = self.new_update_request('firewall_groups', data,
|
||||||
|
fwg1['firewall_group']['id'])
|
||||||
|
res = self.deserialize(self.fmt,
|
||||||
|
req.get_response(self.ext_api))
|
||||||
|
self.assertEqual('PortNotFound',
|
||||||
|
res['NeutronError']['type'])
|
||||||
|
|
||||||
|
def test_update_firewall_group_with_ports_and_policy(self):
|
||||||
|
"""neutron firewall_group create test-policy """
|
||||||
|
with self.router(name='router1', admin_state_up=True,
|
||||||
|
tenant_id=self._tenant_id) as r,\
|
||||||
|
self.subnet() as s1,\
|
||||||
|
self.subnet(cidr='20.0.0.0/24') as s2:
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s1['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id1 = body['port_id']
|
||||||
|
|
||||||
|
body = self._router_interface_action(
|
||||||
|
'add',
|
||||||
|
r['router']['id'],
|
||||||
|
s2['subnet']['id'],
|
||||||
|
None)
|
||||||
|
port_id2 = body['port_id']
|
||||||
|
|
||||||
|
fwg_ports = [port_id1, port_id2]
|
||||||
|
with self.firewall_rule() as fwr:
|
||||||
|
with self.firewall_policy(
|
||||||
|
firewall_rules=[fwr['firewall_rule']['id']]) as fwp:
|
||||||
|
with self.firewall_group(
|
||||||
|
name='test',
|
||||||
|
default_policy=False,
|
||||||
|
ports=fwg_ports,
|
||||||
|
admin_state_up=True) as fwg1:
|
||||||
|
self.assertEqual(nl_constants.INACTIVE,
|
||||||
|
fwg1['firewall_group']['status'])
|
||||||
|
fwp_id = fwp["firewall_policy"]["id"]
|
||||||
|
|
||||||
|
data = {'firewall_group': {'ports': fwg_ports}}
|
||||||
|
req = (self.
|
||||||
|
new_update_request('firewall_groups', data,
|
||||||
|
fwg1['firewall_group']['id'],
|
||||||
|
context=self._self_context))
|
||||||
|
res = self.deserialize(self.fmt,
|
||||||
|
req.get_response(self.ext_api))
|
||||||
|
self.assertEqual(nl_constants.INACTIVE,
|
||||||
|
res['firewall_group']['status'])
|
||||||
|
|
||||||
|
data = {'firewall_group': {
|
||||||
|
'ingress_firewall_policy_id': fwp_id}}
|
||||||
|
req = (self.
|
||||||
|
new_update_request('firewall_groups', data,
|
||||||
|
fwg1['firewall_group']['id'],
|
||||||
|
context=self._self_context))
|
||||||
|
res = self.deserialize(self.fmt,
|
||||||
|
req.get_response(self.ext_api))
|
||||||
|
self.assertEqual(nl_constants.PENDING_UPDATE,
|
||||||
|
res['firewall_group']['status'])
|
||||||
|
|
||||||
|
def test_create_firewall_group_with_dvr(self):
|
||||||
|
cfg.CONF.set_override('router_distributed', True)
|
||||||
|
attrs = self._get_test_firewall_group_attrs("firewall1")
|
||||||
|
self._test_create_firewall_group(attrs)
|
||||||
|
|
||||||
|
def test_create_firewall_group(self):
|
||||||
|
attrs = self._get_test_firewall_group_attrs("firewall1")
|
||||||
|
self._test_create_firewall_group(attrs)
|
||||||
|
|
||||||
|
def test_create_firewall_group_with_empty_ports(self):
|
||||||
|
attrs = self._get_test_firewall_group_attrs("fwg1")
|
||||||
|
attrs['ports'] = []
|
||||||
|
self._test_create_firewall_group(attrs)
|
@ -15,9 +15,12 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers \
|
||||||
from neutron_fwaas.services.firewall.drivers import fwaas_base
|
import fwaas_base
|
||||||
from neutron_fwaas.services.firewall.drivers import fwaas_base_v2
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers \
|
||||||
|
import fwaas_base_v2
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents \
|
||||||
|
import firewall_agent_api as api
|
||||||
from neutron_fwaas.tests import base
|
from neutron_fwaas.tests import base
|
||||||
|
|
||||||
|
|
@ -16,10 +16,12 @@
|
|||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_service
|
from neutron_fwaas.services.firewall.service_drivers.agents import\
|
||||||
|
firewall_service
|
||||||
|
|
||||||
FWAAS_NOP_DEVICE = ('neutron_fwaas.tests.unit.services.firewall.agents.'
|
FWAAS_NOP_DEVICE = ('neutron_fwaas.tests.unit.services.firewall.'
|
||||||
'test_firewall_agent_api.NoopFwaasDriver')
|
'service_drivers.agents.test_firewall_agent_api.'
|
||||||
|
'NoopFwaasDriver')
|
||||||
|
|
||||||
|
|
||||||
class TestFirewallDeviceDriverLoading(base.BaseTestCase):
|
class TestFirewallDeviceDriverLoading(base.BaseTestCase):
|
File diff suppressed because it is too large
Load Diff
22
setup.cfg
22
setup.cfg
@ -34,9 +34,9 @@ setup-hooks =
|
|||||||
firewall_drivers =
|
firewall_drivers =
|
||||||
# These are for backwards compat with Juno firewall service provider
|
# These are for backwards compat with Juno firewall service provider
|
||||||
# configuration values
|
# configuration values
|
||||||
neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
||||||
iptables = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
iptables = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
||||||
iptables_v2 = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas_v2:IptablesFwaasDriver
|
iptables_v2 = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas_v2:IptablesFwaasDriver
|
||||||
neutron.service_plugins =
|
neutron.service_plugins =
|
||||||
firewall = neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin
|
firewall = neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin
|
||||||
firewall_v2 = neutron_fwaas.services.firewall.fwaas_plugin_v2:FirewallPluginV2
|
firewall_v2 = neutron_fwaas.services.firewall.fwaas_plugin_v2:FirewallPluginV2
|
||||||
@ -50,16 +50,16 @@ oslo.config.opts =
|
|||||||
neutron.fwaas = neutron_fwaas.opts:list_opts
|
neutron.fwaas = neutron_fwaas.opts:list_opts
|
||||||
firewall.agent = neutron_fwaas.opts:list_agent_opts
|
firewall.agent = neutron_fwaas.opts:list_agent_opts
|
||||||
neutron.agent.l2.extensions =
|
neutron.agent.l2.extensions =
|
||||||
fwaas_v2 = neutron_fwaas.services.firewall.agents.l2.fwaas_v2:FWaaSV2AgentExtension
|
fwaas_v2 = neutron_fwaas.services.firewall.service_drivers.agents.l2.fwaas_v2:FWaaSV2AgentExtension
|
||||||
neutron.agent.l2.firewall_drivers =
|
neutron.agent.l2.firewall_drivers =
|
||||||
noop = neutron_fwaas.services.firewall.drivers.linux.l2.noop.noop_driver:NoopFirewallL2Driver
|
noop = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.noop.noop_driver:NoopFirewallL2Driver
|
||||||
ovs = neutron_fwaas.services.firewall.drivers.linux.l2.openvswitch_firewall.firewall:OVSFirewallDriver
|
ovs = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.openvswitch_firewall.firewall:OVSFirewallDriver
|
||||||
neutron.agent.l3.extensions =
|
neutron.agent.l3.extensions =
|
||||||
fwaas = neutron_fwaas.services.firewall.agents.l3reference.firewall_l3_agent:L3WithFWaaS
|
fwaas = neutron_fwaas.services.firewall.service_drivers.agents.l3reference.firewall_l3_agent:L3WithFWaaS
|
||||||
fwaas_v2 = neutron_fwaas.services.firewall.agents.l3reference.firewall_l3_agent_v2:L3WithFWaaS
|
fwaas_v2 = neutron_fwaas.services.firewall.service_drivers.agents.l3reference.firewall_l3_agent_v2:L3WithFWaaS
|
||||||
neutron_fwaas.services.firewall.drivers.linux =
|
neutron.agent.l3.firewall_drivers =
|
||||||
conntrack = neutron_fwaas.services.firewall.drivers.linux.legacy_conntrack:ConntrackLegacy
|
conntrack = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.legacy_conntrack:ConntrackLegacy
|
||||||
netlink_conntrack = neutron_fwaas.services.firewall.drivers.linux.netlink_conntrack:ConntrackNetlink
|
netlink_conntrack = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.netlink_conntrack:ConntrackNetlink
|
||||||
|
|
||||||
[extract_messages]
|
[extract_messages]
|
||||||
keywords = _ gettext ngettext l_ lazy_gettext
|
keywords = _ gettext ngettext l_ lazy_gettext
|
||||||
|
Loading…
Reference in New Issue
Block a user