Merge "Remove deprecated upgrade scripts"
This commit is contained in:
commit
4e46f2ac6a
|
@ -1,267 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import math
|
||||
import psycopg2
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from controllerconfig.common import log
|
||||
from operator import itemgetter
|
||||
from psycopg2.extras import RealDictCursor
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
BACKUP_GUID = 'ba5eba11-0000-1111-2222-000000000002'
|
||||
SYSINV_GUID = 'ba5eba11-0000-1111-2222-000000000001'
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None # noqa
|
||||
arg = 1
|
||||
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg] # noqa
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
log.configure()
|
||||
|
||||
LOG.debug("%s invoked with from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
if from_release == "21.05" and action == "migrate":
|
||||
try:
|
||||
adjust_backup_partition()
|
||||
except Exception as ex:
|
||||
LOG.exception(ex)
|
||||
return 1
|
||||
|
||||
|
||||
def adjust_backup_partition():
|
||||
installed_backup_size = get_backup_size()
|
||||
conn = psycopg2.connect("dbname=sysinv user=postgres")
|
||||
with conn:
|
||||
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
||||
cur.execute("select i_host.id, i_host.rootfs_device from i_host "
|
||||
"where personality='controller'")
|
||||
controllers = cur.fetchall()
|
||||
if not controllers:
|
||||
LOG.exception("Failed to fetch controller host information")
|
||||
raise
|
||||
|
||||
for controller in controllers:
|
||||
controller_rootfs_disk = get_host_rootfs(cur, controller)
|
||||
db_partitions = get_db_partitions(
|
||||
cur, controller, controller_rootfs_disk)
|
||||
LOG.info("Database partition data: %s" % db_partitions)
|
||||
|
||||
backup_partition = next(p for p in db_partitions if
|
||||
p['type_guid'].lower() == BACKUP_GUID)
|
||||
original_backup_size = backup_partition['size_mib']
|
||||
if installed_backup_size == original_backup_size:
|
||||
LOG.info("Backup partition size unchanged, nothing to do. "
|
||||
"Installed: %s DB: %s" %
|
||||
(installed_backup_size, original_backup_size))
|
||||
continue
|
||||
|
||||
backup_change = installed_backup_size - original_backup_size
|
||||
adjusted_partitions = move_partitions(
|
||||
db_partitions, backup_partition, backup_change)
|
||||
|
||||
# Ensure the last partition will fit on the disk
|
||||
disk_size = controller_rootfs_disk['size_mib'] - 1
|
||||
last_partition = adjusted_partitions[-1]
|
||||
required_space = max(0, last_partition['end_mib'] - disk_size)
|
||||
|
||||
if required_space == 0:
|
||||
update_partitions(cur, adjusted_partitions)
|
||||
LOG.info("Adjusted partitions fit rootfs, can continue. "
|
||||
"Partitions: %s " % adjusted_partitions)
|
||||
continue
|
||||
|
||||
added_partitions = [p for p in db_partitions if
|
||||
p['type_guid'].lower() == SYSINV_GUID]
|
||||
unassigned_partitions = [p for p in added_partitions if
|
||||
p['foripvid'] is None]
|
||||
|
||||
if not added_partitions:
|
||||
# This is not an AIO system, we'll resize the last partiton
|
||||
added_partitions.append(last_partition)
|
||||
|
||||
partitions = unassigned_partitions if unassigned_partitions else added_partitions # noqa
|
||||
partition = max(partitions, key=itemgetter('size_mib'))
|
||||
|
||||
if partition['size_mib'] < required_space:
|
||||
LOG.exception(
|
||||
"Insufficient space to resize partition %s - %s" %
|
||||
(partition, required_space))
|
||||
raise
|
||||
|
||||
reduced_partitions = move_partitions(
|
||||
adjusted_partitions, partition, required_space * -1)
|
||||
final_partitions = adjusted_partitions[:adjusted_partitions.index(partition)] # noqa
|
||||
final_partitions.extend(reduced_partitions)
|
||||
update_partitions(cur, final_partitions)
|
||||
|
||||
host_pvs = get_pvs(cur, controller)
|
||||
partition_vg_name = get_vg_name(partition, host_pvs)
|
||||
|
||||
if partition_vg_name == 'cgts-vg':
|
||||
resize_cgts_vg(cur, controller, required_space)
|
||||
|
||||
|
||||
def get_host_rootfs(cursor, host):
|
||||
disk_query = "select * from i_idisk where forihostid=%s and capabilities like %s" # noqa: E501
|
||||
cursor.execute(disk_query, (host['id'], '%rootfs%',))
|
||||
return cursor.fetchone()
|
||||
|
||||
|
||||
def get_db_partitions(cursor, host, rootfs):
|
||||
partition_query = "select * from partition where forihostid = %s and idisk_uuid = %s" # noqa: E501
|
||||
cursor.execute(partition_query, (host['id'], rootfs['uuid'],))
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def get_backup_size():
|
||||
lsblk_command = 'lsblk -pno PKNAME $(findmnt -n / -o SOURCE)'
|
||||
lsblk = subprocess.Popen(lsblk_command, stdout=subprocess.PIPE, shell=True)
|
||||
root_disk_path = lsblk.stdout.read()
|
||||
part_info = get_sgdisk_info(root_disk_path)
|
||||
|
||||
backup_size = next(part['size_mib'] for part in part_info if
|
||||
part['type_guid'].lower() == BACKUP_GUID)
|
||||
|
||||
return int(backup_size)
|
||||
|
||||
|
||||
def get_sgdisk_info(device_path):
|
||||
"""Obtain partition info: type GUID, type name, UUID, start, end, size.
|
||||
:param: device_path: the disk's device path
|
||||
:returns: list of partition info
|
||||
"""
|
||||
sgdisk_part_info = []
|
||||
fields = ['part_number', 'device_node', 'type_guid', 'type_name', 'uuid',
|
||||
'start_mib', 'end_mib', 'size_mib']
|
||||
sgdisk_command = '{} {}'.format('/usr/bin/partition_info.sh',
|
||||
device_path)
|
||||
|
||||
try:
|
||||
sgdisk_process = subprocess.Popen(sgdisk_command,
|
||||
stdout=subprocess.PIPE,
|
||||
shell=True)
|
||||
except Exception as e:
|
||||
LOG.exception("Could not retrieve partition information: %s" % e)
|
||||
raise
|
||||
|
||||
sgdisk_output = sgdisk_process.stdout.read()
|
||||
|
||||
rows = [row for row in sgdisk_output.split(';') if row.strip()]
|
||||
|
||||
for row in rows:
|
||||
values = row.split()
|
||||
partition = dict(zip(fields, values))
|
||||
|
||||
if 'part_number' in partition.keys():
|
||||
partition['part_number'] = int(partition['part_number'])
|
||||
|
||||
sgdisk_part_info.append(partition)
|
||||
|
||||
return sgdisk_part_info
|
||||
|
||||
|
||||
def move_partitions(db_values, start, size):
|
||||
"""
|
||||
Updates the list of partitions based on the new size of a given partition
|
||||
:param: db_values: A list of partitions to adjust
|
||||
:param: start: The partition being adjusted
|
||||
:param: size: The change in size of the partition
|
||||
:returns: A sorted list of updated partitions
|
||||
"""
|
||||
partitions = sorted(db_values, key=itemgetter('start_mib'))
|
||||
partitions = partitions[partitions.index(start):]
|
||||
# Update the specified partition size and end_mib
|
||||
partitions[0]['size_mib'] += size
|
||||
partitions[0]['end_mib'] += size
|
||||
# Shift the rest of the partitions
|
||||
for partition in partitions[1:]:
|
||||
partition['start_mib'] += size
|
||||
partition['end_mib'] += size
|
||||
|
||||
return partitions
|
||||
|
||||
|
||||
def update_partitions(cursor, updated_partitions):
|
||||
LOG.info("Updating partitions to: %s" % updated_partitions)
|
||||
update_query = "update partition set start_mib=%s, end_mib=%s, size_mib=%s where id=%s" # noqa: E501
|
||||
for partition in updated_partitions:
|
||||
cursor.execute(update_query,
|
||||
(partition['start_mib'], partition['end_mib'],
|
||||
partition['size_mib'], partition['id']))
|
||||
|
||||
|
||||
def get_pvs(cursor, host):
|
||||
query = "select * from i_pv where forihostid=%s"
|
||||
cursor.execute(query, (host['id'],))
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def get_vg_name(partition, pvs):
|
||||
pv_id = partition['foripvid']
|
||||
if not pv_id:
|
||||
return None
|
||||
return next(pv['lvm_vg_name'] for pv in pvs if pv['id'] == pv_id)
|
||||
|
||||
|
||||
def resize_cgts_vg(cursor, host, required_space):
|
||||
cgts_vg = get_cgts_vg(cursor, host)
|
||||
cgts_vg_free_space = int(cgts_vg['lvm_vg_size'] / cgts_vg['lvm_vg_total_pe']) * cgts_vg['lvm_vg_free_pe'] # noqa: E501
|
||||
|
||||
# There may be available space in the cgts_vg
|
||||
if cgts_vg_free_space >= required_space:
|
||||
LOG.info("cgts_vg has sufficient space, can continue. "
|
||||
"cgts_vg: %s " % cgts_vg)
|
||||
return
|
||||
|
||||
# Otherwise we'll reduce the backup fs by up to 15GB and remove
|
||||
# the rest from the docker fs
|
||||
required_space -= cgts_vg_free_space
|
||||
required_gb = int(math.ceil(required_space / 1024.0))
|
||||
backup_fs_reduction = min(15, required_gb)
|
||||
update_host_fs(cursor, host, 'backup', backup_fs_reduction)
|
||||
|
||||
required_gb -= backup_fs_reduction
|
||||
if required_gb > 0:
|
||||
update_host_fs(cursor, host, 'docker', required_gb)
|
||||
|
||||
|
||||
def get_cgts_vg(cursor, host):
|
||||
query = "select * from i_lvg where lvm_vg_name='cgts-vg' and forihostid=%s"
|
||||
cursor.execute(query, (host['id'],))
|
||||
return cursor.fetchone()
|
||||
|
||||
|
||||
def update_host_fs(cursor, host, fs_name, reduction):
|
||||
size_query = "select size from host_fs where name=%s and forihostid=%s"
|
||||
cursor.execute(size_query, (fs_name, host['id']))
|
||||
original_size = cursor.fetchone()['size']
|
||||
|
||||
new_size = original_size - reduction
|
||||
LOG.info("Updating %s host fs to %s" % (fs_name, new_size))
|
||||
update_query = "update host_fs set size=%s where name=%s and forihostid=%s"
|
||||
cursor.execute(update_query, (new_size, fs_name, host['id']))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
|
@ -1,106 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script will add service parameters specific to handling of ghcr.io
|
||||
# registry into the sysinv database during migration phase of upgrade
|
||||
# procedure.
|
||||
# Also, the previous horizon parameters will be removed without necessity
|
||||
# to keep the old unused values.
|
||||
|
||||
import sys
|
||||
import psycopg2
|
||||
from datetime import datetime
|
||||
from oslo_utils import uuidutils
|
||||
from psycopg2.extras import RealDictCursor
|
||||
from controllerconfig.common import log
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
log.configure()
|
||||
|
||||
LOG.info("%s invoked with from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
if action == "migrate" and from_release == '21.05':
|
||||
try:
|
||||
conn = psycopg2.connect("dbname=sysinv user=postgres")
|
||||
with conn:
|
||||
add_ghcr_registry(conn)
|
||||
|
||||
remove_horizon_params(conn)
|
||||
|
||||
return 0
|
||||
except Exception as ex:
|
||||
LOG.exception(ex)
|
||||
return 1
|
||||
|
||||
|
||||
def get_gcr_rows(db_conn):
|
||||
with db_conn.cursor(cursor_factory=RealDictCursor) as cur:
|
||||
cur.execute("select name, value, personality, resource from "
|
||||
"service_parameter where service='docker' and "
|
||||
"section='gcr-registry'")
|
||||
|
||||
return cur.fetchall()
|
||||
|
||||
|
||||
def add_ghcr_registry(db_conn):
|
||||
cmd = """
|
||||
INSERT INTO service_parameter (created_at, uuid, name,
|
||||
value, service, section, personality, resource) VALUES
|
||||
(%s, %s, %s, %s, %s, %s, %s, %s);
|
||||
"""
|
||||
rows = get_gcr_rows(db_conn)
|
||||
for row in rows:
|
||||
timestamp = str(datetime.now())
|
||||
uuid = uuidutils.generate_uuid()
|
||||
value = row.get('value')
|
||||
|
||||
# There are two names where we expect to need to
|
||||
# replace the registry name in the corresponding value.
|
||||
for key in ['additional-overrides', 'url']:
|
||||
if value and row.get('name') == key:
|
||||
value = value.replace('gcr.io', 'ghcr.io')
|
||||
|
||||
LOG.info("Adding %s=%s to db for ghcr-registry"
|
||||
% (row['name'], value))
|
||||
with db_conn.cursor() as cur:
|
||||
cur.execute(
|
||||
cmd,
|
||||
(timestamp, uuid, row['name'], value,
|
||||
'docker', 'ghcr-registry', row['personality'],
|
||||
row['resource']))
|
||||
LOG.info("ghcr_registry parameters upgrade completed")
|
||||
|
||||
|
||||
def remove_horizon_params(db_conn):
|
||||
cmd_delete = "DELETE FROM service_parameter WHERE " \
|
||||
"service='horizon' and section='auth'"
|
||||
LOG.info("Removing horizon auth params from db")
|
||||
with db_conn.cursor() as cur:
|
||||
cur.execute(cmd_delete)
|
||||
LOG.info("Horizon auth params removed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
|
@ -1,65 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script updates armada to add tolerations for the
|
||||
# node-role.kubernetes.io/master:NoSchedule taint on armada-api pod.
|
||||
#
|
||||
# This script can be removed in the release that follows stx6
|
||||
import subprocess
|
||||
import sys
|
||||
from controllerconfig.common import log
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
log.configure()
|
||||
|
||||
if action == 'activate' and from_release == '21.05':
|
||||
LOG.info("%s invoked with from_release = %s to_release = %s "
|
||||
"action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
update_armada_toleration()
|
||||
|
||||
|
||||
def update_armada_toleration():
|
||||
"""Run upgrade-k8s-armada-helm.yml to update armada helm chart.
|
||||
|
||||
When this script is run, all hosts have been upgraded and the new helm
|
||||
chart and the armada-overrides.yaml.j2 file with the tolerations override
|
||||
are available on the active controller.
|
||||
|
||||
This function will run the upgrade-k8s-armada-helm.yml playbook that
|
||||
upgrades the armada chart with overrides present on armada-overrides.yaml.
|
||||
"""
|
||||
|
||||
playbooks_root = '/usr/share/ansible/stx-ansible/playbooks'
|
||||
upgrade_script = 'upgrade-k8s-armada-helm.yml'
|
||||
cmd = 'ansible-playbook {}/{}'.format(playbooks_root, upgrade_script)
|
||||
sub = subprocess.Popen(cmd, shell=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = sub.communicate()
|
||||
if sub.returncode != 0:
|
||||
LOG.error('Command failed:\n %s\n. %s\n%s' % (cmd, stdout, stderr))
|
||||
raise Exception('Cannot update armada')
|
||||
LOG.info('Toleration applied to armada successfully')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
|
@ -1,89 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Copyright (c) 2021 Intel Corporation.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# Enable separate etcd ca during upgrade.
|
||||
#
|
||||
# Note: this can be removed in the release after STX6.0
|
||||
|
||||
. /etc/platform/platform.conf
|
||||
|
||||
# This will log to /var/log/platform.log
|
||||
function log {
|
||||
logger -p local1.info $1
|
||||
}
|
||||
|
||||
|
||||
FROM_REL=$1
|
||||
TO_REL=$2
|
||||
ACTION=$3
|
||||
|
||||
# below function is cloned from ../scripts/controller_config
|
||||
get_ip()
|
||||
{
|
||||
HOST_NAME=$1
|
||||
|
||||
# Check /etc/hosts for the hostname
|
||||
HOST_IP=$(cat /etc/hosts | grep "${HOST_NAME}" | awk '{print $1}')
|
||||
if [ -n "${HOST_IP}" ]; then
|
||||
echo "${HOST_IP}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Try the DNS query
|
||||
# Because dnsmasq can resolve both a hostname to both an IPv4 and an IPv6
|
||||
# address in certain situations, and the last address is the IPv6, which
|
||||
# would be the management, this is preferred over the IPv4 pxeboot address,
|
||||
# so take the last address only.
|
||||
HOST_IP=$(dig +short ANY $host|tail -1)
|
||||
if [[ "${HOST_IP}" =~ ^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$ ]]; then
|
||||
echo "${HOST_IP}"
|
||||
return
|
||||
fi
|
||||
if [[ "${HOST_IP}" =~ ^[0-9a-z]*\:[0-9a-z\:]*$ ]]; then
|
||||
echo "${HOST_IP}"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
enable_separate_etcd_ca()
|
||||
{
|
||||
STATIC_YAML="/opt/platform/puppet/${sw_version}/hieradata/static.yaml"
|
||||
SYSTEM_YAML="/opt/platform/puppet/${sw_version}/hieradata/system.yaml"
|
||||
|
||||
if [[ ! -f ${STATIC_YAML} ]] || [[ ! -f ${SYSTEM_YAML} ]]; then
|
||||
log "Could not find specific static/system yaml files in /opt/platform/puppet/${sw_version}/hieradata!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CLUSTER_FLOATING_ADDRESS=$(grep "platform::network::cluster_host::params::controller_address" ${SYSTEM_YAML} | awk '{print $2}')
|
||||
CLUSTER_FLOATING_ADDRESS_VERSION=$(grep "platform::network::cluster_host::params::subnet_version" ${SYSTEM_YAML} | awk '{print $2}')
|
||||
HOST_ADDR=$(get_ip $(hostname))
|
||||
|
||||
ansible-playbook /usr/share/ansible/stx-ansible/playbooks/separate_etcd_ca.yml \
|
||||
-e "cluster_floating_address=${CLUSTER_FLOATING_ADDRESS}" \
|
||||
-e "etcd_listen_address_version=${CLUSTER_FLOATING_ADDRESS_VERSION}" \
|
||||
-e "puppet_permdir=/opt/platform/puppet/${sw_version}" \
|
||||
-e "config_permdir=/opt/platform/config/${sw_version}" \
|
||||
-e "ipaddress=${HOST_ADDR}" \
|
||||
-e "etcd_root_ca_cert=''" \
|
||||
-e "etcd_root_ca_key=''"
|
||||
if [ $? -ne 0 ]; then
|
||||
log "Failed to run ansible playbook!"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
log "${0} invoked with from_release = ${FROM_REL} to_release = ${TO_REL} action = ${ACTION}"
|
||||
|
||||
if [ ${FROM_REL} == "21.05" -a ${ACTION} == "activate" ]; then
|
||||
enable_separate_etcd_ca
|
||||
else
|
||||
log "Only execute this upgrade code when the activate action is being done and the from release is 21.05!"
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -1,148 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This script will run during the upgrade activation step after all nodes have
|
||||
# been upgraded.
|
||||
#
|
||||
# This will set the required_osd_release to 'nautilus' and enable the straw2
|
||||
# bucket algorithm. 'straw2' has improvements over the previous 'straw'
|
||||
# algorithm. For more information see:
|
||||
# https://docs.ceph.com/en/latest/rados/operations/crush-map/#hammer-crush-v4
|
||||
#
|
||||
# This script can be removed in the release that follows 21.12.
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from controllerconfig.common import log
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
action = None
|
||||
from_release = None
|
||||
to_release = None
|
||||
arg = 1
|
||||
while arg < len(sys.argv):
|
||||
if arg == 1:
|
||||
from_release = sys.argv[arg]
|
||||
elif arg == 2:
|
||||
to_release = sys.argv[arg]
|
||||
elif arg == 3:
|
||||
action = sys.argv[arg]
|
||||
else:
|
||||
print("Invalid option %s." % sys.argv[arg])
|
||||
return 1
|
||||
arg += 1
|
||||
|
||||
log.configure()
|
||||
|
||||
LOG.debug("%s invoked with from_release = %s to_release = %s action = %s"
|
||||
% (sys.argv[0], from_release, to_release, action))
|
||||
|
||||
if from_release == "21.05" and action == "activate":
|
||||
try:
|
||||
upgrade_ceph()
|
||||
except Exception as e:
|
||||
LOG.exception('Upgrade failed due to the following exception: %s'
|
||||
% e)
|
||||
return 1
|
||||
|
||||
|
||||
def upgrade_ceph():
|
||||
if not is_ceph_configured():
|
||||
LOG.info("Ceph backend absent. "
|
||||
"No further upgrade actions are required."
|
||||
)
|
||||
return
|
||||
else:
|
||||
LOG.info("Ceph backend present. Verifying Ceph upgrade to Nautilus is "
|
||||
"complete.")
|
||||
|
||||
osd_release = get_required_osd_release()
|
||||
straw2_enabled = is_straw2_enabled()
|
||||
|
||||
if osd_release != 'nautilus' or not straw2_enabled:
|
||||
LOG.info("Completing upgrade to Ceph Nautilus...")
|
||||
|
||||
# Setting to nautilus release first is mandatory
|
||||
if osd_release != 'nautilus':
|
||||
set_required_osd_release()
|
||||
|
||||
if not straw2_enabled:
|
||||
enable_straw2()
|
||||
|
||||
LOG.info("Upgrade complete to Ceph Nautilus")
|
||||
else:
|
||||
LOG.info("No additional Ceph upgraded actions required")
|
||||
|
||||
|
||||
def is_ceph_configured():
|
||||
# This command was used because it was not possible to connect to
|
||||
# the sysinv database using the psycopg2 module when in 'activate'
|
||||
# action
|
||||
command = ("sudo -u postgres psql -U postgres -d sysinv -t -A -q -c "
|
||||
"\"SELECT count(*) FROM storage_backend "
|
||||
"where backend='ceph' AND name='ceph-store';\"")
|
||||
out = exec_command(command)
|
||||
return out.strip() == "1"
|
||||
|
||||
|
||||
def get_required_osd_release():
|
||||
command = "ceph osd dump -f json"
|
||||
out = exec_ceph_command(command)
|
||||
json_out = json.loads(out)
|
||||
return json_out.get('require_osd_release')
|
||||
|
||||
|
||||
def is_straw2_enabled():
|
||||
command = "ceph osd crush dump -f json"
|
||||
out = exec_ceph_command(command)
|
||||
json_out = json.loads(out)
|
||||
algs = [b['alg'] for b in json_out.get('buckets')]
|
||||
return algs.count('straw') == 0
|
||||
|
||||
|
||||
def set_required_osd_release():
|
||||
LOG.info("Set 'nautilus' for require_osd_release...")
|
||||
command = "ceph osd require-osd-release nautilus"
|
||||
exec_ceph_command(command)
|
||||
release = get_required_osd_release()
|
||||
if release != 'nautilus':
|
||||
raise Exception("Could not set nautilus release 'require_osd_release'")
|
||||
|
||||
|
||||
def enable_straw2():
|
||||
LOG.info("Enabling straw2 bucket algorithm...")
|
||||
command = "ceph osd crush set-all-straw-buckets-to-straw2"
|
||||
exec_ceph_command(command)
|
||||
if not is_straw2_enabled():
|
||||
raise Exception("Could not enable straw2 bucket algorithm")
|
||||
|
||||
|
||||
def exec_command(command):
|
||||
LOG.debug("Running command: %s" % command)
|
||||
process = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
shell=True)
|
||||
stdout, stderr = process.communicate()
|
||||
rc = process.returncode
|
||||
if rc != 0:
|
||||
raise Exception("Failed to run command: %s | rc=%s | stdout: %s"
|
||||
" | stderr: %s" %
|
||||
(command, rc, stdout, stderr))
|
||||
return stdout
|
||||
|
||||
|
||||
def exec_ceph_command(command):
|
||||
command = 'timeout 60s %s' % command
|
||||
return exec_command(command)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
Loading…
Reference in New Issue