text: # Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
  # 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.
  
  from oslo_log import log as logging
  import stevedore
  
  from nova.i18n import _LW
  
  LOG = logging.getLogger(__name__)
  
  RESOURCE_NAMESPACE = 'nova.compute.resources'
  
  
  class ResourceHandler(object):
  
      def _log_missing_plugins(self, names):
          for name in names:
              if name not in self._mgr.names():
                  LOG.warning(_LW('Compute resource plugin %s was not loaded'),
                              name)
  
      def __init__(self, names, propagate_map_exceptions=False):
          """Initialise the resource handler by loading the plugins.
  
          The ResourceHandler uses stevedore to load the resource plugins.
          The handler can handle and report exceptions raised in the plugins
          depending on the value of the propagate_map_exceptions parameter.
          It is useful in testing to propagate exceptions so they are exposed
          as part of the test. If exceptions are not propagated they are
          logged at error level.
  
          Any named plugins that are not located are logged.
  
          :param names: the list of plugins to load by name
          :param propagate_map_exceptions: True indicates exceptions in the
          plugins should be raised, False indicates they should be handled and
          logged.
          """
          self._mgr = stevedore.NamedExtensionManager(
              namespace=RESOURCE_NAMESPACE,
              names=names,
              propagate_map_exceptions=propagate_map_exceptions,
              invoke_on_load=True)
          self._log_missing_plugins(names)
  
      def reset_resources(self, resources, driver):
          """Reset the resources to their initial state.
  
          Each plugin is called to reset its state. The resources data provided
          is initial state gathered from the hypervisor. The driver is also
          provided in case the plugin needs to obtain additional information
          from the driver, for example, the memory calculation obtains
          the memory overhead from the driver.
  
          :param resources: the resources reported by the hypervisor
          :param driver: the driver for the hypervisor
  
          :returns: None
          """
          if self._mgr.extensions:
              self._mgr.map_method('reset', resources, driver)
  
      def test_resources(self, usage, limits):
          """Test the ability to support the given instance.
  
          Each resource plugin is called to determine if it's resource is able
          to support the additional requirements of a new instance. The
          plugins either return None to indicate they have sufficient resource
          available or a human readable string to indicate why they can not.
  
          :param usage: the additional resource usage
          :param limits: limits used for the calculation
  
          :returns: a list or return values from the plugins
          """
          if not self._mgr.extensions:
              return []
  
          reasons = self._mgr.map_method('test', usage, limits)
          return reasons
  
      def update_from_instance(self, usage, sign=1):
          """Update the resource information to reflect the allocation for
          an instance with the given resource usage.
  
          :param usage: the resource usage of the instance
          :param sign: has value 1 or -1. 1 indicates the instance is being
          added to the current usage, -1 indicates the instance is being removed.
  
          :returns: None
          """
          if not self._mgr.extensions:
              return
  
          if sign == 1:
              self._mgr.map_method('add_instance', usage)
          else:
              self._mgr.map_method('remove_instance', usage)
  
      def write_resources(self, resources):
          """Write the resource data to populate the resources.
  
          Each resource plugin is called to write its resource data to
          resources.
  
          :param resources: the compute node resources
  
          :returns: None
          """
          if self._mgr.extensions:
              self._mgr.map_method('write', resources)
  
      def report_free_resources(self):
          """Each resource plugin is called to log free resource information.
  
          :returns: None
          """
          if not self._mgr.extensions:
              return
  
          self._mgr.map_method('report_free')
  