One click upgrade

Discover all available hosts to be maintained

Story: 2004146
Task: #27619

Change-Id: Id11ab3c2f41dfde49d082fb5338182d2c6ede5a5
Signed-off-by: Tomi Juvonen <tomi.juvonen@nokia.com>
This commit is contained in:
Tomi Juvonen 2019-01-25 13:57:17 +02:00
parent 262c503ae4
commit 9eadb36061
5 changed files with 87 additions and 14 deletions

View File

@ -143,6 +143,21 @@ def create_hosts(session_id, hostnames):
return IMPL.create_hosts(hosts)
def create_hosts_by_details(session_id, hosts_dict_list):
hosts = []
for hd in hosts_dict_list:
host = {}
host['session_id'] = session_id
host['hostname'] = hd["hostname"]
host['type'] = hd["type"]
host['maintained'] = hd['maintained']
host['disabled'] = hd['disabled']
if 'details' in hd:
host['details'] = hd['details']
hosts.append(host)
return IMPL.create_hosts(hosts)
def create_projects(session_id, project_ids):
projects = []
for project_id in project_ids:

View File

@ -53,7 +53,7 @@ def upgrade():
sa.Column('session_id', sa.String(36),
sa.ForeignKey('sessions.session_id')),
sa.Column('hostname', sa.String(length=255), nullable=False),
sa.Column('type', sa.String(length=32), nullable=True),
sa.Column('type', sa.String(length=32), nullable=False),
sa.Column('maintained', sa.Boolean, default=False),
sa.Column('disabled', sa.Boolean, default=False),
sa.Column('details', sa.String(length=255), nullable=True),

View File

@ -79,7 +79,7 @@ class MaintenanceHost(mb.FenixBase):
session_id = sa.Column(sa.String(36), sa.ForeignKey('sessions.session_id'),
nullable=False)
hostname = sa.Column(sa.String(length=255), primary_key=True)
type = sa.Column(sa.String(length=32), nullable=True)
type = sa.Column(sa.String(length=32), nullable=False)
maintained = sa.Column(sa.Boolean, default=False)
disabled = sa.Column(sa.Boolean, default=False)
details = sa.Column(sa.String(length=255), nullable=True)

View File

@ -41,11 +41,12 @@ class BaseWorkflow(Thread):
self.timer = {}
self.session = self._init_session(data)
LOG.info('%s: session %s' % (self.session_id, self.session))
if len(data['hosts']):
self.hosts = []
if "hosts" in data and data['hosts']:
# Hosts given as input, not to be discovered in workflow
self.hosts = self.init_hosts(self.convert(data['hosts']))
else:
self.hosts = []
LOG.info('%s: No hosts as input' % self.session_id)
# TBD API to support action plugins
# self.actions =
self.projects = []
@ -118,8 +119,9 @@ class BaseWorkflow(Thread):
instance_computes.append(instance.host)
return [host for host in all_computes if host not in instance_computes]
def get_maintained_hosts(self):
return [host.hostname for host in self.hosts if host.maintained]
def get_maintained_hosts_by_type(self, host_type):
return [host.hostname for host in self.hosts if host.maintained and
host.type == host_type]
def get_disabled_hosts(self):
return [host for host in self.hosts if host.disabled]
@ -287,6 +289,8 @@ class BaseWorkflow(Thread):
def __str__(self):
info = 'Instance info:\n'
for host in self.hosts:
if host.type != 'compute':
continue
info += ('%s:\n' % host.hostname)
for project in self.project_names():
instance_ids = (

View File

@ -48,15 +48,60 @@ class Workflow(BaseWorkflow):
nova_version = max_nova_server_ver
self.nova = novaclient.Client(nova_version,
session=self.auth_session)
self._init_update_hosts()
if not self.hosts:
self.hosts = self._init_hosts_by_services()
else:
self._init_update_hosts()
LOG.info("%s: initialized. Nova version %f" % (self.session_id,
nova_version))
def _init_hosts_by_services(self):
LOG.info("%s: Dicovering hosts by Nova services" % self.session_id)
hosts = []
controllers = self.nova.services.list(binary='nova-conductor')
for controller in controllers:
host = {}
service_host = str(controller.__dict__.get(u'host'))
host['hostname'] = service_host
host['type'] = 'controller'
if str(controller.__dict__.get(u'status')) == 'disabled':
LOG.error("%s: %s nova-conductor disabled before maintenance"
% (self.session_id, service_host))
raise Exception("%s: %s already disabled"
% (self.session_id, service_host))
host['disabled'] = False
host['details'] = str(controller.__dict__.get(u'id'))
host['maintained'] = False
hosts.append(host)
computes = self.nova.services.list(binary='nova-compute')
for compute in computes:
host = {}
service_host = str(compute.__dict__.get(u'host'))
host['hostname'] = service_host
host['type'] = 'compute'
if str(compute.__dict__.get(u'status')) == 'disabled':
LOG.error("%s: %s nova-compute disabled before maintenance"
% (self.session_id, service_host))
raise Exception("%s: %s already disabled"
% (self.session_id, service_host))
host['disabled'] = False
host['details'] = str(compute.__dict__.get(u'id'))
host['maintained'] = False
hosts.append(host)
return db_api.create_hosts_by_details(self.session_id, hosts)
def _init_update_hosts(self):
LOG.info("%s: Update given hosts" % self.session_id)
controllers = self.nova.services.list(binary='nova-conductor')
computes = self.nova.services.list(binary='nova-compute')
for host in self.hosts:
hostname = host.hostname
host.disabled = False
host.maintained = False
match = [compute for compute in computes if
hostname == compute.host]
if match:
@ -161,8 +206,16 @@ class Workflow(BaseWorkflow):
if project_id not in project_ids:
project_ids.append(project_id)
self.projects = self.init_projects(project_ids)
self.instances = self.add_instances(instances)
if len(project_ids):
self.projects = self.init_projects(project_ids)
else:
LOG.info('%s: No projects on computes under maintenance %s' %
self.session_id)
if len(instances):
self.instances = self.add_instances(instances)
else:
LOG.info('%s: No instances on computes under maintenance %s' %
self.session_id)
LOG.info(str(self))
def update_instance(self, project_id, instance_id, instance_name, host,
@ -595,7 +648,7 @@ class Workflow(BaseWorkflow):
LOG.info("%s: No empty host to be maintained" % self.session_id)
self.session.state = 'MAINTENANCE_FAILED'
return
maintained_hosts = self.get_maintained_hosts()
maintained_hosts = self.get_maintained_hosts_by_type('compute')
if not maintained_hosts:
computes = self.get_compute_hosts()
for compute in computes:
@ -641,8 +694,8 @@ class Workflow(BaseWorkflow):
self.enable_host_nova_compute(host)
LOG.info('MAINTENANCE_COMPLETE host %s' % host)
self.host_maintained(host)
maintained_hosts = self.get_maintained_hosts()
if len(maintained_hosts) != len(self.hosts):
maintained_hosts = self.get_maintained_hosts_by_type('compute')
if len(maintained_hosts) != len(self.get_compute_hosts()):
# Not all host maintained
self.session.state = 'PLANNED_MAINTENANCE'
else:
@ -650,8 +703,9 @@ class Workflow(BaseWorkflow):
def planned_maintenance(self):
LOG.info("%s: planned_maintenance called" % self.session_id)
maintained_hosts = self.get_maintained_hosts()
not_maintained_hosts = ([h.hostname for h in self.hosts if h.hostname
maintained_hosts = self.get_maintained_hosts_by_type('compute')
compute_hosts = self.get_compute_hosts()
not_maintained_hosts = ([host for host in compute_hosts if host
not in maintained_hosts])
LOG.info("%s: Not maintained hosts: %s" % (self.session_id,
not_maintained_hosts))