����JFIFXX�����    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222����"��4�� ���,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu���#ډb���_�N�?��wQ���5-�~�I���8����TK<5o�Iv-�����k�_U_�����~b�M��d����Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�?_�'ϔ��_�Ջt��=||I ��6�έ"�����D���/[�k�9���Y�8ds|\���Ҿp6�Ҵ���]��.����6�z<�v��@]�i%��$j��~�g��J>��no����pM[me�i$[����s�o�ᘨ�˸ nɜG-�ĨU�ycP�3.DB�li�;��hj���x7Z^�N�h������N3u{�:j�x�힞��#M&��jL P@_���� P��&��o8������9�����@Sz6�t7#O�ߋ �s}Yf�T���lmr����Z)'N��k�۞p����w\�Tȯ?�8`�O��i{wﭹW�[�r�� ��Q4F�׊���3m&L�=��h3����z~��#�\�l :�F,j@�� ʱ�wQT����8�"kJO���6�֚l����}���R�>ډK���]��y����&����p�}b��;N�1�m�r$�|��7�>e�@B�TM*-iH��g�D�)� E�m�|�ؘbҗ�a��Ҿ����t4���o���G��*oCN�rP���Q��@z,|?W[0�����:�n,jWiE��W��$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S����VN;�}�s?.����� w�9��˟<���Mq4�Wv'��{)0�1mB��V����W[�����8�/<� �%���wT^�5���b��)iM� pg�N�&ݝ��VO~�q���u���9� ����!��J27����$O-���! �:�%H��� ـ����y�ΠM=t{!S�� oK8������t<����è:a������[�����ա�H���~��w��Qz`�po�^ ����Q��n� �,uu�C�$ ^���,������8�#��:�6��e�|~���!�3�3.�\0��q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<���Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y�|�y��� ~�6�@c��1vOp�Ig����4��l�OD���L����� R���c���j�_�uX6��3?nk��Wy�f;^*B� ��@�~a�`��Eu������+���6�L��.ü>��}y���}_�O�6�͐�:�YrG�X��kG�����l^w���~㒶sy��Iu�!� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT��G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2��#I/�׍qz��^t�̔���b�Yz4x���t�){ OH��+(E��A&�N�������XT��o��"�XC��'���)}�J�z�p� ��~5�}�^����+�6����w��c��Q�|Lp�d�H��}�(�.|����k��c4^�"�����Z?ȕ ��a<�L�!039C� �Eu�C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf���M}7����]����s2tcS{�\icTx;�\��7K���P���ʇ Z O-��~��c>"��?�������P��E��O�8��@�8��G��Q�g�a�Վ���󁶠�䧘��_%#r�>�1�z�a��eb��qcPѵ��n���#L��� =��׀t� L�7�`��V���A{�C:�g���e@�w1 Xp3�c3�ġ����p��M"'-�@n4���fG��B3�DJ�8[Jo�ߐ���gK)ƛ��$���� ���8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`���?��K����QK�d����B`�s}�>���`��*�>��,*@J�d�oF*����弝��O}�k��s��]��y�ߘ��c1G�V���<=�7��7����6�q�PT��tXԀ�!9*4�4Tހ3XΛex�46���Y��D ����� �BdemDa����\�_l,��G�/���֌7���Y�](�xTt^%�GE�����4�}bT���ڹ�����;Y)���B�Q��u��>J/J �⮶.�XԄ��j�ݳ�+E��d ��r�5�_D�1 ��o�� �B�x�΢�#���<��W�����8���R6�@g�M�.��� dr�D��>(otU��@x=��~v���2� ӣ�d�oBd��3�eO�6�㣷�����ݜ6��6Y��Qz`��S��{���\P�~z m5{J/L��1������<�e�ͅPu�b�]�ϔ���'������f�b� Zpw��c`"��i���BD@:)ִ�:�]��hv�E�w���T�l��P���"Ju�}��وV J��G6��. J/�Qgl߭�e�����@�z�Zev2u�)]կ�����7x���s�M�-<ɯ�c��r�v�����@��$�ޮ}lk���a���'����>x��O\�ZFu>�����ck#��&:��`�$�ai�>2Δ����l���oF[h��lE�ܺ�Πk:)���`�� $[6�����9�����kOw�\|���8}������ބ:��񶐕��I�A1/�=�2[�,�!��.}gN#�u����b��� ~��݊��}34q����d�E��Lc��$��"�[q�U�硬g^��%B �z���r�pJ�ru%v\h1Y�ne`ǥ:g���pQM~�^�Xi� ��`S�:V29.�P���V�?B�k�� AEvw%�_�9C�Q����wKekPؠ�\�;Io d�{ ߞo�c1eP����\� `����E=���@K<�Y���eڼ�J���w����{av�F�'�M�@/J��+9p���|]�����Iw &`��8���&M�hg��[�{��Xj��%��Ӓ�$��(����ʹN���<>�I���RY���K2�NPlL�ɀ)��&e����B+ь����( � �JTx���_?EZ� }@ 6�U���뙢ط�z��dWI�n` D����噥�[��uV��"�G&Ú����2g�}&m��?ċ�"����Om#��������� ��{�ON��"S�X��Ne��ysQ���@Fn��Vg���dX�~nj�]J�<�K]:��FW��b�������62�=��5f����JKw��bf�X�55��~J �%^����:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v���g�8�1��f24;�V���ǔ�)����9���1\��c��v�/'Ƞ�w�������$�4�R-��t���� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃������A��20�c#��@ 0!1@AP"#2Q`$3V�%45a6�FRUq��� ����^7ׅ,$n�������+��F�`��2X'��0vM��p�L=������5��8������u�p~���.�`r�����\���O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;������S�T���1���i[U�ɵz�]��U)V�S6���3$K{�ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u�!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ���D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v�����멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$�JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4�[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ�dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il��d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J��oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.���3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N�����#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%���JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$���L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)�H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>�dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\�y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7��ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz��)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)'��8Ϣ�ٔ��ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'�L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3�������QT��a����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3�,#c�co��q�a)*Pt����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O���������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l�O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m���PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~�|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0��Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q��nxҍ!U�f�!eh�i�2�m���`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{/ �?�͟��|1�:�#g��W�>$����d��J��d�B��=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l����l�cGs�ځ�������y�Ac�����\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6����N6�q������N ! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td�� ?���N����a��3��m���C���w��������xA�m�q�m���m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4���r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G�����Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q�(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9��3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#yw��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa����Q�#� WeF��ŮNj�p�J* mQ�N����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]��陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WPw���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp�BGv[]�u�Ov���0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND��.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J �4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R��� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(�>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG��{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/��*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>e]�����Q�r�:����g�,i"�����ԩA�*M�<�G��b�if��l^M��5� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f�����֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ���˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)��h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������ G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W�I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��BS�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c���]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪�\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W�����6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}�����6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@�P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6�����m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw�k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e��R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN��ĕ��0 !01@Q"2AaPq3BR������?���@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j�ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^���ԯ̾9Z��F��������n��1��� ��]�[��)�'������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ��&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0��;_��3 !01"@AQa2Pq#3BR������?��ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6����������4B>��o��](��$B���m�����a�!=��?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a�84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b��$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7��k�� 403WebShell
403Webshell
Server IP : 14.139.229.36  /  Your IP : 10.1.1.9
Web Server : Apache
System : Linux gbpuat-tech.ac.in 4.18.0-240.15.1.el8_3.x86_64 #1 SMP Mon Mar 1 17:16:16 UTC 2021 x86_64
User : apache ( 48)
PHP Version : 7.2.24
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /lib64/python3.6/site-packages/pyanaconda/modules/network/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /lib64/python3.6/site-packages/pyanaconda/modules/network/nm_client.py
#
# utility functions using libnm
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.  You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#

import gi
gi.require_version("NM", "1.0")
from gi.repository import NM

import socket
from queue import Queue, Empty
from pykickstart.constants import BIND_TO_MAC
from pyanaconda.modules.network.constants import NM_CONNECTION_UUID_LENGTH, \
    CONNECTION_ACTIVATION_TIMEOUT
from pyanaconda.modules.network.kickstart import default_ks_vlan_interface_name
from pyanaconda.modules.network.utils import is_s390, get_s390_settings, netmask2prefix, \
    prefix2netmask

from pyanaconda.anaconda_loggers import get_module_logger
log = get_module_logger(__name__)


def get_iface_from_connection(nm_client, uuid):
    """Get the name of device that would be used for the connection.

    In installer it should be just one device.
    We need to account also for the case of configurations bound to mac address
    (HWADDR), eg network --bindto=mac command.
    """
    connection = nm_client.get_connection_by_uuid(uuid)
    if not connection:
        return None
    iface = connection.get_setting_connection().get_interface_name()
    if not iface:
        wired_setting = connection.get_setting_wired()
        if wired_setting:
            mac = wired_setting.get_mac_address()
            if mac:
                iface = get_iface_from_hwaddr(nm_client, mac)
    return iface


def get_vlan_interface_name_from_connection(nm_client, connection):
    """Get vlan interface name from vlan connection.

    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection

    If no interface name is specified in the connection settings, infer the
    value as <PARENT_IFACE>.<VLAN_ID> - same as NetworkManager.
    """
    iface = connection.get_setting_connection().get_interface_name()
    if not iface:
        setting_vlan = connection.get_setting_vlan()
        if setting_vlan:
            vlanid = setting_vlan.get_id()
            parent = setting_vlan.get_parent()
            # if parent is specified by UUID
            if len(parent) == NM_CONNECTION_UUID_LENGTH:
                parent = get_iface_from_connection(nm_client, parent)
            if vlanid is not None and parent:
                iface = default_ks_vlan_interface_name(parent, vlanid)
    return iface


def get_iface_from_hwaddr(nm_client, hwaddr):
    """Find the name of device specified by mac address."""
    for device in nm_client.get_devices():
        if device.get_device_type() in (NM.DeviceType.ETHERNET,
                                        NM.DeviceType.WIFI):
            try:
                address = device.get_permanent_hw_address()
                if not address:
                    address = device.get_hw_address()
            except AttributeError as e:
                log.warning("Device %s: %s", device.get_iface(), e)
                address = device.get_hw_address()
        else:
            address = device.get_hw_address()
        # per #1703152, at least in *some* case, we wind up with
        # address as None here, so we need to guard against that
        if address and address.upper() == hwaddr.upper():
            return device.get_iface()
    return None


def get_team_port_config_from_connection(nm_client, uuid):
    connection = nm_client.get_connection_by_uuid(uuid)
    if not connection:
        return None
    team_port = connection.get_setting_team_port()
    if not team_port:
        return None
    config = team_port.get_config()
    return config


def get_team_config_from_connection(nm_client, uuid):
    connection = nm_client.get_connection_by_uuid(uuid)
    if not connection:
        return None
    team = connection.get_setting_team()
    if not team:
        return None
    config = team.get_config()
    return config


def get_device_name_from_network_data(nm_client, network_data, supported_devices, bootif):
    """Get the device name from kickstart device specification.

    Generally given by --device option. For vlans also --interfacename
    and --vlanid comes into play.

    Side effect: for vlan sets network_data.parent value from --device option

    :param network_data: a kickstart device configuartion
    :type network_data: kickstart NetworkData object
    :param supported_devices: list of names of supported devices
    :type supported_devices: list(str)
    :param bootif: MAC addres of device to be used for --device=bootif specification
    :type bootif: str
    :returns: device name the configuration should be used for
    :rtype: str
    """
    spec = network_data.device
    device_name = ""
    msg = ""

    if not spec:
        msg = "device specification missing"

    # Specification by device name
    if spec in supported_devices:
        device_name = spec
        msg = "existing device found"
    # Specification by mac address
    elif ':' in spec:
        device_name = get_iface_from_hwaddr(nm_client, spec) or ""
        msg = "existing device found"
    # Specification by BOOTIF boot option
    elif spec == 'bootif':
        if bootif:
            device_name = get_iface_from_hwaddr(nm_client, bootif) or ""
            msg = "existing device for {} found".format(bootif)
        else:
            msg = "BOOTIF value is not specified in boot options"
    # First device with carrier (sorted lexicographically)
    elif spec == 'link':
        device_name = get_first_iface_with_link(nm_client, supported_devices) or ""
        msg = "first device with link found"

    if device_name:
        if device_name not in supported_devices:
            msg = "{} device found is not supported".format(device_name)
            device_name = ""
    # Virtual devices don't have to exist
    elif spec and any((network_data.vlanid,
                       network_data.bondslaves,
                       network_data.teamslaves,
                       network_data.bridgeslaves)):
        device_name = spec
        msg = "virtual device does not exist, which is OK"

    if network_data.vlanid:
        network_data.parent = device_name
        if network_data.interfacename:
            device_name = network_data.interfacename
            msg = "vlan device name specified by --interfacename"
        else:
            device_name = default_ks_vlan_interface_name(device_name, network_data.vlanid)
            msg = "vlan device name inferred from parent and vlanid"

    log.debug("kickstart specification --device=%s -> %s (%s)", spec, device_name, msg)
    return device_name


def _update_bond_connection_from_ksdata(connection, network_data):
    """Update connection with values from bond kickstart configuration.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    """
    s_con = connection.get_setting_connection()
    s_con.props.type = "bond"

    s_bond = NM.SettingBond.new()
    opts = network_data.bondopts
    for option in opts.split(';' if ';' in opts else ','):
        key, _sep, value = option.partition("=")
        if not s_bond.add_option(key, value):
            log.warning("adding bond option %s failed (invalid?)")
    connection.add_setting(s_bond)


def _update_team_connection_from_ksdata(connection, network_data):
    """Update connection with values from team kickstart configuration.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    """
    s_con = connection.get_setting_connection()
    s_con.props.type = "team"

    s_team = NM.SettingTeam.new()
    s_team.props.config = network_data.teamconfig
    connection.add_setting(s_team)


def _update_vlan_connection_from_ksdata(connection, network_data):
    """Update connection with values from vlan kickstart configuration.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    :returns: interface name of the device
    :rtype: str
    """
    s_con = connection.get_setting_connection()
    s_con.props.type = "vlan"
    if network_data.interfacename:
        s_con.props.id = network_data.interfacename
        s_con.props.interface_name = network_data.interfacename
    else:
        s_con.props.interface_name = None

    s_vlan = NM.SettingVlan.new()
    s_vlan.props.id = int(network_data.vlanid)
    s_vlan.props.parent = network_data.parent
    connection.add_setting(s_vlan)

    return s_con.props.interface_name


def _update_bridge_connection_from_ksdata(connection, network_data):
    """Update connection with values from bridge kickstart configuration.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    """
    s_con = connection.get_setting_connection()
    s_con.props.type = "bridge"

    s_bridge = NM.SettingBridge.new()
    for opt in network_data.bridgeopts.split(","):
        key, _sep, value = opt.partition("=")
        if key in ("stp", "multicast-snooping"):
            if value == "yes":
                value = True
            elif value == "no":
                value = False
        else:
            try:
                value = int(value)
            except ValueError:
                log.error("Invalid bridge option %s", opt)
                continue
        s_bridge.set_property(key, value)
    connection.add_setting(s_bridge)


def _update_infiniband_connection_from_ksdata(connection, network_data):
    """Update connection with values from infiniband kickstart configuration.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    """
    s_con = connection.get_setting_connection()
    s_con.props.type = "infiniband"

    s_ib = NM.SettingInfiniband.new()
    s_ib.props.transport_mode = "datagram"
    connection.add_setting(s_ib)


def _update_ethernet_connection_from_ksdata(connection, network_data, bound_mac):
    """Update connection with values from ethernet kickstart configuration.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    :param bound_mac: MAC address the device name is bound to (ifname=)
    :type bound_mac: str
    """
    s_con = connection.get_setting_connection()
    s_con.props.type = "802-3-ethernet"

    s_wired = NM.SettingWired.new()
    if bound_mac:
        s_wired.props.mac_address = bound_mac
    connection.add_setting(s_wired)


def _update_wired_connection_with_s390_settings(connection, s390cfg):
    """Update connection with values specific for s390 architecture.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param s390cfg: dictionary storing s390 specific settings
    :type s390cfg: dict
    """
    s_wired = connection.get_setting_wired()
    if s390cfg['SUBCHANNELS']:
        subchannels = s390cfg['SUBCHANNELS'].split(",")
        s_wired.props.s390_subchannels = subchannels
    if s390cfg['NETTYPE']:
        s_wired.props.s390_nettype = s390cfg['NETTYPE']
    if s390cfg['OPTIONS']:
        opts = s390cfg['OPTIONS'].split(" ")
        opts_dict = {k: v for k, v in (o.split("=") for o in opts)}
        s_wired.props.s390_options = opts_dict


def create_connections_from_ksdata(nm_client, network_data, device_name, ifname_option_values=None):
    """Create NM connections from kickstart configuration.

    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    :param device_name: name of the device to be configured by kickstart
    :type device_name: str
    :param ifname_option_values: list of ifname boot option values
    :type ifname_option_values: list(str)
    :return: list of tuples (CONNECTION, NAME_OF_DEVICE_TO_BE_ACTIVATED)
    :rtype: list((NM.RemoteConnection, str))
    """
    ifname_option_values = ifname_option_values or []
    connections = []
    device_to_activate = device_name

    con_uuid = NM.utils_uuid_generate()
    con = NM.SimpleConnection.new()

    update_connection_ip_settings_from_ksdata(con, network_data)

    s_con = NM.SettingConnection.new()
    s_con.props.uuid = con_uuid
    s_con.props.id = device_name
    s_con.props.interface_name = device_name
    s_con.props.autoconnect = network_data.onboot
    con.add_setting(s_con)

    # type "bond"
    if network_data.bondslaves:
        _update_bond_connection_from_ksdata(con, network_data)

        for i, slave in enumerate(network_data.bondslaves.split(","), 1):
            slave_con = create_slave_connection('bond', i, slave, device_name)
            bind_connection(nm_client, slave_con, network_data.bindto, slave)
            connections.append((slave_con, slave))

    # type "team"
    elif network_data.teamslaves:
        _update_team_connection_from_ksdata(con, network_data)

        for i, (slave, cfg) in enumerate(network_data.teamslaves, 1):
            s_team_port = NM.SettingTeamPort.new()
            s_team_port.props.config = cfg
            slave_con = create_slave_connection('team', i, slave, device_name,
                                                settings=[s_team_port])
            bind_connection(nm_client, slave_con, network_data.bindto, slave)
            connections.append((slave_con, slave))

    # type "vlan"
    elif network_data.vlanid:
        device_to_activate = _update_vlan_connection_from_ksdata(con, network_data)

    # type "bridge"
    elif network_data.bridgeslaves:
        # bridge connection is autoactivated
        _update_bridge_connection_from_ksdata(con, network_data)

        for i, slave in enumerate(network_data.bridgeslaves.split(","), 1):
            slave_con = create_slave_connection('bridge', i, slave, device_name)
            bind_connection(nm_client, slave_con, network_data.bindto, slave)
            connections.append((slave_con, slave))

    # type "infiniband"
    elif is_infiniband_device(nm_client, device_name):
        _update_infiniband_connection_from_ksdata(con, network_data)

    # type "802-3-ethernet"
    else:
        bound_mac = bound_hwaddr_of_device(nm_client, device_name, ifname_option_values)
        _update_ethernet_connection_from_ksdata(con, network_data, bound_mac)
        if bound_mac:
            log.debug("add connection: mac %s is bound to name %s",
                      bound_mac, device_name)
        else:
            bind_connection(nm_client, con, network_data.bindto, device_name)

        # Add s390 settings
        if is_s390():
            s390cfg = get_s390_settings(device_name)
            _update_wired_connection_with_s390_settings(con, s390cfg)

    connections.insert(0, (con, device_to_activate))

    return connections


def add_connection_from_ksdata(nm_client, network_data, device_name, activate=False,
                               ifname_option_values=None):
    """Add NM connection created from kickstart configuration.

    :param network_data: kickstart configuration
    :type network_data: pykickstart NetworkData
    :param device_name: name of the device to be configured by kickstart
    :type device_name: str
    :param activate: activate the added connection
    :type activate: bool
    :param ifname_option_values: list of ifname boot option values
    :type ifname_option_values: list(str)
    """
    connections = create_connections_from_ksdata(
        nm_client,
        network_data,
        device_name,
        ifname_option_values
    )

    for con, device_name in connections:
        log.debug("add connection: %s for %s\n%s", con.get_uuid(), device_name,
                  con.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))
        device_to_activate = device_name if activate else None
        nm_client.add_connection2(
            con.to_dbus(NM.ConnectionSerializationFlags.ALL),
            (NM.SettingsAddConnection2Flags.TO_DISK |
             NM.SettingsAddConnection2Flags.BLOCK_AUTOCONNECT),
            None,
            False,
            None,
            _connection_added_cb,
            device_to_activate
        )

    return connections


def _connection_added_cb(client, result, device_to_activate=None):
    """Finish asynchronous adding of a connection and activate eventually.

    :param device_to_activate: name of the device to be activated with the
                                added connection.
    :type device_to_activate: str
    """
    con, result = client.add_connection2_finish(result)
    log.debug("connection %s added:\n%s", con.get_uuid(),
              con.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))
    if device_to_activate:
        device = client.get_device_by_iface(device_to_activate)
        if device:
            log.debug("activating with device %s", device.get_iface())
        else:
            log.debug("activating without device specified (not found)")
        client.activate_connection_async(con, device, None, None)


def create_slave_connection(slave_type, slave_idx, slave, master, settings=None):
    """Create a slave NM connection for virtual connection (bond, team, bridge).

    :param slave_type: type of slave ("bond", "team", "bridge")
    :type slave_type: str
    :param slave_idx: index of the slave for naming
    :type slave_idx: int
    :param slave: slave's device name
    :type slave: str
    :param master: slave's master device name
    :type master: str
    :param settings: list of other settings to be added to the connection
    :type settings: list(NM.Setting)

    :return: created connection
    :rtype: NM.SimpleConnection
    """
    settings = settings or []
    slave_name = "%s slave %d" % (master, slave_idx)

    con = NM.SimpleConnection.new()
    s_con = NM.SettingConnection.new()
    s_con.props.uuid = NM.utils_uuid_generate()
    s_con.props.id = slave_name
    s_con.props.slave_type = slave_type
    s_con.props.master = master
    s_con.props.type = '802-3-ethernet'
    # HACK preventing NM to autoactivate the connection
    # The real network --onboot value (ifcfg ONBOOT) will be set later by
    # update_onboot
    s_con.props.autoconnect = False
    con.add_setting(s_con)

    s_wired = NM.SettingWired.new()
    con.add_setting(s_wired)

    for setting in settings:
        con.add_setting(setting)

    return con


def is_infiniband_device(nm_client, device_name):
    """Is the type of the device infiniband?"""
    device = nm_client.get_device_by_iface(device_name)
    if device and device.get_device_type() == NM.DeviceType.INFINIBAND:
        return True
    return False


def is_ibft_connection(connection):
    """Is the connection generated by NM from iBFT?"""
    return connection.get_id().startswith("iBFT Connection")


def bound_hwaddr_of_device(nm_client, device_name, ifname_option_values):
    """Check and return mac address of device bound by device renaming.

    For example ifname=ens3:f4:ce:46:2c:44:7a should bind the device name ens3
    to the MAC address (and rename the device in initramfs eventually).  If
    hwaddress of the device devname is the same as the MAC address, its value
    is returned.

    :param device_name: device name
    :type device_name: str
    :param ifname_option_values: list of ifname boot option values
    :type ifname_option_values: list(str)
    :return: hwaddress of the device if bound, or None
    :rtype: str or None
    """
    for ifname_value in ifname_option_values:
        iface, mac = ifname_value.split(":", 1)
        if iface == device_name:
            if iface == get_iface_from_hwaddr(nm_client, mac):
                return mac.upper()
            else:
                log.warning("MAC address of ifname %s does not correspond to ifname=%s",
                            iface, ifname_value)
    return None


def update_connection_from_ksdata(nm_client, connection, network_data, device_name=None):
    """Update NM connection specified by uuid from kickstart configuration.

    :param connection: existing NetworkManager connection to be updated
    :type connection: NM.RemoteConnection
    :param network_data: kickstart network configuration
    :type network_data: pykickstart NetworkData
    :param device_name: device name the connection should be bound to eventually
    :type device_name: str
    """
    log.debug("updating connection %s:\n%s", connection.get_uuid(),
              connection.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))

    # IP configuration
    update_connection_ip_settings_from_ksdata(connection, network_data)

    s_con = connection.get_setting_connection()
    s_con.set_property(NM.SETTING_CONNECTION_AUTOCONNECT, network_data.onboot)

    bind_connection(nm_client, connection, network_data.bindto, device_name)

    commit_changes_with_autoconnection_blocked(connection)

    log.debug("updated connection %s:\n%s", connection.get_uuid(),
              connection.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS))


def update_connection_ip_settings_from_ksdata(connection, network_data):
    """Update NM connection from kickstart IP configuration in place.

    :param connection: existing NetworkManager connection to be updated
    :type connection: NM.RemoteConnection
    :param network_data: kickstart configuation containing the IP configuration
                            to be applied to the connection
    :type network_data: pykickstart NetworkData
    """
    # ipv4 settings
    if network_data.noipv4:
        method4 = "disabled"
    elif network_data.bootProto == "static":
        method4 = "manual"
    else:
        method4 = "auto"

    connection.remove_setting(NM.SettingIP4Config)
    s_ip4 = NM.SettingIP4Config.new()
    s_ip4.set_property(NM.SETTING_IP_CONFIG_METHOD, method4)
    if method4 == "manual":
        prefix4 = netmask2prefix(network_data.netmask)
        addr4 = NM.IPAddress.new(socket.AF_INET, network_data.ip, prefix4)
        s_ip4.add_address(addr4)
        if network_data.gateway:
            s_ip4.props.gateway = network_data.gateway
    connection.add_setting(s_ip4)

    # ipv6 settings
    if network_data.noipv6:
        method6 = "ignore"
    elif not network_data.ipv6 or network_data.ipv6 == "auto":
        method6 = "auto"
    elif network_data.ipv6 == "dhcp":
        method6 = "dhcp"
    else:
        method6 = "manual"

    connection.remove_setting(NM.SettingIP6Config)
    s_ip6 = NM.SettingIP6Config.new()
    s_ip6.set_property(NM.SETTING_IP_CONFIG_METHOD, method6)
    if method6 == "manual":
        addr6, _slash, prefix6 = network_data.ipv6.partition("/")
        if prefix6:
            prefix6 = int(prefix6)
        else:
            prefix6 = 64
        addr6 = NM.IPAddress.new(socket.AF_INET6, addr6, prefix6)
        s_ip6.add_address(addr6)
        if network_data.ipv6gateway:
            s_ip6.props.gateway = network_data.ipv6gateway
    connection.add_setting(s_ip6)

    # nameservers
    if network_data.nameserver:
        for ns in [str.strip(i) for i in network_data.nameserver.split(",")]:
            if NM.utils_ipaddr_valid(socket.AF_INET6, ns):
                s_ip6.add_dns(ns)
            elif NM.utils_ipaddr_valid(socket.AF_INET, ns):
                s_ip4.add_dns(ns)
            else:
                log.error("IP address %s is not valid", ns)


def bind_settings_to_mac(nm_client, s_connection, s_wired, device_name=None, bind_exclusively=True):
    """Bind the settings to the mac address of the device.

    :param s_connection: connection setting to be updated
    :type s_connection: NM.SettingConnection
    :param s_wired: wired setting to be updated
    :type s_wired: NM.SettingWired
    :param device_name: name of the device to be bound
    :type device_name: str
    :param bind_exclusively: remove reference to the device name from the settings
    :type bind_exclusively: bool
    :returns: True if the settings were modified, False otherwise
    :rtype: bool
    """
    mac_address = s_wired.get_mac_address()
    interface_name = s_connection.get_interface_name()
    modified = False

    if mac_address:
        log.debug("Bind to mac: already bound to %s", mac_address)
    else:
        iface = device_name or interface_name
        if not iface:
            log.warning("Bind to mac: no device name provided to look for mac")
            return False
        device = nm_client.get_device_by_iface(iface)
        if device:
            hwaddr = device.get_permanent_hw_address() or device.get_hw_address()
            s_wired.props.mac_address = hwaddr
            log.debug("Bind to mac: bound to %s", hwaddr)
            modified = True

    if bind_exclusively and interface_name:
        s_connection.props.interface_name = None
        log.debug("Bind to mac: removed interface-name %s from connection", interface_name)
        modified = True

    return modified


def bind_settings_to_device(nm_client, s_connection, s_wired, device_name=None,
                            bind_exclusively=True):
    """Bind the settings to the name of the device.

    :param s_connection: connection setting to be updated
    :type s_connection: NM.SettingConnection
    :param s_wired: wired setting to be updated
    :type s_wired: NM.SettingWired
    :param device_name: name of the device to be bound
    :type device_name: str
    :param bind_exclusively: remove reference to the mac address from the settings
    :type bind_exclusively: bool
    :returns: True if the settings were modified, False otherwise
    :rtype: bool
    """
    mac_address = s_wired.get_mac_address()
    interface_name = s_connection.get_interface_name()
    modified = False

    if device_name:
        s_connection.props.interface_name = device_name
        log.debug("Bind to device: %s -> %s", interface_name, device_name)
        modified = interface_name != device_name
    else:
        if not interface_name:
            log.debug("Bind to device: no device to bind to")
            return False
        else:
            log.debug("Bind to device: already bound to %s", interface_name)

    if bind_exclusively and mac_address:
        s_wired.props.mac_address = None
        log.debug("Bind to device: removed mac-address from connection")
        modified = True

    return modified


def bind_connection(nm_client, connection, bindto, device_name=None, bind_exclusively=True):
    """Bind the connection to device name or mac address.

    :param connection: connection to be updated before adding to NM
    :type connection: NM.SimpleConnection
    :param bindto: type of binding of the connection (mac address of device name)
                    - BIND_TO_MAC for mac address
                    - None for device name (default)
    :type bindto: pykickstart --bindto constant
    :param device_name: device name for binding
    :type device_name: str
    :param bind_exclusively: when binding to an entity, remove reference to the other
    :type bind_exclusively: bool
    :returns: True if the connection was modified, False otherwise
    :rtype: bool
    """
    msg = "Bind connection {} to {}:".format(connection.get_uuid(), bindto or "iface")

    s_con = connection.get_setting_connection()
    if not s_con:
        log.warning("%s no connection settings, bailing", msg)
        return False
    s_wired = connection.get_setting_wired()

    if bindto == BIND_TO_MAC:
        if not s_wired:
            log.warning("%s no wired settings, bailing", msg)
            return False
        modified = bind_settings_to_mac(nm_client, s_con, s_wired, device_name, bind_exclusively)
    else:
        modified = bind_settings_to_device(nm_client, s_con, s_wired, device_name, bind_exclusively)

    return modified


def ensure_active_connection_for_device(nm_client, uuid, device_name, only_replace=False):
    """Make sure active connection of a device is the one specified by uuid.

    :param uuid: uuid of the connection to be applied
    :type uuid: str
    :param device_name: name of device to apply the connection to
    :type device_name: str
    :param only_replace: apply the connection only if the device has different
                         active connection
    :type only_replace: bool
    """
    activated = False
    active_uuid = None
    device = nm_client.get_device_by_iface(device_name)
    if device:
        ac = device.get_active_connection()
        if ac or not only_replace:
            active_uuid = ac.get_uuid() if ac else None
            if uuid != active_uuid:
                ifcfg_con = nm_client.get_connection_by_uuid(uuid)
                if ifcfg_con:
                    activate_connection_sync(nm_client, ifcfg_con, None)
                    activated = True
    msg = "activated" if activated else "not activated"
    log.debug("ensure active ifcfg connection for %s (%s -> %s): %s",
              device_name, active_uuid, uuid, msg)
    return activated


def get_connections_available_for_iface(nm_client, iface):
    """Get all connections available for given interface.

    :param iface: interface name
    :type iface: str
    :return: list of all available connections
    :rtype: list(NM.RemoteConnection)
    """
    cons = []
    device = nm_client.get_device_by_iface(iface)
    if device:
        cons = device.get_available_connections()
    else:
        # Try also non-existing (not real) virtual devices
        for device in nm_client.get_all_devices():
            if not device.is_real() and device.get_iface() == iface:
                cons = device.get_available_connections()
                if cons:
                    break
        else:
            # Getting available connections does not seem to work quite well for
            # non-real team - try to look them up in all connections.
            for con in nm_client.get_connections():
                interface_name = con.get_interface_name()
                if not interface_name and con.get_connection_type() == "vlan":
                    interface_name = get_vlan_interface_name_from_connection(nm_client, con)
                if interface_name == iface:
                    cons.append(con)

    return cons


def update_connection_values(connection, new_values):
    """Update setting values of a connection.

    :param connection: existing NetworkManager connection to be updated
    :type connection: NM.RemoteConnection
    :param new_values: list of properties to be updated
    :type new_values: [(SETTING_NAME, SETTING_PROPERTY, VALUE)]
    """
    for setting_name, setting_property, value in new_values:
        setting = connection.get_setting_by_name(setting_name)
        if setting:
            setting.set_property(setting_property, value)
            log.debug("updating connection %s setting '%s' '%s' to '%s'",
                      connection.get_uuid(), setting_name, setting_property, value)
        else:
            log.debug("setting '%s' not found while updating connection %s",
                      setting_name, connection.get_uuid())
    log.debug("updated connection %s:\n%s", connection.get_uuid(),
              connection.to_dbus(NM.ConnectionSerializationFlags.ALL))


def devices_ignore_ipv6(nm_client, device_types):
    """All connections of devices of given type ignore ipv6."""
    device_types = device_types or []
    for device in nm_client.get_devices():
        if device.get_device_type() in device_types:
            cons = device.get_available_connections()
            for con in cons:
                s_ipv6 = con.get_setting_ip6_config()
                if s_ipv6 and s_ipv6.get_method() != NM.SETTING_IP6_CONFIG_METHOD_IGNORE:
                    return False
    return True


def get_first_iface_with_link(nm_client, ifaces):
    """Find first iface having link (in lexicographical order)."""
    for iface in sorted(ifaces):
        device = nm_client.get_device_by_iface(iface)
        if device and device.get_carrier():
            return device.get_iface()
    return None


def get_connections_dump(nm_client):
    """Dumps all connections for logging."""
    con_dumps = []
    for con in nm_client.get_connections():
        con_dumps.append(str(con.to_dbus(NM.ConnectionSerializationFlags.NO_SECRETS)))
    return "\n".join(con_dumps)


def commit_changes_with_autoconnection_blocked(connection, save_to_disk=True):
    """Implementation of NM CommitChanges() method with blocked autoconnection.

    Update2() API is used to implement the functionality (called synchronously).

    Prevents autoactivation of the connection on its update which would happen
    with CommitChanges if "autoconnect" is set True.

    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param save_to_disk: should the changes be written also to disk?
    :type save_to_disk: bool
    :return: on success result of the Update2() call, None of failure
    :rtype: GVariant of type "a{sv}" or None
    """
    sync_queue = Queue()

    def finish_callback(connection, result, sync_queue):
        ret = connection.update2_finish(result)
        sync_queue.put(ret)

    flags = NM.SettingsUpdate2Flags.BLOCK_AUTOCONNECT
    if save_to_disk:
        flags |= NM.SettingsUpdate2Flags.TO_DISK

    con2 = NM.SimpleConnection.new_clone(connection)
    connection.update2(
        con2.to_dbus(NM.ConnectionSerializationFlags.ALL),
        flags,
        None,
        None,
        finish_callback,
        sync_queue
    )

    return sync_queue.get()


def activate_connection_sync(nm_client, connection, device):
    """Activate a connection synchronously.

    Synchronous wrapper of ActivateConnection() NM method.

    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param device: the preferred device to apply the connection to
                   None if not needed
    :type device: NM.Device
    """
    sync_queue = Queue()

    def finish_callback(nm_client, result, sync_queue):
        ret = nm_client.activate_connection_finish(result)
        sync_queue.put(ret)

    nm_client.activate_connection_async(
        connection,
        device,
        None,
        None,
        finish_callback,
        sync_queue
    )

    try:
        ret = sync_queue.get(timeout=CONNECTION_ACTIVATION_TIMEOUT)
    except Empty:
        log.error("Activation of a connection timed out.")
        ret = None

    return ret


def get_dracut_arguments_from_connection(nm_client, connection, iface, target_ip,
                                         hostname, ibft=False):
    """Get dracut arguments for the iface and SAN target from NM connection.

    Examples of SAN: iSCSI, FCoE

    The dracut arguments would activate the iface in initramfs so that the
    SAN target can be attached (usually to mount root filesystem).

    :param nm_client: instance of NetworkManager client
    :type nm_client: NM.Client
    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param iface: network interface used to connect to the target
                  (can be none if ibft is used)
    :type iface: str
    :param target_ip: IP of the SAN target
    :type target_ip: str
    :param hostname: static hostname to be configured
    :type hostname: str
    :param ibft: network should be configured from ibft
    :type ibft: bool
    :returns: dracut arguments
    :rtype: set(str)
    """
    netargs = set()

    if ibft:
        netargs.add("rd.iscsi.ibft")
    elif target_ip:
        if hostname is None:
            hostname = ""
        if ':' in target_ip:
            # Using IPv6 target IP
            ipv6_arg = _get_dracut_ipv6_argument(connection, iface, hostname)
            if ipv6_arg:
                netargs.add(ipv6_arg)
            else:
                log.error("No IPv6 configuration found in connection %s", connection.get_uuid())
        else:
            # Using IPv4 target IP
            ipv4_arg = _get_dracut_ipv4_argument(connection, iface, hostname)
            if ipv4_arg:
                netargs.add(ipv4_arg)
            else:
                log.error("No IPv4 configuration found in connection %s", connection.get_uuid())

        ifname_arg = _get_dracut_ifname_argument_from_connection(connection, iface)
        if ifname_arg:
            netargs.add(ifname_arg)

        team_arg = _get_dracut_team_argument_from_connection(nm_client, connection, iface)
        if team_arg:
            netargs.add(team_arg)

        vlan_arg, vlan_parent_connection = _get_dracut_vlan_argument_from_connection(nm_client,
                                                                                     connection,
                                                                                     iface)
        if vlan_arg:
            netargs.add(vlan_arg)
        # For vlan the parent connection defines the s390 znet argument values
        if vlan_parent_connection:
            connection = vlan_parent_connection

    znet_arg = _get_dracut_znet_argument_from_connection(connection)
    if znet_arg:
        netargs.add(znet_arg)

    return netargs


def _get_dracut_ipv6_argument(connection, iface, hostname):
    """Get dracut ip IPv6 configuration for given interface and NM connection.

    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param iface: network interface to be used
    :type iface: str
    :param hostname: static hostname to be configured
    :type hostname: str
    :returns: dracut ip argument or "" if the configuration can't be find
    :rtype: set(str)
    """
    argument = ""
    ip6_config = connection.get_setting_ip6_config()
    ip6_method = ip6_config.get_method()
    if ip6_method == NM.SETTING_IP6_CONFIG_METHOD_AUTO:
        argument = "ip={}:auto6".format(iface)
    elif ip6_method == NM.SETTING_IP6_CONFIG_METHOD_DHCP:
        # Most probably not working
        argument = "ip={}:dhcp6".format(iface)
    elif ip6_method == NM.SETTING_IP6_CONFIG_METHOD_MANUAL:
        ipaddr = ""
        if ip6_config.get_num_addresses() > 0:
            addr = ip6_config.get_address(0)
            ipaddr = "[{}/{}]".format(addr.get_address(), addr.get_prefix())
        gateway = ip6_config.get_gateway() or ""
        if gateway:
            gateway = "[{}]".format(gateway)
        if ipaddr or gateway:
            argument = ("ip={}::{}::{}:{}:none".format(ipaddr, gateway, hostname, iface))
    return argument


def _get_dracut_ipv4_argument(connection, iface, hostname):
    """Get dracut ip IPv4 configuration for given interface and NM connection.

    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param iface: network interface to be used
    :type iface: str
    :param hostname: static hostname to be configured
    :type hostname: str
    :returns: dracut ip argument or "" if the configuration can't be find
    :rtype: str
    """
    argument = ""
    ip4_config = connection.get_setting_ip4_config()
    ip4_method = ip4_config.get_method()
    if ip4_method == NM.SETTING_IP4_CONFIG_METHOD_AUTO:
        argument = "ip={}:dhcp".format(iface)
    elif ip4_method == NM.SETTING_IP4_CONFIG_METHOD_MANUAL:
        if ip4_config.get_num_addresses() > 0:
            addr = ip4_config.get_address(0)
            ip = addr.get_address()
            netmask = prefix2netmask(addr.get_prefix())
            gateway = ip4_config.get_gateway() or ""
            argument = "ip={}::{}:{}:{}:{}:none".format(ip, gateway, netmask, hostname, iface)
    return argument


def _get_dracut_ifname_argument_from_connection(connection, iface):
    """Get dracut ifname configuration for given interface and NM connection.

    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param iface: network interface to be used
    :type iface: str
    :returns: dracut ifname argument or "" if the configuration does not apply
    :rtype: str
    """
    argument = ""
    wired_setting = connection.get_setting_wired()
    if wired_setting:
        hwaddr = wired_setting.get_mac_address()
        if hwaddr:
            argument = "ifname={}:{}".format(iface, hwaddr.lower())
    return argument


def _get_dracut_team_argument_from_connection(nm_client, connection, iface):
    """Get dracut team configuration for given interface and NM connection.

    :param nm_client: instance of NetworkManager client
    :type nm_client: NM.Client
    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param iface: network interface to be used
    :type iface: str
    :returns: dracut team argument or "" if the configuration does not apply
    :rtype: str
    """
    argument = ""
    if connection.get_connection_type() == "team":
        slaves = sorted(get_slaves_from_connections(
            nm_client,
            "team",
            [iface, connection.get_uuid()]
        ))
        argument = "team={}:{}".format(iface, ",".join(s_iface for s_iface, _uuid in slaves))
    return argument


def _get_dracut_vlan_argument_from_connection(nm_client, connection, iface):
    """Get dracut vlan configuration for given interface and NM connection.

    Returns also parent vlan connection.

    :param nm_client: instance of NetworkManager client
    :type nm_client: NM.Client
    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :param iface: network interface to be used
    :type iface: str
    :returns: tuple (ARGUMENT, PARENT_CONNECTION) where
              ARGUMENT is dracut vlan argument or "" if the configuration does not apply
              PARENT_CONNECTION is vlan parent connection of the connection
    :rtype: tuple(str, NM.RemoteConnection)
    """
    argument = ""
    parent_con = None
    if connection.get_connection_type() == "vlan":
        setting_vlan = connection.get_setting_vlan()
        parent_spec = setting_vlan.get_parent()
        parent = None
        # parent can be specified by connection uuid (eg from nm-c-e)
        if len(parent_spec) == NM_CONNECTION_UUID_LENGTH:
            parent_con = nm_client.get_connection_by_uuid(parent_spec)
            if parent_con:
                # On s390 with net.ifnames=0 there is no DEVICE so use NAME
                parent = parent_con.get_interface_name() or parent_con.get_id()
        # parent can be specified by interface
        else:
            parent = parent_spec
            parent_cons = get_connections_available_for_iface(nm_client, parent)
            if len(parent_cons) != 1:
                log.error("unexpected number of connections found for vlan parent %s",
                          parent_spec)
            if parent_cons:
                parent_con = parent_cons[0]

        if parent:
            argument = "vlan={}:{}".format(iface, parent)
        else:
            log.error("can't find parent interface of vlan device %s specified by %s",
                      iface, parent_spec)
        if not parent_con:
            log.error("can't find parent connection of vlan device %s specified by %s",
                      iface, parent_spec)

    return argument, parent_con


def _get_dracut_znet_argument_from_connection(connection):
    """Get dracut znet (s390) configuration for given NM connection.

    :param connection: NetworkManager connection
    :type connection: NM.RemoteConnection
    :returns: dracut znet argument or "" if the configuration does not apply
    :rtype: str
    """
    argument = ""
    wired_setting = connection.get_setting_wired()
    if wired_setting and is_s390():
        nettype = wired_setting.get_s390_nettype()
        subchannels = wired_setting.get_s390_subchannels()
        if nettype and subchannels:
            argument = "rd.znet={},{}".format(nettype, subchannels)
            options = wired_setting.get_property(NM.SETTING_WIRED_S390_OPTIONS)
            if options:
                options_string = ','.join("{}={}".format(key, val) for key, val in options.items())
                argument += ",{}".format(options_string)
    return argument


def get_slaves_from_connections(nm_client, slave_type, master_specs):
    """Get slaves of master of given type specified by uuid or interface.

    :param nm_client: instance of NetworkManager client
    :type nm_client: NM.Client
    :param slave_type: type of the slave - NM setting "slave-type" value (eg. "team")
    :type slave_type: str
    :param master_specs: a list containing sepcification of master:
                         interface name or connection uuid or both
    :type master_specs: list(str)
    :returns: slaves specified by interface and connection uuid
    :rtype: set((str,str))
    """
    slaves = set()
    for con in nm_client.get_connections():
        if not con.get_setting_connection().get_slave_type() == slave_type:
            continue
        if con.get_setting_connection().get_master() in master_specs:
            iface = get_iface_from_connection(nm_client, con.get_uuid())
            if iface:
                slaves.add((iface, con.get_uuid()))
    return slaves

Youez - 2016 - github.com/yon3zu
LinuXploit