Merge pull request #48400 from alexvasiu/dev/avasiu/older_nilrt_ip

nilrt_ip: network module for older nilrt
This commit is contained in:
Nicole Thomas 2018-07-12 12:59:05 -04:00 committed by GitHub
commit 570f76d429
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,6 +9,7 @@ from __future__ import absolute_import, print_function, unicode_literals
import logging
import time
import os
import re
# Import salt libs
import salt.exceptions
@ -16,23 +17,30 @@ import salt.utils.files
import salt.utils.validate.net
# Import 3rd-party libs
# pylint: disable=import-error,redefined-builtin,no-name-in-module
from salt.ext.six.moves import map, range, configparser
from salt.ext import six
from salt.ext.six.moves import configparser
# pylint: enable=import-error,redefined-builtin,no-name-in-module
try:
import pyconnman
HAS_PYCONNMAN = True
except ImportError:
HAS_PYCONNMAN = False
pyconnman = None
try:
import dbus
HAS_DBUS = True
except ImportError:
HAS_DBUS = False
dbus = None
try:
import pyiface
HAS_PYIFACE = True
except ImportError:
HAS_PYIFACE = False
pyiface = None
try:
from requests.structures import CaseInsensitiveDict
except ImportError:
CaseInsensitiveDict = None
log = logging.getLogger(__name__)
@ -41,69 +49,79 @@ __virtualname__ = 'ip'
SERVICE_PATH = '/net/connman/service/'
INTERFACES_CONFIG = '/var/lib/connman/interfaces.config'
NIRTCFG_PATH = '/usr/local/natinst/bin/nirtcfg'
INI_FILE = '/etc/natinst/share/ni-rt.ini'
_CONFIG_TRUE = ['yes', 'on', 'true', '1', True]
IFF_LOOPBACK = 0x8
IFF_RUNNING = 0x40
def _assume_condition(condition, err):
'''
Raise an exception if the condition is false
'''
if not condition:
raise RuntimeError(err)
def __virtual__():
'''
Confine this module to NI Linux Real-Time based distros
'''
if not HAS_PYCONNMAN:
return False, 'The python package pyconnman is not installed'
if not HAS_DBUS:
return False, 'The python DBus package is not installed'
if not HAS_PYIFACE:
return False, 'The python pyiface package is not installed'
if __grains__['os_family'] == 'NILinuxRT':
try:
state = _get_state
if state == 'offline':
return False, 'Connmand is not running'
except Exception as exc:
return False, six.text_type(exc)
return __virtualname__
return False, 'The nilrt_ip module could not be loaded: unsupported OS family'
try:
msg = 'The nilrt_ip module could not be loaded: unsupported OS family'
_assume_condition(__grains__['os_family'] == 'NILinuxRT', msg)
_assume_condition(CaseInsensitiveDict, 'The python package request is not installed')
_assume_condition(pyiface, 'The python pyiface package is not installed')
if __grains__['lsb_distrib_id'] != 'nilrt':
_assume_condition(pyconnman, 'The python package pyconnman is not installed')
_assume_condition(dbus, 'The python DBus package is not installed')
_assume_condition(_get_state() != 'offline', 'Connman is not running')
except RuntimeError as exc:
return False, str(exc)
return __virtualname__
def _get_state():
'''
Returns the state of connman
'''
try:
state = pyconnman.ConnManager().get_property('State')
except Exception as exc:
return pyconnman.ConnManager().get_property('State')
except KeyError:
return 'offline'
except dbus.DBusException as exc:
raise salt.exceptions.CommandExecutionError('Connman daemon error: {0}'.format(exc))
return state
def _get_technologies():
strTech = ''
'''
Returns the technologies of connman
'''
tech = ''
technologies = pyconnman.ConnManager().get_technologies()
for path, params in technologies:
strTech += '{0}\n\tName = {1}\n\tType = {2}\n\tPowered = {3}\n\tConnected = {4}\n'.format(
tech += '{0}\n\tName = {1}\n\tType = {2}\n\tPowered = {3}\n\tConnected = {4}\n'.format(
path, params['Name'], params['Type'], params['Powered'] == 1, params['Connected'] == 1)
return strTech
def _add_path(service):
return '{0}{1}'.format(SERVICE_PATH, service)
return tech
def _get_services():
'''
Returns a list with all connman services.
Returns a list with all connman services
'''
serviceList = []
serv = []
services = pyconnman.ConnManager().get_services()
for path, params in services:
serviceList.append(six.text_type(path[len(SERVICE_PATH):]))
return serviceList
for path, _ in services:
serv.append(six.text_type(path[len(SERVICE_PATH):]))
return serv
def _connected(service):
'''
Verify if a connman service is connected
'''
state = pyconnman.ConnService(_add_path(service)).get_property('State')
state = pyconnman.ConnService(os.path.join(SERVICE_PATH, service)).get_property('State')
return state == 'online' or state == 'ready'
@ -117,14 +135,14 @@ def _space_delimited_list(value):
valid = True
else:
_value = value.split()
if _value == []:
if not _value:
raise ValueError
valid = True
except AttributeError:
errmsg = '{0} is not a valid list.\n'.format(value)
except ValueError:
errmsg = '{0} is not a valid list.\n'.format(value)
return (valid, errmsg)
return valid, errmsg
def _validate_ipv4(value):
@ -133,14 +151,14 @@ def _validate_ipv4(value):
'''
if len(value) == 3:
if not salt.utils.validate.net.ipv4_addr(value[0].strip()):
return (False, 'Invalid ip address: {0} for ipv4 option'.format(value[0]))
return False, 'Invalid ip address: {0} for ipv4 option'.format(value[0])
if not salt.utils.validate.net.netmask(value[1].strip()):
return (False, 'Invalid netmask: {0} for ipv4 option'.format(value[1]))
return False, 'Invalid netmask: {0} for ipv4 option'.format(value[1])
if not salt.utils.validate.net.ipv4_addr(value[2].strip()):
return (False, 'Invalid gateway: {0} for ipv4 option'.format(value[2]))
return False, 'Invalid gateway: {0} for ipv4 option'.format(value[2])
else:
return (False, 'Invalid value: {0} for ipv4 option'.format(value))
return (True, '')
return False, 'Invalid value: {0} for ipv4 option'.format(value)
return True, ''
def _interface_to_service(iface):
@ -148,7 +166,7 @@ def _interface_to_service(iface):
returns the coresponding service to given interface if exists, otherwise return None
'''
for _service in _get_services():
service_info = pyconnman.ConnService(_add_path(_service))
service_info = pyconnman.ConnService(os.path.join(SERVICE_PATH, _service))
if service_info.get_property('Ethernet')['Interface'] == iface:
return _service
return None
@ -158,7 +176,7 @@ def _get_service_info(service):
'''
return details about given connman service
'''
service_info = pyconnman.ConnService(_add_path(service))
service_info = pyconnman.ConnService(os.path.join(SERVICE_PATH, service))
data = {
'label': service,
'wireless': service_info.get_property('Type') == 'wifi',
@ -175,31 +193,31 @@ def _get_service_info(service):
ipv4 = 'IPv4'
if service_info.get_property('IPv4')['Method'] == 'manual':
ipv4 += '.Configuration'
ipv4Info = service_info.get_property(ipv4)
ipv4_info = service_info.get_property(ipv4)
for info in ['Method', 'Address', 'Netmask', 'Gateway']:
try:
value = ipv4Info[info]
if info == 'Method':
info = 'requestmode'
if value == 'dhcp':
value = 'dhcp_linklocal'
elif value in ('manual', 'fixed'):
value = 'static'
data['ipv4'][info.lower()] = six.text_type(value)
except Exception as exc:
value = ipv4_info.get(info)
if value is None:
log.warning('Unable to get IPv4 %s for service %s\n', info, service)
continue
if info == 'Method':
info = 'requestmode'
if value == 'dhcp':
value = 'dhcp_linklocal'
elif value in ('manual', 'fixed'):
value = 'static'
data['ipv4'][info.lower()] = six.text_type(value)
ipv6Info = service_info.get_property('IPv6')
ipv6_info = service_info.get_property('IPv6')
for info in ['Address', 'Prefix', 'Gateway']:
try:
value = ipv6Info[info]
data['ipv6'][info.lower()] = [six.text_type(value)]
except Exception as exc:
value = ipv6_info.get(info)
if value is None:
log.warning('Unable to get IPv6 %s for service %s\n', info, service)
continue
data['ipv6'][info.lower()] = [six.text_type(value)]
nameservers = []
for x in service_info.get_property('Nameservers'):
nameservers.append(six.text_type(x))
for nameserver_prop in service_info.get_property('Nameservers'):
nameservers.append(six.text_type(nameserver_prop))
data['ipv4']['dns'] = nameservers
else:
data['up'] = False
@ -212,23 +230,58 @@ def _get_service_info(service):
return data
def _dict_to_string(dictionary):
def _get_dns_info():
'''
converts a dictionary object into a list of strings
return dns list
'''
ret = ''
for key, val in sorted(dictionary.items()):
if isinstance(val, dict):
for line in _dict_to_string(val):
ret += six.text_type(key) + '-' + line + '\n'
elif isinstance(val, list):
stringList = ''
for item in val:
stringList += six.text_type(item) + ' '
ret += six.text_type(key) + ': ' + stringList +'\n'
dns_list = []
try:
with salt.utils.files.fopen('/etc/resolv.conf', 'r+') as dns_info:
lines = dns_info.readlines()
for line in lines:
if 'nameserver' in line:
dns = line.split()[1].strip()
if dns not in dns_list:
dns_list.append(dns)
except IOError:
log.warning('Could not get domain\n')
return dns_list
def _remove_quotes(value):
'''
Remove leading and trailing double quotes if they exist.
'''
# nirtcfg writes values with quotes
if len(value) > 1 and value[0] == value[-1] == '\"':
value = value[1:-1]
return value
def _get_requestmode_info(interface):
'''
return requestmode for given interface
'''
with salt.utils.files.fopen(INI_FILE, 'r') as config_file:
config_parser = configparser.RawConfigParser(dict_type=CaseInsensitiveDict)
config_parser.read_file(config_file)
link_local_enabled = '' if not config_parser.has_option(interface, 'linklocalenabled') else \
int(_remove_quotes(config_parser.get(interface, 'linklocalenabled')))
dhcp_enabled = '' if not config_parser.has_option(interface, 'dhcpenabled') else \
int(_remove_quotes(config_parser.get(interface, 'dhcpenabled')))
if dhcp_enabled == 1:
return 'dhcp_linklocal' if link_local_enabled == 1 else 'dhcp_only'
else:
ret += six.text_type(key) + ': ' + six.text_type(val) +'\n'
return ret.splitlines()
if link_local_enabled == 1:
return 'linklocal_only'
if link_local_enabled == 0:
return 'static'
# some versions of nirtcfg don't set the dhcpenabled/linklocalenabled variables
# when selecting "DHCP or Link Local" from MAX, so return it by default to avoid
# having the requestmode "None" because none of the conditions above matched.
return 'dhcp_linklocal'
def _get_static_info(interface):
@ -265,6 +318,61 @@ def _get_static_info(interface):
return data
def _get_interface_info(interface):
'''
return details about given interface
'''
data = {
'label': interface.name,
'connectionid': interface.name,
'up': False,
'ipv4': {
'supportedrequestmodes': ['dhcp_linklocal', 'dhcp_only', 'linklocal_only', 'static'],
'requestmode': _get_requestmode_info(interface.name)
},
'hwaddr': interface.hwaddr[:-1]
}
if interface.flags & IFF_RUNNING != 0:
data['up'] = True
data['ipv4']['address'] = interface.sockaddrToStr(interface.addr)
data['ipv4']['netmask'] = interface.sockaddrToStr(interface.netmask)
data['ipv4']['gateway'] = '0.0.0.0'
data['ipv4']['dns'] = _get_dns_info()
elif data['ipv4']['requestmode'] == 'static':
with salt.utils.files.fopen(INI_FILE, 'r') as config_file:
config_parser = configparser.RawConfigParser(dict_type=CaseInsensitiveDict)
config_parser.read_file(config_file)
data['ipv4']['address'] = _remove_quotes(config_parser.get(interface.name, 'IP_Address'))
data['ipv4']['netmask'] = _remove_quotes(config_parser.get(interface.name, 'Subnet_Mask'))
data['ipv4']['gateway'] = _remove_quotes(config_parser.get(interface.name, 'Gateway'))
data['ipv4']['dns'] = [_remove_quotes(config_parser.get(interface.name, 'DNS_Address'))]
with salt.utils.files.fopen('/proc/net/route', 'r') as route_file:
pattern = re.compile(r'^{interface}\t[0]{{8}}\t([0-9A-Z]{{8}})'.format(interface=interface.name), re.MULTILINE)
match = pattern.search(route_file.read())
iface_gateway_hex = None if not match else match.group(1)
if iface_gateway_hex is not None and len(iface_gateway_hex) == 8:
data['ipv4']['gateway'] = '.'.join([str(int(iface_gateway_hex[i:i+2], 16)) for i in range(6, -1, -2)])
return data
def _dict_to_string(dictionary):
'''
converts a dictionary object into a list of strings
'''
ret = ''
for key, val in sorted(dictionary.items()):
if isinstance(val, dict):
for line in _dict_to_string(val):
ret += six.text_type(key) + '-' + line + '\n'
elif isinstance(val, list):
text = ' '.join([six.text_type(item) for item in val])
ret += six.text_type(key) + ': ' + text + '\n'
else:
ret += six.text_type(key) + ': ' + six.text_type(val) + '\n'
return ret.splitlines()
def _get_info(interface):
'''
Return information about an interface even if it's not associated with a service.
@ -281,7 +389,7 @@ def get_interfaces_details():
'''
Get details about all the interfaces on the minion
:return: information about all connmans interfaces
:return: information about all interfaces omitting loopback
:rtype: dictionary
CLI Example:
@ -290,16 +398,13 @@ def get_interfaces_details():
salt '*' ip.get_interfaces_details
'''
interfaces = []
for interface in pyiface.getIfaces():
if interface.flags & IFF_LOOPBACK == 0:
interfaces.append(_get_info(interface))
interfaceList = {'interfaces': interfaces}
return interfaceList
_interfaces = [interface for interface in pyiface.getIfaces() if interface.flags & IFF_LOOPBACK == 0]
if __grains__['lsb_distrib_id'] == 'nilrt':
return {'interfaces': list(map(_get_interface_info, _interfaces))}
return {'interfaces': list(map(_get_info, _interfaces))}
def up(interface, iface_type=None):
def up(interface, iface_type=None): # pylint: disable=invalid-name,unused-argument
'''
Enable the specified interface
@ -313,15 +418,21 @@ def up(interface, iface_type=None):
salt '*' ip.up interface-label
'''
if __grains__['lsb_distrib_id'] == 'nilrt':
out = __salt__['cmd.run_all']('ip link set {0} up'.format(interface))
if out['retcode'] != 0:
msg = 'Couldn\'t enable interface {0}. Error: {1}'.format(interface, out['stderr'])
raise salt.exceptions.CommandExecutionError(msg)
return True
service = _interface_to_service(interface)
if not service:
raise salt.exceptions.CommandExecutionError('Invalid interface name: {0}'.format(interface))
if not _connected(service):
service = pyconnman.ConnService(_add_path(service))
service = pyconnman.ConnService(os.path.join(SERVICE_PATH, service))
try:
state = service.connect()
return state is None
except Exception as exc:
except Exception:
raise salt.exceptions.CommandExecutionError('Couldn\'t enable service: {0}\n'.format(service))
return True
@ -343,7 +454,7 @@ def enable(interface):
return up(interface)
def down(interface, iface_type=None):
def down(interface, iface_type=None): # pylint: disable=unused-argument
'''
Disable the specified interface
@ -357,15 +468,21 @@ def down(interface, iface_type=None):
salt '*' ip.down interface-label
'''
if __grains__['lsb_distrib_id'] == 'nilrt':
out = __salt__['cmd.run_all']('ip link set {0} down'.format(interface))
if out['retcode'] != 0:
msg = 'Couldn\'t disable interface {0}. Error: {1}'.format(interface, out['stderr'])
raise salt.exceptions.CommandExecutionError(msg)
return True
service = _interface_to_service(interface)
if not service:
raise salt.exceptions.CommandExecutionError('Invalid interface name: {0}'.format(interface))
if _connected(service):
service = pyconnman.ConnService(_add_path(service))
service = pyconnman.ConnService(os.path.join(SERVICE_PATH, service))
try:
state = service.disconnect()
return state is None
except Exception as exc:
except Exception:
raise salt.exceptions.CommandExecutionError('Couldn\'t disable service: {0}\n'.format(service))
return True
@ -387,6 +504,17 @@ def disable(interface):
return down(interface)
def _persist_config(section, token, value):
'''
Helper function to persist a configuration in the ini file
'''
cmd = NIRTCFG_PATH
cmd += ' --set section={0},token=\'{1}\',value=\'{2}\''.format(section, token, value)
if __salt__['cmd.run_all'](cmd)['retcode'] != 0:
exc_msg = 'Error: could not set {} to {} for {}\n'.format(token, value, section)
raise salt.exceptions.CommandExecutionError(exc_msg)
def set_dhcp_linklocal_all(interface):
'''
Configure specified adapter to use DHCP with linklocal fallback
@ -401,10 +529,16 @@ def set_dhcp_linklocal_all(interface):
salt '*' ip.set_dhcp_linklocal_all interface-label
'''
if __grains__['lsb_distrib_id'] == 'nilrt':
_persist_config(interface, 'dhcpenabled', '1')
_persist_config(interface, 'linklocalenabled', '1')
disable(interface)
enable(interface)
return True
service = _interface_to_service(interface)
if not service:
raise salt.exceptions.CommandExecutionError('Invalid interface name: {0}'.format(interface))
service = pyconnman.ConnService(_add_path(service))
service = pyconnman.ConnService(os.path.join(SERVICE_PATH, service))
ipv4 = service.get_property('IPv4.Configuration')
ipv4['Method'] = dbus.String('dhcp', variant_level=1)
ipv4['Address'] = dbus.String('', variant_level=1)
@ -414,7 +548,54 @@ def set_dhcp_linklocal_all(interface):
service.set_property('IPv4.Configuration', ipv4)
service.set_property('Nameservers.Configuration', ['']) # reset nameservers list
except Exception as exc:
raise salt.exceptions.CommandExecutionError('Couldn\'t set dhcp linklocal for service: {0}\nError: {1}\n'.format(service, exc))
exc_msg = 'Couldn\'t set dhcp linklocal for service: {0}\nError: {1}\n'.format(service, exc)
raise salt.exceptions.CommandExecutionError(exc_msg)
return True
def set_dhcp_only_all(interface):
'''
Configure specified adapter to use DHCP only
:param str interface: interface label
:return: True if the settings ware applied, otherwise an exception will be thrown.
:rtype: bool
CLI Example:
.. code-block:: bash
salt '*' ip.dhcp_only_all interface-label
'''
if not __grains__['lsb_distrib_id'] == 'nilrt':
raise salt.exceptions.CommandExecutionError('Not supported in this version')
_persist_config(interface, 'dhcpenabled', '1')
_persist_config(interface, 'linklocalenabled', '0')
disable(interface)
enable(interface)
return True
def set_linklocal_only_all(interface):
'''
Configure specified adapter to use linklocal only
:param str interface: interface label
:return: True if the settings ware applied, otherwise an exception will be thrown.
:rtype: bool
CLI Example:
.. code-block:: bash
salt '*' ip.linklocal_only_all interface-label
'''
if not __grains__['lsb_distrib_id'] == 'nilrt':
raise salt.exceptions.CommandExecutionError('Not supported in this version')
_persist_config(interface, 'dhcpenabled', '0')
_persist_config(interface, 'linklocalenabled', '1')
disable(interface)
enable(interface)
return True
@ -478,25 +659,32 @@ def set_static_all(interface, address, netmask, gateway, nameservers):
salt '*' ip.set_static_all interface-label address netmask gateway nameservers
'''
service = _interface_to_service(interface)
if not service:
raise salt.exceptions.CommandExecutionError('Invalid interface name: {0}'.format(interface))
validate, msg = _validate_ipv4([address, netmask, gateway])
if not validate:
raise salt.exceptions.CommandExecutionError(msg)
if nameservers:
validate, msg = _space_delimited_list(nameservers)
if not validate:
raise salt.exceptions.CommandExecutionError(msg)
if not isinstance(nameservers, list):
nameservers = nameservers.split(' ')
validate, msg = _space_delimited_list(nameservers)
if not validate:
raise salt.exceptions.CommandExecutionError(msg)
if not isinstance(nameservers, list):
nameservers = nameservers.split(' ')
if __grains__['lsb_distrib_id'] == 'nilrt':
_persist_config(interface, 'dhcpenabled', '0')
_persist_config(interface, 'linklocalenabled', '0')
_persist_config(interface, 'IP_Address', address)
_persist_config(interface, 'Subnet_Mask', netmask)
_persist_config(interface, 'Gateway', gateway)
if nameservers:
_persist_config(interface, 'DNS_Address', nameservers[0])
disable(interface)
enable(interface)
return True
service = _interface_to_service(interface)
if not service:
if interface in pyiface.getIfaces():
return _configure_static_interface(interface, **{'ip': address, 'dns': ','.join(nameservers),
'netmask': netmask, 'gateway': gateway})
raise salt.exceptions.CommandExecutionError('Invalid interface name: {0}'.format(interface))
service = pyconnman.ConnService(_add_path(service))
service = pyconnman.ConnService(os.path.join(SERVICE_PATH, service))
ipv4 = service.get_property('IPv4.Configuration')
ipv4['Method'] = dbus.String('manual', variant_level=1)
ipv4['Address'] = dbus.String('{0}'.format(address), variant_level=1)
@ -504,10 +692,10 @@ def set_static_all(interface, address, netmask, gateway, nameservers):
ipv4['Gateway'] = dbus.String('{0}'.format(gateway), variant_level=1)
try:
service.set_property('IPv4.Configuration', ipv4)
if nameservers:
service.set_property('Nameservers.Configuration', [dbus.String('{0}'.format(d)) for d in nameservers])
service.set_property('Nameservers.Configuration', [dbus.String('{0}'.format(d)) for d in nameservers])
except Exception as exc:
raise salt.exceptions.CommandExecutionError('Couldn\'t set manual settings for service: {0}\nError: {1}\n'.format(service, exc))
exc_msg = 'Couldn\'t set manual settings for service: {0}\nError: {1}\n'.format(service, exc)
raise salt.exceptions.CommandExecutionError(exc_msg)
return True
@ -528,7 +716,7 @@ def get_interface(iface):
return None
def build_interface(iface, iface_type, enable, **settings):
def build_interface(iface, iface_type, enabled, **settings):
'''
Build an interface script for a network interface.
@ -538,13 +726,16 @@ def build_interface(iface, iface_type, enable, **settings):
salt '*' ip.build_interface eth0 eth <settings>
'''
if __grains__['lsb_distrib_id'] == 'nilrt':
raise salt.exceptions.CommandExecutionError('Not supported in this version.')
if iface_type != 'eth':
raise salt.exceptions.CommandExecutionError('Interface type not supported: {0}:'.format(iface_type))
if 'proto' not in settings or settings['proto'] == 'dhcp': # default protocol type used is dhcp
set_dhcp_linklocal_all(iface)
elif settings['proto'] != 'static':
raise salt.exceptions.CommandExecutionError('Protocol type: {0} is not supported'.format(settings['proto']))
exc_msg = 'Protocol type: {0} is not supported'.format(settings['proto'])
raise salt.exceptions.CommandExecutionError(exc_msg)
else:
address = settings['ipaddr']
netmask = settings['netmask']
@ -553,7 +744,9 @@ def build_interface(iface, iface_type, enable, **settings):
for key, val in six.iteritems(settings):
if 'dns' in key or 'domain' in key:
dns += val
if enable:
set_static_all(iface, address, netmask, gateway, dns)
if enabled:
up(iface)
return get_interface(iface)
@ -569,6 +762,8 @@ def build_network_settings(**settings):
salt '*' ip.build_network_settings <settings>
'''
if __grains__['lsb_distrib_id'] == 'nilrt':
raise salt.exceptions.CommandExecutionError('Not supported in this version.')
changes = []
if 'networking' in settings:
if settings['networking'] in _CONFIG_TRUE:
@ -597,8 +792,10 @@ def get_network_settings():
salt '*' ip.get_network_settings
'''
if __grains__['lsb_distrib_id'] == 'nilrt':
raise salt.exceptions.CommandExecutionError('Not supported in this version.')
settings = []
networking = 'no' if _get_state() == 'offline' else "yes"
networking = 'no' if _get_state() == 'offline' else 'yes'
settings.append('networking={0}'.format(networking))
hostname = __salt__['network.get_hostname']
settings.append('hostname={0}'.format(hostname))
@ -615,6 +812,8 @@ def apply_network_settings(**settings):
salt '*' ip.apply_network_settings
'''
if __grains__['lsb_distrib_id'] == 'nilrt':
raise salt.exceptions.CommandExecutionError('Not supported in this version.')
if 'require_reboot' not in settings:
settings['require_reboot'] = False