Fix functional/tempest v2 failures

gate_hook: Fix INSTALL_MYSQL_ONLY != True case

(cherry picked from commit 2a4cffb77a)

Add a variant of gate hook script

I plan to use this for gate-neutron-fwaas-{fwaas-version}-dsvm-tempest
to populate NETWORK_API_EXTENSIONS.

(cherry picked from commit 8af9d55670)

Closes-bug: 1661420
Closes-bug: 1661419

Add Tempest API tests for FWaaS v2.
Partially-Implements: blueprint fwaas-api-2.0

(cherry picked from commit 7880f27d15)

Fix tempest gate issue on FirewallNotFound exception

In case of failed tests the following error appears in
logs/screen-q-svc.txt.gz

  File "/opt/stack/new/neutron-fwaas/neutron_fwaas/db/firewall/v2/firewall_db_v2.py", line 805, in delete_firewall_group
    raise fw_ext.FirewallNotFound(firewall_id=id)
AttributeError: 'module' object has no attribute 'FirewallNotFound'

This exception doesn't exists anymore.
It has been replaced by FirewallGroupNotFound exception.

Closes-Bug: #1649703
Closes-Bug: #1657299
(cherry picked from commit 8a86782c22)

Change-Id: I625146043c7589f0935fcc9a5043b36d5eb763d5
This commit is contained in:
YAMAMOTO Takashi 2016-09-23 13:34:43 +09:00 committed by Armando Migliaccio
parent 7345510f36
commit 1918b9731f
11 changed files with 611 additions and 2 deletions

View File

@ -758,7 +758,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
count = context.session.query(
FirewallGroup).filter_by(id=id).update(fwg)
if not count:
raise fw_ext.FirewallNotFound(firewall_id=id)
raise fw_ext.FirewallGroupNotFound(firewall_id=id)
return self.get_firewall_group(context, id)
def update_firewall_group_status(self, context, id, status, not_in=None):
@ -782,7 +782,7 @@ class Firewall_db_mixin_v2(fw_ext.Firewallv2PluginBase, base_db.CommonDbMixin):
count = context.session.query(
FirewallGroup).filter_by(id=id).delete()
if not count:
raise fw_ext.FirewallNotFound(firewall_id=id)
raise fw_ext.FirewallGroupNotFound(firewall_id=id)
def get_firewall_group(self, context, id, fields=None):
LOG.debug("get_firewall_group() called")

View File

@ -80,5 +80,7 @@ EOF
if [[ "$IS_GATE" != "True" ]]; then
if [[ "$INSTALL_MYSQL_ONLY" == "True" ]]; then
_install_databases nopg
else
_install_databases
fi
fi

View File

@ -0,0 +1,24 @@
#!/bin/bash
set -ex
FWAAS_VERSION=$1
GATE_DEST=$BASE/new
GATE_HOOKS=$GATE_DEST/neutron-fwaas/neutron_fwaas/tests/contrib/hooks
DEVSTACK_PATH=$GATE_DEST/devstack
LOCAL_CONF=$DEVSTACK_PATH/local.conf
# Inject config from hook into localrc
function load_rc_hook {
local hook="$1"
config=$(cat $GATE_HOOKS/$hook)
export DEVSTACK_LOCAL_CONFIG+="
# generated from hook '$hook'
${config}
"
}
load_rc_hook api_extensions-base
load_rc_hook api_extensions-${FWAAS_VERSION}
$BASE/new/devstack-gate/devstack-vm-gate.sh

View File

@ -0,0 +1 @@
NETWORK_API_EXTENSIONS=agent,binding,dhcp_agent_scheduler,external-net,ext-gw-mode,extra_dhcp_opts,quotas,router,security-group,subnet_allocation,network-ip-availability,auto-allocated-topology,timestamp_core,tag,service-type,rbac-policies,standard-attr-description,pagination,sorting,project-id

View File

@ -0,0 +1 @@
NETWORK_API_EXTENSIONS+=,fwaas,fwaasrouterinsertion

View File

@ -0,0 +1 @@
NETWORK_API_EXTENSIONS+=,fwaas,fwaasrouterinsertion

View File

@ -0,0 +1 @@
NETWORK_API_EXTENSIONS+=,fwaas_v2

View File

@ -0,0 +1,123 @@
# Copyright (c) 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.
from tempest.lib import exceptions as lib_exc
from tempest.lib.services.network import base
class FirewallGroupsClient(base.BaseNetworkClient):
def create_firewall_group(self, **kwargs):
uri = '/fwaas/firewall_groups'
post_data = {'firewall_group': kwargs}
return self.create_resource(uri, post_data)
def update_firewall_group(self, firewall_group_id, **kwargs):
uri = '/fwaas/firewall_groups/%s' % firewall_group_id
post_data = {'firewall_group': kwargs}
return self.update_resource(uri, post_data)
def show_firewall_group(self, firewall_group_id, **fields):
uri = '/fwaas/firewall_groups/%s' % firewall_group_id
return self.show_resource(uri, **fields)
def delete_firewall_group(self, firewall_group_id):
uri = '/fwaas/firewall_groups/%s' % firewall_group_id
return self.delete_resource(uri)
def list_firewall_groups(self, **filters):
uri = '/fwaas/firewall_groups'
return self.list_resources(uri, **filters)
def is_resource_deleted(self, id):
try:
self.show_firewall_group(id)
except lib_exc.NotFound:
return True
return False
@property
def resource_type(self):
"""Returns the primary type of resource this client works with."""
return 'firewall_group'
class FirewallRulesClient(base.BaseNetworkClient):
def create_firewall_rule(self, **kwargs):
uri = '/fwaas/firewall_rules'
post_data = {'firewall_rule': kwargs}
return self.create_resource(uri, post_data)
def update_firewall_rule(self, firewall_rule_id, **kwargs):
uri = '/fwaas/firewall_rules/%s' % firewall_rule_id
post_data = {'firewall_rule': kwargs}
return self.update_resource(uri, post_data)
def show_firewall_rule(self, firewall_rule_id, **fields):
uri = '/fwaas/firewall_rules/%s' % firewall_rule_id
return self.show_resource(uri, **fields)
def delete_firewall_rule(self, firewall_rule_id):
uri = '/fwaas/firewall_rules/%s' % firewall_rule_id
return self.delete_resource(uri)
def list_firewall_rules(self, **filters):
uri = '/fwaas/firewall_rules'
return self.list_resources(uri, **filters)
class FirewallPoliciesClient(base.BaseNetworkClient):
def create_firewall_policy(self, **kwargs):
uri = '/fwaas/firewall_policies'
post_data = {'firewall_policy': kwargs}
return self.create_resource(uri, post_data)
def update_firewall_policy(self, firewall_policy_id, **kwargs):
uri = '/fwaas/firewall_policies/%s' % firewall_policy_id
post_data = {'firewall_policy': kwargs}
return self.update_resource(uri, post_data)
def show_firewall_policy(self, firewall_policy_id, **fields):
uri = '/fwaas/firewall_policies/%s' % firewall_policy_id
return self.show_resource(uri, **fields)
def delete_firewall_policy(self, firewall_policy_id):
uri = '/fwaas/firewall_policies/%s' % firewall_policy_id
return self.delete_resource(uri)
def list_firewall_policies(self, **filters):
uri = '/fwaas/firewall_policies'
return self.list_resources(uri, **filters)
def insert_firewall_rule_in_policy(self, firewall_policy_id,
firewall_rule_id, insert_after='',
insert_before=''):
uri = '/fwaas/firewall_policies/%s/insert_rule' % firewall_policy_id
data = {
'firewall_rule_id': firewall_rule_id,
'insert_after': insert_after,
'insert_before': insert_before,
}
return self.update_resource(uri, data)
def remove_firewall_rule_from_policy(self, firewall_policy_id,
firewall_rule_id):
uri = '/fwaas/firewall_policies/%s/remove_rule' % firewall_policy_id
data = {
'firewall_rule_id': firewall_rule_id,
}
return self.update_resource(uri, data)

View File

@ -0,0 +1,310 @@
# Copyright 2016
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import netaddr
import six
from tempest import config
from tempest import exceptions
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest import test
from neutron_fwaas.tests.tempest_plugin.tests.api import v2_base
CONF = config.CONF
class FWaaSv2ExtensionTestJSON(v2_base.BaseFWaaSTest):
"""
Tests the following operations in the Neutron API using the REST client for
Neutron:
List firewall rules
Create firewall rule
Update firewall rule
Delete firewall rule
Show firewall rule
List firewall policies
Create firewall policy
Update firewall policy
Insert firewall rule to policy
Remove firewall rule from policy
Insert firewall rule after/before rule in policy
Update firewall policy audited attribute
Delete firewall policy
Show firewall policy
List firewall group
Create firewall group
Update firewall group
Delete firewall group
Show firewall group
"""
@classmethod
def resource_setup(cls):
super(FWaaSv2ExtensionTestJSON, cls).resource_setup()
if not test.is_extension_enabled('fwaas_v2', 'network'):
msg = "FWaaS v2 Extension not enabled."
raise cls.skipException(msg)
def setUp(self):
super(FWaaSv2ExtensionTestJSON, self).setUp()
self.fw_rule_1 = self.create_firewall_rule(action="allow",
protocol="tcp")
self.fw_rule_2 = self.create_firewall_rule(action="deny",
protocol="udp")
self.fw_policy_1 = self.create_firewall_policy(
firewall_rules=[self.fw_rule_1['id']])
self.fw_policy_2 = self.create_firewall_policy(
firewall_rules=[self.fw_rule_2['id']])
def _create_router_interfaces(self):
network_1 = self.create_network()
network_2 = self.create_network()
cidr = netaddr.IPNetwork(CONF.network.project_network_cidr)
mask_bits = CONF.network.project_network_mask_bits
subnet_cidr_1 = list(cidr.subnet(mask_bits))[-1]
subnet_cidr_2 = list(cidr.subnet(mask_bits))[-2]
subnet_1 = self.create_subnet(network_1, cidr=subnet_cidr_1,
mask_bits=mask_bits)
subnet_2 = self.create_subnet(network_2, cidr=subnet_cidr_2,
mask_bits=mask_bits)
router = self.create_router(
data_utils.rand_name('router-'),
admin_state_up=True)
self.addCleanup(self._try_delete_router, router)
intf_1 = self.routers_client.add_router_interface(router['id'],
subnet_id=subnet_1['id'])
intf_2 = self.routers_client.add_router_interface(router['id'],
subnet_id=subnet_2['id'])
return intf_1, intf_2
def _try_delete_router(self, router):
# delete router, if it exists
try:
self.delete_router(router)
# if policy is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
def _try_delete_policy(self, policy_id):
# delete policy, if it exists
try:
self.firewall_policies_client.delete_firewall_policy(policy_id)
# if policy is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
def _try_delete_rule(self, rule_id):
# delete rule, if it exists
try:
self.firewall_rules_client.delete_firewall_rule(rule_id)
# if rule is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
def _try_delete_firewall_group(self, fwg_id):
# delete firewall group, if it exists
try:
self.firewall_groups_client.delete_firewall_group(fwg_id)
# if firewall is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
self.firewall_groups_client.wait_for_resource_deletion(fwg_id)
def _wait_until_ready(self, fwg_id):
target_states = ('ACTIVE', 'CREATED')
def _wait():
firewall_group = self.firewall_groups_client.show_firewall_group(
fwg_id)
firewall_group = firewall_group['firewall_group']
return firewall_group['status'] in target_states
if not test.call_until_true(_wait, CONF.network.build_timeout,
CONF.network.build_interval):
m = ("Timed out waiting for firewall_group %s to reach %s "
"state(s)" %
(fwg_id, target_states))
raise exceptions.TimeoutException(m)
@test.idempotent_id('ddccfa87-4af7-48a6-9e50-0bd0ad1348cb')
def test_list_firewall_rules(self):
# List firewall rules
fw_rules = self.firewall_rules_client.list_firewall_rules()
fw_rules = fw_rules['firewall_rules']
self.assertIn((self.fw_rule_1['id'],
self.fw_rule_1['name'],
self.fw_rule_1['action'],
self.fw_rule_1['protocol'],
self.fw_rule_1['ip_version'],
self.fw_rule_1['enabled']),
[(m['id'],
m['name'],
m['action'],
m['protocol'],
m['ip_version'],
m['enabled']) for m in fw_rules])
@test.idempotent_id('ffc009fa-cd17-4029-8025-c4b81a7dd923')
def test_create_update_delete_firewall_rule(self):
# Create firewall rule
body = self.firewall_rules_client.create_firewall_rule(
name=data_utils.rand_name("fw-rule"),
action="allow",
protocol="tcp")
fw_rule_id = body['firewall_rule']['id']
# Update firewall rule
body = self.firewall_rules_client.update_firewall_rule(fw_rule_id,
public=True)
self.assertTrue(body["firewall_rule"]['public'])
# Delete firewall rule
self.firewall_rules_client.delete_firewall_rule(fw_rule_id)
# Confirm deletion
fw_rules = self.firewall_rules_client.list_firewall_rules()
self.assertNotIn(fw_rule_id,
[m['id'] for m in fw_rules['firewall_rules']])
@test.idempotent_id('76b07afc-444e-4bb9-abec-9b8c5f994dcd')
def test_show_firewall_rule(self):
# show a created firewall rule
fw_rule = self.firewall_rules_client.show_firewall_rule(
self.fw_rule_1['id'])
for key, value in six.iteritems(fw_rule['firewall_rule']):
self.assertEqual(self.fw_rule_1[key], value)
@test.idempotent_id('f6b83902-746f-4e74-9403-2ec9899583a3')
def test_list_firewall_policies(self):
fw_policies = self.firewall_policies_client.list_firewall_policies()
fw_policies = fw_policies['firewall_policies']
self.assertIn((self.fw_policy_1['id'],
self.fw_policy_1['name'],
self.fw_policy_1['firewall_rules']),
[(m['id'],
m['name'],
m['firewall_rules']) for m in fw_policies])
@test.idempotent_id('6ef9bd02-7349-4d61-8d1f-80479f64d904')
def test_create_update_delete_firewall_policy(self):
# Create firewall policy
body = self.firewall_policies_client.create_firewall_policy(
name=data_utils.rand_name("fw-policy"))
fw_policy_id = body['firewall_policy']['id']
self.addCleanup(self._try_delete_policy, fw_policy_id)
# Update firewall policy
body = self.firewall_policies_client.update_firewall_policy(
fw_policy_id,
public=True,
name="updated_policy")
updated_fw_policy = body["firewall_policy"]
self.assertTrue(updated_fw_policy['public'])
self.assertEqual("updated_policy", updated_fw_policy['name'])
# Delete firewall policy
self.firewall_policies_client.delete_firewall_policy(fw_policy_id)
# Confirm deletion
fw_policies = self.firewall_policies_client.list_firewall_policies()
fw_policies = fw_policies['firewall_policies']
self.assertNotIn(fw_policy_id, [m['id'] for m in fw_policies])
@test.idempotent_id('164381de-61f4-483f-9a5a-48105b8e70e2')
def test_show_firewall_policy(self):
# show a created firewall policy
fw_policy = self.firewall_policies_client.show_firewall_policy(
self.fw_policy_1['id'])
fw_policy = fw_policy['firewall_policy']
for key, value in six.iteritems(fw_policy):
self.assertEqual(self.fw_policy_1[key], value)
@test.idempotent_id('48dfcd75-3924-479d-bb65-b3ed33397663')
def test_create_show_delete_firewall_group(self):
# create router and add interfaces
intf_1, intf_2 = self._create_router_interfaces()
# Create firewall_group
body = self.firewall_groups_client.create_firewall_group(
name=data_utils.rand_name("firewall_group"),
ingress_firewall_policy_id=self.fw_policy_1['id'],
egress_firewall_policy_id=self.fw_policy_2['id'],
ports=[intf_1['port_id'], intf_2['port_id']])
created_firewall_group = body['firewall_group']
fwg_id = created_firewall_group['id']
self.addCleanup(self._try_delete_firewall_group, fwg_id)
# Wait for the firewall resource to become ready
self._wait_until_ready(fwg_id)
# show created firewall_group
firewall_group = self.firewall_groups_client.show_firewall_group(
fwg_id)
fwg = firewall_group['firewall_group']
for key, value in six.iteritems(fwg):
if key == 'status':
continue
self.assertEqual(created_firewall_group[key], value)
# list firewall_groups
firewall_groups = self.firewall_groups_client.list_firewall_groups()
fwgs = firewall_groups['firewall_groups']
self.assertIn((created_firewall_group['id'],
created_firewall_group['name'],
created_firewall_group['ingress_firewall_policy_id'],
created_firewall_group['egress_firewall_policy_id']),
[(m['id'],
m['name'],
m['ingress_firewall_policy_id'],
m['egress_firewall_policy_id']) for m in fwgs])
# Delete firewall_group
self.firewall_groups_client.delete_firewall_group(fwg_id)
@test.idempotent_id('e021baab-d4f7-4bad-b382-bde4946e0e0b')
def test_update_firewall_group(self):
# create router and add interfaces
intf_1, intf_2 = self._create_router_interfaces()
# Create firewall_group
body = self.firewall_groups_client.create_firewall_group(
name=data_utils.rand_name("firewall_group"),
ingress_firewall_policy_id=self.fw_policy_1['id'],
egress_firewall_policy_id=self.fw_policy_2['id'],
ports=[intf_1['port_id']])
created_firewall_group = body['firewall_group']
fwg_id = created_firewall_group['id']
self.addCleanup(self._try_delete_firewall_group, fwg_id)
# Wait for the firewall resource to become ready
self._wait_until_ready(fwg_id)
# Update firewall group
body = self.firewall_groups_client.update_firewall_group(
fwg_id,
ports=[intf_2['port_id']])
updated_fwg = body["firewall_group"]
self.assertEqual([intf_2['port_id']], updated_fwg['ports'])
# Delete firewall_group
self.firewall_groups_client.delete_firewall_group(fwg_id)

View File

@ -0,0 +1,21 @@
# 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 tempest.api.network import base
from neutron_fwaas.tests.tempest_plugin.tests import fwaas_v2_client
class BaseFWaaSTest(fwaas_v2_client.FWaaSClientMixin, base.BaseNetworkTest):
pass

View File

@ -0,0 +1,125 @@
# Copyright (c) 2015 Midokura SARL
# 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 time
from tempest import config
from tempest import exceptions
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions as lib_exc
from neutron_fwaas.tests.tempest_plugin.services import v2_client
from neutron_lib import constants as nl_constants
CONF = config.CONF
class FWaaSClientMixin(object):
@classmethod
def resource_setup(cls):
super(FWaaSClientMixin, cls).resource_setup()
manager = cls.manager
cls.firewall_groups_client = v2_client.FirewallGroupsClient(
manager.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**manager.default_params)
cls.firewall_policies_client = v2_client.FirewallPoliciesClient(
manager.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**manager.default_params)
cls.firewall_rules_client = v2_client.FirewallRulesClient(
manager.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**manager.default_params)
def create_firewall_rule(self, **kwargs):
body = self.firewall_rules_client.create_firewall_rule(
name=data_utils.rand_name("fw-rule"),
**kwargs)
fw_rule = body['firewall_rule']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.firewall_rules_client.delete_firewall_rule,
fw_rule['id'])
return fw_rule
def create_firewall_policy(self, **kwargs):
body = self.firewall_policies_client.create_firewall_policy(
name=data_utils.rand_name("fw-policy"),
**kwargs)
fw_policy = body['firewall_policy']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.firewall_policies_client.delete_firewall_policy,
fw_policy['id'])
return fw_policy
def create_firewall_group(self, **kwargs):
body = self.firewall_groups_client.create_firewall_group(
name=data_utils.rand_name("fwg"),
**kwargs)
fwg = body['firewall_group']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.delete_firewall_and_wait,
fwg['id'])
return fwg
def delete_firewall_group_and_wait(self, firewall_group_id):
self.firewall_groups_client.delete_firewall_group(firewall_group_id)
self._wait_firewall_group_while(firewall_group_id,
[nl_constants.PENDING_DELETE],
not_found_ok=True)
def _wait_firewall_group_ready(self, firewall_group_id):
self._wait_firewall_group_while(firewall_group_id,
[nl_constants.PENDING_CREATE,
nl_constants.PENDING_UPDATE])
def _wait_firewall_group_while(self, firewall_group_id, statuses,
not_found_ok=False):
start = int(time.time())
if not_found_ok:
expected_exceptions = (lib_exc.NotFound)
else:
expected_exceptions = ()
while True:
try:
fwg = self.firewall_groups_client.show_firewall_group(
firewall_group_id)
except expected_exceptions:
break
status = fwg['firewall_group']['status']
if status not in statuses:
break
if int(time.time()) - start >= self.firewalls_client.build_timeout:
msg = ("Firewall Group %(firewall_group)s failed to reach "
"non PENDING status (current %(status)s)") % {
"firewall_group": firewall_group_id,
"status": status,
}
raise exceptions.TimeoutException(msg)
time.sleep(1)