dcmanager for containerized openstack services - service

This update enhanced dcmanager to be able to manage containerized
openstack services of subclouds that have openstack application
deployed.

dcmanager audit query subcloud periodically to check whether
stx-openstack application is installed or not. If it's installed from
previous uninstalled, the subcloud's "openstack_installed" field will be
updated from "False" to "True", openstack sync endpoint types will be
added into subcloud sync endpoint type list, and notify dcorch to update
its sync threads. If it's uninstalled from previous installed, the
subcloud's "openstack_installed" field will be updated from "True" back
to "False", openstack sync endpoint types will be removed from subcloud
sync endpoint type list, and notify dcorch to update its sync threads.

The endpoint type sync status of openstack services will be available
to dcmanager commands such as "dcmanager subcloud list".

Change-Id: I651bebbef0f0a4dd39ec2371a7397c066c747622
Story: 2004766
Task: 36261
Signed-off-by: Andy Ning <andy.ning@windriver.com>
This commit is contained in:
Andy Ning 2019-07-17 10:21:16 -04:00
parent 36702d225c
commit 28aa599715
9 changed files with 139 additions and 9 deletions

View File

@ -27,6 +27,8 @@
import sys
import eventlet
eventlet.monkey_patch(os=False)
from oslo_config import cfg
from oslo_log import log as logging
from oslo_service import systemd
@ -43,7 +45,6 @@ from dcorch.common import messaging as dcorch_messaging
CONF = cfg.CONF
config.register_options()
LOG = logging.getLogger('dcmanager.api')
eventlet.monkey_patch(os=False)
def main():

View File

@ -63,6 +63,7 @@ def subcloud_db_model_to_dict(subcloud):
"management-start-ip": subcloud.management_start_ip,
"management-end-ip": subcloud.management_end_ip,
"management-gateway-ip": subcloud.management_gateway_ip,
"openstack-installed": subcloud.openstack_installed,
"systemcontroller-gateway-ip":
subcloud.systemcontroller_gateway_ip,
"created-at": subcloud.created_at,
@ -73,13 +74,15 @@ def subcloud_db_model_to_dict(subcloud):
def subcloud_create(context, name, description, location, software_version,
management_subnet, management_gateway_ip,
management_start_ip, management_end_ip,
systemcontroller_gateway_ip, deploy_status):
systemcontroller_gateway_ip, deploy_status,
openstack_installed):
"""Create a subcloud."""
return IMPL.subcloud_create(context, name, description, location,
software_version,
management_subnet, management_gateway_ip,
management_start_ip, management_end_ip,
systemcontroller_gateway_ip, deploy_status)
systemcontroller_gateway_ip, deploy_status,
openstack_installed)
def subcloud_get(context, subcloud_id):
@ -110,12 +113,12 @@ def subcloud_get_all_with_status(context):
def subcloud_update(context, subcloud_id, management_state=None,
availability_status=None, software_version=None,
description=None, location=None, audit_fail_count=None,
deploy_status=None):
deploy_status=None, openstack_installed=None):
"""Update a subcloud or raise if it does not exist."""
return IMPL.subcloud_update(context, subcloud_id, management_state,
availability_status, software_version,
description, location, audit_fail_count,
deploy_status)
deploy_status, openstack_installed)
def subcloud_destroy(context, subcloud_id):
@ -130,6 +133,11 @@ def subcloud_status_create(context, subcloud_id, endpoint_type):
return IMPL.subcloud_status_create(context, subcloud_id, endpoint_type)
def subcloud_status_delete(context, subcloud_id, endpoint_type):
"""Delete a subcloud status for an endpoint_type."""
return IMPL.subcloud_status_delete(context, subcloud_id, endpoint_type)
def subcloud_status_db_model_to_dict(subcloud_status):
"""Convert subcloud status db model to dictionary."""
if subcloud_status:

View File

@ -205,7 +205,8 @@ def subcloud_get_all_with_status(context):
def subcloud_create(context, name, description, location, software_version,
management_subnet, management_gateway_ip,
management_start_ip, management_end_ip,
systemcontroller_gateway_ip, deploy_status):
systemcontroller_gateway_ip, deploy_status,
openstack_installed):
with write_session() as session:
subcloud_ref = models.Subcloud()
subcloud_ref.name = name
@ -221,6 +222,7 @@ def subcloud_create(context, name, description, location, software_version,
subcloud_ref.systemcontroller_gateway_ip = systemcontroller_gateway_ip
subcloud_ref.deploy_status = deploy_status
subcloud_ref.audit_fail_count = 0
subcloud_ref.openstack_installed = openstack_installed
session.add(subcloud_ref)
return subcloud_ref
@ -229,7 +231,7 @@ def subcloud_create(context, name, description, location, software_version,
def subcloud_update(context, subcloud_id, management_state=None,
availability_status=None, software_version=None,
description=None, location=None, audit_fail_count=None,
deploy_status=None):
deploy_status=None, openstack_installed=None):
with write_session() as session:
subcloud_ref = subcloud_get(context, subcloud_id)
if management_state is not None:
@ -246,6 +248,8 @@ def subcloud_update(context, subcloud_id, management_state=None,
subcloud_ref.audit_fail_count = audit_fail_count
if deploy_status is not None:
subcloud_ref.deploy_status = deploy_status
if openstack_installed is not None:
subcloud_ref.openstack_installed = openstack_installed
subcloud_ref.save(session)
return subcloud_ref
@ -304,6 +308,14 @@ def subcloud_status_create(context, subcloud_id, endpoint_type):
return subcloud_status_ref
@require_admin_context
def subcloud_status_delete(context, subcloud_id, endpoint_type):
with write_session() as session:
subcloud_status_ref = subcloud_status_get(context, subcloud_id,
endpoint_type)
session.delete(subcloud_status_ref)
@require_admin_context
def subcloud_status_update(context, subcloud_id, endpoint_type, sync_status):
with write_session() as session:

View File

@ -0,0 +1,38 @@
# 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.
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from sqlalchemy import Column, MetaData, Table, Boolean
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
subclouds = Table('subclouds', meta, autoload=True)
# Add the 'openstack_installed' column to the subclouds table.
subclouds.create_column(Column('openstack_installed', Boolean,
nullable=False, default=False,
server_default='0'))
return True
def downgrade(migrate_engine):
raise NotImplementedError('Database downgrade is unsupported.')

View File

@ -92,6 +92,7 @@ class Subcloud(BASE, DCManagerBase):
management_gateway_ip = Column(String(255))
management_start_ip = Column(String(255), unique=True)
management_end_ip = Column(String(255), unique=True)
openstack_installed = Column(Boolean, nullable=False, default=False)
systemcontroller_gateway_ip = Column(String(255))
audit_fail_count = Column(Integer)

View File

@ -124,3 +124,9 @@ class SysinvClient(base.DriverBase):
def get_loads(self):
"""Get a list of loads."""
return self.sysinv_client.load.list()
def get_applications(self):
"""Get a list of containerized applications"""
# Get a list of containerized applications the system knows of
return self.sysinv_client.app.list()

View File

@ -22,7 +22,7 @@
from oslo_log import log as logging
from dcorch.common import consts as dcorch_consts
from dcorch.drivers.openstack.keystone_v3 import KeystoneClient
from dcorch.rpc import client as dcorch_rpc_client
@ -38,6 +38,7 @@ from keystoneauth1 import exceptions as keystone_exceptions
from fm_api import constants as fm_const
from fm_api import fm_api
from sysinv.common import constants as sysinv_constants
LOG = logging.getLogger(__name__)
@ -79,6 +80,7 @@ class SubcloudAuditManager(manager.Manager):
management_state = subcloud.management_state
avail_status_current = subcloud.availability_status
audit_fail_count = subcloud.audit_fail_count
openstack_installed = subcloud.openstack_installed
# Set defaults to None and disabled so we will still set disabled
# status if we encounter an error.
@ -106,6 +108,7 @@ class SubcloudAuditManager(manager.Manager):
LOG.exception(e)
if sysinv_client:
# get a list of service groups in the subcloud
try:
svc_groups = sysinv_client.get_service_groups()
except Exception as e:
@ -257,3 +260,61 @@ class SubcloudAuditManager(manager.Manager):
LOG.info('Ignoring SubcloudNotFound when attempting '
'audit_fail_count update: %s' % subcloud_name)
continue
if sysinv_client:
# get a list of installed apps in the subcloud
try:
apps = sysinv_client.get_applications()
except Exception as e:
apps = None
LOG.warn('Cannot retrieve installed apps for '
'subcloud:%s, %s' % (subcloud_name, e))
if apps:
openstack_installed_current = False
for app in apps:
if app.name == sysinv_constants.HELM_APP_OPENSTACK\
and app.active:
# audit find openstack app is installed and active in
# the subcloud
openstack_installed_current = True
break
dcm_update_func = None
dco_update_func = None
if openstack_installed_current and not openstack_installed:
dcm_update_func = db_api.subcloud_status_create
dco_update_func = self.dcorch_rpc_client.\
add_subcloud_sync_endpoint_type
elif not openstack_installed_current and openstack_installed:
dcm_update_func = db_api.subcloud_status_delete
dco_update_func = self.dcorch_rpc_client.\
remove_subcloud_sync_endpoint_type
if dcm_update_func and dco_update_func:
endpoint_type_list = dcorch_consts.ENDPOINT_TYPES_LIST_OS
try:
# Notify dcorch to add/remove sync endpoint type list
dco_update_func(self.context, subcloud_name,
endpoint_type_list)
LOG.info('Notifying dcorch, subcloud: %s new sync'
' endpoint: %s' % (subcloud_name,
endpoint_type_list))
# Update subcloud status table by adding/removing
# openstack sync endpoint types.
for endpoint_type in endpoint_type_list:
dcm_update_func(self.context, subcloud_id,
endpoint_type)
# Update openstack_installed of subcloud table
db_api.subcloud_update(
self.context, subcloud_id,
openstack_installed=openstack_installed_current)
except exceptions.SubcloudNotFound:
LOG.info('Ignoring SubcloudNotFound when attempting'
' openstack_installed update: %s'
% subcloud_name)
except Exception as e:
LOG.exception(e)
LOG.warn('Problem informing dcorch of subcloud '
'sync endpoint type change, subcloud: %s'
% subcloud_name)

View File

@ -120,7 +120,8 @@ class SubcloudManager(manager.Manager):
payload['management_start_address'],
payload['management_end_address'],
payload['systemcontroller_gateway_address'],
consts.DEPLOY_STATE_NONE)
consts.DEPLOY_STATE_NONE,
False)
except Exception as e:
LOG.exception(e)
raise e

View File

@ -86,6 +86,7 @@ class DBAPISubcloudTest(base.DCManagerTestCase):
'management_end_ip': "192.168.101.50",
'systemcontroller_gateway_ip': "192.168.204.101",
'deploy_status': "not-deployed",
'openstack_installed': False,
}
values.update(kwargs)
return db_api.subcloud_create(ctxt, **values)
@ -104,6 +105,7 @@ class DBAPISubcloudTest(base.DCManagerTestCase):
'systemcontroller_gateway_ip': data[
'systemcontroller_gateway_address'],
'deploy_status': "not-deployed",
'openstack_installed': False,
}
return db_api.subcloud_create(ctxt, **values)