File: //proc/self/root/usr/lib/python2.7/site-packages/salt/modules/win_ip.py
# -*- coding: utf-8 -*-
'''
The networking module for Windows based systems
'''
from __future__ import absolute_import, unicode_literals, print_function
# Import Python libs
import logging
import time
# Import Salt libs
import salt.utils.network
import salt.utils.platform
import salt.utils.validate.net
from salt.exceptions import (
CommandExecutionError,
SaltInvocationError
)
from salt.ext.six.moves import range
# Set up logging
log = logging.getLogger(__name__)
# Define the module's virtual name
__virtualname__ = 'ip'
def __virtual__():
'''
Confine this module to Windows systems
'''
if salt.utils.platform.is_windows():
return __virtualname__
return (False, "Module win_ip: module only works on Windows systems")
def _interface_configs():
'''
Return all interface configs
'''
cmd = ['netsh', 'interface', 'ip', 'show', 'config']
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
ret = {}
current_iface = None
current_ip_list = None
for line in lines:
line = line.strip()
if not line:
current_iface = None
current_ip_list = None
continue
if 'Configuration for interface' in line:
_, iface = line.rstrip('"').split('"', 1) # get iface name
current_iface = {}
ret[iface] = current_iface
continue
if ':' not in line:
if current_ip_list:
current_ip_list.append(line)
else:
log.warning('Cannot parse "%s"', line)
continue
key, val = line.split(':', 1)
key = key.strip()
val = val.strip()
lkey = key.lower()
if ('dns servers' in lkey) or ('wins servers' in lkey):
current_ip_list = []
current_iface[key] = current_ip_list
current_ip_list.append(val)
elif 'ip address' in lkey:
current_iface.setdefault('ip_addrs', []).append({key: val})
elif 'subnet prefix' in lkey:
subnet, _, netmask = val.split(' ', 2)
last_ip = current_iface['ip_addrs'][-1]
last_ip['Subnet'] = subnet.strip()
last_ip['Netmask'] = netmask.lstrip().rstrip(')')
else:
current_iface[key] = val
return ret
def raw_interface_configs():
'''
Return raw configs for all interfaces
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.raw_interface_configs
'''
cmd = ['netsh', 'interface', 'ip', 'show', 'config']
return __salt__['cmd.run'](cmd, python_shell=False)
def get_all_interfaces():
'''
Return configs for all interfaces
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.get_all_interfaces
'''
return _interface_configs()
def get_interface(iface):
'''
Return the configuration of a network interface
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.get_interface 'Local Area Connection'
'''
return _interface_configs().get(iface, {})
def is_enabled(iface):
'''
Returns ``True`` if interface is enabled, otherwise ``False``
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.is_enabled 'Local Area Connection #2'
'''
cmd = ['netsh', 'interface', 'show', 'interface', 'name={0}'.format(iface)]
iface_found = False
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
if 'Connect state:' in line:
iface_found = True
return line.split()[-1] == 'Connected'
if not iface_found:
raise CommandExecutionError(
'Interface \'{0}\' not found'.format(iface)
)
return False
def is_disabled(iface):
'''
Returns ``True`` if interface is disabled, otherwise ``False``
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.is_disabled 'Local Area Connection #2'
'''
return not is_enabled(iface)
def enable(iface):
'''
Enable an interface
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.enable 'Local Area Connection #2'
'''
if is_enabled(iface):
return True
cmd = ['netsh', 'interface', 'set', 'interface',
'name={0}'.format(iface),
'admin=ENABLED']
__salt__['cmd.run'](cmd, python_shell=False)
return is_enabled(iface)
def disable(iface):
'''
Disable an interface
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.disable 'Local Area Connection #2'
'''
if is_disabled(iface):
return True
cmd = ['netsh', 'interface', 'set', 'interface',
'name={0}'.format(iface),
'admin=DISABLED']
__salt__['cmd.run'](cmd, python_shell=False)
return is_disabled(iface)
def get_subnet_length(mask):
'''
Convenience function to convert the netmask to the CIDR subnet length
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.get_subnet_length 255.255.255.0
'''
if not salt.utils.validate.net.netmask(mask):
raise SaltInvocationError(
'\'{0}\' is not a valid netmask'.format(mask)
)
return salt.utils.network.get_net_size(mask)
def set_static_ip(iface, addr, gateway=None, append=False):
'''
Set static IP configuration on a Windows NIC
iface
The name of the interface to manage
addr
IP address with subnet length (ex. ``10.1.2.3/24``). The
:mod:`ip.get_subnet_length <salt.modules.win_ip.get_subnet_length>`
function can be used to calculate the subnet length from a netmask.
gateway : None
If specified, the default gateway will be set to this value.
append : False
If ``True``, this IP address will be added to the interface. Default is
``False``, which overrides any existing configuration for the interface
and sets ``addr`` as the only address on the interface.
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.set_static_ip 'Local Area Connection' 10.1.2.3/24 gateway=10.1.2.1
salt -G 'os_family:Windows' ip.set_static_ip 'Local Area Connection' 10.1.2.4/24 append=True
'''
def _find_addr(iface, addr, timeout=1):
ip, cidr = addr.rsplit('/', 1)
netmask = salt.utils.network.cidr_to_ipv4_netmask(cidr)
for idx in range(timeout):
for addrinfo in get_interface(iface).get('ip_addrs', []):
if addrinfo['IP Address'] == ip \
and addrinfo['Netmask'] == netmask:
return addrinfo
time.sleep(1)
return {}
if not salt.utils.validate.net.ipv4_addr(addr):
raise SaltInvocationError('Invalid address \'{0}\''.format(addr))
if gateway and not salt.utils.validate.net.ipv4_addr(addr):
raise SaltInvocationError(
'Invalid default gateway \'{0}\''.format(gateway)
)
if '/' not in addr:
addr += '/32'
if append and _find_addr(iface, addr):
raise CommandExecutionError(
'Address \'{0}\' already exists on interface '
'\'{1}\''.format(addr, iface)
)
cmd = ['netsh', 'interface', 'ip']
if append:
cmd.append('add')
else:
cmd.append('set')
cmd.extend(['address', 'name={0}'.format(iface)])
if not append:
cmd.append('source=static')
cmd.append('address={0}'.format(addr))
if gateway:
cmd.append('gateway={0}'.format(gateway))
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
raise CommandExecutionError(
'Unable to set IP address: {0}'.format(result['stderr'])
)
new_addr = _find_addr(iface, addr, timeout=10)
if not new_addr:
return {}
ret = {'Address Info': new_addr}
if gateway:
ret['Default Gateway'] = gateway
return ret
def set_dhcp_ip(iface):
'''
Set Windows NIC to get IP from DHCP
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.set_dhcp_ip 'Local Area Connection'
'''
cmd = ['netsh', 'interface', 'ip', 'set', 'address', iface, 'dhcp']
__salt__['cmd.run'](cmd, python_shell=False)
return {'Interface': iface, 'DHCP enabled': 'Yes'}
def set_static_dns(iface, *addrs):
'''
Set static DNS configuration on a Windows NIC
Args:
iface (str): The name of the interface to set
addrs (*):
One or more DNS servers to be added. To clear the list of DNS
servers pass an empty list (``[]``). If undefined or ``None`` no
changes will be made.
Returns:
dict: A dictionary containing the new DNS settings
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.set_static_dns 'Local Area Connection' '192.168.1.1'
salt -G 'os_family:Windows' ip.set_static_dns 'Local Area Connection' '192.168.1.252' '192.168.1.253'
'''
if addrs is () or str(addrs[0]).lower() == 'none':
return {'Interface': iface, 'DNS Server': 'No Changes'}
# Clear the list of DNS servers if [] is passed
if str(addrs[0]).lower() == '[]':
log.debug('Clearing list of DNS servers')
cmd = ['netsh', 'interface', 'ip', 'set', 'dns',
'name={0}'.format(iface),
'source=static',
'address=none']
__salt__['cmd.run'](cmd, python_shell=False)
return {'Interface': iface, 'DNS Server': []}
addr_index = 1
for addr in addrs:
if addr_index == 1:
cmd = ['netsh', 'interface', 'ip', 'set', 'dns',
'name={0}'.format(iface),
'source=static',
'address={0}'.format(addr),
'register=primary']
__salt__['cmd.run'](cmd, python_shell=False)
addr_index = addr_index + 1
else:
cmd = ['netsh', 'interface', 'ip', 'add', 'dns',
'name={0}'.format(iface),
'address={0}'.format(addr),
'index={0}'.format(addr_index)]
__salt__['cmd.run'](cmd, python_shell=False)
addr_index = addr_index + 1
return {'Interface': iface, 'DNS Server': addrs}
def set_dhcp_dns(iface):
'''
Set DNS source to DHCP on Windows
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.set_dhcp_dns 'Local Area Connection'
'''
cmd = ['netsh', 'interface', 'ip', 'set', 'dns', iface, 'dhcp']
__salt__['cmd.run'](cmd, python_shell=False)
return {'Interface': iface, 'DNS Server': 'DHCP'}
def set_dhcp_all(iface):
'''
Set both IP Address and DNS to DHCP
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.set_dhcp_all 'Local Area Connection'
'''
set_dhcp_ip(iface)
set_dhcp_dns(iface)
return {'Interface': iface, 'DNS Server': 'DHCP', 'DHCP enabled': 'Yes'}
def get_default_gateway():
'''
Set DNS source to DHCP on Windows
CLI Example:
.. code-block:: bash
salt -G 'os_family:Windows' ip.get_default_gateway
'''
try:
return next(iter(
x.split()[-1] for x in __salt__['cmd.run'](
['netsh', 'interface', 'ip', 'show', 'config'],
python_shell=False
).splitlines()
if 'Default Gateway:' in x
))
except StopIteration:
raise CommandExecutionError('Unable to find default gateway')