Show Subcloud Deploy Configuration Status
This commit extends the "dcmanager subcloud show <subcloud> --detail" command to display the deploy configuration status of the subcloud from the systemcontroller. The presence of a 260.002 alarm related to a 'host' resource on an online subcloud indicates an outdated deploy configuration. In such cases, the field will display "Deployment: configurations out-of-date". Otherwise, the field will show: "Deployment: configurations up-to-date". The field will not be shown for offline subclouds. Test Plan: PASS: Successful bring up of a fresh DC system with these changes. PASS: Run 'dcmanager subcloud show' without the '--detail' argument. Verify that the new field is not being shown. PASS: Run 'dcmanager subcloud show --detail' for an online subcloud containing a 260.002 alarm related to a host resource. Verify that the output contains 'Deployment: configurations out-of-date'. PASS: Run 'dcmanager subcloud show --detail' for an online subcloud containing a 260.002 alarm related to a resource other than host. Verify that the output contains 'Deployment: configurations up-to-date'. PASS: Run 'dcmanager subcloud show --detail' for an online subcloud without a 260.002 alarm. Verify that the output contains 'Deployment: configurations up-to-date'. PASS: Run 'dcmanager subcloud show --detail' for an offline subcloud. Verify that the new field is not being shown. Story: 2010719 Task: 48025 Change-Id: I223919ded1d6d5dfcc81c2060c5e6491ed8a73d9 Signed-off-by: Enzo Candotti <enzo.candotti@windriver.com>
This commit is contained in:
parent
f174505b66
commit
e88471cd38
@ -21,6 +21,7 @@
|
||||
"data_install": null,
|
||||
"data_upgrade": null,
|
||||
"oam_floating_ip": "192.168.101.2",
|
||||
"config_sync_status": "Deployment: configurations up-to-date"
|
||||
"endpoint_sync_status": [
|
||||
{
|
||||
"sync_status": "in-sync",
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
||||
# Copyright (c) 2020-2023 Wind River Systems, Inc.
|
||||
# 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
|
||||
@ -124,6 +124,11 @@ SYNC_STATUS_UNKNOWN = "unknown"
|
||||
SYNC_STATUS_IN_SYNC = "in-sync"
|
||||
SYNC_STATUS_OUT_OF_SYNC = "out-of-sync"
|
||||
|
||||
# Subcloud deploy configuration status
|
||||
DEPLOY_CONFIG_UP_TO_DATE = 'Deployment: configurations up-to-date'
|
||||
DEPLOY_CONFIG_OUT_OF_DATE = 'Deployment: configurations out-of-date'
|
||||
MONITORED_ALARM_ENTITIES = ['host.starlingx.windriver.com', ]
|
||||
|
||||
# OS type
|
||||
OS_RELEASE_FILE = '/etc/os-release'
|
||||
OS_CENTOS = 'centos'
|
||||
|
@ -39,6 +39,7 @@ from pecan import expose
|
||||
from pecan import request
|
||||
|
||||
from dccommon import consts as dccommon_consts
|
||||
from dccommon.drivers.openstack.fm import FmClient
|
||||
from dccommon.drivers.openstack import patching_v1
|
||||
from dccommon.drivers.openstack.patching_v1 import PatchingClient
|
||||
from dccommon.drivers.openstack.sdk_platform import OpenStackDriver
|
||||
@ -61,6 +62,7 @@ from dcmanager.common import utils
|
||||
from dcmanager.db import api as db_api
|
||||
|
||||
from dcmanager.rpc import client as rpc_client
|
||||
from fm_api.constants import FM_ALARM_ID_UNSYNCHRONIZED_RESOURCE
|
||||
from six.moves import range
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -1006,12 +1008,11 @@ class SubcloudsController(object):
|
||||
return sysinv_client.get_management_address_pool()
|
||||
|
||||
# TODO(gsilvatr): refactor to use implementation from common/utils and test
|
||||
def _get_oam_addresses(self, context, subcloud_name):
|
||||
def _get_oam_addresses(self, context, subcloud_name, sc_ks_client):
|
||||
"""Get the subclouds oam addresses"""
|
||||
|
||||
# First need to retrieve the Subcloud's Keystone session
|
||||
try:
|
||||
sc_ks_client = self.get_ks_client(subcloud_name)
|
||||
endpoint = sc_ks_client.endpoint_cache.get_endpoint('sysinv')
|
||||
sysinv_client = SysinvClient(subcloud_name,
|
||||
sc_ks_client.session,
|
||||
@ -1027,6 +1028,31 @@ class SubcloudsController(object):
|
||||
LOG.error(message)
|
||||
return None
|
||||
|
||||
def _get_deploy_config_sync_status(self, context, subcloud_name, keystone_client):
|
||||
"""Get the deploy configuration insync status of the subcloud """
|
||||
detected_alarms = None
|
||||
try:
|
||||
fm_client = FmClient(subcloud_name, keystone_client.session)
|
||||
detected_alarms = fm_client.get_alarms_by_id(
|
||||
FM_ALARM_ID_UNSYNCHRONIZED_RESOURCE)
|
||||
except Exception as ex:
|
||||
LOG.error(str(ex))
|
||||
return None
|
||||
|
||||
out_of_date = False
|
||||
if detected_alarms:
|
||||
# Check if any alarm.entity_instance_id contains any of the values
|
||||
# in MONITORED_ALARM_ENTITIES.
|
||||
# We want to scope 260.002 alarms to the host entity only.
|
||||
out_of_date = any(
|
||||
any(entity_id in alarm.entity_instance_id
|
||||
for entity_id in dccommon_consts.MONITORED_ALARM_ENTITIES)
|
||||
for alarm in detected_alarms
|
||||
)
|
||||
sync_status = dccommon_consts.DEPLOY_CONFIG_OUT_OF_DATE if out_of_date \
|
||||
else dccommon_consts.DEPLOY_CONFIG_UP_TO_DATE
|
||||
return sync_status
|
||||
|
||||
def _add_subcloud_to_database(self, context, payload):
|
||||
try:
|
||||
db_api.subcloud_get_by_name(context, payload['name'])
|
||||
@ -1190,16 +1216,26 @@ class SubcloudsController(object):
|
||||
|
||||
if detail is not None:
|
||||
oam_floating_ip = "unavailable"
|
||||
config_sync_status = "unknown"
|
||||
if subcloud.availability_status == dccommon_consts.AVAILABILITY_ONLINE:
|
||||
|
||||
# Get the keystone client that will be used
|
||||
# for _get_deploy_config_sync_status and _get_oam_addresses
|
||||
sc_ks_client = self.get_ks_client(subcloud.name)
|
||||
oam_addresses = self._get_oam_addresses(context,
|
||||
subcloud.name)
|
||||
subcloud.name, sc_ks_client)
|
||||
if oam_addresses is not None:
|
||||
oam_floating_ip = oam_addresses.oam_floating_ip
|
||||
|
||||
floating_ip_dict = {"oam_floating_ip":
|
||||
oam_floating_ip}
|
||||
subcloud_dict.update(floating_ip_dict)
|
||||
deploy_config_state = self._get_deploy_config_sync_status(
|
||||
context, subcloud.name, sc_ks_client)
|
||||
if deploy_config_state is not None:
|
||||
config_sync_status = deploy_config_state
|
||||
|
||||
extra_details = {"oam_floating_ip": oam_floating_ip,
|
||||
"config_sync_status": config_sync_status}
|
||||
|
||||
subcloud_dict.update(extra_details)
|
||||
return subcloud_dict
|
||||
|
||||
@utils.synchronized(LOCK_NAME)
|
||||
|
@ -1051,12 +1051,18 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
|
||||
self.assertEqual(response.json.get('oam_floating_ip', None), None)
|
||||
self.assertEqual(response.json['name'], subcloud.name)
|
||||
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'_get_deploy_config_sync_status')
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'_get_oam_addresses')
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'get_ks_client')
|
||||
@mock.patch.object(rpc_client, 'ManagerClient')
|
||||
def test_get_online_subcloud_with_additional_detail(self,
|
||||
mock_rpc_client,
|
||||
mock_get_oam_addresses):
|
||||
mock_get_ks_client,
|
||||
mock_get_oam_addresses,
|
||||
mock_get_deploy_config_sync_status):
|
||||
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
|
||||
updated_subcloud = db_api.subcloud_update(
|
||||
self.ctx, subcloud.id, availability_status=dccommon_consts.AVAILABILITY_ONLINE)
|
||||
@ -1069,11 +1075,14 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
|
||||
'10.10.10.3',
|
||||
'10.10.10.1',
|
||||
'10.10.10.2')
|
||||
mock_get_ks_client.return_value = 'ks_client'
|
||||
mock_get_oam_addresses.return_value = oam_addresses
|
||||
mock_get_deploy_config_sync_status.return_value = dccommon_consts.DEPLOY_CONFIG_UP_TO_DATE
|
||||
response = self.app.get(get_url, headers=FAKE_HEADERS)
|
||||
self.assertEqual(response.content_type, 'application/json')
|
||||
self.assertEqual(response.status_code, http_client.OK)
|
||||
self.assertEqual('10.10.10.2', response.json['oam_floating_ip'])
|
||||
self.assertEqual('Deployment: configurations up-to-date', response.json['config_sync_status'])
|
||||
|
||||
@mock.patch.object(rpc_client, 'ManagerClient')
|
||||
def test_get_offline_subcloud_with_additional_detail(self,
|
||||
@ -1084,18 +1093,47 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
|
||||
self.assertEqual(response.content_type, 'application/json')
|
||||
self.assertEqual(response.status_code, http_client.OK)
|
||||
self.assertEqual('unavailable', response.json['oam_floating_ip'])
|
||||
self.assertEqual('unknown', response.json['config_sync_status'])
|
||||
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'_get_deploy_config_sync_status')
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'_get_oam_addresses')
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'get_ks_client')
|
||||
@mock.patch.object(rpc_client, 'ManagerClient')
|
||||
def test_get_subcloud_deploy_config_status_unknown(self,
|
||||
mock_rpc_client,
|
||||
mock_get_ks_client,
|
||||
mock_get_oam_addresses,
|
||||
mock_get_deploy_config_sync_status):
|
||||
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
|
||||
updated_subcloud = db_api.subcloud_update(
|
||||
self.ctx, subcloud.id, availability_status=dccommon_consts.AVAILABILITY_ONLINE)
|
||||
get_url = FAKE_URL + '/' + str(updated_subcloud.id) + '/detail'
|
||||
mock_get_ks_client.return_value = 'ks_client'
|
||||
mock_get_oam_addresses.return_value = None
|
||||
mock_get_deploy_config_sync_status.return_value = None
|
||||
response = self.app.get(get_url, headers=FAKE_HEADERS)
|
||||
self.assertEqual(response.content_type, 'application/json')
|
||||
self.assertEqual(response.status_code, http_client.OK)
|
||||
self.assertEqual('unknown', response.json['config_sync_status'])
|
||||
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'_get_oam_addresses')
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'get_ks_client')
|
||||
@mock.patch.object(rpc_client, 'ManagerClient')
|
||||
def test_get_subcloud_oam_ip_unavailable(self,
|
||||
mock_rpc_client,
|
||||
mock_get_ks_client,
|
||||
mock_get_oam_addresses):
|
||||
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
|
||||
updated_subcloud = db_api.subcloud_update(
|
||||
self.ctx, subcloud.id, availability_status=dccommon_consts.AVAILABILITY_ONLINE)
|
||||
|
||||
get_url = FAKE_URL + '/' + str(updated_subcloud.id) + '/detail'
|
||||
mock_get_ks_client.return_value = 'ks_client'
|
||||
mock_get_oam_addresses.return_value = None
|
||||
response = self.app.get(get_url, headers=FAKE_HEADERS)
|
||||
self.assertEqual(response.content_type, 'application/json')
|
||||
|
Loading…
Reference in New Issue
Block a user