summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/how-to-use/IntegrationTests.rst10
-rw-r--r--examples/launch.py676
-rw-r--r--snaps/openstack/create_flavor.py2
-rw-r--r--snaps/openstack/create_image.py6
-rw-r--r--snaps/openstack/create_instance.py174
-rw-r--r--snaps/openstack/tests/create_instance_tests.py218
-rw-r--r--snaps/openstack/tests/openstack_tests.py10
-rw-r--r--snaps/openstack/utils/launch_utils.py804
-rw-r--r--snaps/provisioning/ansible_pb/__init__.py0
-rw-r--r--snaps/provisioning/ansible_pb/centos-network-setup/__init__.py0
-rw-r--r--snaps/provisioning/ansible_pb/centos-network-setup/playbooks/__init__.py0
-rw-r--r--snaps/provisioning/ansible_pb/centos-network-setup/playbooks/configure_host.yml26
-rw-r--r--snaps/provisioning/ansible_pb/centos-network-setup/templates/ifcfg-interface14
-rw-r--r--snaps/provisioning/ansible_pb/ubuntu-network-setup/__init__.py0
-rw-r--r--snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/__init__.py0
-rw-r--r--snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/configure_host.yml26
-rw-r--r--snaps/provisioning/ansible_pb/ubuntu-network-setup/templates/ethN.cfg2
-rw-r--r--snaps/provisioning/tests/ansible_utils_tests.py6
-rw-r--r--snaps/test_suite_builder.py19
19 files changed, 912 insertions, 1081 deletions
diff --git a/docs/how-to-use/IntegrationTests.rst b/docs/how-to-use/IntegrationTests.rst
index df8859f..b7aa864 100644
--- a/docs/how-to-use/IntegrationTests.rst
+++ b/docs/how-to-use/IntegrationTests.rst
@@ -606,16 +606,6 @@ create_instance_tests.py - CreateInstanceFromThreePartImage
| | Neutron 2 | delete it when using a 3-part image |
+-----------------------------------------------------+---------------+-----------------------------------------------------------+
-create_instance_tests.py - CreateInstancePubPrivNetTests (Staging)
-------------------------------------------------------------------
-
-+---------------------------------------+---------------+-----------------------------------------------------------+
-| Test Name | API Versions | Description |
-+=======================================+===============+===========================================================+
-| test_dual_ports_dhcp | Nova 2 | Ensures that a VM with two ports/NICs can have its second |
-| | Neutron 2 | NIC configured via SSH/Ansible after startup |
-+---------------------------------------+---------------+-----------------------------------------------------------+
-
create_instance_tests.py - CreateInstanceIPv6NetworkTests (Staging)
-------------------------------------------------------------------
diff --git a/examples/launch.py b/examples/launch.py
index 975d834..04bc5d6 100644
--- a/examples/launch.py
+++ b/examples/launch.py
@@ -18,558 +18,19 @@
# This script is responsible for deploying virtual environments
import argparse
import logging
-import re
-import time
from jinja2 import Environment, FileSystemLoader
import os
import yaml
from snaps import file_utils
-from snaps.config.flavor import FlavorConfig
-from snaps.config.image import ImageConfig
-from snaps.config.keypair import KeypairConfig
-from snaps.config.network import PortConfig, NetworkConfig
-from snaps.config.project import ProjectConfig
-from snaps.config.qos import QoSConfig
-from snaps.config.router import RouterConfig
-from snaps.config.security_group import SecurityGroupConfig
-from snaps.config.user import UserConfig
-from snaps.config.vm_inst import VmInstanceConfig
-from snaps.config.volume import VolumeConfig
-from snaps.config.volume_type import VolumeTypeConfig
-from snaps.openstack.create_flavor import OpenStackFlavor
-from snaps.openstack.create_image import OpenStackImage
-from snaps.openstack.create_keypairs import OpenStackKeypair
-from snaps.openstack.create_network import OpenStackNetwork
-from snaps.openstack.create_project import OpenStackProject
-from snaps.openstack.create_qos import OpenStackQoS
-from snaps.openstack.create_router import OpenStackRouter
-from snaps.openstack.create_security_group import OpenStackSecurityGroup
-from snaps.openstack.create_user import OpenStackUser
-from snaps.openstack.create_volume import OpenStackVolume
-from snaps.openstack.create_volume_type import OpenStackVolumeType
-from snaps.openstack.os_credentials import OSCreds, ProxySettings
-from snaps.openstack.utils import deploy_utils
-from snaps.provisioning import ansible_utils
+from snaps.openstack.utils import launch_utils
__author__ = 'spisarski'
logger = logging.getLogger('snaps_launcher')
ARG_NOT_SET = "argument not set"
-DEFAULT_CREDS_KEY = 'admin'
-
-
-def __get_creds_dict(os_conn_config):
- """
- Returns a dict of OSCreds where the key is the creds name.
- For backwards compatibility, credentials not contained in a list (only
- one) will be returned with the key of None
- :param os_conn_config: the credential configuration
- :return: a dict of OSCreds objects
- """
- if 'connection' in os_conn_config:
- return {DEFAULT_CREDS_KEY: __get_os_credentials(os_conn_config)}
- elif 'connections' in os_conn_config:
- out = dict()
- for os_conn_dict in os_conn_config['connections']:
- config = os_conn_dict.get('connection')
- if not config:
- raise Exception('Invalid connection format')
-
- name = config.get('name')
- if not name:
- raise Exception('Connection config requires a name field')
-
- out[name] = __get_os_credentials(os_conn_dict)
- return out
-
-
-def __get_creds(os_creds_dict, os_user_dict, inst_config):
- """
- Returns the appropriate credentials
- :param os_creds_dict: a dictionary of OSCreds objects where the name is the
- key
- :param os_user_dict: a dictionary of OpenStackUser objects where the name
- is the key
- :param inst_config:
- :return: an OSCreds instance or None
- """
- os_creds = os_creds_dict.get(DEFAULT_CREDS_KEY)
- if 'os_user' in inst_config:
- os_user_conf = inst_config['os_user']
- if 'name' in os_user_conf:
- user_creator = os_user_dict.get(os_user_conf['name'])
- if user_creator:
- return user_creator.get_os_creds(
- project_name=os_user_conf.get('project_name'))
- elif 'os_creds_name' in inst_config:
- if 'os_creds_name' in inst_config:
- os_creds = os_creds_dict[inst_config['os_creds_name']]
- return os_creds
-
-
-def __get_os_credentials(os_conn_config):
- """
- Returns an object containing all of the information required to access
- OpenStack APIs
- :param os_conn_config: The configuration holding the credentials
- :return: an OSCreds instance
- """
- config = os_conn_config.get('connection')
- if not config:
- raise Exception('Invalid connection configuration')
-
- proxy_settings = None
- http_proxy = config.get('http_proxy')
- if http_proxy:
- tokens = re.split(':', http_proxy)
- ssh_proxy_cmd = config.get('ssh_proxy_cmd')
- proxy_settings = ProxySettings(host=tokens[0], port=tokens[1],
- ssh_proxy_cmd=ssh_proxy_cmd)
- else:
- if 'proxy_settings' in config:
- host = config['proxy_settings'].get('host')
- port = config['proxy_settings'].get('port')
- if host and host != 'None' and port and port != 'None':
- proxy_settings = ProxySettings(**config['proxy_settings'])
-
- if proxy_settings:
- config['proxy_settings'] = proxy_settings
- else:
- if config.get('proxy_settings'):
- del config['proxy_settings']
-
- return OSCreds(**config)
-
-
-def __parse_ports_config(config):
- """
- Parses the "ports" configuration
- :param config: The dictionary to parse
- :return: a list of PortConfig objects
- """
- out = list()
- for port_config in config:
- out.append(PortConfig(**port_config.get('port')))
- return out
-
-
-def __create_instances(os_creds_dict, creator_class, config_class, config,
- config_key, cleanup=False, os_users_dict=None):
- """
- Returns a dictionary of SNAPS creator objects where the key is the name
- :param os_creds_dict: Dictionary of OSCreds objects where the key is the
- name
- :param config: The list of configurations for the same type
- :param config_key: The list of configurations for the same type
- :param cleanup: Denotes whether or not this is being called for cleanup
- :return: dictionary
- """
- out = {}
-
- if config:
- try:
- for config_dict in config:
- inst_config = config_dict.get(config_key)
- if inst_config:
- creator = creator_class(
- __get_creds(os_creds_dict, os_users_dict, inst_config),
- config_class(**inst_config))
-
- if cleanup:
- creator.initialize()
- else:
- creator.create()
- out[inst_config['name']] = creator
- logger.info('Created configured %s', config_key)
- except Exception as e:
- logger.error('Unexpected error instantiating creator [%s] '
- 'with exception %s', creator_class, e)
-
- return out
-
-
-def __create_vm_instances(os_creds_dict, os_users_dict, instances_config,
- image_dict, keypairs_dict, cleanup=False):
- """
- Returns a dictionary of OpenStackVmInstance objects where the key is the
- instance name
- :param os_creds_dict: Dictionary of OSCreds objects where the key is the
- name
- :param os_users_dict: Dictionary of OpenStackUser objects where the key is
- the username
- :param instances_config: The list of VM instance configurations
- :param image_dict: A dictionary of images that will probably be used to
- instantiate the VM instance
- :param keypairs_dict: A dictionary of keypairs that will probably be used
- to instantiate the VM instance
- :param cleanup: Denotes whether or not this is being called for cleanup
- :return: dictionary
- """
- vm_dict = {}
-
- if instances_config:
- try:
- for instance_config in instances_config:
- conf = instance_config.get('instance')
- if conf:
- if image_dict:
- image_creator = image_dict.get(conf.get('imageName'))
- if image_creator:
- instance_settings = VmInstanceConfig(
- **instance_config['instance'])
- kp_creator = keypairs_dict.get(
- conf.get('keypair_name'))
- vm_dict[conf[
- 'name']] = deploy_utils.create_vm_instance(
- __get_creds(
- os_creds_dict, os_users_dict, conf),
- instance_settings,
- image_creator.image_settings,
- keypair_creator=kp_creator,
- init_only=cleanup)
- else:
- raise Exception('Image creator instance not found.'
- ' Cannot instantiate')
- else:
- raise Exception('Image dictionary is None. Cannot '
- 'instantiate')
- else:
- raise Exception('Instance configuration is None. Cannot '
- 'instantiate')
- logger.info('Created configured instances')
- except Exception as e:
- logger.error('Unexpected error creating VM instances - %s', e)
- return vm_dict
-
-
-def __apply_ansible_playbooks(ansible_configs, os_creds_dict, vm_dict,
- image_dict, flavor_dict, env_file):
- """
- Applies ansible playbooks to running VMs with floating IPs
- :param ansible_configs: a list of Ansible configurations
- :param os_creds_dict: Dictionary of OSCreds objects where the key is the
- name
- :param vm_dict: the dictionary of newly instantiated VMs where the name is
- the key
- :param image_dict: the dictionary of newly instantiated images where the
- name is the key
- :param flavor_dict: the dictionary of newly instantiated flavors where the
- name is the key
- :param env_file: the path of the environment for setting the CWD so
- playbook location is relative to the deployment file
- :return: t/f - true if successful
- """
- logger.info("Applying Ansible Playbooks")
- if ansible_configs:
- # Ensure all hosts are accepting SSH session requests
- for vm_inst in list(vm_dict.values()):
- if not vm_inst.vm_ssh_active(block=True):
- logger.warning(
- "Timeout waiting for instance to respond to SSH requests")
- return False
-
- # Set CWD so the deployment file's playbook location can leverage
- # relative paths
- orig_cwd = os.getcwd()
- env_dir = os.path.dirname(env_file)
- os.chdir(env_dir)
-
- # Apply playbooks
- for ansible_config in ansible_configs:
- if 'pre_sleep_time' in ansible_config:
- try:
- sleep_time = int(ansible_config['pre_sleep_time'])
- logger.info('Waiting %s seconds to apply playbooks',
- sleep_time)
- time.sleep(sleep_time)
- except:
- pass
-
- os_creds = os_creds_dict.get(None, 'admin')
- __apply_ansible_playbook(ansible_config, os_creds, vm_dict,
- image_dict, flavor_dict)
-
- # Return to original directory
- os.chdir(orig_cwd)
-
- return True
-
-
-def __apply_ansible_playbook(ansible_config, os_creds, vm_dict, image_dict,
- flavor_dict):
- """
- Applies an Ansible configuration setting
- :param ansible_config: the configuration settings
- :param os_creds: the OpenStack credentials object
- :param vm_dict: the dictionary of newly instantiated VMs where the name is
- the key
- :param image_dict: the dictionary of newly instantiated images where the
- name is the key
- :param flavor_dict: the dictionary of newly instantiated flavors where the
- name is the key
- """
- if ansible_config:
- (remote_user, floating_ips, private_key_filepath,
- proxy_settings) = __get_connection_info(
- ansible_config, vm_dict)
- if floating_ips:
- retval = ansible_utils.apply_playbook(
- ansible_config['playbook_location'], floating_ips, remote_user,
- private_key_filepath,
- variables=__get_variables(ansible_config.get('variables'),
- os_creds, vm_dict, image_dict,
- flavor_dict),
- proxy_setting=proxy_settings)
- if retval != 0:
- # Not a fatal type of event
- logger.warning(
- 'Unable to apply playbook found at location - %s',
- ansible_config.get('playbook_location'))
-
-
-def __get_connection_info(ansible_config, vm_dict):
- """
- Returns a tuple of data required for connecting to the running VMs
- (remote_user, [floating_ips], private_key_filepath, proxy_settings)
- :param ansible_config: the configuration settings
- :param vm_dict: the dictionary of VMs where the VM name is the key
- :return: tuple where the first element is the user and the second is a list
- of floating IPs and the third is the
- private key file location and the fourth is an instance of the
- snaps.ProxySettings class
- (note: in order to work, each of the hosts need to have the same sudo_user
- and private key file location values)
- """
- if ansible_config.get('hosts'):
- hosts = ansible_config['hosts']
- if len(hosts) > 0:
- floating_ips = list()
- remote_user = None
- pk_file = None
- proxy_settings = None
- for host in hosts:
- vm = vm_dict.get(host)
- if vm:
- fip = vm.get_floating_ip()
- if fip:
- remote_user = vm.get_image_user()
-
- if fip:
- floating_ips.append(fip.ip)
- else:
- raise Exception(
- 'Could not find floating IP for VM - ' +
- vm.name)
-
- pk_file = vm.keypair_settings.private_filepath
- proxy_settings = vm.get_os_creds().proxy_settings
- else:
- logger.error('Could not locate VM with name - ' + host)
-
- return remote_user, floating_ips, pk_file, proxy_settings
- return None
-
-
-def __get_variables(var_config, os_creds, vm_dict, image_dict, flavor_dict):
- """
- Returns a dictionary of substitution variables to be used for Ansible
- templates
- :param var_config: the variable configuration settings
- :param os_creds: the OpenStack credentials object
- :param vm_dict: the dictionary of newly instantiated VMs where the name is
- the key
- :param image_dict: the dictionary of newly instantiated images where the
- name is the key
- :param flavor_dict: the dictionary of newly instantiated flavors where the
- name is the key
- :return: dictionary or None
- """
- if var_config and vm_dict and len(vm_dict) > 0:
- variables = dict()
- for key, value in var_config.items():
- value = __get_variable_value(value, os_creds, vm_dict, image_dict,
- flavor_dict)
- if key and value:
- variables[key] = value
- logger.info(
- "Set Jinga2 variable with key [%s] the value [%s]",
- key, value)
- else:
- logger.warning('Key [%s] or Value [%s] must not be None',
- str(key), str(value))
- return variables
- return None
-
-
-def __get_variable_value(var_config_values, os_creds, vm_dict, image_dict,
- flavor_dict):
- """
- Returns the associated variable value for use by Ansible for substitution
- purposes
- :param var_config_values: the configuration dictionary
- :param os_creds: the OpenStack credentials object
- :param vm_dict: the dictionary of newly instantiated VMs where the name is
- the key
- :param image_dict: the dictionary of newly instantiated images where the
- name is the key
- :param flavor_dict: the dictionary of newly instantiated flavors where the
- name is the key
- :return:
- """
- if var_config_values['type'] == 'string':
- return __get_string_variable_value(var_config_values)
- if var_config_values['type'] == 'vm-attr':
- return __get_vm_attr_variable_value(var_config_values, vm_dict)
- if var_config_values['type'] == 'os_creds':
- return __get_os_creds_variable_value(var_config_values, os_creds)
- if var_config_values['type'] == 'port':
- return __get_vm_port_variable_value(var_config_values, vm_dict)
- if var_config_values['type'] == 'floating_ip':
- return __get_vm_fip_variable_value(var_config_values, vm_dict)
- if var_config_values['type'] == 'image':
- return __get_image_variable_value(var_config_values, image_dict)
- if var_config_values['type'] == 'flavor':
- return __get_flavor_variable_value(var_config_values, flavor_dict)
- return None
-
-
-def __get_string_variable_value(var_config_values):
- """
- Returns the associated string value
- :param var_config_values: the configuration dictionary
- :return: the value contained in the dictionary with the key 'value'
- """
- return var_config_values['value']
-
-
-def __get_vm_attr_variable_value(var_config_values, vm_dict):
- """
- Returns the associated value contained on a VM instance
- :param var_config_values: the configuration dictionary
- :param vm_dict: the dictionary containing all VMs where the key is the VM's
- name
- :return: the value
- """
- vm = vm_dict.get(var_config_values['vm_name'])
- if vm:
- if var_config_values['value'] == 'floating_ip':
- return vm.get_floating_ip().ip
- if var_config_values['value'] == 'image_user':
- return vm.get_image_user()
-
-
-def __get_os_creds_variable_value(var_config_values, os_creds):
- """
- Returns the associated OS credentials value
- :param var_config_values: the configuration dictionary
- :param os_creds: the credentials
- :return: the value
- """
- logger.info("Retrieving OS Credentials")
- if os_creds:
- if var_config_values['value'] == 'username':
- logger.info("Returning OS username")
- return os_creds.username
- elif var_config_values['value'] == 'password':
- logger.info("Returning OS password")
- return os_creds.password
- elif var_config_values['value'] == 'auth_url':
- logger.info("Returning OS auth_url")
- return os_creds.auth_url
- elif var_config_values['value'] == 'project_name':
- logger.info("Returning OS project_name")
- return os_creds.project_name
-
- logger.info("Returning none")
- return None
-
-
-def __get_vm_port_variable_value(var_config_values, vm_dict):
- """
- Returns the associated OS credentials value
- :param var_config_values: the configuration dictionary
- :param vm_dict: the dictionary containing all VMs where the key is the VM's
- name
- :return: the value
- """
- port_name = var_config_values.get('port_name')
- vm_name = var_config_values.get('vm_name')
-
- if port_name and vm_name:
- vm = vm_dict.get(vm_name)
- if vm:
- port_value_id = var_config_values.get('port_value')
- if port_value_id:
- if port_value_id == 'mac_address':
- return vm.get_port_mac(port_name)
- if port_value_id == 'ip_address':
- return vm.get_port_ip(port_name)
-
-
-def __get_vm_fip_variable_value(var_config_values, vm_dict):
- """
- Returns the floating IP value if found
- :param var_config_values: the configuration dictionary
- :param vm_dict: the dictionary containing all VMs where the key is the VM's
- name
- :return: the floating IP string value or None
- """
- fip_name = var_config_values.get('fip_name')
- vm_name = var_config_values.get('vm_name')
-
- if vm_name:
- vm = vm_dict.get(vm_name)
- if vm:
- fip = vm.get_floating_ip(fip_name)
- if fip:
- return fip.ip
-
-
-def __get_image_variable_value(var_config_values, image_dict):
- """
- Returns the associated image value
- :param var_config_values: the configuration dictionary
- :param image_dict: the dictionary containing all images where the key is
- the name
- :return: the value
- """
- logger.info("Retrieving image values")
-
- if image_dict:
- if var_config_values.get('image_name'):
- image_creator = image_dict.get(var_config_values['image_name'])
- if image_creator:
- if var_config_values.get('value') and \
- var_config_values['value'] == 'id':
- return image_creator.get_image().id
- if var_config_values.get('value') and \
- var_config_values['value'] == 'user':
- return image_creator.image_settings.image_user
-
- logger.info("Returning none")
- return None
-
-
-def __get_flavor_variable_value(var_config_values, flavor_dict):
- """
- Returns the associated flavor value
- :param var_config_values: the configuration dictionary
- :param flavor_dict: the dictionary containing all flavor creators where the
- key is the name
- :return: the value or None
- """
- logger.info("Retrieving flavor values")
-
- if flavor_dict:
- if var_config_values.get('flavor_name'):
- flavor_creator = flavor_dict.get(var_config_values['flavor_name'])
- if flavor_creator:
- if var_config_values.get('value') and \
- var_config_values['value'] == 'id':
- return flavor_creator.get_flavor().id
def main(arguments):
@@ -605,127 +66,11 @@ def main(arguments):
config = yaml.load(output)
if config:
- os_config = config.get('openstack')
-
- creators = list()
- vm_dict = dict()
- images_dict = dict()
- flavors_dict = dict()
- os_creds_dict = dict()
clean = arguments.clean is not ARG_NOT_SET
-
- if os_config:
- os_creds_dict = __get_creds_dict(os_config)
-
- try:
- # Create projects
- projects_dict = __create_instances(
- os_creds_dict, OpenStackProject, ProjectConfig,
- os_config.get('projects'), 'project', clean)
- creators.append(projects_dict)
-
- # Create users
- users_dict = __create_instances(
- os_creds_dict, OpenStackUser, UserConfig,
- os_config.get('users'), 'user', clean)
- creators.append(users_dict)
-
- # Associate new users to projects
- if not clean:
- for project_creator in projects_dict.values():
- users = project_creator.project_settings.users
- for user_name in users:
- user_creator = users_dict.get(user_name)
- if user_creator:
- project_creator.assoc_user(
- user_creator.get_user())
-
- # Create flavors
- flavors_dict = __create_instances(
- os_creds_dict, OpenStackFlavor, FlavorConfig,
- os_config.get('flavors'), 'flavor', clean, users_dict)
- creators.append(flavors_dict)
-
- # Create QoS specs
- qos_dict = __create_instances(
- os_creds_dict, OpenStackQoS, QoSConfig,
- os_config.get('qos_specs'), 'qos_spec', clean, users_dict)
- creators.append(qos_dict)
-
- # Create volume types
- vol_type_dict = __create_instances(
- os_creds_dict, OpenStackVolumeType, VolumeTypeConfig,
- os_config.get('volume_types'), 'volume_type', clean,
- users_dict)
- creators.append(vol_type_dict)
-
- # Create volume types
- vol_dict = __create_instances(
- os_creds_dict, OpenStackVolume, VolumeConfig,
- os_config.get('volumes'), 'volume', clean, users_dict)
- creators.append(vol_dict)
-
- # Create images
- images_dict = __create_instances(
- os_creds_dict, OpenStackImage, ImageConfig,
- os_config.get('images'), 'image', clean, users_dict)
- creators.append(images_dict)
-
- # Create networks
- creators.append(__create_instances(
- os_creds_dict, OpenStackNetwork, NetworkConfig,
- os_config.get('networks'), 'network', clean, users_dict))
-
- # Create routers
- creators.append(__create_instances(
- os_creds_dict, OpenStackRouter, RouterConfig,
- os_config.get('routers'), 'router', clean, users_dict))
-
- # Create keypairs
- keypairs_dict = __create_instances(
- os_creds_dict, OpenStackKeypair, KeypairConfig,
- os_config.get('keypairs'), 'keypair', clean, users_dict)
- creators.append(keypairs_dict)
-
- # Create security groups
- creators.append(__create_instances(
- os_creds_dict, OpenStackSecurityGroup,
- SecurityGroupConfig,
- os_config.get('security_groups'), 'security_group', clean,
- users_dict))
-
- # Create instance
- vm_dict = __create_vm_instances(
- os_creds_dict, users_dict, os_config.get('instances'),
- images_dict, keypairs_dict,
- arguments.clean is not ARG_NOT_SET)
- creators.append(vm_dict)
- logger.info(
- 'Completed creating/retrieving all configured instances')
- except Exception as e:
- logger.error(
- 'Unexpected error deploying environment. Rolling back due'
- ' to - ' + str(e))
- raise
-
- # Must enter either block
- if arguments.clean is not ARG_NOT_SET:
- # Cleanup Environment
- __cleanup(creators, arguments.clean_image is not ARG_NOT_SET)
- elif arguments.deploy is not ARG_NOT_SET:
- logger.info('Configuring NICs where required')
- for vm in vm_dict.values():
- vm.config_nics()
- logger.info('Completed NIC configuration')
-
- # Provision VMs
- ansible_config = config.get('ansible')
- if ansible_config and vm_dict:
- if not __apply_ansible_playbooks(ansible_config,
- os_creds_dict, vm_dict,
- images_dict, flavors_dict,
- arguments.tmplt_file):
- logger.error("Problem applying ansible playbooks")
+ clean_image = arguments.clean_image is not ARG_NOT_SET
+ deploy = arguments.deploy is not ARG_NOT_SET
+ launch_utils.launch_config(
+ config, arguments.tmplt_file, deploy, clean, clean_image)
else:
logger.error(
'Unable to read configuration file - ' + arguments.tmplt_file)
@@ -734,17 +79,6 @@ def main(arguments):
exit(0)
-def __cleanup(creators, clean_image=False):
- for creator_dict in reversed(creators):
- for key, creator in creator_dict.items():
- if ((isinstance(creator, OpenStackImage) and clean_image)
- or not isinstance(creator, OpenStackImage)):
- try:
- creator.clean()
- except Exception as e:
- logger.warning('Error cleaning component - %s', e)
-
-
if __name__ == '__main__':
# To ensure any files referenced via a relative path will begin from the
# directory in which this file resides
diff --git a/snaps/openstack/create_flavor.py b/snaps/openstack/create_flavor.py
index b866d43..65b9059 100644
--- a/snaps/openstack/create_flavor.py
+++ b/snaps/openstack/create_flavor.py
@@ -71,8 +71,6 @@ class OpenStackFlavor(OpenStackComputeObject):
if self.flavor_settings.metadata:
nova_utils.set_flavor_keys(self._nova, self.__flavor,
self.flavor_settings.metadata)
- else:
- logger.info('Did not create flavor due to cleanup mode')
return self.__flavor
diff --git a/snaps/openstack/create_image.py b/snaps/openstack/create_image.py
index 2e7aa39..a5520e3 100644
--- a/snaps/openstack/create_image.py
+++ b/snaps/openstack/create_image.py
@@ -57,6 +57,7 @@ class OpenStackImage(OpenStackCloudObject):
self.__glance = glance_utils.glance_client(self._os_creds)
self.__image = glance_utils.get_image(
self.__glance, image_settings=self.image_settings)
+
if self.__image:
logger.info('Found image with name - ' + self.image_settings.name)
return self.__image
@@ -70,6 +71,7 @@ class OpenStackImage(OpenStackCloudObject):
self.__kernel_image = glance_utils.get_image(
self.__glance,
image_settings=self.image_settings.kernel_image_settings)
+
if self.image_settings.ramdisk_image_settings:
self.__ramdisk_image = glance_utils.get_image(
self.__glance,
@@ -97,6 +99,7 @@ class OpenStackImage(OpenStackCloudObject):
self.__glance,
self.image_settings.kernel_image_settings)
extra_properties['kernel_id'] = self.__kernel_image.id
+
if self.image_settings.ramdisk_image_settings:
if not self.__ramdisk_image:
logger.info(
@@ -113,6 +116,7 @@ class OpenStackImage(OpenStackCloudObject):
logger.info(
'Created image with name - %s', self.image_settings.name)
+
if self.__image and self.image_active(block=True):
logger.info(
'Image is now active with name - %s',
@@ -122,8 +126,6 @@ class OpenStackImage(OpenStackCloudObject):
raise ImageCreationError(
'Image was not created or activated in the alloted amount'
'of time')
- else:
- logger.info('Did not create image due to cleanup mode')
return self.__image
diff --git a/snaps/openstack/create_instance.py b/snaps/openstack/create_instance.py
index 336c936..b68372e 100644
--- a/snaps/openstack/create_instance.py
+++ b/snaps/openstack/create_instance.py
@@ -15,7 +15,6 @@
import logging
import time
-from neutronclient.common.exceptions import PortNotFoundClient
from novaclient.exceptions import NotFound, BadRequest
from snaps.config.vm_inst import VmInstanceConfig, FloatingIpConfig
@@ -33,6 +32,7 @@ logger = logging.getLogger('create_instance')
POLL_INTERVAL = 3
STATUS_ACTIVE = 'ACTIVE'
STATUS_DELETED = 'DELETED'
+CLOUD_INIT_TIMEOUT = 120
class OpenStackVmInstance(OpenStackComputeObject):
@@ -255,19 +255,25 @@ class OpenStackVmInstance(OpenStackComputeObject):
# Cleanup floating IPs
for name, floating_ip in self.__floating_ip_dict.items():
- try:
- logger.info('Deleting Floating IP - ' + floating_ip.ip)
- neutron_utils.delete_floating_ip(self.__neutron, floating_ip)
- except Exception as e:
- logger.error('Error deleting Floating IP - ' + str(e))
+ logger.info('Deleting Floating IP - ' + floating_ip.ip)
+ neutron_utils.delete_floating_ip(self.__neutron, floating_ip)
+
self.__floating_ip_dict = dict()
- # Detach Volume
- for volume_rec in self.__vm.volume_ids:
- cinder = cinder_utils.cinder_client(self._os_creds)
- volume = cinder_utils.get_volume_by_id(cinder, volume_rec['id'])
- if volume:
- try:
+ # Cleanup ports
+ for name, port in self.__ports:
+ logger.info('Deleting Port with ID - %s ', port.id)
+ neutron_utils.delete_port(self.__neutron, port)
+
+ self.__ports = list()
+
+ if self.__vm:
+ # Detach Volume
+ for volume_rec in self.__vm.volume_ids:
+ cinder = cinder_utils.cinder_client(self._os_creds)
+ volume = cinder_utils.get_volume_by_id(
+ cinder, volume_rec['id'])
+ if volume:
vm = nova_utils.detach_volume(
self._nova, self.__neutron, self.__vm, volume, 30)
if vm:
@@ -275,50 +281,32 @@ class OpenStackVmInstance(OpenStackComputeObject):
else:
logger.warn(
'Timeout waiting to detach volume %s', volume.name)
- except Exception as e:
- logger.error('Unexpected error detaching volume %s '
- 'with error %s', volume.name, e)
- else:
- logger.warn('Unable to detach volume with ID - [%s]',
- volume_rec['id'])
+ else:
+ logger.warn('Unable to detach volume with ID - [%s]',
+ volume_rec['id'])
- # Cleanup ports
- for name, port in self.__ports:
- logger.info('Deleting Port with ID - %s ', port.id)
- try:
- neutron_utils.delete_port(self.__neutron, port)
- except PortNotFoundClient as e:
- logger.warning('Unexpected error deleting port - %s', e)
- pass
- self.__ports = list()
+ # Cleanup VM
+ logger.info(
+ 'Deleting VM instance - ' + self.instance_settings.name)
- # Cleanup VM
- if self.__vm:
try:
- logger.info(
- 'Deleting VM instance - ' + self.instance_settings.name)
nova_utils.delete_vm_instance(self._nova, self.__vm)
- except Exception as e:
- logger.error('Error deleting VM - %s', e)
+ except NotFound as e:
+ logger.warn('Instance already deleted - %s', e)
# Block until instance cannot be found or returns the status of
# DELETED
logger.info('Checking deletion status')
- try:
- if self.vm_deleted(block=True):
- logger.info(
- 'VM has been properly deleted VM with name - %s',
- self.instance_settings.name)
- self.__vm = None
- else:
- logger.error(
- 'VM not deleted within the timeout period of %s '
- 'seconds', self.instance_settings.vm_delete_timeout)
- except Exception as e:
+ if self.vm_deleted(block=True):
+ logger.info(
+ 'VM has been properly deleted VM with name - %s',
+ self.instance_settings.name)
+ self.__vm = None
+ else:
logger.error(
- 'Unexpected error while checking VM instance status - %s',
- e)
+ 'VM not deleted within the timeout period of %s '
+ 'seconds', self.instance_settings.vm_delete_timeout)
def __query_ports(self, port_settings):
"""
@@ -489,25 +477,6 @@ class OpenStackVmInstance(OpenStackComputeObject):
"""
return nova_utils.get_server_info(self._nova, self.__vm)
- def config_nics(self):
- """
- Responsible for configuring NICs on RPM systems where the instance has
- more than one configured port
- :return: the value returned by ansible_utils.apply_ansible_playbook()
- """
- if len(self.__ports) > 1 and len(self.__floating_ip_dict) > 0:
- if self.vm_active(block=True) and self.vm_ssh_active(block=True):
- for key, port in self.__ports:
- port_index = self.__ports.index((key, port))
- if port_index > 0:
- nic_name = 'eth' + repr(port_index)
- retval = self.__config_nic(
- nic_name, port,
- self.__get_first_provisioning_floating_ip().ip)
- logger.info('Configured NIC - %s on VM - %s',
- nic_name, self.instance_settings.name)
- return retval
-
def __get_first_provisioning_floating_ip(self):
"""
Returns the first floating IP tagged with the Floating IP name if
@@ -528,31 +497,6 @@ class OpenStackVmInstance(OpenStackComputeObject):
for key, fip in self.__floating_ip_dict.items():
return fip
- def __config_nic(self, nic_name, port, ip):
- """
- Although ports/NICs can contain multiple IPs, this code currently only
- supports the first.
-
- :param nic_name: Name of the interface
- :param port: The port information containing the expected IP values.
- :param ip: The IP on which to apply the playbook.
- :return: the return value from ansible
- """
- port_ip = port.ips[0]['ip_address']
- variables = {
- 'floating_ip': ip,
- 'nic_name': nic_name,
- 'nic_ip': port_ip
- }
-
- if self.image_settings.nic_config_pb_loc and self.keypair_settings:
- return self.apply_ansible_playbook(
- self.image_settings.nic_config_pb_loc, variables)
- else:
- logger.warning(
- 'VM %s cannot self configure NICs eth1++. No playbook or '
- 'keypairs found.', self.instance_settings.name)
-
def apply_ansible_playbook(self, pb_file_loc, variables=None,
fip_name=None):
"""
@@ -722,6 +666,56 @@ class OpenStackVmInstance(OpenStackComputeObject):
return True
return False
+ def cloud_init_complete(self, block=False, poll_interval=POLL_INTERVAL):
+ """
+ Returns true when the VM's cloud-init routine has completed.
+ Note: this is currently done via SSH, therefore, if this instance does
+ not have a Floating IP or a running SSH server, this routine
+ will always return False or raise an Exception
+ :param block: When true, thread will block until active or timeout
+ value in seconds has been exceeded (False)
+ :param poll_interval: The polling interval
+ :return: T/F
+ """
+ # sleep and wait for VM status change
+ logger.info('Checking if cloud-init has completed')
+
+ timeout = CLOUD_INIT_TIMEOUT
+
+ if self.vm_active(block=True) and self.vm_ssh_active(block=True):
+ if block:
+ start = time.time()
+ else:
+ start = time.time() - timeout
+
+ while timeout > time.time() - start:
+ status = self.__cloud_init_complete()
+ if status:
+ logger.info('cloud-init complete for VM instance')
+ return True
+
+ logger.debug('Retry cloud-init query in ' + str(
+ poll_interval) + ' seconds')
+ time.sleep(poll_interval)
+ logger.debug('cloud-init complete timeout in ' + str(
+ timeout - (time.time() - start)))
+
+ logger.error('Timeout waiting for cloud-init to complete')
+ return False
+
+ def __cloud_init_complete(self):
+ """
+ Returns True when can create a SSH session else False
+ :return: T/F
+ """
+ if len(self.__floating_ip_dict) > 0:
+ ssh = self.ssh_client()
+ if ssh:
+ stdin1, stdout1, sterr1 = ssh.exec_command(
+ 'ls -l /var/lib/cloud/instance/boot-finished')
+ return stdout1.channel.recv_exit_status() == 0
+ return False
+
def get_floating_ip(self, fip_name=None):
"""
Returns the floating IP object byt name if found, else the first known,
diff --git a/snaps/openstack/tests/create_instance_tests.py b/snaps/openstack/tests/create_instance_tests.py
index 486018d..bee06ea 100644
--- a/snaps/openstack/tests/create_instance_tests.py
+++ b/snaps/openstack/tests/create_instance_tests.py
@@ -1601,224 +1601,6 @@ class CreateInstanceOnComputeHost(OSIntegrationTestCase):
index += 1
-class CreateInstancePubPrivNetTests(OSIntegrationTestCase):
- """
- Test for the CreateInstance class with two NIC/Ports, eth0 with floating IP
- and eth1 w/o.
- These tests require a Centos image
- """
-
- def setUp(self):
- """
- 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)
-
- # Initialize for tearDown()
- self.image_creator = None
- self.network_creators = list()
- self.router_creators = list()
- self.flavor_creator = None
- self.keypair_creator = None
- self.sec_grp_creator = None
- self.inst_creator = None
-
- self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.keypair_priv_filepath = 'tmp/' + self.guid
- self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
- self.keypair_name = self.guid + '-kp'
- self.vm_inst_name = self.guid + '-inst'
- self.port_1_name = self.guid + '-port-1'
- self.port_2_name = self.guid + '-port-2'
- self.floating_ip_name = self.guid + 'fip1'
- self.priv_net_config = openstack_tests.get_priv_net_config(
- net_name=self.guid + '-priv-net',
- subnet_name=self.guid + '-priv-subnet',
- router_name=self.guid + '-priv-router',
- external_net=self.ext_net_name)
- self.pub_net_config = openstack_tests.get_pub_net_config(
- net_name=self.guid + '-pub-net',
- subnet_name=self.guid + '-pub-subnet',
- router_name=self.guid + '-pub-router',
- external_net=self.ext_net_name)
-
- image_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
- os_image_settings = openstack_tests.centos_image_settings(
- name=image_name, image_metadata=self.image_metadata)
-
- try:
- # Create Image
- self.image_creator = OpenStackImage(self.os_creds,
- os_image_settings)
- self.image_creator.create()
-
- # First network is public
- self.network_creators.append(OpenStackNetwork(
- self.os_creds, self.pub_net_config.network_settings))
- # Second network is private
- self.network_creators.append(OpenStackNetwork(
- self.os_creds, self.priv_net_config.network_settings))
- for network_creator in self.network_creators:
- network_creator.create()
-
- self.router_creators.append(OpenStackRouter(
- self.os_creds, self.pub_net_config.router_settings))
- self.router_creators.append(OpenStackRouter(
- self.os_creds, self.priv_net_config.router_settings))
-
- # Create Routers
- for router_creator in self.router_creators:
- router_creator.create()
-
- # Create Flavor
- self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=self.guid + '-flavor-name', ram=512,
- disk=10, vcpus=2,
- metadata=self.flavor_metadata))
- self.flavor_creator.create()
-
- # Create Keypair
- self.keypair_creator = OpenStackKeypair(
- self.os_creds, KeypairConfig(
- name=self.keypair_name,
- public_filepath=self.keypair_pub_filepath,
- private_filepath=self.keypair_priv_filepath))
- self.keypair_creator.create()
-
- sec_grp_name = self.guid + '-sec-grp'
- rule1 = SecurityGroupRuleConfig(
- sec_grp_name=sec_grp_name, direction=Direction.ingress,
- protocol=Protocol.icmp)
- rule2 = SecurityGroupRuleConfig(
- sec_grp_name=sec_grp_name, direction=Direction.ingress,
- protocol=Protocol.tcp, port_range_min=22, port_range_max=22)
- self.sec_grp_creator = OpenStackSecurityGroup(
- self.os_creds,
- SecurityGroupConfig(
- name=sec_grp_name, rule_settings=[rule1, rule2]))
- self.sec_grp_creator.create()
- except:
- self.tearDown()
- raise
-
- def tearDown(self):
- """
- Cleans the created objects
- """
- if self.inst_creator:
- try:
- self.inst_creator.clean()
- except Exception as e:
- logger.error(
- 'Unexpected exception cleaning VM instance with message '
- '- %s', e)
-
- if self.keypair_creator:
- try:
- self.keypair_creator.clean()
- except Exception as e:
- logger.error(
- 'Unexpected exception cleaning keypair with message - %s',
- e)
-
- if self.flavor_creator:
- try:
- self.flavor_creator.clean()
- except Exception as e:
- logger.error(
- 'Unexpected exception cleaning flavor with message - %s',
- e)
-
- for router_creator in self.router_creators:
- try:
- router_creator.clean()
- except Exception as e:
- logger.error(
- 'Unexpected exception cleaning router with message - %s',
- e)
-
- for network_creator in self.network_creators:
- try:
- network_creator.clean()
- except Exception as e:
- logger.error(
- 'Unexpected exception cleaning network with message - %s',
- e)
-
- if self.sec_grp_creator:
- try:
- self.sec_grp_creator.clean()
- except Exception as e:
- logger.error(
- 'Unexpected exception cleaning security group with message'
- ' - %s', e)
-
- if self.image_creator and not self.image_creator.image_settings.exists:
- try:
- self.image_creator.clean()
- except Exception as e:
- logger.error(
- 'Unexpected exception cleaning image with message - %s', e)
-
- super(self.__class__, self).__clean__()
-
- def test_dual_ports_dhcp(self):
- """
- Tests the creation of an OpenStack instance with a dual ports/NICs with
- a DHCP assigned IP.
- NOTE: This test and any others that call ansible will most likely fail
- unless you do one of two things:
- 1. Have a ~/.ansible.cfg (or alternate means) to
- set host_key_checking = False
- 2. Set the following environment variable in your executing shell:
- ANSIBLE_HOST_KEY_CHECKING=False
- Should this not be performed, the creation of the host ssh key will
- cause your ansible calls to fail.
- """
- # Create ports/NICs for instance
- ports_settings = []
- ctr = 1
- for network_creator in self.network_creators:
- ports_settings.append(PortConfig(
- name=self.guid + '-port-' + str(ctr),
- network_name=network_creator.network_settings.name))
- ctr += 1
-
- # Create instance
- instance_settings = VmInstanceConfig(
- name=self.vm_inst_name,
- flavor=self.flavor_creator.flavor_settings.name,
- port_settings=ports_settings,
- security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
- floating_ip_settings=[FloatingIpConfig(
- name=self.floating_ip_name, port_name=self.port_1_name,
- router_name=self.pub_net_config.router_settings.name)])
-
- self.inst_creator = OpenStackVmInstance(
- self.os_creds, instance_settings,
- self.image_creator.image_settings,
- keypair_settings=self.keypair_creator.keypair_settings)
-
- vm_inst = self.inst_creator.create(block=True)
-
- self.assertEqual(vm_inst.id, self.inst_creator.get_vm_inst().id)
-
- # Effectively blocks until VM has been properly activated
- self.assertTrue(self.inst_creator.vm_active(block=True))
-
- ip = self.inst_creator.get_port_ip(ports_settings[0].name)
- self.assertTrue(check_dhcp_lease(self.inst_creator, ip))
-
- # Effectively blocks until VM's ssh port has been opened
- self.assertTrue(self.inst_creator.vm_ssh_active(block=True))
-
- self.assertEqual(0, self.inst_creator.config_nics())
-
-
class InstanceSecurityGroupTests(OSIntegrationTestCase):
"""
Tests that include, add, and remove security groups from VM instances
diff --git a/snaps/openstack/tests/openstack_tests.py b/snaps/openstack/tests/openstack_tests.py
index 4b00922..7e08fca 100644
--- a/snaps/openstack/tests/openstack_tests.py
+++ b/snaps/openstack/tests/openstack_tests.py
@@ -271,15 +271,12 @@ def centos_image_settings(name, url=None, image_metadata=None,
else:
metadata = image_metadata
- pb_path = pkg_resources.resource_filename(
- 'snaps.provisioning.ansible_pb.centos-network-setup.playbooks',
- 'configure_host.yml')
return create_image_settings(
image_name=name, image_user=CENTOS_USER,
image_format=DEFAULT_IMAGE_FORMAT, metadata=metadata, disk_url=url,
default_url=CENTOS_DEFAULT_IMAGE_URL,
kernel_settings=kernel_settings, ramdisk_settings=ramdisk_settings,
- public=public, nic_config_pb_loc=pb_path)
+ public=public)
def ubuntu_image_settings(name, url=None, image_metadata=None,
@@ -304,15 +301,12 @@ def ubuntu_image_settings(name, url=None, image_metadata=None,
else:
metadata = image_metadata
- pb_path = pkg_resources.resource_filename(
- 'snaps.provisioning.ansible_pb.ubuntu-network-setup.playbooks',
- 'configure_host.yml')
return create_image_settings(
image_name=name, image_user=UBUNTU_USER,
image_format=DEFAULT_IMAGE_FORMAT, metadata=metadata, disk_url=url,
default_url=UBUNTU_DEFAULT_IMAGE_URL,
kernel_settings=kernel_settings, ramdisk_settings=ramdisk_settings,
- public=public, nic_config_pb_loc=pb_path)
+ public=public)
def get_priv_net_config(net_name, subnet_name, router_name=None,
diff --git a/snaps/openstack/utils/launch_utils.py b/snaps/openstack/utils/launch_utils.py
new file mode 100644
index 0000000..abf04b5
--- /dev/null
+++ b/snaps/openstack/utils/launch_utils.py
@@ -0,0 +1,804 @@
+#
+# Copyright (c) 2016 Cable Television Laboratories, Inc. ("CableLabs")
+# and others. 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.
+#
+# This utility makes it easy to create OpenStack objects
+import logging
+import re
+import socket
+import struct
+
+import os
+from keystoneauth1.exceptions import Unauthorized
+
+from snaps.config.flavor import FlavorConfig
+from snaps.config.image import ImageConfig
+from snaps.config.keypair import KeypairConfig
+from snaps.config.network import PortConfig, NetworkConfig
+from snaps.config.project import ProjectConfig
+from snaps.config.qos import QoSConfig
+from snaps.config.router import RouterConfig
+from snaps.config.security_group import SecurityGroupConfig
+from snaps.config.user import UserConfig
+from snaps.config.vm_inst import VmInstanceConfig
+from snaps.config.volume import VolumeConfig
+from snaps.config.volume_type import VolumeTypeConfig
+from snaps.openstack.create_flavor import OpenStackFlavor
+from snaps.openstack.create_image import OpenStackImage
+from snaps.openstack.create_keypairs import OpenStackKeypair
+from snaps.openstack.create_network import OpenStackNetwork
+from snaps.openstack.create_project import OpenStackProject
+from snaps.openstack.create_qos import OpenStackQoS
+from snaps.openstack.create_router import OpenStackRouter
+from snaps.openstack.create_security_group import OpenStackSecurityGroup
+from snaps.openstack.create_user import OpenStackUser
+from snaps.openstack.create_volume import OpenStackVolume
+from snaps.openstack.create_volume_type import OpenStackVolumeType
+from snaps.openstack.os_credentials import OSCreds, ProxySettings
+from snaps.openstack.utils import deploy_utils, neutron_utils
+from snaps.provisioning import ansible_utils
+
+logger = logging.getLogger('lanuch_utils')
+DEFAULT_CREDS_KEY = 'admin'
+
+
+def launch_config(config, tmplt_file, deploy, clean, clean_image):
+ """
+ Launches all objects and applies any configured ansible playbooks
+ :param config: the environment configuration dict object
+ :param tmplt_file: the path to the SNAPS-OO template file
+ :param deploy: when True deploy
+ :param clean: when True clean
+ :param clean_image: when True clean the image when clean is True
+ """
+ os_config = config.get('openstack')
+
+ creators = list()
+ vm_dict = dict()
+ images_dict = dict()
+ flavors_dict = dict()
+ networks_dict = dict()
+ routers_dict = dict()
+ os_creds_dict = dict()
+
+ if os_config:
+ os_creds_dict = __get_creds_dict(os_config)
+
+ # Create projects
+ projects_dict = __create_instances(
+ os_creds_dict, OpenStackProject, ProjectConfig,
+ os_config.get('projects'), 'project', clean)
+ creators.append(projects_dict)
+
+ # Create users
+ users_dict = __create_instances(
+ os_creds_dict, OpenStackUser, UserConfig,
+ os_config.get('users'), 'user', clean)
+ creators.append(users_dict)
+
+ # Associate new users to projects
+ if not clean:
+ for project_creator in projects_dict.values():
+ users = project_creator.project_settings.users
+ for user_name in users:
+ user_creator = users_dict.get(user_name)
+ if user_creator:
+ project_creator.assoc_user(
+ user_creator.get_user())
+
+ # Create flavors
+ flavors_dict = __create_instances(
+ os_creds_dict, OpenStackFlavor, FlavorConfig,
+ os_config.get('flavors'), 'flavor', clean, users_dict)
+ creators.append(flavors_dict)
+
+ # Create QoS specs
+ qos_dict = __create_instances(
+ os_creds_dict, OpenStackQoS, QoSConfig,
+ os_config.get('qos_specs'), 'qos_spec', clean, users_dict)
+ creators.append(qos_dict)
+
+ # Create volume types
+ vol_type_dict = __create_instances(
+ os_creds_dict, OpenStackVolumeType, VolumeTypeConfig,
+ os_config.get('volume_types'), 'volume_type', clean,
+ users_dict)
+ creators.append(vol_type_dict)
+
+ # Create volume types
+ vol_dict = __create_instances(
+ os_creds_dict, OpenStackVolume, VolumeConfig,
+ os_config.get('volumes'), 'volume', clean, users_dict)
+ creators.append(vol_dict)
+
+ # Create images
+ images_dict = __create_instances(
+ os_creds_dict, OpenStackImage, ImageConfig,
+ os_config.get('images'), 'image', clean, users_dict)
+ creators.append(images_dict)
+
+ # Create networks
+ networks_dict = __create_instances(
+ os_creds_dict, OpenStackNetwork, NetworkConfig,
+ os_config.get('networks'), 'network', clean, users_dict)
+ creators.append(networks_dict)
+
+ # Create routers
+ routers_dict = __create_instances(
+ os_creds_dict, OpenStackRouter, RouterConfig,
+ os_config.get('routers'), 'router', clean, users_dict)
+ creators.append(routers_dict)
+
+ # Create keypairs
+ keypairs_dict = __create_instances(
+ os_creds_dict, OpenStackKeypair, KeypairConfig,
+ os_config.get('keypairs'), 'keypair', clean, users_dict)
+ creators.append(keypairs_dict)
+
+ # Create security groups
+ creators.append(__create_instances(
+ os_creds_dict, OpenStackSecurityGroup,
+ SecurityGroupConfig,
+ os_config.get('security_groups'), 'security_group', clean,
+ users_dict))
+
+ # Create instance
+ vm_dict = __create_vm_instances(
+ os_creds_dict, users_dict, os_config.get('instances'),
+ images_dict, keypairs_dict, clean)
+ creators.append(vm_dict)
+ logger.info(
+ 'Completed creating/retrieving all configured instances')
+
+ # Must enter either block
+ if clean:
+ # Cleanup Environment
+ __cleanup(creators, clean_image)
+ elif deploy:
+ # Provision VMs
+ ansible_config = config.get('ansible')
+ if ansible_config and vm_dict:
+ if not __apply_ansible_playbooks(
+ ansible_config, os_creds_dict, vm_dict, images_dict,
+ flavors_dict, networks_dict, routers_dict, tmplt_file):
+ logger.error("Problem applying ansible playbooks")
+
+
+def __get_creds_dict(os_conn_config):
+ """
+ Returns a dict of OSCreds where the key is the creds name.
+ For backwards compatibility, credentials not contained in a list (only
+ one) will be returned with the key of None
+ :param os_conn_config: the credential configuration
+ :return: a dict of OSCreds objects
+ """
+ if 'connection' in os_conn_config:
+ return {DEFAULT_CREDS_KEY: __get_os_credentials(os_conn_config)}
+ elif 'connections' in os_conn_config:
+ out = dict()
+ for os_conn_dict in os_conn_config['connections']:
+ config = os_conn_dict.get('connection')
+ if not config:
+ raise Exception('Invalid connection format')
+
+ name = config.get('name')
+ if not name:
+ raise Exception('Connection config requires a name field')
+
+ out[name] = __get_os_credentials(os_conn_dict)
+ return out
+
+
+def __get_creds(os_creds_dict, os_user_dict, inst_config):
+ """
+ Returns the appropriate credentials
+ :param os_creds_dict: a dictionary of OSCreds objects where the name is the
+ key
+ :param os_user_dict: a dictionary of OpenStackUser objects where the name
+ is the key
+ :param inst_config:
+ :return: an OSCreds instance or None
+ """
+ os_creds = os_creds_dict.get(DEFAULT_CREDS_KEY)
+ if 'os_user' in inst_config:
+ os_user_conf = inst_config['os_user']
+ if 'name' in os_user_conf:
+ user_creator = os_user_dict.get(os_user_conf['name'])
+ if user_creator:
+ return user_creator.get_os_creds(
+ project_name=os_user_conf.get('project_name'))
+ elif 'os_creds_name' in inst_config:
+ if 'os_creds_name' in inst_config:
+ os_creds = os_creds_dict[inst_config['os_creds_name']]
+ return os_creds
+
+
+def __get_os_credentials(os_conn_config):
+ """
+ Returns an object containing all of the information required to access
+ OpenStack APIs
+ :param os_conn_config: The configuration holding the credentials
+ :return: an OSCreds instance
+ """
+ config = os_conn_config.get('connection')
+ if not config:
+ raise Exception('Invalid connection configuration')
+
+ proxy_settings = None
+ http_proxy = config.get('http_proxy')
+ if http_proxy:
+ tokens = re.split(':', http_proxy)
+ ssh_proxy_cmd = config.get('ssh_proxy_cmd')
+ proxy_settings = ProxySettings(host=tokens[0], port=tokens[1],
+ ssh_proxy_cmd=ssh_proxy_cmd)
+ else:
+ if 'proxy_settings' in config:
+ host = config['proxy_settings'].get('host')
+ port = config['proxy_settings'].get('port')
+ if host and host != 'None' and port and port != 'None':
+ proxy_settings = ProxySettings(**config['proxy_settings'])
+
+ if proxy_settings:
+ config['proxy_settings'] = proxy_settings
+ else:
+ if config.get('proxy_settings'):
+ del config['proxy_settings']
+
+ return OSCreds(**config)
+
+
+def __parse_ports_config(config):
+ """
+ Parses the "ports" configuration
+ :param config: The dictionary to parse
+ :return: a list of PortConfig objects
+ """
+ out = list()
+ for port_config in config:
+ out.append(PortConfig(**port_config.get('port')))
+ return out
+
+
+def __create_instances(os_creds_dict, creator_class, config_class, config,
+ config_key, cleanup=False, os_users_dict=None):
+ """
+ Returns a dictionary of SNAPS creator objects where the key is the name
+ :param os_creds_dict: Dictionary of OSCreds objects where the key is the
+ name
+ :param config: The list of configurations for the same type
+ :param config_key: The list of configurations for the same type
+ :param cleanup: Denotes whether or not this is being called for cleanup
+ :return: dictionary
+ """
+ out = {}
+
+ if config:
+ for config_dict in config:
+ inst_config = config_dict.get(config_key)
+ if inst_config:
+ creds = __get_creds(os_creds_dict, os_users_dict, inst_config)
+ if creds:
+ creator = creator_class(
+ creds,
+ config_class(**inst_config))
+
+ if creator:
+ if cleanup:
+ try:
+ creator.initialize()
+ except Unauthorized as e:
+ logger.warn(
+ 'Unable to initialize creator [%s] - %s',
+ creator, e)
+ else:
+ creator.create()
+
+ out[inst_config['name']] = creator
+
+ logger.info('Initialized configured %ss', config_key)
+
+ return out
+
+
+def __create_vm_instances(os_creds_dict, os_users_dict, instances_config,
+ image_dict, keypairs_dict, cleanup=False):
+ """
+ Returns a dictionary of OpenStackVmInstance objects where the key is the
+ instance name
+ :param os_creds_dict: Dictionary of OSCreds objects where the key is the
+ name
+ :param os_users_dict: Dictionary of OpenStackUser objects where the key is
+ the username
+ :param instances_config: The list of VM instance configurations
+ :param image_dict: A dictionary of images that will probably be used to
+ instantiate the VM instance
+ :param keypairs_dict: A dictionary of keypairs that will probably be used
+ to instantiate the VM instance
+ :param cleanup: Denotes whether or not this is being called for cleanup
+ :return: dictionary
+ """
+ vm_dict = {}
+
+ if instances_config:
+ for instance_config in instances_config:
+ conf = instance_config.get('instance')
+ if conf:
+ if image_dict:
+ image_creator = image_dict.get(conf.get('imageName'))
+ if image_creator:
+ instance_settings = VmInstanceConfig(
+ **instance_config['instance'])
+ kp_creator = keypairs_dict.get(
+ conf.get('keypair_name'))
+
+ try:
+ vm_dict[conf[
+ 'name']] = deploy_utils.create_vm_instance(
+ __get_creds(
+ os_creds_dict, os_users_dict, conf),
+ instance_settings,
+ image_creator.image_settings,
+ keypair_creator=kp_creator,
+ init_only=cleanup)
+ except Unauthorized as e:
+ if not cleanup:
+ logger.warn('Unable to initialize VM - %s', e)
+ raise
+ else:
+ raise Exception('Image creator instance not found.'
+ ' Cannot instantiate')
+ else:
+ if not cleanup:
+ raise Exception('Image dictionary is None. Cannot '
+ 'instantiate')
+ else:
+ raise Exception('Instance configuration is None. Cannot '
+ 'instantiate')
+ logger.info('Created configured instances')
+
+ return vm_dict
+
+
+def __apply_ansible_playbooks(ansible_configs, os_creds_dict, vm_dict,
+ image_dict, flavor_dict, networks_dict,
+ routers_dict, tmplt_file):
+ """
+ Applies ansible playbooks to running VMs with floating IPs
+ :param ansible_configs: a list of Ansible configurations
+ :param os_creds_dict: Dictionary of OSCreds objects where the key is the
+ name
+ :param vm_dict: the dictionary of newly instantiated VMs where the name is
+ the key
+ :param image_dict: the dictionary of newly instantiated images where the
+ name is the key
+ :param flavor_dict: the dictionary of newly instantiated flavors where the
+ name is the key
+ :param networks_dict: the dictionary of newly instantiated networks where
+ the name is the key
+ :param routers_dict: the dictionary of newly instantiated routers where
+ the name is the key
+ :param tmplt_file: the path of the SNAPS-OO template file for setting the
+ CWD so playbook location is relative to the deployment
+ file
+ :return: t/f - true if successful
+ """
+ logger.info("Applying Ansible Playbooks")
+ if ansible_configs:
+ # Set CWD so the deployment file's playbook location can leverage
+ # relative paths
+ orig_cwd = os.getcwd()
+ env_dir = os.path.dirname(tmplt_file)
+ os.chdir(env_dir)
+
+ # Apply playbooks
+ for ansible_config in ansible_configs:
+ # Ensure all hosts are accepting SSH session requests
+ for vm_name in ansible_config['hosts']:
+ vm_inst = vm_dict.get(vm_name)
+ if vm_inst:
+ if not vm_inst.vm_ssh_active(block=True):
+ logger.warning(
+ 'Timeout waiting for instance to respond to '
+ 'SSH requests')
+ return False
+
+ os_creds = os_creds_dict.get('admin-creds')
+ __apply_ansible_playbook(
+ ansible_config, os_creds, vm_dict, image_dict, flavor_dict,
+ networks_dict, routers_dict)
+
+ # Return to original directory
+ os.chdir(orig_cwd)
+
+ return True
+
+
+def __apply_ansible_playbook(ansible_config, os_creds, vm_dict, image_dict,
+ flavor_dict, networks_dict, routers_dict):
+ """
+ Applies an Ansible configuration setting
+ :param ansible_config: the configuration settings
+ :param os_creds: the OpenStack admin credentials object
+ :param vm_dict: the dictionary of newly instantiated VMs where the name is
+ the key
+ :param image_dict: the dictionary of newly instantiated images where the
+ name is the key
+ :param flavor_dict: the dictionary of newly instantiated flavors where the
+ name is the key
+ :param networks_dict: the dictionary of newly instantiated networks where
+ the name is the key
+ :param routers_dict: the dictionary of newly instantiated routers where
+ the name is the key
+ """
+ if ansible_config:
+ (remote_user, floating_ips, private_key_filepath,
+ proxy_settings) = __get_connection_info(
+ ansible_config, vm_dict)
+ if floating_ips:
+ for key, vm_creator in vm_dict.items():
+ fip = vm_creator.get_floating_ip()
+ if fip and fip.ip in floating_ips:
+ if not vm_creator.cloud_init_complete(block=True):
+ raise Exception(
+ 'Cannot apply playbooks as cloud-init has not '
+ 'completed')
+
+ variables = __get_variables(
+ ansible_config.get('variables'), os_creds, vm_dict, image_dict,
+ flavor_dict, networks_dict, routers_dict)
+
+ retval = ansible_utils.apply_playbook(
+ ansible_config['playbook_location'], floating_ips, remote_user,
+ private_key_filepath,
+ variables=variables,
+ proxy_setting=proxy_settings)
+ if retval != 0:
+ # Not a fatal type of event
+ logger.warning(
+ 'Unable to apply playbook found at location - %s',
+ ansible_config.get('playbook_location'))
+ return retval
+
+
+def __get_connection_info(ansible_config, vm_dict):
+ """
+ Returns a tuple of data required for connecting to the running VMs
+ (remote_user, [floating_ips], private_key_filepath, proxy_settings)
+ :param ansible_config: the configuration settings
+ :param vm_dict: the dictionary of VMs where the VM name is the key
+ :return: tuple where the first element is the user and the second is a list
+ of floating IPs and the third is the
+ private key file location and the fourth is an instance of the
+ snaps.ProxySettings class
+ (note: in order to work, each of the hosts need to have the same sudo_user
+ and private key file location values)
+ """
+ if ansible_config.get('hosts'):
+ hosts = ansible_config['hosts']
+ if len(hosts) > 0:
+ floating_ips = list()
+ remote_user = None
+ pk_file = None
+ proxy_settings = None
+ for host in hosts:
+ vm = vm_dict.get(host)
+ if vm:
+ fip = vm.get_floating_ip()
+ if fip:
+ remote_user = vm.get_image_user()
+
+ if fip:
+ floating_ips.append(fip.ip)
+ else:
+ raise Exception(
+ 'Could not find floating IP for VM - ' +
+ vm.name)
+
+ pk_file = vm.keypair_settings.private_filepath
+ proxy_settings = vm.get_os_creds().proxy_settings
+ else:
+ logger.error('Could not locate VM with name - ' + host)
+
+ return remote_user, floating_ips, pk_file, proxy_settings
+ return None
+
+
+def __get_variables(var_config, os_creds, vm_dict, image_dict, flavor_dict,
+ networks_dict, routers_dict):
+ """
+ Returns a dictionary of substitution variables to be used for Ansible
+ templates
+ :param var_config: the variable configuration settings
+ :param os_creds: the OpenStack admin credentials object
+ :param vm_dict: the dictionary of newly instantiated VMs where the name is
+ the key
+ :param image_dict: the dictionary of newly instantiated images where the
+ name is the key
+ :param flavor_dict: the dictionary of newly instantiated flavors where the
+ name is the key
+ :param networks_dict: the dictionary of newly instantiated networks where
+ the name is the key
+ :param routers_dict: the dictionary of newly instantiated routers where
+ the name is the key
+ :return: dictionary or None
+ """
+ if var_config and vm_dict and len(vm_dict) > 0:
+ variables = dict()
+ for key, value in var_config.items():
+ value = __get_variable_value(
+ value, os_creds, vm_dict, image_dict, flavor_dict,
+ networks_dict, routers_dict)
+ if key and value:
+ variables[key] = value
+ logger.info(
+ "Set Jinga2 variable with key [%s] the value [%s]",
+ key, value)
+ else:
+ raise Exception(
+ 'Key - [' + str(key) + '] or Value [' + str(value)
+ + '] must not be None')
+ return variables
+ return None
+
+
+def __get_variable_value(var_config_values, os_creds, vm_dict, image_dict,
+ flavor_dict, networks_dict, routers_dict):
+ """
+ Returns the associated variable value for use by Ansible for substitution
+ purposes
+ :param var_config_values: the configuration dictionary
+ :param os_creds: the OpenStack admin credentials object
+ :param vm_dict: the dictionary of newly instantiated VMs where the name is
+ the key
+ :param image_dict: the dictionary of newly instantiated images where the
+ name is the key
+ :param flavor_dict: the dictionary of newly instantiated flavors where the
+ name is the key
+ :param networks_dict: the dictionary of newly instantiated networks where
+ the name is the key
+ :param routers_dict: the dictionary of newly instantiated routers where
+ the name is the key
+ :return:
+ """
+ if var_config_values['type'] == 'string':
+ return __get_string_variable_value(var_config_values)
+ if var_config_values['type'] == 'vm-attr':
+ return __get_vm_attr_variable_value(var_config_values, vm_dict)
+ if var_config_values['type'] == 'os_creds':
+ return __get_os_creds_variable_value(var_config_values, os_creds)
+ if var_config_values['type'] == 'network':
+ return __get_network_variable_value(var_config_values, networks_dict)
+ if var_config_values['type'] == 'router':
+ return __get_router_variable_value(var_config_values, routers_dict,
+ os_creds)
+ if var_config_values['type'] == 'port':
+ return __get_vm_port_variable_value(var_config_values, vm_dict)
+ if var_config_values['type'] == 'floating_ip':
+ return __get_vm_fip_variable_value(var_config_values, vm_dict)
+ if var_config_values['type'] == 'image':
+ return __get_image_variable_value(var_config_values, image_dict)
+ if var_config_values['type'] == 'flavor':
+ return __get_flavor_variable_value(var_config_values, flavor_dict)
+ return None
+
+
+def __get_string_variable_value(var_config_values):
+ """
+ Returns the associated string value
+ :param var_config_values: the configuration dictionary
+ :return: the value contained in the dictionary with the key 'value'
+ """
+ return var_config_values['value']
+
+
+def __get_vm_attr_variable_value(var_config_values, vm_dict):
+ """
+ Returns the associated value contained on a VM instance
+ :param var_config_values: the configuration dictionary
+ :param vm_dict: the dictionary containing all VMs where the key is the VM's
+ name
+ :return: the value
+ """
+ vm = vm_dict.get(var_config_values['vm_name'])
+ if vm:
+ if var_config_values['value'] == 'floating_ip':
+ return vm.get_floating_ip().ip
+ if var_config_values['value'] == 'image_user':
+ return vm.get_image_user()
+
+
+def __get_os_creds_variable_value(var_config_values, os_creds):
+ """
+ Returns the associated OS credentials value
+ :param var_config_values: the configuration dictionary
+ :param os_creds: the admin OpenStack OSCreds object
+ :return: the value
+ """
+ if os_creds:
+ if var_config_values['value'] == 'username':
+ logger.info("Returning OS username")
+ return os_creds.username
+ elif var_config_values['value'] == 'password':
+ logger.info("Returning OS password")
+ return os_creds.password
+ elif var_config_values['value'] == 'auth_url':
+ logger.info("Returning OS auth_url")
+ return os_creds.auth_url
+ elif var_config_values['value'] == 'project_name':
+ logger.info("Returning OS project_name")
+ return os_creds.project_name
+
+
+def __get_network_variable_value(var_config_values, networks_dict):
+ """
+ Returns the associated network value
+ :param var_config_values: the configuration dictionary
+ :param networks_dict: the dictionary containing all networks where the key
+ is the network name
+ :return: the value
+ """
+ net_name = var_config_values.get('network_name')
+
+ if net_name and networks_dict.get(net_name):
+ network_creator = networks_dict[net_name]
+
+ if 'subnet_name' in var_config_values:
+ subnet_name = var_config_values.get('subnet_name')
+ if subnet_name:
+ for subnet in network_creator.get_network().subnets:
+ if subnet_name == subnet.name:
+ if 'value' in var_config_values:
+ if 'gateway_ip' == var_config_values['value']:
+ return subnet.gateway_ip
+ if 'ip_range' == var_config_values['value']:
+ return subnet.start + ' ' + subnet.end
+ if 'cidr_ip' == var_config_values['value']:
+ cidr_split = subnet.cidr.split('/')
+ return cidr_split[0]
+ if 'netmask' == var_config_values['value']:
+ cidr_split = subnet.cidr.split('/')
+ cidr_bits = 32 - int(cidr_split[1])
+ netmask = socket.inet_ntoa(
+ struct.pack(
+ '!I', (1 << 32) - (1 << cidr_bits)))
+ return netmask
+ if 'broadcast_ip' == var_config_values['value']:
+ end_split = subnet.end.split('.')
+ broadcast_ip = (
+ end_split[0] + '.' + end_split[1] + '.'
+ + end_split[2] + '.255')
+ return broadcast_ip
+
+
+def __get_router_variable_value(var_config_values, routers_dict, os_creds):
+ """
+ Returns the associated network value
+ :param var_config_values: the configuration dictionary
+ :param routers_dict: the dictionary containing all networks where the key
+ is the network name
+ :param os_creds: the admin OpenStack credentials
+ :return: the value
+ """
+ router_name = var_config_values.get('router_name')
+ router_creator = routers_dict[router_name]
+
+ if router_creator:
+ if 'external_fixed_ip' == var_config_values.get('attr'):
+ neutron = neutron_utils.neutron_client(os_creds)
+ ext_nets = neutron_utils.get_external_networks(neutron)
+
+ subnet_name = var_config_values.get('subnet_name')
+
+ for ext_net in ext_nets:
+ for subnet in ext_net.subnets:
+ if subnet_name == subnet.name:
+ router = router_creator.get_router()
+ for fixed_ips in router.external_fixed_ips:
+ if subnet.id == fixed_ips['subnet_id']:
+ return fixed_ips['ip_address']
+
+
+def __get_vm_port_variable_value(var_config_values, vm_dict):
+ """
+ Returns the associated OS credentials value
+ :param var_config_values: the configuration dictionary
+ :param vm_dict: the dictionary containing all VMs where the key is the VM's
+ name
+ :return: the value
+ """
+ port_name = var_config_values.get('port_name')
+ vm_name = var_config_values.get('vm_name')
+
+ if port_name and vm_name:
+ vm = vm_dict.get(vm_name)
+ if vm:
+ for vm_port in vm.get_vm_inst().ports:
+ if vm_port.name == port_name:
+ port_value_id = var_config_values.get('port_value')
+ if port_value_id:
+ if port_value_id == 'mac_address':
+ return vm_port.mac_address
+ if port_value_id == 'ip_address':
+ return vm_port.ips[0]['ip_address']
+
+
+def __get_vm_fip_variable_value(var_config_values, vm_dict):
+ """
+ Returns the floating IP value if found
+ :param var_config_values: the configuration dictionary
+ :param vm_dict: the dictionary containing all VMs where the key is the VM's
+ name
+ :return: the floating IP string value or None
+ """
+ fip_name = var_config_values.get('fip_name')
+ vm_name = var_config_values.get('vm_name')
+
+ if vm_name:
+ vm = vm_dict.get(vm_name)
+ if vm:
+ fip = vm.get_floating_ip(fip_name)
+ if fip:
+ return fip.ip
+
+
+def __get_image_variable_value(var_config_values, image_dict):
+ """
+ Returns the associated image value
+ :param var_config_values: the configuration dictionary
+ :param image_dict: the dictionary containing all images where the key is
+ the name
+ :return: the value
+ """
+ if image_dict:
+ if var_config_values.get('image_name'):
+ image_creator = image_dict.get(var_config_values['image_name'])
+ if image_creator:
+ if (var_config_values.get('value')
+ and var_config_values['value'] == 'id'):
+ return image_creator.get_image().id
+ if (var_config_values.get('value')
+ and var_config_values['value'] == 'user'):
+ return image_creator.image_settings.image_user
+
+
+def __get_flavor_variable_value(var_config_values, flavor_dict):
+ """
+ Returns the associated flavor value
+ :param var_config_values: the configuration dictionary
+ :param flavor_dict: the dictionary containing all flavor creators where the
+ key is the name
+ :return: the value or None
+ """
+ if flavor_dict:
+ if var_config_values.get('flavor_name'):
+ flavor_creator = flavor_dict.get(var_config_values['flavor_name'])
+ if flavor_creator:
+ if (var_config_values.get('value')
+ and var_config_values['value'] == 'id'):
+ return flavor_creator.get_flavor().id
+
+
+def __cleanup(creators, clean_image=False):
+ """
+ Cleans up environment
+ :param creators: the list of creators by type
+ :param clean_image: when true
+ :return:
+ """
+ for creator_dict in reversed(creators):
+ for key, creator in creator_dict.items():
+ if ((isinstance(creator, OpenStackImage) and clean_image)
+ or not isinstance(creator, OpenStackImage)):
+ creator.clean()
diff --git a/snaps/provisioning/ansible_pb/__init__.py b/snaps/provisioning/ansible_pb/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/snaps/provisioning/ansible_pb/__init__.py
+++ /dev/null
diff --git a/snaps/provisioning/ansible_pb/centos-network-setup/__init__.py b/snaps/provisioning/ansible_pb/centos-network-setup/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/snaps/provisioning/ansible_pb/centos-network-setup/__init__.py
+++ /dev/null
diff --git a/snaps/provisioning/ansible_pb/centos-network-setup/playbooks/__init__.py b/snaps/provisioning/ansible_pb/centos-network-setup/playbooks/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/snaps/provisioning/ansible_pb/centos-network-setup/playbooks/__init__.py
+++ /dev/null
diff --git a/snaps/provisioning/ansible_pb/centos-network-setup/playbooks/configure_host.yml b/snaps/provisioning/ansible_pb/centos-network-setup/playbooks/configure_host.yml
deleted file mode 100644
index 8df03cb..0000000
--- a/snaps/provisioning/ansible_pb/centos-network-setup/playbooks/configure_host.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2016 Cable Television Laboratories, Inc. ("CableLabs")
-# and others. 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.
----
-- name: Configure NIC
- hosts: all
- become: yes
- become_method: sudo
- become_user: root
-
- tasks:
- - name: Setup /etc/sysconfig/network-scripts/ifcfg-eth1 file
- action: template owner=root group=root mode=644 src=../templates/ifcfg-interface dest=/etc/sysconfig/network-scripts/ifcfg-{{nic_name}}
- - name : Restart Network
- command: systemctl restart network \ No newline at end of file
diff --git a/snaps/provisioning/ansible_pb/centos-network-setup/templates/ifcfg-interface b/snaps/provisioning/ansible_pb/centos-network-setup/templates/ifcfg-interface
deleted file mode 100644
index 47aa3fa..0000000
--- a/snaps/provisioning/ansible_pb/centos-network-setup/templates/ifcfg-interface
+++ /dev/null
@@ -1,14 +0,0 @@
-DEVICE={{ nic_name }}
-NAME={{ nic_name }}
-IPADDR={{ nic_ip }}
-
-DEFROUTE=no
-NETMASK=255.255.255.0
-NM_CONTROLLED=no
-IPV6INIT=yes
-IPV6_AUTOCONF=yes
-IPV6_DEFROUTE=yes
-IPV6_PEERDNS=yes
-IPV6_PEERROUTES=yes
-IPV6_FAILURE_FATAL=no
-ONBOOT=yes \ No newline at end of file
diff --git a/snaps/provisioning/ansible_pb/ubuntu-network-setup/__init__.py b/snaps/provisioning/ansible_pb/ubuntu-network-setup/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/snaps/provisioning/ansible_pb/ubuntu-network-setup/__init__.py
+++ /dev/null
diff --git a/snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/__init__.py b/snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/__init__.py
+++ /dev/null
diff --git a/snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/configure_host.yml b/snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/configure_host.yml
deleted file mode 100644
index 5d43f96..0000000
--- a/snaps/provisioning/ansible_pb/ubuntu-network-setup/playbooks/configure_host.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2016 Cable Television Laboratories, Inc. ("CableLabs")
-# and others. 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.
----
-- name: Configure NIC
- hosts: all
- become: yes
- become_method: sudo
- become_user: root
-
- tasks:
- - name: Setup /etc/network/interfaces.d/{{nic_name}}.cfg file
- action: template owner=root group=root mode=644 src=../templates/ethN.cfg dest=/etc/network/interfaces.d/{{nic_name}}.cfg
- - name : Restart Network
- command: service networking restart \ No newline at end of file
diff --git a/snaps/provisioning/ansible_pb/ubuntu-network-setup/templates/ethN.cfg b/snaps/provisioning/ansible_pb/ubuntu-network-setup/templates/ethN.cfg
deleted file mode 100644
index 3fa7708..0000000
--- a/snaps/provisioning/ansible_pb/ubuntu-network-setup/templates/ethN.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-auto {{ nic_name }}
-iface {{ nic_name }} inet dhcp
diff --git a/snaps/provisioning/tests/ansible_utils_tests.py b/snaps/provisioning/tests/ansible_utils_tests.py
index 4f1f65e..7600002 100644
--- a/snaps/provisioning/tests/ansible_utils_tests.py
+++ b/snaps/provisioning/tests/ansible_utils_tests.py
@@ -241,6 +241,9 @@ class AnsibleProvisioningTests(OSIntegrationTestCase):
# Block until VM's ssh port has been opened
self.assertTrue(self.inst_creator.vm_ssh_active(block=True))
+ # Block until cloud-init has completed
+ self.assertTrue(self.inst_creator.cloud_init_complete(block=True))
+
ssh_client = self.inst_creator.ssh_client()
self.assertIsNotNone(ssh_client)
@@ -310,6 +313,9 @@ class AnsibleProvisioningTests(OSIntegrationTestCase):
# Block until VM's ssh port has been opened
self.assertTrue(self.inst_creator.vm_ssh_active(block=True))
+ # Block until cloud-init has completed
+ self.assertTrue(self.inst_creator.cloud_init_complete(block=True))
+
# Apply Security Group
self.inst_creator.add_security_group(
self.sec_grp_creator.get_security_group())
diff --git a/snaps/test_suite_builder.py b/snaps/test_suite_builder.py
index ec8196d..1990cd6 100644
--- a/snaps/test_suite_builder.py
+++ b/snaps/test_suite_builder.py
@@ -65,13 +65,13 @@ from snaps.openstack.tests.create_image_tests import (
CreateImageSuccessTests, CreateImageNegativeTests,
CreateMultiPartImageTests)
from snaps.openstack.tests.create_instance_tests import (
- CreateInstanceSingleNetworkTests, CreateInstancePubPrivNetTests,
- CreateInstanceOnComputeHost, CreateInstanceSimpleTests,
- FloatingIpSettingsUnitTests, InstanceSecurityGroupTests,
- VmInstanceSettingsUnitTests, CreateInstancePortManipulationTests,
- SimpleHealthCheck, CreateInstanceFromThreePartImage,
- CreateInstanceMockOfflineTests, CreateInstanceTwoNetTests,
- CreateInstanceVolumeTests, CreateInstanceIPv6NetworkTests)
+ CreateInstanceSingleNetworkTests, CreateInstanceOnComputeHost,
+ CreateInstanceSimpleTests, FloatingIpSettingsUnitTests,
+ InstanceSecurityGroupTests, VmInstanceSettingsUnitTests,
+ CreateInstancePortManipulationTests, SimpleHealthCheck,
+ CreateInstanceFromThreePartImage, CreateInstanceMockOfflineTests,
+ CreateInstanceTwoNetTests, CreateInstanceVolumeTests,
+ CreateInstanceIPv6NetworkTests)
from snaps.openstack.tests.create_keypairs_tests import (
CreateKeypairsTests, KeypairSettingsUnitTests, CreateKeypairsCleanupTests)
from snaps.openstack.tests.create_network_tests import (
@@ -638,11 +638,6 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstancePubPrivNetTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
AnsibleProvisioningTests, os_creds=os_creds,
ext_net_name=ext_net_name, use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,