diff --git a/vmware_nsx_tempest/doc/README-AdminPolicy.rst b/vmware_nsx_tempest/doc/README-AdminPolicy.rst
new file mode 100644
index 0000000000..29f9387409
--- /dev/null
+++ b/vmware_nsx_tempest/doc/README-AdminPolicy.rst
@@ -0,0 +1,90 @@
+Admin Policy
+============
+
+Admin policy, neutron extension secuirty-group-policy provides organization
+to enforce traffic forwarding utilizing NSX security policy.
+
+The "Admin Policy" feature is admin priviledge, normal project/tenant is not
+able to create security-group-policy.
+
+This feature can be enabled from devstack or manually.
+
+Enable security-group-policy extention at bring up devstack
+===========================================================
+
+You can enable security-group-policy when starting up devstack.
+However, if the policy-id does not exist, starting will fail.
+
+To enable it, add the following tokens to local.conf:
+
+ NSXV_USE_NSX_POLICIES=True
+ NSXV_DEFAULT_POLICY_ID=policy-11
+ NSXV_ALLOW_TENANT_RULES_WITH_POLICY=True
+
+Change values according to your needs though.
+
+Enable security-group-policy extention manually
+===============================================
+
+Instruction is from the view of devstack
+
+#. Add following items to /etc/neutron/policy.json::
+
+ "create_security_group:logging": "rule:admin_only",
+ "update_security_group:logging": "rule:admin_only",
+ "get_security_group:logging": "rule:admin_only",
+ "create_security_group:provider": "rule:admin_only",
+ "create_port:provider_security_groups": "rule:admin_only",
+ "create_security_group:policy": "rule:admin_only",
+ "update_security_group:policy": "rule:admin_only",
+
+#. Add following key=value pair to session [nsxv] of /etc/neutron/plugin/vmware/nsx.ini::
+
+ use_nsx_policies = True
+ default_policy_id = policy-11
+ allow_tenant_rules_with_policy = False
+
+ # NOTE: For automation, set allow_tenant_rules_with_policy to True
+
+tempest.conf
+============
+
+At session [nsxv] add the following 3 key=value pair:
+
+ default_policy_id = policy-11
+ alt_policy_id = policy-22
+ allow_tenant_rules_with_policy = False
+
+ # NOTE: default_policy_id and allow_tenant_rules_with_policy need to match nsx.ini
+
+default_policy_id and alt_policy_id:
+
+ For API tests, both must exist at NSX.
+
+ For scenario tests, please refer to nsxv/scenario/test_admin_policy_basic_ops.py
+
+ In short::
+
+ policy-11 (policy-AA at script & test-plan) firewall rules::
+ action-1: dhcp-in/any/policy-security-groups/dhcp/Allow
+ action-2: dhcp-out/policy-security-groups/dhcp/Allow
+ action-3: ping-in/any/policy-security-groups/ICMP/Allow
+ action-4: ping-out/policy-security-groups/any/ICMP/Allow/
+ action-5: ssh-in/any/policy-security-groups/SSH/Allow/
+ action-6: ssh-in/any/policy-security-groups/SSH/Allow/
+ action-7: http-ok/any/policy-security-groups/HTTP,HTTPS/Allow/
+ action-8: sorry-nothing-allowed/any/policy-security-groups/Any/Reject
+
+ You can import policy-AA to NSX using the admin-policy-AA.blueprint
+
+ policy-22 (policy-BB at script & test-plan) firewall rules::
+ action-1: dhcp-in/any/policy-security-groups/dhcp/Allow
+ action-2: dhcp-out/policy-security-groups/dhcp/Allow
+ action-3: group-ping/policy-security-groups/policy-security-groups/ICMP/Allow/
+ action-4: ssh-in/any/policy-security-groups/SSH/Allow/
+ action-5: ssh-in/any/policy-security-groups/SSH/Allow/
+ action-6: http-ok/any/policy-security-groups/HTTP,HTTPS/Allow/
+ pction-7: sorry-nothing-allowed/any/policy-security-groups/Any/Reject
+
+ NOTE on ping: same as policy-11 but only allowed from policy-security-groups
+ You can import policy-BB to NSX using the admin-policy-BB.blueprint
diff --git a/vmware_nsx_tempest/doc/admin-policy-AA.blueprint b/vmware_nsx_tempest/doc/admin-policy-AA.blueprint
new file mode 100644
index 0000000000..2f928fe6d6
--- /dev/null
+++ b/vmware_nsx_tempest/doc/admin-policy-AA.blueprint
@@ -0,0 +1,341 @@
+
+ admin-policy-AA
+ 8 firewall rules - ping, ssh from anywhere are OK
+
+ 0
+ security-policy-AA
+ Security Policy AA
+
+ false
+ 0
+ false
+ 5500
+
+ firewall
+
+ 0
+ dhcp-in
+
+ false
+ 0
+ firewall
+ 1
+ true
+ false
+ false
+
+
+ 0
+ DHCP-Client
+
+ false
+ 0
+ true
+
+ UDP
+ 68
+
+
+
+ 0
+ DHCP-Server
+
+ false
+ 0
+ true
+
+ UDP
+ 67
+
+
+
+ false
+ false
+ allow
+ inbound
+ false
+
+
+ 0
+ dhcp-out
+
+ false
+ 0
+ firewall
+ 2
+ true
+ false
+ false
+
+
+ 0
+ DHCP-Client
+
+ false
+ 0
+ true
+
+ UDP
+ 68
+
+
+
+ 0
+ DHCP-Server
+
+ false
+ 0
+ true
+
+ UDP
+ 67
+
+
+
+ false
+ false
+ allow
+ outbound
+ false
+
+
+ 0
+ ping-in
+ Everyone can ping me
+
+ false
+ 0
+ firewall
+ 3
+ true
+ false
+ false
+
+
+ 0
+ ICMP Echo
+
+ false
+ 0
+ true
+
+ ICMP
+ echo-request
+
+
+
+ 0
+ ICMP Redirect
+
+ false
+ 0
+ true
+
+ ICMP
+ redirect
+
+
+
+ 0
+ ICMP Echo Reply
+
+ false
+ 0
+ true
+
+ ICMP
+ echo-reply
+
+
+
+ false
+ false
+ allow
+ inbound
+ false
+
+
+ 0
+ ping-out
+
+ false
+ 0
+ firewall
+ 4
+ true
+ false
+ false
+
+
+ 0
+ ICMP Echo
+
+ false
+ 0
+ true
+
+ ICMP
+ echo-request
+
+
+
+ 0
+ ICMP Redirect
+
+ false
+ 0
+ true
+
+ ICMP
+ redirect
+
+
+
+ 0
+ ICMP Echo Reply
+
+ false
+ 0
+ true
+
+ ICMP
+ echo-reply
+
+
+
+ false
+ false
+ allow
+ outbound
+ false
+
+
+ 0
+ ssh-in-ok
+
+ false
+ 0
+ firewall
+ 5
+ true
+ false
+ false
+
+
+ 0
+ SSH
+
+ false
+ 0
+ true
+
+ TCP
+ 22
+
+
+
+ false
+ false
+ allow
+ inbound
+ false
+
+
+ 0
+ ssh-out-ok
+
+ false
+ 0
+ firewall
+ 6
+ true
+ false
+ false
+
+
+ 0
+ SSH
+
+ false
+ 0
+ true
+
+ TCP
+ 22
+
+
+
+ false
+ false
+ allow
+ outbound
+ false
+
+
+ 0
+ HTTP-ok
+ All can http(s) me
+
+ false
+ 0
+ firewall
+ 7
+ true
+ false
+ false
+
+
+ 0
+ HTTP
+
+ false
+ 0
+ true
+
+ TCP
+ 80
+
+
+
+ 0
+ HTTPS
+
+ false
+ 0
+ true
+
+ TCP
+ 443
+
+
+
+ false
+ false
+ allow
+ inbound
+ false
+
+
+ 0
+ sorry-nothing-allowed
+
+ false
+ 0
+ firewall
+ 8
+ true
+ false
+ false
+ false
+ false
+ reject
+ inbound
+ false
+
+
+
+ firewall
+ in_sync
+
+
+
diff --git a/vmware_nsx_tempest/doc/admin-policy-BB.blueprint b/vmware_nsx_tempest/doc/admin-policy-BB.blueprint
new file mode 100644
index 0000000000..f8a512adb1
--- /dev/null
+++ b/vmware_nsx_tempest/doc/admin-policy-BB.blueprint
@@ -0,0 +1,285 @@
+
+ admin-policy-BB
+ policy-BB, ssh from anywhere are OK, but ping limited to same security-group
+
+ 0
+ security-policy-BB
+ Security Policy BB
+
+ false
+ 0
+ false
+ 5600
+
+ firewall
+
+ 0
+ dhcp-in
+
+ false
+ 0
+ firewall
+ 1
+ true
+ false
+ false
+
+
+ 0
+ DHCP-Client
+
+ false
+ 0
+ true
+
+ UDP
+ 68
+
+
+
+ 0
+ DHCP-Server
+
+ false
+ 0
+ true
+
+ UDP
+ 67
+
+
+
+ false
+ false
+ allow
+ inbound
+ false
+
+
+ 0
+ dhcp-out
+
+ false
+ 0
+ firewall
+ 2
+ true
+ false
+ false
+
+
+ 0
+ DHCP-Client
+
+ false
+ 0
+ true
+
+ UDP
+ 68
+
+
+
+ 0
+ DHCP-Server
+
+ false
+ 0
+ true
+
+ UDP
+ 67
+
+
+
+ false
+ false
+ allow
+ outbound
+ false
+
+
+ 0
+ group-ping-ok
+ icmp only allowed from VM with same security-policy
+
+ false
+ 0
+ firewall
+ 3
+ true
+ false
+ false
+
+
+ 0
+ ICMP Echo
+
+ false
+ 0
+ true
+
+ ICMP
+ echo-request
+
+
+
+ 0
+ ICMP Redirect
+
+ false
+ 0
+ true
+
+ ICMP
+ redirect
+
+
+
+ 0
+ ICMP Echo Reply
+
+ false
+ 0
+ true
+
+ ICMP
+ echo-reply
+
+
+
+ false
+ false
+ allow
+ intra
+ false
+
+
+ 0
+ ssh-in-ok
+
+ false
+ 0
+ firewall
+ 4
+ true
+ false
+ false
+
+
+ 0
+ SSH
+
+ false
+ 0
+ true
+
+ TCP
+ 22
+
+
+
+ false
+ false
+ allow
+ inbound
+ false
+
+
+ 0
+ ssh-out-ok
+
+ false
+ 0
+ firewall
+ 5
+ true
+ false
+ false
+
+
+ 0
+ SSH
+
+ false
+ 0
+ true
+
+ TCP
+ 22
+
+
+
+ false
+ false
+ allow
+ outbound
+ false
+
+
+ 0
+ group-HTTP
+
+ false
+ 0
+ firewall
+ 6
+ true
+ false
+ false
+
+
+ 0
+ HTTP
+
+ false
+ 0
+ true
+
+ TCP
+ 80
+
+
+
+ 0
+ HTTPS
+
+ false
+ 0
+ true
+
+ TCP
+ 443
+
+
+
+ false
+ false
+ allow
+ intra
+ false
+
+
+ 0
+ sorry-nothing-allowed
+
+ false
+ 0
+ firewall
+ 7
+ true
+ false
+ false
+ false
+ false
+ reject
+ inbound
+ false
+
+
+
+ firewall
+ in_sync
+
+
+
diff --git a/vmware_nsx_tempest/tests/nsxv/scenario/manager_topo_deployment.py b/vmware_nsx_tempest/tests/nsxv/scenario/manager_topo_deployment.py
index 5bf1385ddb..eb801d8b8b 100644
--- a/vmware_nsx_tempest/tests/nsxv/scenario/manager_topo_deployment.py
+++ b/vmware_nsx_tempest/tests/nsxv/scenario/manager_topo_deployment.py
@@ -399,15 +399,21 @@ class TopoDeployScenarioManager(manager.NetworkScenarioTest):
if port_id:
# attached to port, will not check ip assignement & reachability
return net_floatingip
+ serv_fip = net_floatingip['floating_ip_address']
+ # in some condiction, remove the serv_fip from your local known_hosts
+ # can solve the ssh "Connection refused" problem.
+ rm_sshkey(serv_fip)
if not and_check_assigned:
# caller will do the floatingip assigned to server and ping tests
return net_floatingip
self._waitfor_floatingip_assigned_to_server(client_mgr.servers_client,
server.get('id'))
server_pingable = self._waitfor_associated_floatingip(net_floatingip)
+ STEPINTO_DEBUG_IF_TRUE(not server_pingable)
self.assertTrue(
server_pingable,
- msg="Expect server to be reachable after floatingip assigned.")
+ msg=("Expect server to be reachable after"
+ " floating-ip[%s] assigned." % serv_fip))
return net_floatingip
def _waitfor_floatingip_assigned_to_server(self, server_client, server_id,
@@ -526,7 +532,8 @@ class TopoDeployScenarioManager(manager.NetworkScenarioTest):
def _check_floatingip_connectivity(self, floating_ip, server,
should_connect=True,
- msg=None, ping_timeout=30):
+ msg=None, ping_timeout=30,
+ floating_ips_client=None):
ip_address = floating_ip['floating_ip_address']
floatingip_status = 'ACTIVE' if should_connect else 'DOWN'
is_pingable = self.ping_ip_address(ip_address,
@@ -537,7 +544,37 @@ class TopoDeployScenarioManager(manager.NetworkScenarioTest):
self.assertTrue(is_pingable, msg=msg)
else:
self.assertFalse(is_pingable, msg=msg)
- self.check_floating_ip_status(floating_ip, floatingip_status)
+ self.check_floating_ip_status(floating_ip, floatingip_status,
+ floating_ips_client)
+
+ def check_floating_ip_status(self, floating_ip, status,
+ floating_ips_client=None):
+ """Verifies floatingip reaches the given status
+
+ :param dict floating_ip: floating IP dict to check status
+ :param status: target status
+ :raises: AssertionError if status doesn't match
+ """
+ floating_ips_client = floating_ips_client or self.floating_ips_client
+ floatingip_id = floating_ip['id']
+
+ def refresh():
+ result = (floating_ips_client.
+ show_floatingip(floatingip_id)['floatingip'])
+ return status == result['status']
+
+ test_utils.call_until_true(refresh,
+ CONF.network.build_timeout,
+ CONF.network.build_interval)
+ floating_ip = floating_ips_client.show_floatingip(
+ floatingip_id)['floatingip']
+ self.assertEqual(status, floating_ip['status'],
+ message="FloatingIP: {fp} is at status: {cst}. "
+ "failed to reach status: {st}"
+ .format(fp=floating_ip, cst=floating_ip['status'],
+ st=status))
+ LOG.info("FloatingIP: {fp} is at status: {st}"
+ .format(fp=floating_ip, st=status))
def get_image_userpass(self):
return (CONF.validation.image_ssh_user,
@@ -769,3 +806,13 @@ def copy_file_to_host(file_from, dest, host, username, pkey):
stdout,
stderr)
return stdout
+
+
+def STEPINTO_DEBUG_IF_TRUE(want2debug=False):
+ """Betting you are not set OS_TEST_TIMEOUT=24-hours running tempest"""
+ t_timeout = int(os.environ.get('OS_TEST_TIMEOUT', 0))
+ if want2debug and t_timeout > 86400:
+ # uncomment following statements to turn on debuggging
+ # import pdb
+ # pdb.set_trace()
+ pass
diff --git a/vmware_nsx_tempest/tests/nsxv/scenario/test_admin_policy_basic_ops.py b/vmware_nsx_tempest/tests/nsxv/scenario/test_admin_policy_basic_ops.py
new file mode 100644
index 0000000000..ba389ae62e
--- /dev/null
+++ b/vmware_nsx_tempest/tests/nsxv/scenario/test_admin_policy_basic_ops.py
@@ -0,0 +1,593 @@
+# Copyright 2016 VMware Inc
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import six
+import time
+
+from tempest.common import waiters
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest import test
+
+from vmware_nsx_tempest.tests.nsxv.scenario import (
+ manager_topo_deployment as dmgr)
+from vmware_nsx_tempest.tests.nsxv.scenario import (
+ network_addon_methods as HELO)
+
+CONF = config.CONF
+LOG = dmgr.manager.log.getLogger(__name__)
+
+
+class TestAdminPolicyBasicOps(dmgr.TopoDeployScenarioManager):
+ """Test VMs with security-group-policy traffic is managed by NSX
+
+ Test topology:
+ TOPO:
+
+ logical-router nasa-router] -- [ public GW]
+ |
+ +--- [Tenant jpl interface/subnet x.y.34.0/24]
+ | | |
+ | + [vm-nasa-jpl-3] + [vm-nasa-jpl-4]
+ |
+ +--- [Tenant ames interface/subnet x.y.12.0/24]
+ | | |
+ | + [vm-nasa-ames-1] + [vm-nasa-ames-2]
+
+ Test topology setup and traffic forwarding validation:
+
+ 1. 2 tenants (ames, jpl) each tenant has 2 VMs, and boot with
+ security-group with policy==policy_AA which must allow
+ ping and ssh services as automation relys on this to make
+ sure test environment network connectivity is an OK.
+ NOTE:
+ primary user: ames -- NASA Ames Research Center
+ alt user: jpl -- NASA Jet Propulsion Laboratory
+ 2. Admin create router (nasa-router) with both tenants' network
+ so tenant:ames and tenant:jpl can talk to each other
+ according to policy_AA.
+ 3. under policy_AA, all servers can be ping and ssh from anywhere
+ 4. Admin change tenant:jpl's policy to policy_BB
+ 5. Tenant jpl's VMs are not pingable, ssh still OK
+ Tenant ames's MVs, both ping and ssh are OK
+ 6. Admin change tenant:ames's policy to policy_BB
+ VMs from ames and jpl are not pingalbe; ssh is OK
+
+ ATTENTION:
+ config nsxv.default_policy_id is policy_AA
+ config nsxv.alt_policy_is is policy_BB
+
+ The testbed needs to have policy_AA and policy_BB created
+ and matched with the default_policy_id & alt_plicy_id under
+ session nsxv of tempest.conf or devstack local.conf.
+
+ Test Configuration setup:
+ please refer to vmware_nsx_tempest/doc/README-AdminPolicy.rst
+ """
+
+ @classmethod
+ def skip_checks(cls):
+ super(TestAdminPolicyBasicOps, cls).skip_checks()
+ if not test.is_extension_enabled('security-group-policy', 'network'):
+ msg = "Extension security-group-policy is not enabled."
+ raise cls.skipException(msg)
+ if not (CONF.nsxv.alt_policy_id.startswith('policy-') and
+ CONF.nsxv.default_policy_id.startswith('policy-')):
+ msg = "default and alt policy ids not set correctly."
+ raise cls.skipException(msg)
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestAdminPolicyBasicOps, cls).setup_clients()
+ cls.cmgr_adm = cls.get_client_manager('admin')
+ cls.cmgr_ames = cls.get_client_manager('primary')
+ cls.cmgr_jpl = cls.get_client_manager('alt')
+
+ @classmethod
+ def resource_setup(cls):
+ super(TestAdminPolicyBasicOps, cls).resource_setup()
+ cls.policy_AA = CONF.nsxv.default_policy_id
+ cls.policy_BB = CONF.nsxv.alt_policy_id
+ cls.conn_timeout = CONF.scenario.waitfor_connectivity
+
+ @classmethod
+ def resource_cleanup(cls):
+ super(TestAdminPolicyBasicOps, cls).resource_cleanup()
+
+ def setUp(self):
+ super(TestAdminPolicyBasicOps, self).setUp()
+ self.server_id_list = []
+ self.exc_step = 0
+ self.exc_msg = ("Admin-Policy-Traffic-Forwarding"
+ " Validation Steps:\n")
+
+ def tearDown(self):
+ # delete all servers and make sure they are terminated
+ servers_client = self.cmgr_adm.servers_client
+ server_id_list = getattr(self, 'server_id_list', [])
+ for server_id in server_id_list:
+ servers_client.delete_server(server_id)
+ for server_id in server_id_list:
+ waiters.wait_for_server_termination(servers_client, server_id)
+ # delete all floating-ips
+ if hasattr(self, 'fip_nasa_ames_1'):
+ self.delete_floatingip(self.cmgr_ames, self.fip_nasa_ames_1)
+ if hasattr(self, 'fip_nasa_jpl_3'):
+ self.delete_floatingip(self.cmgr_jpl, self.fip_nasa_jpl_3)
+ super(TestAdminPolicyBasicOps, self).tearDown()
+
+ def log_exc_msg(self, msg):
+ self.exc_step += 1
+ self.exc_msg += ("#%02d %s %s\n" %
+ (self.exc_step, time.strftime("%H:%M:%S"), msg))
+
+ def delete_floatingip(self, cmgr, net_floatingip):
+ test_utils.call_and_ignore_notfound_exc(
+ cmgr.floating_ips_client.delete_floatingip,
+ net_floatingip.get('id'))
+
+ def delete_security_group(self, sg_client, sg_id):
+ sg_client.delete_security_group(sg_id)
+
+ def update_security_group_policy(self, sg_id, policy_id):
+ sg_client = self.cmgr_adm.security_groups_client
+ sg = sg_client.update_security_group(sg_id, policy=policy_id)
+ sg = sg.get('security_group', sg)
+ self.assertEqual(policy_id, sg.get('policy'))
+ return sg
+
+ def create_security_group_policy(self, policy_id, tenant_id,
+ name_prefix=None):
+ sg_name = data_utils.rand_name(name_prefix or 'admin-policy')
+ sg_client = self.cmgr_adm.security_groups_client
+ sg_dict = dict(name=sg_name, policy=policy_id)
+ if tenant_id:
+ sg_dict['tenant_id'] = tenant_id
+ sg = sg_client.create_security_group(**sg_dict)
+ sg = sg.get('security_group', sg)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.delete_security_group,
+ sg_client, sg.get('id'))
+ return sg
+
+ def create_networks(self, cmgr,
+ name_prefix=None, cidr_offset=0):
+ net_name = data_utils.rand_name(name_prefix or 'admin-policy')
+ network = self.create_network(client=cmgr.networks_client,
+ name=net_name)
+ network = network.get('network', network)
+ subnet_kwargs = dict(name=net_name, cidr_offset=cidr_offset)
+ subnet = self.create_subnet(network,
+ client=cmgr.subnets_client,
+ **subnet_kwargs)
+ subnet = subnet.get('subnet', subnet)
+ return (network, subnet)
+
+ def create_router_by_type(self, router_type, client=None, **kwargs):
+ routers_client = client or self.cmgr_adm.routers_client
+ create_kwargs = dict(namestart='nasa-router', external_gateway_info={
+ "network_id": CONF.network.public_network_id})
+ if router_type in ('shared', 'exclusive'):
+ create_kwargs['router_type'] = router_type
+ elif router_type in ('distributed'):
+ create_kwargs['distributed'] = True
+ create_kwargs.update(**kwargs)
+ router = HELO.router_create(self, client=routers_client,
+ **create_kwargs)
+ return router
+
+ def create_router_and_add_interfaces(self, router_type, subnet_list):
+ routers_client = self.cmgr_adm.routers_client
+ router = self.create_router_by_type(router_type)
+ for subnet in subnet_list:
+ HELO.router_interface_add(self, router['id'], subnet['id'],
+ client=routers_client)
+ # check interfaces/subnets are added to router
+ router_port_list = self.get_router_port_list(self.cmgr_adm,
+ router['id'])
+ for subnet in subnet_list:
+ added = self.rports_have_subnet_id(router_port_list, subnet['id'])
+ self.assertTrue(
+ added,
+ "subnet_id:%s is not added to router" % subnet['id'])
+ return router
+
+ def rports_have_subnet_id(self, router_port_list, subnet_id):
+ for rport in router_port_list:
+ for fips in rport.get('fixed_ips', []):
+ if subnet_id == fips['subnet_id']:
+ return True
+ return False
+
+ def get_router_port_list(self, cmgr, router_id):
+ device_owner = u'network:router_interface'
+ ports_client = cmgr.ports_client
+ port_list = ports_client.list_ports(device_id=router_id,
+ device_owner=device_owner)
+ port_list = port_list.get('ports', port_list)
+ return port_list
+
+ def create_servers_on_networks(self, cmgr, sv_name, networks_info):
+ network = networks_info.get('network')
+ security_group = networks_info.get('security_group')
+ security_groups = [{'name': security_group['id']}]
+ svr = self.create_server_on_network(
+ network, security_groups, name=sv_name,
+ wait_on_boot=False,
+ servers_client=cmgr.servers_client)
+ self.server_id_list.append(svr.get('id'))
+ return svr
+
+ def get_server_info(self, cmgr, server_id):
+ """Get server's ip addresses"""
+ svr = cmgr.servers_client.show_server(server_id)
+ svr = svr.get('server', svr)
+ sinfo = dict(id=svr['id'], name=svr['name'],
+ security_gropus=svr['security_groups'],
+ fixed_ip_address=None, floating_ip_address=None)
+ addresses = svr.get('addresses')
+ for n_addresses in six.itervalues(addresses):
+ for n_addr in n_addresses:
+ if n_addr['OS-EXT-IPS:type'] == 'fixed':
+ if not sinfo['fixed_ip_address']:
+ sinfo['fixed_ip_address'] = n_addr['addr']
+ elif n_addr['OS-EXT-IPS:type'] == 'floating':
+ if not sinfo['floating_ip_address']:
+ sinfo['floating_ip_address'] = n_addr['addr']
+ return sinfo
+
+ def create_floatingip_for_server(self, cmgr, server):
+ username, password = self.get_image_userpass()
+ try:
+ floatingip = super(
+ TestAdminPolicyBasicOps,
+ self).create_floatingip_for_server(
+ server, client_mgr=cmgr, and_check_assigned=True)
+ except Exception as ex:
+ floatingip = None
+ msg = (self.exc_msg +
+ ("\n**FAIL to associate floatingip to server[%s]\n%s"
+ % (server['name'], str(ex))))
+ self.assertTrue(floatingip, msg)
+ fix_ip = floatingip['fixed_ip_address']
+ float_ip = floatingip['floating_ip_address']
+ self.log_exc_msg((" floatingip[%s] created for server[%s,%s]"
+ " and is pingable." %
+ (float_ip, server.get('name'), fix_ip)))
+ return floatingip
+
+ def wait_for_servers_become_active(self):
+ servers_client = self.cmgr_adm.servers_client
+ for server_id in self.server_id_list:
+ waiters.wait_for_server_status(
+ servers_client, server_id, 'ACTIVE')
+
+ def find_servers_ips(self):
+ self.server_ips = {}
+ self.jpl_ips = {}
+ self.server_ips['1'] = self.get_server_info(
+ self.cmgr_ames, self.vm_nasa_ames_1['id'])
+ self.server_ips['2'] = self.get_server_info(
+ self.cmgr_ames, self.vm_nasa_ames_2['id'])
+ self.server_ips['3'] = self.get_server_info(
+ self.cmgr_jpl, self.vm_nasa_jpl_3['id'])
+ self.server_ips['4'] = self.get_server_info(
+ self.cmgr_jpl, self.vm_nasa_jpl_4['id'])
+
+ def create_nasa_ames_network_and_servers(self, security_group=None):
+ sg = security_group or self.sg_ames
+ net, subnet = self.create_networks(self.cmgr_ames, 'nasa-ames', 1)
+ self.netinfo_ames = dict(network=net, subnet=subnet,
+ security_group=sg)
+ self.vm_nasa_ames_1 = self.create_servers_on_networks(
+ self.cmgr_ames, 'vm-nasa-ames-1', self.netinfo_ames)
+ self.vm_nasa_ames_2 = self.create_servers_on_networks(
+ self.cmgr_ames, 'vm-nasa-ames-2', self.netinfo_ames)
+
+ def create_nasa_jpl_network_and_servers(self, security_group=None):
+ sg = security_group or self.sg_jpl
+ # jpl and ames attached to the same router, CIDR cannot overlap
+ net, subnet = self.create_networks(self.cmgr_jpl, 'nasa-jpl', 3)
+ self.netinfo_jpl = dict(network=net, subnet=subnet,
+ security_group=sg)
+ self.vm_nasa_jpl_3 = self.create_servers_on_networks(
+ self.cmgr_jpl, 'vm-nasa-jpl-3', self.netinfo_jpl)
+ self.vm_nasa_jpl_4 = self.create_servers_on_networks(
+ self.cmgr_jpl, 'vm-nasa-jpl-4', self.netinfo_jpl)
+
+ def create_nasa_topo(self, router_type=None):
+ router_type = router_type or 'shared'
+ self.sg_ames = self.create_security_group_policy(
+ self.policy_AA,
+ self.cmgr_ames.networks_client.tenant_id,
+ name_prefix='nasa-ames')
+ self.sg_jpl = self.create_security_group_policy(
+ self.policy_AA,
+ self.cmgr_jpl.networks_client.tenant_id,
+ name_prefix='nasa-jpl')
+ self.create_nasa_ames_network_and_servers(self.sg_ames)
+ self.create_nasa_jpl_network_and_servers(self.sg_jpl)
+ subnet_list = [self.netinfo_ames.get('subnet'),
+ self.netinfo_jpl.get('subnet')]
+ self.nasa_router = self.create_router_and_add_interfaces(
+ router_type, subnet_list)
+ self.wait_for_servers_become_active()
+ # associate floating-ip to servers and pingable
+ self.fip_nasa_ames_1 = self.create_floatingip_for_server(
+ self.cmgr_ames, self.vm_nasa_ames_1)
+ self.fip_nasa_jpl_3 = self.create_floatingip_for_server(
+ self.cmgr_jpl, self.vm_nasa_jpl_3)
+ self.find_servers_ips()
+
+ def host_ssh_reachable(self, host_id, host_ip):
+ username, password = self.get_image_userpass()
+ try:
+ ssh_client = dmgr.get_remote_client_by_password(
+ host_ip, username, password)
+ except Exception as ex:
+ ssh_client = None
+ msg = (self.exc_msg +
+ ("\n**FAIL to ssh to host[%s=%s]\n%s" %
+ (host_id, str(ex))))
+ self.assertTrue(ssh_client, msg)
+ self.log_exc_msg(
+ (" SSH host[%s] floatingip[%s] OK" % (host_id, host_ip)))
+ return ssh_client
+
+ def host_can_reach_ips(self, host_id, host_ssh, ip_type, ip_list):
+ for dest_ip in ip_list:
+ reachable = dmgr.is_reachable(host_ssh, dest_ip,
+ time_out=self.conn_timeout)
+ msg = (self.exc_msg +
+ ("\n *FAILURE* VM[%s] cannot PING %s[%s]" %
+ (host_id, ip_type, dest_ip)))
+ if not reachable:
+ reachable = dmgr.is_reachable(host_ssh, dest_ip,
+ time_out=self.conn_timeout)
+ dmgr.STEPINTO_DEBUG_IF_TRUE(not reachable)
+ self.assertTrue(reachable, msg)
+ self.log_exc_msg(
+ (" VM[%s] can PING %s[%s]" % (host_id, ip_type, dest_ip)))
+
+ def host_cannot_reach_ips(self, host_id, host_ssh, ip_type, ip_list):
+ for dest_ip in ip_list:
+ not_reachable = dmgr.isnot_reachable(host_ssh, dest_ip,
+ time_out=self.conn_timeout,
+ ping_timeout=5.0)
+ msg = (self.exc_msg +
+ ("\n *FAILURE* VM[%s] shouldn't able to PING %s[%s]" %
+ (host_id, ip_type, dest_ip)))
+ if not not_reachable:
+ not_reachable = dmgr.isnot_reachable(
+ host_ssh, dest_ip, time_out=self.conn_timeout,
+ ping_timeout=5.0)
+ dmgr.STEPINTO_DEBUG_IF_TRUE(not not_reachable)
+ self.assertTrue(not_reachable, msg)
+ self.log_exc_msg(
+ (" VM[%s] is not able to PING %s[%s]" %
+ (host_id, ip_type, dest_ip)))
+
+ def ican_reach_ip(self, ip_addr, ping_timeout=5):
+ ip_type = 'floating-ip'
+ for x in range(int(self.conn_timeout / ping_timeout)):
+ reachable = self.ping_ip_address(ip_addr,
+ ping_timeout=ping_timeout)
+ if reachable:
+ break
+ time.sleep(2.0)
+ msg = (self.exc_msg +
+ ("\n *FAILURE* Tempest cannot PING %s[%s]" %
+ (ip_type, ip_addr)))
+ if not reachable:
+ reachable = self.ping_ip_address(ip_addr,
+ ping_timeout=ping_timeout)
+ dmgr.STEPINTO_DEBUG_IF_TRUE(not reachable)
+ self.assertTrue(reachable, msg)
+ self.log_exc_msg(" Tempest can PING %s[%s]" % (ip_type, ip_addr))
+
+ def icannot_reach_ip(self, ip_addr, ping_timeout=5):
+ ip_type = 'floating-ip'
+ for x in range(int(self.conn_timeout / ping_timeout)):
+ reachable = self.ping_ip_address(ip_addr,
+ ping_timeout=ping_timeout)
+ if not reachable:
+ break
+ time.sleep(ping_timeout)
+ msg = (self.exc_msg +
+ ("\n *FAILURE* Tempest should not PING %s[%s]" %
+ (ip_type, ip_addr)))
+ if reachable:
+ reachable = self.ping_ip_address(ip_addr,
+ ping_timeout=ping_timeout)
+ dmgr.STEPINTO_DEBUG_IF_TRUE(reachable)
+ self.assertFalse(reachable, msg)
+ self.log_exc_msg((" Tempest isnot able to PING %s[%s]" %
+ (ip_type, ip_addr)))
+
+ def run_admin_policy_op_scenario(self, router_type):
+ self.log_exc_msg(("Setup admin-policy test with router-type[%s]" %
+ router_type))
+ self.create_nasa_topo(router_type)
+ self.jpl_private_ips = [y['fixed_ip_address']
+ for x, y in six.iteritems(self.server_ips)
+ if x > '2']
+ self.ames_private_ips = [y['fixed_ip_address']
+ for x, y in six.iteritems(self.server_ips)
+ if x < '3']
+
+ self.run_policy_AA_on_ames_AA_on_jpl()
+ self.run_policy_AA_on_ames_BB_on_jpl()
+ self.run_policy_BB_on_ames_BB_on_jpl()
+
+ dmgr.LOG.debug(self.exc_msg)
+
+ def run_policy_AA_on_ames_AA_on_jpl(self):
+ self.log_exc_msg(("### tenant:jpl=policy_AA[%s]"
+ ", tenant:ames=policy_AA[%s]" %
+ (self.policy_AA, self.policy_AA)))
+ # at the beginning, can ssh to VM with floating-ip
+ self.log_exc_msg(
+ "Tempest can ping & ssh vm-nasa-ames-1's floatingip")
+ self.ican_reach_ip(self.fip_nasa_ames_1['floating_ip_address'])
+ ames_1_ssh = self.host_ssh_reachable(
+ "nasa-ames-1",
+ self.fip_nasa_ames_1['floating_ip_address'])
+
+ # from vm-nasa-ames-1 can ping all other private-ips
+ self.log_exc_msg(("vm-nasa-ames-1[%s] can ping all private-ips"
+ % (self.server_ips['1']['fixed_ip_address'])))
+ self.host_can_reach_ips('nasa-ames-1', ames_1_ssh,
+ 'ame-private-ip', self.ames_private_ips)
+ self.host_can_reach_ips('nasa-ames-1', ames_1_ssh,
+ 'jp-private-ip', self.jpl_private_ips)
+ # from vm-nasa-jpl_3 can ping all other private-ips
+ self.log_exc_msg(
+ "Tempest can ping & ssh vm-nasa-jpl-3's floatingip")
+ self.ican_reach_ip(self.fip_nasa_jpl_3['floating_ip_address'])
+ jpl_3_ssh = self.host_ssh_reachable(
+ "nasa-jpl-3",
+ self.fip_nasa_jpl_3['floating_ip_address'])
+ self.log_exc_msg(("vm-nasa-jpl-3[%s] can ping all private-ips"
+ % (self.server_ips['3']['fixed_ip_address'])))
+ self.host_can_reach_ips('nasa-jpl-3', jpl_3_ssh,
+ 'jp-private-ip', self.jpl_private_ips)
+ self.host_can_reach_ips('nasa-jpl-3', jpl_3_ssh,
+ 'ames-private-ip', self.ames_private_ips)
+ # within VM can ping both tanants' floating-ips
+ self.log_exc_msg(
+ "vm-nasa-ames-1 can ping vm-nasa-jpl-1's floatingip")
+ self.host_can_reach_ips(
+ 'nasa-ames-1', ames_1_ssh, 'jpl-floating-ip',
+ [self.fip_nasa_jpl_3['floating_ip_address']])
+ self.log_exc_msg(
+ "vm-nasa-jpl-3 can ping vm-nasa-ames-3's floatingip")
+ self.host_can_reach_ips(
+ 'nasa-jpl-3', jpl_3_ssh, 'nasa-floating-ip',
+ [self.fip_nasa_ames_1['floating_ip_address']])
+
+ def run_policy_AA_on_ames_BB_on_jpl(self):
+ # from vm-nasa-ames-1 can ping all other private-ips
+ self.log_exc_msg(
+ ("Update tenant:jpl to use policy_BB[%s] with group-ping"
+ % self.policy_BB))
+ # admin update jpl to policy_BB_GP
+ self.update_security_group_policy(self.sg_jpl['id'], self.policy_BB)
+ # cannot ping vm-nasa-jpl-3, can ssh to both tenants' floating-ips
+ self.log_exc_msg(("### tenant:jpl=policy_BB[%s]"
+ ", tenant:ames=policy_AA[%s]" %
+ (self.policy_BB, self.policy_AA)))
+ self.log_exc_msg(
+ "Tempest can ping & ssh vm-nasa-ames-1's floatingip")
+ self.ican_reach_ip(self.fip_nasa_ames_1['floating_ip_address'])
+ ames_1_ssh = self.host_ssh_reachable(
+ "nasa-ames-1",
+ self.fip_nasa_ames_1['floating_ip_address'])
+ self.log_exc_msg("Tempest can ssh vm-nasa-jpl-3's floatingip"
+ ", but not ping")
+ self.icannot_reach_ip(self.fip_nasa_jpl_3['floating_ip_address'])
+ jpl_3_ssh = self.host_ssh_reachable(
+ "nasa-jpl-3",
+ self.fip_nasa_jpl_3['floating_ip_address'])
+ # vm-nasa-jpl_3 can ping its private-ips, not other tenants
+ self.log_exc_msg(("vm-nasa-jpl-3[%s] can reach all private-ips"
+ % (self.server_ips['3']['fixed_ip_address'])))
+ self.host_can_reach_ips('nasa-jpl-3', jpl_3_ssh,
+ 'jpl-private-ip', self.jpl_private_ips)
+ self.host_can_reach_ips('nasa-jpl-3', jpl_3_ssh,
+ 'ames-private-ip', self.ames_private_ips)
+ # nasa_ames_1 can not ping private-ips of tenant jpl
+ # as policy_BB:ping only allowed from the same security-group
+ self.log_exc_msg(("vm-nasa-ames-1[%s] can reach ames's rivate-ips"
+ ", not jpl's private-ips"
+ % (self.server_ips['1']['fixed_ip_address'])))
+ self.host_can_reach_ips('nasa-ames-1', ames_1_ssh,
+ 'ames-private-ip', self.ames_private_ips)
+ self.host_cannot_reach_ips('nasa-ames-1', ames_1_ssh,
+ 'jpl-private-ip', self.jpl_private_ips)
+ self.log_exc_msg(
+ "vm-nasa-ames-1 cannot ping vm-nasa-jpl-1's floatingip")
+ self.host_cannot_reach_ips(
+ 'nasa-ames-1', ames_1_ssh, 'jpl-floating-ip',
+ [self.fip_nasa_jpl_3['floating_ip_address']])
+ self.log_exc_msg(
+ "vm-nasa-jpl-3 cannot ping vm-nasa-ames-3's floatingip")
+ self.host_cannot_reach_ips(
+ 'nasa-jpl-3', jpl_3_ssh, 'ames-floating-ip',
+ [self.fip_nasa_ames_1['floating_ip_address']])
+
+ def run_policy_BB_on_ames_BB_on_jpl(self):
+ ### tenant jpl:policy_BB_GP, tenant ames:policy_BB_GP
+ self.log_exc_msg(
+ ("Update tenant:ames to use policy_BB[%s] with group-ping"
+ % self.policy_BB))
+ # admin update ames to policy_BB
+ self.update_security_group_policy(self.sg_ames['id'], self.policy_BB)
+ # cannot ping all VMs, but can ssh to both tenants' floating-ips
+ self.log_exc_msg(("### tenant:jpl=policy_BB[%s]"
+ ", tenant:ames=policy_BB[%s]" %
+ (self.policy_BB, self.policy_BB)))
+ self.log_exc_msg("Tempest can ssh vvm-nasa-ames-1's floatingip &"
+ " vm-nasa-jpl-3's floatingip, but not ping.")
+ self.icannot_reach_ip(self.fip_nasa_ames_1['floating_ip_address'])
+ self.icannot_reach_ip(self.fip_nasa_jpl_3['floating_ip_address'])
+ ames_1_ssh = self.host_ssh_reachable(
+ "nasa-ames-1",
+ self.fip_nasa_ames_1['floating_ip_address'])
+ jpl_3_ssh = self.host_ssh_reachable(
+ "nasa-jpl-3",
+ self.fip_nasa_jpl_3['floating_ip_address'])
+ self.log_exc_msg(("vm-nasa-jpl-3[%s] can reach jpl private-ips"
+ ", not ames"
+ % (self.server_ips['3']['fixed_ip_address'])))
+ self.host_can_reach_ips('nasa-jpl-3', jpl_3_ssh,
+ 'private-ip', self.jpl_private_ips)
+ self.host_cannot_reach_ips('nasa-jpl-3', jpl_3_ssh,
+ 'private-ip', self.ames_private_ips)
+ self.log_exc_msg(("vm-nasa-ames-1[%s] can reach ames private-ips"
+ ", not jpl"
+ % (self.server_ips['1']['fixed_ip_address'])))
+ self.host_can_reach_ips('nasa-ames-1', ames_1_ssh,
+ 'private-ip', self.ames_private_ips)
+ self.host_cannot_reach_ips('nasa-ames-1', ames_1_ssh,
+ 'private-ip', self.jpl_private_ips)
+ self.log_exc_msg(
+ "vm-nasa-ames-1 cannot ping vm-nasa-jpl-1's floatingip")
+ self.host_cannot_reach_ips(
+ 'nasa-ames-1', ames_1_ssh, 'floating-ip',
+ [self.fip_nasa_jpl_3['floating_ip_address']])
+ self.log_exc_msg(
+ "vm-nasa-jpl-3 cannot ping vm-nasa-ames-3's floatingip")
+ self.host_cannot_reach_ips(
+ 'nasa-jpl-3', jpl_3_ssh, 'floating-ip',
+ [self.fip_nasa_ames_1['floating_ip_address']])
+
+
+class TestAdminPolicySharedRouter(TestAdminPolicyBasicOps):
+ @test.idempotent_id('78f45717-5f95-4ef5-b2a4-a1b4700ef688')
+ def test_admin_policy_ops_with_shared_router(self):
+ self.run_admin_policy_op_scenario('shared')
+
+
+class TestAdminPolicyExclusiveRouter(TestAdminPolicyBasicOps):
+ @test.idempotent_id('68345852-da2e-4f46-816b-0afc59470a45')
+ def test_admin_policy_ops_with_exclusive_router(self):
+ self.run_admin_policy_op_scenario('exclusive')
+
+
+class TestAdminPolicyDistributedRouter(TestAdminPolicyBasicOps):
+ @test.idempotent_id('76adbfbb-a2e5-40fa-8930-84e7ece87bd5')
+ def test_admin_policy_ops_with_distributed_router(self):
+ self.run_admin_policy_op_scenario('distributed')