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:tjt|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 */ }; NzGot netlink msg of type %d)structunpack NLMSGHDR_FMTMSG_TYPE_OFFSETr(r)r)rZmsg_lenZmsg_typerrrr!r!r"get_netlink_msg_headerSs r2cCsNtj|ggg|\}}}||kr$dStjd|jt}|dkrJtjd|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 ready for readz,Reading from Netlink socket returned no data)selectr(r)ZrecvMAX_SIZEr')r*ZtimeoutZread_set_rr!r!r"read_netlink_socketls    r6c Cstd}}d}y0tjd||dd}tjd||ddd}Wntjk rRdSX||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. rNH)offsetr)r. unpack_fromr'RTA_DATA_START_OFFSETr)rr8rrZ attr_datar!r!r"unpack_rta_attrs r;cCsd}}t}x|t|krt||}| s4|jdkr6Pt|jtt}||j|7}|jtkrlt|j}q|jt krt j |jd}|j d}qW| s|dkrdSt jd||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. Nrzutf-8z!rta attrs: ifname %s operstate %d)RTATTR_START_OFFSETlenr;r PAD_ALIGNMENTrIFLA_OPERSTATEordr IFLA_IFNAMErZ decode_binarystripr(r)r)rrrr8attrpadlenZinterface_namer!r!r"read_rta_oper_states$     rFcs6tjddfdd}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*rJrKr!)rJrr"wait_for_nic_attach_events  rPcs2tjddfdd}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!)rGrHrI)rr!r"rKsz5wait_for_nic_detach_event..should_continue_cb)r(r)rL RTM_DELLINKrO)r*rKr!)rr"wait_for_nic_detach_events   rRcs2fdd}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. cs(|tko|tk}|r$tjddSdS)NzMedia switch happened on %s.FT)rOrNr(r))rGrHrIZ isVnetSwitch)rr!r"rKs  z=wait_for_media_disconnect_connect..should_continue_cbz1Wait for media disconnect and reconnect to happenN)r(r)rLrMrQrNrO)r*rrKr!)rr"!wait_for_media_disconnect_connects  rScCs|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.) RuntimeErrorbytesrNr6SELECT_TIMEOUTr(r)r> NLMSGHDR_SIZEr2rr?rrFrr)r*Z ifname_filterZ rtm_typesZ operstatesZshould_continue_callbackrrHrIZ recv_datar8ZdatalenZnl_msgZnlheaderrEZinterface_stater!r!r"rLs`               rL)N)7Zloggingr$r3r#r. collectionsrZ cloudinitrZ getLoggerrr(r&Z NLMSG_NOOPZ NLMSG_ERRORZ NLMSG_DONErMrQZ RTM_GETLINKZ RTM_SETLINKr4ZRTA_DATA_OFFSETr1rVr0Z IFINFOMSG_FMTcalcsizerWZIFINFOMSG_SIZEr=r:r?rBr@Z OPER_UNKNOWNZOPER_NOTPRESENTrOZOPER_LOWERLAYERDOWNZ OPER_TESTINGZ OPER_DORMANTrNrrrrTrr-r2r6r;rFrPrRrSrLr!r!r!r"sb      %