summaryrefslogtreecommitdiffstats
path: root/snaps/openstack/utils
diff options
context:
space:
mode:
authorspisarski <s.pisarski@cablelabs.com>2017-11-02 12:03:42 -0600
committerspisarski <s.pisarski@cablelabs.com>2017-11-02 12:03:42 -0600
commit79accabe2003937edf8826cf565ef42a0056e9a4 (patch)
tree29aba44646e7a7d5683fb383432d533b9a690c4f /snaps/openstack/utils
parentb20a368daa581e3f649ac5a772da31cd09fdb484 (diff)
Added method to OpenStackHeatStack to return OpenStackRouter objects.
Continuation of the story SNAPS-153 for adding creator/state machine instances for OpenStack objects deployed via Heat. JIRA: SNAPS-173 Change-Id: Iac9138ef7827c10db1637447d3a909e714a0301b Signed-off-by: spisarski <s.pisarski@cablelabs.com>
Diffstat (limited to 'snaps/openstack/utils')
-rw-r--r--snaps/openstack/utils/heat_utils.py22
-rw-r--r--snaps/openstack/utils/neutron_utils.py35
-rw-r--r--snaps/openstack/utils/settings_utils.py96
-rw-r--r--snaps/openstack/utils/tests/heat_utils_tests.py79
-rw-r--r--snaps/openstack/utils/tests/neutron_utils_tests.py2
-rw-r--r--snaps/openstack/utils/tests/settings_utils_tests.py2
6 files changed, 215 insertions, 21 deletions
diff --git a/snaps/openstack/utils/heat_utils.py b/snaps/openstack/utils/heat_utils.py
index ad354e0..02b4f7c 100644
--- a/snaps/openstack/utils/heat_utils.py
+++ b/snaps/openstack/utils/heat_utils.py
@@ -197,14 +197,32 @@ def get_stack_networks(heat_cli, neutron, stack):
out = list()
resources = get_resources(heat_cli, stack, 'OS::Neutron::Net')
for resource in resources:
- network = neutron_utils.get_network_by_id(
- neutron, resource.id)
+ network = neutron_utils.get_network_by_id(neutron, resource.id)
if network:
out.append(network)
return out
+def get_stack_routers(heat_cli, neutron, stack):
+ """
+ Returns a list of Network domain objects deployed by this stack
+ :param heat_cli: the OpenStack heat client object
+ :param neutron: the OpenStack neutron client object
+ :param stack: the SNAPS-OO Stack domain object
+ :return: a list of Network objects
+ """
+
+ out = list()
+ resources = get_resources(heat_cli, stack, 'OS::Neutron::Router')
+ for resource in resources:
+ router = neutron_utils.get_router_by_id(neutron, resource.id)
+ if router:
+ out.append(router)
+
+ return out
+
+
def get_stack_servers(heat_cli, nova, stack):
"""
Returns a list of VMInst domain objects associated with a Stack
diff --git a/snaps/openstack/utils/neutron_utils.py b/snaps/openstack/utils/neutron_utils.py
index 806bb53..24c4afd 100644
--- a/snaps/openstack/utils/neutron_utils.py
+++ b/snaps/openstack/utils/neutron_utils.py
@@ -231,7 +231,7 @@ def create_router(neutron, os_creds, router_settings):
json_body = router_settings.dict_for_neutron(neutron, os_creds)
logger.info('Creating router with name - ' + router_settings.name)
os_router = neutron.create_router(json_body)
- return Router(**os_router['router'])
+ return __map_router(neutron, os_router['router'])
else:
logger.error("Failed to create router.")
raise NeutronException('Failed to create router')
@@ -257,7 +257,7 @@ def get_router_by_id(neutron, router_id):
"""
router = neutron.show_router(router_id)
if router:
- return Router(**router['router'])
+ return __map_router(neutron, router['router'])
def get_router(neutron, router_settings=None, router_name=None):
@@ -281,11 +281,40 @@ def get_router(neutron, router_settings=None, router_name=None):
return None
routers = neutron.list_routers(**router_filter)
+
for routerInst in routers['routers']:
- return Router(**routerInst)
+ return __map_router(neutron, routerInst)
+
return None
+def __map_router(neutron, os_router):
+ """
+ Takes an OpenStack router instance and maps it to a SNAPS Router domain
+ object
+ :param neutron: the neutron client
+ :param os_router: the OpenStack Router object
+ :return:
+ """
+ device_ports = neutron.list_ports(
+ **{'device_id': os_router['id']})['ports']
+ port_subnets = list()
+
+ # Order by create date
+ sorted_ports = sorted(device_ports, key=lambda dev_port: dev_port['created_at'])
+
+ for port in sorted_ports:
+ subnets = list()
+ for fixed_ip in port['fixed_ips']:
+ subnet = get_subnet_by_id(neutron, fixed_ip['subnet_id'])
+ if subnet and subnet.network_id == port['network_id']:
+ subnets.append(subnet)
+ port_subnets.append((Port(**port), subnets))
+
+ os_router['port_subnets'] = port_subnets
+ return Router(**os_router)
+
+
def add_interface_router(neutron, router, subnet=None, port=None):
"""
Adds an interface router for OpenStack for either a subnet or port.
diff --git a/snaps/openstack/utils/settings_utils.py b/snaps/openstack/utils/settings_utils.py
index 2ab3c28..2e29063 100644
--- a/snaps/openstack/utils/settings_utils.py
+++ b/snaps/openstack/utils/settings_utils.py
@@ -21,6 +21,7 @@ from snaps.openstack.create_instance import (
from snaps.openstack.create_keypairs import KeypairSettings
from snaps.openstack.create_network import (
PortSettings, SubnetSettings, NetworkSettings)
+from snaps.openstack.create_router import RouterSettings
from snaps.openstack.create_volume import VolumeSettings
from snaps.openstack.create_volume_type import (
VolumeTypeSettings, VolumeTypeEncryptionSettings, ControlLocation)
@@ -67,6 +68,60 @@ def create_subnet_settings(neutron, network):
return out
+def create_router_settings(neutron, router):
+ """
+ Returns a RouterSettings object
+ :param neutron: the neutron client
+ :param router: a SNAPS-OO Router domain object
+ :return:
+ """
+ ext_net_name = None
+
+ if router.external_network_id:
+ network = neutron_utils.get_network_by_id(
+ neutron, router.external_network_id)
+ if network:
+ ext_net_name = network.name
+
+ ports_tuple_list = list()
+ if router.port_subnets:
+ for port, subnets in router.port_subnets:
+ network = neutron_utils.get_network_by_id(
+ neutron, port.network_id)
+
+ ip_addrs = list()
+ if network and router.external_fixed_ips:
+ for ext_fixed_ips in router.external_fixed_ips:
+ for subnet in subnets:
+ if ext_fixed_ips['subnet_id'] == subnet.id:
+ ip_addrs.append(ext_fixed_ips['ip_address'])
+ else:
+ for ip in port.ips:
+ ip_addrs.append(ip)
+
+ ip_list = list()
+ if len(ip_addrs) > 0:
+ for ip_addr in ip_addrs:
+ if isinstance(ip_addr, dict):
+ ip_list.append(ip_addr['ip_address'])
+ else:
+ ip_list.append(ip_addr)
+
+ ports_tuple_list.append((network, ip_list))
+
+ port_settings = __create_port_settings(neutron, ports_tuple_list)
+
+ filtered_settings = list()
+ for port_setting in port_settings:
+ if port_setting.network_name != ext_net_name:
+ filtered_settings.append(port_setting)
+
+ return RouterSettings(
+ name=router.name, external_gateway=ext_net_name,
+ admin_state_up=router.admin_state_up,
+ port_settings=filtered_settings)
+
+
def create_volume_settings(volume):
"""
Returns a VolumeSettings object
@@ -162,8 +217,15 @@ def create_vm_inst_settings(nova, neutron, server):
kwargs = dict()
kwargs['name'] = server.name
kwargs['flavor'] = flavor_name
+
+ net_tuples = list()
+ for net_name, ips in server.networks.items():
+ network = neutron_utils.get_network(neutron, network_name=net_name)
+ if network:
+ net_tuples.append((network, ips))
+
kwargs['port_settings'] = __create_port_settings(
- neutron, server.networks)
+ neutron, net_tuples)
kwargs['security_group_names'] = server.sec_grp_names
kwargs['floating_ip_settings'] = __create_floatingip_settings(
neutron, kwargs['port_settings'])
@@ -175,24 +237,32 @@ def __create_port_settings(neutron, networks):
"""
Returns a list of port settings based on the networks parameter
:param neutron: the neutron client
- :param networks: a dict where the key is the network name and the value
- is a list of IP addresses
+ :param networks: a list of tuples where #1 is the SNAPS Network domain
+ object and #2 is a list of IP addresses
:return:
"""
out = list()
- for net_name, ips in networks.items():
- network = neutron_utils.get_network(neutron, network_name=net_name)
+ for network, ips in networks:
ports = neutron_utils.get_ports(neutron, network, ips)
for port in ports:
- kwargs = dict()
- if port.name:
- kwargs['name'] = port.name
- kwargs['network_name'] = network.name
- kwargs['mac_address'] = port.mac_address
- kwargs['allowed_address_pairs'] = port.allowed_address_pairs
- kwargs['admin_state_up'] = port.admin_state_up
- out.append(PortSettings(**kwargs))
+ if port.device_owner != 'network:dhcp':
+ ip_addrs = list()
+ for ip_dict in port.ips:
+ subnet = neutron_utils.get_subnet_by_id(
+ neutron, ip_dict['subnet_id'])
+ ip_addrs.append({'subnet_name': subnet.name,
+ 'ip': ip_dict['ip_address']})
+
+ kwargs = dict()
+ if port.name:
+ kwargs['name'] = port.name
+ kwargs['network_name'] = network.name
+ kwargs['mac_address'] = port.mac_address
+ kwargs['allowed_address_pairs'] = port.allowed_address_pairs
+ kwargs['admin_state_up'] = port.admin_state_up
+ kwargs['ip_addrs'] = ip_addrs
+ out.append(PortSettings(**kwargs))
return out
diff --git a/snaps/openstack/utils/tests/heat_utils_tests.py b/snaps/openstack/utils/tests/heat_utils_tests.py
index 567cf7b..56bed6b 100644
--- a/snaps/openstack/utils/tests/heat_utils_tests.py
+++ b/snaps/openstack/utils/tests/heat_utils_tests.py
@@ -405,6 +405,85 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase):
self.assertEqual(self.keypair_name, keypair2_settings.name)
+class HeatUtilsRouterTests(OSComponentTestCase):
+ """
+ Test Heat volume functionality
+ """
+
+ def setUp(self):
+ """
+ Instantiates OpenStack instances that cannot be spawned by Heat
+ """
+ guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ stack_name = guid + '-stack'
+
+ self.net_name = guid + '-net'
+ self.subnet_name = guid + '-subnet'
+ self.router_name = guid + '-router'
+
+ env_values = {
+ 'net_name': self.net_name,
+ 'subnet_name': self.subnet_name,
+ 'router_name': self.router_name,
+ 'external_net_name': self.ext_net_name}
+
+ heat_tmplt_path = pkg_resources.resource_filename(
+ 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
+ self.stack_settings = StackSettings(
+ name=stack_name, template_path=heat_tmplt_path,
+ env_values=env_values)
+ self.stack = None
+ self.heat_client = heat_utils.heat_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(self.os_creds)
+
+ def tearDown(self):
+ """
+ Cleans the image and downloaded image file
+ """
+ if self.stack:
+ try:
+ heat_utils.delete_stack(self.heat_client, self.stack)
+ except:
+ pass
+
+ def test_create_router_with_stack(self):
+ """
+ Tests the creation of an OpenStack router with Heat and the retrieval
+ of the Router Domain objects from heat_utils#get_stack_routers().
+ """
+ self.stack = heat_utils.create_stack(
+ self.heat_client, self.stack_settings)
+
+ # Wait until stack deployment has completed
+ end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT
+ is_active = False
+ while time.time() < end_time:
+ status = heat_utils.get_stack_status(self.heat_client,
+ self.stack.id)
+ if status == create_stack.STATUS_CREATE_COMPLETE:
+ is_active = True
+ break
+ elif status == create_stack.STATUS_CREATE_FAILED:
+ is_active = False
+ break
+
+ time.sleep(3)
+
+ self.assertTrue(is_active)
+
+ routers = heat_utils.get_stack_routers(
+ self.heat_client, self.neutron, self.stack)
+
+ self.assertEqual(1, len(routers))
+
+ router = routers[0]
+ self.assertEqual(self.router_name, router.name)
+
+ ext_net = neutron_utils.get_network(
+ self.neutron, network_name=self.ext_net_name)
+ self.assertEqual(ext_net.id, router.external_network_id)
+
+
class HeatUtilsVolumeTests(OSComponentTestCase):
"""
Test Heat volume functionality
diff --git a/snaps/openstack/utils/tests/neutron_utils_tests.py b/snaps/openstack/utils/tests/neutron_utils_tests.py
index 05d508d..0726920 100644
--- a/snaps/openstack/utils/tests/neutron_utils_tests.py
+++ b/snaps/openstack/utils/tests/neutron_utils_tests.py
@@ -352,7 +352,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
ext_net = neutron_utils.get_network(
self.neutron, network_name=self.ext_net_name)
self.assertEqual(
- self.router.external_gateway_info['network_id'], ext_net.id)
+ self.router.external_network_id, ext_net.id)
def test_create_router_empty_name(self):
"""
diff --git a/snaps/openstack/utils/tests/settings_utils_tests.py b/snaps/openstack/utils/tests/settings_utils_tests.py
index 69bdf7c..3073d53 100644
--- a/snaps/openstack/utils/tests/settings_utils_tests.py
+++ b/snaps/openstack/utils/tests/settings_utils_tests.py
@@ -150,8 +150,6 @@ class SettingsUtilsVmInstTests(OSComponentTestCase):
Instantiates the CreateImage object that is responsible for downloading
and creating an OS image file within OpenStack
"""
- # super(self.__class__, self).__start__()
-
self.nova = nova_utils.nova_client(self.os_creds)
self.glance = glance_utils.glance_client(self.os_creds)
self.neutron = neutron_utils.neutron_client(self.os_creds)