Merge "Metric chassis, driver, node, and port API calls"

This commit is contained in:
Jenkins 2016-07-18 17:34:25 +00:00 committed by Gerrit Code Review
commit d52d23222e
7 changed files with 106 additions and 1 deletions

View File

@ -156,6 +156,7 @@
# is set in the configuration file and other logging
# configuration options are ignored (for example,
# logging_context_format_string). (string value)
# Note: This option can be changed without restarting.
# Deprecated group/name - [DEFAULT]/log_config
#log_config_append = <None>
@ -736,8 +737,12 @@
# From oslo.db
#
# The file name to use with SQLite. (string value)
# DEPRECATED: The file name to use with SQLite. (string value)
# Deprecated group/name - [DEFAULT]/sqlite_db
# This option is deprecated for removal.
# Its value may be silently ignored in the future.
# Reason: Should use config option connection or
# slave_connection to connect the database.
#sqlite_db = oslo.sqlite
# If True, SQLite uses synchronous mode. (boolean value)
@ -1507,6 +1512,49 @@
#socket_timeout = 10000
[metrics]
#
# From ironic_lib.metrics
#
# Backend to use for the metrics system. (string value)
# Allowed values: noop, statsd
#backend = noop
# Prepend the hostname to all metric names. The format of
# metric names is
# [global_prefix.][host_name.]prefix.metric_name. (boolean
# value)
#prepend_host = false
# Split the prepended host value by "." and reverse it (to
# better match the reverse hierarchical form of domain names).
# (boolean value)
#prepend_host_reverse = true
# Prefix all metric names with this value. By default, there
# is no global prefix. The format of metric names is
# [global_prefix.][host_name.]prefix.metric_name. (string
# value)
#global_prefix = <None>
[metrics_statsd]
#
# From ironic_lib.metrics_statsd
#
# Host for use with the statsd backend. (string value)
#statsd_host = localhost
# Port to use with the statsd backend. (port value)
# Minimum value: 0
# Maximum value: 65535
#statsd_port = 8125
[neutron]
#

View File

@ -15,6 +15,7 @@
import datetime
from ironic_lib import metrics_utils
import pecan
from pecan import rest
from six.moves import http_client
@ -32,6 +33,8 @@ from ironic.common import exception
from ironic.common.i18n import _
from ironic import objects
METRICS = metrics_utils.get_metrics_logger(__name__)
_DEFAULT_RETURN_FIELDS = ('uuid', 'description')
@ -190,6 +193,7 @@ class ChassisController(rest.RestController):
sort_key=sort_key,
sort_dir=sort_dir)
@METRICS.timer('ChassisController.get_all')
@expose.expose(ChassisCollection, types.uuid, int,
wtypes.text, wtypes.text, types.listtype)
def get_all(self, marker=None, limit=None, sort_key='id', sort_dir='asc',
@ -209,6 +213,7 @@ class ChassisController(rest.RestController):
return self._get_chassis_collection(marker, limit, sort_key, sort_dir,
fields=fields)
@METRICS.timer('ChassisController.detail')
@expose.expose(ChassisCollection, types.uuid, int,
wtypes.text, wtypes.text)
def detail(self, marker=None, limit=None, sort_key='id', sort_dir='asc'):
@ -228,6 +233,7 @@ class ChassisController(rest.RestController):
return self._get_chassis_collection(marker, limit, sort_key, sort_dir,
resource_url)
@METRICS.timer('ChassisController.get_one')
@expose.expose(Chassis, types.uuid, types.listtype)
def get_one(self, chassis_uuid, fields=None):
"""Retrieve information about the given chassis.
@ -241,6 +247,7 @@ class ChassisController(rest.RestController):
chassis_uuid)
return Chassis.convert_with_links(rpc_chassis, fields=fields)
@METRICS.timer('ChassisController.post')
@expose.expose(Chassis, body=Chassis, status_code=http_client.CREATED)
def post(self, chassis):
"""Create a new chassis.
@ -254,6 +261,7 @@ class ChassisController(rest.RestController):
pecan.response.location = link.build_url('chassis', new_chassis.uuid)
return Chassis.convert_with_links(new_chassis)
@METRICS.timer('ChassisController.patch')
@wsme.validate(types.uuid, [ChassisPatchType])
@expose.expose(Chassis, types.uuid, body=[ChassisPatchType])
def patch(self, chassis_uuid, patch):
@ -286,6 +294,7 @@ class ChassisController(rest.RestController):
rpc_chassis.save()
return Chassis.convert_with_links(rpc_chassis)
@METRICS.timer('ChassisController.delete')
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
def delete(self, chassis_uuid):
"""Delete a chassis.

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from ironic_lib import metrics_utils
import pecan
from pecan import rest
from six.moves import http_client
@ -27,6 +28,8 @@ from ironic.api import expose
from ironic.common import exception
METRICS = metrics_utils.get_metrics_logger(__name__)
# Property information for drivers:
# key = driver name;
# value = dictionary of properties of that driver:
@ -139,6 +142,7 @@ class DriverPassthruController(rest.RestController):
'methods': ['GET']
}
@METRICS.timer('DriverPassthruController.methods')
@expose.expose(wtypes.text, wtypes.text)
def methods(self, driver_name):
"""Retrieve information about vendor methods of the given driver.
@ -157,6 +161,7 @@ class DriverPassthruController(rest.RestController):
return _VENDOR_METHODS[driver_name]
@METRICS.timer('DriverPassthruController._default')
@expose.expose(wtypes.text, wtypes.text, wtypes.text,
body=wtypes.text)
def _default(self, driver_name, method, data=None):
@ -178,6 +183,7 @@ class DriverRaidController(rest.RestController):
'logical_disk_properties': ['GET']
}
@METRICS.timer('DriverRaidController.logical_disk_properties')
@expose.expose(types.jsontype, wtypes.text)
def logical_disk_properties(self, driver_name):
"""Returns the logical disk properties for the driver.
@ -222,6 +228,7 @@ class DriversController(rest.RestController):
'properties': ['GET'],
}
@METRICS.timer('DriversController.get_all')
@expose.expose(DriverList)
def get_all(self):
"""Retrieve a list of drivers."""
@ -232,6 +239,7 @@ class DriversController(rest.RestController):
driver_list = pecan.request.dbapi.get_active_driver_dict()
return DriverList.convert_with_links(driver_list)
@METRICS.timer('DriversController.get_one')
@expose.expose(Driver, wtypes.text)
def get_one(self, driver_name):
"""Retrieve a single driver."""
@ -247,6 +255,7 @@ class DriversController(rest.RestController):
raise exception.DriverNotFound(driver_name=driver_name)
@METRICS.timer('DriversController.properties')
@expose.expose(wtypes.text, wtypes.text)
def properties(self, driver_name):
"""Retrieve property information of the given driver.

View File

@ -16,6 +16,7 @@
import ast
import datetime
from ironic_lib import metrics_utils
import jsonschema
from oslo_config import cfg
from oslo_log import log
@ -79,6 +80,8 @@ _CLEAN_STEPS_SCHEMA = {
}
}
METRICS = metrics_utils.get_metrics_logger(__name__)
# Vendor information for node's driver:
# key = driver name;
# value = dictionary of node vendor methods of that driver:
@ -176,6 +179,7 @@ class BootDeviceController(rest.RestController):
return pecan.request.rpcapi.get_boot_device(pecan.request.context,
rpc_node.uuid, topic)
@METRICS.timer('BootDeviceController.put')
@expose.expose(None, types.uuid_or_name, wtypes.text, types.boolean,
status_code=http_client.NO_CONTENT)
def put(self, node_ident, boot_device, persistent=False):
@ -199,6 +203,7 @@ class BootDeviceController(rest.RestController):
persistent=persistent,
topic=topic)
@METRICS.timer('BootDeviceController.get')
@expose.expose(wtypes.text, types.uuid_or_name)
def get(self, node_ident):
"""Get the current boot device for a node.
@ -214,6 +219,7 @@ class BootDeviceController(rest.RestController):
"""
return self._get_boot_device(node_ident)
@METRICS.timer('BootDeviceController.supported')
@expose.expose(wtypes.text, types.uuid_or_name)
def supported(self, node_ident):
"""Get a list of the supported boot devices.
@ -251,6 +257,7 @@ class ConsoleInfo(base.APIBase):
class NodeConsoleController(rest.RestController):
@METRICS.timer('NodeConsoleController.get')
@expose.expose(ConsoleInfo, types.uuid_or_name)
def get(self, node_ident):
"""Get connection information about the console.
@ -269,6 +276,7 @@ class NodeConsoleController(rest.RestController):
return ConsoleInfo(console_enabled=console_state, console_info=console)
@METRICS.timer('NodeConsoleController.put')
@expose.expose(None, types.uuid_or_name, types.boolean,
status_code=http_client.ACCEPTED)
def put(self, node_ident, enabled):
@ -359,6 +367,7 @@ class NodeStatesController(rest.RestController):
console = NodeConsoleController()
"""Expose console as a sub-element of states"""
@METRICS.timer('NodeStatesController.get')
@expose.expose(NodeStates, types.uuid_or_name)
def get(self, node_ident):
"""List the states of the node.
@ -371,6 +380,7 @@ class NodeStatesController(rest.RestController):
rpc_node = api_utils.get_rpc_node(node_ident)
return NodeStates.convert(rpc_node)
@METRICS.timer('NodeStatesController.raid')
@expose.expose(None, types.uuid_or_name, body=types.jsontype)
def raid(self, node_ident, target_raid_config):
"""Set the target raid config of the node.
@ -399,6 +409,7 @@ class NodeStatesController(rest.RestController):
e.code = http_client.NOT_FOUND
raise
@METRICS.timer('NodeStatesController.power')
@expose.expose(None, types.uuid_or_name, wtypes.text,
status_code=http_client.ACCEPTED)
def power(self, node_ident, target):
@ -438,6 +449,7 @@ class NodeStatesController(rest.RestController):
url_args = '/'.join([node_ident, 'states'])
pecan.response.location = link.build_url('nodes', url_args)
@METRICS.timer('NodeStatesController.provision')
@expose.expose(None, types.uuid_or_name, wtypes.text,
wtypes.text, types.jsontype,
status_code=http_client.ACCEPTED)
@ -873,6 +885,7 @@ class NodeVendorPassthruController(rest.RestController):
'methods': ['GET']
}
@METRICS.timer('NodeVendorPassthruController.methods')
@expose.expose(wtypes.text, types.uuid_or_name)
def methods(self, node_ident):
"""Retrieve information about vendor methods of the given node.
@ -893,6 +906,7 @@ class NodeVendorPassthruController(rest.RestController):
return _VENDOR_METHODS[rpc_node.driver]
@METRICS.timer('NodeVendorPassthruController._default')
@expose.expose(wtypes.text, types.uuid_or_name, wtypes.text,
body=wtypes.text)
def _default(self, node_ident, method, data=None):
@ -924,6 +938,7 @@ class NodeMaintenanceController(rest.RestController):
pecan.request.rpcapi.update_node(pecan.request.context,
rpc_node, topic=topic)
@METRICS.timer('NodeMaintenanceController.put')
@expose.expose(None, types.uuid_or_name, wtypes.text,
status_code=http_client.ACCEPTED)
def put(self, node_ident, reason=None):
@ -935,6 +950,7 @@ class NodeMaintenanceController(rest.RestController):
"""
self._set_maintenance(node_ident, True, reason=reason)
@METRICS.timer('NodeMaintenanceController.delete')
@expose.expose(None, types.uuid_or_name, status_code=http_client.ACCEPTED)
def delete(self, node_ident):
"""Remove the node from maintenance mode.
@ -1109,6 +1125,7 @@ class NodesController(rest.RestController):
"enabled. Please stop the console first.") % node_ident,
status_code=http_client.CONFLICT)
@METRICS.timer('NodesController.get_all')
@expose.expose(NodeCollection, types.uuid, types.uuid, types.boolean,
types.boolean, wtypes.text, types.uuid, int, wtypes.text,
wtypes.text, wtypes.text, types.listtype)
@ -1151,6 +1168,7 @@ class NodesController(rest.RestController):
limit, sort_key, sort_dir,
driver, fields=fields)
@METRICS.timer('NodesController.detail')
@expose.expose(NodeCollection, types.uuid, types.uuid, types.boolean,
types.boolean, wtypes.text, types.uuid, int, wtypes.text,
wtypes.text, wtypes.text)
@ -1192,6 +1210,7 @@ class NodesController(rest.RestController):
limit, sort_key, sort_dir,
driver, resource_url)
@METRICS.timer('NodesController.validate')
@expose.expose(wtypes.text, types.uuid_or_name, types.uuid)
def validate(self, node=None, node_uuid=None):
"""Validate the driver interfaces, using the node's UUID or name.
@ -1215,6 +1234,7 @@ class NodesController(rest.RestController):
return pecan.request.rpcapi.validate_driver_interfaces(
pecan.request.context, rpc_node.uuid, topic)
@METRICS.timer('NodesController.get_one')
@expose.expose(Node, types.uuid_or_name, types.listtype)
def get_one(self, node_ident, fields=None):
"""Retrieve information about the given node.
@ -1232,6 +1252,7 @@ class NodesController(rest.RestController):
rpc_node = api_utils.get_rpc_node(node_ident)
return Node.convert_with_links(rpc_node, fields=fields)
@METRICS.timer('NodesController.post')
@expose.expose(Node, body=Node, status_code=http_client.CREATED)
def post(self, node):
"""Create a new node.
@ -1289,6 +1310,7 @@ class NodesController(rest.RestController):
pecan.response.location = link.build_url('nodes', new_node.uuid)
return Node.convert_with_links(new_node)
@METRICS.timer('NodesController.patch')
@wsme.validate(types.uuid, [NodePatchType])
@expose.expose(Node, types.uuid_or_name, body=[NodePatchType])
def patch(self, node_ident, patch):
@ -1366,6 +1388,7 @@ class NodesController(rest.RestController):
return Node.convert_with_links(new_node)
@METRICS.timer('NodesController.delete')
@expose.expose(None, types.uuid_or_name,
status_code=http_client.NO_CONTENT)
def delete(self, node_ident):

View File

@ -15,6 +15,7 @@
import datetime
from ironic_lib import metrics_utils
from oslo_utils import uuidutils
import pecan
from pecan import rest
@ -32,6 +33,8 @@ from ironic.common import exception
from ironic.common.i18n import _
from ironic import objects
METRICS = metrics_utils.get_metrics_logger(__name__)
_DEFAULT_RETURN_FIELDS = ('uuid', 'address')
@ -280,6 +283,7 @@ class PortsController(rest.RestController):
except exception.PortNotFound:
return []
@METRICS.timer('PortsController.get_all')
@expose.expose(PortCollection, types.uuid_or_name, types.uuid,
types.macaddress, types.uuid, int, wtypes.text,
wtypes.text, types.listtype)
@ -324,6 +328,7 @@ class PortsController(rest.RestController):
limit, sort_key, sort_dir,
fields=fields)
@METRICS.timer('PortsController.detail')
@expose.expose(PortCollection, types.uuid_or_name, types.uuid,
types.macaddress, types.uuid, int, wtypes.text,
wtypes.text)
@ -364,6 +369,7 @@ class PortsController(rest.RestController):
limit, sort_key, sort_dir,
resource_url)
@METRICS.timer('PortsController.get_one')
@expose.expose(Port, types.uuid, types.listtype)
def get_one(self, port_uuid, fields=None):
"""Retrieve information about the given port.
@ -381,6 +387,7 @@ class PortsController(rest.RestController):
rpc_port = objects.Port.get_by_uuid(pecan.request.context, port_uuid)
return Port.convert_with_links(rpc_port, fields=fields)
@METRICS.timer('PortsController.post')
@expose.expose(Port, body=Port, status_code=http_client.CREATED)
def post(self, port):
"""Create a new port.
@ -404,6 +411,7 @@ class PortsController(rest.RestController):
pecan.response.location = link.build_url('ports', new_port.uuid)
return Port.convert_with_links(new_port)
@METRICS.timer('PortsController.patch')
@wsme.validate(types.uuid, [PortPatchType])
@expose.expose(Port, types.uuid, body=[PortPatchType])
def patch(self, port_uuid, patch):
@ -455,6 +463,7 @@ class PortsController(rest.RestController):
return Port.convert_with_links(new_port)
@METRICS.timer('PortsController.delete')
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
def delete(self, port_uuid):
"""Delete a port.

View File

@ -0,0 +1,5 @@
---
features:
- With this change, ironic now emits timing metrics
for all API methods to statsd, if enabled by config
in the [metrics] and [metrics_statsd] sections.

View File

@ -4,6 +4,8 @@ wrap_width = 62
namespace = ironic
namespace = ironic_lib.disk_utils
namespace = ironic_lib.disk_partitioner
namespace = ironic_lib.metrics
namespace = ironic_lib.metrics_statsd
namespace = ironic_lib.utils
namespace = oslo.db
namespace = oslo.messaging