Remove 'hardware.instance_topology_from_instance'

Yet another function that has outstayed its welcome. This one had to
handle random object types that may have had a 'numa_topology' field or
key, which, if present, contained an instance NUMA topology in either
string, dict or object form. This was only called in two places, both of
which don't need this complexity as described below, meaning we can
remove this function.

nova/objects/request_spec.py

  The 'from_components' static method and '_from_instance' helper
  function were both using this, by way of a call to
  '_from_instance_numa_topology'. However, the former always receives an
  actual 'NUMATopology' object, while the latter always receives an
  instance, albeit possibly in serialized form. We add a check to handle
  the serialized form and we're done.

Change-Id: I5ded32a1cd33ab5b64ffa73fcfeb76683eb97df7
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
Stephen Finucane
2019-07-18 18:37:10 +01:00
parent 15799315a8
commit 447b48c826
3 changed files with 10 additions and 86 deletions

View File

@@ -11,13 +11,14 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import itertools
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import versionutils
import six
from nova.db.sqlalchemy import api as db
from nova.db.sqlalchemy import api_models
@@ -26,7 +27,6 @@ from nova import objects
from nova.objects import base
from nova.objects import fields
from nova.objects import instance as obj_instance
from nova.virt import hardware
LOG = logging.getLogger(__name__)
@@ -215,11 +215,11 @@ class RequestSpec(base.NovaObject):
self.pci_requests = pci_requests
def _from_instance_numa_topology(self, numa_topology):
if isinstance(numa_topology, dict):
self.numa_topology = hardware.instance_topology_from_instance(
dict(numa_topology=numa_topology))
else:
self.numa_topology = numa_topology
if isinstance(numa_topology, six.string_types):
numa_topology = objects.InstanceNUMATopology.obj_from_primitive(
jsonutils.loads(numa_topology))
self.numa_topology = numa_topology
def _from_flavor(self, flavor):
if isinstance(flavor, objects.Flavor):

View File

@@ -152,15 +152,14 @@ class _TestRequestSpecObject(object):
user_id=fakes.FAKE_USER_ID,
availability_zone='nova',
pci_requests=None,
numa_topology={'cells': [{'id': 1, 'cpuset': ['1'], 'memory': 8192,
'pagesize': None, 'cpu_topology': None,
'cpu_pinning_raw': None}]})
numa_topology=fake_request_spec.INSTANCE_NUMA_TOPOLOGY,
)
spec = objects.RequestSpec()
spec._from_instance(instance)
self.assertIsInstance(spec.numa_topology, objects.InstanceNUMATopology)
cells = spec.numa_topology.cells
self.assertEqual(1, len(cells))
self.assertEqual(2, len(cells))
self.assertIsInstance(cells[0], objects.InstanceNUMACell)
def test_from_flavor_as_object(self):

View File

@@ -18,18 +18,15 @@ import itertools
import math
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import strutils
from oslo_utils import units
import six
import nova.conf
from nova import context
from nova import exception
from nova.i18n import _
from nova import objects
from nova.objects import fields
from nova.objects import instance as obj_instance
CONF = nova.conf.CONF
@@ -1933,75 +1930,3 @@ def numa_usage_from_instances(host, instances, free=False):
cells.append(newcell)
return objects.NUMATopology(cells=cells)
# TODO(ndipanov): Remove when all code paths are using objects
def instance_topology_from_instance(instance):
"""Extract numa topology from myriad instance representations.
Until the RPC version is bumped to 5.x, an instance may be
represented as a dict, a db object, or an actual Instance object.
Identify the type received and return either an instance of
objects.InstanceNUMATopology if the instance's NUMA topology is
available, else None.
:param host: nova.objects.ComputeNode instance, or a db object or
dict
:returns: An instance of objects.NUMATopology or None
"""
if isinstance(instance, obj_instance.Instance):
# NOTE (ndipanov): This may cause a lazy-load of the attribute
instance_numa_topology = instance.numa_topology
else:
if 'numa_topology' in instance:
instance_numa_topology = instance['numa_topology']
elif 'uuid' in instance:
try:
instance_numa_topology = (
objects.InstanceNUMATopology.get_by_instance_uuid(
context.get_admin_context(), instance['uuid'])
)
except exception.NumaTopologyNotFound:
instance_numa_topology = None
else:
instance_numa_topology = None
if instance_numa_topology:
if isinstance(instance_numa_topology, six.string_types):
instance_numa_topology = (
objects.InstanceNUMATopology.obj_from_primitive(
jsonutils.loads(instance_numa_topology)))
elif isinstance(instance_numa_topology, dict):
# NOTE (ndipanov): A horrible hack so that we can use
# this in the scheduler, since the
# InstanceNUMATopology object is serialized raw using
# the obj_base.obj_to_primitive, (which is buggy and
# will give us a dict with a list of InstanceNUMACell
# objects), and then passed to jsonutils.to_primitive,
# which will make a dict out of those objects. All of
# this is done by scheduler.utils.build_request_spec
# called in the conductor.
#
# Remove when request_spec is a proper object itself!
dict_cells = instance_numa_topology.get('cells')
if dict_cells:
cells = [objects.InstanceNUMACell(
id=cell['id'],
cpuset=set(cell['cpuset']),
memory=cell['memory'],
pagesize=cell.get('pagesize'),
cpu_topology=cell.get('cpu_topology'),
cpu_pinning=cell.get('cpu_pinning_raw'),
cpu_policy=cell.get('cpu_policy'),
cpu_thread_policy=cell.get('cpu_thread_policy'),
cpuset_reserved=cell.get('cpuset_reserved'))
for cell in dict_cells]
emulator_threads_policy = instance_numa_topology.get(
'emulator_threads_policy')
instance_numa_topology = objects.InstanceNUMATopology(
cells=cells,
emulator_threads_policy=emulator_threads_policy)
return instance_numa_topology