Sync charm-helpers for Ussuri/Focal release and version details
Also drop Disco test bundle now that it is EOL. Change-Id: I2d3628d6b10ff8a8917bf867a5ff3d488effe9b0
This commit is contained in:
parent
7ab272e220
commit
1d9afb103d
@ -484,3 +484,17 @@ def add_haproxy_checks(nrpe, unit_name):
|
|||||||
shortname='haproxy_queue',
|
shortname='haproxy_queue',
|
||||||
description='Check HAProxy queue depth {%s}' % unit_name,
|
description='Check HAProxy queue depth {%s}' % unit_name,
|
||||||
check_cmd='check_haproxy_queue_depth.sh')
|
check_cmd='check_haproxy_queue_depth.sh')
|
||||||
|
|
||||||
|
|
||||||
|
def remove_deprecated_check(nrpe, deprecated_services):
|
||||||
|
"""
|
||||||
|
Remove checks fro deprecated services in list
|
||||||
|
|
||||||
|
:param nrpe: NRPE object to remove check from
|
||||||
|
:type nrpe: NRPE
|
||||||
|
:param deprecated_services: List of deprecated services that are removed
|
||||||
|
:type deprecated_services: list
|
||||||
|
"""
|
||||||
|
for dep_svc in deprecated_services:
|
||||||
|
log('Deprecated service: {}'.format(dep_svc))
|
||||||
|
nrpe.remove_check(shortname=dep_svc)
|
||||||
|
@ -295,9 +295,11 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
|||||||
('bionic', 'cloud:bionic-rocky'): self.bionic_rocky,
|
('bionic', 'cloud:bionic-rocky'): self.bionic_rocky,
|
||||||
('bionic', 'cloud:bionic-stein'): self.bionic_stein,
|
('bionic', 'cloud:bionic-stein'): self.bionic_stein,
|
||||||
('bionic', 'cloud:bionic-train'): self.bionic_train,
|
('bionic', 'cloud:bionic-train'): self.bionic_train,
|
||||||
|
('bionic', 'cloud:bionic-ussuri'): self.bionic_ussuri,
|
||||||
('cosmic', None): self.cosmic_rocky,
|
('cosmic', None): self.cosmic_rocky,
|
||||||
('disco', None): self.disco_stein,
|
('disco', None): self.disco_stein,
|
||||||
('eoan', None): self.eoan_train,
|
('eoan', None): self.eoan_train,
|
||||||
|
('focal', None): self.focal_ussuri,
|
||||||
}
|
}
|
||||||
return releases[(self.series, self.openstack)]
|
return releases[(self.series, self.openstack)]
|
||||||
|
|
||||||
@ -316,6 +318,7 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
|||||||
('cosmic', 'rocky'),
|
('cosmic', 'rocky'),
|
||||||
('disco', 'stein'),
|
('disco', 'stein'),
|
||||||
('eoan', 'train'),
|
('eoan', 'train'),
|
||||||
|
('focal', 'ussuri'),
|
||||||
])
|
])
|
||||||
if self.openstack:
|
if self.openstack:
|
||||||
os_origin = self.openstack.split(':')[1]
|
os_origin = self.openstack.split(':')[1]
|
||||||
|
@ -62,6 +62,7 @@ OPENSTACK_RELEASES_PAIRS = [
|
|||||||
'bionic_rocky', 'cosmic_rocky',
|
'bionic_rocky', 'cosmic_rocky',
|
||||||
'bionic_stein', 'disco_stein',
|
'bionic_stein', 'disco_stein',
|
||||||
'bionic_train', 'eoan_train',
|
'bionic_train', 'eoan_train',
|
||||||
|
'bionic_ussuri', 'focal_ussuri',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,8 +244,8 @@ def validate_file_permissions(config):
|
|||||||
@audit(is_audit_type(AuditType.OpenStackSecurityGuide))
|
@audit(is_audit_type(AuditType.OpenStackSecurityGuide))
|
||||||
def validate_uses_keystone(audit_options):
|
def validate_uses_keystone(audit_options):
|
||||||
"""Validate that the service uses Keystone for authentication."""
|
"""Validate that the service uses Keystone for authentication."""
|
||||||
section = _config_section(audit_options, 'DEFAULT')
|
section = _config_section(audit_options, 'api') or _config_section(audit_options, 'DEFAULT')
|
||||||
assert section is not None, "Missing section 'DEFAULT'"
|
assert section is not None, "Missing section 'api / DEFAULT'"
|
||||||
assert section.get('auth_strategy') == "keystone", \
|
assert section.get('auth_strategy') == "keystone", \
|
||||||
"Application is not using Keystone"
|
"Application is not using Keystone"
|
||||||
|
|
||||||
|
@ -730,6 +730,10 @@ class AMQPContext(OSContextGenerator):
|
|||||||
if notification_format:
|
if notification_format:
|
||||||
ctxt['notification_format'] = notification_format
|
ctxt['notification_format'] = notification_format
|
||||||
|
|
||||||
|
notification_topics = conf.get('notification-topics', None)
|
||||||
|
if notification_topics:
|
||||||
|
ctxt['notification_topics'] = notification_topics
|
||||||
|
|
||||||
send_notifications_to_logs = conf.get('send-notifications-to-logs', None)
|
send_notifications_to_logs = conf.get('send-notifications-to-logs', None)
|
||||||
if send_notifications_to_logs:
|
if send_notifications_to_logs:
|
||||||
ctxt['send_notifications_to_logs'] = send_notifications_to_logs
|
ctxt['send_notifications_to_logs'] = send_notifications_to_logs
|
||||||
@ -2177,9 +2181,66 @@ class LogrotateContext(OSContextGenerator):
|
|||||||
class HostInfoContext(OSContextGenerator):
|
class HostInfoContext(OSContextGenerator):
|
||||||
"""Context to provide host information."""
|
"""Context to provide host information."""
|
||||||
|
|
||||||
|
def __init__(self, use_fqdn_hint_cb=None):
|
||||||
|
"""Initialize HostInfoContext
|
||||||
|
|
||||||
|
:param use_fqdn_hint_cb: Callback whose return value used to populate
|
||||||
|
`use_fqdn_hint`
|
||||||
|
:type use_fqdn_hint_cb: Callable[[], bool]
|
||||||
|
"""
|
||||||
|
# Store callback used to get hint for whether FQDN should be used
|
||||||
|
|
||||||
|
# Depending on the workload a charm manages, the use of FQDN vs.
|
||||||
|
# shortname may be a deploy-time decision, i.e. behaviour can not
|
||||||
|
# change on charm upgrade or post-deployment configuration change.
|
||||||
|
|
||||||
|
# The hint is passed on as a flag in the context to allow the decision
|
||||||
|
# to be made in the Jinja2 configuration template.
|
||||||
|
self.use_fqdn_hint_cb = use_fqdn_hint_cb
|
||||||
|
|
||||||
|
def _get_canonical_name(self, name=None):
|
||||||
|
"""Get the official FQDN of the host
|
||||||
|
|
||||||
|
The implementation of ``socket.getfqdn()`` in the standard Python
|
||||||
|
library does not exhaust all methods of getting the official name
|
||||||
|
of a host ref Python issue https://bugs.python.org/issue5004
|
||||||
|
|
||||||
|
This function mimics the behaviour of a call to ``hostname -f`` to
|
||||||
|
get the official FQDN but returns an empty string if it is
|
||||||
|
unsuccessful.
|
||||||
|
|
||||||
|
:param name: Shortname to get FQDN on
|
||||||
|
:type name: Optional[str]
|
||||||
|
:returns: The official FQDN for host or empty string ('')
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
name = name or socket.gethostname()
|
||||||
|
fqdn = ''
|
||||||
|
|
||||||
|
if six.PY2:
|
||||||
|
exc = socket.error
|
||||||
|
else:
|
||||||
|
exc = OSError
|
||||||
|
|
||||||
|
try:
|
||||||
|
addrs = socket.getaddrinfo(
|
||||||
|
name, None, 0, socket.SOCK_DGRAM, 0, socket.AI_CANONNAME)
|
||||||
|
except exc:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
for addr in addrs:
|
||||||
|
if addr[3]:
|
||||||
|
if '.' in addr[3]:
|
||||||
|
fqdn = addr[3]
|
||||||
|
break
|
||||||
|
return fqdn
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
|
name = socket.gethostname()
|
||||||
ctxt = {
|
ctxt = {
|
||||||
'host_fqdn': socket.getfqdn(),
|
'host_fqdn': self._get_canonical_name(name) or name,
|
||||||
'host': socket.gethostname(),
|
'host': name,
|
||||||
|
'use_fqdn_hint': (
|
||||||
|
self.use_fqdn_hint_cb() if self.use_fqdn_hint_cb else False)
|
||||||
}
|
}
|
||||||
return ctxt
|
return ctxt
|
||||||
|
@ -307,9 +307,9 @@ def maybe_do_policyd_overrides(openstack_release,
|
|||||||
blacklist_paths,
|
blacklist_paths,
|
||||||
user=_user,
|
user=_user,
|
||||||
group=_group)
|
group=_group)
|
||||||
if (os.path.isfile(_policy_success_file())
|
if (os.path.isfile(_policy_success_file()) and
|
||||||
and restart_handler is not None
|
restart_handler is not None and
|
||||||
and callable(restart_handler)):
|
callable(restart_handler)):
|
||||||
restart_handler()
|
restart_handler()
|
||||||
remove_policy_success_file()
|
remove_policy_success_file()
|
||||||
return
|
return
|
||||||
|
19
charmhelpers/contrib/openstack/templates/section-placement
Normal file
19
charmhelpers/contrib/openstack/templates/section-placement
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[placement]
|
||||||
|
{% if auth_host -%}
|
||||||
|
auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}
|
||||||
|
auth_type = password
|
||||||
|
{% if api_version == "3" -%}
|
||||||
|
project_domain_name = {{ admin_domain_name }}
|
||||||
|
user_domain_name = {{ admin_domain_name }}
|
||||||
|
{% else -%}
|
||||||
|
project_domain_name = default
|
||||||
|
user_domain_name = default
|
||||||
|
{% endif -%}
|
||||||
|
project_name = {{ admin_tenant_name }}
|
||||||
|
username = {{ admin_user }}
|
||||||
|
password = {{ admin_password }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if region -%}
|
||||||
|
os_region_name = {{ region }}
|
||||||
|
{% endif -%}
|
||||||
|
randomize_allocation_candidates = true
|
@ -50,9 +50,14 @@ from charmhelpers.core.hookenv import (
|
|||||||
hook_name,
|
hook_name,
|
||||||
application_version_set,
|
application_version_set,
|
||||||
cached,
|
cached,
|
||||||
|
leader_set,
|
||||||
|
leader_get,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.core.strutils import BasicStringComparator
|
from charmhelpers.core.strutils import (
|
||||||
|
BasicStringComparator,
|
||||||
|
bool_from_string,
|
||||||
|
)
|
||||||
|
|
||||||
from charmhelpers.contrib.storage.linux.lvm import (
|
from charmhelpers.contrib.storage.linux.lvm import (
|
||||||
deactivate_lvm_volume_group,
|
deactivate_lvm_volume_group,
|
||||||
@ -126,6 +131,7 @@ OPENSTACK_RELEASES = (
|
|||||||
'rocky',
|
'rocky',
|
||||||
'stein',
|
'stein',
|
||||||
'train',
|
'train',
|
||||||
|
'ussuri',
|
||||||
)
|
)
|
||||||
|
|
||||||
UBUNTU_OPENSTACK_RELEASE = OrderedDict([
|
UBUNTU_OPENSTACK_RELEASE = OrderedDict([
|
||||||
@ -146,6 +152,7 @@ UBUNTU_OPENSTACK_RELEASE = OrderedDict([
|
|||||||
('cosmic', 'rocky'),
|
('cosmic', 'rocky'),
|
||||||
('disco', 'stein'),
|
('disco', 'stein'),
|
||||||
('eoan', 'train'),
|
('eoan', 'train'),
|
||||||
|
('focal', 'ussuri'),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@ -167,6 +174,7 @@ OPENSTACK_CODENAMES = OrderedDict([
|
|||||||
('2018.2', 'rocky'),
|
('2018.2', 'rocky'),
|
||||||
('2019.1', 'stein'),
|
('2019.1', 'stein'),
|
||||||
('2019.2', 'train'),
|
('2019.2', 'train'),
|
||||||
|
('2020.1', 'ussuri'),
|
||||||
])
|
])
|
||||||
|
|
||||||
# The ugly duckling - must list releases oldest to newest
|
# The ugly duckling - must list releases oldest to newest
|
||||||
@ -205,6 +213,8 @@ SWIFT_CODENAMES = OrderedDict([
|
|||||||
['2.20.0', '2.21.0']),
|
['2.20.0', '2.21.0']),
|
||||||
('train',
|
('train',
|
||||||
['2.22.0', '2.23.0']),
|
['2.22.0', '2.23.0']),
|
||||||
|
('ussuri',
|
||||||
|
['2.24.0']),
|
||||||
])
|
])
|
||||||
|
|
||||||
# >= Liberty version->codename mapping
|
# >= Liberty version->codename mapping
|
||||||
@ -219,6 +229,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('18', 'rocky'),
|
('18', 'rocky'),
|
||||||
('19', 'stein'),
|
('19', 'stein'),
|
||||||
('20', 'train'),
|
('20', 'train'),
|
||||||
|
('21', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'neutron-common': OrderedDict([
|
'neutron-common': OrderedDict([
|
||||||
('7', 'liberty'),
|
('7', 'liberty'),
|
||||||
@ -230,6 +241,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('13', 'rocky'),
|
('13', 'rocky'),
|
||||||
('14', 'stein'),
|
('14', 'stein'),
|
||||||
('15', 'train'),
|
('15', 'train'),
|
||||||
|
('16', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'cinder-common': OrderedDict([
|
'cinder-common': OrderedDict([
|
||||||
('7', 'liberty'),
|
('7', 'liberty'),
|
||||||
@ -241,6 +253,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('13', 'rocky'),
|
('13', 'rocky'),
|
||||||
('14', 'stein'),
|
('14', 'stein'),
|
||||||
('15', 'train'),
|
('15', 'train'),
|
||||||
|
('16', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'keystone': OrderedDict([
|
'keystone': OrderedDict([
|
||||||
('8', 'liberty'),
|
('8', 'liberty'),
|
||||||
@ -252,6 +265,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('14', 'rocky'),
|
('14', 'rocky'),
|
||||||
('15', 'stein'),
|
('15', 'stein'),
|
||||||
('16', 'train'),
|
('16', 'train'),
|
||||||
|
('17', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'horizon-common': OrderedDict([
|
'horizon-common': OrderedDict([
|
||||||
('8', 'liberty'),
|
('8', 'liberty'),
|
||||||
@ -263,6 +277,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('14', 'rocky'),
|
('14', 'rocky'),
|
||||||
('15', 'stein'),
|
('15', 'stein'),
|
||||||
('16', 'train'),
|
('16', 'train'),
|
||||||
|
('17', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'ceilometer-common': OrderedDict([
|
'ceilometer-common': OrderedDict([
|
||||||
('5', 'liberty'),
|
('5', 'liberty'),
|
||||||
@ -274,6 +289,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('11', 'rocky'),
|
('11', 'rocky'),
|
||||||
('12', 'stein'),
|
('12', 'stein'),
|
||||||
('13', 'train'),
|
('13', 'train'),
|
||||||
|
('14', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'heat-common': OrderedDict([
|
'heat-common': OrderedDict([
|
||||||
('5', 'liberty'),
|
('5', 'liberty'),
|
||||||
@ -285,6 +301,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('11', 'rocky'),
|
('11', 'rocky'),
|
||||||
('12', 'stein'),
|
('12', 'stein'),
|
||||||
('13', 'train'),
|
('13', 'train'),
|
||||||
|
('14', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'glance-common': OrderedDict([
|
'glance-common': OrderedDict([
|
||||||
('11', 'liberty'),
|
('11', 'liberty'),
|
||||||
@ -296,6 +313,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('17', 'rocky'),
|
('17', 'rocky'),
|
||||||
('18', 'stein'),
|
('18', 'stein'),
|
||||||
('19', 'train'),
|
('19', 'train'),
|
||||||
|
('20', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
'openstack-dashboard': OrderedDict([
|
'openstack-dashboard': OrderedDict([
|
||||||
('8', 'liberty'),
|
('8', 'liberty'),
|
||||||
@ -307,6 +325,7 @@ PACKAGE_CODENAMES = {
|
|||||||
('14', 'rocky'),
|
('14', 'rocky'),
|
||||||
('15', 'stein'),
|
('15', 'stein'),
|
||||||
('16', 'train'),
|
('16', 'train'),
|
||||||
|
('17', 'ussuri'),
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +693,7 @@ def openstack_upgrade_available(package):
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
avail_vers = get_os_version_install_source(src)
|
avail_vers = get_os_version_install_source(src)
|
||||||
except:
|
except Exception:
|
||||||
avail_vers = cur_vers
|
avail_vers = cur_vers
|
||||||
apt.init()
|
apt.init()
|
||||||
return apt.version_compare(avail_vers, cur_vers) >= 1
|
return apt.version_compare(avail_vers, cur_vers) >= 1
|
||||||
@ -1868,3 +1887,28 @@ def series_upgrade_complete(resume_unit_helper=None, configs=None):
|
|||||||
configs.write_all()
|
configs.write_all()
|
||||||
if resume_unit_helper:
|
if resume_unit_helper:
|
||||||
resume_unit_helper(configs)
|
resume_unit_helper(configs)
|
||||||
|
|
||||||
|
|
||||||
|
def is_db_initialised():
|
||||||
|
"""Check leader storage to see if database has been initialised.
|
||||||
|
|
||||||
|
:returns: Whether DB has been initialised
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
|
db_initialised = None
|
||||||
|
if leader_get('db-initialised') is None:
|
||||||
|
juju_log(
|
||||||
|
'db-initialised key missing, assuming db is not initialised',
|
||||||
|
'DEBUG')
|
||||||
|
db_initialised = False
|
||||||
|
else:
|
||||||
|
db_initialised = bool_from_string(leader_get('db-initialised'))
|
||||||
|
juju_log('Database initialised: {}'.format(db_initialised), 'DEBUG')
|
||||||
|
return db_initialised
|
||||||
|
|
||||||
|
|
||||||
|
def set_db_initialised():
|
||||||
|
"""Add flag to leader storage to indicate database has been initialised.
|
||||||
|
"""
|
||||||
|
juju_log('Setting db-initialised to True', 'DEBUG')
|
||||||
|
leader_set({'db-initialised': True})
|
||||||
|
@ -182,6 +182,14 @@ CLOUD_ARCHIVE_POCKETS = {
|
|||||||
'train/proposed': 'bionic-proposed/train',
|
'train/proposed': 'bionic-proposed/train',
|
||||||
'bionic-train/proposed': 'bionic-proposed/train',
|
'bionic-train/proposed': 'bionic-proposed/train',
|
||||||
'bionic-proposed/train': 'bionic-proposed/train',
|
'bionic-proposed/train': 'bionic-proposed/train',
|
||||||
|
# Ussuri
|
||||||
|
'ussuri': 'bionic-updates/ussuri',
|
||||||
|
'bionic-ussuri': 'bionic-updates/ussuri',
|
||||||
|
'bionic-ussuri/updates': 'bionic-updates/ussuri',
|
||||||
|
'bionic-updates/ussuri': 'bionic-updates/ussuri',
|
||||||
|
'ussuri/proposed': 'bionic-proposed/ussuri',
|
||||||
|
'bionic-ussuri/proposed': 'bionic-proposed/ussuri',
|
||||||
|
'bionic-proposed/ussuri': 'bionic-proposed/ussuri',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
series: disco
|
|
||||||
applications:
|
|
||||||
swift-proxy:
|
|
||||||
charm: cs:~openstack-charmers-next/swift-proxy
|
|
||||||
series: disco
|
|
||||||
num_units: 1
|
|
||||||
options:
|
|
||||||
zone-assignment: manual
|
|
||||||
replicas: 1
|
|
||||||
swift-hash: fdfef9d4-8b06-11e2-8ac0-531c923c8fae
|
|
||||||
percona-cluster:
|
|
||||||
charm: cs:~openstack-charmers-next/percona-cluster
|
|
||||||
num_units: 1
|
|
||||||
options:
|
|
||||||
dataset-size: 25%
|
|
||||||
max-connections: 1000
|
|
||||||
keystone:
|
|
||||||
expose: True
|
|
||||||
charm: cs:~openstack-charmers-next/keystone
|
|
||||||
num_units: 1
|
|
||||||
glance:
|
|
||||||
expose: True
|
|
||||||
charm: cs:~openstack-charmers-next/glance
|
|
||||||
num_units: 1
|
|
||||||
swift-storage:
|
|
||||||
charm: swift-storage
|
|
||||||
num_units: 1
|
|
||||||
storage:
|
|
||||||
block-devices: 'cinder,10G'
|
|
||||||
options:
|
|
||||||
zone: 1
|
|
||||||
relations:
|
|
||||||
- - keystone:shared-db
|
|
||||||
- percona-cluster:shared-db
|
|
||||||
- - glance:shared-db
|
|
||||||
- percona-cluster:shared-db
|
|
||||||
- - glance:identity-service
|
|
||||||
- keystone:identity-service
|
|
||||||
- - swift-proxy:identity-service
|
|
||||||
- keystone:identity-service
|
|
||||||
- - swift-storage:swift-storage
|
|
||||||
- swift-proxy:swift-storage
|
|
||||||
- - glance:object-store
|
|
||||||
- swift-proxy:object-store
|
|
@ -9,14 +9,11 @@ gate_bundles:
|
|||||||
- xenial-ocata
|
- xenial-ocata
|
||||||
- xenial-mitaka
|
- xenial-mitaka
|
||||||
- trusty-mitaka
|
- trusty-mitaka
|
||||||
- disco-stein
|
|
||||||
- bionic-train-gr:
|
- bionic-train-gr:
|
||||||
- swift_gr_region1: bionic-train-gr-r1
|
- swift_gr_region1: bionic-train-gr-r1
|
||||||
- swift_gr_region2: bionic-train-gr-r2
|
- swift_gr_region2: bionic-train-gr-r2
|
||||||
smoke_bundles:
|
smoke_bundles:
|
||||||
- bionic-train
|
- bionic-train
|
||||||
dev_bundles:
|
|
||||||
- disco-stein
|
|
||||||
tests:
|
tests:
|
||||||
- zaza.openstack.charm_tests.swift.tests.SwiftImageCreateTest
|
- zaza.openstack.charm_tests.swift.tests.SwiftImageCreateTest
|
||||||
- zaza.openstack.charm_tests.swift.tests.SwiftStorageTests
|
- zaza.openstack.charm_tests.swift.tests.SwiftStorageTests
|
||||||
|
Loading…
Reference in New Issue
Block a user