Kubernetes, VIM label support

Changes include:
-Updates to VIM host retrieval to also retrieve kubernetes labels.
-Update VIM webserver to display labels.

Change-Id: I6d0613c8b66cd2396a16976aebde2a845597f96a
Story: 2002843
Task: 27752
Depends-On: https://review.openstack.org/615179
Signed-off-by: Kevin Smith <kevin.smith@windriver.com>
This commit is contained in:
Kevin Smith 2018-11-01 15:26:34 -04:00
parent 47d02931f0
commit 5e0f81481a
17 changed files with 286 additions and 74 deletions

View File

@ -128,6 +128,27 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
else:
return False
@staticmethod
def _get_host_labels(host_label_list):
openstack_compute = False
openstack_control = False
OS_COMPUTE = nfvi.objects.v1.HOST_LABEL_KEYS.OS_COMPUTE_NODE
OS_CONTROL = nfvi.objects.v1.HOST_LABEL_KEYS.OS_CONTROL_PLANE
LABEL_ENABLED = nfvi.objects.v1.HOST_LABEL_VALUES.ENABLED
for host_label in host_label_list:
if host_label['label_key'] == OS_COMPUTE:
if host_label['label_value'] == LABEL_ENABLED:
openstack_compute = True
elif host_label['label_key'] == OS_CONTROL:
if host_label['label_value'] == LABEL_ENABLED:
openstack_control = True
return (openstack_compute, openstack_control)
def __init__(self):
super(NFVIInfrastructureAPI, self).__init__()
self._platform_token = None
@ -140,6 +161,7 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
self._host_state_change_callbacks = list()
self._host_get_callbacks = list()
self._host_upgrade_callbacks = list()
self._host_update_callbacks = list()
self._host_notification_callbacks = list()
self._neutron_extensions = None
self._data_port_fault_handling_enabled = False
@ -346,6 +368,19 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
software_load = host_data['software_load']
target_load = host_data['target_load']
future.work(sysinv.get_host_labels, self._platform_token,
host_uuid)
future.result = (yield)
if not future.result.is_complete():
DLOG.error("Get-Host-Labels did not complete.")
response['incomplete-hosts'].append(host_data['hostname'])
continue
host_label_list = future.result.data['labels']
openstack_compute, openstack_control = self._get_host_labels(host_label_list)
admin_state, oper_state, avail_status, nfvi_data \
= host_state(host_uuid, host_name, host_personality,
host_sub_functions, host_admin_state,
@ -364,6 +399,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
host_data['uptime'],
software_load,
target_load,
openstack_compute,
openstack_control,
nfvi_data)
host_objs.append(host_obj)
@ -473,6 +510,18 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
data_port_avail_status,
self._data_port_fault_handling_enabled)
future.work(sysinv.get_host_labels, self._platform_token, host_uuid)
future.result = (yield)
if not future.result.is_complete():
DLOG.error("Get-Host-Labels did not complete, host=%s."
% host_name)
return
host_label_list = future.result.data['labels']
openstack_compute, openstack_control = self._get_host_labels(host_label_list)
host_obj = nfvi.objects.v1.Host(host_uuid, host_name,
host_sub_functions,
admin_state, oper_state,
@ -481,6 +530,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
host_data['uptime'],
software_load,
target_load,
openstack_compute,
openstack_control,
nfvi_data)
response['result-data'] = host_obj
@ -1614,6 +1665,18 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
data_port_avail_status,
self._data_port_fault_handling_enabled)
future.work(sysinv.get_host_labels, self._platform_token, host_uuid)
future.result = (yield)
if not future.result.is_complete():
DLOG.error("Get-Host-Labels did not complete, host=%s."
% host_name)
return
host_label_list = future.result.data['labels']
openstack_compute, openstack_control = self._get_host_labels(host_label_list)
host_obj = nfvi.objects.v1.Host(host_uuid, host_name,
host_sub_functions,
admin_state, oper_state,
@ -1622,6 +1685,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
host_data['uptime'],
software_load,
target_load,
openstack_compute,
openstack_control,
nfvi_data)
response['result-data'] = host_obj
@ -1715,6 +1780,18 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
data_port_avail_status,
self._data_port_fault_handling_enabled)
future.work(sysinv.get_host_labels, self._platform_token, host_uuid)
future.result = (yield)
if not future.result.is_complete():
DLOG.error("Get-Host-Labels did not complete, host=%s."
% host_name)
return
host_label_list = future.result.data['labels']
openstack_compute, openstack_control = self._get_host_labels(host_label_list)
host_obj = nfvi.objects.v1.Host(host_uuid, host_name,
host_sub_functions,
admin_state, oper_state,
@ -1723,6 +1800,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
host_data['uptime'],
software_load,
target_load,
openstack_compute,
openstack_control,
nfvi_data)
response['result-data'] = host_obj
@ -1815,6 +1894,18 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
data_port_avail_status,
self._data_port_fault_handling_enabled)
future.work(sysinv.get_host_labels, self._platform_token, host_uuid)
future.result = (yield)
if not future.result.is_complete():
DLOG.error("Get-Host-Labels did not complete, host=%s."
% host_name)
return
host_label_list = future.result.data['labels']
openstack_compute, openstack_control = self._get_host_labels(host_label_list)
host_obj = nfvi.objects.v1.Host(host_uuid, host_name,
host_sub_functions,
admin_state, oper_state,
@ -1823,6 +1914,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
host_data['uptime'],
software_load,
target_load,
openstack_compute,
openstack_control,
nfvi_data)
response['result-data'] = host_obj
@ -1914,6 +2007,18 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
data_port_avail_status,
self._data_port_fault_handling_enabled)
future.work(sysinv.get_host_labels, self._platform_token, host_uuid)
future.result = (yield)
if not future.result.is_complete():
DLOG.error("Get-Host-Labels did not complete, host=%s."
% host_name)
return
host_label_list = future.result.data['labels']
openstack_compute, openstack_control = self._get_host_labels(host_label_list)
host_obj = nfvi.objects.v1.Host(host_uuid, host_name,
host_sub_functions,
admin_state, oper_state,
@ -1922,6 +2027,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
host_data['uptime'],
software_load,
target_load,
openstack_compute,
openstack_control,
nfvi_data)
response['result-data'] = host_obj
@ -2065,6 +2172,18 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
data_port_avail_status,
self._data_port_fault_handling_enabled)
future.work(sysinv.get_host_labels, self._platform_token, host_uuid)
future.result = (yield)
if not future.result.is_complete():
DLOG.error("Get-Host-Labels did not complete, host=%s."
% host_name)
return
host_label_list = future.result.data['labels']
openstack_compute, openstack_control = self._get_host_labels(host_label_list)
host_obj = nfvi.objects.v1.Host(host_uuid, host_name,
host_sub_functions,
admin_state, oper_state,
@ -2073,6 +2192,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
host_data['uptime'],
software_load,
target_load,
openstack_compute,
openstack_control,
nfvi_data)
response['result-data'] = host_obj
@ -2887,6 +3008,17 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
% (host_uuid, host_name, upgrade))
http_response = httplib.BAD_REQUEST
elif host_uuid is not None and host_name is not None:
for callback in self._host_update_callbacks:
success = callback(host_uuid, host_name)
if not success:
http_response = httplib.BAD_REQUEST
if httplib.OK == http_response:
http_payload = dict()
http_payload['status'] = "success"
else:
DLOG.error("Invalid host patch data received, host_data=%s."
% host_data)
@ -3035,6 +3167,12 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI):
"""
self._host_upgrade_callbacks.append(callback)
def register_host_update_callback(self, callback):
"""
Register for host update notifications
"""
self._host_update_callbacks.append(callback)
def register_host_notification_callback(self, callback):
"""
Register for host notifications

View File

@ -55,6 +55,20 @@ def get_host(token, host_uuid):
return response
def get_host_labels(token, host_uuid):
"""
Asks System Inventory for host label details
"""
url = token.get_service_url(PLATFORM_SERVICE.SYSINV)
if url is None:
raise ValueError("OpenStack SysInv URL is invalid")
api_cmd = url + "/ihosts/%s/labels" % host_uuid
response = rest_api_request(token, "GET", api_cmd)
return response
def get_upgrade(token):
"""
Asks System Inventory for information about the upgrade

View File

@ -217,6 +217,8 @@ class TestInstance(testcase.NFVTestCase):
action=nfvi.objects.v1.HOST_ACTION.NONE,
software_load=software_load,
target_load=target_load,
openstack_compute=False,
openstack_control=False,
uptime='1000'
)

View File

@ -292,6 +292,8 @@ class TestSwPatchStrategy(testcase.NFVTestCase):
action=nfvi.objects.v1.HOST_ACTION.NONE,
software_load='12.01',
target_load='12.01',
openstack_compute=False,
openstack_control=False,
uptime='1000'
)

View File

@ -269,6 +269,8 @@ class TestSwUpgradeStrategy(testcase.NFVTestCase):
action=nfvi.objects.v1.HOST_ACTION.NONE,
software_load=software_load,
target_load=target_load,
openstack_compute=False,
openstack_control=False,
uptime='1000'
)

View File

@ -63,10 +63,10 @@ def database_host_add(host_obj):
"""
db = database_get()
session = db.session()
query = session.query(model.Host_v5).filter(model.Host_v5.name == host_obj.name)
query = session.query(model.Host_v6).filter(model.Host_v6.name == host_obj.name)
host = query.first()
if not host:
host = model.Host_v5()
host = model.Host_v6()
host.uuid = host_obj.uuid
host.name = host_obj.name
host.personality = host_obj.personality
@ -97,8 +97,8 @@ def database_host_delete(host_name):
"""
db = database_get()
session = db.session()
query = session.query(model.Host_v5)
query.filter(model.Host_v5.name == host_name).delete()
query = session.query(model.Host_v6)
query.filter(model.Host_v6.name == host_name).delete()
session.commit()
@ -108,7 +108,7 @@ def database_host_get_list():
"""
db = database_get()
session = db.session()
query = session.query(model.Host_v5)
query = session.query(model.Host_v6)
host_objs = list()
for host in query.all():
@ -123,6 +123,8 @@ def database_host_get_list():
nfvi_host_data['uptime'],
nfvi_host_data['software_load'],
nfvi_host_data['target_load'],
nfvi_host_data['openstack_compute'],
nfvi_host_data['openstack_control'],
nfvi_host_data['nfvi_data'])
host_obj = objects.Host(nfvi_host, host.state, host.action,

View File

@ -12,79 +12,29 @@ from nfv_common import debug
DLOG = debug.debug_get_logger('nfv_vim.database')
def _migrate_instances_v4_to_v5(session, instances_v4, instances_v5):
def _migrate_hosts_v5_to_v6(session, hosts_v5, hosts_v6):
"""
Migrate instances_v4 table to instances_v5 table
Migrate host_v5 table to host_v6 table
"""
if 0 == len(instances_v5):
instance_type_query = session.query(model.InstanceType)
instance_types = instance_type_query.all()
for instance_v4 in instances_v4:
instance_v5 = model.Instance_v5()
instance_type_uuid = instance_v4.instance_type_uuid
del instance_v4.data['instance_type_uuid']
instance_v5.data = instance_v4.data
nfvi_instance_data = json.loads(instance_v4.nfvi_instance_data)
# We can build the flavor details embedded in the instance from
# the flavor referenced from the original instance.
instance_type = None
for i_type in instance_types:
if i_type.uuid == instance_type_uuid:
instance_type = i_type
break
if instance_type is None:
DLOG.error("Missing instance type: %s" % instance_type_uuid)
continue
flavor = dict()
flavor['vcpus'] = instance_type.vcpus
flavor['ram'] = instance_type.mem_mb
flavor['disk'] = instance_type.disk_gb
flavor['ephemeral'] = instance_type.ephemeral_gb
flavor['swap'] = instance_type.swap_gb
flavor['original_name'] = instance_type.name
# Re-create the flavor extra_specs, undoing all the mangling that
# the VIM did when converting the flavor to an instance_type.
extra_specs = dict()
guest_services = instance_type.guest_services
if 'heartbeat' in guest_services:
if guest_services['heartbeat'] == 'configured':
extra_specs['sw:wrs:guest:heartbeat'] = 'true'
else:
extra_specs['sw:wrs:guest:heartbeat'] = 'false'
if instance_type.auto_recovery is not None:
if instance_type.auto_recovery:
extra_specs['sw:wrs:auto_recovery'] = 'true'
else:
extra_specs['sw:wrs:auto_recovery'] = 'false'
if instance_type.live_migration_timeout is not None:
extra_specs['hw:wrs:live_migration_timeout'] = \
instance_type.live_migration_timeout
if instance_type.live_migration_max_downtime is not None:
extra_specs['hw:wrs:live_migration_max_downtime'] = \
instance_type.live_migration_max_downtime
if instance_type.storage_type is not None:
extra_specs['aggregate_instance_extra_specs:storage'] = \
instance_type.storage_type
if extra_specs:
flavor['extra_specs'] = extra_specs
nfvi_instance_data['instance_type'] = flavor
instance_v5.nfvi_instance_data = json.dumps(nfvi_instance_data)
session.add(instance_v5)
if 0 == len(hosts_v6):
for host_v5 in hosts_v5:
host_v6 = model.Host_v6()
host_v6.data = host_v5.data
nfvi_host_data = json.loads(host_v5.nfvi_host_data)
nfvi_host_data['openstack_compute'] = False
nfvi_host_data['openstack_control'] = False
host_v6.nfvi_host_data = json.dumps(nfvi_host_data)
session.add(host_v6)
def migrate_tables(session, table_names):
"""
Migrate database tables
"""
if 'instances_v4' in table_names and 'instances_v5' in table_names:
instances_v4_query = session.query(model.Instance_v4)
instances_v4 = instances_v4_query.all()
instances_v5_query = session.query(model.Instance_v5)
instances_v5 = instances_v5_query.all()
_migrate_instances_v4_to_v5(session, instances_v4, instances_v5)
instances_v4_query.delete()
if 'hosts_v5' in table_names and 'hosts_v6' in table_names:
hosts_v5_query = session.query(model.Host_v5)
hosts_v5 = hosts_v5_query.all()
hosts_v6_query = session.query(model.Host_v6)
hosts_v6 = hosts_v6_query.all()
_migrate_hosts_v5_to_v6(session, hosts_v5, hosts_v6)
hosts_v5_query.delete()

View File

@ -11,6 +11,7 @@ from nfv_vim.database.model._volume import Volume # noqa: F401
from nfv_vim.database.model._volume_snapshot import VolumeSnapshot # noqa: F401
from nfv_vim.database.model._system import System # noqa: F401
from nfv_vim.database.model._host import Host_v5 # noqa: F401
from nfv_vim.database.model._host import Host_v6 # noqa: F401
from nfv_vim.database.model._host_aggregate import HostAggregate # noqa: F401
from nfv_vim.database.model._host_group import HostGroup # noqa: F401
from nfv_vim.database.model._subnet import Subnet # noqa: F401

View File

@ -11,6 +11,31 @@ from nfv_vim.database.model._base import AsDictMixin
from nfv_vim.database.model._base import Base
class Host_v6(AsDictMixin, Base):
"""
Host Database Table Entry
Note: Changes are only in nfvi_host_data.
"""
__tablename__ = 'hosts_v6'
uuid = Column(String(64), nullable=False, primary_key=True)
name = Column(String(64), nullable=False)
personality = Column(String(64), nullable=False)
state = Column(String(64), nullable=False)
action = Column(String(64), nullable=False)
upgrade_inprogress = Column(Boolean, nullable=False)
recover_instances = Column(Boolean, nullable=False)
uptime = Column(String(64), nullable=False)
elapsed_time_in_state = Column(String(64), nullable=False)
host_services_locked = Column(Boolean, nullable=False)
nfvi_host_data = Column(String(2048), nullable=False)
def __repr__(self):
return "<Host(%r, %r, %r, %r, %r %r)>" % (self.uuid, self.name,
self.personality, self.state,
self.action, self.uptime)
class Host_v5(AsDictMixin, Base):
"""
Host Database Table Entry

View File

@ -153,6 +153,19 @@ def _nfvi_host_upgrade_callback(nfvi_host_uuid, nfvi_host_name,
return True
def _nfvi_host_update_callback(nfvi_host_uuid, nfvi_host_name):
"""
NFVI Host update callback
"""
DLOG.debug("Host update, nfvi_host_uuid=%s, nfvi_host_name=%s" %
(nfvi_host_uuid, nfvi_host_name))
nfvi.nfvi_get_host(nfvi_host_uuid, nfvi_host_name,
_nfvi_host_query_callback())
return True
def _nfvi_host_notification_callback(host_ip, nfvi_notify_type, nfvi_notify_data):
"""
NFVI Host notification callback
@ -468,6 +481,9 @@ def vim_nfvi_events_initialize():
nfvi.nfvi_register_host_upgrade_callback(
_nfvi_host_upgrade_callback)
nfvi.nfvi_register_host_update_callback(
_nfvi_host_update_callback)
nfvi.nfvi_register_host_notification_callback(
_nfvi_host_notification_callback)

View File

@ -55,6 +55,7 @@ from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_register_host_action_c
from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_register_host_state_change_callback # noqa: F401
from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_register_host_get_callback # noqa: F401
from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_register_host_upgrade_callback # noqa: F401
from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_register_host_update_callback # noqa: F401
from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_register_host_notification_callback # noqa: F401
from nfv_vim.nfvi._nfvi_image_module import nfvi_image_plugin_disabled # noqa: F401
from nfv_vim.nfvi._nfvi_image_module import nfvi_get_images # noqa: F401

View File

@ -352,6 +352,14 @@ def nfvi_register_host_upgrade_callback(callback):
callback=callback)
def nfvi_register_host_update_callback(callback):
"""
Register for host update notifications
"""
_infrastructure_plugin.invoke_plugin('register_host_update_callback',
callback=callback)
def nfvi_register_host_notification_callback(callback):
"""
Register for host notifications

View File

@ -256,6 +256,13 @@ class NFVIInfrastructureAPI(object):
"""
pass
@abc.abstractmethod
def register_host_update_callback(self, callback):
"""
Register for host update notifications
"""
pass
@abc.abstractmethod
def initialize(self, config_file):
"""

View File

@ -48,6 +48,8 @@ from nfv_vim.nfvi.objects.v1._host import HOST_OPER_STATE # noqa: F401
from nfv_vim.nfvi.objects.v1._host import HOST_AVAIL_STATUS # noqa: F401
from nfv_vim.nfvi.objects.v1._host import HOST_ACTION # noqa: F401
from nfv_vim.nfvi.objects.v1._host import HOST_NOTIFICATIONS # noqa: F401
from nfv_vim.nfvi.objects.v1._host import HOST_LABEL_KEYS # noqa: F401
from nfv_vim.nfvi.objects.v1._host import HOST_LABEL_VALUES # noqa: F401
from nfv_vim.nfvi.objects.v1._host import Host # noqa: F401
from nfv_vim.nfvi.objects.v1._host_aggregate import HostAggregate # noqa: F401
from nfv_vim.nfvi.objects.v1._host_group import HOST_GROUP_POLICY # noqa: F401

View File

@ -72,12 +72,32 @@ class HostNotifications(Constants):
BOOTING = Constant('booting')
@six.add_metaclass(Singleton)
class KubernetesLabelValues(Constants):
"""
Host Kubernetes Label Value Constants
"""
ENABLED = Constant('enabled')
DISABLED = Constant('disabled')
@six.add_metaclass(Singleton)
class KubernetesLabelKeys(Constants):
"""
Host Kubernetes Label Key Constants
"""
OS_COMPUTE_NODE = Constant('openstack-compute-node')
OS_CONTROL_PLANE = Constant('openstack-control-plane')
# Host Constant Instantiation
HOST_ADMIN_STATE = HostAdministrativeState()
HOST_OPER_STATE = HostOperationalState()
HOST_AVAIL_STATUS = HostAvailabilityStatus()
HOST_ACTION = HostAction()
HOST_NOTIFICATIONS = HostNotifications()
HOST_LABEL_KEYS = KubernetesLabelKeys()
HOST_LABEL_VALUES = KubernetesLabelValues()
class Host(ObjectData):
@ -86,6 +106,8 @@ class Host(ObjectData):
"""
def __init__(self, uuid, name, personality, admin_state, oper_state,
avail_status, action, uptime, software_load, target_load,
openstack_compute=False,
openstack_control=False,
nfvi_data=None):
super(Host, self).__init__('1.0.0')
self.update(dict(uuid=uuid, name=name, personality=personality,
@ -95,6 +117,8 @@ class Host(ObjectData):
action=action,
uptime=uptime,
software_load=software_load,
target_load=target_load))
target_load=target_load,
openstack_compute=openstack_compute,
openstack_control=openstack_control))
self.nfvi_data = nfvi_data

View File

@ -208,6 +208,20 @@ class Host(ObjectData):
"""
return self._nfvi_host.target_load
@property
def openstack_compute(self):
"""
Returns openstack_compute for this host
"""
return self._nfvi_host.openstack_compute
@property
def openstack_control(self):
"""
Returns openstack_control for this host
"""
return self._nfvi_host.openstack_control
@property
def recover_instances(self):
"""

View File

@ -43,6 +43,8 @@
<th>administrative-state</th>
<th>operational-state</th>
<th>availability-status</th>
<th>openstack-control</th>
<th>openstack-compute</th>
</tr>
</thead>
<tbody>
@ -53,6 +55,8 @@
<td class="html_refresh" id="nfvi_host_{{nfvi_host.uuid}}_admin_state">{{nfvi_host.nfvi_data.admin_state}}</td>
<td class="html_refresh" id="nfvi_host_{{nfvi_host.uuid}}_oper_state">{{nfvi_host.nfvi_data.oper_state}}</td>
<td class="html_refresh" id="nfvi_host_{{nfvi_host.uuid}}_avail_status">{{nfvi_host.nfvi_data.avail_status}}</td>
<td class="html_refresh" id="nfvi_host_{{nfvi_host.uuid}}_openstack_control">{{nfvi_host.openstack_control}}</td>
<td class="html_refresh" id="nfvi_host_{{nfvi_host.uuid}}_openstack_compute">{{nfvi_host.openstack_compute}}</td>
</tr>
</tbody>
</table>