Pass agent metrics config via conductor

This adds agent config options for metrics as described in the
spec, and allows those config options to be sent to IPA on
lookup. We're configuring heartbeat timeout this way, and this
change matches nicely with that style.

Additionally, this sets heartbeat_timeout under the new config
namespace for consistency, however, we'll allow the old way to
be deprecated when the vendor_passthru for agent lookups is
deprecated.

Change-Id: I94d81b95feabe46999dbbc02522508cd542a89f8
Co-Authored-By: Josh Gachnang <josh@pcsforeducation.com>
Partial-bug: #1526219
This commit is contained in:
Jay Faulkner 2016-04-05 21:03:50 +00:00
parent 88303cc56c
commit 84bf48431c
8 changed files with 195 additions and 0 deletions

View File

@ -1538,6 +1538,37 @@
[metrics]
#
# From ironic
#
# Backend for the agent ramdisk to use for metrics. Default
# possible backends are "noop" and "statsd". (string value)
#agent_backend = noop
# Prepend the hostname to all metric names sent by the agent
# ramdisk. The format of metric names is
# [global_prefix.][uuid.][host_name.]prefix.metric_name.
# (boolean value)
#agent_prepend_host = false
# Prepend the node's Ironic uuid to all metric names sent by
# the agent ramdisk. The format of metric names is
# [global_prefix.][uuid.][host_name.]prefix.metric_name.
# (boolean value)
#agent_prepend_uuid = false
# Split the prepended host value by "." and reverse it for
# metrics sent by the agent ramdisk (to better match the
# reverse hierarchical form of domain names). (boolean value)
#agent_prepend_host_reverse = true
# Prefix all metric names sent by the agent ramdisk with this
# value. The format of metric names is
# [global_prefix.][uuid.][host_name.]prefix.metric_name.
# (string value)
#agent_global_prefix = <None>
#
# From ironic_lib.metrics
#
@ -1566,6 +1597,21 @@
[metrics_statsd]
#
# From ironic
#
# Host for the agent ramdisk to use with the statsd backend.
# This must be accessible from networks the agent is booted
# on. (string value)
#agent_statsd_host = localhost
# Port for the agent ramdisk to use with the statsd backend.
# (port value)
# Minimum value: 0
# Maximum value: 65535
#agent_statsd_port = 8125
#
# From ironic_lib.metrics_statsd
#

View File

@ -33,6 +33,8 @@ from ironic.conf import inspector
from ironic.conf import ipmi
from ironic.conf import irmc
from ironic.conf import keystone
from ironic.conf import metrics
from ironic.conf import metrics_statsd
from ironic.conf import neutron
from ironic.conf import oneview
from ironic.conf import seamicro
@ -61,6 +63,8 @@ inspector.register_opts(CONF)
ipmi.register_opts(CONF)
irmc.register_opts(CONF)
keystone.register_opts(CONF)
metrics.register_opts(CONF)
metrics_statsd.register_opts(CONF)
neutron.register_opts(CONF)
oneview.register_opts(CONF)
seamicro.register_opts(CONF)

55
ironic/conf/metrics.py Normal file
View File

@ -0,0 +1,55 @@
# Copyright 2016 Intel Corporation
# Copyright 2014 Rackspace, Inc.
# Copyright 2015 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 oslo_config import cfg
from ironic.common.i18n import _
opts = [
# IPA config options: used by IPA to configure how it reports metric data
cfg.StrOpt('agent_backend',
default='noop',
help=_('Backend for the agent ramdisk to use for metrics. '
'Default possible backends are "noop" and "statsd".')),
cfg.BoolOpt('agent_prepend_host',
default=False,
help=_('Prepend the hostname to all metric names sent by the '
'agent ramdisk. The format of metric names is '
'[global_prefix.][uuid.][host_name.]prefix.'
'metric_name.')),
cfg.BoolOpt('agent_prepend_uuid',
default=False,
help=_('Prepend the node\'s Ironic uuid to all metric names '
'sent by the agent ramdisk. The format of metric names '
'is [global_prefix.][uuid.][host_name.]prefix.'
'metric_name.')),
cfg.BoolOpt('agent_prepend_host_reverse',
default=True,
help=_('Split the prepended host value by "." and reverse it '
'for metrics sent by the agent ramdisk (to better '
'match the reverse hierarchical form of domain '
'names).')),
cfg.StrOpt('agent_global_prefix',
help=_('Prefix all metric names sent by the agent ramdisk '
'with this value. The format of metric names is '
'[global_prefix.][uuid.][host_name.]prefix.'
'metric_name.'))
]
def register_opts(conf):
conf.register_opts(opts, group='metrics')

View File

@ -0,0 +1,36 @@
# Copyright 2016 Intel Corporation
# Copyright 2014 Rackspace, Inc.
# Copyright 2015 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 oslo_config import cfg
from ironic.common.i18n import _
opts = [
cfg.StrOpt('agent_statsd_host',
default='localhost',
help=_('Host for the agent ramdisk to use with the statsd '
'backend. This must be accessible from networks the '
'agent is booted on.')),
cfg.PortOpt('agent_statsd_port',
default=8125,
help=_('Port for the agent ramdisk to use with the statsd '
'backend.')),
]
def register_opts(conf):
conf.register_opts(opts, group='metrics_statsd')

View File

@ -54,6 +54,8 @@ _opts = [
('iscsi', ironic.drivers.modules.iscsi_deploy.iscsi_opts),
('keystone', ironic.conf.keystone.opts),
('neutron', ironic.conf.neutron.opts),
('metrics', ironic.conf.metrics.opts),
('metrics_statsd', ironic.conf.metrics_statsd.opts),
('oneview', ironic.conf.oneview.opts),
('pxe', itertools.chain(
ironic.drivers.modules.iscsi_deploy.pxe_opts,

View File

@ -729,6 +729,10 @@ class BaseAgentVendor(AgentDeployMixin, base.VendorInterface):
Currently, we don't handle the instance where the agent doesn't have
a matching node (i.e. a brand new, never been in Ironic node).
Additionally, we may pass on useful configurations to the agent, which
it would then be responsible for applying if relevant. Today these are
limited to heartbeat_timeout and metrics configuration.
kwargs should have the following format::
{
@ -781,8 +785,27 @@ class BaseAgentVendor(AgentDeployMixin, base.VendorInterface):
strutils.mask_password(ndict['driver_info'], "******"))
return {
# heartbeat_timeout is a config, so moving it into the
# config namespace. Instead of a separate deprecation,
# this will die when the vendor_passthru version of
# lookup goes away.
'heartbeat_timeout': CONF.agent.heartbeat_timeout,
'node': ndict,
'config': {
'metrics': {
'backend': CONF.metrics.agent_backend,
'prepend_host': CONF.metrics.agent_prepend_host,
'prepend_uuid': CONF.metrics.agent_prepend_uuid,
'prepend_host_reverse':
CONF.metrics.agent_prepend_host_reverse,
'global_prefix': CONF.metrics.agent_global_prefix
},
'metrics_statsd': {
'statsd_host': CONF.metrics_statsd.agent_statsd_host,
'statsd_port': CONF.metrics_statsd.agent_statsd_port
},
'heartbeat_timeout': CONF.agent.heartbeat_timeout
}
}
def _get_interfaces(self, inventory):

View File

@ -20,6 +20,7 @@ import time
import types
import mock
from oslo_config import cfg
from ironic.common import boot_devices
from ironic.common import exception
@ -37,6 +38,8 @@ from ironic.tests.unit.db import base as db_base
from ironic.tests.unit.db import utils as db_utils
from ironic.tests.unit.objects import utils as object_utils
CONF = cfg.CONF
INSTANCE_INFO = db_utils.get_test_agent_instance_info()
DRIVER_INFO = db_utils.get_test_agent_driver_info()
DRIVER_INTERNAL_INFO = db_utils.get_test_agent_driver_internal_info()
@ -114,10 +117,29 @@ class TestBaseAgentVendor(db_base.DbTestCase):
expected = copy.deepcopy(self.node.as_dict())
if not show_password:
expected['driver_info']['ipmi_password'] = '******'
self.config(agent_backend='statsd', group='metrics')
expected_metrics = {
'metrics': {
'backend': 'statsd',
'prepend_host': CONF.metrics.agent_prepend_host,
'prepend_uuid': CONF.metrics.agent_prepend_uuid,
'prepend_host_reverse':
CONF.metrics.agent_prepend_host_reverse,
'global_prefix': CONF.metrics.agent_global_prefix
},
'metrics_statsd': {
'statsd_host': CONF.metrics_statsd.agent_statsd_host,
'statsd_port': CONF.metrics_statsd.agent_statsd_port
},
'heartbeat_timeout': CONF.agent.heartbeat_timeout
}
find_mock.return_value = self.node
with task_manager.acquire(self.context, self.node.uuid) as task:
node = self.passthru.lookup(task.context, **kwargs)
self.assertEqual(expected, node['node'])
self.assertEqual(expected_metrics, node['config'])
def test_lookup_v2_show_password(self):
self._test_lookup_v2(show_password=True)

View File

@ -0,0 +1,7 @@
---
features:
- Adds the ability for ironic conductor to pass
configurations for agent metrics on lookup.
When paired with a sufficiently new ironic
python agent, this will configure the metrics
backends.