# 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.
#-----------------------------------------------------------------------------
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'))
]
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:
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"))
_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):
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)
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)