Merge "Add support for ceph-mon bootstrap"
This commit is contained in:
commit
8500fd6134
|
@ -9,3 +9,4 @@ bin
|
|||
*.pyc
|
||||
.unit-state.db
|
||||
func-results.json
|
||||
.pydevproject
|
||||
|
|
12
README.md
12
README.md
|
@ -1,11 +1,21 @@
|
|||
# Overview
|
||||
|
||||
---
|
||||
**NOTE**
|
||||
|
||||
This charm is deprecated and will not receive updates past February 2018.
|
||||
|
||||
Existing users should refer to [Appendix A](https://docs.openstack.org/charm-deployment-guide/latest/)
|
||||
of the Charm Deployment Guide for details of how to migration existing
|
||||
deployments to the preferred ceph-mon and ceph-osd charms.
|
||||
|
||||
---
|
||||
|
||||
Ceph is a distributed storage and network file system designed to provide
|
||||
excellent performance, reliability, and scalability.
|
||||
|
||||
This charm deploys a Ceph cluster.
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
The ceph charm has two pieces of mandatory configuration for which no defaults
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ceph_hooks.py
|
|
@ -0,0 +1 @@
|
|||
ceph_hooks.py
|
|
@ -0,0 +1 @@
|
|||
ceph_hooks.py
|
|
@ -0,0 +1 @@
|
|||
ceph_hooks.py
|
|
@ -17,6 +17,7 @@
|
|||
import os
|
||||
import sys
|
||||
import socket
|
||||
import subprocess
|
||||
|
||||
sys.path.append('lib')
|
||||
import ceph.utils as ceph
|
||||
|
@ -47,6 +48,7 @@ from charmhelpers.core.hookenv import (
|
|||
)
|
||||
from charmhelpers.core.host import (
|
||||
service_restart,
|
||||
service_pause,
|
||||
umount,
|
||||
mkdir,
|
||||
write_file,
|
||||
|
@ -62,7 +64,10 @@ from charmhelpers.fetch import (
|
|||
get_upstream_version,
|
||||
)
|
||||
from charmhelpers.payload.execd import execd_preinstall
|
||||
from charmhelpers.contrib.openstack.alternatives import install_alternative
|
||||
from charmhelpers.contrib.openstack.alternatives import (
|
||||
install_alternative,
|
||||
remove_alternative,
|
||||
)
|
||||
from charmhelpers.contrib.network.ip import (
|
||||
get_ipv6_addr,
|
||||
format_ipv6_addr,
|
||||
|
@ -221,10 +226,14 @@ def get_ceph_context():
|
|||
return cephcontext
|
||||
|
||||
|
||||
def ceph_conf_path():
|
||||
return "/var/lib/charm/{}/ceph.conf".format(service_name())
|
||||
|
||||
|
||||
def emit_cephconf():
|
||||
# Install ceph.conf as an alternative to support
|
||||
# co-existence with other charms that write this file
|
||||
charm_ceph_conf = "/var/lib/charm/{}/ceph.conf".format(service_name())
|
||||
charm_ceph_conf = ceph_conf_path()
|
||||
mkdir(os.path.dirname(charm_ceph_conf), owner=ceph.ceph_user(),
|
||||
group=ceph.ceph_user())
|
||||
render('ceph.conf', charm_ceph_conf, get_ceph_context(), perms=0o644)
|
||||
|
@ -539,6 +548,19 @@ def client_relation_changed():
|
|||
log('mon cluster not in quorum', level=DEBUG)
|
||||
|
||||
|
||||
@hooks.hook('bootstrap-source-relation-joined')
|
||||
def bootstrap_source_joined(relid=None):
|
||||
"""Provide required information to bootstrap ceph-mon cluster"""
|
||||
if ceph.is_quorum():
|
||||
source = {
|
||||
'fsid': config('fsid'),
|
||||
'monitor-secret': config('monitor-secret'),
|
||||
'ceph-public-address': get_public_addr(),
|
||||
}
|
||||
relation_set(relation_id=relid,
|
||||
relation_settings=source)
|
||||
|
||||
|
||||
@hooks.hook('upgrade-charm.real')
|
||||
@harden()
|
||||
def upgrade_charm():
|
||||
|
@ -639,6 +661,28 @@ def update_status():
|
|||
log('Updating status.')
|
||||
|
||||
|
||||
@hooks.hook('stop')
|
||||
def stop():
|
||||
# NOTE(jamespage)
|
||||
# Ensure monitor is removed from monmap prior to shutdown
|
||||
# otherwise we end up with odd quorum loss issues during
|
||||
# migration.
|
||||
cmd = ['ceph', 'mon', 'rm', socket.gethostname()]
|
||||
subprocess.check_call(cmd)
|
||||
# NOTE(jamespage)
|
||||
# Pause MON and MGR processes running on this unit, leaving
|
||||
# any OSD processes running, supporting the migration to
|
||||
# using the ceph-mon charm.
|
||||
service_pause('ceph-mon')
|
||||
if cmp_pkgrevno('ceph', '12.0.0') >= 0:
|
||||
service_pause('ceph-mgr@{}'.format(socket.gethostname()))
|
||||
# NOTE(jamespage)
|
||||
# Remove the ceph.conf provided by this charm so
|
||||
# that the ceph.conf from other deployed applications
|
||||
# can take priority post removal.
|
||||
remove_alternative('ceph.conf', ceph_conf_path())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
hooks.execute(sys.argv)
|
||||
|
|
|
@ -70,12 +70,12 @@ class DisabledModuleAudit(BaseAudit):
|
|||
"""Returns the modules which are enabled in Apache."""
|
||||
output = subprocess.check_output(['apache2ctl', '-M'])
|
||||
modules = []
|
||||
for line in output.strip().split():
|
||||
for line in output.splitlines():
|
||||
# Each line of the enabled module output looks like:
|
||||
# module_name (static|shared)
|
||||
# Plus a header line at the top of the output which is stripped
|
||||
# out by the regex.
|
||||
matcher = re.search(r'^ (\S*)', line)
|
||||
matcher = re.search(r'^ (\S*)_module (\S*)', line)
|
||||
if matcher:
|
||||
modules.append(matcher.group(1))
|
||||
return modules
|
||||
|
|
|
@ -29,3 +29,16 @@ def install_alternative(name, target, source, priority=50):
|
|||
target, name, source, str(priority)
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def remove_alternative(name, source):
|
||||
"""Remove an installed alternative configuration file
|
||||
|
||||
:param name: string name of the alternative to remove
|
||||
:param source: string full path to alternative to remove
|
||||
"""
|
||||
cmd = [
|
||||
'update-alternatives', '--remove',
|
||||
name, source
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
|
|
@ -218,6 +218,8 @@ def principal_unit():
|
|||
for rid in relation_ids(reltype):
|
||||
for unit in related_units(rid):
|
||||
md = _metadata_unit(unit)
|
||||
if not md:
|
||||
continue
|
||||
subordinate = md.pop('subordinate', None)
|
||||
if not subordinate:
|
||||
return unit
|
||||
|
@ -511,7 +513,10 @@ def _metadata_unit(unit):
|
|||
"""
|
||||
basedir = os.sep.join(charm_dir().split(os.sep)[:-2])
|
||||
unitdir = 'unit-{}'.format(unit.replace(os.sep, '-'))
|
||||
with open(os.path.join(basedir, unitdir, 'charm', 'metadata.yaml')) as md:
|
||||
joineddir = os.path.join(basedir, unitdir, 'charm', 'metadata.yaml')
|
||||
if not os.path.exists(joineddir):
|
||||
return None
|
||||
with open(joineddir) as md:
|
||||
return yaml.safe_load(md)
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ provides:
|
|||
interface: ceph-osd
|
||||
radosgw:
|
||||
interface: ceph-radosgw
|
||||
bootstrap-source:
|
||||
interface: ceph-bootstrap
|
||||
storage:
|
||||
osd-devices:
|
||||
type: block
|
||||
|
|
|
@ -218,6 +218,8 @@ def principal_unit():
|
|||
for rid in relation_ids(reltype):
|
||||
for unit in related_units(rid):
|
||||
md = _metadata_unit(unit)
|
||||
if not md:
|
||||
continue
|
||||
subordinate = md.pop('subordinate', None)
|
||||
if not subordinate:
|
||||
return unit
|
||||
|
@ -511,7 +513,10 @@ def _metadata_unit(unit):
|
|||
"""
|
||||
basedir = os.sep.join(charm_dir().split(os.sep)[:-2])
|
||||
unitdir = 'unit-{}'.format(unit.replace(os.sep, '-'))
|
||||
with open(os.path.join(basedir, unitdir, 'charm', 'metadata.yaml')) as md:
|
||||
joineddir = os.path.join(basedir, unitdir, 'charm', 'metadata.yaml')
|
||||
if not os.path.exists(joineddir):
|
||||
return None
|
||||
with open(joineddir) as md:
|
||||
return yaml.safe_load(md)
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import copy
|
||||
import unittest
|
||||
|
||||
from mock import patch, DEFAULT
|
||||
from mock import patch, DEFAULT, call
|
||||
|
||||
import charmhelpers.contrib.storage.linux.ceph as ceph
|
||||
import ceph_hooks
|
||||
|
@ -287,3 +287,47 @@ class CephHooksTestCase(unittest.TestCase):
|
|||
ceph_hooks.upgrade_charm()
|
||||
mocks["apt_install"].assert_called_with(
|
||||
["python-dbus", "lockfile-progs"])
|
||||
|
||||
|
||||
class StopHookTestCase(unittest.TestCase):
|
||||
|
||||
@patch.object(ceph_hooks, 'ceph_conf_path')
|
||||
@patch.object(ceph_hooks, 'socket')
|
||||
@patch.object(ceph_hooks, 'subprocess')
|
||||
@patch.object(ceph_hooks, 'service_pause')
|
||||
@patch.object(ceph_hooks, 'cmp_pkgrevno')
|
||||
@patch.object(ceph_hooks, 'remove_alternative')
|
||||
def _test_stop(self,
|
||||
remove_alternative,
|
||||
cmp_pkgrevno,
|
||||
service_pause,
|
||||
subprocess,
|
||||
socket,
|
||||
ceph_conf_path,
|
||||
ceph_mgr=False):
|
||||
if ceph_mgr:
|
||||
cmp_pkgrevno.return_value = 1
|
||||
else:
|
||||
cmp_pkgrevno.return_value = -1
|
||||
socket.gethostname.return_value = 'myself'
|
||||
ceph_conf_path.return_value = '/var/lib/charm/me/ceph.conf'
|
||||
ceph_hooks.stop()
|
||||
subprocess.check_call.assert_called_with(
|
||||
['ceph', 'mon', 'rm', 'myself']
|
||||
)
|
||||
if ceph_mgr:
|
||||
service_pause.assert_has_calls([
|
||||
call('ceph-mon'),
|
||||
call('ceph-mgr@myself')
|
||||
])
|
||||
else:
|
||||
service_pause.assert_called_once_with('ceph-mon')
|
||||
|
||||
remove_alternative.assert_called_with('ceph.conf',
|
||||
'/var/lib/charm/me/ceph.conf')
|
||||
|
||||
def test_stop_jewel(self):
|
||||
self._test_stop()
|
||||
|
||||
def test_stop_luminous(self):
|
||||
self._test_stop(ceph_mgr=True)
|
||||
|
|
Loading…
Reference in New Issue