15 # under the License. |
15 # under the License. |
16 # |
16 # |
17 # @author: Girish Moodalbail, Oracle, Inc. |
17 # @author: Girish Moodalbail, Oracle, Inc. |
18 # |
18 # |
19 |
19 |
|
20 import eventlet |
20 import netaddr |
21 import netaddr |
21 |
22 |
|
23 from oslo_log import log as logging |
|
24 |
22 from neutron.agent.linux import utils |
25 from neutron.agent.linux import utils |
|
26 from neutron.i18n import _LE |
|
27 |
|
28 LOG = logging.getLogger(__name__) |
23 |
29 |
24 |
30 |
25 class CommandBase(object): |
31 class CommandBase(object): |
26 @classmethod |
32 @classmethod |
27 def execute_with_pfexec(cls, cmd, **kwargs): |
33 def execute_with_pfexec(cls, cmd, **kwargs): |
48 except Exception: |
54 except Exception: |
49 return False |
55 return False |
50 return True |
56 return True |
51 |
57 |
52 @classmethod |
58 @classmethod |
53 def ipaddr_exists(cls, ifname, ipaddr): |
59 def ipaddr_exists(cls, ifname, ipaddr, ifcheck=True): |
54 |
60 |
55 if not cls.ifname_exists(ifname): |
61 if ifcheck and not cls.ifname_exists(ifname): |
56 return False |
62 return False |
57 |
63 |
58 cmd = ['/usr/sbin/ipadm', 'show-addr', '-po', 'addr', ifname] |
64 cmd = ['/usr/sbin/ipadm', 'show-addr', '-po', 'addr', ifname] |
59 stdout = cls.execute(cmd) |
65 stdout = cls.execute(cmd) |
60 |
66 |
61 return ipaddr in stdout |
67 return ipaddr in stdout |
81 # create ip interface |
87 # create ip interface |
82 cmd = ['/usr/sbin/ipadm', 'create-ip', self._ifname] |
88 cmd = ['/usr/sbin/ipadm', 'create-ip', self._ifname] |
83 if temp: |
89 if temp: |
84 cmd.append('-t') |
90 cmd.append('-t') |
85 self.execute_with_pfexec(cmd) |
91 self.execute_with_pfexec(cmd) |
86 elif self.ipaddr_exists(self._ifname, ipaddr): |
92 elif self.ipaddr_exists(self._ifname, ipaddr, ifcheck=False): |
87 return |
93 return |
88 |
94 |
89 # If an address is IPv6, then to create a static IPv6 address |
95 # If an address is IPv6, then to create a static IPv6 address |
90 # we need to create link-local address first |
96 # we need to create link-local address first |
91 if netaddr.IPNetwork(ipaddr).version == 6: |
97 if netaddr.IPNetwork(ipaddr).version == 6: |
94 '-p', 'mac-address', self._ifname] |
100 '-p', 'mac-address', self._ifname] |
95 stdout = self.execute(cmd) |
101 stdout = self.execute(cmd) |
96 mac_addr = stdout.splitlines()[0].strip() |
102 mac_addr = stdout.splitlines()[0].strip() |
97 ll_addr = netaddr.EUI(mac_addr).ipv6_link_local() |
103 ll_addr = netaddr.EUI(mac_addr).ipv6_link_local() |
98 |
104 |
99 if not self.ipaddr_exists(self._ifname, str(ll_addr)): |
105 if not self.ipaddr_exists(self._ifname, str(ll_addr), |
|
106 ifcheck=False): |
100 # create a link-local address |
107 # create a link-local address |
101 cmd = ['/usr/sbin/ipadm', 'create-addr', '-T', 'static', '-a', |
108 cmd = ['/usr/sbin/ipadm', 'create-addr', '-T', 'static', '-a', |
102 str(ll_addr), self._ifname] |
109 str(ll_addr), self._ifname] |
103 if temp: |
110 if temp: |
104 cmd.append('-t') |
111 cmd.append('-t') |
221 def show_link(cls): |
228 def show_link(cls): |
222 cmd = ['/usr/sbin/dladm', 'show-link', '-po', 'link'] |
229 cmd = ['/usr/sbin/dladm', 'show-link', '-po', 'link'] |
223 stdout = utils.execute(cmd) |
230 stdout = utils.execute(cmd) |
224 |
231 |
225 return stdout.splitlines() |
232 return stdout.splitlines() |
|
233 |
|
234 |
|
235 def _arping(iface_name, address, count): |
|
236 # Set timeout with -w to ensure arping exits in case the interface |
|
237 # is deleted while it is running |
|
238 arping_cmd = ['/usr/sbin/arping', '-A', '-I', iface_name, '-c', count, |
|
239 '-w', 2 * count, address] |
|
240 try: |
|
241 utils.execute(arping_cmd, check_exit_code=False) |
|
242 except Exception: |
|
243 msg = _LE("Failed sending gratuitous ARP to %(addr)s on " |
|
244 "an interface %(iface)s") |
|
245 LOG.exception(msg, {'addr': address, 'iface': iface_name}) |
|
246 |
|
247 |
|
248 def send_ip_addr_adv_notif(iface_name, address, config): |
|
249 """Send advance notification of an IP address assignment. |
|
250 |
|
251 If the address is in the IPv4 family, send gratuitous ARP. |
|
252 |
|
253 If the address is in the IPv6 family, no advance notification is |
|
254 necessary, since the Neighbor Discovery Protocol (NDP), Duplicate |
|
255 Address Discovery (DAD), and (for stateless addresses) router |
|
256 advertisements (RAs) are sufficient for address resolution and |
|
257 duplicate address detection. |
|
258 """ |
|
259 count = config.send_arp_for_ha |
|
260 |
|
261 def arping(): |
|
262 _arping(iface_name, address, count) |
|
263 |
|
264 if count > 0 and netaddr.IPAddress(address).version == 4: |
|
265 eventlet.spawn_n(arping) |