Merge "Adds metrics collection support in Hyper-V"

This commit is contained in:
Jenkins 2013-09-02 22:05:26 +00:00 committed by Gerrit Code Review
commit 795155c743
5 changed files with 66 additions and 0 deletions

View File

@ -39,6 +39,12 @@
# local_network_vswitch = private # local_network_vswitch = private
# Example: local_network_vswitch = custom_vswitch # 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. # Sample Configurations.
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------

View File

@ -52,6 +52,13 @@ agent_opts = [
cfg.IntOpt('polling_interval', default=2, cfg.IntOpt('polling_interval', default=2,
help=_("The number of seconds the agent will wait between " help=_("The number of seconds the agent will wait between "
"polling for local device changes.")), "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: else:
LOG.error(_('Unsupported network type %s'), network_type) 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): def _port_unbound(self, port_id):
(net_uuid, map) = self._get_network_vswitch_map_by_port_id(port_id) (net_uuid, map) = self._get_network_vswitch_map_by_port_id(port_id)
if net_uuid not in self._network_vswitch_map: if net_uuid not in self._network_vswitch_map:

View File

@ -243,3 +243,7 @@ class HyperVUtils(object):
for switch_port in switch_ports: for switch_port in switch_ports:
if (switch_port.ElementName == port_id): if (switch_port.ElementName == port_id):
return switch_port 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"))

View File

@ -26,10 +26,18 @@ class HyperVUtilsV2(utils.HyperVUtils):
_ETHERNET_SWITCH_PORT = 'Msvm_EthernetSwitchPort' _ETHERNET_SWITCH_PORT = 'Msvm_EthernetSwitchPort'
_PORT_ALLOC_SET_DATA = 'Msvm_EthernetPortAllocationSettingData' _PORT_ALLOC_SET_DATA = 'Msvm_EthernetPortAllocationSettingData'
_PORT_VLAN_SET_DATA = 'Msvm_EthernetSwitchPortVlanSettingData' _PORT_VLAN_SET_DATA = 'Msvm_EthernetSwitchPortVlanSettingData'
_PORT_ALLOC_ACL_SET_DATA = 'Msvm_EthernetSwitchPortAclSettingData'
_LAN_ENDPOINT = 'Msvm_LANEndpoint' _LAN_ENDPOINT = 'Msvm_LANEndpoint'
_STATE_DISABLED = 3 _STATE_DISABLED = 3
_OPERATION_MODE_ACCESS = 1 _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' _wmi_namespace = '//./root/virtualization/v2'
def __init__(self): def __init__(self):
@ -159,3 +167,26 @@ class HyperVUtilsV2(utils.HyperVUtils):
def _get_first_item(self, obj): def _get_first_item(self, obj):
if obj: if obj:
return obj[0] 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)

View File

@ -213,3 +213,18 @@ class TestHyperVUtilsV2(base.BaseTestCase):
True) True)
self.assertEqual(ret_val, (mock_data, False)) 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)