Files
deb-nova/nova/objects/instance_numa_topology.py
Nikola Dipanov a59e1a9c7e Make Instance.save() update numa_topology
This is needed so that we can actually update the given topology with
the updated data after a successful claim.

Deleting it will also be needed when we actually make the resize work
properly for instances with NUMA topology, so we add it here as well.

We do not expose the new InstanceNUMATopology methods as @remotable to
avoid having to bump the object version thus making this an easier
backport target. This is OK since they are only called from
Instance.save() which is @remotable, and can be trivially made remotable
should this be needed later (causing a version bump that need not be
backported).

Change-Id: I64ff2d00ca20bd065bb17ebaa9c40b64b8cbb817
Partial-bug: #1386236
2014-11-20 18:25:30 +01:00

131 lines
5.1 KiB
Python

# Copyright 2014 Red Hat 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
#
# 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.
from nova import db
from nova import exception
from nova.objects import base
from nova.objects import fields
from nova.virt import hardware
class InstanceNUMACell(base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Add pagesize field
VERSION = '1.1'
fields = {
'id': fields.IntegerField(read_only=True),
'cpuset': fields.SetOfIntegersField(),
'memory': fields.IntegerField(),
'pagesize': fields.IntegerField(nullable=True),
}
class InstanceNUMATopology(base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Takes into account pagesize
VERSION = '1.1'
fields = {
# NOTE(danms): The 'id' field is no longer used and should be
# removed in the future when convenient
'id': fields.IntegerField(),
'instance_uuid': fields.UUIDField(),
'cells': fields.ListOfObjectsField('InstanceNUMACell'),
}
@classmethod
def obj_from_db_obj(cls, instance_uuid, db_obj):
topo = hardware.VirtNUMAInstanceTopology.from_json(db_obj)
obj_topology = cls.obj_from_topology(topo)
obj_topology.instance_uuid = instance_uuid
# NOTE (ndipanov) not really needed as we never save, but left for
# consistency
obj_topology.id = 0
obj_topology.obj_reset_changes()
return obj_topology
@classmethod
def obj_from_topology(cls, topology):
if not isinstance(topology, hardware.VirtNUMAInstanceTopology):
raise exception.ObjectActionError(action='obj_from_topology',
reason='invalid topology class')
if topology:
cells = []
for topocell in topology.cells:
pagesize = (topocell.pagesize
and topocell.pagesize.size_kb or None)
cell = InstanceNUMACell(id=topocell.id, cpuset=topocell.cpuset,
memory=topocell.memory,
pagesize=pagesize)
cells.append(cell)
return cls(cells=cells)
def topology_from_obj(self):
cells = []
for objcell in self.cells:
pagesize = (
objcell.pagesize and
hardware.VirtPageSize(objcell.pagesize) or None)
cell = hardware.VirtNUMATopologyCellInstance(objcell.id,
objcell.cpuset,
objcell.memory,
pagesize=pagesize)
cells.append(cell)
return hardware.VirtNUMAInstanceTopology(cells=cells)
# TODO(ndipanov) Remove this method on the major version bump to 2.0
@base.remotable
def create(self, context):
topology = self.topology_from_obj()
if not topology:
return
values = {'numa_topology': topology.to_json()}
db.instance_extra_update_by_uuid(context, self.instance_uuid,
values)
self.obj_reset_changes()
# NOTE(ndipanov): We can't rename create and want to avoid version bump
# as this needs to be backported to stable so this is not a @remotable
# That's OK since we only call it from inside Instance.save() which is.
def _save(self, context):
topology = self.topology_from_obj()
if not topology:
return
values = {'numa_topology': topology.to_json()}
db.instance_extra_update_by_uuid(context, self.instance_uuid,
values)
self.obj_reset_changes()
# NOTE(ndipanov): We want to avoid version bump
# as this needs to be backported to stable so this is not a @remotable
# That's OK since we only call it from inside Instance.save() which is.
@classmethod
def delete_by_instance_uuid(cls, context, instance_uuid):
values = {'numa_topology': None}
db.instance_extra_update_by_uuid(context, instance_uuid,
values)
@base.remotable_classmethod
def get_by_instance_uuid(cls, context, instance_uuid):
db_extra = db.instance_extra_get_by_instance_uuid(
context, instance_uuid, columns=['numa_topology'])
if not db_extra:
raise exception.NumaTopologyNotFound(instance_uuid=instance_uuid)
if db_extra['numa_topology'] is None:
return None
return cls.obj_from_db_obj(instance_uuid, db_extra['numa_topology'])