118 lines
3.8 KiB
Python
118 lines
3.8 KiB
Python
# 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.
|
|
|
|
import logging
|
|
import time
|
|
|
|
from octane import magic_consts
|
|
from octane.util import ssh
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class WaiterException(Exception):
|
|
|
|
message = "After {attempts} tries of checking instances on {hostname}" \
|
|
"some instances are still in {status} status"
|
|
|
|
def __init__(self, hostname, attempts, status):
|
|
msg = self.message.format(
|
|
hostname=hostname, attempts=attempts, status=status)
|
|
super(Exception, self).__init__(msg)
|
|
|
|
|
|
def run_nova_cmd(cmd, node, output=True):
|
|
run_cmd = ['sh', '-c', ' '.join(['.', '/root/openrc;'] + cmd)]
|
|
if output:
|
|
return ssh.call_output(run_cmd, node=node)
|
|
return ssh.call(run_cmd, node=node)
|
|
|
|
|
|
def nova_stdout_parser(cmd_stdout):
|
|
"""Parse nova cmd stdout
|
|
|
|
Return list of dicts ther keys are the header of the cmd out table.
|
|
"""
|
|
results = []
|
|
headers = None
|
|
for line in cmd_stdout.splitlines():
|
|
line = line.strip()
|
|
if not line or line[0] == '+':
|
|
continue
|
|
cols = line.strip("|").split("|")
|
|
cols = [c.strip() for c in cols]
|
|
if headers is None:
|
|
headers = cols
|
|
else:
|
|
results.append(dict(zip(headers, cols)))
|
|
return results
|
|
|
|
|
|
def do_nova_instances_exist(controller, node_fqdn, status=None):
|
|
cmd = ['nova', 'list', '--host', node_fqdn, '--limit', '1', '--minimal']
|
|
if status:
|
|
cmd += ['--status', status]
|
|
result = run_nova_cmd(cmd, controller)
|
|
return bool(nova_stdout_parser(result))
|
|
|
|
|
|
def waiting_for_status_completed(controller, node_fqdn, status,
|
|
attempts=180, attempt_delay=10):
|
|
for iteration in xrange(attempts):
|
|
LOG.info(
|
|
"Waiting until instances on {hostname} hostname "
|
|
"exists in {status} (iteration {iteration})".format(
|
|
hostname=node_fqdn, status=status, iteration=iteration))
|
|
if do_nova_instances_exist(controller, node_fqdn, status):
|
|
time.sleep(attempt_delay)
|
|
else:
|
|
return
|
|
raise WaiterException(node_fqdn, attempts, status)
|
|
|
|
|
|
def get_compute_lists(controller):
|
|
"""return tuple of lists enabled and disabled computes"""
|
|
service_stdout = run_nova_cmd(
|
|
["nova", "service-list", "--binary", "nova-compute"], controller)
|
|
parsed_service_list = nova_stdout_parser(service_stdout)
|
|
enabled_computes = []
|
|
disabled_computes = []
|
|
for service in parsed_service_list:
|
|
if service['Status'] == 'enabled':
|
|
enabled_computes.append(service['Host'])
|
|
elif service['Status'] == 'disabled':
|
|
disabled_computes.append(service['Host'])
|
|
return (enabled_computes, disabled_computes)
|
|
|
|
|
|
def get_active_instances(controller, node_fqdn):
|
|
instances_stdout = run_nova_cmd([
|
|
"nova", "list",
|
|
"--host", node_fqdn,
|
|
"--limit", "-1",
|
|
"--status", "ACTIVE",
|
|
"--minimal"],
|
|
controller)
|
|
instances = nova_stdout_parser(instances_stdout)
|
|
return [i["ID"] for i in instances]
|
|
|
|
|
|
def get_upgrade_levels(version):
|
|
try:
|
|
release = magic_consts.UPGRADE_LEVELS[version]
|
|
except KeyError:
|
|
LOG.error("Could not find suitable upgrade_levels for the "
|
|
"{version} release.".format(version=version))
|
|
raise
|
|
else:
|
|
return release
|