No reformat
Do not reformat devices. A subsequent change will be necessary to account for conditions where a reformat is still desired, such as a set of blocking states and user-driven actions. Partial-bug: #1698154 Depends-On: I90a866aa138d18e4242783c42d4c7c587f696d7d Change-Id: I3a41ab38e7a1679cf4f5380a7cc56556da3aaf2b
This commit is contained in:
parent
2c3eae272f
commit
22ce311b0b
|
@ -31,7 +31,6 @@ import ceph.utils
|
||||||
def add_device(request, device_path, bucket=None):
|
def add_device(request, device_path, bucket=None):
|
||||||
ceph.utils.osdize(dev, hookenv.config('osd-format'),
|
ceph.utils.osdize(dev, hookenv.config('osd-format'),
|
||||||
ceph_hooks.get_journal_devices(),
|
ceph_hooks.get_journal_devices(),
|
||||||
hookenv.config('osd-reformat'),
|
|
||||||
hookenv.config('ignore-device-errors'),
|
hookenv.config('ignore-device-errors'),
|
||||||
hookenv.config('osd-encrypt'),
|
hookenv.config('osd-encrypt'),
|
||||||
hookenv.config('bluestore'))
|
hookenv.config('bluestore'))
|
||||||
|
|
11
config.yaml
11
config.yaml
|
@ -127,17 +127,6 @@ options:
|
||||||
.
|
.
|
||||||
Note that despite bluestore being the default for Ceph Luminous, if this
|
Note that despite bluestore being the default for Ceph Luminous, if this
|
||||||
option is False, OSDs will still use filestore.
|
option is False, OSDs will still use filestore.
|
||||||
osd-reformat:
|
|
||||||
type: boolean
|
|
||||||
default: False
|
|
||||||
description: |
|
|
||||||
By default, the charm will not re-format a device that already looks
|
|
||||||
as if it might be an OSD device. This is a safeguard to try to
|
|
||||||
prevent data loss.
|
|
||||||
.
|
|
||||||
Enabling this option forces a reformat of any OSD devices found which
|
|
||||||
have not been processed by the unit previously or are not already
|
|
||||||
mounted.
|
|
||||||
osd-encrypt:
|
osd-encrypt:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: False
|
default: False
|
||||||
|
|
|
@ -451,7 +451,7 @@ def prepare_disks_and_activate():
|
||||||
emit_cephconf()
|
emit_cephconf()
|
||||||
for dev in get_devices():
|
for dev in get_devices():
|
||||||
ceph.osdize(dev, config('osd-format'),
|
ceph.osdize(dev, config('osd-format'),
|
||||||
osd_journal, config('osd-reformat'),
|
osd_journal,
|
||||||
config('ignore-device-errors'),
|
config('ignore-device-errors'),
|
||||||
config('osd-encrypt'),
|
config('osd-encrypt'),
|
||||||
config('bluestore'),
|
config('bluestore'),
|
||||||
|
@ -499,13 +499,6 @@ def get_conf(name):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def reformat_osd():
|
|
||||||
if config('osd-reformat'):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_devices():
|
def get_devices():
|
||||||
devices = []
|
devices = []
|
||||||
if config('osd-devices'):
|
if config('osd-devices'):
|
||||||
|
|
|
@ -223,6 +223,11 @@ def https():
|
||||||
return True
|
return True
|
||||||
if config_get('ssl_cert') and config_get('ssl_key'):
|
if config_get('ssl_cert') and config_get('ssl_key'):
|
||||||
return True
|
return True
|
||||||
|
for r_id in relation_ids('certificates'):
|
||||||
|
for unit in relation_list(r_id):
|
||||||
|
ca = relation_get('ca', rid=r_id, unit=unit)
|
||||||
|
if ca:
|
||||||
|
return True
|
||||||
for r_id in relation_ids('identity-service'):
|
for r_id in relation_ids('identity-service'):
|
||||||
for unit in relation_list(r_id):
|
for unit in relation_list(r_id):
|
||||||
# TODO - needs fixing for new helper as ssl_cert/key suffixes with CN
|
# TODO - needs fixing for new helper as ssl_cert/key suffixes with CN
|
||||||
|
|
|
@ -544,7 +544,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
return ep
|
return ep
|
||||||
|
|
||||||
def get_default_keystone_session(self, keystone_sentry,
|
def get_default_keystone_session(self, keystone_sentry,
|
||||||
openstack_release=None):
|
openstack_release=None, api_version=2):
|
||||||
"""Return a keystone session object and client object assuming standard
|
"""Return a keystone session object and client object assuming standard
|
||||||
default settings
|
default settings
|
||||||
|
|
||||||
|
@ -559,12 +559,12 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
eyc
|
eyc
|
||||||
"""
|
"""
|
||||||
self.log.debug('Authenticating keystone admin...')
|
self.log.debug('Authenticating keystone admin...')
|
||||||
api_version = 2
|
|
||||||
client_class = keystone_client.Client
|
|
||||||
# 11 => xenial_queens
|
# 11 => xenial_queens
|
||||||
if openstack_release and openstack_release >= 11:
|
if api_version == 3 or (openstack_release and openstack_release >= 11):
|
||||||
api_version = 3
|
|
||||||
client_class = keystone_client_v3.Client
|
client_class = keystone_client_v3.Client
|
||||||
|
api_version = 3
|
||||||
|
else:
|
||||||
|
client_class = keystone_client.Client
|
||||||
keystone_ip = keystone_sentry.info['public-address']
|
keystone_ip = keystone_sentry.info['public-address']
|
||||||
session, auth = self.get_keystone_session(
|
session, auth = self.get_keystone_session(
|
||||||
keystone_ip,
|
keystone_ip,
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
# Copyright 2014-2018 Canonical Limited.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Common python helper functions used for OpenStack charm certificats.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
from charmhelpers.contrib.network.ip import (
|
||||||
|
get_hostname,
|
||||||
|
resolve_network_cidr,
|
||||||
|
)
|
||||||
|
from charmhelpers.core.hookenv import (
|
||||||
|
local_unit,
|
||||||
|
network_get_primary_address,
|
||||||
|
config,
|
||||||
|
relation_get,
|
||||||
|
unit_get,
|
||||||
|
NoNetworkBinding,
|
||||||
|
log,
|
||||||
|
WARNING,
|
||||||
|
)
|
||||||
|
from charmhelpers.contrib.openstack.ip import (
|
||||||
|
ADMIN,
|
||||||
|
resolve_address,
|
||||||
|
get_vip_in_network,
|
||||||
|
INTERNAL,
|
||||||
|
PUBLIC,
|
||||||
|
ADDRESS_MAP)
|
||||||
|
|
||||||
|
from charmhelpers.core.host import (
|
||||||
|
mkdir,
|
||||||
|
write_file,
|
||||||
|
)
|
||||||
|
|
||||||
|
from charmhelpers.contrib.hahelpers.apache import (
|
||||||
|
install_ca_cert
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CertRequest(object):
|
||||||
|
|
||||||
|
"""Create a request for certificates to be generated
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, json_encode=True):
|
||||||
|
self.entries = []
|
||||||
|
self.hostname_entry = None
|
||||||
|
self.json_encode = json_encode
|
||||||
|
|
||||||
|
def add_entry(self, net_type, cn, addresses):
|
||||||
|
"""Add a request to the batch
|
||||||
|
|
||||||
|
:param net_type: str netwrok space name request is for
|
||||||
|
:param cn: str Canonical Name for certificate
|
||||||
|
:param addresses: [] List of addresses to be used as SANs
|
||||||
|
"""
|
||||||
|
self.entries.append({
|
||||||
|
'cn': cn,
|
||||||
|
'addresses': addresses})
|
||||||
|
|
||||||
|
def add_hostname_cn(self):
|
||||||
|
"""Add a request for the hostname of the machine"""
|
||||||
|
ip = unit_get('private-address')
|
||||||
|
addresses = [ip]
|
||||||
|
# If a vip is being used without os-hostname config or
|
||||||
|
# network spaces then we need to ensure the local units
|
||||||
|
# cert has the approriate vip in the SAN list
|
||||||
|
vip = get_vip_in_network(resolve_network_cidr(ip))
|
||||||
|
if vip:
|
||||||
|
addresses.append(vip)
|
||||||
|
self.hostname_entry = {
|
||||||
|
'cn': get_hostname(ip),
|
||||||
|
'addresses': addresses}
|
||||||
|
|
||||||
|
def add_hostname_cn_ip(self, addresses):
|
||||||
|
"""Add an address to the SAN list for the hostname request
|
||||||
|
|
||||||
|
:param addr: [] List of address to be added
|
||||||
|
"""
|
||||||
|
for addr in addresses:
|
||||||
|
if addr not in self.hostname_entry['addresses']:
|
||||||
|
self.hostname_entry['addresses'].append(addr)
|
||||||
|
|
||||||
|
def get_request(self):
|
||||||
|
"""Generate request from the batched up entries
|
||||||
|
|
||||||
|
"""
|
||||||
|
if self.hostname_entry:
|
||||||
|
self.entries.append(self.hostname_entry)
|
||||||
|
request = {}
|
||||||
|
for entry in self.entries:
|
||||||
|
sans = sorted(list(set(entry['addresses'])))
|
||||||
|
request[entry['cn']] = {'sans': sans}
|
||||||
|
if self.json_encode:
|
||||||
|
return {'cert_requests': json.dumps(request, sort_keys=True)}
|
||||||
|
else:
|
||||||
|
return {'cert_requests': request}
|
||||||
|
|
||||||
|
|
||||||
|
def get_certificate_request(json_encode=True):
|
||||||
|
"""Generate a certificatee requests based on the network confioguration
|
||||||
|
|
||||||
|
"""
|
||||||
|
req = CertRequest(json_encode=json_encode)
|
||||||
|
req.add_hostname_cn()
|
||||||
|
# Add os-hostname entries
|
||||||
|
for net_type in [INTERNAL, ADMIN, PUBLIC]:
|
||||||
|
net_config = config(ADDRESS_MAP[net_type]['override'])
|
||||||
|
try:
|
||||||
|
net_addr = resolve_address(endpoint_type=net_type)
|
||||||
|
ip = network_get_primary_address(
|
||||||
|
ADDRESS_MAP[net_type]['binding'])
|
||||||
|
addresses = [net_addr, ip]
|
||||||
|
vip = get_vip_in_network(resolve_network_cidr(ip))
|
||||||
|
if vip:
|
||||||
|
addresses.append(vip)
|
||||||
|
if net_config:
|
||||||
|
req.add_entry(
|
||||||
|
net_type,
|
||||||
|
net_config,
|
||||||
|
addresses)
|
||||||
|
else:
|
||||||
|
# There is network address with no corresponding hostname.
|
||||||
|
# Add the ip to the hostname cert to allow for this.
|
||||||
|
req.add_hostname_cn_ip(addresses)
|
||||||
|
except NoNetworkBinding:
|
||||||
|
log("Skipping request for certificate for ip in {} space, no "
|
||||||
|
"local address found".format(net_type), WARNING)
|
||||||
|
return req.get_request()
|
||||||
|
|
||||||
|
|
||||||
|
def create_ip_cert_links(ssl_dir, custom_hostname_link=None):
|
||||||
|
"""Create symlinks for SAN records
|
||||||
|
|
||||||
|
:param ssl_dir: str Directory to create symlinks in
|
||||||
|
:param custom_hostname_link: str Additional link to be created
|
||||||
|
"""
|
||||||
|
hostname = get_hostname(unit_get('private-address'))
|
||||||
|
hostname_cert = os.path.join(
|
||||||
|
ssl_dir,
|
||||||
|
'cert_{}'.format(hostname))
|
||||||
|
hostname_key = os.path.join(
|
||||||
|
ssl_dir,
|
||||||
|
'key_{}'.format(hostname))
|
||||||
|
# Add links to hostname cert, used if os-hostname vars not set
|
||||||
|
for net_type in [INTERNAL, ADMIN, PUBLIC]:
|
||||||
|
try:
|
||||||
|
addr = resolve_address(endpoint_type=net_type)
|
||||||
|
cert = os.path.join(ssl_dir, 'cert_{}'.format(addr))
|
||||||
|
key = os.path.join(ssl_dir, 'key_{}'.format(addr))
|
||||||
|
if os.path.isfile(hostname_cert) and not os.path.isfile(cert):
|
||||||
|
os.symlink(hostname_cert, cert)
|
||||||
|
os.symlink(hostname_key, key)
|
||||||
|
except NoNetworkBinding:
|
||||||
|
log("Skipping creating cert symlink for ip in {} space, no "
|
||||||
|
"local address found".format(net_type), WARNING)
|
||||||
|
if custom_hostname_link:
|
||||||
|
custom_cert = os.path.join(
|
||||||
|
ssl_dir,
|
||||||
|
'cert_{}'.format(custom_hostname_link))
|
||||||
|
custom_key = os.path.join(
|
||||||
|
ssl_dir,
|
||||||
|
'key_{}'.format(custom_hostname_link))
|
||||||
|
if os.path.isfile(hostname_cert) and not os.path.isfile(custom_cert):
|
||||||
|
os.symlink(hostname_cert, custom_cert)
|
||||||
|
os.symlink(hostname_key, custom_key)
|
||||||
|
|
||||||
|
|
||||||
|
def install_certs(ssl_dir, certs, chain=None):
|
||||||
|
"""Install the certs passed into the ssl dir and append the chain if
|
||||||
|
provided.
|
||||||
|
|
||||||
|
:param ssl_dir: str Directory to create symlinks in
|
||||||
|
:param certs: {} {'cn': {'cert': 'CERT', 'key': 'KEY'}}
|
||||||
|
:param chain: str Chain to be appended to certs
|
||||||
|
"""
|
||||||
|
for cn, bundle in certs.items():
|
||||||
|
cert_filename = 'cert_{}'.format(cn)
|
||||||
|
key_filename = 'key_{}'.format(cn)
|
||||||
|
cert_data = bundle['cert']
|
||||||
|
if chain:
|
||||||
|
# Append chain file so that clients that trust the root CA will
|
||||||
|
# trust certs signed by an intermediate in the chain
|
||||||
|
cert_data = cert_data + chain
|
||||||
|
write_file(
|
||||||
|
path=os.path.join(ssl_dir, cert_filename),
|
||||||
|
content=cert_data, perms=0o640)
|
||||||
|
write_file(
|
||||||
|
path=os.path.join(ssl_dir, key_filename),
|
||||||
|
content=bundle['key'], perms=0o640)
|
||||||
|
|
||||||
|
|
||||||
|
def process_certificates(service_name, relation_id, unit,
|
||||||
|
custom_hostname_link=None):
|
||||||
|
"""Process the certificates supplied down the relation
|
||||||
|
|
||||||
|
:param service_name: str Name of service the certifcates are for.
|
||||||
|
:param relation_id: str Relation id providing the certs
|
||||||
|
:param unit: str Unit providing the certs
|
||||||
|
:param custom_hostname_link: str Name of custom link to create
|
||||||
|
"""
|
||||||
|
data = relation_get(rid=relation_id, unit=unit)
|
||||||
|
ssl_dir = os.path.join('/etc/apache2/ssl/', service_name)
|
||||||
|
mkdir(path=ssl_dir)
|
||||||
|
name = local_unit().replace('/', '_')
|
||||||
|
certs = data.get('{}.processed_requests'.format(name))
|
||||||
|
chain = data.get('chain')
|
||||||
|
ca = data.get('ca')
|
||||||
|
if certs:
|
||||||
|
certs = json.loads(certs)
|
||||||
|
install_ca_cert(ca.encode())
|
||||||
|
install_certs(ssl_dir, certs, chain)
|
||||||
|
create_ip_cert_links(
|
||||||
|
ssl_dir,
|
||||||
|
custom_hostname_link=custom_hostname_link)
|
|
@ -789,17 +789,18 @@ class ApacheSSLContext(OSContextGenerator):
|
||||||
ssl_dir = os.path.join('/etc/apache2/ssl/', self.service_namespace)
|
ssl_dir = os.path.join('/etc/apache2/ssl/', self.service_namespace)
|
||||||
mkdir(path=ssl_dir)
|
mkdir(path=ssl_dir)
|
||||||
cert, key = get_cert(cn)
|
cert, key = get_cert(cn)
|
||||||
if cn:
|
if cert and key:
|
||||||
cert_filename = 'cert_{}'.format(cn)
|
if cn:
|
||||||
key_filename = 'key_{}'.format(cn)
|
cert_filename = 'cert_{}'.format(cn)
|
||||||
else:
|
key_filename = 'key_{}'.format(cn)
|
||||||
cert_filename = 'cert'
|
else:
|
||||||
key_filename = 'key'
|
cert_filename = 'cert'
|
||||||
|
key_filename = 'key'
|
||||||
|
|
||||||
write_file(path=os.path.join(ssl_dir, cert_filename),
|
write_file(path=os.path.join(ssl_dir, cert_filename),
|
||||||
content=b64decode(cert), perms=0o640)
|
content=b64decode(cert), perms=0o640)
|
||||||
write_file(path=os.path.join(ssl_dir, key_filename),
|
write_file(path=os.path.join(ssl_dir, key_filename),
|
||||||
content=b64decode(key), perms=0o640)
|
content=b64decode(key), perms=0o640)
|
||||||
|
|
||||||
def configure_ca(self):
|
def configure_ca(self):
|
||||||
ca_cert = get_ca_cert()
|
ca_cert = get_ca_cert()
|
||||||
|
@ -871,23 +872,31 @@ class ApacheSSLContext(OSContextGenerator):
|
||||||
if not self.external_ports or not https():
|
if not self.external_ports or not https():
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
self.configure_ca()
|
use_keystone_ca = True
|
||||||
|
for rid in relation_ids('certificates'):
|
||||||
|
if related_units(rid):
|
||||||
|
use_keystone_ca = False
|
||||||
|
|
||||||
|
if use_keystone_ca:
|
||||||
|
self.configure_ca()
|
||||||
|
|
||||||
self.enable_modules()
|
self.enable_modules()
|
||||||
|
|
||||||
ctxt = {'namespace': self.service_namespace,
|
ctxt = {'namespace': self.service_namespace,
|
||||||
'endpoints': [],
|
'endpoints': [],
|
||||||
'ext_ports': []}
|
'ext_ports': []}
|
||||||
|
|
||||||
cns = self.canonical_names()
|
if use_keystone_ca:
|
||||||
if cns:
|
cns = self.canonical_names()
|
||||||
for cn in cns:
|
if cns:
|
||||||
self.configure_cert(cn)
|
for cn in cns:
|
||||||
else:
|
self.configure_cert(cn)
|
||||||
# Expect cert/key provided in config (currently assumed that ca
|
else:
|
||||||
# uses ip for cn)
|
# Expect cert/key provided in config (currently assumed that ca
|
||||||
for net_type in (INTERNAL, ADMIN, PUBLIC):
|
# uses ip for cn)
|
||||||
cn = resolve_address(endpoint_type=net_type)
|
for net_type in (INTERNAL, ADMIN, PUBLIC):
|
||||||
self.configure_cert(cn)
|
cn = resolve_address(endpoint_type=net_type)
|
||||||
|
self.configure_cert(cn)
|
||||||
|
|
||||||
addresses = self.get_network_addresses()
|
addresses = self.get_network_addresses()
|
||||||
for address, endpoint in addresses:
|
for address, endpoint in addresses:
|
||||||
|
|
|
@ -184,3 +184,13 @@ def resolve_address(endpoint_type=PUBLIC, override=True):
|
||||||
"clustered=%s)" % (net_type, clustered))
|
"clustered=%s)" % (net_type, clustered))
|
||||||
|
|
||||||
return resolved_address
|
return resolved_address
|
||||||
|
|
||||||
|
|
||||||
|
def get_vip_in_network(network):
|
||||||
|
matching_vip = None
|
||||||
|
vips = config('vip')
|
||||||
|
if vips:
|
||||||
|
for vip in vips.split():
|
||||||
|
if is_address_in_network(network, vip):
|
||||||
|
matching_vip = vip
|
||||||
|
return matching_vip
|
||||||
|
|
|
@ -972,6 +972,13 @@ def application_version_set(version):
|
||||||
log("Application Version: {}".format(version))
|
log("Application Version: {}".format(version))
|
||||||
|
|
||||||
|
|
||||||
|
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
|
||||||
|
def goal_state():
|
||||||
|
"""Juju goal state values"""
|
||||||
|
cmd = ['goal-state', '--format=json']
|
||||||
|
return json.loads(subprocess.check_output(cmd).decode('UTF-8'))
|
||||||
|
|
||||||
|
|
||||||
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
|
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
|
||||||
def is_leader():
|
def is_leader():
|
||||||
"""Does the current unit hold the juju leadership
|
"""Does the current unit hold the juju leadership
|
||||||
|
|
|
@ -1366,20 +1366,18 @@ def get_devices(name):
|
||||||
return set(devices)
|
return set(devices)
|
||||||
|
|
||||||
|
|
||||||
def osdize(dev, osd_format, osd_journal, reformat_osd=False,
|
def osdize(dev, osd_format, osd_journal, ignore_errors=False, encrypt=False,
|
||||||
ignore_errors=False, encrypt=False, bluestore=False,
|
bluestore=False, key_manager=CEPH_KEY_MANAGER):
|
||||||
key_manager=CEPH_KEY_MANAGER):
|
|
||||||
if dev.startswith('/dev'):
|
if dev.startswith('/dev'):
|
||||||
osdize_dev(dev, osd_format, osd_journal,
|
osdize_dev(dev, osd_format, osd_journal,
|
||||||
reformat_osd, ignore_errors, encrypt,
|
ignore_errors, encrypt,
|
||||||
bluestore, key_manager)
|
bluestore, key_manager)
|
||||||
else:
|
else:
|
||||||
osdize_dir(dev, encrypt, bluestore)
|
osdize_dir(dev, encrypt, bluestore)
|
||||||
|
|
||||||
|
|
||||||
def osdize_dev(dev, osd_format, osd_journal, reformat_osd=False,
|
def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False,
|
||||||
ignore_errors=False, encrypt=False, bluestore=False,
|
encrypt=False, bluestore=False, key_manager=CEPH_KEY_MANAGER):
|
||||||
key_manager=CEPH_KEY_MANAGER):
|
|
||||||
"""
|
"""
|
||||||
Prepare a block device for use as a Ceph OSD
|
Prepare a block device for use as a Ceph OSD
|
||||||
|
|
||||||
|
@ -1389,8 +1387,6 @@ def osdize_dev(dev, osd_format, osd_journal, reformat_osd=False,
|
||||||
:param: dev: Full path to block device to use
|
:param: dev: Full path to block device to use
|
||||||
:param: osd_format: Format for OSD filesystem
|
:param: osd_format: Format for OSD filesystem
|
||||||
:param: osd_journal: List of block devices to use for OSD journals
|
:param: osd_journal: List of block devices to use for OSD journals
|
||||||
:param: reformat_osd: Reformat devices that are not currently in use
|
|
||||||
which have been used previously
|
|
||||||
:param: ignore_errors: Don't fail in the event of any errors during
|
:param: ignore_errors: Don't fail in the event of any errors during
|
||||||
processing
|
processing
|
||||||
:param: encrypt: Encrypt block devices using 'key_manager'
|
:param: encrypt: Encrypt block devices using 'key_manager'
|
||||||
|
@ -1418,7 +1414,7 @@ def osdize_dev(dev, osd_format, osd_journal, reformat_osd=False,
|
||||||
log('Path {} is not a block device - bailing'.format(dev))
|
log('Path {} is not a block device - bailing'.format(dev))
|
||||||
return
|
return
|
||||||
|
|
||||||
if is_osd_disk(dev) and not reformat_osd:
|
if is_osd_disk(dev):
|
||||||
log('Looks like {} is already an'
|
log('Looks like {} is already an'
|
||||||
' OSD data or journal, skipping.'.format(dev))
|
' OSD data or journal, skipping.'.format(dev))
|
||||||
return
|
return
|
||||||
|
@ -1432,9 +1428,6 @@ def osdize_dev(dev, osd_format, osd_journal, reformat_osd=False,
|
||||||
' skipping.'.format(dev))
|
' skipping.'.format(dev))
|
||||||
return
|
return
|
||||||
|
|
||||||
if reformat_osd:
|
|
||||||
zap_disk(dev)
|
|
||||||
|
|
||||||
if cmp_pkgrevno('ceph', '12.2.4') >= 0:
|
if cmp_pkgrevno('ceph', '12.2.4') >= 0:
|
||||||
cmd = _ceph_volume(dev,
|
cmd = _ceph_volume(dev,
|
||||||
osd_journal,
|
osd_journal,
|
||||||
|
|
|
@ -63,7 +63,10 @@ class CephOsdBasicDeployment(OpenStackAmuletDeployment):
|
||||||
and the rest of the service are from lp branches that are
|
and the rest of the service are from lp branches that are
|
||||||
compatible with the local charm (e.g. stable or next).
|
compatible with the local charm (e.g. stable or next).
|
||||||
"""
|
"""
|
||||||
this_service = {'name': 'ceph-osd', 'units': 3}
|
this_service = {
|
||||||
|
'name': 'ceph-osd',
|
||||||
|
'units': 3,
|
||||||
|
'storage': {'osd-devices': 'cinder,10G'}}
|
||||||
other_services = [
|
other_services = [
|
||||||
{'name': 'ceph-mon', 'units': 3},
|
{'name': 'ceph-mon', 'units': 3},
|
||||||
{'name': 'percona-cluster'},
|
{'name': 'percona-cluster'},
|
||||||
|
@ -118,9 +121,7 @@ class CephOsdBasicDeployment(OpenStackAmuletDeployment):
|
||||||
# Include a non-existent device as osd-devices is a whitelist,
|
# Include a non-existent device as osd-devices is a whitelist,
|
||||||
# and this will catch cases where proposals attempt to change that.
|
# and this will catch cases where proposals attempt to change that.
|
||||||
ceph_osd_config = {
|
ceph_osd_config = {
|
||||||
'osd-reformat': True,
|
'osd-devices': '/srv/ceph /dev/test-non-existent'
|
||||||
'ephemeral-unmount': '/mnt',
|
|
||||||
'osd-devices': '/dev/vdb /srv/ceph /dev/test-non-existent'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configs = {'keystone': keystone_config,
|
configs = {'keystone': keystone_config,
|
||||||
|
|
|
@ -50,7 +50,8 @@ class AmuletDeployment(object):
|
||||||
this_service['units'] = 1
|
this_service['units'] = 1
|
||||||
|
|
||||||
self.d.add(this_service['name'], units=this_service['units'],
|
self.d.add(this_service['name'], units=this_service['units'],
|
||||||
constraints=this_service.get('constraints'))
|
constraints=this_service.get('constraints'),
|
||||||
|
storage=this_service.get('storage'))
|
||||||
|
|
||||||
for svc in other_services:
|
for svc in other_services:
|
||||||
if 'location' in svc:
|
if 'location' in svc:
|
||||||
|
@ -64,7 +65,8 @@ class AmuletDeployment(object):
|
||||||
svc['units'] = 1
|
svc['units'] = 1
|
||||||
|
|
||||||
self.d.add(svc['name'], charm=branch_location, units=svc['units'],
|
self.d.add(svc['name'], charm=branch_location, units=svc['units'],
|
||||||
constraints=svc.get('constraints'))
|
constraints=svc.get('constraints'),
|
||||||
|
storage=svc.get('storage'))
|
||||||
|
|
||||||
def _add_relations(self, relations):
|
def _add_relations(self, relations):
|
||||||
"""Add all of the relations for the services."""
|
"""Add all of the relations for the services."""
|
||||||
|
|
|
@ -544,7 +544,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
return ep
|
return ep
|
||||||
|
|
||||||
def get_default_keystone_session(self, keystone_sentry,
|
def get_default_keystone_session(self, keystone_sentry,
|
||||||
openstack_release=None):
|
openstack_release=None, api_version=2):
|
||||||
"""Return a keystone session object and client object assuming standard
|
"""Return a keystone session object and client object assuming standard
|
||||||
default settings
|
default settings
|
||||||
|
|
||||||
|
@ -559,12 +559,12 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||||
eyc
|
eyc
|
||||||
"""
|
"""
|
||||||
self.log.debug('Authenticating keystone admin...')
|
self.log.debug('Authenticating keystone admin...')
|
||||||
api_version = 2
|
|
||||||
client_class = keystone_client.Client
|
|
||||||
# 11 => xenial_queens
|
# 11 => xenial_queens
|
||||||
if openstack_release and openstack_release >= 11:
|
if api_version == 3 or (openstack_release and openstack_release >= 11):
|
||||||
api_version = 3
|
|
||||||
client_class = keystone_client_v3.Client
|
client_class = keystone_client_v3.Client
|
||||||
|
api_version = 3
|
||||||
|
else:
|
||||||
|
client_class = keystone_client.Client
|
||||||
keystone_ip = keystone_sentry.info['public-address']
|
keystone_ip = keystone_sentry.info['public-address']
|
||||||
session, auth = self.get_keystone_session(
|
session, auth = self.get_keystone_session(
|
||||||
keystone_ip,
|
keystone_ip,
|
||||||
|
|
|
@ -972,6 +972,13 @@ def application_version_set(version):
|
||||||
log("Application Version: {}".format(version))
|
log("Application Version: {}".format(version))
|
||||||
|
|
||||||
|
|
||||||
|
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
|
||||||
|
def goal_state():
|
||||||
|
"""Juju goal state values"""
|
||||||
|
cmd = ['goal-state', '--format=json']
|
||||||
|
return json.loads(subprocess.check_output(cmd).decode('UTF-8'))
|
||||||
|
|
||||||
|
|
||||||
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
|
@translate_exc(from_exc=OSError, to_exc=NotImplementedError)
|
||||||
def is_leader():
|
def is_leader():
|
||||||
"""Does the current unit hold the juju leadership
|
"""Does the current unit hold the juju leadership
|
||||||
|
|
Loading…
Reference in New Issue