3 \me.@sZddlZddlZddlZddlZddlZddlmZddlmZej e Z dZ dZ dZdZdZdZd Zd Zd Zd ZdZd ZdZdZejeZejeZeeZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(eddddgZ)edddgZ*eddddddgZ+Gdd d e,Z-d!d"Z.d#d$Z/d3d%d&Z0d'd(Z1d)d*Z2d+d,Z3d-d.Z4d/d0Z5d1d2Z6dS)4N) namedtuple)utili <ZIHHIIZBHiIIRTAAttrlengthrta_typedataInterfaceOperstateifname operstate NetlinkHeadertypeflagsseqpidc@seZdZdZdS)NetlinkCreateSocketErrorz5Raised if netlink socket fails during create or bind.N)__name__ __module__ __qualname____doc__r!r!/usr/lib/python3.6/netlink.pyr9srcCszy4tjtjtjtj}|jtjtf|jdWn6tj k rj}zd|}t ||WYdd}~XnXt j d|S)auCreates netlink socket and bind on netlink group to catch interface down/up events. The socket will bound only on RTMGRP_LINK (which only includes RTM_NEWLINK/RTM_DELLINK/RTM_GETLINK events). The socket is set to non-blocking mode since we're only receiving messages. :returns: netlink socket in non-blocking mode :raises: NetlinkCreateSocketError rz*Exception during netlink socket create: %sNzCreated netlink socket) socketZ AF_NETLINKZSOCK_RAWZ NETLINK_ROUTEZbindosgetpid RTMGRP_LINKZ setblockingerrorrLOGdebug)netlink_socketemsgr!r!r"create_bound_netlink_socket=s  r-cCs^|dk stdt|tks$tdtjt|dt\}}}}}tjd|t |||||S)aGets netlink message type and length :param: data read from netlink socket :returns: netlink message type :raises: AssertionError if data is None or data is not >= NLMSGHDR_SIZE struct nlmsghdr { __u32 nlmsg_len; /* Length of message including header */ __u16 nlmsg_type; /* Type of message content */ __u16 nlmsg_flags; /* Additional flags */ __u32 nlmsg_seq; /* Sequence number */ __u32 nlmsg_pid; /* Sender port ID */ }; Nz data is nonez+data is smaller than netlink message headerzGot netlink msg of type %d) AssertionErrorlen NLMSGHDR_SIZEstructunpack NLMSGHDR_FMTMSG_TYPE_OFFSETr(r)r)rZmsg_lenZmsg_typerrrr!r!r"get_netlink_msg_headerSs r5cCs^|dk stdtj|ggg|\}}}||kr4dStjd|jt}|dkrZtjd|S)aSelect and read from the netlink socket if ready. :param: netlink_socket: specify which socket object to read from :param: timeout: specify a timeout value (integer) to wait while reading, if none, it will block indefinitely until socket ready for read :returns: string of data read (max length = ) from socket, if no data read, returns None :raises: AssertionError if netlink_socket is None Nznetlink socket is noneznetlink socket ready for readz,Reading from Netlink socket returned no data)r.selectr(r)ZrecvMAX_SIZEr')r*ZtimeoutZread_set_rr!r!r"read_netlink_socketls    r9c Cs|dk stdt|ts"td|tks2tdd}}d}y0tjd||dd}tjd||ddd}Wntjk rdSX||t||}t|||S) a(Unpack a single rta attribute. :param: data: string of data read from netlink socket :param: offset: starting offset of RTA Attribute :return: RTAAttr object with length, type and data. On error, return None. :raises: AssertionError if data is None or offset is not integer. Nz data is nonezoffset is not integerz'rta offset is less than expected lengthrH)offsetr) r. isinstanceintRTATTR_START_OFFSETr1 unpack_fromr'RTA_DATA_START_OFFSETr)rr;rrZ attr_datar!r!r"unpack_rta_attrs rAcCs|dk stdt|tks$tdd}}t}x|t|krt||}| sX|jdkrZPt|jtt}||j|7}|jtkrt|j }q2|jt kr2t j |j d}|j d}q2W| s|dkrdStjd||t||S)aReads Interface name and operational state from RTA Data. :param: data: string of data read from netlink socket :returns: InterfaceOperstate object containing if_name and oper_state. None if data does not contain valid IFLA_OPERSTATE and IFLA_IFNAME messages. :raises: AssertionError if data is None or length of data is smaller than RTATTR_START_OFFSET. Nz data is nonez2length of data is smaller than RTATTR_START_OFFSETrzutf-8z!rta attrs: ifname %s operstate %d)r.r/r>rAr PAD_ALIGNMENTrIFLA_OPERSTATEordr IFLA_IFNAMErZ decode_binarystripr(r)r)rrrr;attrpadlenZinterface_namer!r!r"read_rta_oper_states*      rJcs6tjddfdd}t|dtgttg|S)zBlock until a single nic is attached. :param: netlink_socket: netlink_socket to receive events :param: existing_nics: List of existing nics so that we can skip them. :raises: AssertionError if netlink_socket is none. z!Preparing to wait for nic attach.Ncs|kr dS|dS)NTFr!)inamecarrier prevCarrier) existing_nicsrr!r"should_continue_cbsz5wait_for_nic_attach_event..should_continue_cb)r(r)read_netlink_messages RTM_NEWLINKOPER_UP OPER_DOWN)r*rNrOr!)rNrr"wait_for_nic_attach_events  rTcs2tjddfdd}t|dtgtg|S)zBlock until a single nic is detached and its operational state is down. :param: netlink_socket: netlink_socket to receive events. z!Preparing to wait for nic detach.Ncs|dS)NFr!)rKrLrM)rr!r"rOsz5wait_for_nic_detach_event..should_continue_cb)r(r)rP RTM_DELLINKrS)r*rOr!)rr"wait_for_nic_detach_events   rVcsf|dk stddk s tdtdks4tdfdd}tjdt|ttgttg|dS) aBlock until media disconnect and connect has happened on an interface. Listens on netlink socket to receive netlink events and when the carrier changes from 0 to 1, it considers event has happened and return from this function :param: netlink_socket: netlink_socket to receive events :param: ifname: Interface name to lookout for netlink events :raises: AssertionError if netlink_socket is None or ifname is None. Nznetlink socket is nonezinterface name is nonerzinterface name cannot be emptycs(|tko|tk}|r$tjddSdS)NzMedia switch happened on %s.FT)rSrRr(r))rKrLrMZ isVnetSwitch)rr!r"rOs  z=wait_for_media_disconnect_connect..should_continue_cbz1Wait for media disconnect and reconnect to happen) r.r/r(r)rPrQrUrRrS)r*rrOr!)rr"!wait_for_media_disconnect_connects   rWcCs|dkrtdt}t}t}xZt|t}|dkr6q"tjdt|||7}tjdt|d} t|} x| | krj|| d} t| tkrtjdPt | } t| | j krtjdP| j t dt d@} | | } tjd | | j |krqnt | }|dkrtjd |qn|dk r>|j|kr>tjd |j|qn|j|krLqn|}|j}||j||sndSqnW|| d}q"WdS) aReads from the netlink socket until the condition specified by the continuation callback is met. :param: netlink_socket: netlink_socket to receive events. :param: ifname_filter: if not None, will only listen for this interface. :param: rtm_types: Type of netlink events to listen for. :param: operstates: Operational states to listen. :param: should_continue_callback: Specifies when to stop listening. NzNetlink socket is nonezread %d bytes from socketzLength of data after concat %drz#Data is smaller than netlink headerz*Partial data. Smaller than netlink messagerz"offset to next netlink message: %dz!Failed to read rta attributes: %sz6Ignored netlink event on interface %s. Waiting for %s.) RuntimeErrorbytesrRr9SELECT_TIMEOUTr(r)r/r0r5rrCrrJrr)r*Z ifname_filterZ rtm_typesZ operstatesZshould_continue_callbackrrLrMZ recv_datar;ZdatalenZnl_msgZnlheaderrIZinterface_stater!r!r"rPs`               rP)N)7Zloggingr$r6r#r1 collectionsrZ cloudinitrZ getLoggerrr(r&Z NLMSG_NOOPZ NLMSG_ERRORZ NLMSG_DONErQrUZ RTM_GETLINKZ RTM_SETLINKr7ZRTA_DATA_OFFSETr4rZr3Z IFINFOMSG_FMTcalcsizer0ZIFINFOMSG_SIZEr>r@rCrFrDZ OPER_UNKNOWNZOPER_NOTPRESENTrSZOPER_LOWERLAYERDOWNZ OPER_TESTINGZ OPER_DORMANTrRrrrrXrr-r5r9rArJrTrVrWrPr!r!r!r"sb      %