Adds metrics collection support in Hyper-V
Blueprint: hyper-v-metrics Hyper-V Server 2012 supports a new set of metrics API that can be used to provide switch port metrics data to external applications, e.g. Ceilometer. Metrics collection is disabled by default and can be enabled with a config option. Metrics are configured via ACLs applied by the Hyper-V plugin agent. Change-Id: Ife2a53db84936bae7c73b8c027022bbc5e89d48a
This commit is contained in:
parent
c137823c54
commit
21140e341a
@ -39,6 +39,12 @@
|
||||
# local_network_vswitch = private
|
||||
# Example: local_network_vswitch = custom_vswitch
|
||||
|
||||
# (BoolOpt) Enables metrics collections for switch ports by using Hyper-V's
|
||||
# metric APIs. Collected data can by retrieved by other apps and services,
|
||||
# e.g.: Ceilometer. Requires Hyper-V / Windows Server 2012 and above.
|
||||
#
|
||||
# enable_metrics_collection = False
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Sample Configurations.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
@ -52,6 +52,13 @@ agent_opts = [
|
||||
cfg.IntOpt('polling_interval', default=2,
|
||||
help=_("The number of seconds the agent will wait between "
|
||||
"polling for local device changes.")),
|
||||
cfg.BoolOpt('enable_metrics_collection',
|
||||
default=False,
|
||||
help=_('Enables metrics collections for switch ports by using '
|
||||
'Hyper-V\'s metric APIs. Collected data can by '
|
||||
'retrieved by other apps and services, e.g.: '
|
||||
'Ceilometer. Requires Hyper-V / Windows Server 2012 '
|
||||
'and above'))
|
||||
]
|
||||
|
||||
|
||||
@ -210,6 +217,9 @@ class HyperVNeutronAgent(object):
|
||||
else:
|
||||
LOG.error(_('Unsupported network type %s'), network_type)
|
||||
|
||||
if CONF.AGENT.enable_metrics_collection:
|
||||
self._utils.enable_port_metrics_collection(port_id)
|
||||
|
||||
def _port_unbound(self, port_id):
|
||||
(net_uuid, map) = self._get_network_vswitch_map_by_port_id(port_id)
|
||||
if net_uuid not in self._network_vswitch_map:
|
||||
|
@ -243,3 +243,7 @@ class HyperVUtils(object):
|
||||
for switch_port in switch_ports:
|
||||
if (switch_port.ElementName == port_id):
|
||||
return switch_port
|
||||
|
||||
def enable_port_metrics_collection(self, switch_port_name):
|
||||
raise NotImplementedError(_("Metrics collection is not supported on "
|
||||
"this version of Hyper-V"))
|
||||
|
@ -26,10 +26,18 @@ class HyperVUtilsV2(utils.HyperVUtils):
|
||||
_ETHERNET_SWITCH_PORT = 'Msvm_EthernetSwitchPort'
|
||||
_PORT_ALLOC_SET_DATA = 'Msvm_EthernetPortAllocationSettingData'
|
||||
_PORT_VLAN_SET_DATA = 'Msvm_EthernetSwitchPortVlanSettingData'
|
||||
_PORT_ALLOC_ACL_SET_DATA = 'Msvm_EthernetSwitchPortAclSettingData'
|
||||
_LAN_ENDPOINT = 'Msvm_LANEndpoint'
|
||||
_STATE_DISABLED = 3
|
||||
_OPERATION_MODE_ACCESS = 1
|
||||
|
||||
_ACL_DIR_IN = 1
|
||||
_ACL_DIR_OUT = 2
|
||||
_ACL_TYPE_IPV4 = 2
|
||||
_ACL_TYPE_IPV6 = 3
|
||||
_ACL_ACTION_METER = 3
|
||||
_ACL_APPLICABILITY_LOCAL = 1
|
||||
|
||||
_wmi_namespace = '//./root/virtualization/v2'
|
||||
|
||||
def __init__(self):
|
||||
@ -159,3 +167,26 @@ class HyperVUtilsV2(utils.HyperVUtils):
|
||||
def _get_first_item(self, obj):
|
||||
if obj:
|
||||
return obj[0]
|
||||
|
||||
def enable_port_metrics_collection(self, switch_port_name):
|
||||
port, found = self._get_switch_port_allocation(switch_port_name, False)
|
||||
if not found:
|
||||
return
|
||||
|
||||
# Add the ACLs only if they don't already exist
|
||||
acls = port.associators(wmi_result_class=self._PORT_ALLOC_ACL_SET_DATA)
|
||||
for acl_type in [self._ACL_TYPE_IPV4, self._ACL_TYPE_IPV6]:
|
||||
for acl_dir in [self._ACL_DIR_IN, self._ACL_DIR_OUT]:
|
||||
acls = [v for v in acls
|
||||
if v.Action == self._ACL_ACTION_METER and
|
||||
v.Applicability == self._ACL_APPLICABILITY_LOCAL and
|
||||
v.Direction == acl_dir and
|
||||
v.AclType == acl_type]
|
||||
if not acls:
|
||||
acl = self._get_default_setting_data(
|
||||
self._PORT_ALLOC_ACL_SET_DATA)
|
||||
acl.AclType = acl_type
|
||||
acl.Direction = acl_dir
|
||||
acl.Action = self._ACL_ACTION_METER
|
||||
acl.Applicability = self._ACL_APPLICABILITY_LOCAL
|
||||
self._add_virt_feature(port, acl)
|
||||
|
@ -213,3 +213,18 @@ class TestHyperVUtilsV2(base.BaseTestCase):
|
||||
True)
|
||||
|
||||
self.assertEqual(ret_val, (mock_data, False))
|
||||
|
||||
def test_enable_port_metrics_collection(self):
|
||||
mock_port = mock.MagicMock()
|
||||
self._utils._get_switch_port_allocation = mock.MagicMock(return_value=(
|
||||
mock_port, True))
|
||||
|
||||
mock_acl = mock.MagicMock()
|
||||
self._utils._get_default_setting_data = mock.MagicMock(
|
||||
return_value=mock_acl)
|
||||
self._utils._add_virt_feature = mock.MagicMock()
|
||||
|
||||
self._utils.enable_port_metrics_collection(self._FAKE_PORT_NAME)
|
||||
|
||||
self.assertEqual(4, len(self._utils._add_virt_feature.mock_calls))
|
||||
self._utils._add_virt_feature.assert_called_with(mock_port, mock_acl)
|
||||
|
Loading…
Reference in New Issue
Block a user