Add health_status and health_status_reason to cluster

APIImpact
Related blueprint cluster-healing

Change-Id: I78d4d14fb064996de77bdd6a381d2df53a9488b8
This commit is contained in:
Feilong Wang 2018-05-15 23:34:09 +12:00
parent ee643b3ccb
commit d80febb384
8 changed files with 91 additions and 2 deletions

View File

@ -134,6 +134,12 @@ class Cluster(base.APIBase):
status_reason = wtypes.text
"""Status reason of the cluster from the heat stack"""
health_status = wtypes.Enum(str, *fields.ClusterStatus.ALL)
"""Health status of the cluster from the native COE API"""
health_status_reason = wtypes.DictType(str, str)
"""Health status reason of the cluster from the native COE API"""
discovery_url = wtypes.text
"""Url used for cluster node discovery"""
@ -211,6 +217,8 @@ class Cluster(base.APIBase):
stack_id='49dc23f5-ffc9-40c3-9d34-7be7f9e34d63',
status=fields.ClusterStatus.CREATE_COMPLETE,
status_reason="CREATE completed successfully",
health_status=fields.ClusterHealthStatus.HEALTHY,
health_status_reason='{"api_server": "OK"}',
api_address='172.24.4.3',
node_addresses=['172.24.4.4', '172.24.4.5'],
created_at=timeutils.utcnow(),

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.
"""Add health_status and health_status_reason to cluster
Revision ID: cbbc65a86986
Revises: 9a1539f1cd2c
Create Date: 2018-05-15 22:24:49.527558
"""
# revision identifiers, used by Alembic.
revision = 'cbbc65a86986'
down_revision = '9a1539f1cd2c'
from alembic import op
import sqlalchemy as sa
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('cluster', sa.Column('health_status',
sa.String(20),
nullable=True))
op.add_column('cluster', sa.Column('health_status_reason',
sa.Text,
nullable=True))
# ### end Alembic commands ###

View File

@ -128,6 +128,8 @@ class Cluster(Base):
master_count = Column(Integer())
status = Column(String(20))
status_reason = Column(Text)
health_status = Column(String(20))
health_status_reason = Column(JSONEncodedDict)
create_timeout = Column(Integer())
discovery_url = Column(String(255, mysql_ndb_type=TINYTEXT))
master_addresses = Column(JSONEncodedList)

View File

@ -46,8 +46,9 @@ class Cluster(base.MagnumPersistentObject, base.MagnumObject,
# Version 1.15: Added 'labels' field
# Version 1.16: Added 'master_flavor_id' field
# Version 1.17: Added 'flavor_id' field
# Version 1.18: Added 'health_status' and 'health_status_reason' field
VERSION = '1.17'
VERSION = '1.18'
dbapi = dbapi.get_instance()
@ -66,6 +67,8 @@ class Cluster(base.MagnumPersistentObject, base.MagnumObject,
'stack_id': fields.StringField(nullable=True),
'status': m_fields.ClusterStatusField(nullable=True),
'status_reason': fields.StringField(nullable=True),
'health_status': m_fields.ClusterHealthStatusField(nullable=True),
'health_status_reason': fields.DictOfStringsField(nullable=True),
'create_timeout': fields.IntegerField(nullable=True),
'api_address': fields.StringField(nullable=True),
'node_addresses': fields.ListOfStringsField(nullable=True),

View File

@ -49,6 +49,19 @@ class ClusterStatus(fields.Enum):
super(ClusterStatus, self).__init__(valid_values=ClusterStatus.ALL)
class ClusterHealthStatus(fields.Enum):
HEALTHY = 'HEALTHY'
UNHEALTHY = 'UNHEALTHY'
ALL = (HEALTHY, UNHEALTHY)
STATUS_FAILED = (UNHEALTHY)
def __init__(self):
super(ClusterHealthStatus, self).__init__(
valid_values=ClusterHealthStatus.ALL)
class FederationStatus(fields.Enum):
CREATE_IN_PROGRESS = 'CREATE_IN_PROGRESS'
CREATE_FAILED = 'CREATE_FAILED'
@ -150,6 +163,10 @@ class ClusterStatusField(fields.BaseEnumField):
AUTO_TYPE = ClusterStatus()
class ClusterHealthStatusField(fields.BaseEnumField):
AUTO_TYPE = ClusterHealthStatus()
class MagnumServiceField(fields.BaseEnumField):
AUTO_TYPE = MagnumServiceState()

View File

@ -40,6 +40,8 @@ class TestClusterObject(base.DbTestCase):
self.fake_cluster['keypair'] = 'keypair1'
self.fake_cluster['docker_volume_size'] = 3
self.fake_cluster['labels'] = {}
self.fake_cluster['health_status'] = 'HEALTHY'
self.fake_cluster['health_status_reason'] = {}
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_get_by_id(self, mock_cluster_template_get):

View File

@ -50,6 +50,25 @@ class TestClusterStatus(test_fields.TestField):
self.assertRaises(ValueError, self.field.stringify, 'DELETE_STOPPED')
class TestClusterHealthStatus(test_fields.TestField):
def setUp(self):
super(TestClusterHealthStatus, self).setUp()
self.field = fields.ClusterHealthStatusField()
self.coerce_good_values = [('HEALTHY', 'HEALTHY'),
('UNHEALTHY', 'UNHEALTHY')]
self.coerce_bad_values = ['FAKE']
self.to_primitive_values = self.coerce_good_values[0:1]
self.from_primitive_values = self.coerce_good_values[0:1]
def test_stringify(self):
self.assertEqual("'UNHEALTHY'",
self.field.stringify('UNHEALTHY'))
def test_stringify_invalid(self):
self.assertRaises(ValueError, self.field.stringify, 'FAKE')
class TestContainerStatus(test_fields.TestField):
def setUp(self):
super(TestContainerStatus, self).setUp()

View File

@ -355,7 +355,7 @@ class TestObject(test_base.TestCase, _TestObject):
# For more information on object version testing, read
# https://docs.openstack.org/magnum/latest/contributor/objects.html
object_data = {
'Cluster': '1.17-c32c07425ab0042c7370bef2902b4d21',
'Cluster': '1.18-9f0dfcc3e898eef2b9a09647b612adb6',
'ClusterTemplate': '1.18-7fa94f4fdd027acfb4f022f202afdfb5',
'Certificate': '1.1-1924dc077daa844f0f9076332ef96815',
'MyObj': '1.0-34c4b1aadefd177b13f9a2f894cc23cd',