Add action to list unmounted disks
This action is fairly simple in that it returns a list of unmounted disks This also includes a git-sync to pull in charms.ceph changes. Change-Id: I0daa514958799cf5899375335e8e9e684df27704 Closes-Bug: 1645481
This commit is contained in:
parent
d045424c54
commit
2dfbb5fe47
|
@ -35,4 +35,5 @@ replace-osd:
|
||||||
description: The replacement device to use. Example /dev/sdb.
|
description: The replacement device to use. Example /dev/sdb.
|
||||||
required: [osd-number, replacement-device]
|
required: [osd-number, replacement-device]
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
list-disks:
|
||||||
|
description: List the unmounted disk on the specified unit
|
|
@ -0,0 +1 @@
|
||||||
|
list_disks.py
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright 2016 Canonical Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
List unmounted devices.
|
||||||
|
|
||||||
|
This script will get all block devices known by udev and check if they
|
||||||
|
are mounted so that we can give unmounted devices to the administrator.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.append('hooks/')
|
||||||
|
sys.path.append('lib/')
|
||||||
|
|
||||||
|
from charmhelpers.core.hookenv import action_set
|
||||||
|
|
||||||
|
from ceph import unmounted_disks
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
action_set({
|
||||||
|
'disks': unmounted_disks()})
|
|
@ -2,7 +2,7 @@
|
||||||
# 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=('apt' 'netaddr' 'netifaces' 'pip' 'yaml' 'dnspython')
|
declare -a DEPS=('apt' 'netaddr' 'netifaces' 'pip' 'yaml')
|
||||||
|
|
||||||
check_and_install() {
|
check_and_install() {
|
||||||
pkg="${1}-${2}"
|
pkg="${1}-${2}"
|
||||||
|
@ -17,4 +17,5 @@ for dep in ${DEPS[@]}; do
|
||||||
check_and_install ${PYTHON} ${dep}
|
check_and_install ${PYTHON} ${dep}
|
||||||
done
|
done
|
||||||
|
|
||||||
|
./hooks/install_deps
|
||||||
exec ./hooks/install.real
|
exec ./hooks/install.real
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Wrapper to ensure that python dependencies are installed before we get into
|
||||||
|
# the python part of the hook execution
|
||||||
|
|
||||||
|
declare -a DEPS=('dnspython' 'pyudev')
|
||||||
|
|
||||||
|
check_and_install() {
|
||||||
|
pkg="${1}-${2}"
|
||||||
|
if ! dpkg -s ${pkg} 2>&1 > /dev/null; then
|
||||||
|
apt-get -y install ${pkg}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
PYTHON="python"
|
||||||
|
|
||||||
|
for dep in ${DEPS[@]}; do
|
||||||
|
check_and_install ${PYTHON} ${dep}
|
||||||
|
done
|
|
@ -2,5 +2,5 @@
|
||||||
# Wrapper to ensure that old python bytecode isn't hanging around
|
# Wrapper to ensure that old python bytecode isn't hanging around
|
||||||
# after we upgrade the charm with newer libraries
|
# after we upgrade the charm with newer libraries
|
||||||
rm -rf **/*.pyc
|
rm -rf **/*.pyc
|
||||||
|
./hooks/install_deps
|
||||||
exec ./hooks/upgrade-charm.real
|
exec ./hooks/upgrade-charm.real
|
||||||
|
|
|
@ -23,6 +23,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import errno
|
import errno
|
||||||
import shutil
|
import shutil
|
||||||
|
import pyudev
|
||||||
|
|
||||||
from charmhelpers.core import hookenv
|
from charmhelpers.core import hookenv
|
||||||
from charmhelpers.core.host import (
|
from charmhelpers.core.host import (
|
||||||
|
@ -50,13 +51,15 @@ from charmhelpers.contrib.storage.linux.utils import (
|
||||||
is_block_device,
|
is_block_device,
|
||||||
zap_disk,
|
zap_disk,
|
||||||
is_device_mounted)
|
is_device_mounted)
|
||||||
|
from charmhelpers.contrib.openstack.utils import (
|
||||||
|
get_os_codename_install_source)
|
||||||
|
|
||||||
LEADER = 'leader'
|
LEADER = 'leader'
|
||||||
PEON = 'peon'
|
PEON = 'peon'
|
||||||
QUORUM = [LEADER, PEON]
|
QUORUM = [LEADER, PEON]
|
||||||
|
|
||||||
PACKAGES = ['ceph', 'gdisk', 'ntp', 'btrfs-tools', 'python-ceph',
|
PACKAGES = ['ceph', 'gdisk', 'ntp', 'btrfs-tools', 'python-ceph',
|
||||||
'radosgw', 'xfsprogs']
|
'radosgw', 'xfsprogs', 'python-pyudev']
|
||||||
|
|
||||||
LinkSpeed = {
|
LinkSpeed = {
|
||||||
"BASE_10": 10,
|
"BASE_10": 10,
|
||||||
|
@ -100,6 +103,23 @@ NETWORK_ADAPTER_SYSCTLS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def unmounted_disks():
|
||||||
|
"""List of unmounted block devices on the current host."""
|
||||||
|
disks = []
|
||||||
|
context = pyudev.Context()
|
||||||
|
for device in context.list_devices(DEVTYPE='disk'):
|
||||||
|
if device['SUBSYSTEM'] == 'block':
|
||||||
|
matched = False
|
||||||
|
for block_type in [u'dm', u'loop', u'ram', u'nbd']:
|
||||||
|
if block_type in device.device_node:
|
||||||
|
matched = True
|
||||||
|
if matched:
|
||||||
|
continue
|
||||||
|
disks.append(device.device_node)
|
||||||
|
log("Found disks: {}".format(disks))
|
||||||
|
return [disk for disk in disks if not is_device_mounted(disk)]
|
||||||
|
|
||||||
|
|
||||||
def save_sysctls(sysctl_dict, save_location):
|
def save_sysctls(sysctl_dict, save_location):
|
||||||
"""
|
"""
|
||||||
Persist the sysctls to the hard drive.
|
Persist the sysctls to the hard drive.
|
||||||
|
@ -949,7 +969,7 @@ def get_mds_bootstrap_key():
|
||||||
|
|
||||||
|
|
||||||
_default_caps = collections.OrderedDict([
|
_default_caps = collections.OrderedDict([
|
||||||
('mon', ['allow rw']),
|
('mon', ['allow r']),
|
||||||
('osd', ['allow rwx']),
|
('osd', ['allow rwx']),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -1344,7 +1364,7 @@ def roll_monitor_cluster(new_version, upgrade_key):
|
||||||
version=new_version)
|
version=new_version)
|
||||||
else:
|
else:
|
||||||
# Check if the previous node has finished
|
# Check if the previous node has finished
|
||||||
status_set('blocked',
|
status_set('waiting',
|
||||||
'Waiting on {} to finish upgrading'.format(
|
'Waiting on {} to finish upgrading'.format(
|
||||||
mon_sorted_list[position - 1]))
|
mon_sorted_list[position - 1]))
|
||||||
wait_on_previous_node(upgrade_key=upgrade_key,
|
wait_on_previous_node(upgrade_key=upgrade_key,
|
||||||
|
@ -1361,11 +1381,10 @@ def roll_monitor_cluster(new_version, upgrade_key):
|
||||||
status_set('blocked', 'failed to upgrade monitor')
|
status_set('blocked', 'failed to upgrade monitor')
|
||||||
|
|
||||||
|
|
||||||
def upgrade_monitor():
|
def upgrade_monitor(new_version):
|
||||||
current_version = get_version()
|
current_version = get_version()
|
||||||
status_set("maintenance", "Upgrading monitor")
|
status_set("maintenance", "Upgrading monitor")
|
||||||
log("Current ceph version is {}".format(current_version))
|
log("Current ceph version is {}".format(current_version))
|
||||||
new_version = config('release-version')
|
|
||||||
log("Upgrading to: {}".format(new_version))
|
log("Upgrading to: {}".format(new_version))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1393,7 +1412,6 @@ def upgrade_monitor():
|
||||||
service_start('ceph-mon@{}'.format(mon_id))
|
service_start('ceph-mon@{}'.format(mon_id))
|
||||||
else:
|
else:
|
||||||
service_start('ceph-mon-all')
|
service_start('ceph-mon-all')
|
||||||
status_set("active", "")
|
|
||||||
except subprocess.CalledProcessError as err:
|
except subprocess.CalledProcessError as err:
|
||||||
log("Stopping ceph and upgrading packages failed "
|
log("Stopping ceph and upgrading packages failed "
|
||||||
"with message: {}".format(err.message))
|
"with message: {}".format(err.message))
|
||||||
|
@ -1415,9 +1433,9 @@ def lock_and_roll(upgrade_key, service, my_name, version):
|
||||||
|
|
||||||
# This should be quick
|
# This should be quick
|
||||||
if service == 'osd':
|
if service == 'osd':
|
||||||
upgrade_osd()
|
upgrade_osd(version)
|
||||||
elif service == 'mon':
|
elif service == 'mon':
|
||||||
upgrade_monitor()
|
upgrade_monitor(version)
|
||||||
else:
|
else:
|
||||||
log("Unknown service {}. Unable to upgrade".format(service),
|
log("Unknown service {}. Unable to upgrade".format(service),
|
||||||
level=ERROR)
|
level=ERROR)
|
||||||
|
@ -1541,11 +1559,10 @@ def roll_osd_cluster(new_version, upgrade_key):
|
||||||
status_set('blocked', 'failed to upgrade osd')
|
status_set('blocked', 'failed to upgrade osd')
|
||||||
|
|
||||||
|
|
||||||
def upgrade_osd():
|
def upgrade_osd(new_version):
|
||||||
current_version = get_version()
|
current_version = get_version()
|
||||||
status_set("maintenance", "Upgrading osd")
|
status_set("maintenance", "Upgrading osd")
|
||||||
log("Current ceph version is {}".format(current_version))
|
log("Current ceph version is {}".format(current_version))
|
||||||
new_version = config('release-version')
|
|
||||||
log("Upgrading to: {}".format(new_version))
|
log("Upgrading to: {}".format(new_version))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1578,3 +1595,58 @@ def upgrade_osd():
|
||||||
"with message: {}".format(err.message))
|
"with message: {}".format(err.message))
|
||||||
status_set("blocked", "Upgrade to {} failed".format(new_version))
|
status_set("blocked", "Upgrade to {} failed".format(new_version))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def list_pools(service):
|
||||||
|
"""
|
||||||
|
This will list the current pools that Ceph has
|
||||||
|
|
||||||
|
:param service: String service id to run under
|
||||||
|
:return: list. Returns a list of the ceph pools. Raises CalledProcessError
|
||||||
|
if the subprocess fails to run.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
pool_list = []
|
||||||
|
pools = subprocess.check_output(['rados', '--id', service, 'lspools'])
|
||||||
|
for pool in pools.splitlines():
|
||||||
|
pool_list.append(pool)
|
||||||
|
return pool_list
|
||||||
|
except subprocess.CalledProcessError as err:
|
||||||
|
log("rados lspools failed with error: {}".format(err.output))
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
# A dict of valid ceph upgrade paths. Mapping is old -> new
|
||||||
|
UPGRADE_PATHS = {
|
||||||
|
'firefly': 'hammer',
|
||||||
|
'hammer': 'jewel',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Map UCA codenames to ceph codenames
|
||||||
|
UCA_CODENAME_MAP = {
|
||||||
|
'icehouse': 'firefly',
|
||||||
|
'juno': 'firefly',
|
||||||
|
'kilo': 'hammer',
|
||||||
|
'liberty': 'hammer',
|
||||||
|
'mitaka': 'jewel',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def pretty_print_upgrade_paths():
|
||||||
|
'''Pretty print supported upgrade paths for ceph'''
|
||||||
|
lines = []
|
||||||
|
for key, value in UPGRADE_PATHS.iteritems():
|
||||||
|
lines.append("{} -> {}".format(key, value))
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_ceph_version(source):
|
||||||
|
'''
|
||||||
|
Resolves a version of ceph based on source configuration
|
||||||
|
based on Ubuntu Cloud Archive pockets.
|
||||||
|
|
||||||
|
@param: source: source configuration option of charm
|
||||||
|
@returns: ceph release codename or None if not resolvable
|
||||||
|
'''
|
||||||
|
os_release = get_os_codename_install_source(source)
|
||||||
|
return UCA_CODENAME_MAP.get(os_release)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,3 +10,4 @@ Jinja2>=2.6 # BSD License (3 clause)
|
||||||
six>=1.9.0
|
six>=1.9.0
|
||||||
dnspython>=1.12.0
|
dnspython>=1.12.0
|
||||||
psutil>=1.1.1,<2.0.0
|
psutil>=1.1.1,<2.0.0
|
||||||
|
pyudev
|
||||||
|
|
Loading…
Reference in New Issue