a 'Dg.@sBddlZddlZddlZddlZddlZddlmZddlmZe e Z dZ dZ dZdZdZd ZdZd Zd Zd ZeeZeeZeeZd Zd ZdZdZdZdZdZ dZ!d Z"dZ#dZ$edgdZ%edddgZ&edgdZ'Gddde(Z)ddZ*ddZ+d-dd Z,d!d"Z-d#d$Z.d%d&Z/d'd(Z0d)d*Z1d+d,Z2dS).N) namedtuple)utili<ZIHHIIZBHiIIRTAAttr)lengthrta_typedataInterfaceOperstateifname operstate NetlinkHeader)rtypeflagsseqpidc@seZdZdZdS)NetlinkCreateSocketErrorz5Raised if netlink socket fails during create or bind.N)__name__ __module__ __qualname____doc__r r E/usr/lib/python3.9/site-packages/cloudinit/sources/helpers/netlink.pyr5src Cs|z4ttjtjtj}|ttf|dWn8tj yl}zd|}t ||WYd}~n d}~00t 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_socket9s    r,cCs^|dusJdt|tks$Jdtt|dt\}}}}}td|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 */ }; N data is nonez+data is smaller than netlink message headerzGot netlink msg of type %d) len NLMSGHDR_SIZEstructunpack NLMSGHDR_FMTMSG_TYPE_OFFSETr'r(r)rZmsg_lenZmsg_typerrrr r r!get_netlink_msg_headerOs   r4cCs^|dusJdt|ggg|\}}}||vr4dStd|t}|durZtd|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 Nnetlink socket is noneznetlink socket ready for readz,Reading from Netlink socket returned no data)selectr'r(ZrecvMAX_SIZEr&)r)timeoutZread_set_rr r r!read_netlink_sockeths    r:cCs|dusJdt|ts"Jd|tks2Jdd}}d}z0tjd||dd}tjd||ddd}WntjyYdS0||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. Nr-zoffset is not integerz'rta offset is less than expected lengthrH)offsetr ) isinstanceintRTATTR_START_OFFSETr0 unpack_fromr&RTA_DATA_START_OFFSETr)rr<rrZ attr_datar r r!unpack_rta_attrsrBcCs|dusJdt|tks$Jdd}}t}|t|krt||}|r|jdkrVqt|jtt}||j|7}|jtkrt|j}q0|jt kr0t |jd}| d}q0|r|durdSt d||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. Nr-z2length of data is smaller than RTATTR_START_OFFSETrzutf-8z!rta attrs: ifname %s operstate %d)r.r?rBr PAD_ALIGNMENTrIFLA_OPERSTATEordr IFLA_IFNAMErZ decode_binarystripr'r(r)rrrr<attrpadlenZinterface_namer r r!read_rta_oper_states0          rKcs6tddfdd}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|vr 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)rQrRr rPr!wait_for_nic_attach_events  rWcs2tddfdd}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 rLrr r!rRsz5wait_for_nic_detach_event..should_continue_cb)r'r(rS RTM_DELLINKrV)r)rRr rXr!wait_for_nic_detach_events  rZcsf|dusJddus Jdtdks4Jdfdd}tdt|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. Nr5zinterface name is nonerzinterface name cannot be emptycs(|tko|tk}|r$tddSdS)NzMedia switch happened on %s.FT)rVrUr'r()rMrNrOZ isVnetSwitchrXr r!rRs  z=wait_for_media_disconnect_connect..should_continue_cbz1Wait for media disconnect and reconnect to happen)r.r'r(rSrTrYrUrV)r)rrRr rXr!!wait_for_media_disconnect_connects   r[cCsx|durtdt}t}t}t|t}|dur2qtdt|||7}tdt|d} t|} | | krf|| d} t| tkrtdqft | } t| | j krtdqf| j t dt d@} | | } td | | j |vrqft | }|durtd |qf|dur:|j|kr:td |j|qf|j|vrHqf|}|j}||j||sfdSqf|| d}qdS) 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.) RuntimeErrorbytesrUr:SELECT_TIMEOUTr'r(r.r/r4rrDrrKrr)r)Z ifname_filterZ rtm_typesZ operstatesZshould_continue_callbackrrNrOZ recv_datar<ZdatalenZnl_msgZnlheaderrJZinterface_stater r r!rSsh            rS)N)3Zloggingr#r6r"r0 collectionsrZ cloudinitrZ getLoggerrr'r%rTrYZ RTM_GETLINKZ RTM_SETLINKr7r3r^r2Z IFINFOMSG_FMTcalcsizer/ZIFINFOMSG_SIZEr?rArDrGrEZ OPER_UNKNOWNZOPER_NOTPRESENTrVZOPER_LOWERLAYERDOWNZ OPER_TESTINGZ OPER_DORMANTrUrrrr\rr,r4r:rBrKrWrZr[rSr r r r!s\      %