Metric chassis, driver, node, and port API calls
This change adds initial metrics for Ironic based on new support in ironic-lib. Emits timing metrics for basic Ironic API calls. Bumps ironic-lib to 2.0.0 in requirements to add metrics support, as well as adding ironic_lib.metrics and ironic_lib.metrics_statds to ironic-config-generator.conf to get them in the sample config, which is also regenerated. Change-Id: Ic35802e4cd11763ebbedb8ddc28f7e8dc535cc2f Partial-bug: #1526219
This commit is contained in:
parent
e8e1ea9ed6
commit
15c366580a
@ -135,6 +135,7 @@
|
|||||||
# is set in the configuration file and other logging
|
# is set in the configuration file and other logging
|
||||||
# configuration options are ignored (for example,
|
# configuration options are ignored (for example,
|
||||||
# logging_context_format_string). (string value)
|
# logging_context_format_string). (string value)
|
||||||
|
# Note: This option can be changed without restarting.
|
||||||
# Deprecated group/name - [DEFAULT]/log_config
|
# Deprecated group/name - [DEFAULT]/log_config
|
||||||
#log_config_append = <None>
|
#log_config_append = <None>
|
||||||
|
|
||||||
@ -713,8 +714,12 @@
|
|||||||
# From oslo.db
|
# 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
|
# 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
|
#sqlite_db = oslo.sqlite
|
||||||
|
|
||||||
# If True, SQLite uses synchronous mode. (boolean value)
|
# If True, SQLite uses synchronous mode. (boolean value)
|
||||||
@ -902,17 +907,18 @@
|
|||||||
|
|
||||||
# Size of EFI system partition in MiB when configuring UEFI
|
# Size of EFI system partition in MiB when configuring UEFI
|
||||||
# systems for local boot. (integer value)
|
# systems for local boot. (integer value)
|
||||||
# Deprecated group/name - [deploy]/efi_system_partition_size
|
|
||||||
#efi_system_partition_size = 200
|
#efi_system_partition_size = 200
|
||||||
|
|
||||||
|
# Size of BIOS Boot partition in MiB when configuring GPT
|
||||||
|
# partitioned systems for local boot in BIOS. (integer value)
|
||||||
|
#bios_boot_partition_size = 1
|
||||||
|
|
||||||
# Block size to use when writing to the nodes disk. (string
|
# Block size to use when writing to the nodes disk. (string
|
||||||
# value)
|
# value)
|
||||||
# Deprecated group/name - [deploy]/dd_block_size
|
|
||||||
#dd_block_size = 1M
|
#dd_block_size = 1M
|
||||||
|
|
||||||
# Maximum attempts to verify an iSCSI connection is active,
|
# Maximum attempts to verify an iSCSI connection is active,
|
||||||
# sleeping 1 second between attempts. (integer value)
|
# sleeping 1 second between attempts. (integer value)
|
||||||
# Deprecated group/name - [deploy]/iscsi_verify_attempts
|
|
||||||
#iscsi_verify_attempts = 3
|
#iscsi_verify_attempts = 3
|
||||||
|
|
||||||
|
|
||||||
@ -1271,7 +1277,16 @@
|
|||||||
# From keystonemiddleware.auth_token
|
# From keystonemiddleware.auth_token
|
||||||
#
|
#
|
||||||
|
|
||||||
# Complete public Identity API endpoint. (string value)
|
# Complete "public" Identity API endpoint. This endpoint
|
||||||
|
# should not be an "admin" endpoint, as it should be
|
||||||
|
# accessible by all end users. Unauthenticated clients are
|
||||||
|
# redirected to this endpoint to authenticate. Although this
|
||||||
|
# endpoint should ideally be unversioned, client support in
|
||||||
|
# the wild varies. If you're using a versioned v2 endpoint
|
||||||
|
# here, then this should *not* be the same endpoint the
|
||||||
|
# service user utilizes for validating tokens, because normal
|
||||||
|
# end users may not be able to reach that endpoint. (string
|
||||||
|
# value)
|
||||||
#auth_uri = <None>
|
#auth_uri = <None>
|
||||||
|
|
||||||
# API version of the admin Identity API endpoint. (string
|
# API version of the admin Identity API endpoint. (string
|
||||||
@ -1470,6 +1485,49 @@
|
|||||||
#socket_timeout = 10000
|
#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]
|
[neutron]
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from ironic_lib import metrics_utils
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import rest
|
from pecan import rest
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
@ -32,6 +33,8 @@ from ironic.common import exception
|
|||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
from ironic import objects
|
from ironic import objects
|
||||||
|
|
||||||
|
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
_DEFAULT_RETURN_FIELDS = ('uuid', 'description')
|
_DEFAULT_RETURN_FIELDS = ('uuid', 'description')
|
||||||
|
|
||||||
@ -190,6 +193,7 @@ class ChassisController(rest.RestController):
|
|||||||
sort_key=sort_key,
|
sort_key=sort_key,
|
||||||
sort_dir=sort_dir)
|
sort_dir=sort_dir)
|
||||||
|
|
||||||
|
@METRICS.timer('ChassisController.get_all')
|
||||||
@expose.expose(ChassisCollection, types.uuid, int,
|
@expose.expose(ChassisCollection, types.uuid, int,
|
||||||
wtypes.text, wtypes.text, types.listtype)
|
wtypes.text, wtypes.text, types.listtype)
|
||||||
def get_all(self, marker=None, limit=None, sort_key='id', sort_dir='asc',
|
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,
|
return self._get_chassis_collection(marker, limit, sort_key, sort_dir,
|
||||||
fields=fields)
|
fields=fields)
|
||||||
|
|
||||||
|
@METRICS.timer('ChassisController.detail')
|
||||||
@expose.expose(ChassisCollection, types.uuid, int,
|
@expose.expose(ChassisCollection, types.uuid, int,
|
||||||
wtypes.text, wtypes.text)
|
wtypes.text, wtypes.text)
|
||||||
def detail(self, marker=None, limit=None, sort_key='id', sort_dir='asc'):
|
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,
|
return self._get_chassis_collection(marker, limit, sort_key, sort_dir,
|
||||||
resource_url)
|
resource_url)
|
||||||
|
|
||||||
|
@METRICS.timer('ChassisController.get_one')
|
||||||
@expose.expose(Chassis, types.uuid, types.listtype)
|
@expose.expose(Chassis, types.uuid, types.listtype)
|
||||||
def get_one(self, chassis_uuid, fields=None):
|
def get_one(self, chassis_uuid, fields=None):
|
||||||
"""Retrieve information about the given chassis.
|
"""Retrieve information about the given chassis.
|
||||||
@ -241,6 +247,7 @@ class ChassisController(rest.RestController):
|
|||||||
chassis_uuid)
|
chassis_uuid)
|
||||||
return Chassis.convert_with_links(rpc_chassis, fields=fields)
|
return Chassis.convert_with_links(rpc_chassis, fields=fields)
|
||||||
|
|
||||||
|
@METRICS.timer('ChassisController.post')
|
||||||
@expose.expose(Chassis, body=Chassis, status_code=http_client.CREATED)
|
@expose.expose(Chassis, body=Chassis, status_code=http_client.CREATED)
|
||||||
def post(self, chassis):
|
def post(self, chassis):
|
||||||
"""Create a new chassis.
|
"""Create a new chassis.
|
||||||
@ -254,6 +261,7 @@ class ChassisController(rest.RestController):
|
|||||||
pecan.response.location = link.build_url('chassis', new_chassis.uuid)
|
pecan.response.location = link.build_url('chassis', new_chassis.uuid)
|
||||||
return Chassis.convert_with_links(new_chassis)
|
return Chassis.convert_with_links(new_chassis)
|
||||||
|
|
||||||
|
@METRICS.timer('ChassisController.patch')
|
||||||
@wsme.validate(types.uuid, [ChassisPatchType])
|
@wsme.validate(types.uuid, [ChassisPatchType])
|
||||||
@expose.expose(Chassis, types.uuid, body=[ChassisPatchType])
|
@expose.expose(Chassis, types.uuid, body=[ChassisPatchType])
|
||||||
def patch(self, chassis_uuid, patch):
|
def patch(self, chassis_uuid, patch):
|
||||||
@ -286,6 +294,7 @@ class ChassisController(rest.RestController):
|
|||||||
rpc_chassis.save()
|
rpc_chassis.save()
|
||||||
return Chassis.convert_with_links(rpc_chassis)
|
return Chassis.convert_with_links(rpc_chassis)
|
||||||
|
|
||||||
|
@METRICS.timer('ChassisController.delete')
|
||||||
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
|
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
|
||||||
def delete(self, chassis_uuid):
|
def delete(self, chassis_uuid):
|
||||||
"""Delete a chassis.
|
"""Delete a chassis.
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from ironic_lib import metrics_utils
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import rest
|
from pecan import rest
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
@ -27,6 +28,8 @@ from ironic.api import expose
|
|||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
|
|
||||||
|
|
||||||
|
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||||
|
|
||||||
# Property information for drivers:
|
# Property information for drivers:
|
||||||
# key = driver name;
|
# key = driver name;
|
||||||
# value = dictionary of properties of that driver:
|
# value = dictionary of properties of that driver:
|
||||||
@ -139,6 +142,7 @@ class DriverPassthruController(rest.RestController):
|
|||||||
'methods': ['GET']
|
'methods': ['GET']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@METRICS.timer('DriverPassthruController.methods')
|
||||||
@expose.expose(wtypes.text, wtypes.text)
|
@expose.expose(wtypes.text, wtypes.text)
|
||||||
def methods(self, driver_name):
|
def methods(self, driver_name):
|
||||||
"""Retrieve information about vendor methods of the given driver.
|
"""Retrieve information about vendor methods of the given driver.
|
||||||
@ -157,6 +161,7 @@ class DriverPassthruController(rest.RestController):
|
|||||||
|
|
||||||
return _VENDOR_METHODS[driver_name]
|
return _VENDOR_METHODS[driver_name]
|
||||||
|
|
||||||
|
@METRICS.timer('DriverPassthruController._default')
|
||||||
@expose.expose(wtypes.text, wtypes.text, wtypes.text,
|
@expose.expose(wtypes.text, wtypes.text, wtypes.text,
|
||||||
body=wtypes.text)
|
body=wtypes.text)
|
||||||
def _default(self, driver_name, method, data=None):
|
def _default(self, driver_name, method, data=None):
|
||||||
@ -178,6 +183,7 @@ class DriverRaidController(rest.RestController):
|
|||||||
'logical_disk_properties': ['GET']
|
'logical_disk_properties': ['GET']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@METRICS.timer('DriverRaidController.logical_disk_properties')
|
||||||
@expose.expose(types.jsontype, wtypes.text)
|
@expose.expose(types.jsontype, wtypes.text)
|
||||||
def logical_disk_properties(self, driver_name):
|
def logical_disk_properties(self, driver_name):
|
||||||
"""Returns the logical disk properties for the driver.
|
"""Returns the logical disk properties for the driver.
|
||||||
@ -222,6 +228,7 @@ class DriversController(rest.RestController):
|
|||||||
'properties': ['GET'],
|
'properties': ['GET'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@METRICS.timer('DriversController.get_all')
|
||||||
@expose.expose(DriverList)
|
@expose.expose(DriverList)
|
||||||
def get_all(self):
|
def get_all(self):
|
||||||
"""Retrieve a list of drivers."""
|
"""Retrieve a list of drivers."""
|
||||||
@ -232,6 +239,7 @@ class DriversController(rest.RestController):
|
|||||||
driver_list = pecan.request.dbapi.get_active_driver_dict()
|
driver_list = pecan.request.dbapi.get_active_driver_dict()
|
||||||
return DriverList.convert_with_links(driver_list)
|
return DriverList.convert_with_links(driver_list)
|
||||||
|
|
||||||
|
@METRICS.timer('DriversController.get_one')
|
||||||
@expose.expose(Driver, wtypes.text)
|
@expose.expose(Driver, wtypes.text)
|
||||||
def get_one(self, driver_name):
|
def get_one(self, driver_name):
|
||||||
"""Retrieve a single driver."""
|
"""Retrieve a single driver."""
|
||||||
@ -247,6 +255,7 @@ class DriversController(rest.RestController):
|
|||||||
|
|
||||||
raise exception.DriverNotFound(driver_name=driver_name)
|
raise exception.DriverNotFound(driver_name=driver_name)
|
||||||
|
|
||||||
|
@METRICS.timer('DriversController.properties')
|
||||||
@expose.expose(wtypes.text, wtypes.text)
|
@expose.expose(wtypes.text, wtypes.text)
|
||||||
def properties(self, driver_name):
|
def properties(self, driver_name):
|
||||||
"""Retrieve property information of the given driver.
|
"""Retrieve property information of the given driver.
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import ast
|
import ast
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from ironic_lib import metrics_utils
|
||||||
import jsonschema
|
import jsonschema
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
@ -78,6 +79,8 @@ _CLEAN_STEPS_SCHEMA = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||||
|
|
||||||
# Vendor information for node's driver:
|
# Vendor information for node's driver:
|
||||||
# key = driver name;
|
# key = driver name;
|
||||||
# value = dictionary of node vendor methods of that driver:
|
# value = dictionary of node vendor methods of that driver:
|
||||||
@ -167,6 +170,7 @@ class BootDeviceController(rest.RestController):
|
|||||||
return pecan.request.rpcapi.get_boot_device(pecan.request.context,
|
return pecan.request.rpcapi.get_boot_device(pecan.request.context,
|
||||||
rpc_node.uuid, topic)
|
rpc_node.uuid, topic)
|
||||||
|
|
||||||
|
@METRICS.timer('BootDeviceController.put')
|
||||||
@expose.expose(None, types.uuid_or_name, wtypes.text, types.boolean,
|
@expose.expose(None, types.uuid_or_name, wtypes.text, types.boolean,
|
||||||
status_code=http_client.NO_CONTENT)
|
status_code=http_client.NO_CONTENT)
|
||||||
def put(self, node_ident, boot_device, persistent=False):
|
def put(self, node_ident, boot_device, persistent=False):
|
||||||
@ -190,6 +194,7 @@ class BootDeviceController(rest.RestController):
|
|||||||
persistent=persistent,
|
persistent=persistent,
|
||||||
topic=topic)
|
topic=topic)
|
||||||
|
|
||||||
|
@METRICS.timer('BootDeviceController.get')
|
||||||
@expose.expose(wtypes.text, types.uuid_or_name)
|
@expose.expose(wtypes.text, types.uuid_or_name)
|
||||||
def get(self, node_ident):
|
def get(self, node_ident):
|
||||||
"""Get the current boot device for a node.
|
"""Get the current boot device for a node.
|
||||||
@ -205,6 +210,7 @@ class BootDeviceController(rest.RestController):
|
|||||||
"""
|
"""
|
||||||
return self._get_boot_device(node_ident)
|
return self._get_boot_device(node_ident)
|
||||||
|
|
||||||
|
@METRICS.timer('BootDeviceController.supported')
|
||||||
@expose.expose(wtypes.text, types.uuid_or_name)
|
@expose.expose(wtypes.text, types.uuid_or_name)
|
||||||
def supported(self, node_ident):
|
def supported(self, node_ident):
|
||||||
"""Get a list of the supported boot devices.
|
"""Get a list of the supported boot devices.
|
||||||
@ -242,6 +248,7 @@ class ConsoleInfo(base.APIBase):
|
|||||||
|
|
||||||
class NodeConsoleController(rest.RestController):
|
class NodeConsoleController(rest.RestController):
|
||||||
|
|
||||||
|
@METRICS.timer('NodeConsoleController.get')
|
||||||
@expose.expose(ConsoleInfo, types.uuid_or_name)
|
@expose.expose(ConsoleInfo, types.uuid_or_name)
|
||||||
def get(self, node_ident):
|
def get(self, node_ident):
|
||||||
"""Get connection information about the console.
|
"""Get connection information about the console.
|
||||||
@ -260,6 +267,7 @@ class NodeConsoleController(rest.RestController):
|
|||||||
|
|
||||||
return ConsoleInfo(console_enabled=console_state, console_info=console)
|
return ConsoleInfo(console_enabled=console_state, console_info=console)
|
||||||
|
|
||||||
|
@METRICS.timer('NodeConsoleController.put')
|
||||||
@expose.expose(None, types.uuid_or_name, types.boolean,
|
@expose.expose(None, types.uuid_or_name, types.boolean,
|
||||||
status_code=http_client.ACCEPTED)
|
status_code=http_client.ACCEPTED)
|
||||||
def put(self, node_ident, enabled):
|
def put(self, node_ident, enabled):
|
||||||
@ -350,6 +358,7 @@ class NodeStatesController(rest.RestController):
|
|||||||
console = NodeConsoleController()
|
console = NodeConsoleController()
|
||||||
"""Expose console as a sub-element of states"""
|
"""Expose console as a sub-element of states"""
|
||||||
|
|
||||||
|
@METRICS.timer('NodeStatesController.get')
|
||||||
@expose.expose(NodeStates, types.uuid_or_name)
|
@expose.expose(NodeStates, types.uuid_or_name)
|
||||||
def get(self, node_ident):
|
def get(self, node_ident):
|
||||||
"""List the states of the node.
|
"""List the states of the node.
|
||||||
@ -362,6 +371,7 @@ class NodeStatesController(rest.RestController):
|
|||||||
rpc_node = api_utils.get_rpc_node(node_ident)
|
rpc_node = api_utils.get_rpc_node(node_ident)
|
||||||
return NodeStates.convert(rpc_node)
|
return NodeStates.convert(rpc_node)
|
||||||
|
|
||||||
|
@METRICS.timer('NodeStatesController.raid')
|
||||||
@expose.expose(None, types.uuid_or_name, body=types.jsontype)
|
@expose.expose(None, types.uuid_or_name, body=types.jsontype)
|
||||||
def raid(self, node_ident, target_raid_config):
|
def raid(self, node_ident, target_raid_config):
|
||||||
"""Set the target raid config of the node.
|
"""Set the target raid config of the node.
|
||||||
@ -390,6 +400,7 @@ class NodeStatesController(rest.RestController):
|
|||||||
e.code = http_client.NOT_FOUND
|
e.code = http_client.NOT_FOUND
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@METRICS.timer('NodeStatesController.power')
|
||||||
@expose.expose(None, types.uuid_or_name, wtypes.text,
|
@expose.expose(None, types.uuid_or_name, wtypes.text,
|
||||||
status_code=http_client.ACCEPTED)
|
status_code=http_client.ACCEPTED)
|
||||||
def power(self, node_ident, target):
|
def power(self, node_ident, target):
|
||||||
@ -429,6 +440,7 @@ class NodeStatesController(rest.RestController):
|
|||||||
url_args = '/'.join([node_ident, 'states'])
|
url_args = '/'.join([node_ident, 'states'])
|
||||||
pecan.response.location = link.build_url('nodes', url_args)
|
pecan.response.location = link.build_url('nodes', url_args)
|
||||||
|
|
||||||
|
@METRICS.timer('NodeStatesController.provision')
|
||||||
@expose.expose(None, types.uuid_or_name, wtypes.text,
|
@expose.expose(None, types.uuid_or_name, wtypes.text,
|
||||||
wtypes.text, types.jsontype,
|
wtypes.text, types.jsontype,
|
||||||
status_code=http_client.ACCEPTED)
|
status_code=http_client.ACCEPTED)
|
||||||
@ -860,6 +872,7 @@ class NodeVendorPassthruController(rest.RestController):
|
|||||||
'methods': ['GET']
|
'methods': ['GET']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@METRICS.timer('NodeVendorPassthruController.methods')
|
||||||
@expose.expose(wtypes.text, types.uuid_or_name)
|
@expose.expose(wtypes.text, types.uuid_or_name)
|
||||||
def methods(self, node_ident):
|
def methods(self, node_ident):
|
||||||
"""Retrieve information about vendor methods of the given node.
|
"""Retrieve information about vendor methods of the given node.
|
||||||
@ -880,6 +893,7 @@ class NodeVendorPassthruController(rest.RestController):
|
|||||||
|
|
||||||
return _VENDOR_METHODS[rpc_node.driver]
|
return _VENDOR_METHODS[rpc_node.driver]
|
||||||
|
|
||||||
|
@METRICS.timer('NodeVendorPassthruController._default')
|
||||||
@expose.expose(wtypes.text, types.uuid_or_name, wtypes.text,
|
@expose.expose(wtypes.text, types.uuid_or_name, wtypes.text,
|
||||||
body=wtypes.text)
|
body=wtypes.text)
|
||||||
def _default(self, node_ident, method, data=None):
|
def _default(self, node_ident, method, data=None):
|
||||||
@ -911,6 +925,7 @@ class NodeMaintenanceController(rest.RestController):
|
|||||||
pecan.request.rpcapi.update_node(pecan.request.context,
|
pecan.request.rpcapi.update_node(pecan.request.context,
|
||||||
rpc_node, topic=topic)
|
rpc_node, topic=topic)
|
||||||
|
|
||||||
|
@METRICS.timer('NodeMaintenanceController.put')
|
||||||
@expose.expose(None, types.uuid_or_name, wtypes.text,
|
@expose.expose(None, types.uuid_or_name, wtypes.text,
|
||||||
status_code=http_client.ACCEPTED)
|
status_code=http_client.ACCEPTED)
|
||||||
def put(self, node_ident, reason=None):
|
def put(self, node_ident, reason=None):
|
||||||
@ -922,6 +937,7 @@ class NodeMaintenanceController(rest.RestController):
|
|||||||
"""
|
"""
|
||||||
self._set_maintenance(node_ident, True, reason=reason)
|
self._set_maintenance(node_ident, True, reason=reason)
|
||||||
|
|
||||||
|
@METRICS.timer('NodeMaintenanceController.delete')
|
||||||
@expose.expose(None, types.uuid_or_name, status_code=http_client.ACCEPTED)
|
@expose.expose(None, types.uuid_or_name, status_code=http_client.ACCEPTED)
|
||||||
def delete(self, node_ident):
|
def delete(self, node_ident):
|
||||||
"""Remove the node from maintenance mode.
|
"""Remove the node from maintenance mode.
|
||||||
@ -1096,6 +1112,7 @@ class NodesController(rest.RestController):
|
|||||||
"enabled. Please stop the console first.") % node_ident,
|
"enabled. Please stop the console first.") % node_ident,
|
||||||
status_code=http_client.CONFLICT)
|
status_code=http_client.CONFLICT)
|
||||||
|
|
||||||
|
@METRICS.timer('NodesController.get_all')
|
||||||
@expose.expose(NodeCollection, types.uuid, types.uuid, types.boolean,
|
@expose.expose(NodeCollection, types.uuid, types.uuid, types.boolean,
|
||||||
types.boolean, wtypes.text, types.uuid, int, wtypes.text,
|
types.boolean, wtypes.text, types.uuid, int, wtypes.text,
|
||||||
wtypes.text, wtypes.text, types.listtype)
|
wtypes.text, wtypes.text, types.listtype)
|
||||||
@ -1137,6 +1154,7 @@ class NodesController(rest.RestController):
|
|||||||
limit, sort_key, sort_dir,
|
limit, sort_key, sort_dir,
|
||||||
driver, fields=fields)
|
driver, fields=fields)
|
||||||
|
|
||||||
|
@METRICS.timer('NodesController.detail')
|
||||||
@expose.expose(NodeCollection, types.uuid, types.uuid, types.boolean,
|
@expose.expose(NodeCollection, types.uuid, types.uuid, types.boolean,
|
||||||
types.boolean, wtypes.text, types.uuid, int, wtypes.text,
|
types.boolean, wtypes.text, types.uuid, int, wtypes.text,
|
||||||
wtypes.text, wtypes.text)
|
wtypes.text, wtypes.text)
|
||||||
@ -1178,6 +1196,7 @@ class NodesController(rest.RestController):
|
|||||||
limit, sort_key, sort_dir,
|
limit, sort_key, sort_dir,
|
||||||
driver, resource_url)
|
driver, resource_url)
|
||||||
|
|
||||||
|
@METRICS.timer('NodesController.validate')
|
||||||
@expose.expose(wtypes.text, types.uuid_or_name, types.uuid)
|
@expose.expose(wtypes.text, types.uuid_or_name, types.uuid)
|
||||||
def validate(self, node=None, node_uuid=None):
|
def validate(self, node=None, node_uuid=None):
|
||||||
"""Validate the driver interfaces, using the node's UUID or name.
|
"""Validate the driver interfaces, using the node's UUID or name.
|
||||||
@ -1201,6 +1220,7 @@ class NodesController(rest.RestController):
|
|||||||
return pecan.request.rpcapi.validate_driver_interfaces(
|
return pecan.request.rpcapi.validate_driver_interfaces(
|
||||||
pecan.request.context, rpc_node.uuid, topic)
|
pecan.request.context, rpc_node.uuid, topic)
|
||||||
|
|
||||||
|
@METRICS.timer('NodesController.get_one')
|
||||||
@expose.expose(Node, types.uuid_or_name, types.listtype)
|
@expose.expose(Node, types.uuid_or_name, types.listtype)
|
||||||
def get_one(self, node_ident, fields=None):
|
def get_one(self, node_ident, fields=None):
|
||||||
"""Retrieve information about the given node.
|
"""Retrieve information about the given node.
|
||||||
@ -1217,6 +1237,7 @@ class NodesController(rest.RestController):
|
|||||||
rpc_node = api_utils.get_rpc_node(node_ident)
|
rpc_node = api_utils.get_rpc_node(node_ident)
|
||||||
return Node.convert_with_links(rpc_node, fields=fields)
|
return Node.convert_with_links(rpc_node, fields=fields)
|
||||||
|
|
||||||
|
@METRICS.timer('NodesController.post')
|
||||||
@expose.expose(Node, body=Node, status_code=http_client.CREATED)
|
@expose.expose(Node, body=Node, status_code=http_client.CREATED)
|
||||||
def post(self, node):
|
def post(self, node):
|
||||||
"""Create a new node.
|
"""Create a new node.
|
||||||
@ -1254,6 +1275,7 @@ class NodesController(rest.RestController):
|
|||||||
pecan.response.location = link.build_url('nodes', new_node.uuid)
|
pecan.response.location = link.build_url('nodes', new_node.uuid)
|
||||||
return Node.convert_with_links(new_node)
|
return Node.convert_with_links(new_node)
|
||||||
|
|
||||||
|
@METRICS.timer('NodesController.patch')
|
||||||
@wsme.validate(types.uuid, [NodePatchType])
|
@wsme.validate(types.uuid, [NodePatchType])
|
||||||
@expose.expose(Node, types.uuid_or_name, body=[NodePatchType])
|
@expose.expose(Node, types.uuid_or_name, body=[NodePatchType])
|
||||||
def patch(self, node_ident, patch):
|
def patch(self, node_ident, patch):
|
||||||
@ -1316,6 +1338,7 @@ class NodesController(rest.RestController):
|
|||||||
|
|
||||||
return Node.convert_with_links(new_node)
|
return Node.convert_with_links(new_node)
|
||||||
|
|
||||||
|
@METRICS.timer('NodesController.delete')
|
||||||
@expose.expose(None, types.uuid_or_name,
|
@expose.expose(None, types.uuid_or_name,
|
||||||
status_code=http_client.NO_CONTENT)
|
status_code=http_client.NO_CONTENT)
|
||||||
def delete(self, node_ident):
|
def delete(self, node_ident):
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from ironic_lib import metrics_utils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import rest
|
from pecan import rest
|
||||||
@ -32,6 +33,8 @@ from ironic.common import exception
|
|||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
from ironic import objects
|
from ironic import objects
|
||||||
|
|
||||||
|
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
_DEFAULT_RETURN_FIELDS = ('uuid', 'address')
|
_DEFAULT_RETURN_FIELDS = ('uuid', 'address')
|
||||||
|
|
||||||
@ -263,6 +266,7 @@ class PortsController(rest.RestController):
|
|||||||
except exception.PortNotFound:
|
except exception.PortNotFound:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@METRICS.timer('PortsController.get_all')
|
||||||
@expose.expose(PortCollection, types.uuid_or_name, types.uuid,
|
@expose.expose(PortCollection, types.uuid_or_name, types.uuid,
|
||||||
types.macaddress, types.uuid, int, wtypes.text,
|
types.macaddress, types.uuid, int, wtypes.text,
|
||||||
wtypes.text, types.listtype)
|
wtypes.text, types.listtype)
|
||||||
@ -302,6 +306,7 @@ class PortsController(rest.RestController):
|
|||||||
limit, sort_key, sort_dir,
|
limit, sort_key, sort_dir,
|
||||||
fields=fields)
|
fields=fields)
|
||||||
|
|
||||||
|
@METRICS.timer('PortsController.detail')
|
||||||
@expose.expose(PortCollection, types.uuid_or_name, types.uuid,
|
@expose.expose(PortCollection, types.uuid_or_name, types.uuid,
|
||||||
types.macaddress, types.uuid, int, wtypes.text,
|
types.macaddress, types.uuid, int, wtypes.text,
|
||||||
wtypes.text)
|
wtypes.text)
|
||||||
@ -341,6 +346,7 @@ class PortsController(rest.RestController):
|
|||||||
limit, sort_key, sort_dir,
|
limit, sort_key, sort_dir,
|
||||||
resource_url)
|
resource_url)
|
||||||
|
|
||||||
|
@METRICS.timer('PortsController.get_one')
|
||||||
@expose.expose(Port, types.uuid, types.listtype)
|
@expose.expose(Port, types.uuid, types.listtype)
|
||||||
def get_one(self, port_uuid, fields=None):
|
def get_one(self, port_uuid, fields=None):
|
||||||
"""Retrieve information about the given port.
|
"""Retrieve information about the given port.
|
||||||
@ -357,6 +363,7 @@ class PortsController(rest.RestController):
|
|||||||
rpc_port = objects.Port.get_by_uuid(pecan.request.context, port_uuid)
|
rpc_port = objects.Port.get_by_uuid(pecan.request.context, port_uuid)
|
||||||
return Port.convert_with_links(rpc_port, fields=fields)
|
return Port.convert_with_links(rpc_port, fields=fields)
|
||||||
|
|
||||||
|
@METRICS.timer('PortsController.post')
|
||||||
@expose.expose(Port, body=Port, status_code=http_client.CREATED)
|
@expose.expose(Port, body=Port, status_code=http_client.CREATED)
|
||||||
def post(self, port):
|
def post(self, port):
|
||||||
"""Create a new port.
|
"""Create a new port.
|
||||||
@ -373,6 +380,7 @@ class PortsController(rest.RestController):
|
|||||||
pecan.response.location = link.build_url('ports', new_port.uuid)
|
pecan.response.location = link.build_url('ports', new_port.uuid)
|
||||||
return Port.convert_with_links(new_port)
|
return Port.convert_with_links(new_port)
|
||||||
|
|
||||||
|
@METRICS.timer('PortsController.patch')
|
||||||
@wsme.validate(types.uuid, [PortPatchType])
|
@wsme.validate(types.uuid, [PortPatchType])
|
||||||
@expose.expose(Port, types.uuid, body=[PortPatchType])
|
@expose.expose(Port, types.uuid, body=[PortPatchType])
|
||||||
def patch(self, port_uuid, patch):
|
def patch(self, port_uuid, patch):
|
||||||
@ -417,6 +425,7 @@ class PortsController(rest.RestController):
|
|||||||
|
|
||||||
return Port.convert_with_links(new_port)
|
return Port.convert_with_links(new_port)
|
||||||
|
|
||||||
|
@METRICS.timer('PortsController.delete')
|
||||||
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
|
@expose.expose(None, types.uuid, status_code=http_client.NO_CONTENT)
|
||||||
def delete(self, port_uuid):
|
def delete(self, port_uuid):
|
||||||
"""Delete a port.
|
"""Delete a port.
|
||||||
|
@ -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.
|
@ -13,7 +13,7 @@ paramiko>=2.0 # LGPLv2.1+
|
|||||||
python-neutronclient>=4.2.0 # Apache-2.0
|
python-neutronclient>=4.2.0 # Apache-2.0
|
||||||
python-glanceclient>=2.0.0 # Apache-2.0
|
python-glanceclient>=2.0.0 # Apache-2.0
|
||||||
python-keystoneclient!=1.8.0,!=2.1.0,>=1.7.0 # Apache-2.0
|
python-keystoneclient!=1.8.0,!=2.1.0,>=1.7.0 # Apache-2.0
|
||||||
ironic-lib>=1.3.0 # Apache-2.0
|
ironic-lib>=2.0.0 # Apache-2.0
|
||||||
python-swiftclient>=2.2.0 # Apache-2.0
|
python-swiftclient>=2.2.0 # Apache-2.0
|
||||||
pytz>=2013.6 # MIT
|
pytz>=2013.6 # MIT
|
||||||
stevedore>=1.10.0 # Apache-2.0
|
stevedore>=1.10.0 # Apache-2.0
|
||||||
|
@ -4,6 +4,8 @@ wrap_width = 62
|
|||||||
namespace = ironic
|
namespace = ironic
|
||||||
namespace = ironic_lib.disk_utils
|
namespace = ironic_lib.disk_utils
|
||||||
namespace = ironic_lib.disk_partitioner
|
namespace = ironic_lib.disk_partitioner
|
||||||
|
namespace = ironic_lib.metrics
|
||||||
|
namespace = ironic_lib.metrics_statsd
|
||||||
namespace = ironic_lib.utils
|
namespace = ironic_lib.utils
|
||||||
namespace = oslo.db
|
namespace = oslo.db
|
||||||
namespace = oslo.messaging
|
namespace = oslo.messaging
|
||||||
|
Loading…
Reference in New Issue
Block a user