Files
deb-nova/nova/scheduler/ironic_host_manager.py
Rui Chen 26a4f430d1 Fix resource leaking when consume_from_instance raise exception
When we boot instance with force host, and the instance
request some pci devices, all the scheduler filters
would been ignored, include: PciPassthroughFilter.
So if the specified host can't apply the pci request,
PciDeviceRequestFailed exception would been raised
from HostState.consume_from_instance, at this time
the part of compute resource had been updated,
e.g. vcpus, ram, disk and so on, we should make
the resource of HostState having chance to been reverted
in order to avoid resource leaking.

When the exception is raised from self.pci_stats.apply_requests(),
catch it and don't set the update field of HostState,
HostState will be synced with db in next scheduling,
the resource is reverted at that time.

Change-Id: I0a87088d56337bcd180606013a5473fa2ec6c608
Related-Bug: #1391816
Closes-Bug: #1482019
2015-08-06 11:32:03 +08:00

109 lines
3.9 KiB
Python

# Copyright (c) 2012 NTT DOCOMO, INC.
# Copyright (c) 2011-2014 OpenStack Foundation
# All Rights Reserved.
#
# 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.
"""
Ironic host manager.
This host manager will consume all cpu's, disk space, and
ram from a host / node as it is supporting Baremetal hosts, which can not be
subdivided into multiple instances.
"""
from oslo_config import cfg
from oslo_log import log as logging
from nova.compute import hv_type
from nova.scheduler import host_manager
host_manager_opts = [
cfg.ListOpt('baremetal_scheduler_default_filters',
default=[
'RetryFilter',
'AvailabilityZoneFilter',
'ComputeFilter',
'ComputeCapabilitiesFilter',
'ImagePropertiesFilter',
'ExactRamFilter',
'ExactDiskFilter',
'ExactCoreFilter',
],
help='Which filter class names to use for filtering '
'baremetal hosts when not specified in the request.'),
cfg.BoolOpt('scheduler_use_baremetal_filters',
default=False,
help='Flag to decide whether to use '
'baremetal_scheduler_default_filters or not.'),
]
CONF = cfg.CONF
CONF.register_opts(host_manager_opts)
LOG = logging.getLogger(__name__)
class IronicNodeState(host_manager.HostState):
"""Mutable and immutable information tracked for a host.
This is an attempt to remove the ad-hoc data structures
previously used and lock down access.
"""
def update_from_compute_node(self, compute):
"""Update information about a host from a ComputeNode object."""
self.vcpus_total = compute.vcpus
self.vcpus_used = compute.vcpus_used
self.free_ram_mb = compute.free_ram_mb
self.total_usable_ram_mb = compute.memory_mb
self.free_disk_mb = compute.free_disk_gb * 1024
self.stats = compute.stats or {}
self.total_usable_disk_gb = compute.local_gb
self.hypervisor_type = compute.hypervisor_type
self.hypervisor_version = compute.hypervisor_version
self.hypervisor_hostname = compute.hypervisor_hostname
self.cpu_info = compute.cpu_info
if compute.supported_hv_specs:
self.supported_instances = [spec.to_list() for spec
in compute.supported_hv_specs]
else:
self.supported_instances = []
self.updated = compute.updated_at
@host_manager.set_update_time_on_success
def consume_from_instance(self, instance):
"""Consume nodes entire resources regardless of instance request."""
self.free_ram_mb = 0
self.free_disk_mb = 0
self.vcpus_used = self.vcpus_total
class IronicHostManager(host_manager.HostManager):
"""Ironic HostManager class."""
def _load_filters(self):
if CONF.scheduler_use_baremetal_filters:
return CONF.baremetal_scheduler_default_filters
return super(IronicHostManager, self)._load_filters()
def host_state_cls(self, host, node, **kwargs):
"""Factory function/property to create a new HostState."""
compute = kwargs.get('compute')
if compute and compute.get('hypervisor_type') == hv_type.IRONIC:
return IronicNodeState(host, node, **kwargs)
else:
return host_manager.HostState(host, node, **kwargs)