Merge pull request #67 from gnuoy/more-docstring-tidy

More docstring tidy
This commit is contained in:
David Ames
2018-06-13 15:17:38 -07:00
committed by GitHub
18 changed files with 164 additions and 170 deletions

View File

@@ -0,0 +1 @@
"""Modules for running lifecycle phases."""

View File

@@ -0,0 +1 @@
"""Run collect phase."""

View File

@@ -1,3 +1,4 @@
"""Run configuration phase."""
import asyncio
import argparse
import logging
@@ -7,8 +8,10 @@ import zaza.charm_lifecycle.utils as utils
def run_configure_list(functions):
"""Run the configure scripts as defined in the list of test classes in
series.
"""Run the configure scripts.
Run the configure scripts as defined in the list of test classes in
series.
:param functions: List of configure functions functions
:type tests: ['zaza.charms_tests.svc.setup', ...]
@@ -18,16 +21,17 @@ def run_configure_list(functions):
def configure(model_name, functions):
"""Run all post-deployment configuration steps
"""Run all post-deployment configuration steps.
:param functions: List of configure functions functions
:type tests: ['zaza.charms_tests.svc.setup', ...]"""
:type tests: ['zaza.charms_tests.svc.setup', ...]
"""
utils.set_juju_model(model_name)
run_configure_list(functions)
def parse_args(args):
"""Parse command line arguments
"""Parse command line arguments.
:param args: List of configure functions functions
:type list: [str1, str2,...] List of command line arguments
@@ -44,9 +48,12 @@ def parse_args(args):
def main():
"""Run the configuration defined by the command line args or if none were
provided read the configuration functions from the charms tests.yaml
config file"""
"""Run the configuration defined by the command line args.
Run the configuration defined by the command line args or if none were
provided read the configuration functions from the charms tests.yaml
config file
"""
logging.basicConfig(level=logging.INFO)
args = parse_args(sys.argv[1:])
funcs = args.configfuncs or utils.get_charm_config()['configure']

View File

@@ -1,3 +1,4 @@
"""Run deploy phase."""
import argparse
import jinja2
import logging
@@ -26,7 +27,7 @@ applications:
def is_valid_env_key(key):
"""Check if key is a valid environment variable name for use with template
"""Check if key is a valid environment variable name for use with template.
:param key: List of configure functions functions
:type key: str
@@ -42,8 +43,7 @@ def is_valid_env_key(key):
def get_template_context_from_env():
"""Return environment variables from the current environment that can be
used for template rendering.
"""Return environment vars from the current env for template rendering.
:returns: Environment variable key values for use with template rendering
:rtype: dict
@@ -52,7 +52,7 @@ def get_template_context_from_env():
def get_charm_config_context():
"""Return settings from charm config file
"""Return settings from charm config file.
:returns: Context for template rendering
:rtype: dict
@@ -65,7 +65,7 @@ def get_charm_config_context():
def get_template_overlay_context():
"""Combine contexts which can be used for overlay template rendering
"""Combine contexts which can be used for overlay template rendering.
:returns: Context for template rendering
:rtype: dict
@@ -101,8 +101,10 @@ def get_jinja2_env():
def get_template_name(target_file):
"""Return the expected name of the template used to generate the
target_file
"""Return the template name for target_file.
Return the expected name of the template used to generate the
target_file
:param target_file: File to be rendered
:type target_file: str
@@ -113,7 +115,7 @@ def get_template_name(target_file):
def get_template(target_file):
"""Return the jinja2 template for the given file
"""Return the jinja2 template for the given file.
:returns: Template object used to generate target_file
:rtype: jinja2.Template
@@ -127,7 +129,7 @@ def get_template(target_file):
def render_template(template, target_file):
"""Render the template to the file supplied
"""Render the template to the file supplied.
:param template: Template to be rendered
:type template: jinja2.Template
@@ -140,7 +142,7 @@ def render_template(template, target_file):
def render_overlay(overlay_name, target_dir):
"""Render the overlay template in the directory supplied
"""Render the overlay template in the directory supplied.
:param overlay_name: Name of overlay to be rendered
:type overlay_name: str
@@ -160,7 +162,7 @@ def render_overlay(overlay_name, target_dir):
def render_local_overlay(target_dir):
"""Render the local overlay template in the directory supplied
"""Render the local overlay template in the directory supplied.
:param target_dir: Directory to render overlay in
:type overlay_name: str
@@ -177,7 +179,7 @@ def render_local_overlay(target_dir):
def render_overlays(bundle, target_dir):
"""Render the overlays for the given bundle in the directory provided
"""Render the overlays for the given bundle in the directory provided.
:param bundle: Name of bundle being deployed
:type bundle: str
@@ -194,7 +196,7 @@ def render_overlays(bundle, target_dir):
def deploy_bundle(bundle, model):
"""Deploy the given bundle file in the specified model
"""Deploy the given bundle file in the specified model.
:param bundle: Path to bundle file
:type bundle: str
@@ -210,7 +212,7 @@ def deploy_bundle(bundle, model):
def deploy(bundle, model, wait=True):
"""Run all steps to complete deployment
"""Run all steps to complete deployment.
:param bundle: Path to bundle file
:type bundle: str
@@ -230,7 +232,7 @@ def deploy(bundle, model, wait=True):
def parse_args(args):
"""Parse command line arguments
"""Parse command line arguments.
:param args: List of configure functions functions
:type list: [str1, str2,...] List of command line arguments
@@ -252,7 +254,7 @@ def parse_args(args):
def main():
"""Deploy bundle"""
"""Deploy bundle."""
logging.basicConfig(level=logging.INFO)
args = parse_args(sys.argv[1:])
deploy(args.bundle, args.model, wait=args.wait)

View File

@@ -1,3 +1,4 @@
"""Run destroy phase."""
import argparse
import logging
import sys
@@ -6,7 +7,7 @@ import zaza.controller
def destroy(model_name):
"""Run all steps to cleaup after a test run
"""Run all steps to cleaup after a test run.
:param model: Name of model to remove
:type bundle: str
@@ -15,7 +16,7 @@ def destroy(model_name):
def parse_args(args):
"""Parse command line arguments
"""Parse command line arguments.
:param args: List of configure functions functions
:type list: [str1, str2,...] List of command line arguments
@@ -29,7 +30,7 @@ def parse_args(args):
def main():
"""Cleanup after test run"""
"""Cleanup after test run."""
logging.basicConfig(level=logging.INFO)
args = parse_args(sys.argv[1:])
destroy(args.model_name)

View File

@@ -1,3 +1,4 @@
"""Run full test lifecycle."""
import argparse
import asyncio
import logging
@@ -14,11 +15,16 @@ import zaza.charm_lifecycle.test as test
def generate_model_name():
"""Generate a unique model name.
:returns: Model name
:rtype: str
"""
return 'zaza-{}'.format(str(uuid.uuid4())[-12:])
def func_test_runner(keep_model=False, smoke=False, bundle=None):
"""Deploy the bundles and run the tests as defined by the charms tests.yaml
"""Deploy the bundles and run the tests as defined by the charms tests.yaml.
:param keep_model: Whether to destroy model at end of run
:type keep_model: boolean
@@ -58,7 +64,7 @@ def func_test_runner(keep_model=False, smoke=False, bundle=None):
def parse_args(args):
"""Parse command line arguments
"""Parse command line arguments.
:param args: List of configure functions functions
:type list: [str1, str2,...] List of command line arguments
@@ -82,6 +88,7 @@ def parse_args(args):
def main():
"""Execute full test run."""
args = parse_args(sys.argv[1:])
level = getattr(logging, args.loglevel.upper(), None)

View File

@@ -1,3 +1,4 @@
"""Run prepare phase."""
import argparse
import logging
import sys
@@ -21,7 +22,7 @@ MODEL_DEFAULTS = {
def prepare(model_name):
"""Run all steps to prepare the environment before a functional test run
"""Run all steps to prepare the environment before a functional test run.
:param model: Name of model to add
:type bundle: str
@@ -30,7 +31,7 @@ def prepare(model_name):
def parse_args(args):
"""Parse command line arguments
"""Parse command line arguments.
:param args: List of configure functions functions
:type list: [str1, str2,...] List of command line arguments
@@ -44,7 +45,7 @@ def parse_args(args):
def main():
"""Add a new model"""
"""Add a new model."""
logging.basicConfig(level=logging.INFO)
args = parse_args(sys.argv[1:])
prepare(args.model_name)

View File

@@ -1,3 +1,4 @@
"""Run test phase."""
import asyncio
import argparse
import logging
@@ -22,13 +23,13 @@ def run_test_list(tests):
def test(model_name, tests):
"""Run all steps to execute tests against the model"""
"""Run all steps to execute tests against the model."""
utils.set_juju_model(model_name)
run_test_list(tests)
def parse_args(args):
"""Parse command line arguments
"""Parse command line arguments.
:param args: List of configure functions functions
:type list: [str1, str2,...] List of command line arguments
@@ -45,8 +46,11 @@ def parse_args(args):
def main():
"""Run the tests defined by the command line args or if none were provided
read the tests from the charms tests.yaml config file"""
"""Run the tests defined by the command line args.
Run the tests defined by the command line args or if none were provided
read the tests from the charms tests.yaml config file
"""
logging.basicConfig(level=logging.INFO)
args = parse_args(sys.argv[1:])
tests = args.tests or utils.get_charm_config()['tests']

View File

@@ -1,3 +1,4 @@
"""Utilities to support running lifecycle phases."""
import importlib
import os
import yaml
@@ -9,7 +10,7 @@ DEFAULT_TEST_CONFIG = "./tests/tests.yaml"
def get_charm_config(yaml_file=None):
"""Read the yaml test config file and return the resulting config
"""Read the yaml test config file and return the resulting config.
:param yaml_file: File to be read
:type yaml_file: str
@@ -23,10 +24,10 @@ def get_charm_config(yaml_file=None):
def get_class(class_str):
"""Get the class represented by the given string
"""Get the class represented by the given string.
For example, get_class('zaza.charms_tests.svc.TestSVCClass1')
returns zaza.charms_tests.svc.TestSVCClass1
For example, get_class('zaza.charms_tests.svc.TestSVCClass1')
returns zaza.charms_tests.svc.TestSVCClass1
:param class_str: Class to be returned
:type class_str: str
@@ -40,7 +41,7 @@ def get_class(class_str):
def set_juju_model(model_name):
"""Point environment at the given model
"""Point environment at the given model.
:param model_name: Model to point environment at
:type model_name: str
@@ -49,7 +50,7 @@ def set_juju_model(model_name):
def get_juju_model():
"""Retrieve current model
"""Retrieve current model.
First check the environment for JUJU_MODEL. If this is not set, get the
current active model.
@@ -57,7 +58,6 @@ def get_juju_model():
:returns: In focus model name
:rtype: str
"""
try:
# Check the environment
return os.environ["JUJU_MODEL"]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
"""Run configuration phase."""
import zaza.charm_tests.vault.utils as vault_utils

View File

@@ -0,0 +1 @@
"""Collection of utilities to support zaza tests etc."""

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python3
#
# Copyright 2018 Canonical Ltd.
#
@@ -13,6 +12,7 @@
# 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.
"""Module for working with x.509 certificates."""
import cryptography
from cryptography.hazmat.primitives.asymmetric import rsa
@@ -29,7 +29,7 @@ def generate_cert(common_name,
signing_key=None,
signing_key_password=None,
generate_ca=False):
"""Generate x.509 certificate
"""Generate x.509 certificate.
Example of how to create a certificate chain::

View File

@@ -1,11 +1,11 @@
#!/usr/bin/env python3
"""Module containing utilities for working with commandline tools."""
import logging
import os
def parse_arg(options, arg, multiargs=False):
"""Parse argparse argments
"""Parse argparse argments.
:param options: Argparse options
:type options: argparse object
@@ -16,7 +16,6 @@ def parse_arg(options, arg, multiargs=False):
:returns: Argparse atrribute value
:rtype: string
"""
if arg.upper() in os.environ:
if multiargs:
return os.environ[arg.upper()].split()
@@ -27,12 +26,11 @@ def parse_arg(options, arg, multiargs=False):
def setup_logging():
"""Setup zaza logging
"""Do setup for logging.
:returns: Nothing: This fucntion is executed for its sideffect
:rtype: None
"""
logFormatter = logging.Formatter(
fmt="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")

View File

@@ -1,3 +1,7 @@
"""Module of exceptions that zaza may raise."""
class MissingOSAthenticationException(Exception):
"""Exception when some data needed to authenticate is missing."""
pass

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
"""Collection of functions that did not fit anywhere else."""
import logging
import os
@@ -10,20 +10,21 @@ from zaza.utilities import juju as juju_utils
def dict_to_yaml(dict_data):
"""Return YAML from dictionary
"""Return YAML from dictionary.
:param dict_data: Dictionary data
:type dict_data: dict
:returns: YAML dump
:rtype: string
"""
return yaml.dump(dict_data, default_flow_style=False)
def get_network_config(net_topology, ignore_env_vars=False,
net_topology_file="network.yaml"):
"""Get network info from network.yaml, override the values if specific
"""Get network info from environment.
Get network info from network.yaml, override the values if specific
environment variables are set for the undercloud.
This function may be used when running network configuration from CLI to
@@ -36,7 +37,6 @@ def get_network_config(net_topology, ignore_env_vars=False,
:returns: Dictionary of network configuration
:rtype: dict
"""
if os.path.exists(net_topology_file):
net_info = get_yaml_config(net_topology_file)[net_topology]
else:
@@ -53,7 +53,7 @@ def get_network_config(net_topology, ignore_env_vars=False,
def get_pkg_version(application, pkg):
"""Return package version
"""Return package version.
:param application: Application name
:type application: string
@@ -62,7 +62,6 @@ def get_pkg_version(application, pkg):
:returns: List of package version
:rtype: list
"""
versions = []
units = model.get_units(
lifecycle_utils.get_juju_model(), application)
@@ -76,7 +75,9 @@ def get_pkg_version(application, pkg):
def get_undercloud_env_vars():
""" Get environment specific undercloud network configuration settings from
"""Get environment specific undercloud network configuration settings.
Get environment specific undercloud network configuration settings from
environment variables.
For each testing substrate, specific undercloud network configuration
@@ -106,7 +107,6 @@ def get_undercloud_env_vars():
:returns: Network environment variables
:rtype: dict
"""
# Handle backward compatibile OSCI enviornment variables
_vars = {}
_vars['net_id'] = os.environ.get('NET_ID')
@@ -141,14 +141,13 @@ def get_undercloud_env_vars():
def get_yaml_config(config_file):
"""Return configuration from YAML file
"""Return configuration from YAML file.
:param config_file: Configuration file name
:type config_file: string
:returns: Dictionary of configuration
:rtype: dict
"""
# Note in its original form get_mojo_config it would do a search pattern
# through mojo stage directories. This version assumes the yaml file is in
# the pwd.

View File

@@ -13,6 +13,7 @@
# 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.
"""Module for interacting with juju."""
import os
from pathlib import Path
import yaml
@@ -26,7 +27,7 @@ from zaza.utilities import generic as generic_utils
def get_application_status(application=None, unit=None):
"""Return the juju status for an application
"""Return the juju status for an application.
:param application: Application name
:type application: string
@@ -35,7 +36,6 @@ def get_application_status(application=None, unit=None):
:returns: Juju status output for an application
:rtype: dict
"""
status = get_full_juju_status()
if unit and not application:
@@ -49,7 +49,7 @@ def get_application_status(application=None, unit=None):
def get_cloud_configs(cloud=None):
"""Get cloud configuration from local clouds.yaml
"""Get cloud configuration from local clouds.yaml.
libjuju does not yet have cloud information implemented.
Use libjuju as soon as possible.
@@ -59,7 +59,6 @@ def get_cloud_configs(cloud=None):
:returns: Dictionary of cloud configuration
:rtype: dict
"""
home = str(Path.home())
cloud_config = os.path.join(home, ".local", "share", "juju", "clouds.yaml")
if cloud:
@@ -69,25 +68,23 @@ def get_cloud_configs(cloud=None):
def get_full_juju_status():
"""Return the full juju status output
"""Return the full juju status output.
:returns: Full juju status output
:rtype: dict
"""
status = model.get_status(lifecycle_utils.get_juju_model())
return status
def get_machines_for_application(application):
"""Return machines for a given application
"""Return machines for a given application.
:param application: Application name
:type application: string
:returns: List of machines for an application
:rtype: list
"""
status = get_application_status(application)
# libjuju juju status no longer has units for subordinate charms
@@ -103,7 +100,7 @@ def get_machines_for_application(application):
def get_machine_status(machine, key=None):
"""Return the juju status for a machine
"""Return the juju status for a machine.
:param machine: Machine number
:type machine: string
@@ -112,7 +109,6 @@ def get_machine_status(machine, key=None):
:returns: Juju status output for a machine
:rtype: dict
"""
status = get_full_juju_status()
status = status.machines.get(machine)
if key:
@@ -121,14 +117,13 @@ def get_machine_status(machine, key=None):
def get_machine_uuids_for_application(application):
"""Return machine uuids for a given application
"""Return machine uuids for a given application.
:param application: Application name
:type application: string
:returns: List of machine uuuids for an application
:rtype: list
"""
uuids = []
for machine in get_machines_for_application(application):
uuids.append(get_machine_status(machine, key="instance-id"))
@@ -136,12 +131,11 @@ def get_machine_uuids_for_application(application):
def get_provider_type():
"""Get the type of the undercloud
"""Get the type of the undercloud.
:returns: Name of the undercloud type
:rtype: string
"""
cloud = controller.get_cloud()
if cloud:
# If the controller was deployed from this system with
@@ -155,7 +149,7 @@ def get_provider_type():
def remote_run(unit, remote_cmd, timeout=None, fatal=None):
"""Run command on unit and return the output
"""Run command on unit and return the output.
NOTE: This function is pre-deprecated. As soon as libjuju unit.run is able
to return output this functionality should move to model.run_on_unit.
@@ -186,7 +180,8 @@ def remote_run(unit, remote_cmd, timeout=None, fatal=None):
def _get_unit_names(names):
"""
"""Resolve given application names to first unit name of said application.
Helper function that resolves application names to first unit name of
said application. Any already resolved unit names are returned as-is.
@@ -207,7 +202,8 @@ def _get_unit_names(names):
def get_relation_from_unit(entity, remote_entity, remote_interface_name):
"""
"""Get relation data passed between two units.
Get relation data for relation with `remote_interface_name` between
`entity` and `remote_entity` from the perspective of `entity`.

View File

@@ -1,3 +1,7 @@
"""Module for interacting with OpenStack.
This module contains a number of functions for interacting with Openstack.
"""
from .os_versions import (
OPENSTACK_CODENAMES,
SWIFT_CODENAMES,
@@ -82,7 +86,7 @@ UPGRADE_SERVICES = [
# Openstack Client helpers
def get_ks_creds(cloud_creds, scope='PROJECT'):
"""Return the credentials for authenticating against keystone
"""Return the credentials for authenticating against keystone.
:param cloud_creds: Openstack RC environment credentials
:type cloud_creds: dict
@@ -91,7 +95,6 @@ def get_ks_creds(cloud_creds, scope='PROJECT'):
:returns: Credentials dictionary
:rtype: dict
"""
if cloud_creds.get('API_VERSION', 2) == 2:
auth = {
'username': cloud_creds['OS_USERNAME'],
@@ -122,7 +125,7 @@ def get_ks_creds(cloud_creds, scope='PROJECT'):
def get_glance_session_client(session):
"""Return glanceclient authenticated by keystone session
"""Return glanceclient authenticated by keystone session.
:param session: Keystone session object
:type session: keystoneauth1.session.Session object
@@ -133,36 +136,33 @@ def get_glance_session_client(session):
def get_nova_session_client(session):
"""Return novaclient authenticated by keystone session
"""Return novaclient authenticated by keystone session.
:param session: Keystone session object
:type session: keystoneauth1.session.Session object
:returns: Authenticated novaclient
:rtype: novaclient.Client object
"""
return novaclient_client.Client(2, session=session)
def get_neutron_session_client(session):
"""Return neutronclient authenticated by keystone session
"""Return neutronclient authenticated by keystone session.
:param session: Keystone session object
:type session: keystoneauth1.session.Session object
:returns: Authenticated neutronclient
:rtype: neutronclient.Client object
"""
return neutronclient.Client(session=session)
def get_keystone_scope():
"""Return Keystone scope based on OpenStack release
"""Return Keystone scope based on OpenStack release.
:returns: String keystone scope
:rtype: string
"""
os_version = get_current_os_versions("keystone")["keystone"]
# Keystone policy.json shipped the charm with liberty requires a domain
# scoped token. Bug #1649106
@@ -174,7 +174,7 @@ def get_keystone_scope():
def get_keystone_session(opentackrc_creds, insecure=True, scope='PROJECT'):
"""Return keystone session
"""Return keystone session.
:param openrc_creds: Openstack RC credentials
:type openrc_creds: dict
@@ -185,7 +185,6 @@ def get_keystone_session(opentackrc_creds, insecure=True, scope='PROJECT'):
:returns: Keystone session object
:rtype: keystoneauth1.session.Session object
"""
keystone_creds = get_ks_creds(opentackrc_creds, scope=scope)
if opentackrc_creds.get('API_VERSION', 2) == 2:
auth = v2.Password(**keystone_creds)
@@ -195,41 +194,38 @@ def get_keystone_session(opentackrc_creds, insecure=True, scope='PROJECT'):
def get_overcloud_keystone_session():
"""Return Over cloud keystone session
"""Return Over cloud keystone session.
:returns keystone_session: keystoneauth1.session.Session object
:rtype: keystoneauth1.session.Session
"""
return get_keystone_session(get_overcloud_auth(),
scope=get_keystone_scope())
def get_undercloud_keystone_session():
"""Return Under cloud keystone session
"""Return Under cloud keystone session.
:returns keystone_session: keystoneauth1.session.Session object
:rtype: keystoneauth1.session.Session
"""
return get_keystone_session(get_undercloud_auth(),
scope=get_keystone_scope())
def get_keystone_session_client(session):
"""Return keystoneclient authenticated by keystone session
"""Return keystoneclient authenticated by keystone session.
:param session: Keystone session object
:type session: keystoneauth1.session.Session object
:returns: Authenticated keystoneclient
:rtype: keystoneclient.v3.Client object
"""
return keystoneclient_v3.Client(session=session)
def get_keystone_client(opentackrc_creds, insecure=True):
"""Return authenticated keystoneclient and set auth_ref for service_catalog
"""Return authenticated keystoneclient and set auth_ref for service_catalog.
:param openrc_creds: Openstack RC credentials
:type openrc_creds: dict
@@ -238,7 +234,6 @@ def get_keystone_client(opentackrc_creds, insecure=True):
:returns: Authenticated keystoneclient
:rtype: keystoneclient.v3.Client object
"""
session = get_keystone_session(opentackrc_creds, insecure)
client = get_keystone_session_client(session)
keystone_creds = get_ks_creds(opentackrc_creds)
@@ -252,7 +247,7 @@ def get_keystone_client(opentackrc_creds, insecure=True):
def get_project_id(ks_client, project_name, api_version=2, domain_name=None):
"""Return project ID
"""Return project ID.
:param ks_client: Authenticated keystoneclient
:type ks_client: keystoneclient.v3.Client object
@@ -265,7 +260,6 @@ def get_project_id(ks_client, project_name, api_version=2, domain_name=None):
:returns: Project ID
:rtype: string or None
"""
domain_id = None
if domain_name:
domain_id = ks_client.domains.list(name=domain_name)[0].id
@@ -278,22 +272,20 @@ def get_project_id(ks_client, project_name, api_version=2, domain_name=None):
# Neutron Helpers
def get_gateway_uuids():
"""Return machine uuids for neutron-gateway(s)
"""Return machine uuids for neutron-gateway(s).
:returns: List of uuids
:rtype: list
"""
return juju_utils.get_machine_uuids_for_application('neutron-gateway')
def get_ovs_uuids():
"""Return machine uuids for neutron-openvswitch(s)
"""Return machine uuids for neutron-openvswitch(s).
:returns: List of uuids
:rtype: list
"""
return (juju_utils
.get_machine_uuids_for_application('neutron-openvswitch'))
@@ -303,14 +295,13 @@ NEW_STYLE_NETWORKING = 'physnet1:br-ex'
def deprecated_external_networking(dvr_mode=False):
"""Determine whether deprecated external network mode is in use
"""Determine whether deprecated external network mode is in use.
:param dvr_mode: Using DVR mode or not
:type dvr_mode: boolean
:returns: True or False
:rtype: boolean
"""
bridge_mappings = None
if dvr_mode:
bridge_mappings = get_application_config_option('neutron-openvswitch',
@@ -325,7 +316,7 @@ def deprecated_external_networking(dvr_mode=False):
def get_net_uuid(neutron_client, net_name):
"""Determine whether deprecated external network mode is in use
"""Determine whether deprecated external network mode is in use.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -334,20 +325,18 @@ def get_net_uuid(neutron_client, net_name):
:returns: Network ID
:rtype: string
"""
network = neutron_client.list_networks(name=net_name)['networks'][0]
return network['id']
def get_admin_net(neutron_client):
"""Return admin netowrk
"""Return admin netowrk.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
:returns: Admin network object
:rtype: dict
"""
for net in neutron_client.list_networks()['networks']:
if net['name'].endswith('_admin_net'):
return net
@@ -355,7 +344,7 @@ def get_admin_net(neutron_client):
def configure_gateway_ext_port(novaclient, neutronclient,
dvr_mode=None, net_id=None):
"""Configure the neturong-gateway external port
"""Configure the neturong-gateway external port.
:param novaclient: Authenticated novaclient
:type novaclient: novaclient.Client object
@@ -366,7 +355,6 @@ def configure_gateway_ext_port(novaclient, neutronclient,
:param net_id: Network ID
:type net_id: string
"""
if dvr_mode:
uuids = get_ovs_uuids()
else:
@@ -432,7 +420,7 @@ def configure_gateway_ext_port(novaclient, neutronclient,
def create_project_network(neutron_client, project_id, net_name='private',
shared=False, network_type='gre', domain=None):
"""Create the project network
"""Create the project network.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -449,7 +437,6 @@ def create_project_network(neutron_client, project_id, net_name='private',
:returns: Network object
:rtype: dict
"""
networks = neutron_client.list_networks(name=net_name)
if len(networks['networks']) == 0:
logging.info('Creating network: %s',
@@ -473,7 +460,7 @@ def create_project_network(neutron_client, project_id, net_name='private',
def create_external_network(neutron_client, project_id, dvr_mode,
net_name='ext_net'):
"""Create the external network
"""Create the external network.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -486,7 +473,6 @@ def create_external_network(neutron_client, project_id, dvr_mode,
:returns: Network object
:rtype: dict
"""
networks = neutron_client.list_networks(name=net_name)
if len(networks['networks']) == 0:
logging.info('Configuring external network')
@@ -512,7 +498,7 @@ def create_external_network(neutron_client, project_id, dvr_mode,
def create_project_subnet(neutron_client, project_id, network, cidr, dhcp=True,
subnet_name='private_subnet', domain=None,
subnetpool=None, ip_version=4, prefix_len=24):
"""Create the project subnet
"""Create the project subnet.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -537,7 +523,6 @@ def create_project_subnet(neutron_client, project_id, network, cidr, dhcp=True,
:returns: Subnet object
:rtype: dict
"""
# Create subnet
subnets = neutron_client.list_subnets(name=subnet_name)
if len(subnets['subnets']) == 0:
@@ -567,7 +552,7 @@ def create_external_subnet(neutron_client, project_id, network,
default_gateway=None, cidr=None,
start_floating_ip=None, end_floating_ip=None,
subnet_name='ext_net_subnet'):
"""Create the external subnet
"""Create the external subnet.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -588,7 +573,6 @@ def create_external_subnet(neutron_client, project_id, network,
:returns: Subnet object
:rtype: dict
"""
subnets = neutron_client.list_subnets(name=subnet_name)
if len(subnets['subnets']) == 0:
subnet_msg = {
@@ -620,7 +604,7 @@ def create_external_subnet(neutron_client, project_id, network,
def update_subnet_dns(neutron_client, subnet, dns_servers):
"""Update subnet DNS servers
"""Update subnet DNS servers.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -629,7 +613,6 @@ def update_subnet_dns(neutron_client, subnet, dns_servers):
:param dns_servers: Comma separted list of IP addresses
:type project_id: string
"""
msg = {
'subnet': {
'dns_nameservers': dns_servers.split(',')
@@ -641,7 +624,7 @@ def update_subnet_dns(neutron_client, subnet, dns_servers):
def create_provider_router(neutron_client, project_id):
"""Create the provider router
"""Create the provider router.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -650,7 +633,6 @@ def create_provider_router(neutron_client, project_id):
:returns: Router object
:rtype: dict
"""
routers = neutron_client.list_routers(name='provider-router')
if len(routers['routers']) == 0:
logging.info('Creating provider router for external network access')
@@ -669,7 +651,7 @@ def create_provider_router(neutron_client, project_id):
def plug_extnet_into_router(neutron_client, router, network):
"""Add external interface to virtual router
"""Add external interface to virtual router.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -678,7 +660,6 @@ def plug_extnet_into_router(neutron_client, router, network):
:param network: Network object
:type network: dict
"""
ports = neutron_client.list_ports(device_owner='network:router_gateway',
network_id=network['id'])
if len(ports['ports']) == 0:
@@ -692,7 +673,7 @@ def plug_extnet_into_router(neutron_client, router, network):
def plug_subnet_into_router(neutron_client, router, network, subnet):
"""Add subnet interface to virtual router
"""Add subnet interface to virtual router.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -703,7 +684,6 @@ def plug_subnet_into_router(neutron_client, router, network, subnet):
:param subnet: Subnet object
:type subnet: dict
"""
routers = neutron_client.list_routers(name=router)
if len(routers['routers']) == 0:
logging.error('Unable to locate provider router %s', router)
@@ -723,7 +703,7 @@ def plug_subnet_into_router(neutron_client, router, network, subnet):
def create_address_scope(neutron_client, project_id, name, ip_version=4):
"""Create address scope
"""Create address scope.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -736,7 +716,6 @@ def create_address_scope(neutron_client, project_id, name, ip_version=4):
:returns: Address scope object
:rtype: dict
"""
address_scopes = neutron_client.list_address_scopes(name=name)
if len(address_scopes['address_scopes']) == 0:
logging.info('Creating {} address scope'.format(name))
@@ -759,7 +738,7 @@ def create_address_scope(neutron_client, project_id, name, ip_version=4):
def create_subnetpool(neutron_client, project_id, name, subnetpool_prefix,
address_scope, shared=True):
"""Create subnet pool
"""Create subnet pool.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -776,7 +755,6 @@ def create_subnetpool(neutron_client, project_id, name, subnetpool_prefix,
:returns: Subnetpool object
:rtype: dict
"""
subnetpools = neutron_client.list_subnetpools(name=name)
if len(subnetpools['subnetpools']) == 0:
logging.info('Creating subnetpool: %s',
@@ -800,7 +778,7 @@ def create_subnetpool(neutron_client, project_id, name, subnetpool_prefix,
def create_bgp_speaker(neutron_client, local_as=12345, ip_version=4,
name='bgp-speaker'):
"""Create BGP speaker
"""Create BGP speaker.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -813,7 +791,6 @@ def create_bgp_speaker(neutron_client, local_as=12345, ip_version=4,
:returns: BGP speaker object
:rtype: dict
"""
bgp_speakers = neutron_client.list_bgp_speakers(name=name)
if len(bgp_speakers['bgp_speakers']) == 0:
logging.info('Creating BGP Speaker')
@@ -833,7 +810,7 @@ def create_bgp_speaker(neutron_client, local_as=12345, ip_version=4,
def add_network_to_bgp_speaker(neutron_client, bgp_speaker, network_name):
"""Advertise network on BGP Speaker
"""Advertise network on BGP Speaker.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -842,7 +819,6 @@ def add_network_to_bgp_speaker(neutron_client, bgp_speaker, network_name):
:param network_name: Name of network to advertise
:type network_name: string
"""
network_id = get_net_uuid(neutron_client, network_name)
# There is no direct way to determine which networks have already
# been advertised. For example list_route_advertised_from_bgp_speaker shows
@@ -859,7 +835,7 @@ def add_network_to_bgp_speaker(neutron_client, bgp_speaker, network_name):
def create_bgp_peer(neutron_client, peer_application_name='quagga',
remote_as=10000, auth_type='none'):
"""Create BGP peer
"""Create BGP peer.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -872,7 +848,6 @@ def create_bgp_peer(neutron_client, peer_application_name='quagga',
:returns: BGP peer object
:rtype: dict
"""
peer_unit = model.get_units(
lifecycle_utils.get_juju_model(), peer_application_name)[0]
peer_ip = peer_unit.public_address
@@ -895,7 +870,7 @@ def create_bgp_peer(neutron_client, peer_application_name='quagga',
def add_peer_to_bgp_speaker(neutron_client, bgp_speaker, bgp_peer):
"""Add BGP peer relationship to BGP speaker
"""Add BGP peer relationship to BGP speaker.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -904,7 +879,6 @@ def add_peer_to_bgp_speaker(neutron_client, bgp_speaker, bgp_peer):
:param bpg_peer: BGP peer object
:type bgp_peer: dict
"""
# Handle the expected exception if the peer is already on the
# speaker
try:
@@ -918,14 +892,13 @@ def add_peer_to_bgp_speaker(neutron_client, bgp_speaker, bgp_peer):
def add_neutron_secgroup_rules(neutron_client, project_id):
"""Add neutron security group rules
"""Add neutron security group rules.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
:param project_id: Project ID
:type project_id: string
"""
secgroup = None
for group in neutron_client.list_security_groups().get('security_groups'):
if (group.get('name') == 'default' and
@@ -968,7 +941,7 @@ def add_neutron_secgroup_rules(neutron_client, project_id):
def create_port(neutron_client, name, network_name):
"""Create port on network
"""Create port on network.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -979,7 +952,6 @@ def create_port(neutron_client, name, network_name):
:returns: Port object
:rtype: dict
"""
ports = neutron_client.list_ports(name=name)
if len(ports['ports']) == 0:
logging.info('Creating port: {}'.format(name))
@@ -999,7 +971,7 @@ def create_port(neutron_client, name, network_name):
def create_floating_ip(neutron_client, network_name, port=None):
"""Create floating IP on network and optionally associate to a port
"""Create floating IP on network and optionally associate to a port.
:param neutron_client: Authenticated neutronclient
:type neutron_client: neutronclient.Client object
@@ -1010,7 +982,6 @@ def create_floating_ip(neutron_client, network_name, port=None):
:returns: Floating IP object
:rtype: dict
"""
floatingips = neutron_client.list_floatingips()
if len(floatingips['floatingips']) > 0:
if port:
@@ -1038,20 +1009,19 @@ def create_floating_ip(neutron_client, network_name, port=None):
# Codename and package versions
def get_swift_codename(version):
"""Determine OpenStack codename that corresponds to swift version
"""Determine OpenStack codename that corresponds to swift version.
:param version: Version of Swift
:type version: string
:returns: Codename for swift
:rtype: string
"""
codenames = [k for k, v in six.iteritems(SWIFT_CODENAMES) if version in v]
return codenames[0]
def get_os_code_info(package, pkg_version):
"""Determine OpenStack codename that corresponds to package version
"""Determine OpenStack codename that corresponds to package version.
:param package: Package name
:type package: string
@@ -1060,7 +1030,6 @@ def get_os_code_info(package, pkg_version):
:returns: Codename for package
:rtype: string
"""
# {'code_num': entry, 'code_name': OPENSTACK_CODENAMES[entry]}
# Remove epoch if it exists
if ':' in pkg_version:
@@ -1090,14 +1059,13 @@ def get_os_code_info(package, pkg_version):
def get_current_os_versions(deployed_applications):
"""Determine OpenStack codename of deployed applications
"""Determine OpenStack codename of deployed applications.
:param deployed_applications: List of deployed applications
:type deployed_applications: list
:returns: List of aplication to codenames dictionaries
:rtype: list
"""
versions = {}
for application in UPGRADE_SERVICES:
if application['name'] not in deployed_applications:
@@ -1111,21 +1079,20 @@ def get_current_os_versions(deployed_applications):
def get_application_config_keys(application):
"""Return application configuration keys
"""Return application configuration keys.
:param application: Name of application
:type application: string
:returns: List of aplication configuration keys
:rtype: list
"""
application_config = model.get_application_config(
lifecycle_utils.get_juju_model(), application)
return list(application_config.keys())
def get_application_config_option(application, option):
"""Return application configuration
"""Return application configuration.
:param application: Name of application
:type application: string
@@ -1134,7 +1101,6 @@ def get_application_config_option(application, option):
:returns: Value of configuration option
:rtype: Configuration option value type
"""
application_config = model.get_application_config(
lifecycle_utils.get_juju_model(), application)
try:
@@ -1144,13 +1110,11 @@ def get_application_config_option(application, option):
def get_undercloud_auth():
"""Get the undercloud OpenStack authentication settings from the
environment.
"""Get undercloud OpenStack authentication settings from environment.
:returns: Dictionary of authentication settings
:rtype: dict
"""
os_auth_url = os.environ.get('OS_AUTH_URL')
if os_auth_url:
api_version = os_auth_url.split('/')[-1].replace('v', '')
@@ -1213,6 +1177,11 @@ def get_undercloud_auth():
# Openstack Client helpers
def get_keystone_ip():
"""Return the IP address to use when communicating with keystone api.
:returns: IP address
:rtype: str
"""
if get_application_config_option('keystone', 'vip'):
return get_application_config_option('keystone', 'vip')
unit = model.get_units(
@@ -1221,13 +1190,11 @@ def get_keystone_ip():
def get_overcloud_auth():
"""Get the overcloud OpenStack authentication settings from the
environment.
"""Get overcloud OpenStack authentication from the environment.
:returns: Dictionary of authentication settings
:rtype: dict
"""
if get_application_config_option('keystone', 'use-https').lower() == 'yes':
transport = 'https'
port = 35357
@@ -1274,7 +1241,7 @@ def get_overcloud_auth():
def get_urllib_opener():
"""Create a urllib opener taking into account proxy settings
"""Create a urllib opener taking into account proxy settings.
Using urllib.request.urlopen will automatically handle proxies so none
of this function is needed except we are currently specifying proxies
@@ -1295,7 +1262,7 @@ def get_urllib_opener():
def find_cirros_image(arch):
"""Return the url for the latest cirros image for the given architecture
"""Return the url for the latest cirros image for the given architecture.
:param arch: aarch64, arm, i386, x86_64 etc
:type arch: str
@@ -1310,7 +1277,7 @@ def find_cirros_image(arch):
def download_image(image_url, target_file):
"""Download the image from the given url to the specified file
"""Download the image from the given url to the specified file.
:param image_url: URL to download image from
:type image_url: str
@@ -1327,7 +1294,9 @@ def download_image(image_url, target_file):
def resource_reaches_status(resource, resource_id,
expected_status='available',
msg='resource'):
"""Wait for an openstack resources status to reach an expected status
"""Wait for an openstack resources status to reach an expected status.
Wait for an openstack resources status to reach an expected status
within a specified time. Useful to confirm that nova instances, cinder
vols, snapshots, glance images, heat stacks and other resources
eventually reach the expected status.
@@ -1351,7 +1320,7 @@ def resource_reaches_status(resource, resource_id,
@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60),
reraise=True, stop=tenacity.stop_after_attempt(2))
def resource_removed(resource, resource_id, msg="resource"):
"""Wait for an openstack resource to no longer be present
"""Wait for an openstack resource to no longer be present.
:param resource: pointer to os resource type, ex: heat_client.stacks
:type resource: str
@@ -1367,7 +1336,9 @@ def resource_removed(resource, resource_id, msg="resource"):
def delete_resource(resource, resource_id, msg="resource"):
"""Delete an openstack resource, such as one instance, keypair,
"""Delete an openstack resource.
Delete an openstack resource, such as one instance, keypair,
image, volume, stack, etc., and confirm deletion within max wait time.
:param resource: pointer to os resource type, ex:glance_client.images
@@ -1384,7 +1355,7 @@ def delete_resource(resource, resource_id, msg="resource"):
def delete_image(glance, img_id):
"""Delete the given image from glance
"""Delete the given image from glance.
:param glance: Authenticated glanceclient
:type glance: glanceclient.Client
@@ -1396,7 +1367,7 @@ def delete_image(glance, img_id):
def upload_image_to_glance(glance, local_path, image_name, disk_format='qcow2',
visibility='public', container_format='bare'):
"""Upload the given image to glance and apply the given label
"""Upload the given image to glance and apply the given label.
:param glance: Authenticated glanceclient
:type glance: glanceclient.Client

View File

@@ -1,3 +1,4 @@
"""Module containing data about OpenStack versions."""
from collections import OrderedDict