¡@

Home 

OpenStack Study: __init__.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2013 Intel Corporation.

# 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.

"""

Resource monitor API specification.

ResourceMonitorBase provides the definition of minimum set of methods

that needs to be implemented by Resource Monitor.

"""

import types

import six

from oslo.config import cfg

from nova import loadables

from nova.openstack.common.gettextutils import _

from nova.openstack.common import log as logging

from nova.openstack.common import timeutils

compute_monitors_opts = [

cfg.MultiStrOpt('compute_available_monitors',

default=['nova.compute.monitors.all_monitors'],

help='Monitor classes available to the compute which may '

'be specified more than once.'),

cfg.ListOpt('compute_monitors',

default=[],

help='A list of monitors that can be used for getting '

'compute metrics.'),

]

CONF = cfg.CONF

CONF.register_opts(compute_monitors_opts)

LOG = logging.getLogger(__name__)

**** CubicPower OpenStack Study ****

class ResourceMonitorMeta(type):

**** CubicPower OpenStack Study ****

    def __init__(cls, names, bases, dict_):

        """Metaclass that allows us to create a function map and call it later

        to get the metric names and their values.

        """

        super(ResourceMonitorMeta, cls).__init__(names, bases, dict_)

        prefix = '_get_'

        prefix_len = len(prefix)

        cls.metric_map = {}

        for name, value in cls.__dict__.iteritems():

            if (len(name) > prefix_len

               and name[:prefix_len] == prefix

               and isinstance(value, types.FunctionType)):

                metric_name = name[prefix_len:].replace('_', '.')

                cls.metric_map[metric_name] = value

@six.add_metaclass(ResourceMonitorMeta)

**** CubicPower OpenStack Study ****

class ResourceMonitorBase(object):

"""Base class for resource monitors

"""

**** CubicPower OpenStack Study ****

    def __init__(self, parent):

        self.compute_manager = parent

        self.source = None

        self._data = {}

    @classmethod

**** CubicPower OpenStack Study ****

    def add_timestamp(arg, func):

        """Decorator to indicate that a method needs to add a timestamp.

        When a function returning a value is decorated by the decorator,

        which means a timestamp should be added into the returned value.

        That is, a tuple (value, timestamp) is returned.

        The timestamp is the time when we update the value in the _data.

        If users hope to define how the timestamp is got by themselves,

        they should not use this decorator in their own classes.

        """

        def wrapper(cls, **kwargs):

            return func(cls, **kwargs), cls._data.get("timestamp", None)

        return wrapper

**** CubicPower OpenStack Study ****

        def wrapper(cls, **kwargs):

            return func(cls, **kwargs), cls._data.get("timestamp", None)

        return wrapper

**** CubicPower OpenStack Study ****

    def _update_data(self):

        """Method to update the metrics data.

        Each subclass can implement this method to update metrics

        into _data. It will be called in get_metrics.

        """

        pass

**** CubicPower OpenStack Study ****

    def get_metric_names(self):

        """Get available metric names.

        Get available metric names, which are represented by a set of keys

        that can be used to check conflicts and duplications

        :returns: a set of keys representing metrics names

        """

        return self.metric_map.keys()

**** CubicPower OpenStack Study ****

    def get_metrics(self, **kwargs):

        """Get metrics.

        Get metrics, which are represented by a list of dictionaries

        [{'name': metric name,

          'value': metric value,

          'timestamp': the time when the value is retrieved,

          'source': what the value is got by}, ...]

        :param kwargs: extra arguments that might be present

        :returns: a list to tell the current metrics

        """

        data = []

        self._update_data()

        for name, func in self.metric_map.iteritems():

            ret = func(self, **kwargs)

            data.append(self._populate(name, ret[0], ret[1]))

        return data

**** CubicPower OpenStack Study ****

    def _populate(self, metric_name, metric_value, timestamp=None):

        """Populate the format what we want from metric name and metric value

        """

        result = {}

        result['name'] = metric_name

        result['value'] = metric_value

        result['timestamp'] = timestamp or timeutils.utcnow()

        result['source'] = self.source

        return result

**** CubicPower OpenStack Study ****

class ResourceMonitorHandler(loadables.BaseLoader):

"""Base class to handle loading monitor classes.

"""

**** CubicPower OpenStack Study ****

    def __init__(self):

        super(ResourceMonitorHandler, self).__init__(ResourceMonitorBase)

**** CubicPower OpenStack Study ****

    def choose_monitors(self, manager):

        """This function checks the monitor names and metrics names against a

        predefined set of acceptable monitors.

        """

        monitor_classes = self.get_matching_classes(

             CONF.compute_available_monitors)

        monitor_class_map = dict((cls.__name__, cls)

                                 for cls in monitor_classes)

        monitor_cls_names = CONF.compute_monitors

        good_monitors = []

        bad_monitors = []

        metric_names = set()

        for monitor_name in monitor_cls_names:

            if monitor_name not in monitor_class_map:

                bad_monitors.append(monitor_name)

                continue

            try:

                # make sure different monitors do not have the same

                # metric name

                monitor = monitor_class_map[monitor_name](manager)

                metric_names_tmp = set(monitor.get_metric_names())

                overlap = metric_names & metric_names_tmp

                if not overlap:

                    metric_names = metric_names | metric_names_tmp

                    good_monitors.append(monitor)

                else:

                    msg = (_("Excluding monitor %(monitor_name)s due to "

                             "metric name overlap; overlapping "

                             "metrics: %(overlap)s") %

                             {'monitor_name': monitor_name,

                              'overlap': ', '.join(overlap)})

                    LOG.warn(msg)

                    bad_monitors.append(monitor_name)

            except Exception as ex:

                msg = (_("Monitor %(monitor_name)s cannot be used: %(ex)s") %

                         {'monitor_name': monitor_name, 'ex': ex})

                LOG.warn(msg)

                bad_monitors.append(monitor_name)

        if bad_monitors:

            LOG.warn(_("The following monitors have been disabled: %s"),

                       ', '.join(bad_monitors))

        return good_monitors

def all_monitors():

    """Return a list of monitor classes found in this directory.

    This method is used as the default for available monitors

    and should return a list of all monitor classes avaiable.

    """

    return ResourceMonitorHandler().get_all_classes()

**** CubicPower OpenStack Study ****

def all_monitors():

    """Return a list of monitor classes found in this directory.

    This method is used as the default for available monitors

    and should return a list of all monitor classes avaiable.

    """

    return ResourceMonitorHandler().get_all_classes()