Include version info in bay/cluster show operation

Currently bay-show operation does not return bay/cluster
version information. This change contain changes to return
bay/cluster version and container version info.

Change-Id: Ie12b6583e6d85faa3607f87295c04d72698034a5
Closes-Bug: #1613413
This commit is contained in:
Vijendar Komalla 2016-08-23 09:44:57 -05:00
parent c1c6cf0214
commit 50bc376c4d
21 changed files with 180 additions and 11 deletions

View File

@ -111,6 +111,13 @@ class Bay(base.APIBase):
api_address = wsme.wsattr(wtypes.text, readonly=True)
"""Api address of cluster master node"""
coe_version = wsme.wsattr(wtypes.text, readonly=True)
"""Version of the COE software currently running in this cluster.
Example: swarm version or kubernetes version."""
container_version = wsme.wsattr(wtypes.text, readonly=True)
"""Version of the container software. Example: docker version."""
node_addresses = wsme.wsattr([wtypes.text], readonly=True)
"""IP addresses of cluster agent nodes"""
@ -165,7 +172,9 @@ class Bay(base.APIBase):
api_address='172.24.4.3',
node_addresses=['172.24.4.4', '172.24.4.5'],
created_at=timeutils.utcnow(),
updated_at=timeutils.utcnow())
updated_at=timeutils.utcnow(),
coe_version=None,
container_version=None)
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
@ -365,6 +374,8 @@ class BaysController(base.Controller):
# bay if the name is not spcified by user.
name = bay_dict.get('name') or self._generate_name_for_bay(context)
bay_dict['name'] = name
bay_dict['coe_version'] = None
bay_dict['container_version'] = None
new_bay = objects.Bay(context, **bay_dict)
new_bay.uuid = uuid.uuid4()

View File

@ -121,6 +121,13 @@ class Cluster(base.APIBase):
api_address = wsme.wsattr(wtypes.text, readonly=True)
"""Api address of cluster master node"""
coe_version = wsme.wsattr(wtypes.text, readonly=True)
"""Version of the COE software currently running in this cluster.
Example: swarm version or kubernetes version."""
container_version = wsme.wsattr(wtypes.text, readonly=True)
"""Version of the container software. Example: docker version."""
node_addresses = wsme.wsattr([wtypes.text], readonly=True)
"""IP addresses of cluster agent nodes"""
@ -198,7 +205,9 @@ class Cluster(base.APIBase):
api_address='172.24.4.3',
node_addresses=['172.24.4.4', '172.24.4.5'],
created_at=timeutils.utcnow(),
updated_at=timeutils.utcnow())
updated_at=timeutils.utcnow(),
coe_version=None,
container_version=None)
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
def as_dict(self):
@ -405,6 +414,8 @@ class ClustersController(base.Controller):
name = cluster_dict.get('name') or \
self._generate_name_for_cluster(context)
cluster_dict['name'] = name
cluster_dict['coe_version'] = None
cluster_dict['container_version'] = None
new_cluster = objects.Bay(context, **cluster_dict)
new_cluster.uuid = uuid.uuid4()

View File

@ -19,6 +19,7 @@ from heatclient import exc
from oslo_config import cfg
from oslo_log import log as logging
from oslo_service import loopingcall
from oslo_utils import importutils
from pycadf import cadftaxonomy as taxonomy
import six
@ -360,8 +361,27 @@ class HeatPoller(object):
self.bay.node_count = stack.parameters[stack_nc_param]
self.bay.save()
def get_version_info(self, stack):
stack_param = self.template_def.get_heat_param(
bay_attr='coe_version')
if stack_param:
self.bay.coe_version = stack.parameters[stack_param]
tdef = TDef.get_template_definition(self.baymodel.server_type,
self.baymodel.cluster_distro,
self.baymodel.coe)
version_module_path = tdef.driver_module_path+'.version'
try:
ver = importutils.import_module(version_module_path)
container_version = ver.container_version
except Exception:
container_version = None
self.bay.container_version = container_version
def _sync_bay_and_template_status(self, stack):
self.template_def.update_outputs(stack, self.baymodel, self.bay)
self.get_version_info(stack)
self._sync_bay_status(stack)
def _bay_failed(self, stack):

View File

@ -0,0 +1,34 @@
# 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 version info to bay
Revision ID: fcb4efee8f8b
Revises: b1f612248cab
Create Date: 2016-08-22 15:04:32.256811
"""
# revision identifiers, used by Alembic.
revision = 'fcb4efee8f8b'
down_revision = 'b1f612248cab'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('bay',
sa.Column('coe_version', sa.String(length=255),
nullable=True))
op.add_column('bay',
sa.Column('container_version', sa.String(length=255),
nullable=True))

View File

@ -129,6 +129,8 @@ class Bay(Base):
trustee_user_id = Column(String(255))
# TODO(wanghua): encrypt trustee_password in db
trustee_password = Column(String(255))
coe_version = Column(String(255))
container_version = Column(String(255))
# (yuanying) if we use barbican,
# cert_ref size is determined by below format
# * http(s)://${DOMAIN_NAME}/v1/containers/${UUID}

View File

@ -317,6 +317,10 @@ class TemplateDefinition(object):
for output in self.output_mappings:
output.set_output(stack, baymodel, bay)
@abc.abstractproperty
def driver_module_path(self):
pass
@abc.abstractproperty
def template_path(self):
pass
@ -348,6 +352,10 @@ class BaseTemplateDefinition(TemplateDefinition):
self.add_parameter('number_of_masters',
bay_attr='master_count')
@property
def driver_module_path(self):
pass
@abc.abstractproperty
def template_path(self):
pass

View File

@ -73,6 +73,8 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
param_type=str)
self.add_parameter('insecure_registry_url',
baymodel_attr='insecure_registry')
self.add_parameter('kube_version',
bay_attr='coe_version')
self.add_output('api_address',
bay_attr='api_address',
@ -133,6 +135,10 @@ class CoreOSK8sTemplateDefinition(K8sTemplateDefinition):
else:
return ['../../common/templates/environments/no_master_lb.yaml']
@property
def driver_module_path(self):
return __name__[:__name__.rindex('.')]
@property
def template_path(self):
return os.path.join(os.path.dirname(os.path.realpath(__file__)),

View File

@ -0,0 +1,17 @@
# Copyright 2016 - Rackspace Hosting
#
# 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.
version = '1.0.0'
driver = 'k8s_coreos'
container_version = '1.9.0'

View File

@ -77,6 +77,8 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
param_type=str)
self.add_parameter('insecure_registry_url',
baymodel_attr='insecure_registry')
self.add_parameter('kube_version',
bay_attr='coe_version')
self.add_output('api_address',
bay_attr='api_address',
@ -157,6 +159,10 @@ class AtomicK8sTemplateDefinition(K8sTemplateDefinition):
else:
return ['../../common/templates/environments/no_master_lb.yaml']
@property
def driver_module_path(self):
return __name__[:__name__.rindex('.')]
@property
def template_path(self):
return os.path.join(os.path.dirname(os.path.realpath(__file__)),
@ -214,6 +220,10 @@ class FedoraK8sIronicTemplateDefinition(AtomicK8sTemplateDefinition):
extra_params=extra_params,
**kwargs)
@property
def driver_module_path(self):
return __name__[:__name__.rindex('.')]
@property
def template_path(self):
return os.path.join(os.path.dirname(os.path.realpath(__file__)),

View File

@ -14,3 +14,4 @@
version = '1.0.0'
driver = 'k8s_fedora_atomic'
container_version = '1.9.1'

View File

@ -87,6 +87,10 @@ class UbuntuMesosTemplateDefinition(template_def.BaseTemplateDefinition):
else:
return ['../../common/templates/environments/no_master_lb.yaml']
@property
def driver_module_path(self):
return __name__[:__name__.rindex('.')]
@property
def template_path(self):
return os.path.join(os.path.dirname(os.path.realpath(__file__)),

View File

@ -0,0 +1,17 @@
# Copyright 2016 - Rackspace Hosting
#
# 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.
version = '1.0.0'
driver = 'mesos_ubuntu'
container_version = '1.9.1'

View File

@ -71,6 +71,9 @@ class AtomicSwarmTemplateDefinition(template_def.BaseTemplateDefinition):
baymodel_attr='registry_enabled')
self.add_parameter('docker_storage_driver',
baymodel_attr='docker_storage_driver')
self.add_parameter('swarm_version',
bay_attr='coe_version')
self.add_output('api_address',
bay_attr='api_address',
mapping_type=SwarmApiAddressOutputMapping)
@ -116,6 +119,10 @@ class AtomicSwarmTemplateDefinition(template_def.BaseTemplateDefinition):
else:
return ['../../common/templates/environments/no_master_lb.yaml']
@property
def driver_module_path(self):
return __name__[:__name__.rindex('.')]
@property
def template_path(self):
return os.path.join(os.path.dirname(os.path.realpath(__file__)),

View File

@ -14,3 +14,4 @@
version = '1.0.0'
driver = 'swarm_atomic'
container_version = '1.9.1'

View File

@ -36,7 +36,8 @@ class Bay(base.MagnumPersistentObject, base.MagnumObject,
# Add 'trustee_user_name', 'trustee_password',
# 'trustee_user_id' field
# Version 1.6: Add rollback support for Bay
VERSION = '1.6'
# Version 1.7: Added 'coe_version' and 'container_version' fields
VERSION = '1.7'
dbapi = dbapi.get_instance()
@ -63,7 +64,9 @@ class Bay(base.MagnumPersistentObject, base.MagnumObject,
'trust_id': fields.StringField(nullable=True),
'trustee_username': fields.StringField(nullable=True),
'trustee_password': fields.StringField(nullable=True),
'trustee_user_id': fields.StringField(nullable=True)
'trustee_user_id': fields.StringField(nullable=True),
'coe_version': fields.StringField(nullable=True),
'container_version': fields.StringField(nullable=True)
}
@staticmethod

View File

@ -502,6 +502,7 @@ class TestHeatPoller(base.TestCase):
baymodel = objects.BayModel(self.context, **baymodel_dict)
mock_retrieve_baymodel.return_value = baymodel
poller = bay_conductor.HeatPoller(mock_openstack_client, bay)
poller.get_version_info = mock.MagicMock()
return (mock_heat_stack, bay, poller)
def test_poll_and_check_send_notification(self):

View File

@ -67,6 +67,7 @@ class TestBayConductorWithK8s(base.TestCase):
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'coe_version': 'fake-version',
}
self.context.auth_url = 'http://192.168.10.10:5000/v3'
self.context.user_name = 'fake_user'
@ -172,6 +173,7 @@ class TestBayConductorWithK8s(base.TestCase):
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3',
'insecure_registry_url': '10.0.0.1:5000',
'kube_version': 'fake-version',
}
if missing_attr is not None:
expected.pop(mapping[missing_attr], None)
@ -242,6 +244,7 @@ class TestBayConductorWithK8s(base.TestCase):
'username': 'fake_user',
'volume_driver': 'volume_driver',
'insecure_registry_url': '10.0.0.1:5000',
'kube_version': 'fake-version',
}
self.assertEqual(expected, definition)
@ -299,6 +302,7 @@ class TestBayConductorWithK8s(base.TestCase):
'bay_uuid': self.bay_dict['uuid'],
'magnum_url': self.mock_osc.magnum_url.return_value,
'insecure_registry_url': '10.0.0.1:5000',
'kube_version': 'fake-version',
}
self.assertEqual(expected, definition)
self.assertEqual(
@ -353,6 +357,7 @@ class TestBayConductorWithK8s(base.TestCase):
'bay_uuid': self.bay_dict['uuid'],
'magnum_url': self.mock_osc.magnum_url.return_value,
'insecure_registry_url': '10.0.0.1:5000',
'kube_version': 'fake-version',
}
self.assertEqual(expected, definition)
self.assertEqual(
@ -515,6 +520,7 @@ class TestBayConductorWithK8s(base.TestCase):
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3',
'insecure_registry_url': '10.0.0.1:5000',
'kube_version': 'fake-version',
}
self.assertEqual(expected, definition)
self.assertEqual(

View File

@ -284,6 +284,7 @@ class TestBayConductorWithMesos(base.TestCase):
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_retrieve_baymodel.return_value = baymodel
poller = bay_conductor.HeatPoller(mock_openstack_client, bay)
poller.get_version_info = mock.MagicMock()
return (mock_heat_stack, bay, poller)
def test_poll_node_count(self):

View File

@ -63,7 +63,8 @@ class TestBayConductorWithSwarm(base.TestCase):
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de'
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'coe_version': 'fake-version'
}
osc_patcher = mock.patch('magnum.common.clients.OpenStackClients')
self.mock_osc_class = osc_patcher.start()
@ -124,7 +125,8 @@ class TestBayConductorWithSwarm(base.TestCase):
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3'
'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version'
}
self.assertEqual(expected, definition)
self.assertEqual(
@ -186,7 +188,8 @@ class TestBayConductorWithSwarm(base.TestCase):
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3',
'docker_storage_driver': 'devicemapper'
'docker_storage_driver': 'devicemapper',
'swarm_version': 'fake-version'
}
self.assertEqual(expected, definition)
self.assertEqual(
@ -240,7 +243,8 @@ class TestBayConductorWithSwarm(base.TestCase):
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3'
'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version'
}
self.assertEqual(expected, definition)
self.assertEqual(
@ -296,7 +300,8 @@ class TestBayConductorWithSwarm(base.TestCase):
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3'
'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version'
}
self.assertEqual(expected, definition)
self.assertEqual(
@ -353,7 +358,8 @@ class TestBayConductorWithSwarm(base.TestCase):
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3'
'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version'
}
self.assertEqual(expected, definition)
self.assertEqual(
@ -374,6 +380,7 @@ class TestBayConductorWithSwarm(base.TestCase):
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_retrieve_baymodel.return_value = baymodel
poller = bay_conductor.HeatPoller(mock_openstack_client, bay)
poller.get_version_info = mock.MagicMock()
return (mock_heat_stack, bay, poller)
def test_poll_node_count(self):

View File

@ -32,6 +32,8 @@ class TestBayObject(base.DbTestCase):
self.fake_bay['trustee_username'] = 'trustee_user'
self.fake_bay['trustee_user_id'] = 'trustee_user_id'
self.fake_bay['trustee_password'] = 'password'
self.fake_bay['coe_version'] = 'fake-coe-version'
self.fake_bay['container_version'] = 'fake-container-version'
baymodel_id = self.fake_bay['baymodel_id']
self.fake_baymodel = objects.BayModel(uuid=baymodel_id)

View File

@ -362,7 +362,7 @@ class TestObject(test_base.TestCase, _TestObject):
# For more information on object version testing, read
# http://docs.openstack.org/developer/magnum/objects.html
object_data = {
'Bay': '1.6-2386f79585a6c24bc7960884a4d0ebce',
'Bay': '1.7-88cb12f991721fe31602dc3fd7acd654',
'BayModel': '1.15-9b961246b348aa380783dae14014e423',
'Certificate': '1.0-2aff667971b85c1edf8d15684fd7d5e2',
'MyObj': '1.0-b43567e512438205e32f4e95ca616697',