PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/salt/modules/linux_ip.py

https://gitlab.com/ricardo.hernandez/salt
Python | 194 lines | 175 code | 5 blank | 14 comment | 4 complexity | 6d7c924f2ee8e8f0febac652502c56c9 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. '''
  3. The networking module for Non-RH/Deb Linux distros
  4. '''
  5. from __future__ import absolute_import
  6. import salt.utils
  7. from salt.ext.six.moves import zip
  8. __virtualname__ = 'ip'
  9. def __virtual__():
  10. '''
  11. Confine this module to Non-RH/Deb Linux distros
  12. '''
  13. if salt.utils.is_windows():
  14. return (False, 'Module linux_ip: Windows systems are not supported.')
  15. if __grains__['os_family'] == 'RedHat':
  16. return (False, 'Module linux_ip: RedHat systems are not supported.')
  17. if __grains__['os_family'] == 'Debian':
  18. return (False, 'Module linux_ip: Debian systems are not supported.')
  19. if not salt.utils.which('ip'):
  20. return (False, 'The linux_ip execution module cannot be loaded: '
  21. 'the ip binary is not in the path.')
  22. return __virtualname__
  23. def down(iface, iface_type=None):
  24. '''
  25. Shutdown a network interface
  26. CLI Example:
  27. .. code-block:: bash
  28. salt '*' ip.down eth0
  29. '''
  30. # Slave devices are controlled by the master.
  31. if iface_type not in ['slave']:
  32. return __salt__['cmd.run']('ip link set {0} down'.format(iface))
  33. return None
  34. def get_interface(iface):
  35. '''
  36. Return the contents of an interface script
  37. CLI Example:
  38. .. code-block:: bash
  39. salt '*' ip.get_interface eth0
  40. '''
  41. ifaces = _ip_ifaces()
  42. return ifaces.get(iface)
  43. def _ip_ifaces():
  44. '''
  45. Parse output from 'ip a'
  46. '''
  47. tmp = {}
  48. ret = {}
  49. if_ = None
  50. at_ = None
  51. out = __salt__['cmd.run']('ip a')
  52. for line in out.splitlines():
  53. if not line.startswith(' '):
  54. comps = line.split(':')
  55. if_ = comps[1].strip()
  56. opts_comps = comps[2].strip().split()
  57. flags = opts_comps.pop(0).lstrip('<').rstrip('>').split(',')
  58. opts_iter = iter(opts_comps)
  59. ret[if_] = {
  60. 'flags': flags,
  61. 'options': dict(list(zip(opts_iter, opts_iter)))
  62. }
  63. else:
  64. if line.strip().startswith('link'):
  65. comps = iter(line.strip().split())
  66. ret[if_]['link_layer'] = dict(list(zip(comps, comps)))
  67. elif line.strip().startswith('inet'):
  68. comps = line.strip().split()
  69. at_ = comps[0]
  70. if len(comps) % 2 != 0:
  71. last = comps.pop()
  72. comps[-1] += ' {0}'.format(last)
  73. ifi = iter(comps)
  74. ret[if_][at_] = dict(list(zip(ifi, ifi)))
  75. else:
  76. comps = line.strip().split()
  77. ifi = iter(comps)
  78. ret[if_][at_].update(dict(list(zip(ifi, ifi))))
  79. return ret
  80. def up(iface, iface_type=None):
  81. '''
  82. Start up a network interface
  83. CLI Example:
  84. .. code-block:: bash
  85. salt '*' ip.up eth0
  86. '''
  87. # Slave devices are controlled by the master.
  88. if iface_type not in ['slave']:
  89. return __salt__['cmd.run']('ip link set {0} up'.format(iface))
  90. return None
  91. def get_routes(iface=None):
  92. '''
  93. Return the current routing table
  94. CLI Examples:
  95. .. code-block:: bash
  96. salt '*' ip.get_routes
  97. salt '*' ip.get_routes eth0
  98. '''
  99. routes = _parse_routes()
  100. if iface is not None:
  101. return routes.get(iface)
  102. return routes
  103. def _parse_routes():
  104. '''
  105. Parse the contents of ``/proc/net/route``
  106. '''
  107. with salt.utils.fopen('/proc/net/route', 'r') as fp_:
  108. out = fp_.read()
  109. ret = {}
  110. for line in out.splitlines():
  111. tmp = {}
  112. if not line.strip():
  113. continue
  114. if line.startswith('Iface'):
  115. continue
  116. comps = line.split()
  117. tmp['iface'] = comps[0]
  118. tmp['destination'] = _hex_to_octets(comps[1])
  119. tmp['gateway'] = _hex_to_octets(comps[2])
  120. tmp['flags'] = _route_flags(int(comps[3]))
  121. tmp['refcnt'] = comps[4]
  122. tmp['use'] = comps[5]
  123. tmp['metric'] = comps[6]
  124. tmp['mask'] = _hex_to_octets(comps[7])
  125. tmp['mtu'] = comps[8]
  126. tmp['window'] = comps[9]
  127. tmp['irtt'] = comps[10]
  128. if comps[0] not in ret:
  129. ret[comps[0]] = []
  130. ret[comps[0]].append(tmp)
  131. return ret
  132. def _hex_to_octets(addr):
  133. '''
  134. Convert hex fields from /proc/net/route to octects
  135. '''
  136. return '{0}:{1}:{2}:{3}'.format(
  137. int(addr[6:8], 16),
  138. int(addr[4:6], 16),
  139. int(addr[2:4], 16),
  140. int(addr[0:2], 16),
  141. )
  142. def _route_flags(rflags):
  143. '''
  144. https://github.com/torvalds/linux/blob/master/include/uapi/linux/route.h
  145. https://github.com/torvalds/linux/blob/master/include/uapi/linux/ipv6_route.h
  146. '''
  147. flags = ''
  148. fmap = {
  149. 0x0001: 'U', # RTF_UP, route is up
  150. 0x0002: 'G', # RTF_GATEWAY, use gateway
  151. 0x0004: 'H', # RTF_HOST, target is a host
  152. 0x0008: 'R', # RET_REINSTATE, reinstate route for dynamic routing
  153. 0x0010: 'D', # RTF_DYNAMIC, dynamically installed by daemon or redirect
  154. 0x0020: 'M', # RTF_MODIFIED, modified from routing daemon or redirect
  155. 0x00040000: 'A', # RTF_ADDRCONF, installed by addrconf
  156. 0x01000000: 'C', # RTF_CACHE, cache entry
  157. 0x0200: '!', # RTF_REJECT, reject route
  158. }
  159. for item in fmap.keys():
  160. if rflags & item:
  161. flags += fmap[item]
  162. return flags