o x[h.@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<IHHIIBHiIIRTAAttr)lengthrta_typedataInterfaceOperstateifname operstate NetlinkHeader)rtypeflagsseqpidc@seZdZdZdS)NetlinkCreateSocketErrorz5Raised if netlink socket fails during create or bind.N)__name__ __module__ __qualname____doc__r"r"C/usr/lib/python3/dist-packages/cloudinit/sources/helpers/netlink.pyr5src Cspzttjtjtj}|ttf|dWntj y0}z d|}t ||d}~wwt 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) socket AF_NETLINKSOCK_RAW NETLINK_ROUTEbindosgetpid RTMGRP_LINK setblockingerrorrLOGdebug)netlink_socketemsgr"r"r#create_bound_netlink_socket9s    r3cCs^|dusJdt|tksJdtt|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)rmsg_lenmsg_typerrrr"r"r#get_netlink_msg_headerOs  r=cCs^|dusJdt|ggg|\}}}||vrdStd|t}|dur-td|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/recvMAX_SIZEr-)r0timeoutread_set_rr"r"r#read_netlink_sockeths    rEcCs|dusJdt|tsJd|tksJdd}}d}ztjd||dd}tjd||ddd}Wn tjyBYdSw||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. Nr4zoffset is not integerz'rta offset is less than expected lengthrH)offsetr) isinstanceintRTATTR_START_OFFSETr7 unpack_fromr-RTA_DATA_START_OFFSETr)rrGrr attr_datar"r"r#unpack_rta_attrs  rNcCs|dusJdt|tksJdd}}t}|t|kr]t||}|r*|jdkr+n2t|jtt}||j|7}|jtkrFt|j}n|jt krWt |jd}| d}|t|ks|rc|duredSt 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. Nr4z2length of data is smaller than RTATTR_START_OFFSETrzutf-8z!rta attrs: ifname %s operstate %d)r5rJrNr PAD_ALIGNMENTrIFLA_OPERSTATEordr IFLA_IFNAMEr decode_binarystripr.r/r)rrrrGattrpadleninterface_namer"r"r#read_rta_oper_states0          rYcs6tddfdd}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|vrdS|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)r0r_r`r"r^r#wait_for_nic_attach_events  recs2tddfdd}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"rZrr"r#r`sz5wait_for_nic_detach_event..should_continue_cb)r.r/ra RTM_DELLINKrd)r0r`r"rfr#wait_for_nic_detach_events  rhcsf|dusJddusJdtdksJdfdd}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. Nr>zinterface name is nonerzinterface name cannot be emptycs(|tko|tk}|rtddSdS)NzMedia switch happened on %s.FT)rdrcr.r/)r[r\r] isVnetSwitchrfr"r#r`s  z=wait_for_media_disconnect_connect..should_continue_cbz1Wait for media disconnect and reconnect to happen)r5r.r/rarbrgrcrd)r0rr`r"rfr#!wait_for_media_disconnect_connects   rjcCsn|durtdt}t}t} t|t}|durqtdt|||7}tdt|d} t|} | | kr|| d} t| tkrJtdnft | } t| | j kr[tdnU| j t d t d @} | | } td | | j |vrwq4t | }|durtd |q4|dur|j|krtd |j|q4|j|vrq4|}|j}||j||sdS| | ks8|| d}q) 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 noneTzread %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.) RuntimeErrorbytesrcrESELECT_TIMEOUTr.r/r5r6r=rrPrrYrr)r0 ifname_filter rtm_types operstatesshould_continue_callbackrr\r] recv_datarGdatalennl_msgnlheaderrWinterface_stater"r"r#rasj            'ra)N)3loggingr)r?r$r7 collectionsr cloudinitr getLoggerrr.r+rbrg RTM_GETLINK RTM_SETLINKrAr:rmr9 IFINFOMSG_FMTcalcsizer6IFINFOMSG_SIZErJrLrPrSrQ OPER_UNKNOWNOPER_NOTPRESENTrdOPER_LOWERLAYERDOWN OPER_TESTING OPER_DORMANTrcrrrrkrr3r=rErNrYrerhrjrar"r"r"r#s^      %