x[h.ddlZddlZddlZddlZddlZddlmZddlmZeje Z dZ dZ dZdZdZd ZdZd Zd Zd Zej,eZej,eZeezZd Zd ZdZdZdZdZdZ dZ!d Z"dZ#dZ$edgdZ%edddgZ&edgdZ'Gdde(Z)dZ*dZ+d$dZ,dZ-dZ.d Z/d!Z0d"Z1d#Z2y)%N) namedtuple)utili<IHHIIBHiIIRTAAttr)lengthrta_typedataInterfaceOperstateifname operstate NetlinkHeader)rtypeflagsseqpidceZdZdZy)NetlinkCreateSocketErrorz5Raised if netlink socket fails during create or bind.N)__name__ __module__ __qualname____doc__C/usr/lib/python3/dist-packages/cloudinit/sources/helpers/netlink.pyrr5s?r%rc tjtjtjtj}|j t j tf|jdtjd|S#tj$r}d|z}t||d}~wwxYw)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_socketemsgs r&create_bound_netlink_socketr79s3   v0D0D  RYY[+67""1%II&'  <<3:Q>&s+23sA;BB='B88B=c|Jdt|tk\sJdtjt|dt \}}}}}t jd|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_OFFSETr2r3r)rmsg_lenmsg_typerrrs r&get_netlink_msg_headerrBOs{  +^+  D ]"545")/d+O,*&GXuc3II*H5 (E3 <) 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)selectr2r3recvMAX_SIZEr1)r4timeoutread_set_rs r&read_netlink_socketrKhst  %?'?? %]]N#3RWENHaX%II-.   x (D | @A Kr%cL|Jdt|tsJd|tk\sJddx}}d} tjd||d}tjd||dzd}||t z||z}t|||S#tj $rYywxYw) 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. Nr9zoffset is not integerz'rta offset is less than expected lengthrH)offsetr) isinstanceintRTATTR_START_OFFSETr< unpack_fromr1RTA_DATA_START_OFFSETr)rrNrr attr_datas r&unpack_rta_attrrUs  +^+  fc ";$;; "%%101%FXI##Cf=a@%%c4 CAF V33fvoFI 68Y // <<s9B B#"B#c`|Jdt|tkDsJddx}}t}|t|krt||}|r|jdk(rnt|jtzz tz}||j|zz }|j t k(rt|j}nD|j tk(r1tj|jd}|jd}|t|kr|r|ytjd||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. Nr9z2length of data is smaller than RTATTR_START_OFFSETrzutf-8z!rta attrs: ifname %s operstate %d)r:rQrUr PAD_ALIGNMENTrIFLA_OPERSTATEordr IFLA_IFNAMEr decode_binarystripr2r3r)rrrrNattrpadleninterface_names r&read_rta_oper_stateras   +^+  D ''<;<'FY F CI tV,t{{a'  T[[=8 9  $++&& ==N *DIII ]]k )!// 7CN#))$/F CI  Y&II169E fi 00r%ctjddfd}t|dtgtt g|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.Nc|vry|y)NTFr$)inamecarrier prevCarrier existing_nicsrs r&should_continue_cbz5wait_for_nic_attach_event..should_continue_cbs M !r%)r2r3read_netlink_messages RTM_NEWLINKOPER_UP OPER_DOWN)r4rgrhrs ` @r&wait_for_nic_attach_eventrmsCII12 F  )  Mr%crtjddfd}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.Nc |y)NFr$)rdrerfrs r&rhz5wait_for_nic_detach_event..should_continue_cbs r%)r2r3ri RTM_DELLINKrl)r4rhrs @r&wait_for_nic_detach_eventrqs= II12 F {mi[:L Mr%c|JdJdtdkDsJdfd}tjdt|tt gt tg|y)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. NrDzinterface name is nonerzinterface name cannot be emptyc`|tk(xr |tk(}|rtjdyy)NzMedia switch happened on %s.FT)rlrkr2r3)rdrerf isVnetSwitchrs r&rhz=wait_for_media_disconnect_connect..should_continue_cbs/#y0Jw'7I  II4f =r%z1Wait for media disconnect and reconnect to happen)r:r2r3rirjrprkrl)r4rrhs ` r&!wait_for_media_disconnect_connectrust  %?'?? %  777  v;?<<  2CI>d)w&']F6{]* ?@-f5H6{X__, FGoo 59!>Ff_F II:F C}}I-1&9O& =O)#**m; L#**! (( :!K%//G+&&MwNFG}a r%)N)3loggingr-rEr(r< collectionsr cloudinitr getLoggerr r2r/rjrp RTM_GETLINK RTM_SETLINKrGr?ryr> IFINFOMSG_FMTcalcsizer;IFINFOMSG_SIZErQrSrXr[rY OPER_UNKNOWNOPER_NOTPRESENTrlOPER_LOWERLAYERDOWN OPER_TESTING OPER_DORMANTrkrrrrwrr7rBrKrUrarmrqrurir$r%r&rs6  "g!        -  /#n4       Y > ? 4x6MN> @|@,=2.04"1J:&@Er%