From b62c51c5f5ee32dcf090f4fe8fc6a941792a11c0 Mon Sep 17 00:00:00 2001 From: Alessandro Pilotti Date: Wed, 11 Jun 2014 20:39:51 +0300 Subject: [PATCH] Adds Windows MTU plugin --- cloudbaseinit/osutils/windows.py | 46 +++++++++++++++++++---- cloudbaseinit/plugins/factory.py | 1 + cloudbaseinit/plugins/windows/mtu.py | 55 ++++++++++++++++++++++++++++ cloudbaseinit/utils/dhcp.py | 1 + 4 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 cloudbaseinit/plugins/windows/mtu.py diff --git a/cloudbaseinit/osutils/windows.py b/cloudbaseinit/osutils/windows.py index 07754786..b7937ca4 100644 --- a/cloudbaseinit/osutils/windows.py +++ b/cloudbaseinit/osutils/windows.py @@ -474,11 +474,7 @@ class WindowsUtils(base.BaseOSUtils): return dhcp_hosts def set_ntp_client_config(self, ntp_host): - if self.check_sysnative_dir_exists(): - base_dir = self.get_sysnative_dir() - else: - base_dir = self.get_system32_dir() - + base_dir = self._get_system_dir() w32tm_path = os.path.join(base_dir, "w32tm.exe") args = [w32tm_path, '/config', '/manualpeerlist:%s' % ntp_host, @@ -490,6 +486,38 @@ class WindowsUtils(base.BaseOSUtils): 'Output: %(out)s\nError: %(err)s' % {'out': out, 'err': err}) + def set_network_adapter_mtu(self, mac_address, mtu): + if not self.check_os_version(6, 0): + raise Exception('Setting the MTU is currently not supported on ' + 'Windows XP and Windows Server 2003') + + conn = wmi.WMI(moniker='//./root/cimv2') + net_cfg_list = conn.Win32_NetworkAdapterConfiguration( + MACAddress=mac_address) + + if not net_cfg_list: + raise Exception('Network interface with MAC address "%s" ' + 'not found' % mac_address) + else: + net_cfg = net_cfg_list[0] + + LOG.debug('Setting MTU for interface "%(mac_address)s" with ' + 'value "%(mtu)s"' % + {'mac_address': mac_address, 'mtu': mtu}) + + base_dir = self._get_system_dir() + netsh_path = os.path.join(base_dir, 'netsh.exe') + + args = [netsh_path, "interface", "ipv4", "set", "subinterface", + str(net_cfg.InterfaceIndex), "mtu=%s" % mtu, + "store=persistent"] + (out, err, ret_val) = self.execute_process(args, False) + if ret_val: + raise Exception('Setting MTU for interface ' + '"%(mac_address)s" with ' + 'value "%(mtu)s" failed' % + {'mac_address': mac_address, 'mtu': mtu}) + def set_static_network_config(self, adapter_name, address, netmask, broadcast, gateway, dnsnameservers): conn = wmi.WMI(moniker='//./root/cimv2') @@ -901,12 +929,14 @@ class WindowsUtils(base.BaseOSUtils): 'you have KB942589 installed') return sysnative_dir_exists - def execute_powershell_script(self, script_path, sysnative=True): + def _get_system_dir(self, sysnative=True): if sysnative and self.check_sysnative_dir_exists(): - base_dir = self.get_sysnative_dir() + return self.get_sysnative_dir() else: - base_dir = self.get_system32_dir() + return self.get_system32_dir() + def execute_powershell_script(self, script_path, sysnative=True): + base_dir = self._get_system_dir(sysnative) powershell_path = os.path.join(base_dir, 'WindowsPowerShell\\v1.0\\' 'powershell.exe') diff --git a/cloudbaseinit/plugins/factory.py b/cloudbaseinit/plugins/factory.py index fa5d1886..758a7ca7 100644 --- a/cloudbaseinit/plugins/factory.py +++ b/cloudbaseinit/plugins/factory.py @@ -22,6 +22,7 @@ opts = [ cfg.ListOpt( 'plugins', default=[ + 'cloudbaseinit.plugins.windows.mtu.MTUPlugin', 'cloudbaseinit.plugins.windows.ntpclient.NTPClientPlugin', 'cloudbaseinit.plugins.windows.sethostname.SetHostNamePlugin', 'cloudbaseinit.plugins.windows.createuser.CreateUserPlugin', diff --git a/cloudbaseinit/plugins/windows/mtu.py b/cloudbaseinit/plugins/windows/mtu.py new file mode 100644 index 00000000..e2f25b15 --- /dev/null +++ b/cloudbaseinit/plugins/windows/mtu.py @@ -0,0 +1,55 @@ +# Copyright 2014 Cloudbase Solutions Srl +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import struct + +from oslo.config import cfg + +from cloudbaseinit.openstack.common import log as logging +from cloudbaseinit.osutils import factory as osutils_factory +from cloudbaseinit.plugins import base +from cloudbaseinit.utils import dhcp + +opts = [ + cfg.BoolOpt('mtu_use_dhcp_config', default=True, + help='Configures the network interfaces MTU based on the ' + 'values provided via DHCP'), +] + +CONF = cfg.CONF +CONF.register_opts(opts) + +LOG = logging.getLogger(__name__) + + +class MTUPlugin(base.BasePlugin): + + def execute(self, service, shared_data): + if CONF.mtu_use_dhcp_config: + osutils = osutils_factory.get_os_utils() + dhcp_hosts = osutils.get_dhcp_hosts_in_use() + + for (mac_address, dhcp_host) in dhcp_hosts: + options_data = dhcp.get_dhcp_options(dhcp_host, + [dhcp.OPTION_MTU]) + if options_data: + mtu_option_data = options_data.get(dhcp.OPTION_MTU) + if mtu_option_data: + mtu = struct.unpack('!H', mtu_option_data)[0] + osutils.set_network_adapter_mtu(mac_address, mtu) + else: + LOG.debug('Could not obtain the MTU configuration ' + 'via DHCP for interface "%s"' % mac_address) + + return (base.PLUGIN_EXECUTE_ON_NEXT_BOOT, False) diff --git a/cloudbaseinit/utils/dhcp.py b/cloudbaseinit/utils/dhcp.py index 90de3a91..74542377 100644 --- a/cloudbaseinit/utils/dhcp.py +++ b/cloudbaseinit/utils/dhcp.py @@ -21,6 +21,7 @@ import struct _DHCP_COOKIE = b'\x63\x82\x53\x63' _OPTION_END = b'\xff' +OPTION_MTU = 26 OPTION_NTP_SERVERS = 42