Add object and database support for host_status API

This is initial object and database support for the API discovering and
exposing the state of an instance's host.

Related to blueprint get-valid-server-state

Change-Id: Id6e59065bc2784d376d569591583d9572fc9597f
Co-Authored-By: Dan Smith <dansmith@redhat.com>
This commit is contained in:
Tomi Juvonen 2016-01-15 09:20:36 +02:00 committed by Dan Smith
parent b558d616c3
commit b65a8794c4
6 changed files with 54 additions and 4 deletions

View File

@ -103,6 +103,15 @@ class Service(BASE, NovaBase, models.SoftDeleteMixin):
forced_down = Column(Boolean, default=False)
version = Column(Integer, default=0)
instance = orm.relationship(
"Instance",
backref='services',
primaryjoin='and_(Service.host == Instance.host,'
'Service.binary == "nova-compute",'
'Instance.deleted == 0)',
foreign_keys=host,
)
class ComputeNode(BASE, NovaBase, models.SoftDeleteMixin):
"""Represents a running compute service on a host."""

View File

@ -420,6 +420,20 @@ class MonitorMetricType(Enum):
valid_values=MonitorMetricType.ALL)
class HostStatus(Enum):
UP = "UP" # The nova-compute is up.
DOWN = "DOWN" # The nova-compute is forced_down.
MAINTENANCE = "MAINTENANCE" # The nova-compute is disabled.
UNKNOWN = "UNKNOWN" # The nova-compute has not reported.
ALL = (UP, DOWN, MAINTENANCE, UNKNOWN)
def __init__(self):
super(HostStatus, self).__init__(
valid_values=HostStatus.ALL)
class PciDeviceStatus(Enum):
AVAILABLE = "available"

View File

@ -19,6 +19,7 @@ from oslo_db import exception as db_exc
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import timeutils
from oslo_utils import versionutils
from nova.cells import opts as cells_opts
from nova.cells import rpcapi as cells_rpcapi
@ -40,7 +41,7 @@ LOG = logging.getLogger(__name__)
# List of fields that can be joined in DB layer.
_INSTANCE_OPTIONAL_JOINED_FIELDS = ['metadata', 'system_metadata',
'info_cache', 'security_groups',
'pci_devices', 'tags']
'pci_devices', 'tags', 'services']
# These are fields that are optional but don't translate to db columns
_INSTANCE_OPTIONAL_NON_COLUMN_FIELDS = ['fault', 'flavor', 'old_flavor',
'new_flavor', 'ec2_ids']
@ -86,7 +87,8 @@ _NO_DATA_SENTINEL = object()
class Instance(base.NovaPersistentObject, base.NovaObject,
base.NovaObjectDictCompat):
# Version 2.0: Initial version
VERSION = '2.0'
# Version 2.1: Added services
VERSION = '2.1'
fields = {
'id': fields.IntegerField(),
@ -107,6 +109,8 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
'vm_state': fields.StringField(nullable=True),
'task_state': fields.StringField(nullable=True),
'services': fields.ObjectField('ServiceList'),
'memory_mb': fields.IntegerField(nullable=True),
'vcpus': fields.IntegerField(nullable=True),
'root_gb': fields.IntegerField(nullable=True),
@ -187,6 +191,12 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
obj_extra_fields = ['name']
def obj_make_compatible(self, primitive, target_version):
super(Instance, self).obj_make_compatible(primitive, target_version)
target_version = versionutils.convert_version_to_tuple(target_version)
if target_version < (2, 1) and 'services' in primitive:
del primitive['services']
def __init__(self, *args, **kwargs):
super(Instance, self).__init__(*args, **kwargs)
self._reset_metadata_tracking()
@ -360,6 +370,12 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
objects.Tag, db_inst['tags'])
instance['tags'] = tags
if 'services' in expected_attrs:
services = base.obj_make_list(
context, objects.ServiceList(context),
objects.Service, db_inst['services'])
instance['services'] = services
instance.obj_reset_changes()
return instance

View File

@ -74,7 +74,8 @@ def fake_db_instance(**updates):
'numa_topology': None,
'vcpu_model': None,
},
'tags': []
'tags': [],
'services': []
}
for name, field in objects.Instance.fields.items():

View File

@ -153,7 +153,16 @@ class _TestInstanceObject(object):
test_vcpu_model.fake_vcpumodel.obj_to_primitive())
fake_mig_context = jsonutils.dumps(
test_mig_ctxt.fake_migration_context_obj.obj_to_primitive())
fake_service = {'created_at': None, 'updated_at': None,
'deleted_at': None, 'deleted': False, 'id': 123,
'host': 'fake-host', 'binary': 'nova-fake',
'topic': 'fake-service-topic', 'report_count': 1,
'forced_down': False, 'disabled': False,
'disabled_reason': None, 'last_seen_up': None,
'version': 1,
}
fake_instance = dict(self.fake_instance,
services=[fake_service],
extra={
'numa_topology': fake_topology,
'pci_requests': fake_requests,
@ -177,6 +186,7 @@ class _TestInstanceObject(object):
expected_attrs=instance.INSTANCE_OPTIONAL_ATTRS)
for attr in instance.INSTANCE_OPTIONAL_ATTRS:
self.assertTrue(inst.obj_attr_is_set(attr))
self.assertEqual(123, inst.services[0].id)
def test_get_by_id(self):
self.mox.StubOutWithMock(db, 'instance_get')

View File

@ -1134,7 +1134,7 @@ object_data = {
'HVSpec': '1.2-db672e73304da86139086d003f3977e7',
'ImageMeta': '1.8-642d1b2eb3e880a367f37d72dd76162d',
'ImageMetaProps': '1.11-96aa14a8ba226701bbd22e63557a63ea',
'Instance': '2.0-ff56804dce87d81d9a04834d4bd1e3d2',
'Instance': '2.1-416fdd0dfc33dfa12ff2cfdd8cc32e17',
'InstanceAction': '1.1-f9f293e526b66fca0d05c3b3a2d13914',
'InstanceActionEvent': '1.1-e56a64fa4710e43ef7af2ad9d6028b33',
'InstanceActionEventList': '1.1-13d92fb953030cdbfee56481756e02be',