Docstrings and trusty deploy fixes
This commit is contained in:
parent
a1d6ab62cd
commit
7605fb49cf
3
actions/__init__.py
Normal file
3
actions/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.append('lib')
|
@ -13,6 +13,7 @@ import charmhelpers.fetch as fetch
|
|||||||
|
|
||||||
|
|
||||||
def setup_git(branch, git_dir, tempest_conf):
|
def setup_git(branch, git_dir, tempest_conf):
|
||||||
|
"""Clone tempest and symlink in rendered tempest.conf"""
|
||||||
conf = hookenv.config()
|
conf = hookenv.config()
|
||||||
if not os.path.exists(git_dir):
|
if not os.path.exists(git_dir):
|
||||||
git_url = conf['tempest-source']
|
git_url = conf['tempest-source']
|
||||||
@ -23,36 +24,47 @@ def setup_git(branch, git_dir, tempest_conf):
|
|||||||
os.symlink(tempest_conf, conf_symlink)
|
os.symlink(tempest_conf, conf_symlink)
|
||||||
|
|
||||||
|
|
||||||
def execute_tox(run_dir, logfile):
|
def execute_tox(run_dir, logfile, tox_target):
|
||||||
|
"""Trigger tempest run through tox setting proxies if needed"""
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
conf = hookenv.config()
|
conf = hookenv.config()
|
||||||
if conf.get('http-proxy'):
|
if conf.get('http-proxy'):
|
||||||
env['http_proxy'] = conf['http-proxy']
|
env['http_proxy'] = conf['http-proxy']
|
||||||
if conf.get('https-proxy'):
|
if conf.get('https-proxy'):
|
||||||
env['https_proxy'] = conf['https-proxy']
|
env['https_proxy'] = conf['https-proxy']
|
||||||
cmd = ['tox', '-e', 'smoke']
|
cmd = ['tox', '-e', tox_target]
|
||||||
f = open(logfile, "w")
|
f = open(logfile, "w")
|
||||||
subprocess.call(cmd, cwd=run_dir, stdout=f, stderr=f)
|
subprocess.call(cmd, cwd=run_dir, stdout=f, stderr=f)
|
||||||
|
|
||||||
|
|
||||||
def run_smoke_test():
|
def get_tempest_files(branch_name):
|
||||||
action_args = hookenv.action_get()
|
"""Prepare tempets files and directories
|
||||||
branch = action_args['branch']
|
|
||||||
|
@return git_dir, logfile, run_dir
|
||||||
|
"""
|
||||||
log_time_str = time.strftime("%Y%m%d%H%M%S", time.gmtime())
|
log_time_str = time.strftime("%Y%m%d%H%M%S", time.gmtime())
|
||||||
tempest_git_dir = '{}/tempest-{}'.format(
|
git_dir = '{}/tempest-{}'.format(
|
||||||
tempest.TempestCharm.TEMPEST_ROOT,
|
tempest.TempestCharm.TEMPEST_ROOT,
|
||||||
branch
|
branch_name
|
||||||
)
|
)
|
||||||
tempest_logfile = '{}/run_{}.log'.format(
|
logfile = '{}/run_{}.log'.format(
|
||||||
tempest.TempestCharm.TEMPEST_LOGDIR,
|
tempest.TempestCharm.TEMPEST_LOGDIR,
|
||||||
log_time_str
|
log_time_str
|
||||||
)
|
)
|
||||||
|
run_dir = git_dir + '/tempest'
|
||||||
|
return git_dir, logfile, run_dir
|
||||||
|
|
||||||
|
|
||||||
|
def run_test(tox_target):
|
||||||
|
"""Run smoke tests"""
|
||||||
|
action_args = hookenv.action_get()
|
||||||
|
branch_name = action_args['branch']
|
||||||
|
tempest_git_dir, tempest_logfile, run_dir = get_tempest_files(branch_name)
|
||||||
action_info = {
|
action_info = {
|
||||||
'tempest-logfile': tempest_logfile,
|
'tempest-logfile': tempest_logfile,
|
||||||
}
|
}
|
||||||
run_dir = tempest_git_dir + '/tempest'
|
setup_git(branch_name, tempest_git_dir, tempest.TempestCharm.TEMPEST_CONF)
|
||||||
setup_git(branch, tempest_git_dir, tempest.TempestCharm.TEMPEST_CONF)
|
execute_tox(run_dir, tempest_logfile, tox_target)
|
||||||
execute_tox(run_dir, tempest_logfile)
|
|
||||||
hookenv.action_set(action_info)
|
hookenv.action_set(action_info)
|
||||||
|
|
||||||
|
|
||||||
@ -60,4 +72,4 @@ if __name__ == '__main__':
|
|||||||
# Cloud may have different artifacts (flavors, images etc) since last run
|
# Cloud may have different artifacts (flavors, images etc) since last run
|
||||||
# so rerun handlers file to regenerate config.
|
# so rerun handlers file to regenerate config.
|
||||||
reactive.main()
|
reactive.main()
|
||||||
run_smoke_test()
|
run_test('smoke')
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
# Wrapper to deal with newer Ubuntu versions that don't have py2 installed
|
# Wrapper to deal with newer Ubuntu versions that don't have py2 installed
|
||||||
# by default.
|
# by default.
|
||||||
|
|
||||||
declare -a DEPS=('libssl-dev' 'libffi-dev' 'apt' 'python3-netaddr' 'python3-netifaces' 'python3-pip' 'python3-yaml' 'python-cinderclient' 'python-glanceclient' 'python-heatclient' 'python-keystoneclient' 'python-neutronclient' 'python-novaclient' 'python-swiftclient' 'python-ceilometerclient' 'openvswitch-test' 'python3-cinderclient' 'python3-glanceclient' 'python3-heatclient' 'python3-keystoneclient' 'python3-neutronclient' 'python3-novaclient' 'python3-swiftclient' 'python3-ceilometerclient', 'tox')
|
|
||||||
|
|
||||||
check_and_install() {
|
check_and_install() {
|
||||||
pkg="${1}"
|
pkg="${1}"
|
||||||
if ! dpkg -s ${pkg} 2>&1 > /dev/null; then
|
if ! dpkg -s ${pkg} 2>&1 > /dev/null; then
|
||||||
@ -11,6 +9,20 @@ check_and_install() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [[ $(lsb_release -sc) -eq "trusty" ]]; then
|
||||||
|
# Add a random cloud archive for the Openstack python3 clients
|
||||||
|
add-apt-repository --yes ppa:ubuntu-cloud-archive/mitaka-staging
|
||||||
|
apt-get update
|
||||||
|
# The trusty version of tox is too low (tox version is 1.6, required is at least 2.3.1)
|
||||||
|
# pip install tox to get around this and die a little inside
|
||||||
|
pip install tox
|
||||||
|
else
|
||||||
|
check_and_install 'tox'
|
||||||
|
fi
|
||||||
|
|
||||||
|
declare -a DEPS=('libssl-dev' 'libffi-dev' 'apt' 'python3-netaddr' 'python3-netifaces' 'python3-pip' 'python3-yaml' 'python-cinderclient' 'python-glanceclient' 'python-heatclient' 'python-keystoneclient' 'python-neutronclient' 'python-novaclient' 'python-swiftclient' 'python-ceilometerclient' 'openvswitch-test' 'python3-cinderclient' 'python3-glanceclient' 'python3-heatclient' 'python3-keystoneclient' 'python3-neutronclient' 'python3-novaclient' 'python3-swiftclient' 'python3-ceilometerclient')
|
||||||
|
|
||||||
|
|
||||||
PYTHON="python"
|
PYTHON="python"
|
||||||
|
|
||||||
for dep in ${DEPS[@]}; do
|
for dep in ${DEPS[@]}; do
|
||||||
|
@ -12,6 +12,9 @@ tempest_charm = None
|
|||||||
|
|
||||||
|
|
||||||
def get_charm():
|
def get_charm():
|
||||||
|
""" Return a new instance of TempestCharm or existing global instance
|
||||||
|
@returns TempestCharm
|
||||||
|
"""
|
||||||
global tempest_charm
|
global tempest_charm
|
||||||
if tempest_charm is None:
|
if tempest_charm is None:
|
||||||
tempest_charm = TempestCharmFactory.charm()
|
tempest_charm = TempestCharmFactory.charm()
|
||||||
@ -20,28 +23,38 @@ def get_charm():
|
|||||||
|
|
||||||
class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
||||||
|
|
||||||
|
"""Inspect relations and provide properties that can be used when
|
||||||
|
rendering templates"""
|
||||||
|
|
||||||
interface_type = "identity-admin"
|
interface_type = "identity-admin"
|
||||||
|
|
||||||
def __init__(self, relation):
|
def __init__(self, relation):
|
||||||
|
"""Initialise a keystone client and collect user defined config"""
|
||||||
self.kc = None
|
self.kc = None
|
||||||
super(TempestAdminAdapter, self).__init__(relation)
|
super(TempestAdminAdapter, self).__init__(relation)
|
||||||
self.init_keystone_client()
|
self.init_keystone_client()
|
||||||
self.uconfig = hookenv.config()
|
self.uconfig = hookenv.config()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def keystone_info(self):
|
||||||
|
"""Collection keystone information from keystone relation"""
|
||||||
|
return self.relation.credentials()
|
||||||
|
|
||||||
def init_keystone_client(self):
|
def init_keystone_client(self):
|
||||||
|
"""Initialise keystone client"""
|
||||||
if self.kc:
|
if self.kc:
|
||||||
return
|
return
|
||||||
self.keystone_auth_url = '{}://{}:{}/v2.0'.format(
|
self.keystone_auth_url = '{}://{}:{}/v2.0'.format(
|
||||||
'http',
|
'http',
|
||||||
self.creds['service_hostname'],
|
self.keystone_info['service_hostname'],
|
||||||
self.creds['service_port']
|
self.keystone_info['service_port']
|
||||||
)
|
)
|
||||||
auth = {
|
auth = {
|
||||||
'username': self.creds['service_username'],
|
'username': self.keystone_info['service_username'],
|
||||||
'password': self.creds['service_password'],
|
'password': self.keystone_info['service_password'],
|
||||||
'auth_url': self.keystone_auth_url,
|
'auth_url': self.keystone_auth_url,
|
||||||
'tenant_name': self.creds['service_tenant_name'],
|
'tenant_name': self.keystone_info['service_tenant_name'],
|
||||||
'region_name': self.creds['service_region'],
|
'region_name': self.keystone_info['service_region'],
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
self.kc = keystoneclient.client.Client(**auth)
|
self.kc = keystoneclient.client.Client(**auth)
|
||||||
@ -50,6 +63,10 @@ class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def ec2_creds(self):
|
def ec2_creds(self):
|
||||||
|
"""Generate EC2 style tokens or return existing EC2 tokens
|
||||||
|
|
||||||
|
@returns {'access_token' token1, 'secret_token': token2}
|
||||||
|
"""
|
||||||
self.init_keystone_client()
|
self.init_keystone_client()
|
||||||
if not self.kc:
|
if not self.kc:
|
||||||
return {}
|
return {}
|
||||||
@ -62,6 +79,10 @@ class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def image_info(self):
|
def image_info(self):
|
||||||
|
"""Return image ids for the user-defined image names
|
||||||
|
|
||||||
|
@returns {'image_id' id1, 'image_alt_id': id2}
|
||||||
|
"""
|
||||||
self.init_keystone_client()
|
self.init_keystone_client()
|
||||||
glance_endpoint = self.kc.service_catalog.url_for(
|
glance_endpoint = self.kc.service_catalog.url_for(
|
||||||
service_type='image',
|
service_type='image',
|
||||||
@ -81,6 +102,11 @@ class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def network_info(self):
|
def network_info(self):
|
||||||
|
"""Return public network and router ids for user-defined router and
|
||||||
|
network names
|
||||||
|
|
||||||
|
@returns {'image_id' id1, 'image_alt_id': id2}
|
||||||
|
"""
|
||||||
self.init_keystone_client()
|
self.init_keystone_client()
|
||||||
neutron_ep = self.kc.service_catalog.url_for(
|
neutron_ep = self.kc.service_catalog.url_for(
|
||||||
service_type='network',
|
service_type='network',
|
||||||
@ -110,6 +136,10 @@ class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def compute_info(self):
|
def compute_info(self):
|
||||||
|
"""Return flavor ids for user-defined flavors
|
||||||
|
|
||||||
|
@returns {'flavor_id' id1, 'flavor_alt_id': id2}
|
||||||
|
"""
|
||||||
self.init_keystone_client()
|
self.init_keystone_client()
|
||||||
nova_ep = self.kc.service_catalog.url_for(
|
nova_ep = self.kc.service_catalog.url_for(
|
||||||
service_type='compute',
|
service_type='compute',
|
||||||
@ -122,9 +152,9 @@ class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
|||||||
url.netloc.split(':')[0])
|
url.netloc.split(':')[0])
|
||||||
try:
|
try:
|
||||||
nova_client = novaclient.client.Client(
|
nova_client = novaclient.client.Client(
|
||||||
self.creds['service_username'],
|
self.keystone_info['service_username'],
|
||||||
self.creds['service_password'],
|
self.keystone_info['service_password'],
|
||||||
self.creds['service_tenant_name'],
|
self.keystone_info['service_tenant_name'],
|
||||||
self.keystone_auth_url,
|
self.keystone_auth_url,
|
||||||
)
|
)
|
||||||
for flavor in nova_client.flavors.list():
|
for flavor in nova_client.flavors.list():
|
||||||
@ -136,24 +166,26 @@ class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
|||||||
hookenv.log("Nova is not ready, deferring nova query")
|
hookenv.log("Nova is not ready, deferring nova query")
|
||||||
return compute_info
|
return compute_info
|
||||||
|
|
||||||
@property
|
|
||||||
def creds(self):
|
|
||||||
return self.relation.credentials()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def auth_url(self):
|
|
||||||
bob = self.get_keystone_client() or 'bugger'
|
|
||||||
return bob
|
|
||||||
|
|
||||||
def get_present_services(self):
|
def get_present_services(self):
|
||||||
|
"""Query keystone catalogue for a list for registered services
|
||||||
|
|
||||||
|
@returns [svc1, svc2, ...]: List of registered services
|
||||||
|
"""
|
||||||
self.init_keystone_client()
|
self.init_keystone_client()
|
||||||
services = [svc.name for svc in self.kc.services.list() if svc.enabled]
|
services = [svc.name for svc in self.kc.services.list() if svc.enabled]
|
||||||
# if DashboardRelation().get('dashboard_url'):
|
|
||||||
# services.append('horizon')
|
|
||||||
return services
|
return services
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def service_info(self):
|
def service_info(self):
|
||||||
|
"""Assemble a list of services tempest should tests
|
||||||
|
|
||||||
|
Compare the list of keystone registered services with the services the
|
||||||
|
user has requested be tested. If in 'auto' mode test all services
|
||||||
|
registered in keystone.
|
||||||
|
|
||||||
|
@returns [svc1, svc2, ...]: List of services to test
|
||||||
|
"""
|
||||||
service_info = {}
|
service_info = {}
|
||||||
tempest_candidates = ['ceilometer', 'cinder', 'glance', 'heat',
|
tempest_candidates = ['ceilometer', 'cinder', 'glance', 'heat',
|
||||||
'horizon', 'ironic', 'neutron', 'nova',
|
'horizon', 'ironic', 'neutron', 'nova',
|
||||||
@ -181,7 +213,7 @@ class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
|||||||
|
|
||||||
class TempestAdapters(adapters.OpenStackRelationAdapters):
|
class TempestAdapters(adapters.OpenStackRelationAdapters):
|
||||||
"""
|
"""
|
||||||
Adapters class for the Designate charm.
|
Adapters class for the Tempest charm.
|
||||||
"""
|
"""
|
||||||
relation_adapters = {
|
relation_adapters = {
|
||||||
'identity_admin': TempestAdminAdapter,
|
'identity_admin': TempestAdminAdapter,
|
||||||
@ -194,18 +226,26 @@ class TempestAdapters(adapters.OpenStackRelationAdapters):
|
|||||||
|
|
||||||
|
|
||||||
class TempestConfigurationAdapter(adapters.ConfigurationAdapter):
|
class TempestConfigurationAdapter(adapters.ConfigurationAdapter):
|
||||||
|
"""
|
||||||
|
Manipulate user supplied config as needed
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(TempestConfigurationAdapter, self).__init__()
|
super(TempestConfigurationAdapter, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
class TempestCharm(charm.OpenStackCharm):
|
class TempestCharm(charm.OpenStackCharm):
|
||||||
|
|
||||||
|
"""Directories and files used for running tempest"""
|
||||||
TEMPEST_ROOT = '/var/lib/tempest/'
|
TEMPEST_ROOT = '/var/lib/tempest/'
|
||||||
TEMPEST_LOGDIR = TEMPEST_ROOT + '/logs'
|
TEMPEST_LOGDIR = TEMPEST_ROOT + '/logs'
|
||||||
TEMPEST_CONF = TEMPEST_ROOT + '/tempest.conf'
|
TEMPEST_CONF = TEMPEST_ROOT + '/tempest.conf'
|
||||||
|
"""pip.conf for proxy settings etc"""
|
||||||
PIP_CONF = '/root/.pip/pip.conf'
|
PIP_CONF = '/root/.pip/pip.conf'
|
||||||
|
|
||||||
|
"""List of packages charm should install
|
||||||
|
XXX The install hook is currently installing most packages ahead of
|
||||||
|
this because modules like keystoneclient are needed at load time
|
||||||
|
"""
|
||||||
packages = [
|
packages = [
|
||||||
'git', 'testrepository', 'subunit', 'python-nose', 'python-lxml',
|
'git', 'testrepository', 'subunit', 'python-nose', 'python-lxml',
|
||||||
'python-boto', 'python-junitxml', 'python-subunit',
|
'python-boto', 'python-junitxml', 'python-subunit',
|
||||||
@ -217,10 +257,14 @@ class TempestCharm(charm.OpenStackCharm):
|
|||||||
'python3-keystoneclient', 'python3-neutronclient',
|
'python3-keystoneclient', 'python3-neutronclient',
|
||||||
'python3-novaclient', 'python3-swiftclient',
|
'python3-novaclient', 'python3-swiftclient',
|
||||||
'python3-ceilometerclient', 'openvswitch-common', 'libffi-dev',
|
'python3-ceilometerclient', 'openvswitch-common', 'libffi-dev',
|
||||||
'libssl-dev', 'python-dev', 'python-cffi', 'tox'
|
'libssl-dev', 'python-dev', 'python-cffi'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
"""Use the Tempest specific adapters"""
|
||||||
adapters_class = TempestAdapters
|
adapters_class = TempestAdapters
|
||||||
|
"""Tempest has no running services so no services need restarting on
|
||||||
|
config file change
|
||||||
|
"""
|
||||||
restart_map = {
|
restart_map = {
|
||||||
TEMPEST_CONF: [],
|
TEMPEST_CONF: [],
|
||||||
PIP_CONF: [],
|
PIP_CONF: [],
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# {{ identity_admin.auth_url }}
|
|
||||||
# {{ identity_admin.creds }}
|
|
||||||
# {{ identity_admin.ec2_creds.access_token }}
|
# {{ identity_admin.ec2_creds.access_token }}
|
||||||
# {{ identity_admin.image_info }}
|
# {{ identity_admin.image_info }}
|
||||||
# {{ identity_admin.image_info.image_id }}
|
# {{ identity_admin.image_info.image_id }}
|
||||||
@ -39,8 +37,8 @@ login_url={{ dashboard_url }}/horizon/auth/login/
|
|||||||
[data_processing]
|
[data_processing]
|
||||||
[debug]
|
[debug]
|
||||||
[identity]
|
[identity]
|
||||||
uri=http://{{ identity_admin.creds.service_hostname }}:5000/v2.0
|
uri=http://{{ identity_admin.keystone_info.service_hostname }}:5000/v2.0
|
||||||
uri_v3=http://{{ identity_admin.creds.service_hostname }}:5000/v3
|
uri_v3=http://{{ identity_admin.keystone_info.service_hostname }}:5000/v3
|
||||||
admin_username=admin
|
admin_username=admin
|
||||||
admin_tenant_name=admin
|
admin_tenant_name=admin
|
||||||
admin_password=openstack
|
admin_password=openstack
|
||||||
|
Loading…
x
Reference in New Issue
Block a user