Compare commits
1806 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a8479cd85 | |||
| f3449882b3 | |||
| 8f3b04bd1a | |||
| abbd20549a | |||
| a487eeda81 | |||
| e0ff38a38a | |||
| e75be5fe88 | |||
| c822d4f560 | |||
| 4d262b0db4 | |||
| fe545184b5 | |||
| 2709ec4d25 | |||
| 4c88b1b469 | |||
| 95a3d8ef3c | |||
| 8be3e23145 | |||
| 435e989da4 | |||
| 36c2404d1c | |||
| 9f9768fd28 | |||
| 194b864487 | |||
| eb3e5aaee0 | |||
| 0297069b71 | |||
| 054ef6d125 | |||
| ec8a2069cd | |||
| e60212cfb8 | |||
| dba2219b18 | |||
| 5694147a73 | |||
| d183a0bb9d | |||
| 021b4c69fb | |||
| 8fcfccb42f | |||
| 3fa9fd3e7b | |||
| 17aa3f84ac | |||
| 5a3847d3ea | |||
| 737550e69b | |||
| 25f7bb326e | |||
| 398e63f180 | |||
| 0a45d0bcf9 | |||
| 1535113fb1 | |||
| 43fefadf30 | |||
| b186280ab8 | |||
| 373cc13aa0 | |||
| 12f1819180 | |||
| b96b2d0ec9 | |||
| ff619264a4 | |||
| 3bac60fac8 | |||
| 4aafb62e16 | |||
| eab4fced6a | |||
| bd7a9096b2 | |||
| 9c3ed358b4 | |||
| c2b6d4def1 | |||
| 221a6854b7 | |||
| 149f0fd277 | |||
| 81dc649a24 | |||
| a0dc770139 | |||
| 7ad5cf800d | |||
| 0bd4753702 | |||
| 9a2305dd3a | |||
| a5ff9cfeec | |||
| 707f0c315b | |||
| 596aadcd3e | |||
| 83732b7b5d | |||
| 2a65930be9 | |||
| 120312c5ea | |||
| 5529a93267 | |||
| 79d7b55208 | |||
| c55655a50c | |||
| 6cf827b891 | |||
| 3f08f410fe | |||
| 3eaf383163 | |||
| 7f63cf564c | |||
| 6f79aead61 | |||
| df3239cbb5 | |||
| 50fed0a17a | |||
| 9ae698fb70 | |||
| dcaef3f2eb | |||
| 5fc7fe289e | |||
| 2c49eb1195 | |||
| 770e8a7301 | |||
| 25e02c8b73 | |||
| ddcec671a0 | |||
| 62cdefa219 | |||
| 655148ffdd | |||
| 24da10e021 | |||
| acc07123e9 | |||
| 89c649ae56 | |||
| dbf362ea52 | |||
| 77f1e2452e | |||
| d3f205440a | |||
| dd1eaab04c | |||
| cc955a172b | |||
| 4323842e28 | |||
| 376c57d74e | |||
| 127934c3d3 | |||
| 1ded53ae14 | |||
| 35ed43d06b | |||
| 5a8d12715a | |||
| 72abb182bb | |||
| c8ebe8a9df | |||
| 555810f7ed | |||
| aff04efce8 | |||
| d3c808f75f | |||
| f4cc23ef0f | |||
| 82d9b5b9ef | |||
| 971808efbd | |||
| bf27c3ac96 | |||
| e9f220cecc | |||
| 6be8450b9b | |||
| aecc720d7d | |||
| 9893a2dd71 | |||
| c464e3c1d6 | |||
| 43f9eb6384 | |||
| a7867e1370 | |||
| 8751f25154 | |||
| 316470c60d | |||
| bccae8efe7 | |||
| 49d53ed922 | |||
| 681ec3c968 | |||
| d122c8a3fa | |||
| 318cf6bfa8 | |||
| 8f6bbd40d9 | |||
| 78d3e285a6 | |||
| cd8389984f | |||
| a5e378a641 | |||
| 4abeecbd03 | |||
| ef589ec580 | |||
| f3392ba1ee | |||
| ec5de72ee4 | |||
| c58f440db1 | |||
| 29c8b4216b | |||
| 61a686acac | |||
| 242b39ace6 | |||
| 1607a1dac6 | |||
| d5695f5727 | |||
| 539f37f391 | |||
| 86e663860d | |||
| b77b8e7c7d | |||
| e251f0a2cf | |||
| aea43684c3 | |||
| 54982068cf | |||
| 84bc552130 | |||
| 56e8e8b0d5 | |||
| 2e0ccb7d7e | |||
| e331cf5085 | |||
| 4c031e1806 | |||
| 542259583c | |||
| c159000f94 | |||
| 2598e30ee1 | |||
| 9db5ceef6a | |||
| 1a59531d6c | |||
| cdf72640fd | |||
| d45ba76f8e | |||
| 8ced46f7cc | |||
| e16e4d327b | |||
| 22b529f8e3 | |||
| d0e85aeee2 | |||
| 1b6225b820 | |||
| 26d8a9b4a5 | |||
| c2e2cefd9f | |||
| 35b919185e | |||
| 540e11c599 | |||
| 14b61f339d | |||
| 72acb3b564 | |||
| 352f12aaee | |||
| 8987ad4702 | |||
| c58b291e98 | |||
| ea0241e836 | |||
| 8aa878427e | |||
| 8bc490094a | |||
| 76a60547ff | |||
| 751f3c4b89 | |||
| 6b40d076fa | |||
| 98bc658385 | |||
| 84ee1eb9f1 | |||
| 9e91cf4f63 | |||
| af305e1c65 | |||
| 2b8f1c5086 | |||
| 29b7e4331b | |||
| b7a04d3c94 | |||
| 9c0fa6a8bb | |||
| 80d4cf913b | |||
| 56556bdeec | |||
| 7f39eb7fe4 | |||
| d25680575d | |||
| c2c29970ff | |||
| dd8096b39f | |||
| 91b4041a3c | |||
| 466d5f0a9f | |||
| 7032988d7f | |||
| ac83cbe428 | |||
| 65470149e9 | |||
| 179a62145b | |||
| a3d6555515 | |||
| 9db688423c | |||
| 0f829608d1 | |||
| ae62c9e403 | |||
| 2825e469fe | |||
| 4c74a94daf | |||
| 9374e01b76 | |||
| 5a9abe2acf | |||
| edf9a4dc64 | |||
| e299342956 | |||
| b26b5c42bd | |||
| d5cfab0c97 | |||
| addd4ed9c4 | |||
| 6ffaad98d1 | |||
| fa236764e1 | |||
| 225a2564bd | |||
| 542a3dbbe4 | |||
| 407bef3e3d | |||
| ad6649144c | |||
| 60f33728d2 | |||
| 9908a8156c | |||
| 9cb232d069 | |||
| cc207c5ecd | |||
| 584fe221c2 | |||
| e86917e218 | |||
| 481a93554f | |||
| 894bdb17e7 | |||
| 9164cf83a3 | |||
| f93a5eb28b | |||
| caafd03ca0 | |||
| 0fab0368ec | |||
| 35376641b4 | |||
| dd3f08682f | |||
| b58e374758 | |||
| e5bde95310 | |||
| a4e0952b6c | |||
| 24215114c6 | |||
| e01827f9d3 | |||
| 23c464cbe8 | |||
| 3b1d444077 | |||
| 835ab6b592 | |||
| 9e81eccc66 | |||
| 41a16bb370 | |||
| 99802e8a09 | |||
| 69e5f3abf6 | |||
| 9976df95e9 | |||
| adf723db25 | |||
| 23b836102a | |||
| e02a913e86 | |||
| ee812a995f | |||
| 23a51d7bbb | |||
| 69833876fa | |||
| e87604fd5f | |||
| bb4fa36b29 | |||
| adb04f1651 | |||
| 0723ce1117 | |||
| 66bb1bc712 | |||
| 2cca891e35 | |||
| e7dc46a03a | |||
| 0599847898 | |||
| 553ecb83d2 | |||
| 05946f11db | |||
| 9383ceca98 | |||
| 3b1900c52d | |||
| 3221fed0da | |||
| cf371f30e7 | |||
| 045f334d33 | |||
| 0c911a96a3 | |||
| 85d9803221 | |||
| c60e45b4b2 | |||
| b63193149d | |||
| 01f621ee32 | |||
| 17b7ee559a | |||
| 62a0cb6350 | |||
| a2aee1a0bb | |||
| 921d251301 | |||
| b12771ab54 | |||
| 623ccadcc0 | |||
| 71213c8719 | |||
| 8b38c35e63 | |||
| 1e3062d8e4 | |||
| 06af9c15a1 | |||
| bd36de6f1b | |||
| f75d136828 | |||
| 8eb9348c51 | |||
| b014538601 | |||
| abea7eceee | |||
| 412f3b51c6 | |||
| 2f17a10f92 | |||
| c4170ce728 | |||
| 69fbb8add5 | |||
| a2d494c501 | |||
| f7812a2517 | |||
| 91347e0a9b | |||
| b3af99e178 | |||
| 78bde6f6f7 | |||
| 0851987c3b | |||
| 7c81f38a80 | |||
| 9b5ad5113e | |||
| 8b71e68c68 | |||
| ca73b902f1 | |||
| 22e3c40f09 | |||
| 5585b97e18 | |||
| 55f981ea47 | |||
| f8bb5e4b50 | |||
| 7c45a82a53 | |||
| 7a8b802a86 | |||
| 7ab60cf654 | |||
| 663a0b7da8 | |||
| 2dd2518120 | |||
| e2688d0211 | |||
| f4b432b9ab | |||
| b952e390f2 | |||
| b4ab8a1b4c | |||
| 94ca59d560 | |||
| 7f5465e80f | |||
| 75f28121ec | |||
| 1170cda7f4 | |||
| c78350a9bf | |||
| 0d00b1be94 | |||
| 810c5324b5 | |||
| 6dd972fd50 | |||
| 9c24bcf48b | |||
| 20ec000e77 | |||
| ef5ec3c17c | |||
| 75fbe70734 | |||
| 7abd27fbfe | |||
| e2672df777 | |||
| 4e4ea3c0a2 | |||
| 794ca69b97 | |||
| d21d6271cc | |||
| 0585d387fb | |||
| f02239bf29 | |||
| 5570ab24cf | |||
| 05f5636ebc | |||
| 14ac0776d0 | |||
| 2ce177d155 | |||
| b19f226801 | |||
| cd984f7c51 | |||
| 8bc0488764 | |||
| a8ba71961f | |||
| a2a8bbf514 | |||
| 49cda4ba0f | |||
| f132ece7be | |||
| 9fbd6a0f7d | |||
| a3cad111de | |||
| 3b9be43df8 | |||
| 9799071116 | |||
| f1311c0aa8 | |||
| f77e980e2e | |||
| 7e66fc5072 | |||
| e52df92352 | |||
| 0a4d9fd9bc | |||
| 0bf9efc290 | |||
| 6da15f4770 | |||
| 6f9f434b4a | |||
| f475c143e9 | |||
| c010a68bb3 | |||
| 2afe367b20 | |||
| e770d4b6dc | |||
| 00f940d48b | |||
| 88cbc07d96 | |||
| 039cf57962 | |||
| efb4906c68 | |||
| bfca7b0bb7 | |||
| 80b54be58e | |||
| 2f930993c0 | |||
| 3dccc94696 | |||
| 5509f6ab48 | |||
| 1e40a422b1 | |||
| b9ef6a4282 | |||
| 5669c23ff1 | |||
| b91d6cd875 | |||
| 712ac48e82 | |||
| 3a4b586ea9 | |||
| 5be4fab2b3 | |||
| c7fbdf4626 | |||
| 9dabf11cd4 | |||
| a11fd07dbc | |||
| 3698609370 | |||
| d8f6d1a6b4 | |||
| d3894733bd | |||
| 3bd9fbc891 | |||
| ad7916eba0 | |||
| a3040af400 | |||
| efb4565f32 | |||
| 9ab47e362f | |||
| d1066357b4 | |||
| b91db176cd | |||
| c2e30cadf2 | |||
| 253c365f3c | |||
| 1fbcfd4785 | |||
| 5249e76e70 | |||
| 4e47350c59 | |||
| 3c1268bc75 | |||
| 2ef2f3d77b | |||
| dae22d2531 | |||
| 40ea9ba362 | |||
| 88926480a2 | |||
| 7ba5977869 | |||
| b33e239dc1 | |||
| 4624c6b9fa | |||
| 957403a1d2 | |||
| adae06ce7b | |||
| 53302a77ed | |||
| 4fb578678c | |||
| d863097b05 | |||
| dcefc401c7 | |||
| 128c35fa74 | |||
| dee77954a1 | |||
| 72b9ac43c7 | |||
| fc3d050265 | |||
| 67c66abb1e | |||
| 4904b08a78 | |||
| 9f1fd6c223 | |||
| 36e4842a1c | |||
| 7b57d0ba6c | |||
| 5e8d0c91e3 | |||
| 23905cb311 | |||
| ae1241c0b2 | |||
| c76c88f0e2 | |||
| 79f90a33a8 | |||
| e727395b75 | |||
| 0bd4a8fc81 | |||
| 6f1ff7a924 | |||
| b5589691a9 | |||
| 4cf04607d1 | |||
| ec3fa3a7ec | |||
| d526bbaaa8 | |||
| 195bd69ab2 | |||
| 0e54237c42 | |||
| 213556c27f | |||
| 3477b1f7a1 | |||
| 13e7903b43 | |||
| 2b7def707f | |||
| 0eb918b7bd | |||
| cac2677c1c | |||
| 3664f1d5c3 | |||
| 08accdf517 | |||
| 952ff38ce4 | |||
| fbce5a6a00 | |||
| abbbe735b5 | |||
| b0ddf05865 | |||
| 908efae0ba | |||
| ec85d06117 | |||
| 0d827b59ab | |||
| 3be3d26ac3 | |||
| 8ecf88438c | |||
| 0c7e33c045 | |||
| 428058af5a | |||
| 06fe33434a | |||
| bb351003dc | |||
| bd899691b0 | |||
| 7cab5a1f41 | |||
| dc9dd79a5b | |||
| 1e8ebff8ac | |||
| 2aaeb87959 | |||
| b44b1bbd6e | |||
| fbc44597ca | |||
| ca3e7da99b | |||
| 84f4f2c7c9 | |||
| 0ffc189fee | |||
| f7ae606485 | |||
| dc9c746cbc | |||
| 3d9582728b | |||
| aaed135c1e | |||
| b8f9d57194 | |||
| a5424b703b | |||
| 5de59481e1 | |||
| 9a09552de5 | |||
| 4bac666675 | |||
| 3cae77406c | |||
| 399e71a4c0 | |||
| d53c777ca1 | |||
| 245c3eab83 | |||
| b18d580dd5 | |||
| fb60b65258 | |||
| 5565f20b8b | |||
| eac9954e26 | |||
| 526ef5fbd8 | |||
| 3bf30fcc38 | |||
| 857af4d498 | |||
| 67f5b9c808 | |||
| 7cff252401 | |||
| 4e59b13e0f | |||
| 50a853c96e | |||
| 3243037a91 | |||
| 06e244202b | |||
| 105b54d4cd | |||
| bcd72b4040 | |||
| d464001ca1 | |||
| f8daa39253 | |||
| e852d0b264 | |||
| a77996e933 | |||
| 42bc6cef07 | |||
| 66d62f7e65 | |||
| ef75e82fe3 | |||
| 81679ffdb9 | |||
| 80ba0a4601 | |||
| 617de03d13 | |||
| 49f714850b | |||
| c88d7751de | |||
| 41b7c99bee | |||
| 9f53a3c4e6 | |||
| e1c55be4ff | |||
| 059a4fd6f6 | |||
| 4fcf3a96e6 | |||
| c30f46cc80 | |||
| e5d8576cfd | |||
| 6bdf5bfc3f | |||
| 899be1a70d | |||
| c05b7c9a66 | |||
| 6d00593449 | |||
| 87db317493 | |||
| 52344f9997 | |||
| f8a56d3712 | |||
| b3a222e811 | |||
| 529a287a92 | |||
| 6043695181 | |||
| 74dffc5f26 | |||
| 5e5cf68068 | |||
| c8899e694a | |||
| 8081d7bf4f | |||
| ace7a82ef9 | |||
| 3bd7a65b37 | |||
| 7040aebf37 | |||
| b9144fc028 | |||
| a52dc5b5f9 | |||
| 53974fcaa8 | |||
| 9c7f3e41c0 | |||
| 248415daea | |||
| 3aca3b2a70 | |||
| 882d64f809 | |||
| 8b035a3570 | |||
| 6375fb72ad | |||
| f788778e48 | |||
| ca6318cf58 | |||
| e2213896d2 | |||
| a9b4000b61 | |||
| 7fc282011b | |||
| 53dc1cde81 | |||
| feda4dddbb | |||
| d962fc5092 | |||
| f229e78a9e | |||
| baabb6d4ba | |||
| 6fa8fdfb74 | |||
| 008e6ecdb7 | |||
| e329e234a7 | |||
| 7a187b19aa | |||
| 1842cff1cf | |||
| 62b436be08 | |||
| 5bfcf11689 | |||
| 8376bfab67 | |||
| d3c49894d5 | |||
| 764e263c2f | |||
| fa24d1f47c | |||
| 3724f333fe | |||
| f4610cfc6d | |||
| 8b84e9e0eb | |||
| cd1c5414d6 | |||
| 4a04c8fb10 | |||
| d8c0929f24 | |||
| 39b5298569 | |||
| 381287e451 | |||
| bf0c433a8e | |||
| 81760673e3 | |||
| b733b711c3 | |||
| b83cb162dd | |||
| 2a4a063169 | |||
| e81fae18d1 | |||
| 8862d59f99 | |||
| 3598d5047d | |||
| eb6cc1d15c | |||
| 80291f4473 | |||
| 9c409845ba | |||
| 4116445f88 | |||
| a632c7b307 | |||
| 8461780ea5 | |||
| 4711465ad0 | |||
| d74b4a2527 | |||
| a4ebd3bf6a | |||
| 422cf661ee | |||
| 10dd94e428 | |||
| 8b786b30c5 | |||
| 213394d3a6 | |||
| 698cf75276 | |||
| 73d269c8c1 | |||
| 490ea0e57c | |||
| c440e892da | |||
| 57f924c50d | |||
| 36c1eb5fd7 | |||
| 3e6abbcc60 | |||
| d856b6caf4 | |||
| 09fe6d5c8f | |||
| 58e403c28c | |||
| 9f8a003107 | |||
| fbb1c3c1c0 | |||
| c0585e091b | |||
| e600768e19 | |||
| 9845d52bb7 | |||
| c5119b23fd | |||
| 18d6398e02 | |||
| f9c1bd930e | |||
| 25dd2ce800 | |||
| 14696db19f | |||
| b5c87afbb2 | |||
| 4a1260201d | |||
| 5f0bc62131 | |||
| cbba505632 | |||
| 4dd033b069 | |||
| ed0e4b6fc2 | |||
| 9b5e17ab88 | |||
| 25563cc4eb | |||
| eb16d571a0 | |||
| c3749b7f93 | |||
| 25c5e4686a | |||
| 9f7f09d0f7 | |||
| a23b9ab782 | |||
| 57db78797e | |||
| 16f60b110a | |||
| 5e0fde83cd | |||
| e11faa9992 | |||
| e8d067b359 | |||
| bfe3cdad05 | |||
| 982f411251 | |||
| 29d9d824fe | |||
| 82617219fc | |||
| 863481ab17 | |||
| 35479c4cf9 | |||
| ce0d0e18f7 | |||
| 22cbc9f005 | |||
| c3963a7f80 | |||
| 07397d277f | |||
| 69d3902280 | |||
| a731c4f20b | |||
| c667ff8f28 | |||
| a854eaa08f | |||
| df24dc4db9 | |||
| a9b22625d3 | |||
| 71274bf063 | |||
| 48e922423a | |||
| bfd7e6c7ee | |||
| cf14e652d1 | |||
| 0b9bccf4df | |||
| 1b808bcffd | |||
| 1223ff467e | |||
| 9390efe04e | |||
| 787fb3207c | |||
| 0537dc4e61 | |||
| de087c0f9d | |||
| f3d00082c2 | |||
| 9f2f230037 | |||
| f9e7a88e69 | |||
| d7db26b19c | |||
| 689d4837fb | |||
| 069169902d | |||
| ad095fe20c | |||
| 0c36ee3155 | |||
| 3b1333d88f | |||
| 73cf93f36b | |||
| 6c6f954ff8 | |||
| e42ce7835c | |||
| b10396f556 | |||
| 742fc45068 | |||
| f39001788f | |||
| 0fac74810f | |||
| 3b82ab0817 | |||
| cf6f185635 | |||
| ec4622a096 | |||
| 371c4c79a9 | |||
| 4cb0606746 | |||
| db4b5a2065 | |||
| 3e71a82741 | |||
| 0f9cd87b13 | |||
| 9263cb2f15 | |||
| e9d60852b7 | |||
| c9053f4a6c | |||
| bfbdb24622 | |||
| f2ded51dec | |||
| 856dd30fae | |||
| a5fb87a364 | |||
| 2662d2913f | |||
| e8052e3e37 | |||
| 072e57437a | |||
| f61d224d1c | |||
| edabe5dc6c | |||
| 79abddc476 | |||
| c0fbda2ee2 | |||
| b20f9ae848 | |||
| bacfae1024 | |||
| 260d2a5746 | |||
| aa892335de | |||
| 1fc54f6bdc | |||
| b2f511f4df | |||
| 098ddc4b46 | |||
| 1f7cb1b593 | |||
| 2f175e4cef | |||
| 0b874a4bd5 | |||
| a8c36721b0 | |||
| afc950912d | |||
| e87d5fa074 | |||
| 56ed1f53d0 | |||
| 82e6644c85 | |||
| 84b36c29ab | |||
| 10a1973aae | |||
| 969f535536 | |||
| 6df017b620 | |||
| 5d7072da13 | |||
| 0565563156 | |||
| 5aee2ceea8 | |||
| 66700054a3 | |||
| 9e2bb00b82 | |||
| 65a2d35112 | |||
| 2275e87b6f | |||
| 7ac9dae5af | |||
| 21e8a18c9e | |||
| 0a59a7beb6 | |||
| 6439ab60ee | |||
| 8e48b6a40f | |||
| 3188ab14cc | |||
| 19d72e6f84 | |||
| 6cac1a8001 | |||
| bae1fbbdf4 | |||
| 6b546dbf85 | |||
| fd0accd00c | |||
| 565f67b9fe | |||
| 6769c92f7e | |||
| 50901d0ac1 | |||
| ef4a931440 | |||
| 8eb4b81c90 | |||
| c507d9a7d1 | |||
| 1e6f25b395 | |||
| 6a42e3c11b | |||
| 4c1c27c753 | |||
| f78ec64c25 | |||
| 004e0533f0 | |||
| 125fb4d812 | |||
| b1d5658f5e | |||
| 7cbc8b1bea | |||
| 6131921307 | |||
| 988da99f89 | |||
| c8ca832460 | |||
| e918aa27a4 | |||
| 908508f44c | |||
| 3cef537a5f | |||
| 1c8bee1e14 | |||
| 433866fb0b | |||
| a13dc3db50 | |||
| ac9a21620d | |||
| 10ecce9fac | |||
| f11b298acd | |||
| f8cf3fd1d9 | |||
| fa1b9f924b | |||
| 23cb176d27 | |||
| e14616c4f8 | |||
| c6608120cb | |||
| 6e5fcf3edd | |||
| 4b506b415a | |||
| 2f352c0b1a | |||
| 1d3d316d05 | |||
| 275a19151b | |||
| a02372c5cb | |||
| 9209ba674b | |||
| ddc5274f50 | |||
| 221caa74ab | |||
| 0b9b5f957c | |||
| 754866a6f5 | |||
| 325f887b40 | |||
| 2952f0e907 | |||
| ab02c12352 | |||
| d5609b9ca8 | |||
| 65e1f6f484 | |||
| fcd5f2fc45 | |||
| 4139e20fb3 | |||
| 9650919738 | |||
| c3ebc4ec3b | |||
| a092441f67 | |||
| 00861c3455 | |||
| 2aeee72311 | |||
| 2810fbea3f | |||
| b868858de3 | |||
| d6debec1a6 | |||
| 9ddfd08f24 | |||
| f6ecd4a68e | |||
| f18d19a102 | |||
| cff10ef530 | |||
| 5fe991bc02 | |||
| 42b5373796 | |||
| 27747c44fa | |||
| 38c2e8e06f | |||
| a4f86be2c9 | |||
| aa83596560 | |||
| b4578aeabe | |||
| f0c90b3a51 | |||
| 67161bdcc7 | |||
| 6d1a5a12ea | |||
| 8591165766 | |||
| e0e331fc2e | |||
| fd48d12d60 | |||
| 9800265c12 | |||
| 9ed91d3a09 | |||
| da34a50431 | |||
| 057c5668cb | |||
| f0e5505b24 | |||
| 03281d9891 | |||
| cc888734aa | |||
| 6588a4e05f | |||
| 8947209fd7 | |||
| 9ffbe24f64 | |||
| 992d5c50ce | |||
| 39ba905704 | |||
| 8098a1b4d7 | |||
| d9415d6871 | |||
| 581631e87d | |||
| 14656f2613 | |||
| efbc5003b9 | |||
| d7c4c6e5f9 | |||
| d82e567d13 | |||
| 40a65cc564 | |||
| e55dcc8b3e | |||
| 725e89bef5 | |||
| 7fd861742e | |||
| d331353592 | |||
| 1d733e7911 | |||
| 66493d480a | |||
| a734799fa1 | |||
| d755a59421 | |||
| 1d217b4d47 | |||
| be0c38e03b | |||
| 18c8045c66 | |||
| 383c35fb49 | |||
| b3413a47bf | |||
| c55ab672f0 | |||
| d57098c482 | |||
| cd85ac13c1 | |||
| 52dff9bf51 | |||
| db0dd06b3f | |||
| 89f2a8fcb5 | |||
| 0604637110 | |||
| ea552b5898 | |||
| 3f6796b1d3 | |||
| 04bb21fef7 | |||
| e5dd20f15e | |||
| c321b3223b | |||
| 97db7efd56 | |||
| ee1ec2e91f | |||
| 9e41f13680 | |||
| 40f9dee2c6 | |||
| 5801a0db29 | |||
| 8c671750b9 | |||
| 1f6177a5c6 | |||
| 367df148be | |||
| f468d1a5d3 | |||
| 31c6ef075e | |||
| acc6f2769c | |||
| 9fdebefca8 | |||
| 437b9348d1 | |||
| 0602dcfb6d | |||
| f4e93057b1 | |||
| 4e11f026ef | |||
| dac3f1ca3f | |||
| 63abcb074b | |||
| 4e4e10d1f8 | |||
| 5c82c9606d | |||
| 713a3a5408 | |||
| ae708fa5e2 | |||
| 4d21c75a7e | |||
| 22290197a7 | |||
| d36a03cc36 | |||
| d18c4b0307 | |||
| 03fc1d2f34 | |||
| c025c72802 | |||
| b3b29d3c76 | |||
| 4057237b48 | |||
| 246b1aaa53 | |||
| 125b6e006c | |||
| 785fe50e9f | |||
| 6ca8ae5366 | |||
| 160343bdef | |||
| 5b661a3160 | |||
| a0e2438e06 | |||
| bc9aaf6b5b | |||
| f485547a4d | |||
| 97473a8b09 | |||
| c71bc4a320 | |||
| 8e7e887e37 | |||
| af1638ce7d | |||
| 12b4fd8975 | |||
| 9c94100609 | |||
| ba7484e5a1 | |||
| d12f9bd051 | |||
| bb1a93a385 | |||
| d8ccaf37e8 | |||
| 4fa363e910 | |||
| 86276afd3b | |||
| c642e22556 | |||
| 5ff3e2c42d | |||
| 7245c20ef8 | |||
| ba524d3dba | |||
| f2d4b07d2b | |||
| bad07970cf | |||
| 5263081254 | |||
| 0db7fd3e4a | |||
| e5e572f940 | |||
| b5f3b1b526 | |||
| 4e38b17f76 | |||
| 5779f4e927 | |||
| f40260f9cb | |||
| c1731fec39 | |||
| 5d0a2c75b7 | |||
| 277eb7cc53 | |||
| 2cf7521735 | |||
| 8a1502f0a9 | |||
| e54dbe69e4 | |||
| 8db9e8be80 | |||
| 4bc071aa8d | |||
| 01ae96dcb5 | |||
| 7aabf34d76 | |||
| 5f35f1d961 | |||
| daf8435663 | |||
| a728938094 | |||
| ef30d13e94 | |||
| 5881cc4268 | |||
| 01d68774a2 | |||
| d3f0f4013f | |||
| 57889f408a | |||
| 425a715d3c | |||
| 0111c1e6c3 | |||
| bb811495cb | |||
| 37c0f9a382 | |||
| 5acfd5a014 | |||
| 81b7bb502b | |||
| ba92de3034 | |||
| f317a3e10a | |||
| f7acefece1 | |||
| fb6844fb64 | |||
| 171c5a189f | |||
| 17d195449a | |||
| 9d2b7e46b0 | |||
| 07c61eb98c | |||
| a028fabf7f | |||
| 358ba2c411 | |||
| 58c5cfaafb | |||
| 20383d8ba8 | |||
| 7e808dc649 | |||
| ca435eb5d1 | |||
| bbeddd775a | |||
| 6ab9ab0e29 | |||
| cc619af68b | |||
| 9bd662e82a | |||
| 7f3a029049 | |||
| 349e081cc0 | |||
| abf8941676 | |||
| 1d9e405667 | |||
| 536bc94da7 | |||
| 68e4dd3d70 | |||
| 360e76309f | |||
| 18f0040778 | |||
| ba7d622595 | |||
| d05143bef8 | |||
| fb95977151 | |||
| 58d0965249 | |||
| 8a22702ae3 | |||
| a9b79e36d2 | |||
| a007fb74c9 | |||
| b10007be4b | |||
| c448c7f09a | |||
| 69b2b419d6 | |||
| 2d905826f8 | |||
| fc16c672ba | |||
| 265308065c | |||
| 8af3b2587d | |||
| f87e899c78 | |||
| 98295e06b1 | |||
| 2aefc417d9 | |||
| 2a998b99d9 | |||
| 70f8cae983 | |||
| 85237d5126 | |||
| 508071d903 | |||
| 3e67ba3e19 | |||
| 4998ce006e | |||
| e47c090868 | |||
| 28d9fdd2aa | |||
| 1e42465195 | |||
| 33127b6f2d | |||
| 5e70dbce10 | |||
| 46c918d22d | |||
| e95b7084b9 | |||
| 1fba5dfceb | |||
| 79c3f3e825 | |||
| 2ff3e57296 | |||
| 0eecf43a7e | |||
| fe9a146b36 | |||
| 4eacc008e3 | |||
| 9e4450bab0 | |||
| 3dc34ed30d | |||
| 6c6f16a8f5 | |||
| 0f99809daa | |||
| 1b47f597b7 | |||
| 02836b7287 | |||
| 2a33d3dcb2 | |||
| eee22d9c39 | |||
| 0ef86edf17 | |||
| b1d6199c98 | |||
| ce47cdc151 | |||
| 94d469f741 | |||
| 7fb9cdeff5 | |||
| d9e740a251 | |||
| 56f28c07ab | |||
| e997e19531 | |||
| 1141f649c0 | |||
| 399b7f31bb | |||
| d329307578 | |||
| 28e70dd89d | |||
| 0afc9b9d9d | |||
| b6e87461db | |||
| 1b0e64699a | |||
| 3f1f14aa94 | |||
| cd4f866c6a | |||
| 62761908f2 | |||
| 9c7b61f341 | |||
| 48b710c7cd | |||
| d9100200e1 | |||
| 61a42ec882 | |||
| 32f4697d67 | |||
| 5184e7da2b | |||
| 1dd791c776 | |||
| 3e86b5f20c | |||
| 4e16d8fb9f | |||
| df8fdf3896 | |||
| 5222f25f25 | |||
| 8dba31f059 | |||
| 5849169891 | |||
| 57da947035 | |||
| 1226f58bc6 | |||
| 6abbe5c74b | |||
| ebf7ea4be4 | |||
| 628e2a6ca5 | |||
| da0ceef6b3 | |||
| 9b0c3f100f | |||
| 7d0cb74de6 | |||
| 428c8f299d | |||
| c4ac51c87d | |||
| ab6f939e62 | |||
| 38b5424c5d | |||
| 246362ca48 | |||
| 25c5f5fc28 | |||
| 434739f3a3 | |||
| b855407d64 | |||
| a079b6c306 | |||
| 7e10342919 | |||
| d1230bcf16 | |||
| 29e4fa31e7 | |||
| d069bff740 | |||
| 9e7a1c8fb4 | |||
| bdfe498ee7 | |||
| 87ebb6ae87 | |||
| b145a34062 | |||
| 2956839732 | |||
| 43a7d86394 | |||
| f341aa50ab | |||
| 0b44aaa1ad | |||
| 28a6d78c06 | |||
| f14b1042d3 | |||
| 41e538c46d | |||
| 1753ea7474 | |||
| b4f1b9a6ea | |||
| 20b3960c09 | |||
| 11e2d1e834 | |||
| 73e90f6cd9 | |||
| 8ffc45d9cb | |||
| afa886e729 | |||
| 518d0c0b02 | |||
| 9ba0cd197e | |||
| faec9945d0 | |||
| 5a18669108 | |||
| f7f871278c | |||
| f8bbdf8a97 | |||
| 9a42e826b9 | |||
| cabe21df2c | |||
| e6c93dc100 | |||
| 72f6e3f1b2 | |||
| 7e9a9d09f3 | |||
| f79b2850ad | |||
| a0f0158e74 | |||
| 12467ecd6c | |||
| fd4a5040ba | |||
| 2bccc85011 | |||
| dc5b18e4ef | |||
| 0c5c11b541 | |||
| 4d28e9fbe6 | |||
| c67d9135c1 | |||
| bcabd11857 | |||
| 83db9da9b1 | |||
| e24032c284 | |||
| 235e3e9d7f | |||
| a9f5a6b396 | |||
| 9a7b3b91df | |||
| d5f7c77bc1 | |||
| 427d482261 | |||
| 0eb9db534b | |||
| 1e30875be2 | |||
| 72e4bea17f | |||
| 73f7a9322b | |||
| 25300a2ef5 | |||
| 8016f03610 | |||
| 4029cba989 | |||
| 42af8e7112 | |||
| c17cce832a | |||
| bbfe35a452 | |||
| a11e9f3242 | |||
| edbbcb625b | |||
| 2bd59af6a2 | |||
| 68bf4ad971 | |||
| cfa71e3f2c | |||
| 43a3259a69 | |||
| e4838e2efb | |||
| 88f35c5e0e | |||
| 22e92e3c05 | |||
| d7ddcebef2 | |||
| 0b7943fe28 | |||
| cadca639d8 | |||
| ccfd373fd3 | |||
| dccddf6428 | |||
| 93511ea70d | |||
| e30fbd2b80 | |||
| 7009498b84 | |||
| e78c04591c | |||
| 30285d5f10 | |||
| 5c8c7c2a4d | |||
| 01e0c1c6f5 | |||
| ae3c564ef0 | |||
| 80588e01c8 | |||
| 6c293a26e3 | |||
| 257666102d | |||
| 58a6b7a28d | |||
| 3f43a9a760 | |||
| 2f8b62530d | |||
| a0f77dc958 | |||
| 3165c35860 | |||
| 130d2b2494 | |||
| fb01e8e151 | |||
| 03ea26b499 | |||
| 425ec1d0cd | |||
| a180201e24 | |||
| 970aa52ab3 | |||
| 1bbe000d21 | |||
| 5f7c88a8b9 | |||
| ac3633b1b2 | |||
| cbe902cf22 | |||
| 9a3d8b8703 | |||
| 1d89fb6e1b | |||
| e6fedc6556 | |||
| 7f3056c15f | |||
| e2e793d864 | |||
| e11519483c | |||
| 1da068a263 | |||
| 0147aa233f | |||
| 389c3cb193 | |||
| f5ccad350e | |||
| 916a05b1cc | |||
| d86b8b8413 | |||
| 32cf475cf8 | |||
| e815ba5ac9 | |||
| 398b975563 | |||
| 083623ab1b | |||
| 20655afd7b | |||
| 181dc9ec47 | |||
| 0f7e5d53f0 | |||
| 2071c5945c | |||
| 0d6b9af866 | |||
| 38b3d1c46a | |||
| 973597d493 | |||
| ee7d43cc61 | |||
| dd438f5cfa | |||
| 0b30264d39 | |||
| a21422aad7 | |||
| 784b582b1f | |||
| 2a8e95b4e8 | |||
| e3cbfd954f | |||
| 2a396bc1fd | |||
| b21c3d7a61 | |||
| 5c3e7c96e7 | |||
| 9064aaf24b | |||
| 99a88822e3 | |||
| c45ed81db3 | |||
| 43c5246b1a | |||
| 8dde80a13a | |||
| 92091599da | |||
| 86e108ead9 | |||
| 6d452dbcd4 | |||
| 62b988207f | |||
| 748b4ee78c | |||
| cc457b33ee | |||
| 8a98c3f75d | |||
| 53ba6a49ef | |||
| 5b4d1a01d6 | |||
| c8eadb91df | |||
| cd4e45e385 | |||
| c20c72aba9 | |||
| eef51c0af1 | |||
| 322fde4ed9 | |||
| 688aec431a | |||
| 775339a584 | |||
| 24cfe77966 | |||
| 6839048a17 | |||
| 60609b1b24 | |||
| 86466c955c | |||
| 6684bdab99 | |||
| 94f876a1cc | |||
| 6c19753851 | |||
| d8c107b54a | |||
| 5b81a7a8ca | |||
| d569bfab3d | |||
| b173de4f13 | |||
| 906dbc3015 | |||
| 89e1f04f29 | |||
| fb9501a197 | |||
| e6f7ece3d2 | |||
| cae54539ab | |||
| 34acc982c3 | |||
| 8d2e4859fc | |||
| 7fd4933fe8 | |||
| ebd1b34f84 | |||
| 867e18a67c | |||
| 79a0dcd3d5 | |||
| 2bbce57260 | |||
| e1a21649ff | |||
| 58dc034d02 | |||
| 336a1aa2ab | |||
| 57e42eaccc | |||
| 71eb28ebc6 | |||
| 473f1e6761 | |||
| 686ebdb500 | |||
| 5463dcdfa5 | |||
| b13e95a70b | |||
| cdb5b59df5 | |||
| b44063e744 | |||
| 4dc12d61ab | |||
| 1e59b83e1d | |||
| 2c2079b8bb | |||
| 441ba139d4 | |||
| a7d3d1da21 | |||
| 6f9e40db93 | |||
| e2c745d9ba | |||
| f7ca82b1d1 | |||
| 90a932fe28 | |||
| 71862fdff0 | |||
| 1141b16f3e | |||
| 6f69796223 | |||
| 8ae4adb75c | |||
| f0bfee65d2 | |||
| ec6325f1f7 | |||
| f1e4a15d4e | |||
| 12bad57506 | |||
| b502edec67 | |||
| e39d942d9c | |||
| 54909beda7 | |||
| 37a76708f1 | |||
| 14b475f74e | |||
| 4f10fd671a | |||
| 4c2f445b0a | |||
| fd95ac4c80 | |||
| f8261cf6ad | |||
| 1023dbc6f7 | |||
| 4669c26b02 | |||
| 1f1430f074 | |||
| 3713a0de0b | |||
| ff434f5822 | |||
| 0d857ceabf | |||
| 1ec86928e6 | |||
| 36a7a4486c | |||
| 71b56b9ed3 | |||
| 0f2a45f436 | |||
| fc05b61ce0 | |||
| 715e42d86c | |||
| f8d8231255 | |||
| ac4206007d | |||
| f96b7b59fa | |||
| 5dab441718 | |||
| 121d3de03b | |||
| c0fdce99e0 | |||
| d2ea7c3b54 | |||
| d628976bd4 | |||
| ab25897d4e | |||
| 0bf672f284 | |||
| 37307c1058 | |||
| 272b5fb0eb | |||
| 42fa7a7ef1 | |||
| 29af0d1043 | |||
| e3d0fb9c9e | |||
| 7839592fbc | |||
| 8067ecb0e1 | |||
| 55e71dcde5 | |||
| a478ed4eb4 | |||
| 7b70df4161 | |||
| a8a4a10263 | |||
| 337c515d02 | |||
| 1ccb22b56a | |||
| c2dcbfc537 | |||
| 390f7693b9 | |||
| 52d1725a0c | |||
| d19f601dec | |||
| eab43f0f39 | |||
| 2cd7e5aaa4 | |||
| 8cf5c6de87 | |||
| 72993ed022 | |||
| ce0fe877db | |||
| a21935e9c7 | |||
| 315a7a3c4a | |||
| 9e9000d609 | |||
| 30d67b4813 | |||
| 51e03a7c4d | |||
| 90f638f3b2 | |||
| 248569fa64 | |||
| 1b87913d30 | |||
| c8a4383e9d | |||
| feb65fcb64 | |||
| e78b7a27f6 | |||
| 775941db70 | |||
| 34a90f1e78 | |||
| 59af92bb8f | |||
| 58f0ffc4f1 | |||
| 1d13b5c300 | |||
| ca67d14658 | |||
| c362fa3bc7 | |||
| 226c907bbd | |||
| 6c4ed80d83 | |||
| 0b1d186caf | |||
| 31fc76401d | |||
| 8421c4bcba | |||
| f643ea5156 | |||
| a868d2358c | |||
| e5a4cc7075 | |||
| 7546f8ab98 | |||
| 4f2d1153b1 | |||
| 6fe6d9d9c8 | |||
| 2151ea5130 | |||
| 19a7849178 | |||
| c3e9663bf0 | |||
| adf9297047 | |||
| 370376f043 | |||
| d64e320ce1 | |||
| 85f1c3e9b0 | |||
| 27b0f260e6 | |||
| eacba49833 | |||
| c40b974182 | |||
| 3375666c53 | |||
| 7b85d31579 | |||
| 6f21c19ba0 | |||
| 75f98c010e | |||
| 7ec6aaf2ee | |||
| 233b2bf351 | |||
| a2247f0170 | |||
| 439985c34d | |||
| 0d716b5691 | |||
| 16b23e8045 | |||
| e61f74a602 | |||
| cf032d05d6 | |||
| 79cf47513e | |||
| d8cf8fa312 | |||
| b3c503a8d0 | |||
| f4acade014 | |||
| e8edeca80c | |||
| 3f51657eef | |||
| ac38b17a5a | |||
| 7f60027aa1 | |||
| 97c4aef241 | |||
| 3faab403aa | |||
| 9d73e3a4fb | |||
| 61eacdadad | |||
| 34f0ece400 | |||
| 4817dfbe26 | |||
| d3adad02ee | |||
| 7d7bfb00b4 | |||
| f54c5dfb36 | |||
| 47f73b0569 | |||
| 39d6a2e0d4 | |||
| 6de92a9ef1 | |||
| 08c3c1cefc | |||
| 607ef66ea8 | |||
| 75159bbfea | |||
| eae50e0deb | |||
| cf581571a2 | |||
| 0eff1909de | |||
| adbb9d5609 | |||
| cb445f14ec | |||
| ffe3068f8c | |||
| 5b09fc7b4b | |||
| 7b6e031df2 | |||
| ab76120c96 | |||
| 40fe923477 | |||
| 0fd3f77e32 | |||
| 87f87fe85f | |||
| 996e2e9741 | |||
| afdd5ef8a7 | |||
| 73c2949cee | |||
| 90ba6dba21 | |||
| 1242f4c912 | |||
| 2740e8a6ec | |||
| ca78a2dc38 | |||
| 876fa7df69 | |||
| 57cbc0c372 | |||
| 9c368aaf55 | |||
| 29efa2321b | |||
| 361c5e5665 | |||
| af8cf07ece | |||
| ecd3fbc5ba | |||
| 869e5948f6 | |||
| a94d088a91 | |||
| 6d4cc3f97d | |||
| f3fc6a7f25 | |||
| a18693ec9f | |||
| ac252f7f83 | |||
| 21df7c201c | |||
| 6985f95b28 | |||
| 033b6706b7 | |||
| f2de7ef12e | |||
| 27459a2869 | |||
| 15d0a15364 | |||
| 4204e9070e | |||
| b9e587e703 | |||
| 1138ab87d4 | |||
| 0a226feef7 | |||
| efa051a181 | |||
| d5ef187fe1 | |||
| bfee3cf96a | |||
| 6801e064cf | |||
| db6fc2c563 | |||
| 89f238f5cd | |||
| cdb7aa0ab6 | |||
| 91a1736e61 | |||
| 3e02ce0e4f | |||
| e2e7c0b35c | |||
| beadfcd627 | |||
| dfd91e4d4a | |||
| 64af7cbc19 | |||
| 2d555c821a | |||
| 786cfde0a8 | |||
| e1c60cb830 | |||
| b7daccfe36 | |||
| 571487bf46 | |||
| 85b4be21c5 | |||
| aca5b290c2 | |||
| 97e50a2aae | |||
| 4a30157492 | |||
| c72f824670 | |||
| e30d85bf2d | |||
| 1d37352e85 | |||
| c0e81dc8ad | |||
| bd67c19612 | |||
| 0768e46b91 | |||
| c1a25ac668 | |||
| 3995fae3b6 | |||
| 2d0f36801a | |||
| 66e30f3a17 | |||
| cb415007ba | |||
| 0a89522d18 | |||
| 8990dc25ff | |||
| c256f1c0fe | |||
| c5e3b1a06d | |||
| acbcc58858 | |||
| be6a71e607 | |||
| f69b6ac018 | |||
| 7ace2412fe | |||
| ea3431f5a7 | |||
| 8360cddd12 | |||
| d3043285f2 | |||
| 28d75b347f | |||
| 9a639e015e | |||
| ce4e807a04 | |||
| e05b6c62b2 | |||
| e705fc08e9 | |||
| 8f37638f66 | |||
| e0b1400489 | |||
| fb0028623a | |||
| 528ecb3e56 | |||
| b5afe5e3b9 | |||
| 525d1dcb63 | |||
| e01282f5eb | |||
| a1fdfce779 | |||
| 85e66bdcfc | |||
| 2d9139705f | |||
| e927682f24 | |||
| 69812d996a | |||
| ff67a1d864 | |||
| a9e5f73abd | |||
| 9e26b11fe2 | |||
| ef9db848fd | |||
| a2c0e85f08 | |||
| 265cbde35b | |||
| 9eda055ddd | |||
| ce3ea63680 | |||
| 83e983106c | |||
| 30d3984998 | |||
| 1e1b6417d7 | |||
| d8824a068f | |||
| 70414d2b08 | |||
| 236a415bf7 | |||
| 4c82d3101f | |||
| 4c2f0c2ceb | |||
| 6b9baa15e5 | |||
| f93460d4f6 | |||
| b5f73f7a23 | |||
| 43c44ee347 | |||
| 25eb443587 | |||
| e899e3d62b | |||
| 52620d3edd | |||
| d7987c5e46 | |||
| e9441739a0 | |||
| abf400572b | |||
| 5cabc2b9ef | |||
| 1d11ddb65f | |||
| 03eb28bb46 | |||
| 430d5c0c09 | |||
| ea966447d6 | |||
| 1533cf185c | |||
| 749cf2f240 | |||
| c06c616558 | |||
| 7dbd6aaf3e | |||
| 51fe0df1c4 | |||
| 045b83d76d | |||
| 3d8c237a01 | |||
| 5ac785b6f6 | |||
| 4768f5adba | |||
| 18193f31a4 | |||
| aad6c3c311 | |||
| 42ae915878 | |||
| e5755dbc64 | |||
| 4b2e5beb12 | |||
| ee48169642 | |||
| f20e77dd93 | |||
| cdf3b7aeb2 | |||
| 1a2383d9f8 | |||
| 037f32bd54 | |||
| 61158bbfcf | |||
| 6a8534a0f6 | |||
| f19761ef71 | |||
| a4187efcb2 | |||
| 922921a739 | |||
| cee8a7a73b | |||
| 474c298630 | |||
| 0575001ef2 | |||
| 3ceb5fe7e4 | |||
| d00ded29a2 | |||
| 4312042e2a | |||
| d129856a4f | |||
| 5c1c601119 | |||
| a2a91cdd21 | |||
| 4940906c05 | |||
| b857a25081 | |||
| 83bed2cb04 | |||
| 079665a651 | |||
| bd38609ba1 | |||
| 5777cd4dd7 | |||
| bab48dbc50 | |||
| 6c1a840369 | |||
| 2830bab937 | |||
| eda584a0f5 | |||
| 67787dad86 | |||
| 4c6b234e13 | |||
| d095c0fc5f | |||
| cab8191379 | |||
| 586c212d93 | |||
| 8d8c38d3b4 | |||
| c9778bf3f7 | |||
| 029df230d6 | |||
| 1eb4411009 | |||
| d4e79d7a95 | |||
| 3bcdc5e371 | |||
| cfed625f4c | |||
| c6672270ea | |||
| f0161a5c45 | |||
| 2d6b18cfc9 | |||
| eb3ccaa773 | |||
| de9fbe4f82 | |||
| 0a4d227a2d | |||
| 9d374c1421 | |||
| ef8f762590 | |||
| 95c6a3d93d | |||
| c519c111ec | |||
| 717cd66082 | |||
| 4a572f5015 | |||
| 0344b08ba1 | |||
| 4bde0a0ded | |||
| c602006c04 | |||
| 7eaed897e8 | |||
| 16642a0810 | |||
| 4337554e71 | |||
| 1dc28f2540 | |||
| 43826a511a | |||
| 57707391b4 | |||
| f211c92b82 | |||
| 17abb515db | |||
| 3c81f67a62 | |||
| 221a44d1bd | |||
| 45fb564db6 | |||
| 5a4e5a3559 | |||
| 2fbdba3fe3 | |||
| c4e7fe9f02 | |||
| df466fe7b6 | |||
| 8df12f9219 | |||
| bc44b57b73 | |||
| dea73cdb01 | |||
| 621ad77911 | |||
| 29945eb0d1 | |||
| 111782a728 | |||
| 4b09b8f926 | |||
| d07d624b01 | |||
| 10ad3b6945 | |||
| 46ad21d88c | |||
| 2de350cf80 | |||
| 2ce147d84b | |||
| e05797bb60 | |||
| 774c178272 | |||
| 5f8ed93998 | |||
| 50445cdc26 | |||
| 4de0a47920 | |||
| c4c942fbab | |||
| 5d3e1f3d53 | |||
| fbfe3777b4 | |||
| 907b14ba9d | |||
| ede3d3ced7 | |||
| e59dc8a9ce | |||
| f5ed6658ec | |||
| 2abdf800d9 | |||
| 180eb62560 | |||
| e6a50b4215 | |||
| e2aa75569f | |||
| a0d1d5b41a | |||
| 80b20c444f | |||
| 15447d0398 | |||
| 51d4c30e4a | |||
| 7ab0cf1ffd | |||
| 20ff90225a | |||
| 04e63c307e | |||
| 6d6ab9b951 | |||
| 9765d32dc6 | |||
| 86b29b0edb | |||
| 4613a85c23 | |||
| f2eb32b3c9 | |||
| 93bcbc5e71 | |||
| 361cd8c42b | |||
| 6ae785af6e | |||
| a288b88bd9 | |||
| 1e797ed26b | |||
| 89dba8092d | |||
| 2195f9261e | |||
| 87a957642f | |||
| a5fd918ba7 | |||
| 7f90243337 | |||
| 11ecff91d4 | |||
| d342bab175 | |||
| 9c367350c9 | |||
| 002b2ec9df | |||
| 59e4b3df05 | |||
| 2bdbf688ab | |||
| 845774a571 | |||
| 8612355df9 | |||
| 002d093a37 | |||
| b787fc643b | |||
| 0073bfd6b3 | |||
| 09d423997e | |||
| 9a7dba6d86 | |||
| 7d2ad45443 | |||
| 1c2f665993 | |||
| 706eca1ef7 | |||
| 0d195918e3 | |||
| dc488dfc08 | |||
| 2a5ae3d1b4 | |||
| acd8d676c1 | |||
| 01f1a52525 | |||
| 46a89fa1c6 | |||
| d53284d914 | |||
| e36f3e5684 | |||
| 17ae3213cd | |||
| 111793e3a6 | |||
| f9069a18e0 | |||
| a0bb9e1665 | |||
| 92ecdf8b0b | |||
| 2c8c8257a8 | |||
| e706f5cbd4 | |||
| 37c015a7ca | |||
| 200e369d5d | |||
| a9829ab17b | |||
| b6ff220b06 | |||
| 6b2012900a | |||
| e5011c3919 | |||
| 72cf13e8e3 | |||
| 2c6158570b | |||
| 5be856cddc | |||
| cbf108f8b8 | |||
| 6e9b41d4bc | |||
| 0f17710b39 | |||
| 0308e63ef4 | |||
| 6a8f62a2ac | |||
| 05bc99e483 | |||
| d9725518d8 | |||
| 6116ea5bd7 | |||
| 9aacc4d203 | |||
| b79f6bb7ee | |||
| 651e259871 | |||
| 889ef5508e | |||
| dee47b2c55 | |||
| 39230d1672 | |||
| a5a4feb798 | |||
| 5a21746fe8 | |||
| b22f425c3e | |||
| 56684fb6da | |||
| d49c882778 | |||
| e166962d49 | |||
| a19b640ba4 | |||
| 9581e25412 | |||
| a035d397ce | |||
| 6208b57203 | |||
| 05687101ee | |||
| 9d01a63782 | |||
| 73eae21f3c | |||
| dabd5d5f09 | |||
| bcfacb1dbf | |||
| bbd1498272 | |||
| 311a25a05a | |||
| cece5458f9 | |||
| 816d98fb73 | |||
| 2192c8e148 | |||
| 2e9d460772 | |||
| 3c4b71e06a | |||
| adfb223fd4 | |||
| 38b5874b32 | |||
| 2142411c43 | |||
| b9034410a9 | |||
| a840161de9 | |||
| 3d98c4fe6e | |||
| 2b61bf2c91 | |||
| 200373f48d | |||
| 6bbbfeff81 | |||
| ba1cadb6e9 | |||
| 68f86b703b | |||
| 413f6c0010 | |||
| a3caf9e5aa | |||
| b5d6951f62 | |||
| 1c1e78bf89 | |||
| 116e770bfb | |||
| bf2aa12fd3 | |||
| afe5dd5024 | |||
| dbdd43de8d | |||
| cfcca53716 | |||
| 85828d24aa | |||
| bd812ab851 | |||
| daf319a402 | |||
| 9154b2edc9 | |||
| e69cdc2d5f | |||
| d5c6ad426c | |||
| 4650f29bb7 | |||
| 6329990417 | |||
| 1acb9398d6 | |||
| fa89345a5c | |||
| bb1f68f440 | |||
| b4ad09c0ce | |||
| 3535bd753d | |||
| b6e467acff | |||
| a838da18d7 | |||
| 40dc51dd1b | |||
| 8bc4dd7476 | |||
| 04268e1f5d | |||
| f942046a68 | |||
| 24003e0910 | |||
| 1e2c70f859 | |||
| 1f69def767 | |||
| a60ce4d483 | |||
| 4b7181dfee | |||
| f9f370cd5f | |||
| 8b1334a3d6 | |||
| 23f7cd6d36 | |||
| 3f986ecf29 | |||
| 2a55eb6ee5 | |||
| 6f0b9a6eec | |||
| 0835970d7f | |||
| d2e361331a | |||
| 52db6d0e9a | |||
| 204d1a8df5 | |||
| cad9eca293 | |||
| 612b2d8098 | |||
| efed7f2b66 | |||
| 5f6ccbff86 | |||
| 12bf36dfc0 | |||
| ab2cfba24a | |||
| c4dc675a87 | |||
| fde574046e | |||
| 8fbae2dfa7 | |||
| 48872e61fd | |||
| a215989fb3 | |||
| 11c5f32f0e | |||
| 15616a151e | |||
| fa783ea9b7 | |||
| 8066ec5c07 | |||
| e665d1dad8 | |||
| 318d33b9b1 | |||
| eda83f4580 | |||
| 23625b7a48 | |||
| af9c8731ee | |||
| ae99ef1a30 | |||
| 5b29162989 | |||
| a6eea2c977 | |||
| 9c69cb198a | |||
| 8efa7cdd67 | |||
| f6c999796f | |||
| 3f6d09e554 | |||
| 615363b332 | |||
| c2238857f4 | |||
| 602854999a | |||
| 72f1715eb0 | |||
| 2af0eff7ed | |||
| 4a241ef34e | |||
| 8c58adf552 | |||
| 6baabbe7bc | |||
| 4c5f1d54d6 |
@@ -1,241 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Update GSA Ubuntu Repositories or create a local repository
|
||||
#
|
||||
# Author: Leonardo Tonetto (tonetto@linux.vnet.ibm.com)
|
||||
# Revisor: Arif Ali (aali@ocf.co.uk)
|
||||
#
|
||||
# After running this script, add the following line to
|
||||
# /etc/apt/sources.list for local repository
|
||||
# deb file://<core_repo_path>/xcat-core/ maverick main
|
||||
# deb file://<dep_repo_path>/xcat-dep/ maverick main
|
||||
#
|
||||
|
||||
# For the purpose of getting the distribution name
|
||||
|
||||
# Supported distributions
|
||||
dists="squeeze"
|
||||
|
||||
a_flag= # automatic flag - only update if repo was updated
|
||||
c_flag= # xcat-core (trunk-delvel) path
|
||||
d_flag= # xcat-dep (trunk) path
|
||||
local_flag= # build the repository localy
|
||||
|
||||
while getopts 'c:d:u:p:l:a' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
c) c_flag=1
|
||||
xcat_core_path="$OPTARG"
|
||||
;;
|
||||
d) d_flag=1
|
||||
xcat_dep_path="$OPTARG"
|
||||
;;
|
||||
l) local_flag=1
|
||||
local_repo_path="$OPTARG"
|
||||
;;
|
||||
a) a_flag=1
|
||||
;;
|
||||
|
||||
?) printf "Usage: %s -c <core_trunk_path> [-d <dep_trunk_path>] -l <local-repo_path> [-a]\n" $(basename $0) >&2
|
||||
echo "-a Automatic: update only if there's any update on repo"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
if [ -z "$c_flag" -a -z "$d_flag" ]
|
||||
then
|
||||
printf "Usage: %s -c <core_trunk_path> [-d <dep_trunk_path>] { -l <local-repo_path> | [-u <gsa_id> -p <gsa_passwd>] } [-a]\n" $(basename $0) >&2
|
||||
echo "-a Automatic: update only if there's any update on repo"
|
||||
exit 2
|
||||
fi
|
||||
if [ ! -d $xcat_core_path ]
|
||||
then
|
||||
printf "%s: No such directory\n" "$xcat_core_path" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$d_flag" ]
|
||||
then
|
||||
if [ ! -d $xcat_dep_path ]
|
||||
then
|
||||
printf "%s: No such directory\n" "$xcat_dep_path" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$local_flag" ]
|
||||
then
|
||||
repo_xcat_core_path=$local_repo_path"/xcat-core"
|
||||
repo_xcat_dep_path=$local_repo_path"/xcat-dep"
|
||||
else
|
||||
printf "Usage: %s -c <core_trunk_path> [-d <dep_trunk_path>] -l <local-repo_path> [-a]\n" $(basename $0) >&2
|
||||
echo "-a Automatic: update only if there's any update on repo"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$a_flag" ]
|
||||
then
|
||||
touch svcupdate.trace
|
||||
SVCUP='svcupdate.trace'
|
||||
svn update $xcat_core_path 1> $SVCUP 2>&1
|
||||
if ! grep 'Tree is up to date' $SVCUP
|
||||
then
|
||||
update_core=1
|
||||
else
|
||||
update_core=
|
||||
fi
|
||||
rm -f $SVCUP
|
||||
else
|
||||
update_core=1
|
||||
fi
|
||||
if [ "$c_flag" -a "$update_core" ]
|
||||
then
|
||||
echo "###############################"
|
||||
echo "# Building xcat-core packages #"
|
||||
echo "###############################"
|
||||
|
||||
CMD_PATH=`pwd`
|
||||
cd $xcat_core_path
|
||||
./build-debs-all "snap" "Nightly_Builds"
|
||||
|
||||
echo "#################################"
|
||||
echo "# Creating xcat-core repository #"
|
||||
echo "#################################"
|
||||
|
||||
if [ -d $repo_xcat_core_path ]; then
|
||||
rm -rf $repo_xcat_core_path
|
||||
fi
|
||||
mkdir -p $repo_xcat_core_path/conf
|
||||
|
||||
find . -iname '*.deb' -exec mv {} $repo_xcat_core_path \;
|
||||
|
||||
rm -rf debs/
|
||||
cd $CMD_PATH
|
||||
|
||||
rm -rf $repo_xcat_core_path/conf/distributions
|
||||
|
||||
for dist in $dists; do
|
||||
cat << __EOF__ >> $repo_xcat_core_path/conf/distributions
|
||||
Origin: xCAT internal repository
|
||||
Label: xcat-core bazaar repository
|
||||
Codename: $dist
|
||||
Architectures: amd64
|
||||
Components: main
|
||||
Description: Repository automatically genereted conf
|
||||
|
||||
__EOF__
|
||||
done
|
||||
|
||||
cat << __EOF__ > $repo_xcat_core_path/conf/options
|
||||
verbose
|
||||
basedir .
|
||||
__EOF__
|
||||
|
||||
for dist in $dists; do
|
||||
for file in `ls $repo_xcat_core_path/*.deb`; do
|
||||
reprepro -b $repo_xcat_core_path includedeb $dist $file;
|
||||
done
|
||||
done
|
||||
|
||||
mv $xcat_core_path/latest_version $repo_xcat_core_path/xcat-core_latest-build
|
||||
|
||||
cat << '__EOF__' > $repo_xcat_core_path/mklocalrepo.sh
|
||||
codename=`lsb_release -a 2>null | grep Codename | awk '{print $2}'`
|
||||
cd `dirname $0`
|
||||
echo deb file://"`pwd`" $codename main > /etc/apt/sources.list.d/xcat-core.list
|
||||
__EOF__
|
||||
|
||||
chmod 775 $repo_xcat_core_path/mklocalrepo.sh
|
||||
rm -rf $repo_xcat_core_path/*.deb
|
||||
|
||||
if [ -z "$local_flag" ]
|
||||
then
|
||||
echo "###############################"
|
||||
echo "# Updating GSA xcat-core repo #"
|
||||
echo "###############################"
|
||||
lftp -e "mirror -R --delete-first $repo_xcat_core_path /projects/i/ipl-xcat/ubuntu/; exit;" -u $gsa_id,$gsa_passwd -p 22 sftp://ausgsa.ibm.com
|
||||
fi ### if [ -z "$local_flag" ]
|
||||
fi ### if [ "$a_flag" ]
|
||||
|
||||
if [ "$a_flag" -a "$d_flag" ]
|
||||
then
|
||||
touch svcupdate.trace
|
||||
SVCUP='svcupdate.trace'
|
||||
svn update $xcat_dep_path 1> $SVCUP 2>&1
|
||||
if ! grep 'Tree is up to date' $SVCUP
|
||||
then
|
||||
update_dep=1
|
||||
else
|
||||
update_dep=
|
||||
fi
|
||||
rm -f $SVCUP
|
||||
else
|
||||
update_dep=1
|
||||
fi
|
||||
if [ "$d_flag" -a "$update_dep" ]
|
||||
then
|
||||
echo "##############################"
|
||||
echo "# Building xcat-dep packages #"
|
||||
echo "##############################"
|
||||
|
||||
CMD_PATH=`pwd`
|
||||
cd $xcat_dep_path
|
||||
./build-debs-all "snap" "Nightly_Builds"
|
||||
|
||||
echo "################################"
|
||||
echo "# Creating xcat-dep repository #"
|
||||
echo "################################"
|
||||
rm -rf $repo_xcat_dep_path
|
||||
mkdir -p $repo_xcat_dep_path/conf
|
||||
find $xcat_dep_path -iname '*.deb' -exec cp {} $repo_xcat_dep_path \;
|
||||
|
||||
rm -rf $repo_xcat_core_path/conf/distributions
|
||||
|
||||
for dist in $dists; do
|
||||
cat << __EOF__ >> $repo_xcat_dep_path/conf/distributions
|
||||
Origin: xCAT internal repository
|
||||
Label: xcat-dep bazaar repository
|
||||
Codename: $dist
|
||||
Architectures: i386 amd64
|
||||
Components: main
|
||||
Description: Repository automatically genereted conf
|
||||
|
||||
__EOF__
|
||||
done
|
||||
|
||||
cat << __EOF__ > $repo_xcat_dep_path/conf/options
|
||||
verbose
|
||||
basedir .
|
||||
__EOF__
|
||||
|
||||
for dist in $dists; do
|
||||
for file in `ls $repo_xcat_dep_path/*.deb`; do
|
||||
reprepro -b $repo_xcat_dep_path includedeb $dist $file;
|
||||
done
|
||||
done
|
||||
|
||||
cat << '__EOF__' > $repo_xcat_dep_path/mklocalrepo.sh
|
||||
codename=`lsb_release -a 2>null | grep Codename | awk '{print $2}'`
|
||||
cd `dirname $0`
|
||||
echo deb file://"`pwd`" $codename main > /etc/apt/sources.list.d/xcat-dep.list
|
||||
__EOF__
|
||||
|
||||
chmod 775 $repo_xcat_dep_path/mklocalrepo.sh
|
||||
rm -rf $repo_xcat_dep_path/*.deb
|
||||
|
||||
if [ -z "$local_flag" ]
|
||||
then
|
||||
echo "##############################"
|
||||
echo "# Updating GSA xcat-dep repo #"
|
||||
echo "##############################"
|
||||
lftp -e "mirror -R --delete-first $repo_xcat_dep_path /projects/i/ipl-xcat/ubuntu/; exit;" -u $gsa_id,$gsa_passwd -p 22 sftp://ausgsa.ibm.com
|
||||
fi ### if [ -z "$local_flag" ]
|
||||
fi ### if [ "$d_flag" -a "$a_flag"]
|
||||
|
||||
if [ -z "$local_flag" ] # delete the temp repo after upload is done
|
||||
then
|
||||
rm -rf ./gsa-repo_temp
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -1,88 +0,0 @@
|
||||
#!/bin/bash
|
||||
###########
|
||||
#
|
||||
# This script call make<package>deb and create the deb packages
|
||||
# for xCAT
|
||||
#
|
||||
# Author: Leonardo Tonetto <tonetto@linux.vnet.ibm.com>
|
||||
# Revisor: Adalberto Medeiros <adalbas@linux.vnet.ibm.com>
|
||||
# Revisor2: Arif Ali <aali@ocf.co.uk>
|
||||
#
|
||||
# Input:
|
||||
#
|
||||
# $1 is the build type/location
|
||||
# $2 is the string added to the debian/changelog of each package
|
||||
#
|
||||
############
|
||||
|
||||
##############
|
||||
# Get input
|
||||
##############
|
||||
|
||||
PKG_LOCATION=$1 # local | snap | alpha
|
||||
if [ -z $PKG_LOCATION ]; then
|
||||
PKG_LOCATION="local"
|
||||
fi
|
||||
BUILD_STRING=$2
|
||||
if [ -z $BUILD_STRING ]; then
|
||||
BUILD_STRING="Personal Build"
|
||||
fi
|
||||
XCAT_VERSION=`cat Version`
|
||||
TRUNK_REVISION=`svnversion | cut -d ":" -f1`
|
||||
CUR_DATE=`date +%Y%m%d`
|
||||
VERSION="${XCAT_VERSION}-${PKG_LOCATION}${CUR_DATE}"
|
||||
|
||||
function makedeb {
|
||||
SRC_ROOT=$1
|
||||
PKG_LOCATION=$2
|
||||
BUILD_STRING=$3
|
||||
VERSION=$4
|
||||
|
||||
#
|
||||
# Make DEBs
|
||||
#
|
||||
# build perl-xCAT - deps are libsoap-lite-perl, libdigest-sha1-perl, libdbi-perl
|
||||
#
|
||||
|
||||
find $SRC_ROOT -maxdepth 2 -name debian -type d | while read DEBIAN_DIR
|
||||
do
|
||||
DIR=`echo ${DEBIAN_DIR} | sed -e 's/[/]debian$//'`
|
||||
cd ${DIR}
|
||||
dch -v $VERSION -b -c debian/changelog "$BUILD_STRING"
|
||||
dpkg-buildpackage
|
||||
cd -
|
||||
RC=$?
|
||||
if [ ${RC} -gt 0 ]
|
||||
then
|
||||
echo "Warning: ${DEBIAN_DIR} failed exit code ${RC}"
|
||||
fi
|
||||
done
|
||||
|
||||
#
|
||||
# Clean up
|
||||
#
|
||||
# Eliminate unnecessary directories and debian/files made by dpkg-buildpackage
|
||||
|
||||
find $SRC_ROOT -maxdepth 3 -type d -name "xcat-*" | grep debian | xargs rm -rf
|
||||
find $SRC_ROOT -maxdepth 3 -type f -name "files" | grep debian | xargs rm -f
|
||||
}
|
||||
|
||||
# build all debian packages
|
||||
packages="xCAT-client xCAT-nbroot xCAT-nbroot2 perl-xCAT xCAT-server xCAT-UI xCAT xCATsn xCAT-test xCAT-IBMhpc xCAT-rmc"
|
||||
|
||||
for file in `echo $packages`
|
||||
do
|
||||
makedeb $file $PKG_LOCATION "$BUILD_STRING" $VERSION
|
||||
done
|
||||
|
||||
if [ -d debs ]; then
|
||||
rm -rf debs
|
||||
fi
|
||||
|
||||
mkdir debs
|
||||
mv xcat* debs/
|
||||
mv perl-xcat* debs/
|
||||
|
||||
echo $VERSION > latest_version
|
||||
|
||||
exit 0
|
||||
+318
-160
@@ -1,264 +1,422 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# Update GSA Ubuntu Repositories or create a local repository
|
||||
#
|
||||
# Author: Leonardo Tonetto (tonetto@linux.vnet.ibm.com)
|
||||
# Revisor: Arif Ali (aali@ocf.co.uk)
|
||||
#
|
||||
# After running this script, add the following line to
|
||||
# /etc/apt/sources.list for local repository
|
||||
# deb file://<core_repo_path>/xcat-core/ maverick main
|
||||
# deb file://<dep_repo_path>/xcat-dep/ maverick main
|
||||
#
|
||||
# Getting Started:
|
||||
# - Check out the xcat-core svn repository (either the trunk or a branch) into
|
||||
# a dir called <rel>/src/xcat-core, where <rel> is the same as the release dir it will be
|
||||
# uploaded to in sourceforge (e.g. devel, or 2.3).
|
||||
# - You probably also want to put root's pub key from the build machine onto sourceforge for
|
||||
# the upload user listed below, so you don't have to keep entering pw's. You can do this
|
||||
# at https://sourceforge.net/account/ssh
|
||||
# - make sure reprepro is installed on the build machine
|
||||
# - Run this script from the local svn repository you just created. It will create the other directories that are needed.
|
||||
|
||||
# Usage: attr=value attr=value ... ./build-ubunturepo { -c | -d }
|
||||
# PROMOTE=1 - if the attribute "PROMOTE" is specified, means an official dot release. This does not
|
||||
# actually build xcat, just uploads the most recent snap build to https://sourceforge.net/projects/xcat/files/xcat/ .
|
||||
# If not specified, a snap build is assumed, which uploads to https://sourceforge.net/projects/xcat/files/yum/
|
||||
# or https://sourceforge.net/projects/xcat/files/aix/.
|
||||
# PREGA=1 - use this option with PROMOTE=1 on a branch that already has a released dot release, but this build is
|
||||
# a GA candidate build, not to be released yet. This will result in the tarball being uploaded to
|
||||
# https://sourceforge.net/projects/xcat/files/yum/ or https://sourceforge.net/projects/xcat/files/aix/
|
||||
# (but the tarball file name will be like a released tarball, not a snap build). When you are ready to
|
||||
# release this build, use PROMOTE=1 without PREGA
|
||||
# BUILDALL=1 - build all rpms, whether they changed or not. Should be used for snap builds that are in prep for a release.
|
||||
# UP=0 or UP=1 - override the default upload behavior
|
||||
#
|
||||
# For the dependency packages 1. please run the build-debs-all in xcat-dep svn first( there is usage detail in that script)
|
||||
# 2. run ./build-ubunturepo -d
|
||||
#
|
||||
############################
|
||||
printusage()
|
||||
{
|
||||
printf "Usage: %s {-c | -d} \n" $(basename $0) >&2
|
||||
echo " -c : Build the xcat core packages and create the repo"
|
||||
echo " -d : Create the xcat dep repo. Building the xcat dep packages can refer \"build-debs-all\" from svn"
|
||||
}
|
||||
# For the purpose of getting the distribution name
|
||||
. /etc/lsb-release
|
||||
|
||||
# Supported distributions
|
||||
dists="maverick natty oneiric precise "
|
||||
# Process cmd line variable assignments, assigning each attr=val pair to a variable of same name
|
||||
for i in $*; do
|
||||
echo $i | grep '='
|
||||
if [ $? != 0 ];then
|
||||
continue
|
||||
fi
|
||||
# upper case the variable name
|
||||
varstring=`echo "$i"|cut -d '=' -f 1|tr '[a-z]' '[A-Z]'`=`echo "$i"|cut -d '=' -f 2`
|
||||
export $varstring
|
||||
done
|
||||
|
||||
# Supported distributions
|
||||
dists="maverick natty oneiric precise saucy"
|
||||
|
||||
a_flag= # automatic flag - only update if repo was updated
|
||||
c_flag= # xcat-core (trunk-delvel) path
|
||||
d_flag= # xcat-dep (trunk) path
|
||||
u_flag= # gsa user-id
|
||||
p_flag= # gsa passwd
|
||||
local_flag= # build the repository localy
|
||||
r_flag= #genesis base rpm package path
|
||||
|
||||
while getopts 'c:d:u:p:l:a' OPTION
|
||||
while getopts 'cdr:' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
c) c_flag=1
|
||||
xcat_core_path="$OPTARG"
|
||||
;;
|
||||
d) d_flag=1
|
||||
xcat_dep_path="$OPTARG"
|
||||
;;
|
||||
u) u_flag=1
|
||||
gsa_id="$OPTARG"
|
||||
;;
|
||||
p) p_flag=1
|
||||
gsa_passwd="$OPTARG"
|
||||
;;
|
||||
l) local_flag=1
|
||||
local_repo_path="$OPTARG"
|
||||
;;
|
||||
a) a_flag=1
|
||||
;;
|
||||
|
||||
?) printf "Usage: %s -c <core_trunk_path> [-d <dep_trunk_path>] { -l <local-repo_path> | [-u <gsa_id> -p <gsa_passwd>] } [-a]\n" $(basename $0) >&2
|
||||
echo "-a Automatic: update only if there's any update on repo"
|
||||
r) r_flag=1
|
||||
genesis_rpm_path="$OPTARG"
|
||||
;;
|
||||
?) printusage
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
if [ -z "$c_flag" -a -z "$d_flag" ]
|
||||
then
|
||||
printf "Usage: %s -c <core_trunk_path> [-d <dep_trunk_path>] { -l <local-repo_path> | [-u <gsa_id> -p <gsa_passwd>] } [-a]\n" $(basename $0) >&2
|
||||
echo "-a Automatic: update only if there's any update on repo"
|
||||
exit 2
|
||||
fi
|
||||
if [ ! -d $xcat_core_path ]
|
||||
then
|
||||
printf "%s: No such directory\n" "$xcat_core_path" >&2
|
||||
if [ -z "$c_flag" -a -z "$d_flag" ];then
|
||||
printusage
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$d_flag" ]
|
||||
then
|
||||
if [ ! -d $xcat_dep_path ]
|
||||
then
|
||||
printf "%s: No such directory\n" "$xcat_dep_path" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [ "$c_flag" -a "$d_flag" ];then
|
||||
printusage
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$local_flag" ]
|
||||
then
|
||||
repo_xcat_core_path=$local_repo_path"/xcat-core"
|
||||
repo_xcat_dep_path=$local_repo_path"/xcat-dep"
|
||||
else
|
||||
if [ -z "$u_flag" ]
|
||||
then
|
||||
if [ "$p_flag" ]
|
||||
then
|
||||
printf "Usage: %s -c <core_trunk_path> [-d <dep_trunk_path>] { -l <local-repo_path> | [-u <gsa_id> -p <gsa_passwd>] } [-a]\n" $(basename $0) >&2
|
||||
echo "-a Automatic: update only if there's any update on repo"
|
||||
exit 2
|
||||
fi
|
||||
echo -n "GSA id: "
|
||||
read gsa_id
|
||||
echo -n "GSA password: "
|
||||
stty -echo; read gsa_passwd; stty echo;
|
||||
echo ""; echo "";
|
||||
fi
|
||||
uploader="bp-sawyers"
|
||||
# Find where this script is located to set some build variables
|
||||
old_pwd=`pwd`
|
||||
cd `dirname $0`
|
||||
curdir=`pwd`
|
||||
|
||||
repo_xcat_core_path="`pwd`/gsa-repo_temp/xcat-core"
|
||||
repo_xcat_dep_path="`pwd`/gsa-repo_temp/xcat-dep"
|
||||
#define the dep source code path, core build target path and dep build target path
|
||||
local_core_repo_path="$curdir/../../xcat-core"
|
||||
xcat_dep_path="$curdir/../../../xcat-dep/src/xcat-dep"
|
||||
local_dep_repo_path="$curdir/../../../xcat-dep/xcat-dep"
|
||||
|
||||
#define the url used for creating the source list file
|
||||
#define the upload dir used for uploading packages
|
||||
sf_repo_url="https://sourceforge.net/projects/xcat/files/ubuntu"
|
||||
sf_dir="/home/frs/project/x/xc/xcat"
|
||||
|
||||
#use flock to only one person build at the same time
|
||||
# Get a lock, so can not do 2 builds at once
|
||||
exec 8>/var/lock/xcatbld.lock
|
||||
if ! flock -n 8; then
|
||||
echo "Can't get lock /var/lock/xcatbld.lock. Someone else must be doing a build right now. Exiting...."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$a_flag" ]
|
||||
export HOME=/root
|
||||
|
||||
#sync the gpg key to the build machine local
|
||||
gsa_url=http://pokgsa.ibm.com/projects/x/xcat/build/linux
|
||||
mkdir -p $HOME/.gnupg
|
||||
for key_name in pubring.gpg secring.gpg trustdb.gpg; do
|
||||
if [ ! -f $HOME/.gnupg/$key_name ] || [ `wc -c $HOME/.gnupg/$key_name|cut -f 1 -d' '` == 0 ]; then
|
||||
rm -f $HOME/.gnupg/$key_name
|
||||
wget -P $HOME/.gnupg $gsa_url/keys/$key_name
|
||||
chmod 600 $HOME/.gnupg/$key_name
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$c_flag" ]
|
||||
then
|
||||
touch svcupdate.trace
|
||||
SVCUP='svcupdate.trace'
|
||||
svn update $xcat_core_path 1> $SVCUP 2>&1
|
||||
if ! grep 'Tree is up to date' $SVCUP
|
||||
then
|
||||
update_core=1
|
||||
# strip the /src/xcat-core from the end of the dir to get the next dir up and use as the release
|
||||
if [ -z "$REL" ]; then
|
||||
t=${curdir%/src/xcat-core}
|
||||
REL=`basename $t`
|
||||
fi
|
||||
|
||||
ver=`cat Version`
|
||||
if [ "$PROMOTE" != 1 ]; then
|
||||
code_change=0
|
||||
update_log=''
|
||||
#get the version
|
||||
if [ "$REL" = "xcat-core" ];then
|
||||
git_flag=1
|
||||
REL=`git rev-parse --abbrev-ref HEAD`
|
||||
if [ "$REL" = "master" ]; then
|
||||
REL="devel"
|
||||
fi
|
||||
if [ -z "$GITUP" ];then
|
||||
update_log=../coregitup
|
||||
echo "git pull > $update_log"
|
||||
git pull > $update_log
|
||||
else
|
||||
update_log=$GITUP
|
||||
fi
|
||||
|
||||
if ! grep -q 'Already up-to-date' $update_log; then
|
||||
code_change=1
|
||||
fi
|
||||
else
|
||||
git_flag=0
|
||||
if [ -z "$SVNUP" ]; then
|
||||
update_log=../coresvnup
|
||||
echo "svn up > $update_log"
|
||||
svn up > $update_log
|
||||
else
|
||||
update_log=$SVNUP
|
||||
fi
|
||||
|
||||
if ! grep -q 'At revision' $update_log;then
|
||||
code_change=1
|
||||
fi
|
||||
fi
|
||||
ver=`cat Version`
|
||||
short_ver=`cat Version|cut -d. -f 1,2`
|
||||
short_short_ver=`cat Version|cut -d. -f 1`
|
||||
|
||||
package_dir_name=debs$REL
|
||||
#TODO: define the core path and tarball name
|
||||
tarball_name="core-debs-snap.tar.bz2"
|
||||
|
||||
if [ $code_change == 0 -a "$UP" != 1 -a "$BUILDALL" != 1 ]; then
|
||||
echo "Nothing new detected"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "###############################"
|
||||
echo "# Building xcat-core packages #"
|
||||
echo "###############################"
|
||||
|
||||
#the package type: local | snap | alpha
|
||||
#the build introduce stirng
|
||||
pkg_type="snap"
|
||||
build_string="Snap_Build"
|
||||
cur_date=`date +%Y%m%d`
|
||||
pkg_version="${short_ver}-${pkg_type}${cur_date}"
|
||||
|
||||
if [ ! -d ../../$package_dir_name ];then
|
||||
mkdir -p "../../$package_dir_name"
|
||||
fi
|
||||
packages="xCAT-client xCAT-genesis-scripts perl-xCAT xCAT-server xCAT-UI xCAT xCATsn xCAT-test xCAT-OpenStack xCAT-OpenStack-baremetal"
|
||||
|
||||
for file in `echo $packages`
|
||||
do
|
||||
file_low=`echo $file | tr '[A-Z]' '[a-z]'`
|
||||
if grep -q $file $update_log || [ "$BUILDALL" == 1 -o "$file" = "perl-xCAT" ]; then
|
||||
rm -f ../../$package_dir_name/${file_low}_*.deb
|
||||
#only for genesis package
|
||||
rm -f ../../$package_dir_name/${file_low}-amd64_*.deb
|
||||
cd $file
|
||||
dch -v $pkg_version -b -c debian/changelog $build_string
|
||||
dpkg-buildpackage -uc -us
|
||||
rc=$?
|
||||
if [ $rc -gt 0 ]; then
|
||||
echo "Error: $file build package failed exit code $rc"
|
||||
fi
|
||||
cd -
|
||||
find $file -maxdepth 3 -type d -name "${file_low}*" | grep debian | xargs rm -rf
|
||||
find $file -maxdepth 3 -type f -name "files" | grep debian | xargs rm -rf
|
||||
mv ${file_low}* ../../$package_dir_name/
|
||||
fi
|
||||
done
|
||||
|
||||
find ../../$package_dir_name/* ! -name *.deb | xargs rm -f
|
||||
else
|
||||
update_core=
|
||||
if [ "$REL" = "xcat-core" ];then
|
||||
git_flag=1
|
||||
REL=`git rev-parse --abbrev-ref HEAD`
|
||||
if [ "$REL" = "master" ]; then
|
||||
REL="devel"
|
||||
fi
|
||||
fi
|
||||
package_dir_name=debs$REL
|
||||
fi
|
||||
rm -f $SVCUP
|
||||
else
|
||||
update_core=1
|
||||
fi
|
||||
if [ "$c_flag" -a "$update_core" ]
|
||||
then
|
||||
echo "###############################"
|
||||
echo "# Building xcat-core packages #"
|
||||
echo "###############################"
|
||||
|
||||
CMD_PATH=`pwd`
|
||||
cd $xcat_core_path
|
||||
./build-debs-all "snap" "Nightly_Builds"
|
||||
if [ "$PROMOTE" = 1 ]; then
|
||||
upload_dir="xcat-core"
|
||||
tar_name="xcat-core-$ver.tar.bz2"
|
||||
else
|
||||
upload_dir="core-snap"
|
||||
tar_name="core-debs-snap.tar.bz2"
|
||||
fi
|
||||
|
||||
echo "#################################"
|
||||
echo "# Creating xcat-core repository #"
|
||||
echo "#################################"
|
||||
|
||||
if [ -d $repo_xcat_core_path ]; then
|
||||
rm -rf $repo_xcat_core_path
|
||||
#clean the repo directory
|
||||
if [ -e $local_core_repo_path ]; then
|
||||
rm -rf $local_core_repo_path
|
||||
fi
|
||||
mkdir -p $repo_xcat_core_path/conf
|
||||
|
||||
find . -iname '*.deb' -exec mv {} $repo_xcat_core_path \;
|
||||
|
||||
rm -rf debs/
|
||||
cd $CMD_PATH
|
||||
|
||||
rm -rf $repo_xcat_core_path/conf/distributions
|
||||
mkdir -p $local_core_repo_path
|
||||
cd $local_core_repo_path
|
||||
mkdir conf
|
||||
|
||||
for dist in $dists; do
|
||||
cat << __EOF__ >> $repo_xcat_core_path/conf/distributions
|
||||
cat << __EOF__ >> conf/distributions
|
||||
Origin: xCAT internal repository
|
||||
Label: xcat-core bazaar repository
|
||||
Codename: $dist
|
||||
Architectures: amd64 i386
|
||||
Architectures: amd64
|
||||
Components: main
|
||||
Description: Repository automatically genereted conf
|
||||
SignWith: yes
|
||||
|
||||
__EOF__
|
||||
done
|
||||
|
||||
cat << __EOF__ > $repo_xcat_core_path/conf/options
|
||||
cat << __EOF__ > conf/options
|
||||
verbose
|
||||
ask-passphrase
|
||||
basedir .
|
||||
__EOF__
|
||||
|
||||
#import the deb packages into the repo
|
||||
for dist in $dists; do
|
||||
for file in `ls $repo_xcat_core_path/*.deb`; do
|
||||
reprepro -b $repo_xcat_core_path includedeb $dist $file;
|
||||
for file in `ls ../$package_dir_name/*.deb`; do
|
||||
reprepro -b ./ includedeb $dist $file;
|
||||
done
|
||||
done
|
||||
|
||||
mv $xcat_core_path/latest_version $repo_xcat_core_path/xcat-core_latest-build
|
||||
|
||||
cat << '__EOF__' > $repo_xcat_core_path/mklocalrepo.sh
|
||||
#create the mklocalrepo script
|
||||
cat << '__EOF__' > mklocalrepo.sh
|
||||
. /etc/lsb-release
|
||||
cd `dirname $0`
|
||||
echo deb file://"`pwd`" $DISTRIB_CODENAME main > /etc/apt/sources.list.d/xcat-core.list
|
||||
__EOF__
|
||||
|
||||
chmod 775 $repo_xcat_core_path/mklocalrepo.sh
|
||||
rm -rf $repo_xcat_core_path/*.deb
|
||||
chmod 775 mklocalrepo.sh
|
||||
|
||||
if [ -z "$local_flag" ]
|
||||
then
|
||||
echo "###############################"
|
||||
echo "# Updating GSA xcat-core repo #"
|
||||
echo "###############################"
|
||||
lftp -e "mirror -R --delete-first $repo_xcat_core_path /projects/i/ipl-xcat/ubuntu/; exit;" -u $gsa_id,$gsa_passwd -p 22 sftp://ausgsa.ibm.com
|
||||
fi ### if [ -z "$local_flag" ]
|
||||
fi ### if [ "$a_flag" ]
|
||||
#create the xcat-core.list file
|
||||
#echo "deb ${sf_repo_url}/${REL}/${upload_dir}/ precise main" > xcat-core.list
|
||||
|
||||
if [ "$a_flag" -a "$d_flag" ]
|
||||
then
|
||||
touch svcupdate.trace
|
||||
SVCUP='svcupdate.trace'
|
||||
svn update $xcat_dep_path 1> $SVCUP 2>&1
|
||||
if ! grep 'Tree is up to date' $SVCUP
|
||||
then
|
||||
update_dep=1
|
||||
else
|
||||
update_dep=
|
||||
cd ../
|
||||
if ! grep xcat /etc/group ; then
|
||||
groupadd xcat
|
||||
fi
|
||||
|
||||
chgrp -R root xcat-core
|
||||
chmod -R g+w xcat-core
|
||||
|
||||
#build the tar ball
|
||||
tar -hjcf $tar_name xcat-core
|
||||
chgrp root $tar_name
|
||||
chmod g+w $tar_name
|
||||
|
||||
if [ ! -e core-snap ]; then
|
||||
ln -s xcat-core core-snap
|
||||
fi
|
||||
rm -f $SVCUP
|
||||
else
|
||||
update_dep=1
|
||||
|
||||
# Decide whether to upload or not
|
||||
if [ -n "$UP" ] && [ "$UP" == 0 ]; then
|
||||
echo "No need to upload"
|
||||
cd $old_pwd
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#upload the deb packages
|
||||
if [ "$REL" = "devel" -o "$PREGA" != 1 ]; then
|
||||
i=0
|
||||
echo "Uploading RPMs from $upload_dir to ${sf_dir}/ubuntu/${REL}/ ..."
|
||||
while [ $((i+=1)) -le 5 ] && ! rsync -urLv --delete $upload_dir ${uploader},xcat@web.sourceforge.net:${sf_dir}/ubuntu/${REL}/
|
||||
do : ; done
|
||||
fi
|
||||
|
||||
#upload the tar ball
|
||||
#for the GA build, upload to https://sourceforge.net/projects/xcat/files/xcat/<version>.x_Ubuntu/
|
||||
#for other scenario, upload to https://sourceforge.net/projects/xcat/files/ubuntu/<version>
|
||||
if [ "$PROMOTE" = 1 -a "$REL" != "devel" -a "$PREGA" != 1 ]; then
|
||||
i=0
|
||||
echo "Uploading $tar_name to ${sf_dir}/xcat/${REL}.x_Ubuntu/ ..."
|
||||
while [ $((i+=1)) -le 5 ] && ! rsync -v $tar_name ${uploader},xcat@web.sourceforge.net:${sf_dir}/xcat/${REL}.x_Ubuntu/
|
||||
do : ; done
|
||||
else
|
||||
i=0
|
||||
echo "Uploading $tar_name to ${sf_dir}/ubuntu/${REL}/ ..."
|
||||
while [ $((i+=1)) -le 5 ] && ! rsync -v $tar_name ${uploader},xcat@web.sourceforge.net:${sf_dir}/ubuntu/${REL}/
|
||||
do : ; done
|
||||
fi
|
||||
|
||||
cd $old_pwd
|
||||
fi
|
||||
if [ "$d_flag" -a "$update_dep" ]
|
||||
|
||||
if [ "$d_flag" ]
|
||||
then
|
||||
echo "##############################"
|
||||
echo "# Building xcat-dep packages #"
|
||||
echo "##############################"
|
||||
|
||||
CMD_PATH=`pwd`
|
||||
cd $xcat_dep_path
|
||||
./build-debs-all "snap" "Nightly_Builds"
|
||||
|
||||
echo "################################"
|
||||
echo "# Creating xcat-dep repository #"
|
||||
echo "################################"
|
||||
rm -rf $repo_xcat_dep_path
|
||||
mkdir -p $repo_xcat_dep_path/conf
|
||||
find $xcat_dep_path -iname '*.deb' -exec cp {} $repo_xcat_dep_path \;
|
||||
|
||||
rm -rf $repo_xcat_core_path/conf/distributions
|
||||
#clean all old files
|
||||
if [ -e $local_dep_repo_path ];then
|
||||
rm -rf $local_dep_repo_path
|
||||
fi
|
||||
mkdir -p $local_dep_repo_path
|
||||
cd $local_dep_repo_path
|
||||
mkdir conf
|
||||
|
||||
#create the conf/distributions file
|
||||
for dist in $dists; do
|
||||
cat << __EOF__ >> $repo_xcat_dep_path/conf/distributions
|
||||
cat << __EOF__ >> conf/distributions
|
||||
Origin: xCAT internal repository
|
||||
Label: xcat-dep bazaar repository
|
||||
Codename: $dist
|
||||
Architectures: i386 amd64
|
||||
Architectures: amd64
|
||||
Components: main
|
||||
Description: Repository automatically genereted conf
|
||||
SignWith: yes
|
||||
|
||||
__EOF__
|
||||
done
|
||||
done
|
||||
|
||||
cat << __EOF__ > $repo_xcat_dep_path/conf/options
|
||||
cat << __EOF__ > conf/options
|
||||
verbose
|
||||
ask-passphrase
|
||||
basedir .
|
||||
__EOF__
|
||||
|
||||
for dist in $dists; do
|
||||
for file in `ls $repo_xcat_dep_path/*.deb`; do
|
||||
reprepro -b $repo_xcat_dep_path includedeb $dist $file;
|
||||
for file in `ls ../debs/*.deb`; do
|
||||
reprepro -b ./ includedeb $dist $file;
|
||||
done
|
||||
done
|
||||
|
||||
cat << '__EOF__' > $repo_xcat_dep_path/mklocalrepo.sh
|
||||
cat << '__EOF__' > mklocalrepo.sh
|
||||
. /etc/lsb-release
|
||||
cd `dirname $0`
|
||||
echo deb file://"`pwd`" $DISTRIB_CODENAME main > /etc/apt/sources.list.d/xcat-dep.list
|
||||
__EOF__
|
||||
|
||||
chmod 775 $repo_xcat_dep_path/mklocalrepo.sh
|
||||
rm -rf $repo_xcat_dep_path/*.deb
|
||||
chmod 775 mklocalrepo.sh
|
||||
|
||||
if [ -z "$local_flag" ]
|
||||
then
|
||||
echo "##############################"
|
||||
echo "# Updating GSA xcat-dep repo #"
|
||||
echo "##############################"
|
||||
lftp -e "mirror -R --delete-first $repo_xcat_dep_path /projects/i/ipl-xcat/ubuntu/; exit;" -u $gsa_id,$gsa_passwd -p 22 sftp://ausgsa.ibm.com
|
||||
fi ### if [ -z "$local_flag" ]
|
||||
fi ### if [ "$d_flag" -a "$a_flag"]
|
||||
#echo ""deb ${sf_repo_url}/xcat-dep/ precise main"" > xcat-dep.list
|
||||
|
||||
if [ -z "$local_flag" ] # delete the temp repo after upload is done
|
||||
then
|
||||
rm -rf ./gsa-repo_temp
|
||||
cd ..
|
||||
if ! grep xcat /etc/group ; then
|
||||
groupadd xcat
|
||||
fi
|
||||
|
||||
chgrp -R root xcat-dep
|
||||
chmod -R g+w xcat-dep
|
||||
|
||||
#create the tar ball
|
||||
dep_tar_name=xcat-dep-ubuntu.tar.bz
|
||||
tar -hjcf $dep_tar_name xcat-dep
|
||||
chgrp root $dep_tar_name
|
||||
chmod g+w $dep_tar_name
|
||||
|
||||
if [ -n "$UP" ] && [ "$UP" == 0 ];then
|
||||
echo "No need to upload the dep packages"
|
||||
cd $old_pwd
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#upload the dep packages
|
||||
i=0
|
||||
echo "Uploading debs from xcat-dep to ${sf_dir}/ubuntu/xcat-dep/ ..."
|
||||
while [ $((i+=1)) -le 5 ] && ! rsync -urLv --delete xcat-dep ${uploader},xcat@web.sourceforge.net:${sf_dir}/ubuntu/
|
||||
do : ; done
|
||||
#upload the tarball
|
||||
i=0
|
||||
echo "Uploading $dep_tar_name to ${sf_dir}/xcat-dep/2.x_Ubuntu/ ..."
|
||||
while [ $((i+=1)) -le 5 ] && ! rsync -v $dep_tar_name ${uploader},xcat@web.sourceforge.net:${sf_dir}/xcat-dep/2.x_Ubuntu/
|
||||
do : ; done
|
||||
cd $old_pwd
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
+31
-18
@@ -41,7 +41,7 @@ UPLOADUSER=bp-sawyers
|
||||
FRS=/home/frs/project/x/xc/xcat
|
||||
|
||||
# These are the rpms that should be built for each kind of xcat build
|
||||
ALLBUILD="perl-xCAT xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit xCAT xCATsn xCAT-genesis-scripts"
|
||||
ALLBUILD="perl-xCAT xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit xCAT xCATsn xCAT-genesis-scripts xCAT-OpenStack xCAT-SoftLayer xCAT-OpenStack-baremetal"
|
||||
ZVMBUILD="perl-xCAT xCAT-server xCAT-UI"
|
||||
ZVMLINK="xCAT-client xCAT xCATsn"
|
||||
PCMBUILD="xCAT"
|
||||
@@ -137,8 +137,10 @@ SRCD=core-snap-srpms
|
||||
# currently aix builds ppc rpms, but someday it should build noarch
|
||||
if [ "$OSNAME" = "AIX" ]; then
|
||||
NOARCH=ppc
|
||||
SYSGRP=system
|
||||
else
|
||||
NOARCH=noarch
|
||||
SYSGRP=root
|
||||
fi
|
||||
|
||||
function setversionvars {
|
||||
@@ -183,6 +185,11 @@ if [ "$GIT" = "1" ]; then # using git
|
||||
GITUP=../coregitup
|
||||
echo "git pull > $GITUP"
|
||||
git pull > $GITUP
|
||||
if [[ $? != 0 ]]; then
|
||||
# do not continue so we do not build with old files
|
||||
echo "The 'git pull' command failed. Exiting the build."
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
if ! $GREP 'Already up-to-date' $GITUP; then
|
||||
SOMETHINGCHANGED=1
|
||||
@@ -230,7 +237,7 @@ if [ "$OSNAME" = "AIX" ]; then
|
||||
fi
|
||||
|
||||
# Build the rest of the noarch rpms
|
||||
for rpmname in xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit; do
|
||||
for rpmname in xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-UI xCAT-test xCAT-buildkit xCAT-SoftLayer; do
|
||||
#if [ "$EMBED" = "zvm" -a "$rpmname" != "xCAT-server" -a "$rpmname" != "xCAT-UI" ]; then continue; fi # for zvm embedded env only need to build server and UI
|
||||
if [[ " $EMBEDBUILD " != *\ $rpmname\ * ]]; then continue; fi
|
||||
if [ "$OSNAME" = "AIX" -a "$rpmname" = "xCAT-buildkit" ]; then continue; fi # do not build xCAT-buildkit on aix
|
||||
@@ -265,17 +272,19 @@ if [ "$OSNAME" != "AIX" ]; then
|
||||
fi
|
||||
|
||||
# Build the xCAT and xCATsn rpms for all platforms
|
||||
for rpmname in xCAT xCATsn; do
|
||||
for rpmname in xCAT xCATsn xCAT-OpenStack xCAT-OpenStack-baremetal; do
|
||||
#if [ "$EMBED" = "zvm" ]; then break; fi
|
||||
if [[ " $EMBEDBUILD " != *\ $rpmname\ * ]]; then continue; fi
|
||||
if [ $SOMETHINGCHANGED == 1 -o "$BUILDALL" == 1 ]; then # used to be: if $GREP -E "^[UAD] +$rpmname/" $GITUP; then
|
||||
UPLOAD=1
|
||||
ORIGFAILEDRPMS="$FAILEDRPMS"
|
||||
if [ "$OSNAME" = "AIX" ]; then
|
||||
if [ "$rpmname" = "xCAT-OpenStack" ] || [ "$rpmname" = "xCAT-OpenStack-baremetal" ]; then continue; fi # do not bld openstack on aix
|
||||
./makerpm $rpmname "$EMBED"
|
||||
if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname"; fi
|
||||
else
|
||||
for arch in x86_64 ppc64 s390x; do
|
||||
if [ "$rpmname" = "xCAT-OpenStack" -a "$arch" != "x86_64" ] || [ "$rpmname" = "xCAT-OpenStack-baremetal" -a "$arch" != "x86_64" ] ; then continue; fi # only bld openstack for x86_64 for now
|
||||
./makerpm $rpmname $arch "$EMBED"
|
||||
if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname-$arch"; fi
|
||||
done
|
||||
@@ -346,9 +355,9 @@ if [ "$OSNAME" != "AIX" ]; then
|
||||
echo '%_gpg_name Jarrod Johnson' >> $MACROS
|
||||
fi
|
||||
echo "Signing RPMs..."
|
||||
build-utils/rpmsign.exp `find $DESTDIR -type f -name '*.rpm'` | grep -v -E '(was already signed|rpm --quiet --resign|WARNING: standard input reopened)'
|
||||
build-utils/rpmsign.exp $SRCDIR/*rpm | grep -v -E '(was already signed|rpm --quiet --resign|WARNING: standard input reopened)'
|
||||
createrepo --checksum sha $DESTDIR # specifying checksum so the repo will work on rhel5
|
||||
build-utils/rpmsign.exp `find $DESTDIR -type f -name '*.rpm'` | grep -v -E '(already contains identical signature|was already signed|rpm --quiet --resign|WARNING: standard input reopened)'
|
||||
build-utils/rpmsign.exp $SRCDIR/*rpm | grep -v -E '(already contains identical signature|was already signed|rpm --quiet --resign|WARNING: standard input reopened)'
|
||||
createrepo --checksum sha $DESTDIR # specifying checksum so the repo will work on rhel5
|
||||
createrepo --checksum sha $SRCDIR
|
||||
rm -f $SRCDIR/repodata/repomd.xml.asc
|
||||
rm -f $DESTDIR/repodata/repomd.xml.asc
|
||||
@@ -362,20 +371,13 @@ if [ "$OSNAME" != "AIX" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# make everything have a group of xcat, so anyone can manage them once they get on SF
|
||||
# set group and permissions correctly on the built rpms
|
||||
if [ "$OSNAME" = "AIX" ]; then
|
||||
if ! lsgroup xcat >/dev/null 2>&1; then
|
||||
mkgroup xcat
|
||||
fi
|
||||
chmod +x $DESTDIR/instxcat
|
||||
else # linux
|
||||
if ! $GREP xcat /etc/group; then
|
||||
groupadd xcat
|
||||
fi
|
||||
fi
|
||||
chgrp -R xcat $DESTDIR
|
||||
chgrp -R $SYSGRP $DESTDIR
|
||||
chmod -R g+w $DESTDIR
|
||||
chgrp -R xcat $SRCDIR
|
||||
chgrp -R $SYSGRP $SRCDIR
|
||||
chmod -R g+w $SRCDIR
|
||||
|
||||
else # end of very long if-not-promote
|
||||
@@ -428,14 +430,17 @@ else
|
||||
verboseflag=""
|
||||
fi
|
||||
echo "Creating $TARNAME ..."
|
||||
if [[ -e $TARNAME ]]; then
|
||||
mkdir -p previous
|
||||
mv -f $TARNAME previous
|
||||
fi
|
||||
if [ "$OSNAME" = "AIX" ]; then
|
||||
tar $verboseflag -hcf ${TARNAME%.gz} $XCATCORE
|
||||
rm -f $TARNAME
|
||||
gzip ${TARNAME%.gz}
|
||||
else
|
||||
tar $verboseflag -hjcf $TARNAME $XCATCORE
|
||||
fi
|
||||
chgrp xcat $TARNAME
|
||||
chgrp $SYSGRP $TARNAME
|
||||
chmod g+w $TARNAME
|
||||
|
||||
# Decide whether to upload or not
|
||||
@@ -490,8 +495,16 @@ if [ "$OSNAME" != "AIX" -a "$REL" = "devel" -a "$PROMOTE" != 1 -a -z "$EMBED" ];
|
||||
rpm2cpio ../$XCATCORE/perl-xCAT-*.$NOARCH.rpm | cpio -id '*.html'
|
||||
rpm2cpio ../$XCATCORE/xCAT-test-*.$NOARCH.rpm | cpio -id '*.html'
|
||||
rpm2cpio ../$XCATCORE/xCAT-buildkit-*.$NOARCH.rpm | cpio -id '*.html'
|
||||
rpm2cpio ../$XCATCORE/xCAT-OpenStack-*.x86_64.rpm | cpio -id '*.html'
|
||||
rpm2cpio ../$XCATCORE/xCAT-SoftLayer-*.$NOARCH.rpm | cpio -id '*.html'
|
||||
i=0
|
||||
while [ $((i+=1)) -le 5 ] && ! rsync $verboseflag -r opt/xcat/share/doc/man1 opt/xcat/share/doc/man3 opt/xcat/share/doc/man5 opt/xcat/share/doc/man7 opt/xcat/share/doc/man8 $UPLOADUSER,xcat@web.sourceforge.net:htdocs/
|
||||
do : ; done
|
||||
|
||||
# extract and upload the tools readme
|
||||
rpm2cpio ../$XCATCORE/xCAT-server-*.$NOARCH.rpm | cpio -id ./opt/xcat/share/xcat/tools/README.html
|
||||
i=0
|
||||
while [ $((i+=1)) -le 5 ] && ! rsync $verboseflag opt/xcat/share/xcat/tools/README.html $UPLOADUSER,xcat@web.sourceforge.net:htdocs/tools/
|
||||
do : ; done
|
||||
cd ..
|
||||
fi
|
||||
|
||||
+41
-29
@@ -97,15 +97,15 @@ if [ "$OSNAME" != "AIX" ]; then
|
||||
|
||||
# Sign the rpms that are not already signed. The "standard input reopened" warnings are normal.
|
||||
echo "Signing RPMs..."
|
||||
$XCATCOREDIR/build-utils/rpmsign.exp `find . -type f -name '*.rpm'` | grep -v -E '(was already signed|rpm --quiet --resign|WARNING: standard input reopened)'
|
||||
$XCATCOREDIR/build-utils/rpmsign.exp `find . -type f -name '*.rpm'` | grep -v -E '(already contains identical signature|was already signed|rpm --quiet --resign|WARNING: standard input reopened)'
|
||||
|
||||
# Create the repodata dirs
|
||||
echo "Creating repodata directories..."
|
||||
for i in `find -mindepth 2 -maxdepth 2 -type d `; do
|
||||
if [ -n "$VERBOSEMODE" ]; then
|
||||
createrepo $i
|
||||
createrepo --checksum sha $i # specifying checksum so the repo will work on rhel5
|
||||
else
|
||||
createrepo $i >/dev/null
|
||||
createrepo --checksum sha $i >/dev/null
|
||||
fi
|
||||
rm -f $i/repodata/repomd.xml.asc
|
||||
gpg -a --detach-sign $i/repodata/repomd.xml
|
||||
@@ -138,8 +138,21 @@ if [ "$PERLVER" == "v5.8.2" ]; then
|
||||
OSVER='5.3'
|
||||
elif [ "$PERLVER" == "v5.8.8" ]; then
|
||||
OSVER='6.1'
|
||||
aixver=`lslpp -lc|grep 'bos.rte:'|head -1|cut -d: -f3`
|
||||
if [[ $aixver < '6.1.9.0' ]]; then
|
||||
AIX61Y=0
|
||||
else
|
||||
AIX61Y=1
|
||||
fi
|
||||
elif [ "$PERLVER" == "v5.10.1" ]; then
|
||||
OSVER='7.1'
|
||||
aixver=`lslpp -lc|grep 'bos.rte:'|head -1|cut -d: -f3`
|
||||
if [[ $aixver < '7.1.3.0' ]]; then
|
||||
AIX71L=0
|
||||
else
|
||||
AIX71L=1
|
||||
fi
|
||||
|
||||
else
|
||||
echo "Error: the perl version of '$PERLVER' is not one that instoss understands. Exiting..."
|
||||
exit 2
|
||||
@@ -149,33 +162,37 @@ cd $OSVER
|
||||
# The only interdependency between the dep rpms so far is that net-snmp requires bash, and
|
||||
# pyodbc requires unixODBC. (The bash dependency is taken care of automatically because it
|
||||
# comes earlier in the alphabet.)
|
||||
|
||||
# first run /usr/sbin/updtvpkg to make sure any installp software is
|
||||
# registered with RPM.
|
||||
echo "Running updtvpkg. This could take a few minutes."
|
||||
/usr/sbin/updtvpkg
|
||||
echo "updtvpkg has completed."
|
||||
|
||||
# unixODBC is required by pyodbc, so install it first
|
||||
rpm -Uvh unixODBC*
|
||||
for i in `ls *.rpm|grep -v -E '^tcl-|^tk-|^expect-|^unixODBC-|^xCAT-UI-deps|^perl-DBD-DB2Lite'`; do
|
||||
# Now install the bulk of the rpms, one at a time, in case some are already installed
|
||||
for i in `ls *.rpm|grep -v -E '^tcl-|^tk-|^expect-|^unixODBC-|^xCAT-UI-deps|^perl-DBD-DB2Lite|^net-snmp'`; do
|
||||
if [ "$i" == "perl-Net-DNS-0.66-1.aix5.3.ppc.rpm" ]; then
|
||||
opts="--nodeps"
|
||||
else
|
||||
opts=""
|
||||
fi
|
||||
|
||||
# just in case we need it sometime, this next if stmt would mean: if it does not start with perl-DBD-DB2
|
||||
#if [ "${i#perl-DBD-DB2}" == "$i" ]; then
|
||||
|
||||
# On 7.1L and 6.1Y we need a newer version of perl-Net_SSLeay.pm
|
||||
if [[ $AIX71L -eq 1 || $AIX61Y -eq 1 ]]; then
|
||||
if [[ $i == perl-Net_SSLeay.pm-1.30-* ]]; then continue; fi # skip the old rpm
|
||||
else
|
||||
if [[ $i == perl-Net_SSLeay.pm-1.55-* ]]; then continue; fi # skip the new rpm
|
||||
fi
|
||||
|
||||
echo rpm -Uvh $opts $i
|
||||
rpm -Uvh $opts $i
|
||||
done
|
||||
# don't try to install tcl, tk, or expect if they are already installed!
|
||||
# this section about expect/tcl/tk can be removed once 2.8 releases, because 2.8 no longer requires expect
|
||||
lslpp -l | grep expect.base > /dev/null 2>&1
|
||||
if [ $? -gt 0 ]; then
|
||||
if [ "$OSVER" == "5.3" ]; then
|
||||
for i in tcl-*.rpm tk-*.rpm expect-*.rpm; do
|
||||
echo rpm -Uvh $i
|
||||
rpm -Uvh $i
|
||||
done
|
||||
else
|
||||
echo "The expect.base, tcl.base, and tk.base filesets must also be installed before installing the xCAT RPMs from xcat-core."
|
||||
fi
|
||||
fi
|
||||
# Have to upgrade all of the net-snmp rpms together because they depend on each other.
|
||||
# Also, they require bash, so do it after the loop, rather than before
|
||||
rpm -Uvh net-snmp*
|
||||
|
||||
EOF
|
||||
# end of instoss file content ---------------------------------------------
|
||||
|
||||
@@ -183,18 +200,13 @@ EOF
|
||||
chmod +x instoss
|
||||
fi
|
||||
|
||||
# Get the permissions correct. Have to have all dirs/files with a group of xcat
|
||||
# and have them writeable by group, so any member of the xcat can build.
|
||||
# Get the permissions and group correct
|
||||
if [ "$OSNAME" == "AIX" ]; then
|
||||
if ! lsgroup xcat >/dev/null 2>&1; then
|
||||
mkgroup xcat
|
||||
fi
|
||||
SYSGRP=system
|
||||
else
|
||||
if ! $GREP xcat /etc/group; then
|
||||
groupadd xcat
|
||||
fi
|
||||
SYSGRP=root
|
||||
fi
|
||||
chgrp -R xcat *
|
||||
chgrp -R -h $SYSGRP *
|
||||
chmod -R g+w *
|
||||
|
||||
# Build the tarball
|
||||
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
#######################################################################
|
||||
#build script for local usage
|
||||
#used for Linux/AIX/Ubuntu
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
|
||||
OSNAME=$(uname)
|
||||
NAMEALL=$(uname -a)
|
||||
|
||||
echo "OSNAME is $OSNAME!"
|
||||
echo "NAMEALL is $NAMEALL"
|
||||
|
||||
ls /code/xcat-core
|
||||
|
||||
if [ $? -gt 0 ]; then
|
||||
echo "Error:no repo exist, exit 1."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get a lock, so can not do 2 builds at once
|
||||
exec 8>/var/lock/xcatbld.lock
|
||||
if ! flock -n 8; then
|
||||
echo "Can't get lock /var/lock/xcatbld.lock. Someone else must be doing a build right now. Exiting...."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#used only for hard code, will change later
|
||||
cd /code/xcat-core
|
||||
|
||||
rm -rf build/
|
||||
|
||||
echo "==============================================="
|
||||
echo $NAMEALL | egrep "Ubuntu"
|
||||
|
||||
#Check if it is an Ubuntu system
|
||||
if [ $? -eq 0 ]; then
|
||||
|
||||
echo "This is an Ubuntu system"
|
||||
pkg_type="snap"
|
||||
build_string="Snap_Build"
|
||||
cur_date=`date +%Y%m%d`
|
||||
short_ver=`cat Version|cut -d. -f 1,2`
|
||||
pkg_version="${short_ver}-${pkg_type}${cur_date}"
|
||||
|
||||
mkdir -p /code/xcat-core/build
|
||||
|
||||
for rpmname in xCAT-client xCAT-genesis-scripts perl-xCAT xCAT-server xCAT xCATsn xCAT-test; do
|
||||
rpmname_low=`echo $rpmname | tr '[A-Z]' '[a-z]'`
|
||||
echo "============================================"
|
||||
echo "$rpmname_low"
|
||||
cd $rpmname
|
||||
dch -v $pkg_version -b -c debian/changelog $build_string
|
||||
dpkg-buildpackage -uc -us
|
||||
rc=$?
|
||||
if [ $rc -gt 0 ]; then
|
||||
echo "Error: $rpmname build package failed exit code $rc"
|
||||
fi
|
||||
cd -
|
||||
mv ${rpmname_low}* /code/xcat-core/build
|
||||
|
||||
done
|
||||
#delete all files except .deb file
|
||||
find /code/xcat-core/build/* ! -name *.deb | xargs rm -f
|
||||
|
||||
else
|
||||
#This is not an Ubuntu system
|
||||
echo "This is an $OSNAME system"
|
||||
|
||||
rm -rf /root/rpmbuild/RPMS/noarch/*
|
||||
rm -rf /root/rpmbuild/RPMS/x86_64/*
|
||||
rm -rf /root/rpmbuild/RPMS/ppc64/*
|
||||
mkdir build/
|
||||
# Build the rest of the noarch rpms
|
||||
for rpmname in xCAT-client xCAT-server xCAT-IBMhpc xCAT-rmc xCAT-test xCAT-buildkit; do
|
||||
if [ "$OSNAME" = "AIX" -a "$rpmname" = "xCAT-buildkit" ]; then continue; fi
|
||||
./makerpm $rpmname
|
||||
done
|
||||
|
||||
#build xCAT-genesis-scripts if it is x86_64 platform
|
||||
ARCH=$(uname -p)
|
||||
if [ "$ARCH" = "x64_64" ]; then
|
||||
./makerpm xCAT-genesis-scripts x86_64
|
||||
fi
|
||||
|
||||
|
||||
# Build the xCAT and xCATsn rpms for all platforms
|
||||
for rpmname in xCAT xCATsn; do
|
||||
if [ "$OSNAME" = "AIX" ]; then
|
||||
./makerpm $rpmname
|
||||
if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname"; fi
|
||||
else
|
||||
for arch in x86_64 ppc64 s390x; do
|
||||
./makerpm $rpmname $arch
|
||||
if [ $? -ne 0 ]; then FAILEDRPMS="$FAILEDRPMS $rpmname-$arch"; fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
cp /root/rpmbuild/RPMS/noarch/* build/
|
||||
cp /root/rpmbuild/RPMS/x86_64/* build/
|
||||
cp /root/rpmbuild/RPMS/ppc64/* build/
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
<packagereq type="required">xCAT-server</packagereq>
|
||||
<packagereq type="required">xCAT-client</packagereq>
|
||||
<packagereq type="required">perl-xCAT</packagereq>
|
||||
<packagereq type="required">xCAT-nbroot-core-x86_64</packagereq>
|
||||
<packagereq type="required">xCAT-nbroot-core-x86</packagereq>
|
||||
<packagereq type="optional">xCAT-nbroot-core-ppc64</packagereq>
|
||||
</packagelist>
|
||||
</group>
|
||||
</comps>
|
||||
|
||||
@@ -24,7 +24,7 @@ function makenoarch {
|
||||
else # linux
|
||||
echo "Building $RPMROOT/RPMS/noarch/$RPMNAME-$VER-snap*.noarch.rpm $EMBEDTXT..."
|
||||
tar --exclude .svn -czf $RPMROOT/SOURCES/$RPMNAME-$VER.tar.gz $RPMNAME
|
||||
rm -f $RPMROOT/SRPMS/xCAT-server-$VER*rpm $RPMROOT/RPMS/noarch/$RPMNAME-$VER*rpm
|
||||
rm -f $RPMROOT/SRPMS/$RPMNAME-$VER*rpm $RPMROOT/RPMS/noarch/$RPMNAME-$VER*rpm
|
||||
rpmbuild $QUIET -ta $RPMROOT/SOURCES/$RPMNAME-$VER.tar.gz
|
||||
RC=$?
|
||||
fi
|
||||
@@ -32,7 +32,7 @@ function makenoarch {
|
||||
|
||||
|
||||
|
||||
# Make one of the following rpms: xCAT, xCATsn, xCAT-buildkit
|
||||
# Make one of the following rpms: xCAT, xCATsn, xCAT-buildkit, xCAT-OpenStack
|
||||
function makexcat {
|
||||
if [ "$OSNAME" != "AIX" -a "$1" != "xCAT-buildkit" -a -z "$2" ]; then
|
||||
echo 'Usage: makerpm <RPMname> <arch> [<embedded-system>]'
|
||||
@@ -53,6 +53,7 @@ function makexcat {
|
||||
tar -X /tmp/xcat-excludes -cf $RPMROOT/SOURCES/templates.tar templates
|
||||
gzip -f $RPMROOT/SOURCES/templates.tar
|
||||
cp xcat.conf $RPMROOT/SOURCES
|
||||
cp xcat.conf.apach24 $RPMROOT/SOURCES
|
||||
cp xCATMN $RPMROOT/SOURCES
|
||||
else # xCATsn
|
||||
tar -X /tmp/xcat-excludes -cf $RPMROOT/SOURCES/license.tar LICENSE.html
|
||||
@@ -75,7 +76,9 @@ function makexcat {
|
||||
tar --exclude .svn --exclude upflag -czf $RPMROOT/SOURCES/postscripts.tar.gz postscripts LICENSE.html
|
||||
tar --exclude .svn -czf $RPMROOT/SOURCES/prescripts.tar.gz prescripts
|
||||
tar --exclude .svn -czf $RPMROOT/SOURCES/templates.tar.gz templates
|
||||
tar --exclude .svn -czf $RPMROOT/SOURCES/winpostscripts.tar.gz winpostscripts
|
||||
cp xcat.conf $RPMROOT/SOURCES
|
||||
cp xcat.conf.apach24 $RPMROOT/SOURCES
|
||||
cp xCATMN $RPMROOT/SOURCES
|
||||
cd - >/dev/null
|
||||
elif [ "$RPMNAME" = "xCATsn" ]; then
|
||||
@@ -88,6 +91,8 @@ function makexcat {
|
||||
ARCH="noarch"
|
||||
TARGET=""
|
||||
tar --exclude .svn --exclude xCAT-buildkit.spec -czf $RPMROOT/SOURCES/$RPMNAME-$VER.tar.gz $RPMNAME
|
||||
elif [ "$RPMNAME" = "xCAT-OpenStack" ]; then
|
||||
tar --exclude .svn --exclude xCAT-OpenStack.spec -czf $RPMROOT/SOURCES/$RPMNAME-$VER.tar.gz $RPMNAME
|
||||
else # do not recognize rpm
|
||||
echo "Unrecognized rpm: $RPMNAME"
|
||||
exit 2
|
||||
@@ -201,7 +206,7 @@ else # linux
|
||||
fi
|
||||
|
||||
|
||||
if [ "$1" = "xCAT" -o "$1" = "xCATsn" -o "$1" = "xCAT-buildkit" ]; then
|
||||
if [ "$1" = "xCAT" -o "$1" = "xCATsn" -o "$1" = "xCAT-buildkit" -o "$1" = "xCAT-OpenStack" ]; then
|
||||
exportEmbed $3
|
||||
makexcat $1 $2
|
||||
elif [ "$1" = "xCAT-nbroot" -o "$1" = "xCAT-nbroot-core" ]; then
|
||||
|
||||
+67
-51
@@ -157,61 +157,69 @@ B<tabedit> or B<chtab> commands. They can be viewed using B<nodels> or B<tabdum
|
||||
|
||||
Alternatively, the xCAT database can be viewed and edited as logical objects, instead of flat tables.
|
||||
In this mode, xCAT takes care of which table each attribute should go in. To treat the database
|
||||
as logical object definitions, use the commands: lsdef, mkdef, chdef, rmdef. See Object Definitions
|
||||
as logical object definitions, use the commands: B<lsdef>, B<mkdef>, B<chdef>, B<rmdef>. See Object Definitions
|
||||
below.
|
||||
|
||||
xCAT allows the use of different database applications, depending on the needs of your cluster.
|
||||
The default database is SQLite, which is a daemonless, zero-config database. But you could instead
|
||||
choose to use something like postgresql for greater scalability and remote access in the
|
||||
hierarchical/service node case. To use a different database or a different location, create
|
||||
the file /etc/xcat/cfgloc.
|
||||
See the appropriate xCAT docuementation for the format of the file for the database you choose.
|
||||
The following example is for PostgreSQL:
|
||||
the file /etc/xcat/cfgloc. See the appropriate xCAT docuementation for the format of the file for the database you choose.
|
||||
The following example /etc/xcat/cfgloc file is for PostgreSQL:
|
||||
|
||||
|
||||
=over 4
|
||||
|
||||
=item Pg:dbname=xcat;host=<mgmtnode>|<pgadminuserid>|<pgadminpasswd>
|
||||
Pg:dbname=xcat;host=<mgmtnode>|<pgadminuserid>|<pgadminpasswd>
|
||||
|
||||
where mgmtnode is the hostname of the management node adapter on the cluster side, and the pgadminuserid and pgadminpasswd are the database admin and password.
|
||||
|
||||
=back
|
||||
=head2 GROUPS AND REGULAR EXPRESSIONS IN TABLES
|
||||
|
||||
The xCAT database spans a number of tables, some with records associated with particular nodes
|
||||
(such as nodelist and nodehm) and others that do not have a direct relationship with any given node.
|
||||
The tables not associated with a given node are straightforward, the data is stored and retrieved
|
||||
as-is from the database without interpretation, and without any generic inheritance
|
||||
(though some calling code may implement inheritance for specific fields, for example
|
||||
nodehm.power inheriting from nodehm.mgt).
|
||||
|
||||
The tables with records typically retrieved by node name have some extra features to enable a more
|
||||
The xCAT database has a number of tables, some with rows that are keyed by node name
|
||||
(such as noderes and nodehm) and others that are not keyed by node name (for example, the policy table).
|
||||
The tables that are keyed by node name have some extra features that enable a more
|
||||
template-based style to be used:
|
||||
|
||||
Any group name can be used in lieu of a node name in the node field, and that record will then
|
||||
be taken to be applicable to any node in that group. If a field is requested for a specific node,
|
||||
and either a record doesn't exist specifically for that nodename or a record exists, but has no
|
||||
definition for the requested field, that node's groups are then used to search for
|
||||
records. If multiple records could apply from two different groups, the precedence is
|
||||
the order the groups are specified in the nodelist table for that node. This is nearly identical to
|
||||
most xCAT 1.x tab file conventions. This is useful in tables such as noderes, where typical
|
||||
configurations have exactly the same field values for large sets of nodes.
|
||||
Any group name can be used in lieu of a node name in the node field, and that row will then
|
||||
provide "default" attribute values for any node in that group. A row with a specific node name
|
||||
can then override one or more attribute values for that specific node. For example, if the nodehm table contains:
|
||||
|
||||
xCAT 2 extends the above to be made useful where a field will vary for every node with a given tag,
|
||||
but in ways that would be trivial to describe. If a field is of the format /I<pattern>/I<replacement>/,
|
||||
it is taken to be a perl regular expression, to be performed on the nodename. For example, the bmc field
|
||||
of the ipmi table might be B</\z/-bmc/> for a record with node=ipmi to specify that the BMC hostname is derived
|
||||
by appending B<-bmc> to the end of the nodename of every node in the ipmi group.
|
||||
#node,power,mgt,cons,termserver,termport,conserver,serialport,serialspeed,serialflow,getmac,cmdmapping,comments,disable
|
||||
"mygroup",,"ipmi",,,,,,"19200",,,,,
|
||||
"node1",,,,,,,,"115200",,,,,
|
||||
|
||||
As an extension to the above, a regular expression extended with arithmetic operators is available,
|
||||
by using the format |I<pattern>|I<replacement>|. This behaves similarly to the above, but () enclosed parts
|
||||
in I<replacement> are taken to signify arithmetic operations and substituted in. All operations are integer
|
||||
arithmetic, so 5/4 would come out as 1. The typical perl positional variables are available in such expressions.
|
||||
In the above example, the node group called mygroup sets mgt=ipmi and serialspeed=19200. Any nodes that are in this group
|
||||
will have those attribute values, unless overridden. For example, if node2 is a member of mygroup, it will automatically
|
||||
inherit these attribute values (even though it is not explicitly listed in this table). In the case of node1 above, it
|
||||
inherits mgt=ipmi, but overrides the serialspeed to be 115200, instead of 19200. A useful, typical way to use this
|
||||
capability is to create a node group for your nodes and for all the attribute values that are the same for every node,
|
||||
set them at the group level. Then you only have to set attributes for each node that vary from node to node.
|
||||
|
||||
For example, if you have many blades in your cluster and their hostnames have a regular
|
||||
pattern of blade1, blade2, etc., and your BladeCenter management modules also have a hostname
|
||||
pattern of amm1, amm2, etc., then your B<mp> table could be expressed by the following single row:
|
||||
xCAT extends the group capability so that it can also be used for attribute values that vary from node to node
|
||||
in a very regular pattern. For example, if in the ipmi table you want the bmc attribute to be set to whatever the nodename is with
|
||||
"-bmc" appended to the end of it, then use this in the ipmi table:
|
||||
|
||||
"blade","|\D+(\d+)|amm(($1-1)/14+1)|","|\D+(\d+)|(($1-1)%14+1)|",,
|
||||
#node,bmc,bmcport,taggedvlan,bmcid,username,password,comments,disable
|
||||
"compute","/\z/-bmc/",,,,,,,
|
||||
|
||||
In this example, "compute" is a node group that contains all of the compute nodes. The 2nd attribute (bmc) is a regular
|
||||
expression that is similar to a substitution pattern. The 1st part "\z" matches the end of the node name and substitutes "-bmc", effectively appending it to the node name.
|
||||
|
||||
Another example is if node1 is to have IP address 10.0.0.1, node2 is to have IP address 10.0.0.2, etc.,
|
||||
then this could be represented in the hosts table with the single row:
|
||||
|
||||
#node,ip,hostnames,otherinterfaces,comments,disable
|
||||
"compute","|node(\d+)|10.0.0.($1+0)|",,,,
|
||||
|
||||
In this example, the regular expression in the ip attribute uses "|" to separate the 1st and 2nd part. This means that
|
||||
xCAT will allow arithmetic operations in the 2nd part. In the 1st part, "(\d+)", will match the number part of the node
|
||||
name and put that in a variable called $1. The 2nd part
|
||||
is what value to give the ip attribute. In this case it will set it to the string "10.0.0." and the number that is
|
||||
in $1. (Zero is added to $1 just to remove any leading zeroes.)
|
||||
|
||||
A more involved example is with the mp table. If your blades have node names node01, node02, etc., and your chassis
|
||||
node names are cmm01, cmm02, etc., then you might have an mp table like:
|
||||
|
||||
#node,mpa,id,nodetype,comments,disable
|
||||
"blade","|\D+(\d+)|cmm(sprintf('%02d',($1-1)/14+1))|","|\D+(\d+)|(($1-1)%14+1)|",,
|
||||
|
||||
Before you panic, let me explain each column:
|
||||
|
||||
@@ -221,37 +229,45 @@ Before you panic, let me explain each column:
|
||||
|
||||
This is a group name. In this example, we are assuming that all of your blades belong to this
|
||||
group. Each time the xCAT software accesses the B<mp> table to get the management module and slot number
|
||||
of a specific blade (e.g. B<blade20>), this row will match (because B<blade20> is in the B<blade> group).
|
||||
Once this row is matched for B<blade20>, then the processing described in the following items will take
|
||||
of a specific blade (e.g. B<node20>), this row will match (because B<node20> is in the B<blade> group).
|
||||
Once this row is matched for B<node20>, then the processing described in the following items will take
|
||||
place.
|
||||
|
||||
=item B<|\D+(\d+)|amm(($1-1)/14+1)|>
|
||||
=item B<|\D+(\d+)|cmm(sprintf('%02d',($1-1)/14+1))|>
|
||||
|
||||
This is a perl substitution pattern that will produce the value for the second column of the table (the
|
||||
management module hostname).
|
||||
The text B<\D+(\d+)> between the 1st two vertical bars is
|
||||
management module hostname). The text B<\D+(\d+)> between the 1st two vertical bars is
|
||||
a regular expression that matches the node
|
||||
name that was searched for in this table (in this example B<blade20>). The text that matches
|
||||
name that was searched for in this table (in this example B<node20>). The text that matches
|
||||
within the 1st set of parentheses is set to $1. (If there was a 2nd set of parentheses, it would
|
||||
be set to $2, and so on.) In our case, the \D+ matches the non-numeric part of the name
|
||||
(B<blade>) and the \d+ matches the numeric part (B<20>). So $1 is set to B<20>. The text B<amm(($1-1)/14+1)> between the
|
||||
2nd and 3rd vertical bars produces the string that should be used as the value
|
||||
for this column in a hypothetical row for blade20. Since $1 is set to 20, the expression B<($1-1)/14+1> equals
|
||||
19/14 + 1, which equals 2. Therefore the whole string is B<amm2>, which will be used as the hostname
|
||||
(B<node>) and the B<\d+> matches the numeric part (B<20>). So $1 is set to B<20>. The text B<cmm(sprintf('%02d',($1-1)/14+1))> between the
|
||||
2nd and 3rd vertical bars produces the string that should be used as the value for the mpa attribute for node20.
|
||||
Since $1 is set to 20, the expression B<($1-1)/14+1> equals
|
||||
19/14 + 1, which equals 2. (The division is integer division,
|
||||
so 19/14 equals 1. Fourteen is used as the divisor, because there are 14 blades in each chassis.) The value of 2 is then passed into sprintf() with a format string to add a leading
|
||||
zero, if necessary, to always make the number two digits. Lastly the string B<cmm> is added to the beginning,
|
||||
making the resulting string B<cmm02>, which will be used as the hostname
|
||||
of the management module.
|
||||
|
||||
=item B<|\D+(\d+)|(($1-1)%14+1)|>
|
||||
|
||||
This item is similar to the one above. This substituion pattern will produce the value for
|
||||
the 3rd column (the BladeCenter chassis slot number for this blade). Because this row was
|
||||
the match for B<blade20>, the parentheses
|
||||
the 3rd column (the chassis slot number for this blade). Because this row was
|
||||
the match for B<node20>, the parentheses
|
||||
within the 1st set of vertical bars will set $1 to 20. Since % means modulo division, the
|
||||
expression B<($1-1)%14+1> will evaluate to 6.
|
||||
expression B<($1-1)%14+1> will evaluate to B<6>.
|
||||
|
||||
=back
|
||||
|
||||
See http://www.perl.com/doc/manual/html/pod/perlre.html for information on perl regular expressions.
|
||||
|
||||
=head2 Easy Regular Expressions
|
||||
|
||||
As of xCAT 2.8.1, you can use a modified version of the regular expression support described in the previous section. You do not need to enter the node information (1st part of the expression), it will be derived from the input nodename. You only need to supply the 2nd part of the expression to determine the value to give the attribute. For examples, see
|
||||
|
||||
https://sourceforge.net/apps/mediawiki/xcat/index.php?title=Listing_and_Modifying_the_Database#Easy_Regular_expressions
|
||||
|
||||
=head1 OBJECT DEFINITIONS
|
||||
|
||||
Because it can get confusing what attributes need to go in what tables, the xCAT database can also
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Source: perl-xcat
|
||||
Section: libs
|
||||
Priority: extra
|
||||
Maintainer: Arif Ali <aali@ocf.co.uk>
|
||||
Maintainer: xCAT <xcat-user@lists.sourceforge.net>
|
||||
Build-Depends: debhelper (>= 5), libsoap-lite-perl, libdbi-perl
|
||||
Standards-Version: 3.7.2
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ export DH_COMPAT=5
|
||||
|
||||
build:
|
||||
dh_testdir
|
||||
./modifyUtils `cat ../Version` `svn info | grep Revision | cut -d" " -f 2`
|
||||
./db2man
|
||||
|
||||
clean:
|
||||
@@ -49,6 +48,7 @@ binary-arch: build install
|
||||
chmod 644 `pwd`/debian/perl-xcat/opt/xcat/share/doc/man5/*
|
||||
chmod 644 `pwd`/debian/perl-xcat/opt/xcat/share/man/man7/*
|
||||
chmod 644 `pwd`/debian/perl-xcat/opt/xcat/share/doc/man7/*
|
||||
./modifyUtils `cat ../Version` `svn info | grep Revision | cut -d" " -f 2`
|
||||
# dh_installmenu
|
||||
# dh_installdebconf
|
||||
# dh_installlogrotate
|
||||
|
||||
+13
-18
@@ -191,7 +191,12 @@ sub updateUserInfo {
|
||||
{
|
||||
for my $record (@diff)
|
||||
{
|
||||
print $fp "$record\n";
|
||||
# skip to add ROOT relative records into MERGE file
|
||||
if ($record =~ /^root/)
|
||||
{
|
||||
next;
|
||||
}
|
||||
print $fp "$record\n";
|
||||
}
|
||||
}
|
||||
close ($fp);
|
||||
@@ -230,24 +235,13 @@ sub setCFMSynclistFile {
|
||||
# get the cfmdir and synclists attributes
|
||||
my $osimage_t = xCAT::Table->new('osimage');
|
||||
my $records = $osimage_t->getAttribs({imagename=>$img}, 'cfmdir', 'synclists');
|
||||
if ($records)
|
||||
if (defined ($records->{'cfmdir'}))
|
||||
{
|
||||
if ($records->{'cfmdir'}) {$cfmdir = $records->{'cfmdir'}}
|
||||
if ($records->{'synclists'}) {$synclists = $records->{'synclists'}}
|
||||
$cfmdir = $records->{'cfmdir'};
|
||||
if (defined ($records->{'synclists'})) {$synclists = $records->{'synclists'}}
|
||||
} else {
|
||||
if ($::VERBOSE)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "There are no records for cfmdir and synclists attribute in the osimage:$img. There is nothing to process.";
|
||||
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
# no cfmdir defined, return directly
|
||||
if (!$cfmdir)
|
||||
{
|
||||
return;
|
||||
# no cfmdir defined, return directly
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $found = 0;
|
||||
@@ -369,7 +363,8 @@ sub updateCFMSynclistFile {
|
||||
|
||||
# recursively list the files under cfm directory
|
||||
my @files = ();
|
||||
find ( sub { push @files, $File::Find::name if (! -d) }, $cfmdir);
|
||||
|
||||
find ( { wanted => sub { push @files, $File::Find::name if -f }, follow => 1 }, $cfmdir);
|
||||
if (!@files) # not files under cfm directory, skip to next loop
|
||||
{
|
||||
next;
|
||||
|
||||
+134
-18
@@ -8,9 +8,11 @@ BEGIN
|
||||
|
||||
# if AIX - make sure we include perl 5.8.2 in INC path.
|
||||
# Needed to find perl dependencies shipped in deps tarball.
|
||||
use Storable qw/nstore_fd fd_retrieve/;
|
||||
if ($^O =~ /^aix/i) {
|
||||
unshift(@INC, qw(/usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2));
|
||||
}
|
||||
use IO::Handle;
|
||||
|
||||
my $inet6support;
|
||||
if ($^O =~ /^aix/i) { # disable AIX IPV6 TODO fix
|
||||
@@ -77,6 +79,23 @@ sub rspclean {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
sub send_request {
|
||||
my $request = shift;
|
||||
my $sock = shift;
|
||||
my $encode = shift;
|
||||
if ($encode eq "xml") {
|
||||
my $msg=XMLout($request,RootName=>'xcatrequest',NoAttr=>1,KeyAttr=>[]);
|
||||
if ($ENV{XCATXMLTRACE}) { print $msg; }
|
||||
if($ENV{XCATXMLWARNING}) {
|
||||
validateXML($msg);
|
||||
}
|
||||
print $sock $msg;
|
||||
$sock->flush();
|
||||
} else {
|
||||
nstore_fd($request,$sock);
|
||||
$sock->flush();
|
||||
}
|
||||
}
|
||||
#################################
|
||||
# submit_request will take an xCAT command and pass it to the xCAT
|
||||
# server for execution.
|
||||
@@ -179,11 +198,28 @@ if (ref($request) eq 'HASH') { # the request is an array, not pure XML
|
||||
if ($ENV{XCATHOST}) {
|
||||
$xcathost=$ENV{XCATHOST};
|
||||
}
|
||||
my %connargs=();
|
||||
if ($xcathost =~ s/%([^\]|:]*)//) {
|
||||
$connargs{PeerScope} = $1;
|
||||
}
|
||||
$connargs{PeerAddr} = $xcathost;
|
||||
$connargs{Timeout} = 15;
|
||||
if ($connargs{PeerScope} and $connargs{PeerScope} =~ /[a-zA-Z]/) { #non-numeric, need to translate...
|
||||
my @ipdata = `ip link`;
|
||||
@ipdata = grep(/[^@]$connargs{PeerScope}(:|@)/,@ipdata);
|
||||
if (scalar(@ipdata) != 1) {
|
||||
print STDERR "Unable to identify scope ".$connargs{PeerScope}."\n";
|
||||
exit(1);
|
||||
}
|
||||
$connargs{PeerScope} = $ipdata[0];
|
||||
$connargs{PeerScope} =~ s/:.*//;
|
||||
}
|
||||
|
||||
|
||||
my $pclient;
|
||||
if ($inet6support) {
|
||||
$pclient = IO::Socket::INET6->new(
|
||||
PeerAddr => $xcathost,
|
||||
Timeout => 15,
|
||||
%connargs,
|
||||
);
|
||||
} else {
|
||||
$pclient = IO::Socket::INET->new(
|
||||
@@ -206,6 +242,7 @@ if (ref($request) eq 'HASH') { # the request is an array, not pure XML
|
||||
SSL_key_file => $keyfile,
|
||||
SSL_cert_file => $certfile,
|
||||
SSL_ca_file => $cafile,
|
||||
SSL_verify_mode => SSL_VERIFY_PEER,
|
||||
SSL_use_cert => 1,
|
||||
Timeout => 0,
|
||||
);
|
||||
@@ -214,21 +251,37 @@ if (ref($request) eq 'HASH') { # the request is an array, not pure XML
|
||||
Timeout => 0,
|
||||
);
|
||||
}
|
||||
unless ($client) {
|
||||
print "Unable to open socket connection to xcatd daemon on $xcathost.\n";
|
||||
print "Verify that the xcatd daemon is running and that your SSL setup is correct.\n";
|
||||
if ($@ =~ /SSL Timeout/) {
|
||||
die "Connection failure: SSL Timeout or incorrect certificates in ~/.xcat";
|
||||
} else {
|
||||
die "Connection failure: $@"
|
||||
}
|
||||
}
|
||||
|
||||
my $msg;
|
||||
my $encode = "xml";
|
||||
#storable encoding is unsafe, carry on with the unsafe xml scheme
|
||||
#perhaps one day will support faster schemes
|
||||
#my $encode = "storable";
|
||||
#my $straightprint=0;
|
||||
#if ($ENV{XCATXMLTRACE} or $ENV{XCATXMLWARNING}) { $encode="xml"; }
|
||||
if (ref($request) eq 'HASH') { # the request is an array, not pure XML
|
||||
$msg=XMLout($request,RootName=>'xcatrequest',NoAttr=>1,KeyAttr=>[]);
|
||||
#print $client "xcatencoding: $encode\n";
|
||||
#my $encok=<$client>;
|
||||
send_request($request,$client,$encode);
|
||||
} else { #XML
|
||||
$straightprint=1;
|
||||
$msg=$request;
|
||||
print $client $msg;
|
||||
}
|
||||
if ($ENV{XCATXMLTRACE}) { print $msg; }
|
||||
if($ENV{XCATXMLWARNING}) {
|
||||
validateXML($msg);
|
||||
}
|
||||
$SIG{TERM} = $SIG{INT} = sub { print $client XMLout({abortcommand=>1},RootName=>'xcatrequest',NoAttr=>1,KeyAttr=>[]); exit 0; };
|
||||
print $client $msg;
|
||||
$SIG{TERM} = $SIG{INT} = sub { send_request({abortcommand=>[1]},$client,$encode); exit 0; };
|
||||
my $response;
|
||||
my $rsp;
|
||||
my $cleanexit=0;
|
||||
if ($encode eq 'xml') {
|
||||
my $massresponse="<massresponse>";
|
||||
my $nextcoalescetime=time()+1;
|
||||
my $coalescenow=0;
|
||||
@@ -282,9 +335,31 @@ if (ref($request) eq 'HASH') { # the request is an array, not pure XML
|
||||
$massresponse .= "</massresponse>";
|
||||
$cleanexit = rspclean($massresponse,$callback);
|
||||
}
|
||||
} else { #storable encode
|
||||
my $rsp;
|
||||
eval { $rsp = fd_retrieve($client); };
|
||||
SERVERINPUT: while ($rsp) {
|
||||
my @rsps;
|
||||
if (ref $rsp eq 'ARRAY') {
|
||||
@rsps = @$rsp;
|
||||
} else {
|
||||
@rsps = ($rsp);
|
||||
}
|
||||
foreach (@rsps) {
|
||||
$callback->($_);
|
||||
if ($_->{serverdone}) {
|
||||
$cleanexit=1;
|
||||
last SERVERINPUT;
|
||||
}
|
||||
}
|
||||
$rsp = undef;
|
||||
eval { $rsp = fd_retrieve($client); };
|
||||
}
|
||||
}
|
||||
$massresponse="";
|
||||
unless ($cleanexit) {
|
||||
print STDERR "ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely\n";
|
||||
$xCAT::Client::EXITCODE = 1;
|
||||
}
|
||||
|
||||
sub validateXML {
|
||||
@@ -433,7 +508,7 @@ sub plugin_command {
|
||||
$usesiteglobal = 1;
|
||||
}
|
||||
foreach (@nodes) { #Specified a specific plugin, not a table lookup
|
||||
$handler_hash{$sent->{value}}->{$_} = 1;
|
||||
$handler_hash{$::XCATSITEVALS{$sitekey}}->{$_} = 1;
|
||||
}
|
||||
}
|
||||
} elsif ($hdlspec =~ /:/) { #Specificed a table lookup path for plugin name
|
||||
@@ -597,7 +672,10 @@ sub plugin_command {
|
||||
no strict "refs";
|
||||
# eval { #REMOVEEVALFORDEBUG
|
||||
# if ($dispatch_requests) {
|
||||
dispatch_request($req,$callback,$modname);
|
||||
# backup the original req and recover it after the a run
|
||||
my $org_req = {%$req};
|
||||
dispatch_request($req,$callback,$modname);
|
||||
$req = {%$org_req};
|
||||
# } else {
|
||||
# $SIG{CHLD}='DEFAULT';
|
||||
# ${"xCAT_plugin::".$modname."::"}{process_request}->($req,$callback,\&do_request);
|
||||
@@ -998,7 +1076,7 @@ sub handle_response {
|
||||
}
|
||||
#print "in handle_response\n";
|
||||
# Handle errors
|
||||
if ($rsp->{errorcode}) {
|
||||
if (defined($rsp->{errorcode})) {
|
||||
if (ref($rsp->{errorcode}) eq 'ARRAY') {
|
||||
foreach my $ecode (@{$rsp->{errorcode}}) {
|
||||
$xCAT::Client::EXITCODE |= $ecode;
|
||||
@@ -1012,22 +1090,38 @@ sub handle_response {
|
||||
#print "printing error\n";
|
||||
if (ref($rsp->{error}) eq 'ARRAY') {
|
||||
foreach my $text (@{$rsp->{error}}) {
|
||||
print STDERR "Error: $text\n";
|
||||
if ($rsp->{NoErrorPrefix}) {
|
||||
print STDERR "$text\n";
|
||||
} else {
|
||||
print STDERR "Error: $text\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
print ("Error: ".$rsp->{error}."\n");
|
||||
if ($rsp->{NoErrorPrefix}) {
|
||||
print STDERR ($rsp->{error}."\n");
|
||||
} else {
|
||||
print STDERR ("Error: ".$rsp->{error}."\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($rsp->{warning}) {
|
||||
#print "printing warning\n";
|
||||
if (ref($rsp->{warning}) eq 'ARRAY') {
|
||||
foreach my $text (@{$rsp->{warning}}) {
|
||||
print STDERR "Warning: $text\n";
|
||||
if ($rsp->{NoWarnPrefix}) {
|
||||
print STDERR "$text\n";
|
||||
} else {
|
||||
print STDERR "Warning: $text\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
print ("Warning: ".$rsp->{warning}."\n");
|
||||
if ($rsp->{NoWarnPrefix}) {
|
||||
print STDERR ($rsp->{warning}."\n");
|
||||
} else {
|
||||
print STDERR ("Warning: ".$rsp->{warning}."\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($rsp->{info}) {
|
||||
@@ -1065,7 +1159,12 @@ sub handle_response {
|
||||
#print "printing node\n";
|
||||
my $node;
|
||||
foreach $node (@$nodes) {
|
||||
my $desc=$node->{name}->[0];
|
||||
my $desc;
|
||||
if (ref($node->{name}) eq 'ARRAY') {
|
||||
$desc=$node->{name}->[0];
|
||||
} else {
|
||||
$desc=$node->{name};
|
||||
}
|
||||
if ($node->{errorcode}) {
|
||||
if (ref($node->{errorcode}) eq 'ARRAY') {
|
||||
foreach my $ecode (@{$node->{errorcode}}) {
|
||||
@@ -1085,7 +1184,24 @@ sub handle_response {
|
||||
$errflg=1;
|
||||
}
|
||||
if ($node->{data}) {
|
||||
if (ref(\($node->{data}->[0])) eq 'SCALAR') {
|
||||
if (ref(\($node->{data})) eq 'SCALAR') {
|
||||
$desc=$desc.": ".$node->{data};
|
||||
} elsif (ref($node->{data}) eq 'HASH') {
|
||||
if ($node->{data}->{desc}) {
|
||||
if (ref($node->{data}->{desc}) eq 'ARRAY') {
|
||||
$desc=$desc.": ".$node->{data}->{desc}->[0];
|
||||
} else {
|
||||
$desc=$desc.": ".$node->{data}->{desc};
|
||||
}
|
||||
}
|
||||
if ($node->{data}->{contents}) {
|
||||
if (ref($node->{data}->{contents}) eq 'ARRAY') {
|
||||
$desc="$desc: ".$node->{data}->{contents}->[0];
|
||||
} else {
|
||||
$desc="$desc: ".$node->{data}->{contents};
|
||||
}
|
||||
}
|
||||
} elsif (ref(\($node->{data}->[0])) eq 'SCALAR') {
|
||||
$desc=$desc.": ".$node->{data}->[0];
|
||||
} else {
|
||||
if ($node->{data}->[0]->{desc}) {
|
||||
|
||||
+11
-13
@@ -8,6 +8,7 @@ use File::stat;
|
||||
use File::Copy;
|
||||
use xCAT::Usage;
|
||||
use Thread qw/yield/;
|
||||
use Storable qw/store_fd fd_retrieve/;
|
||||
|
||||
BEGIN
|
||||
{
|
||||
@@ -29,19 +30,18 @@ sub forward_data {
|
||||
my $rfh;
|
||||
my $rc = @ready_fds;
|
||||
foreach $rfh (@ready_fds) {
|
||||
my $data;
|
||||
if ($data = <$rfh>) {
|
||||
while ($data !~ /ENDOFFREEZE6sK4ci/) {
|
||||
$data .= <$rfh>;
|
||||
}
|
||||
my $responses;
|
||||
eval {
|
||||
$responses = fd_retrieve($rfh);
|
||||
};
|
||||
if ($@ and $@ =~ /^Magic number checking on storable file/) { #this most likely means we ran over the end of available input
|
||||
$fds->remove($rfh);
|
||||
close($rfh);
|
||||
} else {
|
||||
eval { print $rfh "ACK\n"; }; #Ignore ack loss due to child giving up and exiting, we don't actually explicitly care about the acks
|
||||
my $responses=thaw($data);
|
||||
foreach (@$responses) {
|
||||
$callback->($_);
|
||||
}
|
||||
} else {
|
||||
$fds->remove($rfh);
|
||||
close($rfh);
|
||||
}
|
||||
}
|
||||
yield(); #Try to avoid useless iterations as much as possible
|
||||
@@ -62,8 +62,7 @@ sub send_data {
|
||||
foreach(@_) {
|
||||
my %output;
|
||||
if (ref($_) eq HASH) {
|
||||
print $out freeze([$_]);
|
||||
print $out "\nENDOFFREEZE6sK4ci\n";
|
||||
store_fd([$_],$out);
|
||||
yield();
|
||||
waitforack($out);
|
||||
next;
|
||||
@@ -97,8 +96,7 @@ sub send_data {
|
||||
} else {
|
||||
$output{node}->[0]->{data}->[0]->{contents}->[0]=$text;
|
||||
}
|
||||
print $out freeze([\%output]);
|
||||
print $out "\nENDOFFREEZE6sK4ci\n";
|
||||
store_fd([\%output],$out);
|
||||
yield();
|
||||
waitforack($out);
|
||||
}
|
||||
|
||||
Regular → Executable
+195
-8
@@ -57,7 +57,7 @@ sub getObjectsOfType
|
||||
|
||||
# The database may be changed between getObjectsOfType calls
|
||||
# do not use cache %::saveObjList if --nocache is specified
|
||||
if ($::saveObjList{$type} && !$::opt_c)
|
||||
if ($::saveObjList{$type} && !$::opt_nc)
|
||||
{
|
||||
@objlist = @{$::saveObjList{$type}};
|
||||
}
|
||||
@@ -200,7 +200,8 @@ sub getobjattrs
|
||||
# list of object names
|
||||
foreach my $table (keys %tableattrs) {
|
||||
# open the table
|
||||
my $thistable = xCAT::Table->new($table, -create => 1, -autocommit => 0);
|
||||
# with autocommit => 0, it does not work on Ubuntu running mysql
|
||||
my $thistable = xCAT::Table->new($table, -create => 1, -autocommit => 1);
|
||||
if (!$thistable) {
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "Could not open the \'$table\' table.";
|
||||
@@ -606,7 +607,7 @@ sub getDBtable
|
||||
|
||||
# save this table info - in case this subr gets called multiple times
|
||||
# --nocache flag specifies not to use cahe
|
||||
if (grep(/^$table$/, @::foundTableList) && !$::opt_c)
|
||||
if (grep(/^$table$/, @::foundTableList) && !$::opt_nc)
|
||||
{
|
||||
|
||||
# already have this
|
||||
@@ -617,7 +618,7 @@ sub getDBtable
|
||||
{
|
||||
|
||||
# need to get info from DB
|
||||
my $thistable = xCAT::Table->new($table, -create => 1, -autocommit => 0);
|
||||
my $thistable = xCAT::Table->new($table, -create => 1);
|
||||
if (!$thistable)
|
||||
{
|
||||
return undef;
|
||||
@@ -1679,7 +1680,14 @@ sub readFileInput
|
||||
|
||||
$look_for_colon = 0; # ok - we have a colon
|
||||
|
||||
($objectname, $junk2) = split(/:/, $l);
|
||||
# Remove any trailing whitespace
|
||||
$l =~ s/\s*$//;
|
||||
|
||||
# IPv6 network names could be something like fd59::/64
|
||||
# Use all the characters before the last ":" as the object name
|
||||
# .* means greedy regular expression
|
||||
$l =~ /^(.*):(.*?)$/;
|
||||
($objectname, $junk2) = ($1, $2);
|
||||
|
||||
# if $junk2 is defined or there's an =
|
||||
if ($junk2 || grep(/=/, $objectname))
|
||||
@@ -1999,7 +2007,14 @@ sub getNetwkInfo
|
||||
my @nodes = ("$node");
|
||||
my $sn = xCAT::ServiceNodeUtils->get_ServiceNode(\@nodes,"xcat","Node");
|
||||
my $snkey = (keys %{$sn})[0];
|
||||
$nethash{$node}{'gateway'} = xCAT::NetworkUtils->getipaddr($snkey);
|
||||
my $gw = xCAT::NetworkUtils->getipaddr($snkey);
|
||||
# two possible cases when this code is run:
|
||||
# 1. flat cluster: ip forwarding is not enabled on MN
|
||||
# 2. hw ctrl in hierarchy cluster, in which HCP SN is not set
|
||||
# in either case, MN itself should not be the gateway
|
||||
if (xCAT::NetworkUtils->thishostisnot($gw)) {
|
||||
$nethash{$node}{'gateway'} = $gw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2150,7 +2165,7 @@ sub getchildren
|
||||
$::RUNCMD_RC = 1;
|
||||
return undef;
|
||||
}
|
||||
my @ps = $ppctab->getAllNodeAttribs(['node','parent','nodetype']);
|
||||
my @ps = $ppctab->getAllNodeAttribs(['node','parent','nodetype','hcp']);
|
||||
foreach my $entry ( @ps ) {
|
||||
my $p = $entry->{parent};
|
||||
my $c = $entry->{node};
|
||||
@@ -2161,13 +2176,19 @@ sub getchildren
|
||||
# build hash of ppc.parent -> ppc.node
|
||||
push @{$PPCHASH{$p}}, $c;
|
||||
}
|
||||
elsif ($t eq 'blade') {
|
||||
push @{$PPCHASH{$c}}, $entry->{hcp};
|
||||
}
|
||||
} else { # go look in the nodetype table to find nodetype
|
||||
my $type = getnodetype($c);
|
||||
my $type = getnodetype($c, "ppc");
|
||||
if ( $type eq 'fsp' or $type eq 'bpa')
|
||||
{
|
||||
# build hash of ppc.parent -> ppc.node
|
||||
push @{$PPCHASH{$p}}, $c;
|
||||
}
|
||||
elsif ($type eq "blade") {
|
||||
push @{$PPCHASH{$c}}, $entry->{hcp};
|
||||
}
|
||||
}
|
||||
} # not $p and $c
|
||||
}
|
||||
@@ -2592,4 +2613,170 @@ sub judge_node
|
||||
|
||||
return $flag;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 expandnicsattr
|
||||
Expand the nics related attributes into the readable format,
|
||||
for example, the nicsips=eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
|
||||
expanded format:
|
||||
nicsips.eth0=1.1.1.1|2.1.1.1
|
||||
nicsips.eth1=3.1.1.1|4.1.1.1
|
||||
|
||||
Arguments:
|
||||
nicsattr value, like niccsips=eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
|
||||
nicnames: only return the value for specific nics, like "eth0,eth1"
|
||||
Returns:
|
||||
expanded format, like:
|
||||
nicsips.eth0=1.1.1.1|2.1.1.1
|
||||
nicsips.eth1=3.1.1.1|4.1.1.1
|
||||
Error:
|
||||
none
|
||||
|
||||
Example:
|
||||
my $nicsstr = xCAT::DBobjUtils->expandnicsattr($attrval);
|
||||
|
||||
Comments:
|
||||
none
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub expandnicsattr()
|
||||
{
|
||||
my $nicstr = shift;
|
||||
if (($nicstr) && ($nicstr =~ /xCAT::/))
|
||||
{
|
||||
$nicstr = shift;
|
||||
}
|
||||
my $nicnames = shift;
|
||||
|
||||
my $ret;
|
||||
|
||||
$nicstr =~ /^(.*?)=(.*?)$/;
|
||||
|
||||
#Attribute: nicips, nichostnamesuffix, etc.
|
||||
my $nicattr = $1;
|
||||
|
||||
# Value: eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
|
||||
my $nicval=$2;
|
||||
|
||||
# $nicarr[0]: eth0!1.1.1.1|2.1.1.1
|
||||
# $nicarr[1]: eth1!3.1.1.1|4.1.1.1
|
||||
my @nicarr = split(/,/, $nicval);
|
||||
|
||||
foreach my $nicentry (@nicarr)
|
||||
{
|
||||
#nicentry: eth0!1.1.1.1|2.1.1.1
|
||||
# $nicv[0]: eth0
|
||||
# $nicv[1]: 1.1.1.1|2.1.1.1
|
||||
my @nicv = split(/!/, $nicentry);
|
||||
|
||||
# only return nic* attr for these specific nics
|
||||
if ($nicnames)
|
||||
{
|
||||
my @nics = split(/,/, $nicnames);
|
||||
if ($nicv[0])
|
||||
{
|
||||
# Do not need to return the nic attr for this nic
|
||||
if (!grep(/^$nicv[0]$/, @nics))
|
||||
{
|
||||
next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ignore the line that does not have nicname or value
|
||||
if ($nicv[0] && $nicv[1])
|
||||
{
|
||||
$ret .= " $nicattr.$nicv[0]=$nicv[1]\n";
|
||||
}
|
||||
}
|
||||
|
||||
chomp($ret);
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 collapsenicsattr
|
||||
Collapse the nics related attributes into the database format,
|
||||
for example,
|
||||
nicsips.eth0=1.1.1.1|2.1.1.1
|
||||
nicsips.eth1=3.1.1.1|4.1.1.1
|
||||
|
||||
the collapsed format:
|
||||
nicsips=eth0!1.1.1.1|2.1.1.1,eth1!3.1.1.1|4.1.1.1
|
||||
|
||||
The collapse will be done against the hash %::FILEATTRS or %::CLIATTRS,
|
||||
remove the nicips.thx attributes from %::FILEATTRS or %::CLIATTRS,
|
||||
add the collapsed info nicips into %::FILEATTRS or %::CLIATTRS.
|
||||
|
||||
Arguments:
|
||||
$::FILEATTRS{$objname} or $::CLIATTRS{$objname}
|
||||
$objname
|
||||
|
||||
Returns:
|
||||
None, update %::FILEATTRS or %::CLIATTRS directly
|
||||
|
||||
Error:
|
||||
none
|
||||
|
||||
Example:
|
||||
xCAT::DBobjUtils->collapsenicsattr($nodeattrhash);
|
||||
|
||||
Comments:
|
||||
none
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub collapsenicsattr()
|
||||
{
|
||||
my $nodeattrhash = shift;
|
||||
if (($nodeattrhash) && ($nodeattrhash =~ /xCAT::/))
|
||||
{
|
||||
$nodeattrhash = shift;
|
||||
}
|
||||
my $objname = shift;
|
||||
|
||||
my %nicattrs = ();
|
||||
foreach my $nodeattr (keys %{$nodeattrhash})
|
||||
{
|
||||
# e.g nicips.eth0
|
||||
# do not need to handle nic attributes without the postfix .ethx,
|
||||
# it will be overwritten by the attributes with the postfix .ethx,
|
||||
if ($nodeattr =~ /^(nic\w+)\.(.*)$/)
|
||||
{
|
||||
if ($1 && $2)
|
||||
{
|
||||
# chdef <noderange> nicips.eth2= to remove the definition for eth2
|
||||
# in this case, the $nodeattrhash->{'nicips.eth0'} is blank
|
||||
if ($nodeattrhash->{$nodeattr})
|
||||
{
|
||||
# $nicattrs{nicips}{eth0} = "1.1.1.1|1.2.1.1"
|
||||
$nicattrs{$1}{$2} = $nodeattrhash->{$nodeattr};
|
||||
}
|
||||
|
||||
# remove nicips.eth0 from the %::FILEATTRS
|
||||
delete $nodeattrhash->{$nodeattr};
|
||||
}
|
||||
}
|
||||
}
|
||||
# $nicattrs{'nicips'}{'eth0'} = "1.1.1.1|1.2.1.1"
|
||||
# $nicattrs{'nicips'}{'eth1'} = "2.1.1.1|2.2.1.1"
|
||||
foreach my $nicattr (keys %nicattrs)
|
||||
{
|
||||
my @tmparray = ();
|
||||
foreach my $nicname (keys %{$nicattrs{$nicattr}})
|
||||
{
|
||||
# eth0!1.1.1.1|1.2.1.1
|
||||
push @tmparray, "$nicname!$nicattrs{$nicattr}{$nicname}";
|
||||
}
|
||||
# eth0!1.1.1.1|1.2.1.1,eth1!2.1.1.1|2.2.1.1
|
||||
$nodeattrhash->{$nicattr} = join(',', @tmparray);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
+170
-92
@@ -592,6 +592,7 @@ sub _execute_dsh
|
||||
xCAT::MsgUtils->message("D", $rsp, $::CALLBACK);
|
||||
$rsp = {};
|
||||
push @{$rsp->{error}}, @{$error_buffers{$user_target}};
|
||||
$rsp->{NoErrorPrefix} = 1;
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK,0);
|
||||
}
|
||||
}
|
||||
@@ -607,6 +608,7 @@ sub _execute_dsh
|
||||
xCAT::MsgUtils->message("D", $rsp, $::CALLBACK);
|
||||
$rsp = {};
|
||||
push @{$rsp->{error}}, @{$error_buffers{$user_target}};
|
||||
$rsp->{NoErrorPrefix} = 1;
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK,0);
|
||||
|
||||
}
|
||||
@@ -815,7 +817,7 @@ sub fork_fanout_dcp
|
||||
my @dcp_command;
|
||||
my $rsyncfile;
|
||||
|
||||
if (!$$target_properties{'localhost'})
|
||||
if (!$$target_properties{'localhost'}) # this is to a remote host
|
||||
{
|
||||
my $target_type = $$target_properties{'type'};
|
||||
|
||||
@@ -837,6 +839,7 @@ sub fork_fanout_dcp
|
||||
|
||||
$rcp_config{'preserve'} = $$options{'preserve'};
|
||||
$rcp_config{'recursive'} = $$options{'recursive'};
|
||||
$rcp_config{'sudo'} = $$options{'sudo'};
|
||||
|
||||
if ($$options{'pull'})
|
||||
{
|
||||
@@ -869,21 +872,25 @@ sub fork_fanout_dcp
|
||||
my $localhost=0; # this is from the MN to another node
|
||||
@dcp_command =
|
||||
$remoteshell->remote_copy_command(\%rcp_config, $remote_copy);
|
||||
# add sudo for non-root users
|
||||
if ($$options{'sudo'}) {
|
||||
unshift (@dcp_command,'sudo');
|
||||
}
|
||||
|
||||
}
|
||||
else # this is the local host ( running on the Management Node)
|
||||
{
|
||||
if ($$options{'destDir_srcFile'}{$user_target})
|
||||
{
|
||||
my $target_type = $$target_properties{'type'};
|
||||
my $target_type = $$target_properties{'type'};
|
||||
|
||||
my %rcp_config = ();
|
||||
my %rcp_config = ();
|
||||
|
||||
my $remote_copy;
|
||||
my $rsh_extension = 'RSH';
|
||||
my $remote_copy;
|
||||
my $rsh_extension = 'RSH';
|
||||
|
||||
if ($target_type eq 'node')
|
||||
{
|
||||
if ($target_type eq 'node')
|
||||
{
|
||||
$remote_copy =
|
||||
$$options{'node-rcp'}{$$target_properties{'context'}}
|
||||
|| $$target_properties{'remote-copy'};
|
||||
@@ -891,10 +898,10 @@ sub fork_fanout_dcp
|
||||
($remote_copy =~ /\/rsync$/) && ($rsh_extension = 'RSYNC');
|
||||
$rcp_config{'options'} =
|
||||
$$options{'node-options'}{$$target_properties{'context'}};
|
||||
}
|
||||
}
|
||||
|
||||
$rcp_config{'preserve'} = $$options{'preserve'};
|
||||
$rcp_config{'recursive'} = $$options{'recursive'};
|
||||
$rcp_config{'preserve'} = $$options{'preserve'};
|
||||
$rcp_config{'recursive'} = $$options{'recursive'};
|
||||
|
||||
|
||||
$rcp_config{'src-file'} = $$options{'source'};
|
||||
@@ -905,20 +912,19 @@ sub fork_fanout_dcp
|
||||
$rcp_config{'destDir_srcFile'} =
|
||||
$$options{'destDir_srcFile'}{$user_target};
|
||||
|
||||
#eval "require RemoteShell::$rsh_extension";
|
||||
eval "require xCAT::$rsh_extension";
|
||||
my $remoteshell = "xCAT::$rsh_extension";
|
||||
# HERE: Build the dcp command based on the arguments
|
||||
my $localhost=1; # this is on the MN to the MN
|
||||
@dcp_command =
|
||||
eval "require xCAT::$rsh_extension";
|
||||
my $remoteshell = "xCAT::$rsh_extension";
|
||||
# HERE: Build the dcp command based on the arguments
|
||||
my $localhost=1; # this is on the MN to the MN
|
||||
@dcp_command =
|
||||
$remoteshell->remote_copy_command(\%rcp_config, $remote_copy,$localhost);
|
||||
|
||||
}
|
||||
else # just a copy not a sync
|
||||
{
|
||||
}
|
||||
else # just a copy not a sync
|
||||
{
|
||||
@dcp_command =
|
||||
('/bin/cp', '-r', $$options{'source'}, $$options{'target'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $rsp = {};
|
||||
@@ -1013,11 +1019,18 @@ sub fork_fanout_dsh
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# save the original exports, we are going to add the unique node name below
|
||||
while (@$targets_waiting
|
||||
&& (keys(%$targets_active) < $$options{'fanout'}))
|
||||
{
|
||||
my $user_target = shift @$targets_waiting;
|
||||
# now add export NODE=nodename to the pre-command, if not a device;
|
||||
my $exportnode;
|
||||
if (($$options{'devicetype'})) {
|
||||
$exportnode="";
|
||||
} else{
|
||||
$exportnode="export NODE=$user_target; ";
|
||||
}
|
||||
my $target_properties = $$resolved_targets{$user_target};
|
||||
my @commands;
|
||||
my $localShell =
|
||||
@@ -1031,17 +1044,39 @@ sub fork_fanout_dsh
|
||||
$$options{'post-command'} = "";
|
||||
$dsh_cmd_background = 1;
|
||||
}
|
||||
|
||||
if ($$options{'environment'})
|
||||
{
|
||||
# if we are on a servicenode need to get the environment file
|
||||
# from the SNsyncfiledir, not local
|
||||
if (xCAT::Utils->isServiceNode()) {
|
||||
my $newenvfile;
|
||||
my $synfiledir = "/var/xcat/syncfiles"; #default
|
||||
|
||||
# get the directory on the servicenode to and add to filepath
|
||||
my @syndir= xCAT::TableUtils->get_site_attribute("SNsyncfiledir");
|
||||
if ($syndir[0])
|
||||
{
|
||||
$synfiledir = $syndir[0];
|
||||
}
|
||||
$newenvfile = $synfiledir;
|
||||
$newenvfile .= $$options{'environment'};
|
||||
$$options{'environment'} = $newenvfile;
|
||||
}
|
||||
if (!(-e $$options{'environment'}))
|
||||
{
|
||||
my $rsp={};
|
||||
$rsp->{error}->[0] = "File $$options{'environment'} does not exist";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
}
|
||||
# build the xdsh command
|
||||
push @dsh_command,
|
||||
"$$options{'pre-command'} . $$options{'environment'} ; $$options{'command'}$$options{'post-command'}";
|
||||
"$exportnode$$options{'pre-command'} . $$options{'environment'} ; $$options{'command'}$$options{'post-command'}";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
push @dsh_command,
|
||||
"$$options{'pre-command'}$$options{'command'}$$options{'post-command'}";
|
||||
"$exportnode$$options{'pre-command'}$$options{'command'}$$options{'post-command'}";
|
||||
}
|
||||
|
||||
if ($$target_properties{'localhost'})
|
||||
@@ -1109,7 +1144,7 @@ sub fork_fanout_dsh
|
||||
#eval "require RemoteShell::$rsh_extension";
|
||||
eval "require xCAT::$rsh_extension";
|
||||
|
||||
$rsh_config{'command'} = "$$options{'pre-command'}";
|
||||
$rsh_config{'command'} = "$exportnode$$options{'pre-command'}";
|
||||
my $tmp_env_file;
|
||||
# for the -E flag here we build and copy the -E env variable
|
||||
# file to the nodes
|
||||
@@ -1163,13 +1198,13 @@ sub fork_fanout_dsh
|
||||
if ($$options{'execute'})
|
||||
{
|
||||
# first build the scp command to copy the file to execute
|
||||
# down to the node into /tmp/*.dsh
|
||||
# down to the node into /tmp/*.dsh
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "TRACE: Execute option specified.";
|
||||
$dsh_trace && (xCAT::MsgUtils->message("I", $rsp, $::CALLBACK));
|
||||
|
||||
my %exe_rcp_config = ();
|
||||
$tmp_cmd_file = POSIX::tmpnam . ".dsh";
|
||||
$tmp_cmd_file = POSIX::tmpnam . ".dsh";
|
||||
|
||||
my ($exe_cmd, @args) = @{$$options{'execute'}};
|
||||
my $chmod_cmd = "";
|
||||
@@ -2310,10 +2345,14 @@ sub config_dsh
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
# if not Mellanox, it does not need a config file
|
||||
if (!($$options{'devicetype'} =~ /Mellanox/i)) {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] = "EMsgMISSING_DEV_CFG";
|
||||
xCAT::MsgUtils->message('E', $rsp, $::CALLBACK);
|
||||
$rsp->{error}->[0] = "The config file: $devicepath is missing";
|
||||
xCAT::MsgUtils->message('E', $rsp, $::CALLBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3198,7 +3237,17 @@ sub bld_resolve_nodes_hash
|
||||
|
||||
# find out if we have an MN in the list, local cp and sh will be used
|
||||
# not remote shell
|
||||
my $mname = xCAT::Utils->noderangecontainsMn(@target_list);
|
||||
# find out the names for the Management Node
|
||||
my @MNnodeinfo = xCAT::NetworkUtils->determinehostname;
|
||||
my $mname = pop @MNnodeinfo; # hostname
|
||||
my $cmd="hostname";
|
||||
my $localhostname = xCAT::Utils->runcmd($cmd,0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{info}->[0] = "Command: $cmd failed. Continuing...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
|
||||
}
|
||||
foreach my $target (@target_list)
|
||||
{
|
||||
|
||||
@@ -3207,11 +3256,9 @@ sub bld_resolve_nodes_hash
|
||||
my $localhost;
|
||||
my $user;
|
||||
my $context = "XCAT";
|
||||
# check to see if this node is the Management Node
|
||||
if ($mname) {
|
||||
if ($mname eq $target) {
|
||||
# check to see if this node is the Management Node we are on, can run local commands (sh,cp)
|
||||
if (($mname eq $target) || ($localhostname eq $target)){
|
||||
$localhost=$target;
|
||||
}
|
||||
}
|
||||
my %properties = (
|
||||
'hostname' => $hostname,
|
||||
@@ -4040,11 +4087,12 @@ sub parse_and_run_dsh
|
||||
# check if any node in the noderange is the Management Node and exit
|
||||
# with error, if the Management Node is in the Database and in the
|
||||
# noderange
|
||||
my $mname = xCAT::Utils->noderangecontainsMn(@nodelist);
|
||||
if ($mname) { # MN in the nodelist
|
||||
my @mname = xCAT::Utils->noderangecontainsMn(@nodelist);
|
||||
if (@mname) { # MN in the nodelist
|
||||
my $nodes=join(',', @mname);
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"You must not run -K option against the Management Node:$mname.";
|
||||
"You must not run -K option against the Management Node:$nodes.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1);
|
||||
return;
|
||||
}
|
||||
@@ -4146,7 +4194,7 @@ sub parse_and_run_dsh
|
||||
#
|
||||
# setup ssh keys on the nodes or ib switch
|
||||
#
|
||||
my $rc = xCAT::TableUtils->setupSSH($options{'nodes'});
|
||||
my $rc = xCAT::TableUtils->setupSSH($options{'nodes'},$options{'timeout'});
|
||||
my @results = "return code = $rc";
|
||||
return (@results);
|
||||
}
|
||||
@@ -4216,7 +4264,7 @@ sub usage_dcp
|
||||
{
|
||||
### usage message
|
||||
my $usagemsg1 = " xdcp -h \n xdcp -q\n xdcp -V \n xdcp <noderange>\n";
|
||||
my $usagemsg2 = " [-B bypass] [-c] [-f fanout] [-l user_ID]\n";
|
||||
my $usagemsg2 = " [-B bypass] [-c] [-f fanout] [-l user_ID] [--sudo]\n";
|
||||
my $usagemsg3 =
|
||||
" [-m] [-o options] [-p] [-P] [-q] [-Q] [-r node_remote_copy]\n";
|
||||
my $usagemsg4 =
|
||||
@@ -4325,7 +4373,8 @@ sub parse_and_run_dcp
|
||||
'T|trace' => \$options{'trace'},
|
||||
'V|version' => \$options{'version'},
|
||||
'devicetype=s' => \$options{'devicetype'},
|
||||
'nodestatus|nodestatus' => \$options{'nodestatus'},
|
||||
'nodestatus|nodestatus' => \$options{'nodestatus'},
|
||||
'sudo|sudo' => \$options{'sudo'},
|
||||
'X:s' => \$options{'ignore_env'}
|
||||
)
|
||||
)
|
||||
@@ -4570,8 +4619,8 @@ sub parse_and_run_dcp
|
||||
close FILE;
|
||||
# now put the original syncfile on the queue to sync to the SN's
|
||||
$rc =
|
||||
&parse_rsync_input_file_on_MN(\@nodelist, \%options, $tmpsyncfile,
|
||||
$::SYNCSN, $synfiledir,$nodesyncfiledir);
|
||||
&parse_rsync_input_file_on_MN(\@nodelist, \%options,$tmpsyncfile,
|
||||
$::SYNCSN, $synfiledir,$nodesyncfiledir);
|
||||
# cleanup
|
||||
my $cmd = "rm $tmpsyncfile";
|
||||
my @output = xCAT::Utils->runcmd($cmd, 0);
|
||||
@@ -4657,21 +4706,42 @@ sub parse_and_run_dcp
|
||||
my $ranpostscripts;
|
||||
my $ranappendscripts;
|
||||
my $ranmergescripts;
|
||||
|
||||
# if we were called with runxcmd, like by updatenode
|
||||
# need to save the runxcmd buffer
|
||||
# $::xcmd_outref
|
||||
my $save_xcmd_outref;
|
||||
if ($::xcmd_outref) { # this means we were called with runxcmd
|
||||
$save_xcmd_outref = $::xcmd_outref;
|
||||
}
|
||||
|
||||
if ((@::postscripts) && ($::SYNCSN == 0)) {
|
||||
@results2 = &run_rsync_postscripts(\@results,$synfiledir);
|
||||
@results2 = &run_rsync_postscripts(\@results,$synfiledir,\%options);
|
||||
$ranpostscripts=1;
|
||||
}
|
||||
if ((@::alwayspostscripts) && ($::SYNCSN == 0)) {
|
||||
@results3 = &run_always_rsync_postscripts(\@nodelist,$synfiledir);
|
||||
@results3 = &run_always_rsync_postscripts(\@nodelist,$synfiledir,\%options);
|
||||
}
|
||||
if (($::appendscript) && ($::SYNCSN == 0)) {
|
||||
@results4 = &bld_and_run_append(\@nodelist,\@results,$synfiledir,$nodesyncfiledir);
|
||||
@results4 = &bld_and_run_append(\@nodelist,\@results,$synfiledir,$nodesyncfiledir,\%options);
|
||||
$ranappendscripts=1;
|
||||
}
|
||||
if (($::mergescript) && ($::SYNCSN == 0)) {
|
||||
@results5 = &bld_and_run_merge(\@nodelist,\@results,$synfiledir,$nodesyncfiledir);
|
||||
@results5 = &bld_and_run_merge(\@nodelist,\@results,$synfiledir,$nodesyncfiledir,\%options);
|
||||
$ranmergescripts=1;
|
||||
}
|
||||
# restore the runxcmd buffer
|
||||
if ($save_xcmd_outref) { # this means we were called with runxcmd
|
||||
$::xcmd_outref = $save_xcmd_outref;
|
||||
}
|
||||
# TODO, will we ever need to merge
|
||||
# if we ran a postscript and we were run
|
||||
# using runxcmd, and there was previous output in the
|
||||
# runxcmd buffer and we have output from the postscript
|
||||
# then we have to merge the outputs
|
||||
#if (($ranaps == 1) && ($save_xcmd_outref) && ($::xcmd_outref) ) {
|
||||
# &mergeoutput($save_xcmd_outref);
|
||||
#}
|
||||
my @newresults;
|
||||
if (@results2) {
|
||||
@newresults = (@results2);
|
||||
@@ -4686,9 +4756,14 @@ sub parse_and_run_dcp
|
||||
@newresults = (@newresults,@results3,@results4,@results5);
|
||||
}
|
||||
if (@newresults) {
|
||||
if ($save_xcmd_outref) { # this means we were called with runxcmd
|
||||
foreach my $line (@newresults) {
|
||||
push @$::xcmd_outref,$line;
|
||||
}
|
||||
}
|
||||
return (@newresults);
|
||||
} else {
|
||||
# don't report results for postscripts,appendscripts,mergescripts because
|
||||
# don't report other results for postscripts,appendscripts,mergescripts because
|
||||
# you get all the rsync returned lines
|
||||
if (($ranpostscripts == 0 ) && ($ranappendscripts == 0)
|
||||
&& ($ranmergescripts == 0)) {
|
||||
@@ -5563,7 +5638,7 @@ sub parse_rsync_input_file_on_SN
|
||||
|
||||
sub run_rsync_postscripts
|
||||
{
|
||||
my ($rsyncoutput,$syncdir) = @_;
|
||||
my ($rsyncoutput,$syncdir,$options) = @_;
|
||||
my @rsync_output = @$rsyncoutput;
|
||||
my @newoutput= ();
|
||||
my $dshparms;
|
||||
@@ -5606,27 +5681,26 @@ sub run_rsync_postscripts
|
||||
# now if we have postscripts to run, run xdsh
|
||||
my $out;
|
||||
|
||||
# if we were called with runxcmd, like by updatenode
|
||||
# need to save the runxcmd buffer
|
||||
# $::xcmd_outref
|
||||
my $save_xcmd_outref;
|
||||
if ($::xcmd_outref) { # this means we were called with runxcmd
|
||||
$save_xcmd_outref = $::xcmd_outref;
|
||||
}
|
||||
# my $ranaps=0; # did we run a postscript
|
||||
|
||||
foreach my $ps ( keys %{$$dshparms{'postscripts'}}) {
|
||||
my @nodes;
|
||||
push (@nodes, @{$$dshparms{'postscripts'}{$ps}});
|
||||
my @args=();
|
||||
if ($$options{'nodestatus'}) {
|
||||
push @args,"--nodestatus" ;
|
||||
}
|
||||
push @args,"-e";
|
||||
# if on the service node need to add the $syncdir directory
|
||||
# to the path
|
||||
if (xCAT::Utils->isServiceNode()) {
|
||||
my $tmpp=$syncdir . $ps;
|
||||
$ps=$tmpp;
|
||||
}
|
||||
$out=xCAT::Utils->runxcmd( { command => ['xdsh'],
|
||||
push @args,$ps;
|
||||
$out=xCAT::Utils->runxcmd( { command => ['xdsh'],
|
||||
node => \@nodes,
|
||||
arg => [ "-e", $ps ]
|
||||
arg => \@args,
|
||||
}, $::SUBREQ, 0,1);
|
||||
foreach my $r (@$out){
|
||||
push(@newoutput, $r);
|
||||
@@ -5634,18 +5708,6 @@ sub run_rsync_postscripts
|
||||
}
|
||||
# $ranaps=1;
|
||||
}
|
||||
# restore the runxcmd buffer
|
||||
if ($save_xcmd_outref) { # this means we were called with runxcmd
|
||||
$::xcmd_outref = $save_xcmd_outref;
|
||||
}
|
||||
# TODO, will we ever need to merge
|
||||
# if we ran a postscript and we were run
|
||||
# using runxcmd, and there was previous output in the
|
||||
# runxcmd buffer and we have output from the postscript
|
||||
# then we have to merge the outputs
|
||||
#if (($ranaps == 1) && ($save_xcmd_outref) && ($::xcmd_outref) ) {
|
||||
# &mergeoutput($save_xcmd_outref);
|
||||
#}
|
||||
return @newoutput;
|
||||
}
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -5683,7 +5745,7 @@ sub run_rsync_postscripts
|
||||
|
||||
sub bld_and_run_append
|
||||
{
|
||||
my ($hostnames,$rsyncoutput,$syncdir,$nodesyncfiledir) = @_;
|
||||
my ($hostnames,$rsyncoutput,$syncdir,$nodesyncfiledir,$options) = @_;
|
||||
my @hosts = @$hostnames;
|
||||
my @rsync_output = @$rsyncoutput;
|
||||
my @newoutput= ();
|
||||
@@ -5733,8 +5795,10 @@ sub bld_and_run_append
|
||||
# that were rsyn'd to at least one node
|
||||
if ($tmpappendfile eq $ps) {
|
||||
my $parm="$appendfile:$filetoappend ";
|
||||
|
||||
$::xdcpappendparms .= $parm;
|
||||
# check to see if the parameter is already in the list
|
||||
if (!($::xdcpappendparms =~ /$parm/)) {
|
||||
$::xdcpappendparms .= $parm;
|
||||
}
|
||||
$processappend=1;
|
||||
|
||||
}
|
||||
@@ -5755,10 +5819,16 @@ sub bld_and_run_append
|
||||
foreach my $ps ( keys %{$$dshparms{'appendscripts'}}) {
|
||||
my @nodes;
|
||||
push (@nodes, @{$$dshparms{'appendscripts'}{$ps}});
|
||||
my @args=();
|
||||
if ($$options{'nodestatus'}) {
|
||||
push @args,"--nodestatus" ;
|
||||
}
|
||||
push @args,$ps;
|
||||
push @args,$::xdcpappendparms;
|
||||
|
||||
$out=xCAT::Utils->runxcmd( { command => ['xdsh'],
|
||||
node => \@nodes,
|
||||
arg => [ $ps , $::xdcpappendparms ]
|
||||
arg => \@args,
|
||||
}, $::SUBREQ, 0,1);
|
||||
foreach my $r (@$out){
|
||||
push(@newoutput, $r);
|
||||
@@ -5805,7 +5875,7 @@ sub bld_and_run_append
|
||||
|
||||
sub bld_and_run_merge
|
||||
{
|
||||
my ($hostnames,$rsyncoutput,$syncdir,$nodesyncfiledir) = @_;
|
||||
my ($hostnames,$rsyncoutput,$syncdir,$nodesyncfiledir,$options) = @_;
|
||||
my @hosts = @$hostnames;
|
||||
my @rsync_output = @$rsyncoutput;
|
||||
my @newoutput= ();
|
||||
@@ -5864,8 +5934,10 @@ sub bld_and_run_merge
|
||||
# that were rsyn'd to at least one node
|
||||
if ($tmpmergefile eq $ps) {
|
||||
my $parm="$mergefile:$filetomerge ";
|
||||
|
||||
$::xdcpmergeparms .= $parm;
|
||||
# check to see if the parameter is already in the list
|
||||
if (!($::xdcpmergeparms =~ /$parm/)) {
|
||||
$::xdcpmergeparms .= $parm;
|
||||
}
|
||||
$processmerge=1;
|
||||
|
||||
}
|
||||
@@ -5887,9 +5959,17 @@ sub bld_and_run_merge
|
||||
my @nodes;
|
||||
push (@nodes, @{$$dshparms{'mergescripts'}{$ps}});
|
||||
|
||||
# build the argument list
|
||||
my @args=();
|
||||
|
||||
if ($$options{'nodestatus'}) {
|
||||
push @args,"--nodestatus" ;
|
||||
}
|
||||
push @args, $ps;
|
||||
push @args, $::xdcpmergeparms;
|
||||
$out=xCAT::Utils->runxcmd( { command => ['xdsh'],
|
||||
node => \@nodes,
|
||||
arg => [ $ps , $::xdcpmergeparms ]
|
||||
arg => \@args,
|
||||
}, $::SUBREQ, 0,1);
|
||||
foreach my $r (@$out){
|
||||
push(@newoutput, $r);
|
||||
@@ -5915,7 +5995,7 @@ sub bld_and_run_merge
|
||||
|
||||
sub run_always_rsync_postscripts
|
||||
{
|
||||
my ($hostnames,$syncdir) = @_;
|
||||
my ($hostnames,$syncdir,$options) = @_;
|
||||
my @hosts = @$hostnames;
|
||||
my @newoutput= ();
|
||||
my $dshparms;
|
||||
@@ -5937,26 +6017,28 @@ sub run_always_rsync_postscripts
|
||||
# now if we have postscripts to run, run xdsh
|
||||
my $out;
|
||||
|
||||
# if we were called with runxcmd, like by updatenode
|
||||
# need to save the runxcmd buffer
|
||||
# $::xcmd_outref
|
||||
my $save_xcmd_outref;
|
||||
if ($::xcmd_outref) { # this means we were called with runxcmd
|
||||
$save_xcmd_outref = $::xcmd_outref;
|
||||
}
|
||||
|
||||
foreach my $ps ( keys %{$$dshparms{'postscripts'}}) {
|
||||
my @nodes;
|
||||
push (@nodes, @{$$dshparms{'postscripts'}{$ps}});
|
||||
# build the argument list
|
||||
my @args=();
|
||||
if ($$options{'nodestatus'}) {
|
||||
push @args,"--nodestatus" ;
|
||||
}
|
||||
push @args,"-e";
|
||||
# if on the service node need to add the $syncdir directory
|
||||
# to the path
|
||||
if (xCAT::Utils->isServiceNode()) {
|
||||
my $tmpp=$syncdir . $ps;
|
||||
$ps=$tmpp;
|
||||
}
|
||||
push @args, $ps;
|
||||
|
||||
push (@nodes, @{$$dshparms{'postscripts'}{$ps}});
|
||||
|
||||
$out=xCAT::Utils->runxcmd( { command => ['xdsh'],
|
||||
$out=xCAT::Utils->runxcmd( { command => ['xdsh'],
|
||||
node => \@nodes,
|
||||
arg => [ "-e", $ps ]
|
||||
arg => \@args,
|
||||
}, $::SUBREQ, 0,1);
|
||||
foreach my $r (@$out){
|
||||
push(@newoutput, $r);
|
||||
@@ -5964,10 +6046,6 @@ sub run_always_rsync_postscripts
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
# restore the runxcmd buffer
|
||||
if ($save_xcmd_outref) { # this means we were called with runxcmd
|
||||
$::xcmd_outref = $save_xcmd_outref;
|
||||
}
|
||||
return @newoutput;
|
||||
}
|
||||
|
||||
@@ -754,8 +754,20 @@ sub pping_hostnames
|
||||
my ($class, @hostnames) = @_;
|
||||
|
||||
my $hostname_list = join ",", @hostnames;
|
||||
# read site table, usefping attribute
|
||||
# if set then run pping -f to use fping
|
||||
# this fixes a broken nmap in Redhat 6.2 with ip alias (3512)
|
||||
my $cmd="$::XCATROOT/bin/pping $hostname_list"; # default
|
||||
my @usefping=xCAT::TableUtils->get_site_attribute("usefping");
|
||||
if ((defined($usefping[0])) && ($usefping[0] eq "1")) {
|
||||
$cmd = "$::XCATROOT/bin/pping -f $hostname_list";
|
||||
}
|
||||
#my $rsp={};
|
||||
#$rsp->{data}->[0] = "running command $cmd";
|
||||
#xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
|
||||
|
||||
my @output =
|
||||
xCAT::Utils->runcmd("$::XCATROOT/bin/pping $hostname_list", -1);
|
||||
xCAT::Utils->runcmd($cmd, -1);
|
||||
if ($::RUNCMD_RC !=0) {
|
||||
my $rsp={};
|
||||
$rsp->{error}->[0] = "Error from pping";
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env perl
|
||||
# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
package xCAT::DiscoveryUtils;
|
||||
|
||||
use strict;
|
||||
use XML::Simple;
|
||||
$XML::Simple::PREFERRED_PARSER='XML::Parser';
|
||||
|
||||
use xCAT::MsgUtils;
|
||||
|
||||
=head3 update_discovery_data
|
||||
Update the discovery data from the xcat request to discoverydata table to indicate the discovery events
|
||||
arg1 - the request
|
||||
|
||||
=cut
|
||||
|
||||
sub update_discovery_data {
|
||||
my $class = shift;
|
||||
my $request = shift;
|
||||
|
||||
my %disdata;
|
||||
my %otherdata;
|
||||
|
||||
unless ($request->{'uuid'}->[0]) {
|
||||
xCAT::MsgUtils->message("S", "Discovery Error: Found a node without uuid");
|
||||
}
|
||||
|
||||
if ($request->{'discoverymethod'}->[0]) {
|
||||
$disdata{'method'} = $request->{'discoverymethod'}->[0];
|
||||
} else {
|
||||
$disdata{'method'} = "undef";
|
||||
}
|
||||
|
||||
#discoverytime
|
||||
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
|
||||
my $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d",
|
||||
$mon + 1, $mday, $year + 1900, $hour, $min, $sec);
|
||||
$disdata{'discoverytime'} = $currtime;
|
||||
|
||||
foreach my $attr (keys %$request) {
|
||||
if ($attr =~ /^(command|discoverymethod|_xcat|cacheonly|noderange|environment|method|discoverytime|updateswitch)/) {
|
||||
next;
|
||||
} elsif ($attr =~ /^(node|uuid|arch|cpucount|cputype|memory|mtm|serial)$/) {
|
||||
$disdata{$attr} = $request->{$attr}->[0];
|
||||
} elsif ($attr eq 'nic') {
|
||||
# Set the nics attributes
|
||||
foreach my $nic (@{$request->{nic}}) {
|
||||
my $nicname = $nic->{'devname'}->[0];
|
||||
foreach my $nicattr (keys %$nic) {
|
||||
my $tbattr;
|
||||
if ($nicattr eq 'driver') {
|
||||
$tbattr = "nicdriver";
|
||||
} elsif ($nicattr eq 'ip4address') {
|
||||
$tbattr = "nicipv4";
|
||||
} elsif ($nicattr eq 'hwaddr') {
|
||||
$tbattr = "nichwaddr";
|
||||
} elsif ($nicattr eq 'pcidev') {
|
||||
$tbattr = "nicpci";
|
||||
} elsif ($nicattr eq 'location') {
|
||||
$tbattr = "nicloc";
|
||||
} elsif ($nicattr eq 'onboardeth') {
|
||||
$tbattr = "niconboard";
|
||||
} elsif ($nicattr eq 'firmdesc') {
|
||||
$tbattr = "nicfirm";
|
||||
} elsif ($nicattr =~ /^(switchname|switchaddr|switchdesc|switchport)$/) {
|
||||
$tbattr = $nicattr;
|
||||
}
|
||||
|
||||
if ($tbattr) {
|
||||
if ($disdata{$tbattr}) {
|
||||
$disdata{$tbattr} .= ','.$nicname.'!'.$nic->{$nicattr}->[0];
|
||||
} else {
|
||||
$disdata{$tbattr} = $nicname.'!'.$nic->{$nicattr}->[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# store to otherdata for the not parsed attributes
|
||||
$otherdata{$attr} = $request->{$attr};
|
||||
}
|
||||
}
|
||||
|
||||
if (keys %otherdata) {
|
||||
$disdata{'otherdata'} = XMLout(\%otherdata,RootName=>'discoveryotherdata' ,NoAttr=>1);
|
||||
}
|
||||
|
||||
my $distab = xCAT::Table->new('discoverydata');
|
||||
if ($distab) {
|
||||
$distab->setAttribs({uuid=>$request->{'uuid'}->[0]},\%disdata);
|
||||
$distab->close();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -67,7 +67,7 @@ sub getHcpAttribs
|
||||
}
|
||||
}
|
||||
|
||||
my @ps = $tabs->{ppc}->getAllNodeAttribs(['node','parent','nodetype']);
|
||||
my @ps = $tabs->{ppc}->getAllNodeAttribs(['node','parent','nodetype','hcp','id']);
|
||||
for my $entry ( @ps ) {
|
||||
my $tmp_parent = $entry->{parent};
|
||||
my $tmp_node = $entry->{node};
|
||||
@@ -76,6 +76,12 @@ sub getHcpAttribs
|
||||
push @{$ppchash{$tmp_parent}{children}}, $tmp_node;
|
||||
#push @{$ppchash{$tmp_parent}}, $tmp_node;
|
||||
}
|
||||
if (defined($tmp_node) && defined($tmp_type) && ($tmp_type eq "blade") && defined($entry->{hcp})) {
|
||||
push @{$ppchash{$tmp_node}{children}}, $entry->{hcp};
|
||||
}
|
||||
if (defined($tmp_node) && defined($entry->{id}) && defined($tmp_parent) && defined($tmp_type) && ($tmp_type eq "lpar")) {
|
||||
$ppchash{$tmp_parent}{mapping}{$tmp_node} = $entry->{id};
|
||||
}
|
||||
|
||||
#if(exists($ppchash{$tmp_node})) {
|
||||
# if( defined($tmp_type) ) {
|
||||
@@ -173,6 +179,8 @@ sub getIPaddress
|
||||
#the $nodetocheck is its' hcp. So set $nodetocheck to $parent variable.
|
||||
#And then get the FSPs IPs for the CEC.
|
||||
$parent = $nodetocheck;
|
||||
} elsif ($type eq "blade") {
|
||||
return $ppc->{$nodetocheck}->{children}->[0];
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
@@ -363,11 +371,19 @@ sub fsp_api_action {
|
||||
} elsif( $parameter !=0 && $action =~ /^(on|reset)$/ ) {
|
||||
#powerinterval for lpars power on
|
||||
$cmd = "$fsp_api -a $action -i $parameter -T $tooltype -t $type:$fsp_ip:$id:$node_name:";
|
||||
} elsif ($action =~ /^part_set_lpar_def_state$/) {
|
||||
$cmd = "$fsp_api -a $action -T $tooltype -s $parameter -t $type:$fsp_ip:$id:$node_name:";
|
||||
} elsif (exists($request->{opt}->{vios})) {
|
||||
$cmd = "$fsp_api -a $action -T $tooltype -s 1 -t $type:$fsp_ip:$id:$node_name:$parameter";
|
||||
} else {
|
||||
$cmd = "$fsp_api -a $action -T $tooltype -t $type:$fsp_ip:$id:$node_name:$parameter";
|
||||
}
|
||||
} else {
|
||||
$cmd = "$fsp_api -a $action -T $tooltype -t $type:$fsp_ip:$id:$node_name:";
|
||||
if (exists($request->{opt}->{vios})) {
|
||||
$cmd = "$fsp_api -a $action -T $tooltype -s 1 -t $type:$fsp_ip:$id:$node_name:";
|
||||
} else {
|
||||
$cmd = "$fsp_api -a $action -T $tooltype -t $type:$fsp_ip:$id:$node_name:";
|
||||
}
|
||||
}
|
||||
}
|
||||
xCAT::MsgUtils->verbose_message($request, "fsp_api_action cmd:$cmd.");
|
||||
|
||||
@@ -236,7 +236,7 @@ sub powercmd {
|
||||
if($action =~ /^lowpower$/) { $action = "cec_on_low_power"; }
|
||||
#if($action =~ /^cycle$/) {$action = "cec_reboot";}
|
||||
if($action =~ /^cycle$/) {$action = "reset";}
|
||||
if($action !~ /^cec_on_autostart$/ && $action !~ /^cec_off$/ && $action !~ /^cec_on_low_power$/ && $action !~ /^onstandby$/ && $action !~ /^reboot_service_processor$/ && $action !~ /^reset$/) {
|
||||
if($action !~ /^cec_on_autostart$/ && $action !~ /^cec_off$/ && $action !~ /^cec_on_low_power$/ && $action !~ /^onstandby$/ && $action !~ /^reboot_service_processor$/ && $action !~ /^reset$/ && $action !~ /^sms$/) {
|
||||
push @output, [$node_name, "\'$action\' command not supported for $$d[4]", -1 ];
|
||||
return (\@output);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ use xCAT::GlobalDef;
|
||||
use xCAT::Usage;
|
||||
use xCAT::NetworkUtils;
|
||||
use xCAT::FSPUtils;
|
||||
require xCAT::data::ibmhwtypes;
|
||||
#use Data::Dumper;
|
||||
|
||||
##############################################
|
||||
@@ -259,7 +260,8 @@ sub format_output {
|
||||
# Strip errors for results
|
||||
#######################################
|
||||
my @val = grep( !/^#.*: ERROR /, @$values );
|
||||
xCAT::PPCdb::add_ppc( $hwtype, \@val );
|
||||
#xCAT::PPCdb::add_ppc( $hwtype, \@val );
|
||||
$values = xCAT::PPCdb::update_lpar( $hwtype, \@val, "write");
|
||||
}
|
||||
|
||||
###########################################
|
||||
@@ -270,7 +272,8 @@ sub format_output {
|
||||
# Strip errors for results
|
||||
#######################################
|
||||
my @val = grep( !/^#.*: ERROR /, @$values );
|
||||
$values = xCAT::PPCdb::update_ppc( $hwtype, \@val );
|
||||
#$values = xCAT::PPCdb::update_ppc( $hwtype, \@val );
|
||||
$values = xCAT::PPCdb::update_lpar( $hwtype, \@val );
|
||||
if ( exists( $opt->{x} ) or exists( $opt->{z} ))
|
||||
{
|
||||
unshift @$values, "hmc";
|
||||
@@ -391,6 +394,7 @@ sub format_stanza {
|
||||
#################################
|
||||
# Add each attribute
|
||||
#################################
|
||||
my $mtm = undef;
|
||||
foreach ( @attribs ) {
|
||||
my $d = $data[$i++];
|
||||
|
||||
@@ -401,7 +405,8 @@ sub format_stanza {
|
||||
} elsif ( /^hwtype$/ ) {
|
||||
$d = $globalhwtype{$type};
|
||||
} elsif ( /^groups$/ ) {
|
||||
$d = "$type,all";
|
||||
next;
|
||||
#$d = "$type,all";
|
||||
} elsif ( /^mgt$/ ) {
|
||||
$d = $hwtype;
|
||||
} elsif ( /^cons$/ ) {
|
||||
@@ -414,7 +419,9 @@ sub format_stanza {
|
||||
} elsif ( /^(mtm|serial)$/ ) {
|
||||
if ( $type eq "lpar" ) {
|
||||
$d = undef;
|
||||
}
|
||||
} elsif (/^mtm$/) {
|
||||
$mtm = $d;
|
||||
}
|
||||
} elsif (/^side$/) {
|
||||
unless ( $type =~ /^fsp|bpa$/ ) {
|
||||
next;
|
||||
@@ -422,6 +429,15 @@ sub format_stanza {
|
||||
}
|
||||
$result .= "\t$_=$d\n";
|
||||
}
|
||||
my $tmp_groups = "$type,all";
|
||||
if (defined($mtm)) {
|
||||
my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($mtm);
|
||||
if (defined($tmp_pre)) {
|
||||
$tmp_groups .= ",$tmp_pre";
|
||||
}
|
||||
}
|
||||
$result .= "\tgroups=$tmp_groups\n";
|
||||
|
||||
}
|
||||
return( $result );
|
||||
}
|
||||
@@ -464,6 +480,7 @@ sub format_xml {
|
||||
#################################
|
||||
# Add each attribute
|
||||
#################################
|
||||
my $mtm = undef;
|
||||
foreach ( @attribs ) {
|
||||
my $d = $data[$i++];
|
||||
|
||||
@@ -472,7 +489,8 @@ sub format_xml {
|
||||
} elsif ( /^hwtype$/ ) {
|
||||
$d = $globalhwtype{$type};
|
||||
} elsif ( /^groups$/ ) {
|
||||
$d = "$type,all";
|
||||
next;
|
||||
#$d = "$type,all";
|
||||
} elsif ( /^mgt$/ ) {
|
||||
$d = $hwtype;
|
||||
} elsif ( /^cons$/ ) {
|
||||
@@ -484,6 +502,8 @@ sub format_xml {
|
||||
} elsif ( /^(mtm|serial)$/ ) {
|
||||
if ( $type eq "lpar" ) {
|
||||
$d = undef;
|
||||
} elsif (/^mtm$/) {
|
||||
$mtm = $d;
|
||||
}
|
||||
} elsif (/^side$/) {
|
||||
unless ( $type =~ /^fsp|bpa$/ ) {
|
||||
@@ -492,6 +512,15 @@ sub format_xml {
|
||||
}
|
||||
$href->{Node}->{$_} = $d;
|
||||
}
|
||||
my $tmp_groups = "$type,all";
|
||||
if (defined($mtm)) {
|
||||
my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($mtm);
|
||||
if (defined($tmp_pre)) {
|
||||
$tmp_groups .= ",$tmp_pre";
|
||||
}
|
||||
}
|
||||
$href->{Node}->{groups}=$tmp_groups;
|
||||
|
||||
#print Dumper($href);
|
||||
#################################
|
||||
# XML encoding
|
||||
|
||||
@@ -116,6 +116,9 @@ sub enumerate_lcds {
|
||||
} else {
|
||||
my @array = split(/\n/, $data);
|
||||
foreach my $a (@array) {
|
||||
if ($a !~ /:\s?[^\s]*\s?[0|1]/) {
|
||||
next;
|
||||
}
|
||||
my @t = split(/:/, $a);
|
||||
my $name = $t[0];
|
||||
$data = $t[1];
|
||||
@@ -429,8 +432,10 @@ sub lcds {
|
||||
}
|
||||
}
|
||||
|
||||
if( $type =~ /lpar|blade/ ) {
|
||||
if( $type eq "lpar" ) {
|
||||
$action = "query_lcds";
|
||||
} elsif ($type eq "blade") {
|
||||
$action = "pblade_query_lcds";
|
||||
} else {
|
||||
$action = "cec_query_lcds";
|
||||
}
|
||||
|
||||
+906
-53
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@ $::NODETYPE_MP="mp";
|
||||
$::STATUS_SYNCING="syncing";
|
||||
$::STATUS_OUT_OF_SYNC="out-of-sync";
|
||||
$::STATUS_SYNCED="synced";
|
||||
$::STATUS_FAILED="failed";
|
||||
|
||||
|
||||
# valid values for nodelist.status columns or other status
|
||||
@@ -55,6 +56,7 @@ $::STATUS_SHELL="shell";
|
||||
$::STATUS_DEFINED="defined";
|
||||
$::STATUS_UNKNOWN="unknown";
|
||||
$::STATUS_FAILED="failed";
|
||||
$::STATUS_BMCREADY="bmcready";
|
||||
%::VALID_STATUS_VALUES = (
|
||||
$::STATUS_ACTIVE=>1,
|
||||
$::STATUS_INACTIVE=>1,
|
||||
@@ -71,6 +73,7 @@ $::STATUS_FAILED="failed";
|
||||
$::STATUS_DEFINED=>1,
|
||||
$::STATUS_UNKNOWN=>1,
|
||||
$::STATUS_FAILED=>1,
|
||||
$::STATUS_BMCREADY=>1,
|
||||
|
||||
$::STATUS_SYNCING=>1,
|
||||
$::STATUS_OUT_OF_SYNC=>1,
|
||||
|
||||
@@ -893,12 +893,12 @@ sub dolitesetup
|
||||
}
|
||||
}
|
||||
|
||||
if (-e $litetreetab) {
|
||||
my $rc = xCAT::Utils->runcmd("rm $litetreetab", -1);
|
||||
if (-e $litetreetable) {
|
||||
my $rc = xCAT::Utils->runcmd("rm $litetreetable", -1);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "Could not remove existing $litetreetab file.";
|
||||
push @{$rsp->{data}}, "Could not remove existing $litetreetable file.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
@@ -1132,6 +1132,10 @@ sub dolitesetup
|
||||
# $file could be full path file name or dir name
|
||||
# ex. /foo/bar/ or /etc/lppcfg
|
||||
my ($node, $option, $file) = split (/\|/, $line);
|
||||
|
||||
if (!$file) {
|
||||
next;
|
||||
}
|
||||
|
||||
# ex. .../inst_root/foo/bar/ or .../inst_root/etc/lppcfg
|
||||
my $instrootfile = $instrootloc . $file;
|
||||
@@ -1349,6 +1353,16 @@ sub dolitesetup
|
||||
return 1;
|
||||
}
|
||||
|
||||
# also copy $instrootloc/.statelite contents
|
||||
$ccmd = "/usr/bin/cp -p -r $instrootloc/.statelite $SRloc";
|
||||
$out = xCAT::Utils->runcmd("$ccmd", -1);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "Could not copy $instrootloc/.statelite to $SRloc.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,7 +827,7 @@ sub get_mac_addr {
|
||||
$done[0] = 0;
|
||||
$cmd[0] = "\" local-mac-address\" ". $phandle . " get-package-property\r";
|
||||
$msg[0] = "Status: return code and mac-address now on stack\n";
|
||||
$pattern[0] = "ok";#"\s*3 >";
|
||||
$pattern[0] = "local-mac-address.*ok";#"\s*3 >";
|
||||
$newstate[0] = 1;
|
||||
|
||||
# cmd(1) is a dot (.). This is a stack manipulation command that removes one
|
||||
@@ -1231,8 +1231,8 @@ sub ping_server{
|
||||
$done[2] = 0;
|
||||
$cmd[2] = "dev /packages/net\r";
|
||||
$msg[2] = "Status: selected the /packages/net node as the active package\n";
|
||||
#$pattern[2] = ".*dev(.*)ok(.*)0 >(.*)";
|
||||
$pattern[2] = "ok";
|
||||
$pattern[2] = ".*dev.*packages.*net(.*)ok(.*)0 >(.*)";
|
||||
#$pattern[2] = "ok";
|
||||
$newstate[2]= 3;
|
||||
|
||||
# state 3, ping the server
|
||||
@@ -1266,6 +1266,7 @@ sub ping_server{
|
||||
# state 5, all done
|
||||
$done[5] = 1;
|
||||
|
||||
|
||||
# for ping, only need to set speed and duplex for ethernet adapters
|
||||
#
|
||||
if ( $list_type eq "ent" ) {
|
||||
@@ -1323,8 +1324,10 @@ sub ping_server{
|
||||
|
||||
$timeout = 300;
|
||||
while ( $done[$state] eq 0 ) {
|
||||
|
||||
send_command($verbose, $rconsole, $cmd[$state]);
|
||||
@result = $rconsole->expect(
|
||||
|
||||
$timeout,
|
||||
[qr/$pattern[$state]/s=>
|
||||
sub {
|
||||
@@ -1362,7 +1365,9 @@ sub ping_server{
|
||||
}
|
||||
],
|
||||
);
|
||||
return 1 if ($rc eq 1);
|
||||
|
||||
return 1 if ($rc eq 1);
|
||||
|
||||
if ( $state eq 1 ) {
|
||||
$adap_conn = $adap_conn_list[$j];
|
||||
$cmd[1] = "\" ethernet,$adap_speed,$adap_conn,$adap_duplex\" encode-string \" chosen-network-type\" property\r";
|
||||
@@ -1849,6 +1854,14 @@ sub boot_network {
|
||||
$state = $newstate[$state];
|
||||
}
|
||||
],
|
||||
# For some old firmware, does not output "----"
|
||||
[qr/BOOTP/=>
|
||||
sub {
|
||||
nc_msg ($verbose, $msg[$state]);
|
||||
$rconsole->clear_accum();
|
||||
$state = $newstate[$state];
|
||||
}
|
||||
],
|
||||
[qr/]/=>
|
||||
sub {
|
||||
nc_msg($verbose, "Unexpected prompt\n");
|
||||
@@ -1917,7 +1930,28 @@ sub Boot {
|
||||
#],
|
||||
[qr/BOOTP/=> #-ex
|
||||
sub {
|
||||
nc_msg($verbose, "# Network boot proceeding, exiting.\n");
|
||||
nc_msg($verbose, "# Network boot proceeding - matched BOOTP, exiting.\n");
|
||||
$rconsole->clear_accum();
|
||||
}
|
||||
],
|
||||
# Welcome to AIX - some old firmware does not output BOOTP or ----
|
||||
[qr/Welcome/=> #-ex
|
||||
sub {
|
||||
nc_msg($verbose, "# Network boot proceeding - matched Welcome, exiting.\n");
|
||||
$rconsole->clear_accum();
|
||||
}
|
||||
],
|
||||
# tftp file download - some old firmware does not output BOOTP or ----
|
||||
[qr/FILE/=> #-ex
|
||||
sub {
|
||||
nc_msg($verbose, "# Network boot proceeding - matched FILE.\n");
|
||||
$rconsole->clear_accum();
|
||||
}
|
||||
],
|
||||
# some old firmware does not output BOOTP or ----
|
||||
[qr/Elapsed/=> #-ex
|
||||
sub {
|
||||
nc_msg($verbose, "# Network boot proceeding - matched Elapsed, exiting.\n");
|
||||
$rconsole->clear_accum();
|
||||
}
|
||||
],
|
||||
@@ -2021,14 +2055,46 @@ sub multiple_open_dev {
|
||||
; \r";
|
||||
send_command($verbose, $rconsole, $command);
|
||||
|
||||
$command = "patch new-open-dev open-dev net-ping \r";
|
||||
send_command($verbose, $rconsole, $command);
|
||||
|
||||
$timeout = 30;
|
||||
$rconsole->expect(
|
||||
$timeout,
|
||||
#[qr/patch new-open-dev(.*)>/=>
|
||||
[qr/>/=>
|
||||
[qr/new-open-dev(.*)ok/=>
|
||||
#[qr/>/=>
|
||||
sub {
|
||||
nc_msg($verbose, "Status: at End of multiple_open_dev \n");
|
||||
$rconsole->clear_accum();
|
||||
}
|
||||
],
|
||||
[qr/]/=>
|
||||
sub {
|
||||
nc_msg($verbose, "Unexpected prompt\n");
|
||||
$rconsole->clear_accum();
|
||||
$rc = 1;
|
||||
}
|
||||
],
|
||||
[timeout =>
|
||||
sub {
|
||||
send_user(2, "Timeout\n");
|
||||
$rconsole->clear_accum();
|
||||
$rc = 1;
|
||||
}
|
||||
],
|
||||
[eof =>
|
||||
sub {
|
||||
send_user(2, "Cannot connect to $node\n");
|
||||
$rconsole->clear_accum();
|
||||
$rc = 1;
|
||||
}
|
||||
],
|
||||
);
|
||||
|
||||
$command = "patch new-open-dev open-dev net-ping \r";
|
||||
send_command($verbose, $rconsole, $command);
|
||||
|
||||
$rconsole->expect(
|
||||
$timeout,
|
||||
[qr/patch new-open-dev(.*)ok/=>
|
||||
#[qr/>/=>
|
||||
sub {
|
||||
nc_msg($verbose, "Status: at End of multiple_open_dev \n");
|
||||
$rconsole->clear_accum();
|
||||
@@ -2057,6 +2123,7 @@ sub multiple_open_dev {
|
||||
}
|
||||
],
|
||||
);
|
||||
|
||||
return $rc;
|
||||
}
|
||||
###################################################################
|
||||
@@ -2540,7 +2607,7 @@ sub lparnetbootexp
|
||||
####################################
|
||||
nc_msg($verbose, "Connecting to the $node.\n");
|
||||
sleep 3;
|
||||
$timeout = 2;
|
||||
$timeout = 10;
|
||||
$rconsole->expect(
|
||||
$timeout,
|
||||
[ qr/Enter.* for help.*/i =>
|
||||
@@ -2749,6 +2816,8 @@ sub lparnetbootexp
|
||||
$done = 0;
|
||||
$retry_count = 0;
|
||||
|
||||
$timeout = 10;
|
||||
|
||||
while (!$done) {
|
||||
my @result = $rconsole->expect(
|
||||
$timeout,
|
||||
@@ -2856,6 +2925,7 @@ sub lparnetbootexp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
##############################
|
||||
# Call multiple_open_dev to
|
||||
# circumvent firmware OPEN-DEV
|
||||
@@ -2890,6 +2960,7 @@ sub lparnetbootexp
|
||||
$match_pat = ".*";
|
||||
}
|
||||
|
||||
|
||||
if($colon) {
|
||||
nc_msg($verbose, "#Type:Location_Code:MAC_Address:Full_Path_Name:Ping_Result:Device_Type:Size_MB:OS:OS_Version:\n");
|
||||
$outputarrayindex++; # start from 1, 0 is used to set as 0
|
||||
@@ -2943,7 +3014,7 @@ sub lparnetbootexp
|
||||
} else {
|
||||
for( $i = 0; $i < $adapter_found; $i++) {
|
||||
if ($adap_type[$i] =~ /$match_pat/) {
|
||||
if ($adap_type[$i] eq "hfi-ent") {
|
||||
if (!($adap_type[$i] eq "hfi-ent")) {
|
||||
$mac_address = get_mac_addr($phandle_array[$i], $rconsole, $node, $verbose);
|
||||
$loc_code = get_adaptr_loc($phandle_array[$i], $rconsole, $node, $verbose);
|
||||
}
|
||||
@@ -3148,12 +3219,12 @@ sub lparnetbootexp
|
||||
}
|
||||
],
|
||||
);
|
||||
return [1] if ($rc eq 1);
|
||||
}
|
||||
nc_msg($verbose, "# bootp sent over network.\n");
|
||||
$rc = Boot($rconsole, $node, $verbose);#, @expect_out);
|
||||
unless ($rc eq 0) {
|
||||
nc_msg($verbose, "Can't boot here. \n");
|
||||
return [1] if ($rc eq 1);
|
||||
nc_msg($verbose, "# bootp sent over network.\n");
|
||||
$rc = Boot($rconsole, $node, $verbose);#, @expect_out);
|
||||
unless ($rc eq 0) {
|
||||
nc_msg($verbose, "Can't boot here. \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ if ($^O =~ /^aix/i) {
|
||||
}
|
||||
|
||||
use strict;
|
||||
use Sys::Syslog qw (:DEFAULT setlogsock);
|
||||
use Sys::Syslog;
|
||||
use xCAT::Utils;
|
||||
#use locale;
|
||||
use Socket;
|
||||
@@ -456,8 +456,7 @@ sub message
|
||||
|
||||
# If they want this msg to also go to syslog, do that now
|
||||
eval {
|
||||
openlog("xCAT", '', 'local4');
|
||||
setlogsock(["tcp", "unix", "stream"]);
|
||||
openlog("xCAT", "nofatal,pid", "local4");
|
||||
if ($sev eq 'SE') {
|
||||
syslog("err", $rsp);
|
||||
} else {
|
||||
@@ -503,8 +502,7 @@ sub message
|
||||
{
|
||||
print $stdouterrf "Unable to open auditlog\n";
|
||||
eval {
|
||||
openlog("xCAT", '', 'local4');
|
||||
setlogsock(["tcp", "unix", "stream"]);
|
||||
openlog("xCAT", "nofatal,pid", "local4");
|
||||
syslog("err", "Unable to write to auditlog");
|
||||
closelog();
|
||||
};
|
||||
@@ -521,8 +519,7 @@ sub message
|
||||
{ # error
|
||||
print $stdouterrf "Unable to open auditlog\n";
|
||||
eval {
|
||||
openlog("xCAT", '', 'local4');
|
||||
setlogsock(["tcp", "unix", "stream"]);
|
||||
openlog("xCAT", "nofatal,pid", "local4");
|
||||
syslog("err", "Unable to open auditlog");
|
||||
closelog();
|
||||
};
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
package xCAT::NameRange;
|
||||
require xCAT::Table;
|
||||
require Exporter;
|
||||
use strict;
|
||||
|
||||
#Perl implementation of namerange
|
||||
# NOTE: This is identical to xCAT::NodeRange except that no
|
||||
# database access occurs, no nodes are verified, and
|
||||
# no nodegroups are expanded.
|
||||
# Made a new utility since NodeRange is used EVERYWHERE in
|
||||
# xCAT code and did not want to risk de-stabilizing existing code.
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(namerange);
|
||||
|
||||
my $recurselevel=0;
|
||||
|
||||
|
||||
sub subnodes (\@@) {
|
||||
#Subtract set of nodes from the first list
|
||||
my $nodes = shift;
|
||||
my $node;
|
||||
foreach $node (@_) {
|
||||
@$nodes = (grep(!/^$node$/,@$nodes));
|
||||
}
|
||||
}
|
||||
|
||||
sub expandatom {
|
||||
my $atom = shift;
|
||||
my @nodes= ();
|
||||
if ($atom =~ /^\(.*\)$/) { # handle parentheses by recursively calling namerange()
|
||||
$atom =~ s/^\((.*)\)$/$1/;
|
||||
$recurselevel++;
|
||||
return namerange($atom);
|
||||
}
|
||||
if ($atom =~ /@/) {
|
||||
$recurselevel++;
|
||||
return namerange($atom);
|
||||
}
|
||||
|
||||
if ($atom =~ m/^\//) { # A regular expression - not supported in namerange
|
||||
return ($atom);
|
||||
}
|
||||
|
||||
if ($atom =~ m/(.*)\[(.*)\](.*)/) { # square bracket range
|
||||
#for the time being, we are only going to consider one [] per atom
|
||||
#xcat 1.2 does no better
|
||||
my @subelems = split(/([\,\-\:])/,$2);
|
||||
my $subrange="";
|
||||
while (my $subelem = shift @subelems) {
|
||||
my $subop=shift @subelems;
|
||||
$subrange=$subrange."$1$subelem$3$subop";
|
||||
}
|
||||
foreach (split /,/,$subrange) {
|
||||
my @newnodes=expandatom($_);
|
||||
@nodes=(@nodes,@newnodes);
|
||||
}
|
||||
return @nodes;
|
||||
}
|
||||
|
||||
if ($atom =~ m/\+/) { # process the + operator
|
||||
$atom =~ m/^([^0-9]*)([0-9]+)([^\+]*)\+([0-9]+)/;
|
||||
my $pref=$1;
|
||||
my $startnum=$2;
|
||||
my $suf=$3;
|
||||
my $end=$4+$startnum;
|
||||
my $endnum = sprintf("%d",$end);
|
||||
if (length ($startnum) > length ($endnum)) {
|
||||
$endnum = sprintf("%0".length($startnum)."d",$end);
|
||||
}
|
||||
foreach ("$startnum".."$endnum") {
|
||||
my @addnodes=expandatom($pref.$_.$suf);
|
||||
@nodes=(@nodes,@addnodes);
|
||||
}
|
||||
return (@nodes);
|
||||
}
|
||||
|
||||
if ($atom =~ m/[-:]/) { # process the minus range operator
|
||||
my $left;
|
||||
my $right;
|
||||
if ($atom =~ m/:/) {
|
||||
($left,$right)=split /:/,$atom;
|
||||
} else {
|
||||
my $count= ($atom =~ tr/-//);
|
||||
if (($count % 2)==0) { #can't understand even numbers of - in range context
|
||||
# we might not really be in range context
|
||||
return ($atom);
|
||||
}
|
||||
my $expr="([^-]+?".("-[^-]*"x($count/2)).")-(.*)";
|
||||
$atom =~ m/$expr/;
|
||||
$left=$1;
|
||||
$right=$2;
|
||||
}
|
||||
if ($left eq $right) { #if they said node1-node1 for some strange reason
|
||||
return expandatom($left);
|
||||
}
|
||||
my @leftarr=split(/(\d+)/,$left);
|
||||
my @rightarr=split(/(\d+)/,$right);
|
||||
if (scalar(@leftarr) != scalar(@rightarr)) { #Mismatch formatting..
|
||||
# guess it's meant to be a nodename
|
||||
return ($atom);
|
||||
}
|
||||
my $prefix = "";
|
||||
my $suffix = "";
|
||||
foreach (0..$#leftarr) {
|
||||
my $idx = $_;
|
||||
if ($leftarr[$idx] =~ /^\d+$/ and $rightarr[$idx] =~ /^\d+$/) { #pure numeric component
|
||||
if ($leftarr[$idx] ne $rightarr[$idx]) { #We have found the iterator (only supporting one for now)
|
||||
my $prefix = join('',@leftarr[0..($idx-1)]); #Make a prefix of the pre-validated parts
|
||||
my $luffix; #However, the remainder must still be validated to be the same
|
||||
my $ruffix;
|
||||
if ($idx eq $#leftarr) {
|
||||
$luffix="";
|
||||
$ruffix="";
|
||||
} else {
|
||||
$ruffix = join('',@rightarr[($idx+1)..$#rightarr]);
|
||||
$luffix = join('',@leftarr[($idx+1)..$#leftarr]);
|
||||
}
|
||||
if ($luffix ne $ruffix) { #the suffixes mismatched..
|
||||
return ($atom);
|
||||
}
|
||||
foreach ($leftarr[$idx]..$rightarr[$idx]) {
|
||||
my @addnodes=expandatom($prefix.$_.$luffix);
|
||||
@nodes=(@nodes,@addnodes);
|
||||
}
|
||||
return (@nodes); #the return has been built, return, exiting loop and all
|
||||
}
|
||||
} elsif ($leftarr[$idx] ne $rightarr[$idx]) {
|
||||
return ($atom);
|
||||
}
|
||||
$prefix .= $leftarr[$idx]; #If here, it means that the pieces were the same, but more to come
|
||||
}
|
||||
#I cannot conceive how the code could possibly be here, but whatever it is, it must be questionable
|
||||
return ($atom);
|
||||
}
|
||||
|
||||
return ($atom);
|
||||
}
|
||||
|
||||
sub namerange {
|
||||
#We for now just do left to right operations
|
||||
my $range=shift;
|
||||
my %nodes = ();
|
||||
my %delnodes = ();
|
||||
my $op = ",";
|
||||
my @elems = split(/(,(?![^[]*?])(?![^\(]*?\)))/,$range); # commas outside of [] or ()
|
||||
if (scalar(@elems)==1) {
|
||||
@elems = split(/(@(?![^\(]*?\)))/,$range); # only split on @ when no , are present (inner recursion)
|
||||
}
|
||||
|
||||
while (my $atom = shift @elems) {
|
||||
if ($atom =~ /^-/) { # if this is an exclusion, strip off the minus, but remember it
|
||||
$atom = substr($atom,1);
|
||||
$op = $op."-";
|
||||
}
|
||||
|
||||
if ($atom =~ /^\^(.*)$/) { # get a list of nodes from a file
|
||||
open(NRF,$1);
|
||||
while (<NRF>) {
|
||||
my $line=$_;
|
||||
unless ($line =~ m/^[\^#]/) {
|
||||
$line =~ m/^([^: ]*)/;
|
||||
my $newrange = $1;
|
||||
chomp($newrange);
|
||||
$recurselevel++;
|
||||
my @filenodes = namerange($newrange);
|
||||
foreach (@filenodes) {
|
||||
$nodes{$_}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(NRF);
|
||||
next;
|
||||
}
|
||||
|
||||
my %newset = map { $_ =>1 } expandatom($atom); # expand the atom and make each entry in the resulting array a key in newset
|
||||
|
||||
if ($op =~ /@/) { # compute the intersection of the current atom and the node list we have received before this
|
||||
foreach (keys %nodes) {
|
||||
unless ($newset{$_}) {
|
||||
delete $nodes{$_};
|
||||
}
|
||||
}
|
||||
} elsif ($op =~ /,-/) { # add the nodes from this atom to the exclude list
|
||||
foreach (keys %newset) {
|
||||
$delnodes{$_}=1; #delay removal to end
|
||||
}
|
||||
} else { # add the nodes from this atom to the total node list
|
||||
foreach (keys %newset) {
|
||||
$nodes{$_}=1;
|
||||
}
|
||||
}
|
||||
$op = shift @elems;
|
||||
|
||||
} # end of main while loop
|
||||
|
||||
# Now remove all the exclusion nodes
|
||||
foreach (keys %nodes) {
|
||||
if ($delnodes{$_}) {
|
||||
delete $nodes{$_};
|
||||
}
|
||||
}
|
||||
if ($recurselevel) {
|
||||
$recurselevel--;
|
||||
}
|
||||
return sort (keys %nodes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
xCAT::NameRange - Perl module for xCAT namerange expansion
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use xCAT::NameRange;
|
||||
my @nodes=namerange("storage@rack1,node[1-200],^/tmp/nodelist,node300-node400,node401+10,500-550");
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
namerange interprets xCAT noderange formatted strings and returns a list of
|
||||
names. The following two operations are supported on elements, and interpreted
|
||||
left to right:
|
||||
|
||||
, union next element with everything to the left.
|
||||
|
||||
@ take intersection of element to the right with everything on the left
|
||||
(i.e. mask out anything to the left not belonging to what is described to
|
||||
the right)
|
||||
|
||||
Each element can be a number of things:
|
||||
|
||||
A node name, i.e.:
|
||||
|
||||
=item * node1
|
||||
|
||||
A hyphenated node range (only one group of numbers may differ between the left and right hand side, and those numbers will increment in a base 10 fashion):
|
||||
|
||||
node1-node200 node1-compute-node200-compute
|
||||
node1:node200 node1-compute:node200-compute
|
||||
|
||||
A namerange denoted by brackets:
|
||||
|
||||
node[1-200] node[001-200]
|
||||
|
||||
A regular expression describing the namerange:
|
||||
|
||||
/d(1.?.?|200)
|
||||
|
||||
A node plus offset (this increments the first number found in nodename):
|
||||
|
||||
node1+199
|
||||
|
||||
And most of the above substituting groupnames.
|
||||
3C
|
||||
3C
|
||||
|
||||
NameRange tries to be intelligent about detecting padding, so you can:
|
||||
node001-node200
|
||||
And it will increment according to the pattern.
|
||||
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2007 IBM Corp. All rights reserved.
|
||||
|
||||
|
||||
=cut
|
||||
@@ -422,11 +422,6 @@ sub ishostinsubnet {
|
||||
if ($ip =~ /:/) {#ipv6
|
||||
$numbits=128;
|
||||
}
|
||||
# IPv6 subnet with netmask postfix like /64
|
||||
if ($subnet && ($subnet =~ /\//))
|
||||
{
|
||||
$subnet =~ s/\/.*$//;
|
||||
}
|
||||
if ($mask) {
|
||||
if ($mask =~ /\//) {
|
||||
$mask =~ s/^\///;
|
||||
@@ -442,6 +437,10 @@ sub ishostinsubnet {
|
||||
die "ishostinsubnet must either be called with a netmask or CIDR /bits notation";
|
||||
}
|
||||
}
|
||||
if ($subnet && ($subnet =~ /\//)) #remove CIDR suffix from subnet
|
||||
{
|
||||
$subnet =~ s/\/.*$//;
|
||||
}
|
||||
$ip = getipaddr($ip,GetNumber=>1);
|
||||
$subnet = getipaddr($subnet,GetNumber=>1);
|
||||
$ip &= $mask;
|
||||
@@ -2196,7 +2195,6 @@ sub isValidHostname
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 isValidFQDN
|
||||
@@ -2255,6 +2253,26 @@ sub int_to_ip
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 getBroadcast
|
||||
Description : Get the broadcast ips
|
||||
Arguments : ipstr - the IPv4 string ip.
|
||||
netmask - the subnet mask of network
|
||||
Returns : bcipint - the IPv4 string of broadcast ip.
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub getBroadcast
|
||||
{
|
||||
my ($class, $ipstr, $netmask) = @_;
|
||||
my $ipint = xCAT::NetworkUtils->ip_to_int($ipstr);
|
||||
my $maskint = xCAT::NetworkUtils->ip_to_int($netmask);
|
||||
my $tmp = sprintf("%d", ~$maskint);
|
||||
my $bcnum = sprintf("%d", ($ipint | $tmp) & hex('0x00000000FFFFFFFF'));
|
||||
return xCAT::NetworkUtils->int_to_ip($bcnum);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 get_allips_in_range
|
||||
Description : Get all IPs in a IP range, return in a list.
|
||||
Arguments : $startip - start IP address
|
||||
|
||||
+99
-33
@@ -1,5 +1,6 @@
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
package xCAT::NodeRange;
|
||||
use Text::Balanced qw/extract_bracketed/;
|
||||
require xCAT::Table;
|
||||
require Exporter;
|
||||
use strict;
|
||||
@@ -148,7 +149,7 @@ sub nodesbycriteria {
|
||||
}
|
||||
if ($neednewcache) {
|
||||
if ($nodelist) {
|
||||
$nodelist->_clear_cache();
|
||||
#$nodelist->_clear_cache();
|
||||
$nodelist->_build_cache(\@cachedcolumns);
|
||||
}
|
||||
}
|
||||
@@ -180,7 +181,14 @@ sub nodesbycriteria {
|
||||
return \%critnodes;
|
||||
}
|
||||
|
||||
sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels5.3)
|
||||
# Expand one part of the noderange from the noderange() function. Initially, one part means the
|
||||
# substring between commas in the noderange. But expandatom also calls itself recursively to
|
||||
# further expand some parts.
|
||||
# Input args:
|
||||
# - atom to expand
|
||||
# - verify: whether or not to require that the resulting nodenames exist in the nodelist table
|
||||
# - options: genericrange - a purely syntactical expansion of the range, not using the db at all, e.g not expanding group names
|
||||
sub expandatom {
|
||||
my $atom = shift;
|
||||
if ($recurselevel > 4096) { die "NodeRange seems to be hung on evaluating $atom, recursion limit hit"; }
|
||||
unless (scalar(@allnodeset) and (($allnodesetstamp+5) > time())) { #Build a cache of all nodes, some corner cases will perform worse, but by and large it will do better. We could do tests to see where the breaking points are, and predict how many atoms we have to evaluate to mitigate, for now, implement the strategy that keeps performance from going completely off the rails
|
||||
@@ -189,25 +197,28 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
@allnodeset = $nodelist->getAllAttribs('node','groups');
|
||||
%allnodehash = map { $_->{node} => 1 } @allnodeset;
|
||||
}
|
||||
my $verify = (scalar(@_) == 1 ? shift : 1);
|
||||
my $verify = (scalar(@_) >= 1 ? shift : 1);
|
||||
my %options = @_; # additional options
|
||||
my @nodes= ();
|
||||
#TODO: these env vars need to get passed by the client to xcatd
|
||||
my $nprefix=(defined ($ENV{'XCAT_NODE_PREFIX'}) ? $ENV{'XCAT_NODE_PREFIX'} : 'node');
|
||||
my $nsuffix=(defined ($ENV{'XCAT_NODE_SUFFIX'}) ? $ENV{'XCAT_NODE_SUFFIX'} : '');
|
||||
if ($allnodehash{$atom}) { #The atom is a plain old nodename
|
||||
|
||||
if (not $options{genericrange} and $allnodehash{$atom}) { #The atom is a plain old nodename
|
||||
return ($atom);
|
||||
}
|
||||
if ($atom =~ /^\(.*\)$/) { # handle parentheses by recursively calling noderange()
|
||||
$atom =~ s/^\((.*)\)$/$1/;
|
||||
$recurselevel++;
|
||||
return noderange($atom);
|
||||
return noderange($atom,$verify,1,%options);
|
||||
}
|
||||
if ($atom =~ /@/) {
|
||||
$recurselevel++;
|
||||
return noderange($atom);
|
||||
return noderange($atom,$verify,1,%options);
|
||||
}
|
||||
|
||||
# Try to match groups?
|
||||
unless ($options{genericrange}) {
|
||||
unless ($grptab) {
|
||||
$grptab = xCAT::Table->new('nodegroup');
|
||||
}
|
||||
@@ -269,7 +280,9 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# node selection based on db attribute values (nodetype.os==rhels5.3)
|
||||
if ($atom =~ m/[=~]/) { #TODO: this is the clunky, slow code path to acheive the goal. It also is the easiest to write, strange coincidence. Aggregating multiples would be nice
|
||||
my @nodes;
|
||||
foreach (@allnodeset) {
|
||||
@@ -287,7 +300,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
}
|
||||
if ($atom =~ m/^[0-9]+\z/) { # if only numbers, then add the prefix
|
||||
my $nodename=$nprefix.$atom.$nsuffix;
|
||||
return expandatom($nodename,$verify);
|
||||
return expandatom($nodename,$verify,%options);
|
||||
}
|
||||
my $nodelen=@nodes;
|
||||
if ($nodelen > 0) {
|
||||
@@ -295,7 +308,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
}
|
||||
|
||||
if ($atom =~ m/^\//) { # A regular expression
|
||||
unless ($verify) { # If not in verify mode, regex makes zero possible sense
|
||||
if ($verify==0 or $options{genericrange}) { # If not in verify mode, regex makes zero possible sense
|
||||
return ($atom);
|
||||
}
|
||||
#TODO: check against all groups
|
||||
@@ -309,25 +322,29 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
}
|
||||
|
||||
if ($atom =~ m/(.+?)\[(.+?)\](.*)/) { # square bracket range
|
||||
# if there are more than 1 [], we picked off just the 1st. if there is another, we will process it later
|
||||
my @subelems = split(/([\,\-\:])/,$2);
|
||||
# if there is more than 1 set of [], we picked off just the 1st. If there more sets of [], we will expand
|
||||
# the 1st set and create a new set of atom by concatenating each result in the 1st expandsion with the rest
|
||||
# of the brackets. Then call expandatom() recursively on each new atom.
|
||||
my @subelems = split(/([\,\-\:])/,$2); # $2 is the range inside the 1st set of brackets
|
||||
my $subrange="";
|
||||
my $subelem;
|
||||
my $start = $1;
|
||||
my $ending = $3;
|
||||
my $morebrackets = $ending =~ /\[.+?\]/; # if there are more brackets, we have to expand just the 1st part, then add the 2nd part later
|
||||
while (scalar @subelems) {
|
||||
my $subelem = shift @subelems;
|
||||
my $subelem;
|
||||
my $start = $1; # the text before the 1st set of brackets
|
||||
my $ending = $3; # the text after the 1st set of brackets (could contain more brackets)
|
||||
my $morebrackets = $ending =~ /\[.+?\]/; # if there are more brackets, we have to expand just the 1st part, then add the 2nd part later
|
||||
while (scalar @subelems) { # this while loop turns something like a[1-3] into a1-a3 because another section of expand atom knows how to expand that
|
||||
my $subelem = shift @subelems;
|
||||
my $subop=shift @subelems;
|
||||
$subrange=$subrange."$start$subelem" . ($morebrackets?'':$ending) . "$subop";
|
||||
}
|
||||
foreach (split /,/,$subrange) {
|
||||
my @newnodes=expandatom($_, ($morebrackets?0:$verify));
|
||||
foreach (split /,/,$subrange) { # this foreach is in case there were commas inside the brackets originally, e.g.: a[1,3,5]b[1-2]
|
||||
# this expandatom just expands the part of the noderange that contains the 1st set of brackets
|
||||
# e.g. if noderange is a[1-2]b[1-2] it will create newnodes of a1 and a2
|
||||
my @newnodes=expandatom($_, ($morebrackets?0:$verify), genericrange=>($morebrackets||$options{genericrange}));
|
||||
if (!$morebrackets) { push @nodes,@newnodes; }
|
||||
else {
|
||||
# for each of the new nodes, add the 2nd brackets and then expand
|
||||
# for each of the new nodes (prefixes), add the rest of the brackets and then expand recursively
|
||||
foreach my $n (@newnodes) {
|
||||
push @nodes, expandatom("$n$ending", $verify);
|
||||
push @nodes, expandatom("$n$ending", $verify, %options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -349,7 +366,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
$suf=$nsuffix;
|
||||
}
|
||||
foreach ("$startnum".."$endnum") {
|
||||
my @addnodes=expandatom($pref.$_.$suf,$verify);
|
||||
my @addnodes=expandatom($pref.$_.$suf,$verify,%options);
|
||||
@nodes=(@nodes,@addnodes);
|
||||
}
|
||||
return (@nodes);
|
||||
@@ -376,7 +393,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
$right=$2;
|
||||
}
|
||||
if ($left eq $right) { #if they said node1-node1 for some strange reason
|
||||
return expandatom($left,$verify);
|
||||
return expandatom($left,$verify,%options);
|
||||
}
|
||||
my @leftarr=split(/(\d+)/,$left);
|
||||
my @rightarr=split(/(\d+)/,$right);
|
||||
@@ -413,7 +430,7 @@ sub expandatom { #TODO: implement table selection as an atom (nodetype.os==rhels
|
||||
}
|
||||
}
|
||||
foreach ($leftarr[$idx]..$rightarr[$idx]) {
|
||||
my @addnodes=expandatom($prefix.$_.$luffix,$verify);
|
||||
my @addnodes=expandatom($prefix.$_.$luffix,$verify,%options);
|
||||
push @nodes,@addnodes;
|
||||
}
|
||||
return (@nodes); #the return has been built, return, exiting loop and all
|
||||
@@ -461,7 +478,7 @@ sub retain_cache { #A semi private operation to be used *ONLY* in the interestin
|
||||
%allgrphash=();
|
||||
}
|
||||
}
|
||||
sub extnoderange { #An extended noderange function. Needed as the more straightforward function return format too simple for this.
|
||||
sub extnoderange { #An extended noderange function. Needed by the GUI as the more straightforward function return format too simple for this.
|
||||
my $range = shift;
|
||||
my $namedopts = shift;
|
||||
my $verify=1;
|
||||
@@ -487,7 +504,7 @@ sub extnoderange { #An extended noderange function. Needed as the more straight
|
||||
return $return;
|
||||
}
|
||||
sub abbreviate_noderange {
|
||||
#takes a list of nodes or a string and abbreviates
|
||||
#takes a list of nodes or a string and reduces it by replacing a list of nodes that make up a group with the group name itself
|
||||
my $nodes=shift;
|
||||
my %grouphash;
|
||||
my %sizedgroups;
|
||||
@@ -533,16 +550,40 @@ sub abbreviate_noderange {
|
||||
return (join ',',keys %targetelems,keys %nodesleft);
|
||||
}
|
||||
|
||||
sub set_arith {
|
||||
my $operand = shift;
|
||||
my $op = shift;
|
||||
my $newset = shift;
|
||||
if ($op =~ /@/) { # compute the intersection of the current atom and the node list we have received before this
|
||||
foreach (keys %$operand) {
|
||||
unless ($newset->{$_}) {
|
||||
delete $operand->{$_};
|
||||
}
|
||||
}
|
||||
} elsif ($op =~ /,-/) { # add the nodes from this atom to the exclude list
|
||||
foreach (keys %$newset) {
|
||||
delete $operand->{$_}
|
||||
}
|
||||
} else { # add the nodes from this atom to the total node list
|
||||
foreach (keys %$newset) {
|
||||
$operand->{$_}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
# Expand the given noderange
|
||||
# Input args:
|
||||
# - noderange to expand
|
||||
# - verify: whether or not to require that the resulting nodenames exist in the nodelist table
|
||||
# - exsitenode: whether or not to honor site.excludenodes to automatically exclude those nodes from all noderanges
|
||||
# - options: genericrange - a purely syntactical expansion of the range, not using the db at all, e.g not expanding group names
|
||||
sub noderange {
|
||||
$missingnodes=[];
|
||||
#We for now just do left to right operations
|
||||
my $range=shift;
|
||||
$range =~ s/['"]//g;
|
||||
my $verify = (scalar(@_) >= 1 ? shift : 1);
|
||||
|
||||
#excludenodes attribute in site table,
|
||||
#these nodes should be excluded for any xCAT commands
|
||||
my $exsitenode = (scalar(@_) >= 1 ? shift : 1);
|
||||
my $exsitenode = (scalar(@_) >= 1 ? shift : 1); # if 1, honor site.excludenodes
|
||||
my %options = @_; # additional options
|
||||
|
||||
unless ($nodelist) {
|
||||
$nodelist =xCAT::Table->new('nodelist',-create =>1);
|
||||
@@ -553,20 +594,45 @@ sub noderange {
|
||||
}
|
||||
my %nodes = ();
|
||||
my %delnodes = ();
|
||||
if ($range =~ /\(/) {
|
||||
my ($middle, $end, $start) =
|
||||
extract_bracketed($range, '()', qr/[^()]*/);
|
||||
unless ($middle) { die "Unbalanced parentheses in noderange" }
|
||||
$middle = substr($middle,1,-1);
|
||||
my $op = ",";
|
||||
if ($start =~ m/-$/) { #subtract the parenthetical
|
||||
$op .= "-"
|
||||
} elsif ($start =~ m/\@$/) {
|
||||
$op = "@"
|
||||
}
|
||||
$start =~ s/,-$//;
|
||||
$start =~ s/,$//;
|
||||
$start =~ s/\@$//;
|
||||
%nodes = map { $_ => 1 } noderange($start,$verify,$exsitenode,%options);
|
||||
my %innernodes = map { $_ => 1 } noderange($middle,$verify,$exsitenode,%options);
|
||||
set_arith(\%nodes,$op,\%innernodes);
|
||||
$range = $end;
|
||||
}
|
||||
|
||||
my $op = ",";
|
||||
my @elems = split(/(,(?![^[]*?])(?![^\(]*?\)))/,$range); # commas outside of [] or ()
|
||||
if (scalar(@elems)==1) {
|
||||
@elems = split(/(@(?![^\(]*?\)))/,$range); # only split on @ when no , are present (inner recursion)
|
||||
}
|
||||
|
||||
while (my $atom = shift @elems) {
|
||||
while (defined(my $atom = shift @elems)) {
|
||||
if ($atom eq '') { next; }
|
||||
if ($atom eq ',') {
|
||||
next;
|
||||
}
|
||||
if ($atom =~ /^-/) { # if this is an exclusion, strip off the minus, but remember it
|
||||
$atom = substr($atom,1);
|
||||
$op = $op."-";
|
||||
} elsif ($atom =~ /^\@/) { # if this is an exclusion, strip off the minus, but remember it
|
||||
$atom = substr($atom,1);
|
||||
$op = "@";
|
||||
}
|
||||
if ($atom eq '') { next; }
|
||||
|
||||
if ($atom =~ /^\^(.*)$/) { # get a list of nodes from a file
|
||||
open(NRF,$1);
|
||||
@@ -577,7 +643,7 @@ sub noderange {
|
||||
my $newrange = $1;
|
||||
chomp($newrange);
|
||||
$recurselevel++;
|
||||
my @filenodes = noderange($newrange);
|
||||
my @filenodes = noderange($newrange,$verify,$exsitenode,%options);
|
||||
foreach (@filenodes) {
|
||||
$nodes{$_}=1;
|
||||
}
|
||||
@@ -587,7 +653,7 @@ sub noderange {
|
||||
next;
|
||||
}
|
||||
|
||||
my %newset = map { $_ =>1 } expandatom($atom,$verify); # expand the atom and make each entry in the resulting array a key in newset
|
||||
my %newset = map { $_ =>1 } expandatom($atom,$verify,%options); # expand the atom and make each entry in the resulting array a key in newset
|
||||
|
||||
if ($op =~ /@/) { # compute the intersection of the current atom and the node list we have received before this
|
||||
foreach (keys %nodes) {
|
||||
@@ -614,7 +680,7 @@ sub noderange {
|
||||
my $badnoderange = 0;
|
||||
my @badnodes = ();
|
||||
if ($::XCATSITEVALS{excludenodes}) {
|
||||
@badnodes = noderange($::XCATSITEVALS{excludenodes}, 1, 0);
|
||||
@badnodes = noderange($::XCATSITEVALS{excludenodes}, 1, 0, %options);
|
||||
foreach my $bnode (@badnodes) {
|
||||
if (!$delnodes{$bnode}) {
|
||||
$delnodes{$bnode} = 1;
|
||||
|
||||
@@ -139,7 +139,7 @@ sub connect {
|
||||
my $timeout = $req->{ppctimeout};
|
||||
my $verbose = $req->{verbose};
|
||||
my $ssh;
|
||||
my $expect_log;
|
||||
my $expect_log = "/dev/null";
|
||||
my $errmsg;
|
||||
|
||||
if ($req->{command} eq 'rflash') {
|
||||
@@ -170,7 +170,7 @@ sub connect {
|
||||
##################################################
|
||||
if ( $verbose ) {
|
||||
close STDERR;
|
||||
if ( !open( STDERR, '>', \$expect_log )) {
|
||||
if ( !open( STDERR, '>', $expect_log )) {
|
||||
return( "Unable to redirect STDERR: $!" );
|
||||
}
|
||||
}
|
||||
@@ -179,7 +179,7 @@ sub connect {
|
||||
##################################################
|
||||
if ( $verbose ) {
|
||||
close STDOUT;
|
||||
if ( !open( STDOUT, '>', \$expect_log )) {
|
||||
if ( !open( STDOUT, '>', $expect_log )) {
|
||||
return( "Unable to redirect STDOUT: $!" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ sub mkhwconn_parse_args
|
||||
#my $nodetype_hash = $nodetypetab->getNodeAttribs( $node,[qw(nodetype)]);
|
||||
my $node_parent_hash = $ppctab->getNodeAttribs( $node,[qw(parent)]);
|
||||
#$nodetype = $nodetype_hash->{nodetype};
|
||||
$nodetype = xCAT::DBobjUtils->getnodetype($node);
|
||||
$nodetype = xCAT::DBobjUtils->getnodetype($node,"ppc");
|
||||
$node_parent = $node_parent_hash->{parent};
|
||||
if ( !$nodetype )
|
||||
{
|
||||
@@ -107,7 +107,7 @@ sub mkhwconn_parse_args
|
||||
next;
|
||||
} else
|
||||
{
|
||||
unless ( $nodetype =~ /^(fsp|bpa|frame|cec|hmc)$/)
|
||||
unless ( $nodetype =~ /^(blade|fsp|bpa|frame|cec|hmc)$/)
|
||||
{
|
||||
return ( usage("Node type is incorrect. \n"));
|
||||
}
|
||||
@@ -486,9 +486,13 @@ sub mkhwconn
|
||||
# Get IP address
|
||||
############################
|
||||
my $cnode;
|
||||
my $ntype = xCAT::DBobjUtils::getnodetype($node_name);
|
||||
if ($ntype =~ /^(cec|frame)$/)
|
||||
#my $ntype = xCAT::DBobjUtils::getnodetype($node_name);
|
||||
my $ntype = $$d[4];
|
||||
if ($ntype =~ /^(cec|frame|blade)$/)
|
||||
{
|
||||
if ($ntype eq "blade") {
|
||||
delete $opt->{port};
|
||||
}
|
||||
$cnode = xCAT::DBobjUtils::getchildren($node_name, $opt->{port});
|
||||
} else {
|
||||
$cnode = $node_name;
|
||||
@@ -518,12 +522,17 @@ sub mkhwconn
|
||||
next;
|
||||
}
|
||||
|
||||
my ( undef,undef,$mtms,undef,$type) = @$d;
|
||||
my ( undef,undef,$mtms,undef,$type,$bpa) = @$d;
|
||||
my ($user, $passwd);
|
||||
if ( exists $opt->{P})
|
||||
{
|
||||
($user, $passwd) = ('HMC', $opt->{P});
|
||||
}
|
||||
elsif ($type eq "blade") {
|
||||
$user = "USERID";
|
||||
($user, $passwd) = xCAT::PPCdb::credentials( $bpa, $type, $user);
|
||||
$type = "cec";
|
||||
}
|
||||
else
|
||||
{
|
||||
($user, $passwd) = xCAT::PPCdb::credentials( $node_name, $type,'HMC');
|
||||
@@ -707,7 +716,7 @@ sub rmhwconn
|
||||
my $d = $node_hash->{$node_name};
|
||||
|
||||
my ( undef,undef,undef,undef,$type) = @$d;
|
||||
|
||||
if ($type eq "blade") {$type = "cec";}
|
||||
############################
|
||||
# Get IP address
|
||||
############################
|
||||
@@ -724,10 +733,19 @@ sub rmhwconn
|
||||
|
||||
my @ips;
|
||||
foreach my $entry ( @$nodes_found ) {
|
||||
if ( $entry =~ /$mtm\*$serial/) {
|
||||
$entry =~ /ipaddr=(\d+\.\d+\.\d+\.\d+),/;
|
||||
push @ips, $1;
|
||||
if ($entry =~ /type_model_serial_num=([^,]*),/) {
|
||||
my $match_mtm1 = $1;
|
||||
my $match_mtm2 = $match_mtm1;
|
||||
$match_mtm2 =~ s/\-//;
|
||||
if ($match_mtm1 =~ /$mtm\*$serial/ || $match_mtm2 =~ /$mtm\*$serial/) {
|
||||
$entry =~ /ipaddr=(\d+\.\d+\.\d+\.\d+),/;
|
||||
push @ips, $1;
|
||||
}
|
||||
}
|
||||
#if ( $entry =~ /$mtm\*$serial/) {
|
||||
# $entry =~ /ipaddr=(\d+\.\d+\.\d+\.\d+),/;
|
||||
# push @ips, $1;
|
||||
#}
|
||||
}
|
||||
if (!@ips)
|
||||
{
|
||||
|
||||
+112
-5
@@ -7,6 +7,7 @@ use xCAT::GlobalDef;
|
||||
use xCAT::Utils;
|
||||
use xCAT::TableUtils;
|
||||
use xCAT::NetworkUtils;
|
||||
require xCAT::data::ibmhwtypes;
|
||||
|
||||
###########################################
|
||||
# Factory defaults
|
||||
@@ -100,7 +101,6 @@ sub add_ppc {
|
||||
$parent,
|
||||
$ips,
|
||||
$mac ) = split /,/;
|
||||
|
||||
###############################
|
||||
# Update nodetype table
|
||||
###############################
|
||||
@@ -168,6 +168,10 @@ sub add_ppc {
|
||||
# Update nodelist table
|
||||
###########################
|
||||
updategroups( $name, $db{nodelist}, $type );
|
||||
my $tmp_group = xCAT::data::ibmhwtypes::parse_group($model);
|
||||
if (defined($tmp_group)) {
|
||||
updategroups($name, $db{nodelist}, $tmp_group);
|
||||
}
|
||||
if ( $type =~ /^(fsp|bpa)$/ ) {
|
||||
$db{nodelist}->setNodeAttribs( $name, {hidden => '1'});
|
||||
} else {
|
||||
@@ -236,6 +240,97 @@ sub add_ppc {
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
##########################################################################
|
||||
# Update lpar information in the xCAT databases
|
||||
##########################################################################
|
||||
sub update_lpar {
|
||||
my $hwtype = shift;
|
||||
my $values = shift;
|
||||
my $write = shift;
|
||||
my @tabs = qw(ppc vpd nodehm nodelist nodetype ppcdirect hosts mac);
|
||||
my %db = ();
|
||||
my @update_list = ();
|
||||
my @write_list = ();
|
||||
###################################
|
||||
# Open database needed
|
||||
###################################
|
||||
foreach ( @tabs ) {
|
||||
$db{$_} = xCAT::Table->new( $_, -create=>1, -autocommit=>0 );
|
||||
if ( !$db{$_} ) {
|
||||
return( "Error opening '$_'" );
|
||||
}
|
||||
}
|
||||
my @vpdlist = $db{vpd}->getAllNodeAttribs(['node','serial','mtm','side']);
|
||||
my @ppclist = $db{ppc}->getAllNodeAttribs(['node','hcp','id',
|
||||
'pprofile','parent','nodetype',
|
||||
'comments', 'disable']);
|
||||
# 'cec,cec1,,8246-L1D,100A9DA,,cec1,,cec1',
|
||||
# 'lpar,10-0A9DA,1,8246-L1D,100A9DA,,cec1,,cec1'
|
||||
my %ppchash = ();
|
||||
my %vpdhash = ();
|
||||
foreach my $ppcent (@ppclist) {
|
||||
if ($ppcent->{id} and $ppcent->{nodetype} and $ppcent->{nodetype} eq "lpar") {
|
||||
my $key = $ppcent->{node};
|
||||
$ppchash{$key}{id} = $ppcent->{id};
|
||||
$ppchash{$key}{parent} = $ppcent->{parent};
|
||||
}
|
||||
}
|
||||
foreach my $vpdent (@vpdlist)
|
||||
{
|
||||
my $key = $vpdent->{node};
|
||||
$vpdhash{$key}{mtm} = $vpdent->{mtm};
|
||||
$vpdhash{$key}{serial} = $vpdent->{serial};
|
||||
}
|
||||
my @ppc_lpars = keys %ppchash;
|
||||
foreach my $value ( @$values ) {
|
||||
my ($ttype,
|
||||
$tname,
|
||||
$tid,
|
||||
$tmtm,
|
||||
$tsn,
|
||||
$tside,
|
||||
$server,
|
||||
$pprofile,
|
||||
$parent) = split /,/, $value;
|
||||
if ($ttype ne "lpar") {
|
||||
push @update_list, $value;
|
||||
next;
|
||||
}
|
||||
my $find_node = undef;
|
||||
foreach my $tmp_node (@ppc_lpars) {
|
||||
if ($ppchash{$tmp_node}{id} eq $tid) {
|
||||
if (exists($ppchash{$tmp_node}{parent}) and $ppchash{$tmp_node}{parent} eq $parent) {
|
||||
$find_node = $tmp_node;
|
||||
last;
|
||||
} elsif ($vpdhash{$tmp_node}{mtm} eq $tmtm and $vpdhash{$tmp_node}{serial} eq $tsn) {
|
||||
$find_node = $tmp_node;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (defined($find_node)) {
|
||||
if ( update_node_attribs($hwtype, $ttype, $find_node, $tid, $tmtm, $tsn, $tside,
|
||||
$server, $pprofile, $parent, "", \%db, $tname, \@ppclist))
|
||||
{
|
||||
$value =~ s/^$ttype,$tname,/$ttype,$find_node,/;
|
||||
push @update_list, $value;
|
||||
}
|
||||
} elsif (defined($write)) {
|
||||
push @write_list, $value;
|
||||
}
|
||||
}
|
||||
if (defined($write)) {
|
||||
&add_ppc($hwtype, \@write_list);
|
||||
return ([@update_list,@write_list]);
|
||||
} else {
|
||||
foreach ( @tabs ) {
|
||||
if ( exists( $db{$_}{commit} )) {
|
||||
$db{$_}->commit;
|
||||
}
|
||||
}
|
||||
return \@update_list;
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Update nodes in the xCAT databases
|
||||
@@ -278,7 +373,6 @@ sub update_ppc {
|
||||
$pprofile,
|
||||
$parent,
|
||||
$ips ) = split /,/, $value;
|
||||
|
||||
if ( $ttype eq 'cec' )
|
||||
{
|
||||
my $hostname = get_host($tname, "FSP", $tmtm, $tsn, "", "", $tid, "","");
|
||||
@@ -329,9 +423,7 @@ sub update_ppc {
|
||||
$pprofile,
|
||||
$parent,
|
||||
$ips ) = split /,/, $value;
|
||||
|
||||
next if ( $type ne 'cec' );
|
||||
|
||||
my $predefined_node = undef;
|
||||
foreach my $vpdent (@vpdlist)
|
||||
{
|
||||
@@ -525,6 +617,10 @@ sub update_node_attribs
|
||||
if ( $namediff)
|
||||
{
|
||||
updategroups( $name, $db->{nodelist}, $type );
|
||||
my $tmp_group = xCAT::data::ibmhwtypes::parse_group($model);
|
||||
if (defined($tmp_group)) {
|
||||
updategroups($name, $db->{nodelist}, $tmp_group);
|
||||
}
|
||||
$db->{nodelist}->setNodeAttribs( $name, {status=>$nodelisthash->{status},
|
||||
appstatus=>$nodelisthash->{appstatus},
|
||||
primarysn=>$nodelisthash->{primarysn},
|
||||
@@ -888,6 +984,18 @@ sub get_usr_passwd {
|
||||
} else {
|
||||
($ent) = $passwdtab->getNodeAttribs($key, qw(username password));
|
||||
}
|
||||
if (!$ent) {
|
||||
if ($key eq "cec") {
|
||||
$key = "fsp";
|
||||
} elsif ($key eq "frame") {
|
||||
$key = "bpa";
|
||||
}
|
||||
if ($user) {
|
||||
($ent) = $passwdtab->getAttribs({key => $key, username => $user}, qw(password cryptmethod));
|
||||
} else {
|
||||
($ent) = $passwdtab->getNodeAttribs($key, qw(username password));
|
||||
}
|
||||
}
|
||||
if (!$ent or !$ent->{password}) {
|
||||
my $hash = $default_passwd_accounts{$key};
|
||||
if (!$hash or ($user and !defined($hash->{$user}))) {
|
||||
@@ -958,7 +1066,6 @@ sub get_host {
|
||||
# get the information of existed nodes to do the migration
|
||||
|
||||
read_from_table() unless (%::OLD_DATA_CACHE);
|
||||
|
||||
foreach my $oldnode ( keys %::OLD_DATA_CACHE )
|
||||
{
|
||||
my $tmpmtm = @{$::OLD_DATA_CACHE{$oldnode}}[0];
|
||||
|
||||
@@ -5,6 +5,8 @@ use strict;
|
||||
use Getopt::Long;
|
||||
use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR);
|
||||
use xCAT::Usage;
|
||||
use xCAT::TableUtils;
|
||||
require xCAT::data::ibmhwtypes;
|
||||
|
||||
|
||||
##########################################
|
||||
@@ -59,7 +61,7 @@ sub parse_args {
|
||||
$Getopt::Long::ignorecase = 0;
|
||||
Getopt::Long::Configure( "bundling" );
|
||||
|
||||
if ( !GetOptions( \%opt, qw(V|verbose) )) {
|
||||
if ( !GetOptions( \%opt, qw(V|verbose t) )) {
|
||||
return( usage() );
|
||||
}
|
||||
####################################
|
||||
@@ -75,6 +77,9 @@ sub parse_args {
|
||||
if ( !defined( $cmd )) {
|
||||
return(usage( "Invalid command: $ARGV[0]" ));
|
||||
}
|
||||
if (exists($opt{t}) and $cmd ne "model") {
|
||||
return(["Option 't' can only work with 'model'."]);
|
||||
}
|
||||
####################################
|
||||
# Check for an extra argument
|
||||
####################################
|
||||
@@ -411,6 +416,12 @@ sub vpd {
|
||||
#############################
|
||||
# Output value
|
||||
#############################
|
||||
if ($_ eq 'model' and exists($request->{opt}->{t})) {
|
||||
my $tmp_pre = xCAT::data::ibmhwtypes::parse_args($data->{$_});
|
||||
if (defined($tmp_pre)) {
|
||||
xCAT::TableUtils->updatenodegroups($name, $tmp_pre);
|
||||
}
|
||||
}
|
||||
my $value = "@{$prefix{$_}}[0]: $data->{$_}";
|
||||
push @result, [$name,$value,$Rc];
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use xCAT::PPCdb;
|
||||
use xCAT::GlobalDef;
|
||||
use xCAT::Usage;
|
||||
use xCAT::NetworkUtils;
|
||||
|
||||
require xCAT::data::ibmhwtypes;
|
||||
|
||||
##############################################
|
||||
# Globals
|
||||
@@ -545,6 +545,7 @@ sub format_stanza {
|
||||
#################################
|
||||
# Add each attribute
|
||||
#################################
|
||||
my $mtm = undef;
|
||||
foreach ( @attribs ) {
|
||||
my $d = $data[$i++];
|
||||
|
||||
@@ -555,7 +556,8 @@ sub format_stanza {
|
||||
} elsif ( /^hwtype$/ ) {
|
||||
$d = $globalhwtype{$type};
|
||||
} elsif ( /^groups$/ ) {
|
||||
$d = "$type,all";
|
||||
next;
|
||||
#$d = "$type,all";
|
||||
} elsif ( /^mgt$/ ) {
|
||||
$d = $hwtype;
|
||||
} elsif ( /^cons$/ ) {
|
||||
@@ -568,7 +570,9 @@ sub format_stanza {
|
||||
} elsif ( /^(mtm|serial)$/ ) {
|
||||
if ( $type eq "lpar" ) {
|
||||
$d = undef;
|
||||
}
|
||||
} elsif (/^mtm$/) {
|
||||
$mtm = $d;
|
||||
}
|
||||
} elsif (/^side$/) {
|
||||
unless ( $type =~ /^fsp|bpa$/ ) {
|
||||
next;
|
||||
@@ -576,6 +580,14 @@ sub format_stanza {
|
||||
}
|
||||
$result .= "\t$_=$d\n";
|
||||
}
|
||||
my $tmp_groups = "$type,all";
|
||||
if (defined($mtm)) {
|
||||
my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($mtm);
|
||||
if (defined($tmp_pre)) {
|
||||
$tmp_groups .= ",$tmp_pre";
|
||||
}
|
||||
}
|
||||
$result .= "\tgroups=$tmp_groups\n";
|
||||
}
|
||||
return( $result );
|
||||
}
|
||||
@@ -623,6 +635,7 @@ sub format_xml {
|
||||
#################################
|
||||
# Add each attribute
|
||||
#################################
|
||||
my $mtm = undef;
|
||||
foreach ( @attribs ) {
|
||||
my $d = $data[$i++];
|
||||
|
||||
@@ -631,7 +644,8 @@ sub format_xml {
|
||||
} elsif ( /^hwtype$/ ) {
|
||||
$d = $globalhwtype{$type};
|
||||
} elsif ( /^groups$/ ) {
|
||||
$d = "$type,all";
|
||||
next;
|
||||
#$d = "$type,all";
|
||||
} elsif ( /^mgt$/ ) {
|
||||
$d = $hwtype;
|
||||
} elsif ( /^cons$/ ) {
|
||||
@@ -643,6 +657,8 @@ sub format_xml {
|
||||
} elsif ( /^(mtm|serial)$/ ) {
|
||||
if ( $type eq "lpar" ) {
|
||||
$d = undef;
|
||||
} elsif (/^mtm$/){
|
||||
$mtm = $d;
|
||||
}
|
||||
} elsif (/^side$/) {
|
||||
unless ( $type =~ /^fsp|bpa$/ ) {
|
||||
@@ -651,6 +667,14 @@ sub format_xml {
|
||||
}
|
||||
$href->{Node}->{$_} = $d;
|
||||
}
|
||||
my $tmp_groups = "$type,all";
|
||||
if (defined($mtm)) {
|
||||
my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($mtm);
|
||||
if (defined($tmp_pre)) {
|
||||
$tmp_groups .= ",$tmp_pre";
|
||||
}
|
||||
}
|
||||
$href->{Node}->{groups}=$tmp_groups;
|
||||
#################################
|
||||
# XML encoding
|
||||
#################################
|
||||
|
||||
@@ -52,14 +52,21 @@ sub get_allocable_staticips_innet
|
||||
my $netentry = ($networkstab->getAllAttribsWhere("netname = '$netname'", 'ALL'))[0];
|
||||
my ($startip, $endip) = split('-', $netentry->{'staticrange'});
|
||||
my $incremental = $netentry->{'staticrangeincrement'};
|
||||
my $netmask = $netentry->{'mask'};
|
||||
my $gateway = $netentry->{'gateway'};
|
||||
my $validipsref;
|
||||
if ($incremental and $startip and $endip){
|
||||
$validipsref = xCAT::NetworkUtils->get_allips_in_range($startip, $endip, $incremental);
|
||||
}
|
||||
|
||||
my $broadcastip = xCAT::NetworkUtils->getBroadcast($startip, $netmask);
|
||||
foreach (@$validipsref){
|
||||
if (! exists($iphash{$_})){
|
||||
push @allocableips, $_;
|
||||
#Remove ip which is broadcast ip, exclude ip, ips ended with 0, gateway ip
|
||||
if (exists($iphash{$_}) or $_ eq $broadcastip or $_ eq $gateway
|
||||
or $_ =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(0)$/){
|
||||
next;
|
||||
}
|
||||
push @allocableips, $_;
|
||||
}
|
||||
return \@allocableips;
|
||||
}
|
||||
@@ -258,6 +265,7 @@ sub rackformat_to_numricformat{
|
||||
values are attributes of a specific nic, like:
|
||||
type : nic type
|
||||
hostnamesuffix: hostname suffix
|
||||
hostnameprefix: hostname prefix
|
||||
customscript: custom script for this nic
|
||||
network: network name for this nic
|
||||
ip: ip address of this nic.
|
||||
@@ -269,7 +277,7 @@ sub get_nodes_nic_attrs{
|
||||
my $nodes = shift;
|
||||
|
||||
my $nicstab = xCAT::Table->new( 'nics');
|
||||
my $entry = $nicstab->getNodesAttribs($nodes, ['nictypes', 'nichostnamesuffixes', 'niccustomscripts', 'nicnetworks', 'nicips']);
|
||||
my $entry = $nicstab->getNodesAttribs($nodes, ['nictypes', 'nichostnamesuffixes', 'nichostnameprefixes', 'niccustomscripts', 'nicnetworks', 'nicips']);
|
||||
|
||||
my %nicsattrs;
|
||||
my @nicattrslist;
|
||||
@@ -301,6 +309,20 @@ sub get_nodes_nic_attrs{
|
||||
}
|
||||
}
|
||||
|
||||
if($entry->{$node}->[0]->{'nichostnameprefixes'}){
|
||||
|
||||
@nicattrslist = split(",", $entry->{$node}->[0]->{'nichostnameprefixes'});
|
||||
foreach (@nicattrslist){
|
||||
my @nicattrs;
|
||||
if ($_ =~ /!/) {
|
||||
@nicattrs = split("!", $_);
|
||||
} else {
|
||||
@nicattrs = split(":", $_);
|
||||
}
|
||||
$nicsattrs{$node}{$nicattrs[0]}{'hostnameprefix'} = $nicattrs[1];
|
||||
}
|
||||
}
|
||||
|
||||
if($entry->{$node}->[0]->{'niccustomscripts'}){
|
||||
@nicattrslist = split(",", $entry->{$node}->[0]->{'niccustomscripts'});
|
||||
foreach (@nicattrslist){
|
||||
@@ -542,7 +564,7 @@ sub get_allnode_singleattrib_hash
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
=head3 get_db_swtiches
|
||||
Description : Get all records of switch config from a table, then return a string list.
|
||||
Arguments : $tabname - the table name.
|
||||
@@ -593,6 +615,46 @@ sub get_db_switchports
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 get_all_cecs
|
||||
Description : Get all CEC objects name in system.
|
||||
Arguments : hashref: if not set, return a array ref.
|
||||
if set, return a hash ref.
|
||||
Returns : ref for CECs list.
|
||||
Example :
|
||||
my $arrayref = xCAT::ProfiledNodeUtils->get_all_cecs();
|
||||
my $hashref = xCAT::ProfiledNodeUtils->get_all_cecs(1);
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub get_all_cecs
|
||||
{
|
||||
my $hashref = shift;
|
||||
my %cecshash;
|
||||
my @cecslist;
|
||||
|
||||
my $ppctab = xCAT::Table->new('ppc');
|
||||
my @cecs = $ppctab->getAllAttribsWhere("nodetype = 'cec'", 'node');
|
||||
foreach (@cecs) {
|
||||
if($_->{'node'}) {
|
||||
if ($hashref) {
|
||||
$cecshash{$_->{'node'}} = 1;
|
||||
} else {
|
||||
push @cecslist, $_->{'node'};
|
||||
}
|
||||
}
|
||||
}
|
||||
$ppctab->close();
|
||||
|
||||
# Return the ref accordingly
|
||||
if ($hashref) {
|
||||
return \%cecshash;
|
||||
} else {
|
||||
return \@cecslist;
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 is_discover_started
|
||||
Description : Judge whether profiled nodes discovering is running or not.
|
||||
Arguments : NA
|
||||
@@ -657,6 +719,28 @@ sub get_nodes_profiles
|
||||
return \%profile_dict;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 get_imageprofile_prov_osvers
|
||||
Description : Get A node's provisioning os version and profile from its imageprofile attribute.
|
||||
Arguments : $imgprofilename - imageprofile name
|
||||
Returns : node's osversion and profile
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub get_imageprofile_prov_osvers
|
||||
{
|
||||
|
||||
my $class = shift;
|
||||
my $imgprofilename = shift;
|
||||
my $osimgtab = xCAT::Table->new('osimage');
|
||||
my $osimgentry = ($osimgtab->getAllAttribsWhere("imagename = '$imgprofilename'", 'ALL' ))[0];
|
||||
my $osversion = $osimgentry->{'osvers'};
|
||||
my $profile = $osimgentry->{'profile'};
|
||||
return ($osversion, $profile);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 get_imageprofile_prov_method
|
||||
@@ -751,7 +835,14 @@ sub check_profile_consistent{
|
||||
my $mgt = undef;
|
||||
$mgt = $mgtentry->{'mgt'} if ($mgtentry->{'mgt'});
|
||||
$nodehmtab->close();
|
||||
|
||||
|
||||
#Get hardwareprofile nodetype
|
||||
my $ppctab = xCAT::Table->new('ppc');
|
||||
my $ntentry = $ppctab->getNodeAttribs($hardwareprofile, ['nodetype']);
|
||||
my $nodetype = undef;
|
||||
$nodetype = $ntentry->{'nodetype'} if ($ntentry->{'nodetype'});
|
||||
$ppctab->close();
|
||||
|
||||
# Check if exists provision network
|
||||
if (not ($installnic and exists $netprofile_nicshash{$installnic}{"network"})){
|
||||
return 0, "Provisioning network not defined for network profile."
|
||||
@@ -770,17 +861,24 @@ sub check_profile_consistent{
|
||||
return 0, "$nictype networkprofile must use with hardwareprofile.";
|
||||
}
|
||||
}
|
||||
|
||||
if (not $nictype and $mgt) {
|
||||
# define hardwareprofile, not define fsp or bmc networkprofile
|
||||
|
||||
# For nodetype is lpar node, not need to check the nictype as it is not required for lpar node
|
||||
if (not $nictype and $mgt and $nodetype ne 'lpar' ) {
|
||||
# define hardwareprofile, not define fsp or bmc networkprofile, and the node type is not lpar
|
||||
return 0, "$profile_dict{$mgt} hardwareprofile must use with $profile_dict{$mgt} networkprofile.";
|
||||
}
|
||||
|
||||
if ($profile_dict{$mgt} ne $nictype) {
|
||||
# Networkprofile's nictype is not consistent with hadrwareprofile's mgt
|
||||
if ($profile_dict{$mgt} ne $nictype and $nodetype ne 'lpar') {
|
||||
# Networkprofile's nictype is not consistent with hadrwareprofile's mgt, and the node type is not lpar
|
||||
return 0, "Networkprofile's nictype is not consistent with hardwareprofile's mgt.";
|
||||
}
|
||||
|
||||
|
||||
if ($nodetype eq 'lpar' and $nictype eq 'FSP')
|
||||
{
|
||||
# can not associate FSP network if the node type is lpar
|
||||
return 0, "The node with hardware type $nodetype can not use with $nictype networkprofile.";
|
||||
}
|
||||
|
||||
return 1, "";
|
||||
}
|
||||
|
||||
@@ -939,6 +1037,40 @@ sub parse_nodeinfo_file
|
||||
return 1, "";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 update the table prodkey, in order to support windows
|
||||
per node license key
|
||||
|
||||
Returns: $retcode.
|
||||
$retcode = 1. update failed, the value is undef
|
||||
$retcode = 0. save into db is OK..
|
||||
=cut
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub update_windows_prodkey
|
||||
{
|
||||
my $class = shift;
|
||||
my $node = shift;
|
||||
my $product = shift;
|
||||
my $key = shift;
|
||||
unless(defined($node) && defined($product) && defined($key))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
# please notice this db usage
|
||||
my %keyhash;
|
||||
my %updates;
|
||||
$keyhash{'node'} = $node;
|
||||
$updates{'product'} = $product;
|
||||
$updates{'key'} = $key;
|
||||
my $tab = xCAT::Table->new('prodkey', -create=>1, -autocommit=>0);
|
||||
$tab->setAttribs( \%keyhash,\%updates );
|
||||
$tab->commit;
|
||||
$tab->close;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
=head3 check_nicips
|
||||
Description: Check if the nicips defined in MAC file is correct
|
||||
|
||||
+13
-1
@@ -98,13 +98,21 @@ sub remote_copy_command
|
||||
{
|
||||
if (-e ("/usr/bin/rsync")) {
|
||||
if (($usersh == 0) || ($localhost == 1)) { # using ssh, or local
|
||||
if ($$config{'sudo'}){
|
||||
$sync_opt = '--rsync-path=sudo /usr/bin/rsync ';
|
||||
} else {
|
||||
$sync_opt = '--rsync-path /usr/bin/rsync ';
|
||||
}
|
||||
} else {
|
||||
$sync_opt = '--rsh /bin/rsh --rsync-path /usr/bin/rsync ';
|
||||
}
|
||||
} else {
|
||||
if (($usersh == 0) || ($localhost == 1)) { # using ssh, or local
|
||||
$sync_opt = '--rsync-path /usr/local/bin/rsync ';
|
||||
if ($$config{'sudo'}){
|
||||
$sync_opt = '--rsync-path=sudo /usr/local/bin/rsync ';
|
||||
} else {
|
||||
$sync_opt = '--rsync-path=/usr/local/bin/rsync ';
|
||||
}
|
||||
} else {
|
||||
$sync_opt = '--rsh /bin/rsh --rsync-path /usr/local/bin/rsync ';
|
||||
}
|
||||
@@ -112,7 +120,11 @@ sub remote_copy_command
|
||||
}
|
||||
else #linux
|
||||
{
|
||||
if ($$config{'sudo'}) {
|
||||
$sync_opt = '--rsync-path=\'sudo /usr/bin/rsync\' ';
|
||||
} else {
|
||||
$sync_opt = '--rsync-path /usr/bin/rsync ';
|
||||
}
|
||||
}
|
||||
# if only syncing the service node or
|
||||
# (no postscripts and no append lines) then do not
|
||||
|
||||
@@ -35,21 +35,22 @@ package xCAT::RemoteShellExp;
|
||||
node.
|
||||
DSH_TO_USERID - The userid on the node where the ssh keys will be updated.
|
||||
DSH_ENABLE_SSH - Node to node root passwordless ssh will be setup.
|
||||
|
||||
DSH_ZONE_SSHKEYS - directory containing the zones root .ssh keys
|
||||
|
||||
Usage: remoteshellexp
|
||||
[-t node list] test ssh connection to the node
|
||||
[-k] Generates the ssh keys needed , for the user on the MN.
|
||||
[-s node list] copies the ssh keys to the nodes
|
||||
|
||||
optional $timeout = timeout value for the expect. Usually from the xdsh -t flag
|
||||
default timeout is 10 seconds
|
||||
exit 0 - good
|
||||
exit 1 - abort
|
||||
exit 2 - usage error
|
||||
|
||||
Examples:
|
||||
$rc=xCAT::RemoteShellExp->remoteshellexp("k",$callback,$remoteshellcmd);
|
||||
$rc=xCAT::RemoteShellExp->remoteshellexp("s",$callback,$remoteshellcmd,$nodes);
|
||||
$rc=xCAT::RemoteShellExp->remoteshellexp("t",$callback,$remoteshellcmd,$nodes);
|
||||
$rc=xCAT::RemoteShellExp->remoteshellexp("k",$callback,$remoteshellcmd,$nodes,$timeout);
|
||||
$rc=xCAT::RemoteShellExp->remoteshellexp("s",$callback,$remoteshellcmd,$nodes,$timeout);
|
||||
$rc=xCAT::RemoteShellExp->remoteshellexp("t",$callback,$remoteshellcmd,$nodes,$timeout);
|
||||
|
||||
=cut
|
||||
|
||||
@@ -70,7 +71,7 @@ use strict;
|
||||
#-----------------------------------------------------------------------------
|
||||
sub remoteshellexp
|
||||
{
|
||||
my ($class, $flag, $callback, $remoteshell, $nodes) = @_;
|
||||
my ($class, $flag, $callback, $remoteshell, $nodes, $timeout) = @_;
|
||||
my $rc=0;
|
||||
$::CALLBACK = $callback;
|
||||
if (!($flag))
|
||||
@@ -90,6 +91,10 @@ sub remoteshellexp
|
||||
return 2;
|
||||
|
||||
}
|
||||
my $expecttimeout=10; # default
|
||||
if (defined($timeout)) { # value supplied
|
||||
$expecttimeout=$timeout;
|
||||
}
|
||||
|
||||
# for -s flag must have nodes and a $to_userid password
|
||||
my $to_user_password;
|
||||
@@ -139,7 +144,7 @@ sub remoteshellexp
|
||||
} else {
|
||||
$from_userid="root";
|
||||
}
|
||||
# set User on the node where we will send the keys
|
||||
# set User on the node where we will send the keys
|
||||
# this id can be a local id as well as root
|
||||
if ($ENV{'DSH_TO_USERID'}) {
|
||||
$to_userid=$ENV{'DSH_TO_USERID'};
|
||||
@@ -149,18 +154,19 @@ sub remoteshellexp
|
||||
# set User home directory to find the ssh public key to send
|
||||
# For non-root ids information may not be in /etc/passwd
|
||||
# but elsewhere like LDAP
|
||||
|
||||
if ($ENV{'DSH_FROM_USERID_HOME'}) {
|
||||
$home=$ENV{'DSH_FROM_USERID_HOME'};
|
||||
$home=$ENV{'DSH_FROM_USERID_HOME'};
|
||||
} else {
|
||||
$home=xCAT::Utils->getHomeDir($from_userid);
|
||||
$home=xCAT::Utils->getHomeDir($from_userid);
|
||||
}
|
||||
|
||||
# This indicates we will generate new ssh keys for the user,
|
||||
# if they are not already there
|
||||
my $key="$home/.ssh/id_rsa";
|
||||
my $key2="$home/.ssh/id_rsa.pub";
|
||||
# Check to see if empty
|
||||
if (-z $key) {
|
||||
# unless using zones
|
||||
my $key="$home/.ssh/id_rsa";
|
||||
my $key2="$home/.ssh/id_rsa.pub";
|
||||
# Check to see if empty
|
||||
if (-z $key) {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"The $key file is empty. Remove it and rerun the command.";
|
||||
@@ -178,9 +184,8 @@ sub remoteshellexp
|
||||
}
|
||||
if (($flag eq "k") && (!(-e $key)))
|
||||
{
|
||||
# if the file size of the id_rsa key is 0, tell them to remove it
|
||||
# and run the command again
|
||||
$rc=xCAT::RemoteShellExp->gensshkeys;
|
||||
# updating keys and the key file does not exist
|
||||
$rc=xCAT::RemoteShellExp->gensshkeys($expecttimeout);
|
||||
}
|
||||
# send ssh keys to the nodes/devices, to setup passwordless ssh
|
||||
if ($flag eq "s")
|
||||
@@ -193,15 +198,18 @@ sub remoteshellexp
|
||||
return 1;
|
||||
}
|
||||
if ($ssh_setup_cmd) { # setup ssh on devices
|
||||
$rc=xCAT::RemoteShellExp->senddeviceskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$ssh_setup_cmd,$nodes);
|
||||
$rc=xCAT::RemoteShellExp->senddeviceskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$ssh_setup_cmd,$nodes, $expecttimeout);
|
||||
} else { #setup ssh on nodes
|
||||
$rc=xCAT::RemoteShellExp->sendnodeskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$nodes);
|
||||
if ($ENV{'DSH_ZONE_SSHKEYS'}) { # if using zones the override the location of the keys
|
||||
$home= $ENV{'DSH_ZONE_SSHKEYS'};
|
||||
}
|
||||
$rc=xCAT::RemoteShellExp->sendnodeskeys($remoteshell,$remotecopy,$to_userid,$to_user_password,$home,$nodes, $expecttimeout);
|
||||
}
|
||||
}
|
||||
# test ssh setup on the node
|
||||
if ($flag eq "t")
|
||||
{
|
||||
$rc=xCAT::RemoteShellExp->testkeys($remoteshell,$to_userid,$nodes);
|
||||
$rc=xCAT::RemoteShellExp->testkeys($remoteshell,$to_userid,$nodes,$expecttimeout);
|
||||
}
|
||||
return $rc;
|
||||
}
|
||||
@@ -220,9 +228,9 @@ sub remoteshellexp
|
||||
sub gensshkeys
|
||||
|
||||
{
|
||||
my ($class) = @_;
|
||||
my ($class, $expecttimeout) = @_;
|
||||
my $keygen;
|
||||
my $timeout = 10; # sets Expect default timeout, 0 accepts immediately
|
||||
my $timeout = $expecttimeout; # sets Expect default timeout, 0 accepts immediately
|
||||
my $keygen_sent = 0;
|
||||
my $prompt1 = 'Generating public/private rsa';
|
||||
my $prompt2 = 'Enter file.*:';
|
||||
@@ -347,9 +355,9 @@ sub gensshkeys
|
||||
sub testkeys
|
||||
|
||||
{
|
||||
my ($class,$remoteshell,$to_userid,$nodes) = @_;
|
||||
my ($class,$remoteshell,$to_userid,$nodes, $expecttimeout) = @_;
|
||||
my $testkeys;
|
||||
my $timeout = 10; # sets Expect default timeout, 0 accepts immediately
|
||||
my $timeout = $expecttimeout; # sets Expect default timeout
|
||||
my $testkeys_sent = 0;
|
||||
my $prompt1 = 'Are you sure you want to continue connecting (yes/no)?';
|
||||
my $prompt2 = 'ssword:';
|
||||
@@ -469,9 +477,9 @@ sub testkeys
|
||||
sub sendnodeskeys
|
||||
|
||||
{
|
||||
my ($class,$remoteshell,$remotecopy,$to_userid,$to_userpassword,$home,$nodes) = @_;
|
||||
my ($class,$remoteshell,$remotecopy,$to_userid,$to_userpassword,$home,$nodes, $expecttimeout) = @_;
|
||||
my $sendkeys;
|
||||
my $timeout = 10; # sets Expect default timeout, 0 accepts immediately
|
||||
my $timeout = $expecttimeout; # sets Expect default timeout, 0 accepts immediately
|
||||
my $sendkeys_sent = 0;
|
||||
my $prompt1 = 'Are you sure you want to continue connecting (yes/no)?';
|
||||
my $prompt2 = 'ssword:';
|
||||
@@ -490,11 +498,15 @@ sub sendnodeskeys
|
||||
# in $HOME/.ssh/tmp/authorized_keys
|
||||
# copy to the node to the temp directory
|
||||
# scp $HOME/.ssh/tmp/authorized_keys to_userid@<node>:/tmp/$to_userid/.ssh
|
||||
# scp $HOME/.ssh/id_rsa.pub to_userid@<node>:/tmp/$to_userid/.ssh
|
||||
# Note if using zones, the keys do not come from ~/.ssh but from the
|
||||
# zone table, sshkeydir attribute. For zones the userid is always root
|
||||
# If you are going to enable ssh to ssh between nodes, then
|
||||
# scp $HOME/.ssh/id_rsa to that temp directory on the node
|
||||
# copy the script $HOME/.ssh/copy.sh to the node, it will do the
|
||||
# the work of setting up the user's ssh keys and clean up
|
||||
# ssh (run) copy.sh on the node
|
||||
|
||||
my @nodelist=split(/,/,$nodes);
|
||||
foreach my $node (@nodelist) {
|
||||
$sendkeys = new Expect;
|
||||
@@ -602,11 +614,11 @@ sub sendnodeskeys
|
||||
my $spawncopyfiles;
|
||||
if ($ENV{'DSH_ENABLE_SSH'}) { # we will enable node to node ssh
|
||||
$spawncopyfiles=
|
||||
"$remotecopy $home/.ssh/id_rsa $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh ";
|
||||
"$remotecopy $home/.ssh/id_rsa $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh ";
|
||||
|
||||
} else { # no node to node ssh ( don't send private key)
|
||||
$spawncopyfiles=
|
||||
"$remotecopy $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh ";
|
||||
"$remotecopy $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh ";
|
||||
}
|
||||
# send copy command
|
||||
unless ($sendkeys->spawn($spawncopyfiles))
|
||||
@@ -759,7 +771,7 @@ sub sendnodeskeys
|
||||
|
||||
=head3 senddeviceskeys
|
||||
|
||||
Setup the ssh keys on the nodes
|
||||
Setup the ssh keys on the switches
|
||||
|
||||
=cut
|
||||
|
||||
@@ -768,9 +780,9 @@ sub sendnodeskeys
|
||||
sub senddeviceskeys
|
||||
|
||||
{
|
||||
my ($class,$remoteshell,$remotecopy,$to_userid,$to_userpassword,$home,$ssh_setup_cmd,$nodes) = @_;
|
||||
my ($class,$remoteshell,$remotecopy,$to_userid,$to_userpassword,$home,$ssh_setup_cmd,$nodes, $expecttimeout) = @_;
|
||||
my $sendkeys;
|
||||
my $timeout = 10; # sets Expect default timeout, 0 accepts immediately
|
||||
my $timeout = $expecttimeout; # sets Expect default timeout, 0 accepts immediately
|
||||
my $sendkeys_sent = 0;
|
||||
my $prompt1 = 'Are you sure you want to continue connecting (yes/no)?';
|
||||
my $prompt2 = 'ssword:';
|
||||
|
||||
+32
-14
@@ -202,9 +202,11 @@ sub parse_and_run_sinv
|
||||
#
|
||||
my @nodelist = ();
|
||||
my @cmdparts = ();
|
||||
my $devicecommand =0;
|
||||
if ($options{'devicetype'}) {
|
||||
# must split different because devices have commands with spaces
|
||||
@cmdparts = split(' ', $cmd,3);
|
||||
$devicecommand =1;
|
||||
} else {
|
||||
@cmdparts = split(' ', $cmd);
|
||||
}
|
||||
@@ -503,7 +505,7 @@ sub parse_and_run_sinv
|
||||
);
|
||||
|
||||
# write the results to the tempfile after running through xdshcoll
|
||||
$rc = &storeresults($callback);
|
||||
$rc = &storeresults($callback,$devicecommand);
|
||||
|
||||
}
|
||||
$processflg = "node";
|
||||
@@ -534,7 +536,7 @@ sub parse_and_run_sinv
|
||||
|
||||
|
||||
# write the results to the tempfile after running through xdshcoll
|
||||
$rc = &storeresults($callback);
|
||||
$rc = &storeresults($callback,$devicecommand);
|
||||
|
||||
# Build report and write to output file
|
||||
# if file exist and has something in it
|
||||
@@ -1451,12 +1453,11 @@ sub rinvoutput
|
||||
sub storeresults
|
||||
{
|
||||
my $callback = shift;
|
||||
|
||||
my $devicecommand= shift;
|
||||
# open file to write results of xdsh or rinv command
|
||||
my $newtempfile = $tempfile;
|
||||
$newtempfile .= "temp";
|
||||
open(FILE, ">$newtempfile");
|
||||
if ($? > 0)
|
||||
unless (open(NEWTMPFILE, ">$newtempfile"))
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "Could not open $newtempfile\n";
|
||||
@@ -1465,9 +1466,9 @@ sub storeresults
|
||||
}
|
||||
foreach my $line (@cmdresult)
|
||||
{
|
||||
print FILE $line;
|
||||
print NEWTMPFILE $line;
|
||||
}
|
||||
close FILE;
|
||||
close NEWTMPFILE;
|
||||
my $outputfile;
|
||||
if ($processflg eq "seednode")
|
||||
{ # cmd to seednode
|
||||
@@ -1479,8 +1480,7 @@ sub storeresults
|
||||
}
|
||||
|
||||
# open file to put results of xdshcoll
|
||||
open(FILE, ">$outputfile");
|
||||
if ($? > 0)
|
||||
unless (open(NEWOUTFILE, ">$outputfile"))
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "Could not open $outputfile\n";
|
||||
@@ -1489,8 +1489,7 @@ sub storeresults
|
||||
}
|
||||
my $cmd = " $::XCATROOT/sbin/xdshcoll <$newtempfile |";
|
||||
|
||||
open(XCOLL, "$cmd");
|
||||
if ($? > 0)
|
||||
unless (open(XCOLL, "$cmd"))
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "Could not call xdshcoll \n";
|
||||
@@ -1503,18 +1502,37 @@ sub storeresults
|
||||
while (<XCOLL>)
|
||||
{
|
||||
$line = $_;
|
||||
print FILE $line
|
||||
print NEWOUTFILE $line
|
||||
|
||||
}
|
||||
|
||||
close(XCOLL);
|
||||
close FILE;
|
||||
close NEWOUTFILE;
|
||||
|
||||
system("/bin/rm $newtempfile");
|
||||
# is device command, we get false errors from the Switch, check for
|
||||
# blank error output lines and remove them. If there is nothing left
|
||||
# then there really were no errors
|
||||
my @newerrresult=();
|
||||
my $processerrors =1;
|
||||
if ($devicecommand==1) {
|
||||
foreach my $line (@errresult)
|
||||
{
|
||||
my @newline = (split(/:/, $line));
|
||||
if ($newline[1] !~ /^\s*$/) { # Not blank, then save it
|
||||
push @newerrresult,$line;
|
||||
}
|
||||
|
||||
}
|
||||
my $arraysize=@newerrresult;
|
||||
if ($arraysize < 1) {
|
||||
$processerrors =0;
|
||||
}
|
||||
}
|
||||
|
||||
# capture errors
|
||||
#
|
||||
if (@errresult)
|
||||
if ((@errresult) && ($processerrors ==1))
|
||||
{ # if errors
|
||||
my $rsp = {};
|
||||
my $i = 0;
|
||||
|
||||
Regular → Executable
+589
-428
File diff suppressed because it is too large
Load Diff
+16
-2
@@ -667,6 +667,9 @@ sub decode_spd {
|
||||
1066 => 8500,
|
||||
1333 => 10600,
|
||||
1600 => 12800,
|
||||
1867 => 14900,
|
||||
2133 => 17000,
|
||||
2134 => 17000,
|
||||
);
|
||||
|
||||
my %ddr3modcap = (
|
||||
@@ -707,9 +710,20 @@ sub decode_spd {
|
||||
}
|
||||
$rethash->{product}->{name}=$memtypes{$spd[2]};
|
||||
if ($spd[2] == 11) { #DDR3 spec applies
|
||||
my $ftbdividend = $spd[9] >> 4;
|
||||
my $ftbdivisor = $spd[9] & 0xf;
|
||||
my $ftb = $ftbdividend/$ftbdivisor;
|
||||
my $fineoffset = $spd[34];
|
||||
if ($fineoffset & 0b10000000) {
|
||||
#negative value, twos complement
|
||||
$fineoffset = 0-(($fineoffset ^ 0xff) + 1);
|
||||
}
|
||||
$fineoffset = ($ftb * $fineoffset) * 10**-3;
|
||||
my $mtb = $spd[10]/$spd[11];
|
||||
my $speed = $speedfromclock{int(2/($mtb*$spd[12]*10**-3))};
|
||||
$rethash->{product}->{name}="PC3-".$speed;
|
||||
my $clock = int(2/(($mtb*$spd[12]+$fineoffset)*10**-3));
|
||||
my $speed = $speedfromclock{$clock};
|
||||
unless ($speed) { $speed = "UNKNOWN"; }
|
||||
$rethash->{product}->{name}="PC3-".$speed." ($clock MT/s)";
|
||||
if ($spd[8]&0b11000) {
|
||||
$rethash->{product}->{name} .= " ECC";
|
||||
}
|
||||
|
||||
Regular → Executable
+579
-158
File diff suppressed because it is too large
Load Diff
Regular → Executable
+58
-27
@@ -28,9 +28,8 @@ use strict;
|
||||
Input: service nodename
|
||||
Output: Masternode, OS and ARCH
|
||||
Example:
|
||||
xCAT::ServiceNodeUtils->readSNInfo;
|
||||
my $retdata = xCAT::ServiceNodeUtils->readSNInfo;
|
||||
=cut
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
sub readSNInfo
|
||||
{
|
||||
@@ -81,18 +80,18 @@ sub readSNInfo
|
||||
|
||||
Checks the service node table in the database to see
|
||||
if input Service should be setup on the
|
||||
input service node
|
||||
input service node or Management Node (used by AAsn.pm)
|
||||
|
||||
Input:servicenodename,ipaddres(s) and hostnames of service node
|
||||
Output:
|
||||
array of services to setup for this service node
|
||||
hash of services to setup for this service node
|
||||
Globals:
|
||||
$::RUNCMD_RC = 0; good
|
||||
$::RUNCMD_RC = 1; error
|
||||
Error:
|
||||
none
|
||||
Example:
|
||||
@servicestosetup=xCAT::ServiceNodeUtils->isServiceReq($servicenodename, @serviceip) { blah; }
|
||||
$servicestosetup=xCAT::ServiceNodeUtils->isServiceReq($servicenodename, @serviceip) { blah; }
|
||||
|
||||
=cut
|
||||
|
||||
@@ -102,13 +101,17 @@ sub isServiceReq
|
||||
require xCAT::Table;
|
||||
my ($class, $servicenodename, $serviceip) = @_;
|
||||
|
||||
# list of all services from service node table
|
||||
# note this must be updated if more services added
|
||||
my @services = (
|
||||
"nameserver", "dhcpserver", "tftpserver", "nfsserver",
|
||||
"conserver", "monserver", "ldapserver", "ntpserver",
|
||||
"ftpserver", "ipforward"
|
||||
);
|
||||
# get list of all services from service node table ( actually all defined attributes)
|
||||
# read the schema
|
||||
my $schema = xCAT::Table->getTableSchema("servicenode");
|
||||
my @services; # list of only the actual service attributes from the servicenode table
|
||||
my @servicesattrs; # building second copy for call to getAllNodeAttribs, which modifies the array
|
||||
foreach my $c (@{$schema->{cols}}) {
|
||||
if (($c ne "node") && ($c ne "comments") && ($c ne "disable")) {
|
||||
push @servicesattrs,$c;
|
||||
push @services,$c;
|
||||
}
|
||||
}
|
||||
|
||||
my @ips = @$serviceip; # list of service node ip addresses and names
|
||||
my $rc = 0;
|
||||
@@ -131,12 +134,19 @@ sub isServiceReq
|
||||
return; # do not setup anything
|
||||
}
|
||||
|
||||
my @process_service_list = ();
|
||||
# Are we on the MN
|
||||
my $mname;
|
||||
if (xCAT::Utils->isMN()) {
|
||||
my @nodeinfo = xCAT::NetworkUtils->determinehostname;
|
||||
$mname = pop @nodeinfo; # get hostname
|
||||
}
|
||||
|
||||
# read all the nodes from the table, for each service
|
||||
foreach my $service (@services)
|
||||
my $servicehash;
|
||||
|
||||
# read all the nodes from the table, all the service attributes
|
||||
my @snodelist= $servicenodetab->getAllNodeAttribs(\@servicesattrs);
|
||||
foreach my $service (@services) # check list of services
|
||||
{
|
||||
my @snodelist = $servicenodetab->getAllNodeAttribs([$service]);
|
||||
|
||||
foreach $serviceip (@ips) # check the table for this servicenode
|
||||
{
|
||||
@@ -152,18 +162,38 @@ sub isServiceReq
|
||||
# value 1 or yes then we setup the service
|
||||
if (($value eq "1") || ($value eq "YES"))
|
||||
{
|
||||
push @process_service_list,
|
||||
$service; # found service to setup
|
||||
$servicehash->{$service} = "1";
|
||||
} elsif ($value eq "2") {
|
||||
$servicehash->{$service} = "2";
|
||||
} else {
|
||||
$servicehash->{$service} = "0";
|
||||
}
|
||||
}
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
# if the ftpserver attribute is not defined in the service node table
|
||||
# and we are on
|
||||
# the Linux management node, we need to look at site.vsftp
|
||||
# if the tftpserver attribute is not defined, then we default it 1
|
||||
if (($mname) && (xCAT::Utils->isLinux())) {
|
||||
if (!exists($servicehash->{'ftpserver'})) {
|
||||
my @tmp = xCAT::TableUtils->get_site_attribute("vsftp");
|
||||
if ($tmp[0] && ($tmp[0] !~ /0|NO|No|no|N|n/ )) {
|
||||
$servicehash->{'ftpserver'} = 1;
|
||||
}
|
||||
}
|
||||
if (!exists($servicehash->{'tftpserver'})) {
|
||||
$servicehash->{'tftpserver'} = 1;
|
||||
}
|
||||
}
|
||||
$servicenodetab->close;
|
||||
|
||||
$::RUNCMD_RC = 0;
|
||||
return @process_service_list;
|
||||
return $servicehash;
|
||||
|
||||
}
|
||||
|
||||
@@ -214,12 +244,13 @@ sub getAllSN
|
||||
# if did not input "ALL" and there is a MN, remove it
|
||||
my @newservicenodes;
|
||||
if ((!defined($options)) || ($options ne "ALL")) {
|
||||
my $mname = xCAT::Utils->noderangecontainsMn(@servicenodes);
|
||||
if ($mname) { # if there is a MN
|
||||
foreach my $nodes (@servicenodes) {
|
||||
if ($mname ne ($nodes)){
|
||||
push @newservicenodes, $nodes;
|
||||
}
|
||||
my @mname = xCAT::Utils->noderangecontainsMn(@servicenodes);
|
||||
if (@mname) { # if there is a MN
|
||||
foreach my $node (@servicenodes) {
|
||||
# check to see if node in MN list
|
||||
if (!(grep(/^$node$/, @mname))) { # if node not in the MN array
|
||||
push @newservicenodes, $node;
|
||||
}
|
||||
}
|
||||
$servicenodetab->close;
|
||||
return @newservicenodes; # return without the MN in the array
|
||||
@@ -327,7 +358,7 @@ sub getSNList
|
||||
$servicenodetab->close;
|
||||
foreach my $node (@nodes)
|
||||
{
|
||||
if ($service eq "") # want all the service nodes
|
||||
if (! defined ($service) || ($service eq "")) # want all the service nodes
|
||||
{
|
||||
push @servicenodes, $node->{node};
|
||||
}
|
||||
|
||||
+134
-102
@@ -36,7 +36,7 @@
|
||||
package xCAT::Table;
|
||||
use xCAT::MsgUtils;
|
||||
use Sys::Syslog;
|
||||
use Storable qw/freeze thaw/;
|
||||
use Storable qw/freeze thaw store_fd fd_retrieve/;
|
||||
use IO::Socket;
|
||||
#use Data::Dumper;
|
||||
use POSIX qw/WNOHANG/;
|
||||
@@ -70,7 +70,7 @@ require xCAT::NotifHandler;
|
||||
|
||||
my $dbworkerpid; #The process id of the database worker
|
||||
my $dbworkersocket;
|
||||
my $dbsockpath = "/tmp/xcat/dbworker.sock.".$$;
|
||||
my $dbsockpath = "/var/run/xcat/dbworker.sock.".$$;
|
||||
my $exitdbthread;
|
||||
my $dbobjsforhandle;
|
||||
my $intendedpid;
|
||||
@@ -92,8 +92,6 @@ sub dbc_call {
|
||||
sub dbc_submit {
|
||||
my $request = shift;
|
||||
$request->{'wantarray'} = wantarray();
|
||||
my $data = freeze($request);
|
||||
$data.= "\nENDOFFREEZEQFVyo4Cj6Q0v\n";
|
||||
my $clisock;
|
||||
my $tries=300;
|
||||
while($tries and !($clisock = IO::Socket::UNIX->new(Peer => $dbsockpath, Type => SOCK_STREAM, Timeout => 120) ) ) {
|
||||
@@ -105,22 +103,20 @@ sub dbc_submit {
|
||||
use Carp qw/cluck/;
|
||||
cluck();
|
||||
}
|
||||
print $clisock $data;
|
||||
$data="";
|
||||
store_fd($request,$clisock);
|
||||
#print $clisock $data;
|
||||
my $data="";
|
||||
my $lastline="";
|
||||
while (read($clisock,$lastline,32768)) { #$lastline ne "ENDOFFREEZEQFVyo4Cj6Q0j\n" and $lastline ne "*XCATBUGDETECTED*76e9b54341\n") { #index($lastline,"ENDOFFREEZEQFVyo4Cj6Q0j") < 0) {
|
||||
# $lastline = <$clisock>;
|
||||
$data .= $lastline;
|
||||
}
|
||||
my $retdata = fd_retrieve($clisock);
|
||||
close($clisock);
|
||||
if ($lastline =~ m/\*XCATBUGDETECTED\*76e9b54341\n\z/) { #if it was an error
|
||||
if (ref $retdata eq "SCALAR") { #bug detected
|
||||
#in the midst of the operation, die like it used to die
|
||||
my $err;
|
||||
$data =~ /\*XCATBUGDETECTED\*:(.*):\*XCATBUGDETECTED\*/s;
|
||||
$$retdata =~ /\*XCATBUGDETECTED\*:(.*):\*XCATBUGDETECTED\*/s;
|
||||
$err = $1;
|
||||
die $err;
|
||||
}
|
||||
my @returndata = @{thaw($data)};
|
||||
my @returndata = @{$retdata};
|
||||
if (wantarray) {
|
||||
return @returndata;
|
||||
} else {
|
||||
@@ -163,7 +159,7 @@ sub init_dbworker {
|
||||
#This process is the database worker, it's job is to manage database queries to reduce required handles and to permit cross-process caching
|
||||
$0 = "xcatd: DB Access";
|
||||
use File::Path;
|
||||
mkpath('/tmp/xcat/');
|
||||
mkpath('/var/run/xcat/');
|
||||
use IO::Socket;
|
||||
$SIG{TERM} = $SIG{INT} = sub {
|
||||
$exitdbthread=1;
|
||||
@@ -201,8 +197,7 @@ sub init_dbworker {
|
||||
xCAT::MsgUtils->message("S","xcatd: possible BUG encountered by xCAT DB worker ".$err);
|
||||
if ($currcon) {
|
||||
eval { #avoid hang by allowin client to die too
|
||||
print $currcon "*XCATBUGDETECTED*:$err:*XCATBUGDETECTED*\n";
|
||||
print $currcon "*XCATBUGDETECTED*76e9b54341\n";
|
||||
store_fd("*XCATBUGDETECTED*:$err:*XCATBUGDETECTED*\n",$currcon);
|
||||
$clientset->remove($currcon);
|
||||
close($currcon);
|
||||
};
|
||||
@@ -230,13 +225,14 @@ sub handle_dbc_conn {
|
||||
my $client = shift;
|
||||
my $clientset = shift;
|
||||
my $data;
|
||||
if ($data = <$client>) {
|
||||
my $lastline;
|
||||
while ($lastline ne "ENDOFFREEZEQFVyo4Cj6Q0v\n") { #$data !~ /ENDOFFREEZEQFVyo4Cj6Q0v/) {
|
||||
$lastline = <$client>;
|
||||
$data .= $lastline;
|
||||
}
|
||||
my $request = thaw($data);
|
||||
my $request;
|
||||
eval {
|
||||
$request = fd_retrieve($client);
|
||||
};
|
||||
if ($@ and $@ =~ /^Magic number checking on storable file/) { #this most likely means we ran over the end of available input
|
||||
$clientset->remove($client);
|
||||
close($client);
|
||||
} elsif ($request) {
|
||||
my $response;
|
||||
my @returndata;
|
||||
if ($request->{'wantarray'}) {
|
||||
@@ -244,12 +240,7 @@ sub handle_dbc_conn {
|
||||
} else {
|
||||
@returndata = (scalar(handle_dbc_request($request)));
|
||||
}
|
||||
$response = freeze(\@returndata);
|
||||
# $response .= "\nENDOFFREEZEQFVyo4Cj6Q0j\n";
|
||||
print $client $response;
|
||||
$clientset->remove($client);
|
||||
close($client);
|
||||
} else { #Connection terminated, clean up
|
||||
store_fd(\@returndata,$client);
|
||||
$clientset->remove($client);
|
||||
close($client);
|
||||
}
|
||||
@@ -332,6 +323,8 @@ sub handle_dbc_request {
|
||||
return $opentables{$tablename}->{$autocommit}->getAllNodeAttribs(@args);
|
||||
} elsif ($functionname eq 'getAllEntries') {
|
||||
return $opentables{$tablename}->{$autocommit}->getAllEntries(@args);
|
||||
} elsif ($functionname eq 'getMAXMINEntries') {
|
||||
return $opentables{$tablename}->{$autocommit}->getMAXMINEntries(@args);
|
||||
} elsif ($functionname eq 'writeAllEntries') {
|
||||
return $opentables{$tablename}->{$autocommit}->writeAllEntries(@args);
|
||||
} elsif ($functionname eq 'getAllAttribsWhere') {
|
||||
@@ -1612,7 +1605,7 @@ sub setAttribs
|
||||
# delimit the columns of the table
|
||||
my $delimitedcol = &delimitcol($col);
|
||||
$cols = $cols . $delimitedcol . " = ?,";
|
||||
push @bind, (($$elems{$col} =~ /NULL/) ? undef: $$elems{$col});
|
||||
push @bind, (($$elems{$col} eq "NULL") ? undef: $$elems{$col});
|
||||
}
|
||||
chop($cols);
|
||||
my $cmd ;
|
||||
@@ -1795,7 +1788,7 @@ sub setAttribsWhere
|
||||
# delimit the columns of the table
|
||||
my $delimitedcol = &delimitcol($col);
|
||||
$cols = $cols . $delimitedcol . " = ?,";
|
||||
push @bind, (($$elems{$col} =~ /NULL/) ? undef: $$elems{$col});
|
||||
push @bind, (($$elems{$col} eq "NULL") ? undef: $$elems{$col});
|
||||
}
|
||||
chop($cols);
|
||||
my $cmd = "UPDATE " . $self->{tabname} . " set $cols where " . $where_clause;
|
||||
@@ -2280,17 +2273,16 @@ sub getNodeAttribs
|
||||
#skip undefined values, save time
|
||||
next;
|
||||
}
|
||||
|
||||
if ($datum->{$attrib} =~ /^\/[^\/]*\/[^\/]*\/$/)
|
||||
{
|
||||
my $exp = substr($datum->{$attrib}, 1);
|
||||
chop $exp;
|
||||
my @parts = split('/', $exp, 2);
|
||||
my $retval = $node;
|
||||
my $retval = $node;
|
||||
$retval =~ s/$parts[0]/$parts[1]/;
|
||||
$datum->{$attrib} = $retval;
|
||||
}
|
||||
elsif ($datum->{$attrib} =~ /^\|.*\|.*\|$/)
|
||||
elsif ($datum->{$attrib} =~ /^\|.*\|$/)
|
||||
{
|
||||
|
||||
#Perform arithmetic and only arithmetic operations in bracketed issues on the right.
|
||||
@@ -2300,6 +2292,14 @@ sub getNodeAttribs
|
||||
my $exp = substr($datum->{$attrib}, 1);
|
||||
chop $exp;
|
||||
my @parts = split('\|', $exp, 2);
|
||||
my $arraySize = @parts;
|
||||
if ($arraySize < 2) { # easy regx, generate lhs from node
|
||||
my $lhs;
|
||||
my @numbers = $node =~ m/[\D0]*(\d+)/g;
|
||||
$lhs = '[\D0]*(\d+)' x scalar(@numbers);
|
||||
$lhs .= '.*$';
|
||||
unshift(@parts,$lhs);
|
||||
}
|
||||
my $curr;
|
||||
my $next;
|
||||
my $prev;
|
||||
@@ -2351,71 +2351,6 @@ sub getNodeAttribs
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
=head3 getNodeSpecAttribs
|
||||
Description: Retrieves the requested attributes which matching the specified options for a node
|
||||
Arguments:
|
||||
Noderange
|
||||
The specified options
|
||||
List of attributes
|
||||
Return:
|
||||
Attribute hash
|
||||
Example:
|
||||
my $tab = xCAT::Table->new('ppcdirect');
|
||||
my $ent = $tab->getNodeSpecAttribs($node, {username=>'HMC'}, qw/password/);
|
||||
Comments:
|
||||
The keys of the specified options can be given in the list of attributes or not,
|
||||
this routine will deal with them.
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
#sub getNodeSpecAttribs {
|
||||
# my $self = shift;
|
||||
# my $node = shift;
|
||||
# my %options = ();
|
||||
# my @attribs = ();
|
||||
# my @keys = ();
|
||||
# if (ref $_[0] eq 'HASH') {
|
||||
# %options = %{shift()};
|
||||
# @attribs = @_;
|
||||
# foreach my $key (keys %options) {
|
||||
# if (!grep(/^$key$/, @attribs)) {
|
||||
# push @attribs, $key;
|
||||
# }
|
||||
# }
|
||||
# } else {
|
||||
# @attribs = @_;
|
||||
# }
|
||||
# if ((keys (%options)) == 0) {
|
||||
# my $ent = $self->getNodeAttribs($node, \@attribs);
|
||||
# return $ent;
|
||||
# } else {
|
||||
# my $nodekey = "node";
|
||||
# if (defined $xCAT::Schema::tabspec{$self->{tabname}}->{nodecol}) {
|
||||
# $nodekey = $xCAT::Schema::tabspec{$self->{tabname}}->{nodecol};
|
||||
# }
|
||||
# $options{$nodekey} = $node;
|
||||
# my $ent = $self->getAttribs(\%options, \@attribs);
|
||||
# if ($ent) {
|
||||
# return $ent;
|
||||
# }
|
||||
# my ($nodeghash) = $self->{nodelist}->getAttribs({node=>$node}, "groups");
|
||||
# unless(defined($nodeghash) && defined($nodeghash->{groups})) {
|
||||
# return undef;
|
||||
# }
|
||||
# my @nodegroups = split(/,/, $nodeghash->{groups});
|
||||
# foreach my $group (@nodegroups) {
|
||||
# $options{$nodekey} = $group;
|
||||
# my $g_ret = $self->getAttribs(\%options, \@attribs);
|
||||
# if ($g_ret) {
|
||||
# return $g_ret;
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# return undef;
|
||||
#}
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
=head3 getNodeAttribs_nosub
|
||||
|
||||
Description:
|
||||
@@ -2969,10 +2904,14 @@ sub getAllNodeAttribs
|
||||
$self->{nrcache}->{$data->{$nodekey}}->{tstamp} = time();
|
||||
}
|
||||
@nodes = @{$self->{nrcache}->{$data->{$nodekey}}->{value}}; #expand node entry, to make groups expand
|
||||
unless (@nodes) { #in the event of an entry not in nodelist, use entry value verbatim
|
||||
@nodes = ($data->{$nodekey});
|
||||
}
|
||||
|
||||
#If node not in nodelist do not add to the hash (SF 3580)
|
||||
#unless (@nodes) { #in the event of an entry not in nodelist, use entry value verbatim
|
||||
# @nodes = ($data->{$nodekey});
|
||||
#} end SF 3580
|
||||
|
||||
#my $localhash = $self->getNodesAttribs(\@nodes,$attribq); #NOTE: This is stupid, rebuilds the cache for every entry, FIXME
|
||||
|
||||
foreach (@nodes)
|
||||
{
|
||||
if ($donenodes{$_}) { next; }
|
||||
@@ -4051,5 +3990,98 @@ sub output_table {
|
||||
print $fh "\n";
|
||||
return 0;
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
=head3 getMAXMINEntries
|
||||
|
||||
Description: Select the rows in the Table which has the MAX and the row with the
|
||||
Min value for the input attribute.
|
||||
Currently only the auditlog and evenlog are setup to have such an attribute (recid).
|
||||
|
||||
Arguments:
|
||||
Table handle
|
||||
attribute name ( e.g. recid)
|
||||
|
||||
Returns:
|
||||
HASH
|
||||
max=> max value
|
||||
min=> min value
|
||||
Globals:
|
||||
|
||||
Error:
|
||||
|
||||
Example:
|
||||
|
||||
my $tabh = xCAT::Table->new($table);
|
||||
my $recs=$tabh->getEntries("recid"); # returns row with recid max value in database
|
||||
# and the row with the min value.
|
||||
|
||||
Comments:
|
||||
none
|
||||
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub getMAXMINEntries
|
||||
{
|
||||
my $self = shift;
|
||||
if ($dbworkerpid) {
|
||||
return dbc_call($self,'getMAXMINEntries',@_);
|
||||
}
|
||||
my $attr = shift;
|
||||
my $rets;
|
||||
my $query;
|
||||
my $xcatcfg=get_xcatcfg();
|
||||
|
||||
# delimit the disable column based on the DB
|
||||
my $disable= &delimitcol("disable");
|
||||
my $qstring;
|
||||
if ($xcatcfg =~ /^DB2:/) { # for DB2
|
||||
$qstring = "SELECT MAX (\"$attr\") FROM " . $self->{tabname} . " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
} else {
|
||||
$qstring = "SELECT MAX($attr) FROM " . $self->{tabname} . " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
}
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
|
||||
$query->execute();
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
foreach (keys %$data)
|
||||
{
|
||||
if ($data->{$_} =~ /^$/)
|
||||
{
|
||||
$rets->{"max"} = undef;
|
||||
} else {
|
||||
$rets->{"max"} = $data->{$_};
|
||||
|
||||
}
|
||||
last; # better only be one value for max
|
||||
|
||||
}
|
||||
}
|
||||
$query->finish();
|
||||
if ($xcatcfg =~ /^DB2:/) { # for DB2
|
||||
$qstring = "SELECT MIN (\"$attr\") FROM " . $self->{tabname} . " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
} else {
|
||||
$qstring = "SELECT MIN($attr) FROM " . $self->{tabname} . " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
}
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
|
||||
$query->execute();
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
foreach (keys %$data)
|
||||
{
|
||||
if ($data->{$_} =~ /^$/)
|
||||
{
|
||||
$rets->{"min"} = undef;
|
||||
} else {
|
||||
$rets->{"min"} = $data->{$_};
|
||||
}
|
||||
last; # better be only one value for min
|
||||
}
|
||||
}
|
||||
return $rets;
|
||||
}
|
||||
1;
|
||||
|
||||
|
||||
+458
-56
@@ -19,6 +19,8 @@ if ($^O =~ /^aix/i) {
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use strict;
|
||||
require xCAT::Table;
|
||||
require xCAT::Zone;
|
||||
use File::Path;
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
=head3
|
||||
@@ -256,6 +258,7 @@ sub bldnonrootSSHFiles
|
||||
|
||||
Arguments:
|
||||
Array of nodes
|
||||
Timeout for expect call (optional)
|
||||
Returns:
|
||||
|
||||
Env Variables: $DSH_FROM_USERID, $DSH_TO_USERID, $DSH_REMOTE_PASSWORD
|
||||
@@ -269,7 +272,7 @@ sub bldnonrootSSHFiles
|
||||
Error:
|
||||
0=good, 1=error
|
||||
Example:
|
||||
xCAT::TableUtils->setupSSH(@target_nodes);
|
||||
xCAT::TableUtils->setupSSH(@target_nodes,$expecttimeout);
|
||||
Comments:
|
||||
Does not setup known_hosts. Assumes automatically
|
||||
setup by SSH ( ssh config option StrictHostKeyChecking no should
|
||||
@@ -280,7 +283,7 @@ sub bldnonrootSSHFiles
|
||||
#--------------------------------------------------------------------------------
|
||||
sub setupSSH
|
||||
{
|
||||
my ($class, $ref_nodes) = @_;
|
||||
my ($class, $ref_nodes,$expecttimeout) = @_;
|
||||
my @nodes = $ref_nodes;
|
||||
my @badnodes = ();
|
||||
my $n_str = $nodes[0];
|
||||
@@ -333,23 +336,24 @@ sub setupSSH
|
||||
|
||||
$::REMOTE_SHELL = "/usr/bin/ssh";
|
||||
my $rsp = {};
|
||||
|
||||
|
||||
# Get the home directory
|
||||
my $home = xCAT::Utils->getHomeDir($from_userid);
|
||||
$ENV{'DSH_FROM_USERID_HOME'} = $home;
|
||||
|
||||
if ($from_userid eq "root")
|
||||
{
|
||||
|
||||
# make the directory to hold keys to transfer to the nodes
|
||||
if (!-d $SSHdir)
|
||||
{
|
||||
mkpath("$SSHdir", { mode => 0755 });
|
||||
}
|
||||
|
||||
# generates new keys for root, if they do not already exist
|
||||
# generates new keys for root, if they do not already exist ~/.ssh
|
||||
|
||||
# nodes not used on this option but in there to preserve the interface
|
||||
my $rc=
|
||||
xCAT::RemoteShellExp->remoteshellexp("k",$::CALLBACK,$::REMOTE_SHELL);
|
||||
xCAT::RemoteShellExp->remoteshellexp("k",$::CALLBACK,$::REMOTE_SHELL,$n_str,$expecttimeout);
|
||||
if ($rc != 0) {
|
||||
$rsp->{data}->[0] = "remoteshellexp failed generating keys.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
@@ -371,7 +375,10 @@ else
|
||||
fi
|
||||
mkdir -p \$dest_dir
|
||||
cat /tmp/$to_userid/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1
|
||||
cat /tmp/$to_userid/.ssh/id_rsa.pub >> \$home/.ssh/authorized_keys 2>&1
|
||||
rm -f \$home/.ssh/id_rsa 2>&1
|
||||
cp /tmp/$to_userid/.ssh/id_rsa \$home/.ssh/id_rsa 2>&1
|
||||
cp /tmp/$to_userid/.ssh/id_rsa.pub \$home/.ssh/id_rsa.pub 2>&1
|
||||
chmod 0600 \$home/.ssh/id_* 2>&1
|
||||
rm -f /tmp/$to_userid/.ssh/* 2>&1
|
||||
rmdir \"/tmp/$to_userid/.ssh\"
|
||||
@@ -383,6 +390,7 @@ rmdir \"/tmp/$to_userid\" \n";
|
||||
my $auth_key2=0;
|
||||
if ($from_userid eq "root")
|
||||
{
|
||||
# this will put the root/.ssh/id_rsa.pub key in the authorized keys file to put on the node
|
||||
my $rc = xCAT::TableUtils->cpSSHFiles($SSHdir);
|
||||
if ($rc != 0)
|
||||
{ # error
|
||||
@@ -415,53 +423,50 @@ rmdir \"/tmp/$to_userid\" \n";
|
||||
xCAT::TableUtils->bldnonrootSSHFiles($from_userid);
|
||||
}
|
||||
|
||||
# send the keys to the nodes for root or some other id
|
||||
#
|
||||
# This environment variable determines whether to setup
|
||||
# node to node ssh
|
||||
# The nodes must be checked against the site.sshbetweennodes attribute
|
||||
# send the keys
|
||||
# For root user and not to devices only to nodes
|
||||
if (($from_userid eq "root") && (!($ENV{'DEVICETYPE'}))) {
|
||||
my $enablenodes;
|
||||
my $disablenodes;
|
||||
my @nodelist= split(",", $n_str);
|
||||
foreach my $n (@nodelist)
|
||||
# Need to check if nodes are in a zone.
|
||||
my @zones;
|
||||
my $tab = xCAT::Table->new("zone");
|
||||
my @zones;
|
||||
if ($tab)
|
||||
{
|
||||
my $enablessh=xCAT::TableUtils->enablessh($n);
|
||||
if ($enablessh == 1) {
|
||||
$enablenodes .= $n;
|
||||
$enablenodes .= ",";
|
||||
} else {
|
||||
$disablenodes .= $n;
|
||||
$disablenodes .= ",";
|
||||
# if we have zones, need to send the zone keys to each node in the zone
|
||||
my @attribs = ("zonename");
|
||||
@zones = $tab->getAllAttribs(@attribs);
|
||||
$tab->close();
|
||||
} else {
|
||||
$rsp->{data}->[0] = "Could not open zone table.\n";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
return 1;
|
||||
}
|
||||
# check for zones, key send is different if zones defined or not
|
||||
|
||||
if (@zones) { # we have zones defined
|
||||
my $rc = xCAT::TableUtils->sendkeysTOzones($ref_nodes,$expecttimeout);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$rsp->{data}->[0] = "Error sending ssh keys to the zones.\n";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
exit 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
my $cmd;
|
||||
if ($enablenodes) { # node on list to setup nodetonodessh
|
||||
chop $enablenodes; # remove last comma
|
||||
$ENV{'DSH_ENABLE_SSH'} = "YES";
|
||||
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes);
|
||||
} else { # no zones
|
||||
|
||||
# if no zone table defined, do it the old way , keys are in ~/.ssh
|
||||
my $rc = xCAT::TableUtils->sendkeysNOzones($ref_nodes,$expecttimeout);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$rsp->{data}->[0] = "remoteshellexp failed sending keys to enablenodes.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
|
||||
}
|
||||
}
|
||||
if ($disablenodes) { # node on list to setup nodetonodessh
|
||||
chop $disablenodes; # remove last comma
|
||||
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$rsp->{data}->[0] = "remoteshellexp failed sending keys to disablenodes.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
{
|
||||
$rsp->{data}->[0] = "Error sending ssh keys to the nodes.\n";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else { # from user is not root or it is a device , always send private key
|
||||
$ENV{'DSH_ENABLE_SSH'} = "YES";
|
||||
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$n_str);
|
||||
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$n_str,$expecttimeout);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$rsp->{data}->[0] = "remoteshellexp failed sending keys.";
|
||||
@@ -475,7 +480,7 @@ rmdir \"/tmp/$to_userid\" \n";
|
||||
foreach my $n (@testnodes)
|
||||
{
|
||||
my $rc=
|
||||
xCAT::RemoteShellExp->remoteshellexp("t",$::CALLBACK,"/usr/bin/ssh",$n);
|
||||
xCAT::RemoteShellExp->remoteshellexp("t",$::CALLBACK,"/usr/bin/ssh",$n,$expecttimeout);
|
||||
if ($rc != 0)
|
||||
{
|
||||
push @badnodes, $n;
|
||||
@@ -500,6 +505,235 @@ rmdir \"/tmp/$to_userid\" \n";
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 sendkeysNOzones
|
||||
|
||||
Transfers the ssh keys
|
||||
for the root id on the nodes no zones
|
||||
key from ~/.ssh site.sshbetweennodes honored
|
||||
|
||||
|
||||
Arguments:
|
||||
Array of nodes
|
||||
Timeout for expect call (optional)
|
||||
Returns:
|
||||
|
||||
Env Variables: $DSH_FROM_USERID, $DSH_TO_USERID, $DSH_REMOTE_PASSWORD
|
||||
the ssh keys are transferred from the $DSH_FROM_USERID to the $DSH_TO_USERID
|
||||
on the node(s). The DSH_REMOTE_PASSWORD and the DSH_FROM_USERID
|
||||
must be obtained by
|
||||
the calling script or from the xdsh client
|
||||
|
||||
Globals:
|
||||
$::XCATROOT , $::CALLBACK
|
||||
Error:
|
||||
0=good, 1=error
|
||||
Example:
|
||||
xCAT::TableUtils->sendkeysNOzones($ref_nodes,$expecttimeout);
|
||||
Comments:
|
||||
Does not setup known_hosts. Assumes automatically
|
||||
setup by SSH ( ssh config option StrictHostKeyChecking no should
|
||||
be set in the ssh config file).
|
||||
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub sendkeysNOzones
|
||||
{
|
||||
my ($class, $ref_nodes,$expecttimeout) = @_;
|
||||
my @nodes=$ref_nodes;
|
||||
my $enablenodes;
|
||||
my $disablenodes;
|
||||
my $n_str = $nodes[0];
|
||||
my @nodelist= split(",", $n_str);
|
||||
my $rsp = ();
|
||||
foreach my $n (@nodelist)
|
||||
{
|
||||
my $enablessh=xCAT::TableUtils->enablessh($n);
|
||||
if ($enablessh == 1) {
|
||||
$enablenodes .= $n;
|
||||
$enablenodes .= ",";
|
||||
} else {
|
||||
$disablenodes .= $n;
|
||||
$disablenodes .= ",";
|
||||
}
|
||||
|
||||
}
|
||||
if ($enablenodes) { # node on list to setup nodetonodessh
|
||||
chop $enablenodes; # remove last comma
|
||||
$ENV{'DSH_ENABLE_SSH'} = "YES";
|
||||
# send the keys to the nodes
|
||||
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes,$expecttimeout);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$rsp->{data}->[0] = "remoteshellexp failed sending keys to enablenodes.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
|
||||
}
|
||||
}
|
||||
if ($disablenodes) { # node on list to disable nodetonodessh
|
||||
chop $disablenodes; # remove last comma
|
||||
# send the keys to the nodes
|
||||
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes,$expecttimeout);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$rsp->{data}->[0] = "remoteshellexp failed sending keys to disablenodes.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 sendkeysTOzones
|
||||
|
||||
Transfers the ssh keys
|
||||
for the root id on the nodes using the zone table.
|
||||
If in a zone, then root ssh keys for the node will be taken from the zones ssh keys not ~/.ssh
|
||||
zones are only supported on nodes that are not a service node.
|
||||
Also for the call to RemoteShellExp, we must group the nodes that are in the same zone
|
||||
|
||||
|
||||
Arguments:
|
||||
Array of nodes
|
||||
Timeout for expect call (optional)
|
||||
Returns:
|
||||
|
||||
Env Variables: $DSH_FROM_USERID, $DSH_TO_USERID, $DSH_REMOTE_PASSWORD
|
||||
the ssh keys are transferred from the $DSH_FROM_USERID to the $DSH_TO_USERID
|
||||
on the node(s). The DSH_REMOTE_PASSWORD and the DSH_FROM_USERID
|
||||
must be obtained by
|
||||
the calling script or from the xdsh client
|
||||
|
||||
Globals:
|
||||
$::XCATROOT , $::CALLBACK
|
||||
Error:
|
||||
0=good, 1=error
|
||||
Example:
|
||||
xCAT::TableUtils->sendkeysTOzones($ref_nodes,$expecttimeout);
|
||||
Comments:
|
||||
Does not setup known_hosts. Assumes automatically
|
||||
setup by SSH ( ssh config option StrictHostKeyChecking no should
|
||||
be set in the ssh config file).
|
||||
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub sendkeysTOzones
|
||||
{
|
||||
my ($class, $ref_nodes,$expecttimeout) = @_;
|
||||
my @nodes=$ref_nodes;
|
||||
my $n_str = $nodes[0];
|
||||
my @nodes= split(",", $n_str);
|
||||
my $rsp = ();
|
||||
my $cmd;
|
||||
my $roothome = xCAT::Utils->getHomeDir("root");
|
||||
my $zonehash =xCAT::Zone->getzoneinfo($::CALLBACK,\@nodes);
|
||||
foreach my $zonename (keys %$zonehash) {
|
||||
# build list of nodes
|
||||
my $zonenodelist="";
|
||||
foreach my $node (@{$zonehash->{$zonename}->{nodes}}) {
|
||||
$zonenodelist .= $node;
|
||||
$zonenodelist .= ",";
|
||||
|
||||
}
|
||||
$zonenodelist =~ s/,$//; # remove last comma
|
||||
# if any nodes defined for the zone
|
||||
if ($zonenodelist) {
|
||||
# check to see if we enable passwordless ssh between the nodes
|
||||
if (!(defined($zonehash->{$zonename}->{sshbetweennodes}))||
|
||||
(($zonehash->{$zonename}->{sshbetweennodes} =~ /^yes$/i )
|
||||
|| ($zonehash->{$zonename}->{sshbetweennodes} eq "1"))) {
|
||||
|
||||
$ENV{'DSH_ENABLE_SSH'} = "YES";
|
||||
} else {
|
||||
delete $ENV{'DSH_ENABLE_SSH'}; # do not enable passwordless ssh
|
||||
}
|
||||
# point to the ssh keys to send for this zone
|
||||
my $keydir = $zonehash->{$zonename}->{sshkeydir} ;
|
||||
|
||||
# check to see if the id_rsa and id_rsa.pub key is in the directory
|
||||
my $key="$keydir/id_rsa";
|
||||
my $key2="$keydir/id_rsa.pub";
|
||||
# Check to see if empty
|
||||
if (!(-e $key)) {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"The $key file does not exist for $zonename. Need to use chzone to regenerate the keys.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1);
|
||||
return 1;
|
||||
}
|
||||
if (!(-e $key2)) {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"The $key2 file does not exist for $zonename. Need to use chzone to regenerate the keys.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
# now put copy.sh in the zone directory from ~/.ssh
|
||||
my $rootkeydir="$roothome/.ssh";
|
||||
if ($rootkeydir ne $keydir) { # the zone keydir is not the same as ~/.ssh.
|
||||
$cmd="cp $rootkeydir/copy.sh $keydir";
|
||||
xCAT::Utils->runcmd($cmd, 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"Could not copy copy.sh to the zone key dir";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
# Also create $keydir/tmp and put root's id_rsa.pub (in authorized_keys) for the transfer
|
||||
$cmd="mkdir -p $keydir/tmp";
|
||||
xCAT::Utils->runcmd($cmd, 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"Could not mkdir the zone $keydir/tmp";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
return 1;
|
||||
}
|
||||
# create authorized_keys file
|
||||
if (xCAT::Utils->isMN()) { # if on Management Node
|
||||
$cmd = " cp $roothome/.ssh/id_rsa.pub $keydir/tmp/authorized_keys";
|
||||
} else { # SN
|
||||
$cmd = " cp $roothome/.ssh/authorized_keys $keydir/tmp/authorized_keys";
|
||||
}
|
||||
xCAT::Utils->runcmd($cmd, 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
$rsp->{data}->[0] = "$cmd failed.\n";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
chmod 0600, "$keydir/.ssh/tmp/authorized_keys";
|
||||
}
|
||||
# strip off .ssh
|
||||
my ($newkeydir,$ssh) = (split(/\.ssh/, $keydir));
|
||||
$ENV{'DSH_ZONE_SSHKEYS'} =$newkeydir ;
|
||||
# send the keys to the nodes
|
||||
my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",
|
||||
$zonenodelist,$expecttimeout);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$rsp = {};
|
||||
$rsp->{data}->[0] = "remoteshellexp failed sending keys to $zonename.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
|
||||
}
|
||||
} # end nodes in the zone
|
||||
|
||||
} # end for each zone
|
||||
|
||||
return (0);
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 cpSSHFiles
|
||||
|
||||
Builds authorized_keyfiles for root
|
||||
@@ -1497,19 +1731,10 @@ sub enablessh
|
||||
my ($class, $node) = @_;
|
||||
my $enablessh=1;
|
||||
|
||||
if( %::GLOBAL_SN_HASH ) {
|
||||
if ($::GLOBAL_SN_HASH{$node} == 1) {
|
||||
if( xCAT::Utils->isSN($node) ) {
|
||||
$enablessh=1; # service nodes always enabled
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
if (xCAT::Utils->isSN($node))
|
||||
{
|
||||
$enablessh=1; # service nodes always enabled
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
# if not a service node we need to check, before enabling
|
||||
my $values;
|
||||
my @vals = xCAT::TableUtils->get_site_attribute("sshbetweennodes");
|
||||
@@ -1553,12 +1778,93 @@ sub enablessh
|
||||
$enablessh=1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return $enablessh;
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 enableSSH
|
||||
Description:
|
||||
The function is same as enablessh() above. Before using this function,
|
||||
the $sn_hash for noderange, and $groups_hash for site.sshbetweennodes should be
|
||||
got. This is performance improvement.
|
||||
Arguments:
|
||||
$node -- node name
|
||||
$sn_hash -- if the node is one sn, key is the node name, and value is 1.
|
||||
if the node is not a sn, the key isn't in this hash
|
||||
$groups_hash -- there are two keys:
|
||||
1. Each group in the value of site.sshbetweennodes could be the key
|
||||
2. Each node in the groups from the value of site.sshbetweennodes , if the
|
||||
value isn't ALLGROUPS or NOGROUPS.
|
||||
|
||||
Returns:
|
||||
1 = enable ssh
|
||||
0 = do not enable ssh
|
||||
Globals:
|
||||
none
|
||||
Error:
|
||||
none
|
||||
Example:
|
||||
my $enable = xCAT::TableUtils->enableSSH($node);
|
||||
Comments:
|
||||
|
||||
=cut
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
sub enableSSH
|
||||
{
|
||||
|
||||
my ($class, $node, $sn_hash, $groups_hash) = @_;
|
||||
my $enablessh=1;
|
||||
|
||||
if( defined($sn_hash) && defined($sn_hash->{node}) && $sn_hash->{$node} == 1 ) {
|
||||
$enablessh=1; # service nodes always enabled
|
||||
|
||||
} else {
|
||||
# if not a service node we need to check, before enabling
|
||||
if (keys %$groups_hash) { # not empty
|
||||
if ($groups_hash->{ALLGROUPS} == 1)
|
||||
{
|
||||
$enablessh=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($groups_hash->{NOGROUPS} == 1)
|
||||
{
|
||||
$enablessh=0;
|
||||
}
|
||||
else
|
||||
{ # check to see if the node is a member of a group
|
||||
my $ismember = 0;
|
||||
$ismember = $groups_hash->{$node};
|
||||
|
||||
if ($ismember == 1)
|
||||
{
|
||||
$enablessh=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$enablessh=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ # does not exist, set default
|
||||
$enablessh=1;
|
||||
|
||||
}
|
||||
}
|
||||
return $enablessh;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@@ -1662,4 +1968,100 @@ sub getimagenames()
|
||||
$nodetab->close;
|
||||
return @imagenames;
|
||||
}
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
=head3 updatenodegroups
|
||||
Update groups attribute for the specified node
|
||||
|
||||
Arguments:
|
||||
node
|
||||
tabhd: the handler of 'nodelist' table,
|
||||
groups: the groups attribute need to be merged.
|
||||
Can be an array or string.
|
||||
Globals:
|
||||
none
|
||||
Error:
|
||||
Example:
|
||||
xCAT::TableUtils->updatenodegroups($node, $tab, $groups);
|
||||
|
||||
=cut
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
sub updatenodegroups {
|
||||
my ($class, $node, $tabhd, $groups) = @_;
|
||||
if (!$groups) {
|
||||
$groups = $tabhd;
|
||||
$tabhd = xCAT::Table->new('nodelist');
|
||||
unless ($tabhd) {
|
||||
xCAT::MsgUtils->message("E", " Could not read the nodelist table\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
my ($ent) = $tabhd->getNodeAttribs($node, ['groups']);
|
||||
my @list = ();
|
||||
if (defined($ent) and $ent->{groups}) {
|
||||
push @list, split(/,/,$ent->{groups});
|
||||
}
|
||||
if (ref($groups) eq 'ARRAY') {
|
||||
push @list, @$groups;
|
||||
} else {
|
||||
push @list, split(/,/,$groups);
|
||||
}
|
||||
my %saw;
|
||||
@saw{@list} = ();
|
||||
@list = keys %saw;
|
||||
$tabhd->setNodeAttribs($node, {groups=>join(",",@list)});
|
||||
}
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
=head3 rmnodegroups
|
||||
remove groups from the group attribute for the specified node
|
||||
|
||||
Arguments:
|
||||
node
|
||||
tabhd: the handler of 'nodelist' table,
|
||||
groups: the groups that need to be removed.
|
||||
Can be an array or string.
|
||||
Globals:
|
||||
none
|
||||
Error:
|
||||
Example:
|
||||
xCAT::TableUtils->rmnodegroups($node, $tab, $groups);
|
||||
|
||||
=cut
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
sub rmnodegroups {
|
||||
my ($class, $node, $tabhd, $groups) = @_;
|
||||
my ($ent) = $tabhd->getNodeAttribs($node, ['groups']);
|
||||
my @definedgroups;
|
||||
my @removegroups;
|
||||
my @newgroups;
|
||||
if (defined($ent) and $ent->{groups}) {
|
||||
push @definedgroups, split(/,/,$ent->{groups});
|
||||
}
|
||||
if (ref($groups) eq 'ARRAY') {
|
||||
push @removegroups, @$groups;
|
||||
} else {
|
||||
push @removegroups, split(/,/,$groups);
|
||||
}
|
||||
# take out any groups that match the input list of groups to remove
|
||||
foreach my $dgrp (@definedgroups){
|
||||
if (grep(/^$dgrp$/, @removegroups)) { # is the group to be removed
|
||||
next;
|
||||
} else { # keep this group
|
||||
push @newgroups,$dgrp;
|
||||
}
|
||||
}
|
||||
my %saw;
|
||||
@saw{@newgroups} = ();
|
||||
@newgroups = keys %saw;
|
||||
|
||||
$tabhd->setNodeAttribs($node, {groups=>join(",",@newgroups)});
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
+64
-22
@@ -36,11 +36,13 @@ my %usage = (
|
||||
LPAR(using Direct FSP Management) specific:
|
||||
rpower <noderange> [on|off|reset|stat|state|boot|of|sms]
|
||||
Blade(using Direct FSP Management) specific:
|
||||
rpower <noderange> [on|off|cycle|state]
|
||||
rpower <noderange> [on|onstandby|off|cycle|state|sms]
|
||||
Blade(using AMM) specific:
|
||||
rpower <noderange> [cycle|softoff] [-V|--verbose]
|
||||
zVM specific:
|
||||
rpower noderange [on|off|reset|stat|softoff]
|
||||
MIC specific:
|
||||
rpower noderange [stat|state|on|off|reset|boot]
|
||||
",
|
||||
"rbeacon" =>
|
||||
"Usage: rbeacon <noderange> [on|off|stat] [-V|--verbose]
|
||||
@@ -58,9 +60,11 @@ my %usage = (
|
||||
Blade specific:
|
||||
rvitals noderange {temp|wattage|fanspeed|leds|summary|all}
|
||||
BMC specific:
|
||||
rvitals noderange {temp|voltage|wattage|fanspeed|power|leds|lcds|summary|all}",
|
||||
rvitals noderange {temp|voltage|wattage|fanspeed|power|leds|lcds|summary|all}
|
||||
MIC specific:
|
||||
rvitals noderange {thermal|all}",
|
||||
"reventlog" =>
|
||||
"Usage: reventlog <noderange> [all|clear|<number of entries to retrieve>] [-V|--verbose]
|
||||
"Usage: reventlog <noderange> [all [-s]|clear|<number of entries to retrieve> [-s]] [-V|--verbose]
|
||||
reventlog [-h|--help|-v|--version]",
|
||||
"rinv" =>
|
||||
"Usage:
|
||||
@@ -68,22 +72,24 @@ my %usage = (
|
||||
rinv <noderange> [all|model|serial] [-V|--verbose]
|
||||
rinv [-h|--help|-v|--version]
|
||||
BMC specific:
|
||||
rinv <noderange> [vpd|mprom|deviceid|uuid|guid]
|
||||
rinv <noderange> [mprom|deviceid|uuid|guid|vpd [-t]|all [-t]]
|
||||
MPA specific:
|
||||
rinv <noderange> [firm|bios|diag|mprom|sprom|mparom|mac|mtm]
|
||||
rinv <noderange> [firm|bios|diag|mprom|sprom|mparom|mac|mtm [-t]]
|
||||
PPC specific(with HMC):
|
||||
rinv <noderange> [bus|config|serial|model|firm|all]
|
||||
rinv <noderange> [all|bus|config|serial|model|firm [-t]]
|
||||
PPC specific(using Direct FSP Management):
|
||||
rinv <noderange> [firm]
|
||||
rinv <noderange> [deconfig [-x]]
|
||||
Blade specific:
|
||||
rinv <noderange> [mtm|serial|mac|bios|diag|mprom|mparom|firm|all]
|
||||
rinv <noderange> [all|serial|mac|bios|diag|mprom|mparom|firm|mtm [-t]]
|
||||
IBM Flex System Compute Node specific:
|
||||
rinv <noderange> [firm]
|
||||
VMware specific:
|
||||
rinv <noderange>
|
||||
zVM specific:
|
||||
rinv noderange [all|config]",
|
||||
rinv noderange [all|config]
|
||||
MIC specific:
|
||||
rinv noderange [system|ver|board|core|gddr|all]",
|
||||
"rsetboot" =>
|
||||
"Usage: rsetboot <noderange> [net|hd|cd|floppy|def|stat] [-V|--verbose]
|
||||
rsetboot [-h|--help|-v|--version]",
|
||||
@@ -193,10 +199,15 @@ my %usage = (
|
||||
"Usage:
|
||||
Common:
|
||||
mkvm [-h|--help|-v|--version]
|
||||
For PPC(with HMC):
|
||||
For PPC(with HMC) specific:
|
||||
mkvm noderange -i id -l singlenode [-V|--verbose]
|
||||
mkvm noderange -c destcec -p profile [-V|--verbose]
|
||||
mkvm noderange --full [-V|--verbose]
|
||||
PPC (using Direct FSP Management) specific:
|
||||
mkvm noderange [--full]
|
||||
mkvm noderange [vmcpus=min/req/max] [vmmemory=min/req/max]
|
||||
[vmphyslots=drc_index1,drc_index2...] [vmothersetting=hugepage:N,bsr:N]
|
||||
[vmnics=vlan1,vlan2] [vmstorage=<N|viosnode:slotid>] [--vios]
|
||||
For KVM
|
||||
mkvm noderange -m|--master mastername -s|--size disksize -f|--force
|
||||
For zVM
|
||||
@@ -210,7 +221,8 @@ my %usage = (
|
||||
PPC (with HMC) specific:
|
||||
lsvm <noderange> [-a|--all]
|
||||
PPC (using Direct FSP Management) specific:
|
||||
lsvm <noderange> [-l|--long]
|
||||
lsvm <noderange> [-l|--long] --p775
|
||||
lsvm <noderange>
|
||||
zVM specific:
|
||||
lsvm noderange
|
||||
lsvm noderange --getnetworknames
|
||||
@@ -225,9 +237,13 @@ my %usage = (
|
||||
chvm <noderange> [-p profile][-V|--verbose]
|
||||
chvm <noderange> <attr>=<val> [<attr>=<val>...]
|
||||
PPC (using Direct FSP Management) specific:
|
||||
chvm <noderange> [-p <profile>]
|
||||
chvm <noderange> --p775 [-p <profile>]
|
||||
chvm <noderange> --p775 -i <id> [-m <memory_interleaving>] -r <partition_rule>
|
||||
chvm <noderange> [lparname=<*|name>]
|
||||
chvm <noderange> -i <id> [-m <memory_interleaving>] -r <partition_rule>
|
||||
chvm <noderange> [vmcpus=min/req/max] [vmmemory=min/req/max]
|
||||
[vmphyslots=drc_index1,drc_index2...] [vmothersetting=hugepage:N,bsr:N]
|
||||
[vmnics=vlan1,vlan2] [vmstorage=<N|viosnode:slotid>] [--vios]
|
||||
chvm <noderange> [del_vadapter=slotid]
|
||||
VMware specific:
|
||||
chvm <noderange> [-a size][-d disk][-p disk][--resize disk=size][--cpus count][--mem memory]
|
||||
zVM specific:
|
||||
@@ -258,11 +274,13 @@ my %usage = (
|
||||
"rmvm" =>
|
||||
"Usage: rmvm <noderange> [--service][-V|--verbose]
|
||||
rmvm [-h|--help|-v|--version],
|
||||
rmvm [-p] [-f]",
|
||||
rmvm [-p] [-f]
|
||||
PPC (using Direct FSP Management) specific:
|
||||
rmvm <noderange>",
|
||||
"lsslp" =>
|
||||
"Usage: lsslp [-h|--help|-v|--version]
|
||||
lsslp [<noderange>][-V|--verbose][-i ip[,ip..]][-w][-r|-x|-z][-n][-I][-s FRAME|CEC|MM|IVM|RSA|HMC|CMM]
|
||||
[-t tries][--vpdtable][-C counts][-T timeout][--flexdiscover]",
|
||||
lsslp [<noderange>][-V|--verbose][-i ip[,ip..]][-w][-r|-x|-z][-n][-I][-s FRAME|CEC|MM|IVM|RSA|HMC|CMM|IMM2|FSP]
|
||||
[-u] [--range IPranges][-t tries][--vpdtable][-C counts][-T timeout]",
|
||||
"rflash" =>
|
||||
"Usage:
|
||||
rflash [ -h|--help|-v|--version]
|
||||
@@ -317,17 +335,31 @@ my %usage = (
|
||||
renergy noderange [-V] { all | { [savingstatus] [dsavingstatus] [cappingstatus] [cappingmaxmin] [cappingvalue] [cappingsoftmin] [averageAC] [averageDC] [ambienttemp] [exhausttemp] [CPUspeed] [syssbpower] [sysIPLtime] [fsavingstatus] [ffoMin] [ffoVmin] [ffoTurbo] [ffoNorm] [ffovalue] } }
|
||||
renergy noderange [-V] { {savingstatus}={on | off} | {dsavingstatus}={on-norm | on-maxp | off} | {fsavingstatus}={on | off} | {ffovalue}=MHZ | {cappingstatus}={on | off} | {cappingwatt}=watt | {cappingperc}=percentage }
|
||||
|
||||
Blade specific :
|
||||
renergy noderange [-V] { all | pd1all | pd2all | { [pd1status] [pd2status] [pd1policy] [pd2policy] [pd1powermodule1] [pd1powermodule2] [pd2powermodule1] [pd2powermodule2] [pd1avaiablepower] [pd2avaiablepower] [pd1reservedpower] [pd2reservedpower] [pd1remainpower] [pd2remainpower] [pd1inusedpower] [pd2inusedpower] [availableDC] [averageAC] [thermaloutput] [ambienttemp] [mmtemp] } }
|
||||
renergy noderange [-V] { all | { [averageDC] [capability] [cappingvalue] [CPUspeed] [maxCPUspeed] [savingstatus] [dsavingstatus] } }
|
||||
renergy noderange [-V] { {savingstatus}={on | off} | {dsavingstatus}={on-norm | on-maxp | off} }",
|
||||
BladeCenter specific :
|
||||
For Management Modules:
|
||||
renergy noderange [-V] { all | pd1all | pd2all | [pd1status] [pd2status] [pd1policy] [pd2policy] [pd1powermodule1] [pd1powermodule2] [pd2powermodule1] [pd2powermodule2] [pd1avaiablepower] [pd2avaiablepower] [pd1reservedpower] [pd2reservedpower] [pd1remainpower] [pd2remainpower] [pd1inusedpower] [pd2inusedpower] [availableDC] [averageAC] [thermaloutput] [ambienttemp] [mmtemp] }
|
||||
For a blade server nodes:
|
||||
renergy noderange [-V] { all | [averageDC] [capability] [cappingvalue] [CPUspeed] [maxCPUspeed] [savingstatus] [dsavingstatus] }
|
||||
renergy noderange [-V] { savingstatus={on | off} | dsavingstatus={on-norm | on-maxp | off} }
|
||||
|
||||
Flex specific :
|
||||
For Flex Management Modules:
|
||||
renergy noderange [-V] { all | [powerstatus] [powerpolicy] [powermodule] [avaiablepower] [reservedpower] [remainpower] [inusedpower] [availableDC] [averageAC] [thermaloutput] [ambienttemp] [mmtemp] }
|
||||
|
||||
For Flex node (power and x86):
|
||||
renergy noderange [-V] { all | [averageDC] [capability] [cappingvalue] [cappingmaxmin] [cappingmax] [cappingmin] [cappingGmin] [CPUspeed] [maxCPUspeed] [savingstatus] [dsavingstatus] }
|
||||
renergy noderange [-V] { cappingstatus={on | off} | cappingwatt=watt | cappingperc=percentage | savingstatus={on | off} | dsavingstatus={on-norm | on-maxp | off} }
|
||||
|
||||
iDataPlex specific :
|
||||
renergy noderange [-V] [ { cappingmaxmin | cappingmax | cappingmin } ] [cappingstatus] [cappingvalue] [relhistogram]
|
||||
renergy noderange [-V] { cappingstatus={on | enable | off | disable} | {cappingwatt|cappingvalue}=watt }",
|
||||
"updatenode" =>
|
||||
"Usage:
|
||||
updatenode [-h|--help|-v|--version]
|
||||
updatenode [-h|--help|-v|--version | -g|--genmypost]
|
||||
or
|
||||
updatenode <noderange> [-V|--verbose] [-k|--security] [-s|--sn]
|
||||
updatenode <noderange> [-V|--verbose] [-k|--security] [-s|--sn] [-t <timeout>]
|
||||
or
|
||||
updatenode <noderange> [-V|--verbose] [-F|--sync | -f|--snsync] [-l|--user[username]] [-S|--sw]
|
||||
updatenode <noderange> [-V|--verbose] [-F|--sync | -f|--snsync] [-l|--user[username]] [--fanout=[fanout value]] [-S|--sw] [-t <timeout>]
|
||||
[-P|--scripts [script1,script2,...]] [-s|--sn]
|
||||
[-A|--updateallsw] [-c|--cmdlineonly] [-d alt_source_dir]
|
||||
[attr=val [attr=val...]]
|
||||
@@ -342,8 +374,15 @@ Options:
|
||||
|
||||
[-F|--sync] Perform File Syncing.
|
||||
|
||||
[--fanout] Allows you to assign the fanout value for the command.
|
||||
See xdsh/xdcp fanout parameter in the man page.
|
||||
|
||||
[-f|--snsync] Performs File Syncing to the service nodes that service
|
||||
the nodes in the noderange.
|
||||
|
||||
[-g|--genmypost] Will generate a new mypostscript file for the
|
||||
the nodes in the noderange, if site precreatemypostscripts is 1 or YES.
|
||||
|
||||
[-l|--user] User name to run the updatenode command. It overrides the
|
||||
current user which is the default.
|
||||
|
||||
@@ -357,6 +396,9 @@ Options:
|
||||
|
||||
[-s|--sn] Set the server information stored on the nodes.
|
||||
|
||||
[-t|--timeout] Time out in seconds to allow the command to run. Default is no timeout,
|
||||
except for updatenode -k which has a 10 second default timeout.
|
||||
|
||||
[-A|--updateallsw] Install or update all software contained in the source
|
||||
directory. (AIX only)
|
||||
|
||||
|
||||
+402
-31
@@ -21,10 +21,13 @@ use File::Path;
|
||||
use Socket;
|
||||
use strict;
|
||||
use Symbol;
|
||||
my $sha1support = eval {
|
||||
require Digest::SHA1;
|
||||
1;
|
||||
};
|
||||
my $sha1support;
|
||||
if ( -f "/etc/debian_version" ){
|
||||
$sha1support = eval {require Digest::SHA; 1;};
|
||||
}
|
||||
else {
|
||||
$sha1support = eval { require Digest::SHA1; 1;};
|
||||
}
|
||||
use IPC::Open3;
|
||||
use IO::Select;
|
||||
use xCAT::GlobalDef;
|
||||
@@ -117,6 +120,38 @@ This program module file, is a set of utilities used by xCAT commands.
|
||||
|
||||
#-------------------------------------------------------------
|
||||
|
||||
=head3 clroptionvars
|
||||
|
||||
- use this routine to clear GetOptions global option variables
|
||||
before calling GetOptions.
|
||||
|
||||
- this may be needed because a "command" may be called twice
|
||||
from the same process - and global options may have been
|
||||
set the first time through. (ex. from a plugin using runxcmd() )
|
||||
|
||||
- should really avoid global vars but this provides a quick fix
|
||||
for now
|
||||
|
||||
ex. my $rc = xCAT::Utils->clroptionvars($::opt1, $::opt2 ...)
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub clroptionvars
|
||||
{
|
||||
# skip the class arg and set the rest to undef
|
||||
my $skippedclass=0;
|
||||
foreach (@_) {
|
||||
if ($skippedclass) {
|
||||
$_ = undef;
|
||||
}
|
||||
$skippedclass=1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------
|
||||
|
||||
=head3 genUUID
|
||||
Returns an RFC 4122 compliant UUIDv4 or UUIDv1
|
||||
Arguments:
|
||||
@@ -176,7 +211,13 @@ sub genUUID
|
||||
return $uuid;
|
||||
} elsif ($args{url} and $sha1support) { #generate a UUIDv5 from URL
|
||||
#6ba7b810-9dad-11d1-80b4-00c04fd430c8 is the uuid for URL namespace
|
||||
my $sum = Digest::SHA1::sha1('6ba7b810-9dad-11d1-80b4-00c04fd430c8'.$args{url});
|
||||
my $sum = '';
|
||||
if ( -f "/etc/debian_version" ){
|
||||
$sum = Digest::SHA::sha1('6ba7b810-9dad-11d1-80b4-00c04fd430c8'.$args{url});
|
||||
}
|
||||
else{
|
||||
$sum = Digest::SHA1::sha1('6ba7b810-9dad-11d1-80b4-00c04fd430c8'.$args{url});
|
||||
}
|
||||
my @data = unpack("C*",$sum);
|
||||
splice @data,16;
|
||||
$data[6] = $data[6] & 0xf;
|
||||
@@ -936,13 +977,9 @@ sub runcmd
|
||||
if ($::VERBOSE)
|
||||
{
|
||||
# get this systems name as known by xCAT management node
|
||||
my $Sname = xCAT::InstUtils->myxCATname();
|
||||
my $msg;
|
||||
if ($Sname) {
|
||||
$msg = "Running command on $Sname: $cmd";
|
||||
} else {
|
||||
$msg="Running command: $cmd";
|
||||
}
|
||||
my $hostname = `/bin/hostname`;
|
||||
chomp $hostname;
|
||||
my $msg="Running command on $hostname: $cmd";
|
||||
|
||||
if ($::CALLBACK){
|
||||
my $rsp = {};
|
||||
@@ -1307,6 +1344,10 @@ sub runxcmd_output
|
||||
{
|
||||
push @$::xcmd_outref, @{$resp->{data}};
|
||||
}
|
||||
if (defined($resp->{status}))
|
||||
{
|
||||
push @$::xcmd_outref, @{$resp->{status}};
|
||||
}
|
||||
if (defined($resp->{node}))
|
||||
{
|
||||
my $node = $resp->{node}->[0];
|
||||
@@ -1334,7 +1375,6 @@ sub runxcmd_output
|
||||
if (defined($resp->{error}))
|
||||
{
|
||||
push @$::xcmd_outref, @{$resp->{error}};
|
||||
$::RUNCMD_RC = 1;
|
||||
}
|
||||
if (defined($resp->{errorcode}))
|
||||
{
|
||||
@@ -1379,6 +1419,10 @@ sub runxcmd_output2
|
||||
{
|
||||
push @{$::xcmd_outref_hash->{data}}, @{$resp->{data}};
|
||||
}
|
||||
if (defined($resp->{status}))
|
||||
{
|
||||
push @{$::xcmd_outref_hash->{status}}, @{$resp->{status}};
|
||||
}
|
||||
if (defined($resp->{node}))
|
||||
{
|
||||
push @{$::xcmd_outref_hash->{node}}, @{$resp->{node}};
|
||||
@@ -1386,7 +1430,6 @@ sub runxcmd_output2
|
||||
if (defined($resp->{error}))
|
||||
{
|
||||
push @{$::xcmd_outref_hash->{error}}, @{$resp->{error}};
|
||||
$::RUNCMD_RC = 1;
|
||||
}
|
||||
if (defined($resp->{errorcode}))
|
||||
{
|
||||
@@ -2068,7 +2111,8 @@ sub CheckVersion
|
||||
=head3 osver
|
||||
Returns the os and version of the System you are running on
|
||||
Arguments:
|
||||
none
|
||||
$type: which type of os infor you want. Supported values are:
|
||||
all,os,version,release
|
||||
Returns:
|
||||
0 - ok
|
||||
Globals:
|
||||
@@ -2085,9 +2129,16 @@ sub CheckVersion
|
||||
#-------------------------------------------------------------------------------
|
||||
sub osver
|
||||
{
|
||||
my $type = shift;
|
||||
if ($type =~ /xCAT::Utils/)
|
||||
{
|
||||
$type = shift;
|
||||
}
|
||||
|
||||
my $osver = "unknown";
|
||||
my $os = '';
|
||||
my $ver = '';
|
||||
my $rel = '';
|
||||
my $line = '';
|
||||
my @lines;
|
||||
my $relfile;
|
||||
@@ -2098,14 +2149,31 @@ sub osver
|
||||
close($relfile);
|
||||
chomp($line);
|
||||
$os = "rh";
|
||||
my $verrel=$line;
|
||||
$ver=$line;
|
||||
$ver=~ tr/\.//;
|
||||
$ver =~ s/[^0-9]*([0-9]+).*/$1/;
|
||||
if ( $type ) {
|
||||
$verrel =~ s/[^0-9]*([0-9.]+).*/$1/;
|
||||
($ver,$rel) = split /\./, $verrel;
|
||||
} else {
|
||||
$ver=~ tr/\.//;
|
||||
$ver =~ s/[^0-9]*([0-9]+).*/$1/;
|
||||
}
|
||||
if ($line =~ /AS/) { $os = 'rhas' }
|
||||
elsif ($line =~ /ES/) { $os = 'rhes' }
|
||||
elsif ($line =~ /WS/) { $os = 'rhws' }
|
||||
elsif ($line =~ /Server/) { $os = 'rhserver' }
|
||||
elsif ($line =~ /Client/) { $os = 'rhclient' }
|
||||
elsif ($line =~ /Server/) {
|
||||
if ( $type ) {
|
||||
$os = 'rhels';
|
||||
} else {
|
||||
$os = 'rhserver';
|
||||
}
|
||||
} elsif ($line =~ /Client/) {
|
||||
if ( $type ) {
|
||||
$os = 'rhel';
|
||||
} else {
|
||||
$os = 'rhclient';
|
||||
}
|
||||
}
|
||||
elsif (-f "/etc/fedora-release") { $os = 'rhfc' }
|
||||
}
|
||||
elsif (-f "/etc/SuSE-release")
|
||||
@@ -2120,6 +2188,10 @@ sub osver
|
||||
$ver =~ tr/\.//;
|
||||
$ver =~ s/[^0-9]*([0-9]+).*/$1/;
|
||||
|
||||
$rel = $lines[2];
|
||||
$ver =~ tr/\.//;
|
||||
$rel =~ s/[^0-9]*([0-9]+).*/$1/;
|
||||
|
||||
#print "ver: $ver\n";
|
||||
}
|
||||
elsif (-f "/etc/UnitedLinux-release")
|
||||
@@ -2177,8 +2249,21 @@ sub osver
|
||||
close($relfile);
|
||||
}
|
||||
}
|
||||
$os = "$os" . "$ver";
|
||||
return ($os);
|
||||
if ( $type and $type =~ /all/ ) {
|
||||
if ( $rel ) {
|
||||
return( "$os" . "," . "$ver" . ".$rel" );
|
||||
} else {
|
||||
return( "$os" . "," . "$ver" );
|
||||
}
|
||||
} elsif ( $type and $type =~ /os/ ) {
|
||||
return( $os );
|
||||
} elsif ( $type and $type =~ /version/ ) {
|
||||
return( $ver );
|
||||
} elsif ( $type and $type =~ /release/ ) {
|
||||
return( $rel );
|
||||
} else {
|
||||
return ("$os" . "$ver");
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -3085,7 +3170,7 @@ sub isSELINUX
|
||||
Input:
|
||||
array of nodes in the noderange
|
||||
Example:
|
||||
my $mn=xCAT::Utils->noderangecontainsMN($noderange);
|
||||
my @mn=xCAT::Utils->noderangecontainsMN($noderange);
|
||||
Comments:
|
||||
=cut
|
||||
|
||||
@@ -3094,26 +3179,312 @@ sub noderangecontainsMn
|
||||
{
|
||||
my ($class, @noderange)=@_;
|
||||
# check if any node in the noderange is the Management Node return the
|
||||
# name
|
||||
my $mname;
|
||||
# name
|
||||
my @mnames; # management node names in the database, members of __mgmtnode
|
||||
my $tab = xCAT::Table->new('nodelist');
|
||||
my @nodelist=$tab->getAllNodeAttribs(['node','groups']);
|
||||
foreach my $n (@nodelist) {
|
||||
if (defined($n->{'groups'})) {
|
||||
my @groups=split(",",$n->{'groups'});
|
||||
if ((grep (/__mgmtnode/,@groups))) { # this is the MN
|
||||
$mname=$n->{'node'};
|
||||
last;
|
||||
push @mnames,$n->{'node'};
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($mname) { # if Management Node defined in the database
|
||||
if (grep(/$mname/, @noderange)) { # if MN in the noderange
|
||||
return $mname;
|
||||
} else {
|
||||
return ;
|
||||
my @MNs; # management node names found the noderange
|
||||
if (@mnames) { # if any Management Node defined in the database
|
||||
foreach my $mn (@mnames) {
|
||||
if (grep(/^$mn$/, @noderange)) { # if MN in the noderange
|
||||
push @MNs, $mn;
|
||||
}
|
||||
}
|
||||
if (@MNs) { # management nodes in the noderange
|
||||
return @MNs;
|
||||
}
|
||||
}
|
||||
return; # if no MN in the noderange, return nothing
|
||||
}
|
||||
|
||||
=head3 filter_nodes
|
||||
##########################################################################
|
||||
# Fliter the nodes to specific groups
|
||||
# For specific command, figure out the node lists which should be handled by blade.pm, fsp.pm or ipmi.pm
|
||||
# mp group: the nodes will be handled by blade.pm
|
||||
# fsp group: the nodes will be handled by fsp.pm
|
||||
# bmc group: the nodes will be handled by ipmi.pm
|
||||
# For rspconfig network, the NGP ppc blade will be included in the group of mp, othewise in the fsp group
|
||||
# For getmacs -D, the NGP ppc blade will be included in the group of common fsp, otherwise in the mp group
|
||||
# For renergy command, NGP blade will be moved to mp group
|
||||
##########################################################################
|
||||
=cut
|
||||
|
||||
sub filter_nodes{
|
||||
my ($class, $req, $mpnodes, $fspnodes, $bmcnodes, $nohandle) = @_;
|
||||
|
||||
my (@nodes,@args,$cmd);
|
||||
if (defined($req->{'node'})) {
|
||||
@nodes = @{$req->{'node'}};
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
if (defined($req->{'command'})) {
|
||||
$cmd = $req->{'command'}->[0];
|
||||
}
|
||||
if (defined($req->{'arg'})) {
|
||||
@args = @{$req->{'arg'}};
|
||||
}
|
||||
# get the nodes in the mp table
|
||||
my $mptabhash;
|
||||
my $mptab = xCAT::Table->new("mp");
|
||||
if ($mptab) {
|
||||
$mptabhash = $mptab->getNodesAttribs(\@nodes, ['mpa','nodetype']);
|
||||
}
|
||||
|
||||
# get the nodes in the ppc table
|
||||
my $ppctabhash;
|
||||
my $ppctab = xCAT::Table->new("ppc");
|
||||
if ($ppctab) {
|
||||
$ppctabhash = $ppctab->getNodesAttribs(\@nodes,['hcp']);
|
||||
}
|
||||
|
||||
# get the nodes in the ipmi table
|
||||
my $ipmitabhash;
|
||||
my $ipmitab = xCAT::Table->new("ipmi");
|
||||
if ($ipmitab) {
|
||||
$ipmitabhash = $ipmitab->getNodesAttribs(\@nodes,['bmc']);
|
||||
}
|
||||
my $nodehmhash;
|
||||
my $nodehmtab = xCAT::Table->new("nodehm");
|
||||
if ($nodehmtab) {
|
||||
$nodehmhash = $nodehmtab->getNodesAttribs(\@nodes,['mgt']);
|
||||
}
|
||||
|
||||
my (@mp, @ngpfsp, @ngpbmc, @commonfsp, @commonbmc, @unknow);
|
||||
|
||||
# if existing in both 'mpa' and 'ppc', a ngp power blade
|
||||
# if existing in both 'mpa' and 'ipmi', a ngp x86 blade
|
||||
# if only in 'ppc', a common power node
|
||||
# if only in 'ipmi', a common x86 node
|
||||
foreach (@nodes) {
|
||||
if (defined ($mptabhash->{$_}->[0]) && defined ($mptabhash->{$_}->[0]->{'mpa'})) {
|
||||
if ($mptabhash->{$_}->[0]->{'mpa'} eq $_) {
|
||||
if (defined($nodehmhash->{$_}->[0]) && defined($nodehmhash->{$_}->[0]->{'mgt'}) &&
|
||||
$nodehmhash->{$_}->[0]->{'mgt'} eq "blade") {
|
||||
push @mp, $_;
|
||||
} else {
|
||||
push @unknow, $_;
|
||||
}
|
||||
next;
|
||||
}
|
||||
if (defined ($ppctabhash->{$_}->[0]) && defined ($ppctabhash->{$_}->[0]->{'hcp'})) {
|
||||
# flex power node
|
||||
push @ngpfsp, $_;
|
||||
next;
|
||||
} elsif (defined ($ipmitabhash->{$_}->[0]) && defined ($ipmitabhash->{$_}->[0]->{'bmc'})) {
|
||||
# flex x86 node
|
||||
push @ngpbmc, $_;
|
||||
next;
|
||||
}
|
||||
else {
|
||||
# Non flex blade, but blade node
|
||||
push @mp, $_;
|
||||
next;
|
||||
}
|
||||
} elsif (defined ($ppctabhash->{$_}->[0]) && defined ($ppctabhash->{$_}->[0]->{'hcp'})) {
|
||||
# common power node
|
||||
push @commonfsp, $_;
|
||||
} elsif (defined ($ipmitabhash->{$_}->[0]) && defined ($ipmitabhash->{$_}->[0]->{'bmc'})) {
|
||||
# common bmc node
|
||||
push @commonbmc, $_;
|
||||
} else {
|
||||
push @unknow, $_;
|
||||
}
|
||||
}
|
||||
|
||||
push @{$mpnodes}, @mp;#blade.pm
|
||||
push @{$fspnodes}, @commonfsp;
|
||||
push @{$bmcnodes}, @commonbmc;
|
||||
if (@args && ($cmd eq "rspconfig")) {
|
||||
if (!(grep /^(cec_off_policy|pending_power_on_side)/, @args)) {
|
||||
push @{$mpnodes}, @ngpfsp;
|
||||
} else {
|
||||
push @{$fspnodes}, @ngpfsp;
|
||||
}
|
||||
if (grep /^(network|textid)/, @args) {
|
||||
push @{$mpnodes}, @ngpbmc;
|
||||
} else {
|
||||
push @{$bmcnodes}, @ngpbmc;
|
||||
}
|
||||
} elsif($cmd eq "getmacs") {
|
||||
if (@args && (grep /^-D$/,@args)) {
|
||||
push @{$fspnodes}, @ngpfsp;
|
||||
} else {
|
||||
push @{$mpnodes}, @ngpfsp;
|
||||
}
|
||||
push @{$mpnodes}, @ngpbmc;
|
||||
} elsif ($cmd eq "rvitals") {
|
||||
if (@args && (grep /^lcds$/,@args)) {
|
||||
push @{$fspnodes},@ngpfsp;
|
||||
} else {
|
||||
push @{$mpnodes}, @ngpfsp;
|
||||
}
|
||||
} elsif ($cmd eq "renergy") {
|
||||
if (grep /^(relhistogram)/, @args) {
|
||||
push @{$bmcnodes}, @ngpbmc;
|
||||
} else {
|
||||
push @{$mpnodes}, @ngpbmc;
|
||||
}
|
||||
push @{$mpnodes}, @ngpfsp;
|
||||
} else {
|
||||
push @{$fspnodes}, @ngpfsp;
|
||||
}
|
||||
|
||||
push @{$nohandle}, @unknow;
|
||||
|
||||
## TRACE_LINE print "Nodes filter: nodetype [commp:@mp,ngpp:@ngpfsp,comfsp:@commonfsp]. mpnodes [@{$mpnodes}], fspnodes [@{$fspnodes}], bmcnodes [@{$bmcnodes}]\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
=head3 filter_nostatusupdate()
|
||||
|
||||
filter out the nodes which support provision status feedback from the status-nodes hash
|
||||
Returns:
|
||||
returns the filtered status-nodes hash
|
||||
Globals:
|
||||
none
|
||||
Error:
|
||||
none
|
||||
Input:
|
||||
the ref of status-nodes hash to filter
|
||||
Example:
|
||||
my $mn=xCAT::Utils->filter_nostatusupdate(\%statusnodehash);
|
||||
Comments:
|
||||
=cut
|
||||
#-------------------------------------------------------------------------------
|
||||
sub filter_nostatusupdate{
|
||||
|
||||
my ($class,$inref)=@_;
|
||||
my $nttabdata;
|
||||
my @allnodes=();
|
||||
#read "nodetype" table to get the "os" attribs for all the nodes with status "installing" or "netbooting"
|
||||
if(exists $inref->{$::STATUS_INSTALLING}){
|
||||
push @allnodes, @{$inref->{$::STATUS_INSTALLING}};
|
||||
}
|
||||
if(exists $inref->{$::STATUS_NETBOOTING}){
|
||||
push @allnodes, @{$inref->{$::STATUS_NETBOOTING}};
|
||||
}
|
||||
|
||||
my $nodetypetab = xCAT::Table->new('nodetype');
|
||||
if ($nodetypetab) {
|
||||
$nttabdata = $nodetypetab->getNodesAttribs(\@allnodes, ['node', 'os']);
|
||||
$nodetypetab->close();
|
||||
}
|
||||
|
||||
#filter out the nodes which support the node provision status feedback
|
||||
my @nodesfiltered=();
|
||||
if(exists $inref->{$::STATUS_INSTALLING}){
|
||||
map{ if($nttabdata->{$_}->[0]->{os} !~ /(fedora|rh|centos|sles|ubuntu)/) {push @nodesfiltered,$_;} } @{$inref->{$::STATUS_INSTALLING}};
|
||||
delete $inref->{$::STATUS_INSTALLING};
|
||||
if(@nodesfiltered){
|
||||
@{$inref->{$::STATUS_INSTALLING}}=@nodesfiltered;
|
||||
}
|
||||
}
|
||||
|
||||
@nodesfiltered=();
|
||||
if(exists $inref->{$::STATUS_NETBOOTING}){
|
||||
map{ if($nttabdata->{$_}->[0]->{os} !~ /(fedora|rh|centos|sles|ubuntu)/) {push @nodesfiltered,$_;} } @{$inref->{$::STATUS_NETBOOTING}};
|
||||
delete $inref->{$::STATUS_NETBOOTING};
|
||||
if(@nodesfiltered){
|
||||
@{$inref->{$::STATUS_NETBOOTING}}=@nodesfiltered;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub version_cmp {
|
||||
my $ver_a = shift;
|
||||
if ($ver_a =~ /xCAT::Utils/)
|
||||
{
|
||||
$ver_a = shift;
|
||||
}
|
||||
my $ver_b = shift;
|
||||
my @array_a = ($ver_a =~ /([-.]|\d+|[^-.\d]+)/g);
|
||||
my @array_b = ($ver_b =~ /([-.]|\d+|[^-.\d]+)/g);
|
||||
|
||||
my ($a, $b);
|
||||
my $len_a = @array_a;
|
||||
my $len_b = @array_b;
|
||||
my $len = $len_a;
|
||||
if ( $len_b < $len_a ) {
|
||||
$len = $len_b;
|
||||
}
|
||||
for ( my $i = 0; $i < $len; $i++ ) {
|
||||
$a = $array_a[$i];
|
||||
$b = $array_b[$i];
|
||||
if ($a eq $b) {
|
||||
next;
|
||||
} elsif ( $a eq '-' ) {
|
||||
return -1;
|
||||
} elsif ( $b eq '-') {
|
||||
return 1;
|
||||
} elsif ( $a eq '.' ) {
|
||||
return -1;
|
||||
} elsif ( $b eq '.' ) {
|
||||
return 1;
|
||||
} elsif ($a =~ /^\d+$/ and $b =~ /^\d+$/) {
|
||||
if ($a =~ /^0/ || $b =~ /^0/) {
|
||||
return ($a cmp $b);
|
||||
} else {
|
||||
return ($a <=> $b);
|
||||
}
|
||||
} else {
|
||||
$a = uc $a;
|
||||
$b = uc $b;
|
||||
return ($a cmp $b);
|
||||
}
|
||||
}
|
||||
return ( $len_a <=> $len_b )
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
=head3 fullpathbin
|
||||
returns the full path of a specified binary executable file
|
||||
Arguments:
|
||||
string of the bin file name
|
||||
Returns:
|
||||
string of the full path name of the binary executable file
|
||||
Globals:
|
||||
none
|
||||
Error:
|
||||
string of the bin file name in the argument
|
||||
Example:
|
||||
my $CHKCONFIG = xCAT::Utils->fullpathbin("chkconfig");
|
||||
Comments:
|
||||
none
|
||||
|
||||
=cut
|
||||
#--------------------------------------------------------------------------------
|
||||
sub fullpathbin
|
||||
{
|
||||
my $bin=shift;
|
||||
if( $bin =~ /xCAT::Utils/)
|
||||
{
|
||||
$bin=shift;
|
||||
}
|
||||
|
||||
my @paths= ("/bin","/usr/bin","/sbin","/usr/sbin");
|
||||
my $fullpath=$bin;
|
||||
|
||||
foreach my $path (@paths)
|
||||
{
|
||||
if (-x $path.'/'.$bin)
|
||||
{
|
||||
$fullpath= $path.'/'.$bin;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $fullpath;
|
||||
}
|
||||
1;
|
||||
|
||||
@@ -26,7 +26,7 @@ sub grab_table_data{ #grab table data relevent to VM guest nodes
|
||||
if ($vpdtab) {
|
||||
$cfghash->{vpd} = $vpdtab->getNodesAttribs($noderange,['uuid']);
|
||||
}
|
||||
$cfghash->{vm} = $vmtab->getNodesAttribs($noderange,['node','host','migrationdest','cfgstore','storage','vidmodel','vidproto','vidpassword','storagemodel','memory','cpus','nics','nicmodel','bootorder','virtflags','datacenter','guestostype','othersettings','master']);
|
||||
$cfghash->{vm} = $vmtab->getNodesAttribs($noderange,['node','host','migrationdest','cfgstore','storage','storagecache','storageformat','vidmodel','vidproto','vidpassword','storagemodel','memory','cpus','nics','nicmodel','bootorder','virtflags','datacenter','guestostype','othersettings','master']);
|
||||
my $mactab = xCAT::Table->new("mac",-create=>1);
|
||||
my $nrtab= xCAT::Table->new("noderes",-create=>1);
|
||||
$cfghash->{mac} = $mactab->getAllNodeAttribs(['mac'],1);
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
#!/usr/bin/env perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
package xCAT::Zone;
|
||||
|
||||
BEGIN
|
||||
{
|
||||
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
||||
}
|
||||
|
||||
# if AIX - make sure we include perl 5.8.2 in INC path.
|
||||
# Needed to find perl dependencies shipped in deps tarball.
|
||||
if ($^O =~ /^aix/i) {
|
||||
unshift(@INC, qw(/usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2));
|
||||
}
|
||||
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
# do not put a use or require for xCAT::Table here. Add to each new routine
|
||||
# needing it to avoid reprocessing of user tables ( ExtTab.pm) for each command call
|
||||
use POSIX qw(ceil);
|
||||
use File::Path;
|
||||
use Socket;
|
||||
use strict;
|
||||
use Symbol;
|
||||
use warnings "all";
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head1 xCAT::Zone
|
||||
|
||||
=head2 Package Description
|
||||
|
||||
This program module file, is a set of Zone utilities used by xCAT *zone commands.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 genSSHRootKeys
|
||||
Arguments:
|
||||
callback for error messages
|
||||
directory in which to put the ssh RSA keys
|
||||
zonename
|
||||
rsa private key to use for generation ( optional)
|
||||
Returns:
|
||||
Error: 1 - key generation failure.
|
||||
Example:
|
||||
$rc =xCAT::Zone->genSSHRootKeys($callback,$keydir,$rsakey);
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub genSSHRootKeys
|
||||
{
|
||||
my ($class, $callback, $keydir,$zonename,$rsakey) = @_;
|
||||
|
||||
#
|
||||
# create /keydir if needed
|
||||
#
|
||||
if (!-d $keydir)
|
||||
{
|
||||
my $cmd = "/bin/mkdir -m 700 -p $keydir";
|
||||
my $output = xCAT::Utils->runcmd("$cmd", 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"Could not create $keydir directory";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#need to gen a new rsa key for root for the zone
|
||||
my $pubfile = "$keydir/id_rsa.pub";
|
||||
my $pvtfile = "$keydir/id_rsa";
|
||||
|
||||
# if exists, remove the old files
|
||||
if (-r $pubfile)
|
||||
{
|
||||
|
||||
my $cmd = "/bin/rm $keydir/id_rsa*";
|
||||
my $output = xCAT::Utils->runcmd("$cmd", 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] = "Could not remove id_rsa files from $keydir directory.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# gen new RSA keys
|
||||
my $cmd;
|
||||
my $output;
|
||||
# if private key was input use it
|
||||
if (defined ($rsakey)) {
|
||||
$cmd="/usr/bin/ssh-keygen -y -f $rsakey > $pubfile";
|
||||
$output = xCAT::Utils->runcmd("$cmd", 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] = "Could not generate $pubfile from $rsakey";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
# now copy the private key into the directory
|
||||
$cmd="cp $rsakey $keydir";
|
||||
$output = xCAT::Utils->runcmd("$cmd", 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] = "Could not run $cmd";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
} else { # generate all new keys
|
||||
$cmd = "/usr/bin/ssh-keygen -t rsa -q -b 2048 -N '' -f $pvtfile";
|
||||
$output = xCAT::Utils->runcmd("$cmd", 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] = "Could not generate $pubfile";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#make sure permissions are correct
|
||||
$cmd = "chmod 644 $pubfile;chown root $pubfile";
|
||||
$output = xCAT::Utils->runcmd("$cmd", 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] = "Could set permission and owner on $pubfile";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 getdefaultzone
|
||||
Arguments:
|
||||
None
|
||||
Returns:
|
||||
Name of the current default zone from the zone table
|
||||
Example:
|
||||
my $defaultzone =xCAT::Zone->getdefaultzone($callback);
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub getdefaultzone
|
||||
{
|
||||
my ($class, $callback) = @_;
|
||||
my $defaultzone;
|
||||
# read all the zone table and find the defaultzone, if it exists
|
||||
my $tab = xCAT::Table->new("zone");
|
||||
if ($tab){
|
||||
my @zones = $tab->getAllAttribs('zonename','defaultzone');
|
||||
foreach my $zone (@zones) {
|
||||
# Look for the defaultzone=yes/1 entry
|
||||
if ((defined($zone->{defaultzone})) &&
|
||||
(($zone->{defaultzone} =~ /^yes$/i )
|
||||
|| ($zone->{defaultzone} eq "1"))) {
|
||||
$defaultzone = $zone->{zonename};
|
||||
}
|
||||
$tab->close();
|
||||
}
|
||||
} else {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"Error reading the zone table. ";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
|
||||
}
|
||||
return $defaultzone;
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 iszonedefined
|
||||
Arguments:
|
||||
zonename
|
||||
Returns:
|
||||
1 if the zone is already in the zone table.
|
||||
Example:
|
||||
xCAT::Zone->iszonedefined($zonename);
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub iszonedefined
|
||||
{
|
||||
my ($class,$zonename) = @_;
|
||||
# checks the zone table to see if input zonename already in the table
|
||||
my $tab = xCAT::Table->new("zone");
|
||||
$tab->close();
|
||||
my $zonehash = $tab->getAttribs({zonename => $zonename},'sshkeydir');
|
||||
if ( keys %$zonehash) {
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 getzonekeydir
|
||||
Arguments:
|
||||
zonename
|
||||
Returns:
|
||||
path to the root ssh keys for the zone /etc/xcat/sshkeys/<zonename>/.ssh
|
||||
1 - zone not defined
|
||||
Example:
|
||||
xCAT::Zone->getzonekeydir($zonename);
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub getzonekeydir
|
||||
{
|
||||
my ($class,$zonename) = @_;
|
||||
my $tab = xCAT::Table->new("zone");
|
||||
$tab->close();
|
||||
my $zonehash = $tab->getAttribs({zonename => $zonename},'sshkeydir');
|
||||
if ( keys %$zonehash) {
|
||||
my $zonesshkeydir=$zonehash->{sshkeydir};
|
||||
return $zonesshkeydir;
|
||||
}else{
|
||||
return 1; # this is a bad error zone not defined
|
||||
}
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 getmyzonename
|
||||
Arguments:
|
||||
$node -one nodename
|
||||
Returns:
|
||||
$zonename
|
||||
Example:
|
||||
my $zonename=xCAT::Zone->getmyzonename($node);
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub getmyzonename
|
||||
{
|
||||
my ($class,$node,$callback) = @_;
|
||||
my @node;
|
||||
push @node,$node;
|
||||
my $zonename;
|
||||
my $nodelisttab = xCAT::Table->new("nodelist");
|
||||
my $nodehash = $nodelisttab->getNodesAttribs(\@node, ['zonename']);
|
||||
$nodelisttab->close();
|
||||
if ( defined ($nodehash->{$node}->[0]->{zonename})) { # it was defined in the nodelist table
|
||||
$zonename=$nodehash->{$node}->[0]->{zonename};
|
||||
} else { # get the default zone
|
||||
$zonename =xCAT::Zone->getdefaultzone($callback);
|
||||
}
|
||||
return $zonename;
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 enableSSHbetweennodes
|
||||
Arguments:
|
||||
zonename
|
||||
Returns:
|
||||
1 if the sshbetweennodes attribute is yes/1 or undefined
|
||||
0 if the sshbetweennodes attribute is no/0
|
||||
Example:
|
||||
xCAT::Zone->enableSSHbetweennodes($zonename);
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub enableSSHbetweennodes
|
||||
{
|
||||
my ($class,$node,$callback) = @_;
|
||||
# finds the zone of the node
|
||||
my $enablessh = 1; # default
|
||||
my $zonename=xCAT::Zone->getmyzonename($node);
|
||||
# reads the zone table
|
||||
my $tab = xCAT::Table->new("zone");
|
||||
$tab->close();
|
||||
# read both keys, want to know zone is in the zone table. If sshkeydir is not there
|
||||
# it is either missing or invalid anyway
|
||||
my $zonehash = $tab->getAttribs({zonename => $zonename},'sshbetweennodes','sshkeydir');
|
||||
if (! ( keys %$zonehash)) {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"$node has a zonename: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone. The generated mypostscript may not reflect the correct setting for ENABLESSHBETWEENNODES";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return $enablessh;
|
||||
}
|
||||
my $sshbetweennodes=$zonehash->{sshbetweennodes};
|
||||
if (defined ($sshbetweennodes)) {
|
||||
if (($sshbetweennodes =~ /^no$/i) || ($sshbetweennodes eq "0")) {
|
||||
$enablessh = 0;
|
||||
} else {
|
||||
$enablessh = 1;
|
||||
}
|
||||
} else { # not defined default yes
|
||||
$enablessh = 1 ; # default
|
||||
}
|
||||
return $enablessh;
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 usingzones
|
||||
Arguments:
|
||||
none
|
||||
Returns:
|
||||
1 if the zone table is not empty
|
||||
0 if empty
|
||||
Example:
|
||||
xCAT::Zone->usingzones;
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub usingzones
|
||||
{
|
||||
my ($class) = @_;
|
||||
# reads the zonetable
|
||||
my $tab = xCAT::Table->new("zone");
|
||||
my @zone = $tab->getAllAttribs('zonename');
|
||||
$tab->close();
|
||||
if (@zone) {
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 getzoneinfo
|
||||
Arguments:
|
||||
callback
|
||||
An array of nodes
|
||||
Returns:
|
||||
Hash array by zonename point to the nodes in that zonename and sshkeydir
|
||||
<zonename1> -> {nodelist} -> array of nodes in the zone
|
||||
-> {sshkeydir} -> directory containing ssh RSA keys
|
||||
-> {defaultzone} -> is it the default zone
|
||||
Example:
|
||||
my %zonehash =xCAT::Zone->getzoneinfo($callback,@nodearray);
|
||||
Rules:
|
||||
If the nodes nodelist.zonename attribute is a zonename, it is assigned to that zone
|
||||
If the nodes nodelist.zonename attribute is undefined:
|
||||
If there is a defaultzone in the zone table, the node is assigned to that zone
|
||||
If there is no defaultzone in the zone table, the node is assigned to the ~.ssh keydir
|
||||
$::GETZONEINFO_RC
|
||||
0 = good return
|
||||
1 = error occured
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub getzoneinfo
|
||||
{
|
||||
my ($class, $callback,$nodes) = @_;
|
||||
$::GETZONEINFO_RC=0;
|
||||
my $zonehash;
|
||||
my $defaultzone;
|
||||
# read all the zone table
|
||||
my $zonetab = xCAT::Table->new("zone");
|
||||
my @zones;
|
||||
if ($zonetab){
|
||||
@zones = $zonetab->getAllAttribs('zonename','sshkeydir','sshbetweennodes','defaultzone');
|
||||
$zonetab->close();
|
||||
if (@zones) {
|
||||
foreach my $zone (@zones) {
|
||||
my $zonename=$zone->{zonename};
|
||||
$zonehash->{$zonename}->{sshkeydir}= $zone->{sshkeydir};
|
||||
$zonehash->{$zonename}->{defaultzone}= $zone->{defaultzone};
|
||||
$zonehash->{$zonename}->{sshbetweennodes}= $zone->{sshbetweennodes};
|
||||
# find the defaultzone
|
||||
if ((defined($zone->{defaultzone})) &&
|
||||
(($zone->{defaultzone} =~ /^yes$/i )
|
||||
|| ($zone->{defaultzone} eq "1"))) {
|
||||
$defaultzone = $zone->{zonename};
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"Error reading the zone table. ";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
$::GETZONEINFO_RC =1;
|
||||
return;
|
||||
|
||||
}
|
||||
my $nodelisttab = xCAT::Table->new("nodelist");
|
||||
my $nodehash = $nodelisttab->getNodesAttribs(\@$nodes, ['zonename']);
|
||||
# for each of the nodes, look up it's zone name and assign to the zonehash
|
||||
# If the nodes nodelist.zonename attribute is a zonename, it is assigned to that zone
|
||||
# If the nodes nodelist.zonename attribute is undefined:
|
||||
# If there is a defaultzone in the zone table, the node is assigned to that zone
|
||||
# If there is no defaultzone error out
|
||||
|
||||
|
||||
foreach my $node (@$nodes) {
|
||||
my $zonename;
|
||||
$zonename=$nodehash->{$node}->[0]->{zonename};
|
||||
if (defined($zonename)) { # zonename explicitly defined in nodelist.zonename
|
||||
# check to see if defined in the zone table
|
||||
unless ( xCAT::Zone->iszonedefined($zonename)) {
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"$node has a zonename: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
$::GETZONEINFO_RC =1;
|
||||
return;
|
||||
}
|
||||
push @{$zonehash->{$zonename}->{nodes}},$node;
|
||||
} else { # no explict zonename
|
||||
if (defined ($defaultzone)) { # there is a default zone in the zone table, use it
|
||||
push @{$zonehash->{$defaultzone}->{nodes}},$node;
|
||||
} else { # if no default, this is an error
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
"There is no default zone defined in the zone table. There must be exactly one default zone. ";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
$::GETZONEINFO_RC =1;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return $zonehash;
|
||||
}
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 getnodesinzone
|
||||
Arguments:
|
||||
callback
|
||||
zonename
|
||||
Returns:
|
||||
Array of nodes
|
||||
Example:
|
||||
my @nodes =xCAT::Zone->getnodesinzone($callback,$zonename);
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub getnodesinzone
|
||||
{
|
||||
my ($class, $callback,$zonename) = @_;
|
||||
my @nodes;
|
||||
my $nodelisttab = xCAT::Table->new("nodelist");
|
||||
my @nodelist=$nodelisttab->getAllAttribs('node','zonename');
|
||||
# build the array of nodes in this zone
|
||||
foreach my $nodename (@nodelist) {
|
||||
if ((defined($nodename->{'zonename'})) && ($nodename->{'zonename'} eq $zonename)) {
|
||||
push @nodes,$nodename->{'node'};
|
||||
}
|
||||
}
|
||||
return @nodes;
|
||||
}
|
||||
1;
|
||||
Regular → Executable
+18
-3
@@ -14,8 +14,10 @@ require Exporter;
|
||||
|
||||
%distnames = (
|
||||
"1310229985.226287" => "centos6",
|
||||
"1323560292.885204" => "centos6.2",
|
||||
"1341569670.539525" => "centos6.3",#x86
|
||||
"1323560292.885204" => "centos6.2",
|
||||
"1341569670.539525" => "centos6.3",#x86
|
||||
"1362445555.957609" => "centos6.4",#x86_64
|
||||
"1385726732.061157" => "centos6.5",#x86_64
|
||||
"1176234647.982657" => "centos5",
|
||||
"1156364963.862322" => "centos4.4",
|
||||
"1178480581.024704" => "centos4.5",
|
||||
@@ -26,6 +28,7 @@ require Exporter;
|
||||
"1237641529.260981" => "centos5.3",
|
||||
"1272326751.405938" => "centos5.5",
|
||||
"1330913492.861127" => "centos5.8",#x86_64
|
||||
"1357930415.252042" => "centos5.9",#x86_64
|
||||
"1195488871.805863" => "centos4.6",
|
||||
"1195487524.127458" => "centos4.6",
|
||||
"1301444731.448392" => "centos5.6",
|
||||
@@ -45,6 +48,10 @@ require Exporter;
|
||||
"1269260915.992102" => "rhels5.5", #i386
|
||||
"1269263646.691048" => "rhels5.5", #x86_64
|
||||
"1328205744.315196" => "rhels5.8", #x86_64
|
||||
"1354216429.587870" => "rhels5.9", #x86_64
|
||||
"1354214009.518521" => "rhels5.9", #ppc64
|
||||
"1378846702.129847" => "rhels5.10", #x86_64
|
||||
"1378845049.643372" => "rhels5.10", #ppc64
|
||||
"1285193176.460470" => "rhels6", #x86_64
|
||||
"1285192093.430930" => "rhels6", #ppc64
|
||||
"1305068199.328169" => "rhels6.1", #x86_64
|
||||
@@ -54,10 +61,15 @@ require Exporter;
|
||||
"1339641244.734735" => "rhels6.3", #ppc64
|
||||
"1339640147.274118" => "rhels6.3", #x86_64
|
||||
"1339638991.532890" => "rhels6.3", #i386
|
||||
"1359576752.435900" => "rhels6.4", #x86_64
|
||||
"1359576196.686790" => "rhels6.4", #ppc64
|
||||
"1384196515.415715" => "rhels6.5", #x86_64
|
||||
"1384198011.520581" => "rhels6.5", #ppc64
|
||||
"1285193176.593806" => "rhelhpc6", #x86_64
|
||||
"1305067719.718814" => "rhelhpc6.1",#x86_64
|
||||
"1321545261.599847" => "rhelhpc6.2",#x86_64
|
||||
"1339640148.070971" => "rhelhpc6.3",#x86_64
|
||||
"1359576195.413831" => "rhelhpc6.4",#x86_64, RHEL ComputeNode
|
||||
"1194015916.783841" => "fedora8",
|
||||
"1194015385.299901" => "fedora8",
|
||||
"1210112435.291709" => "fedora9",
|
||||
@@ -69,13 +81,16 @@ require Exporter;
|
||||
"1273712675.937554" => "fedora13", #x86_64 DVD ISO
|
||||
"1287685820.403779" => "fedora14", #x86_64 DVD ISO
|
||||
"1305315870.828212" => "fedora15", #x86_64 DVD ISO
|
||||
|
||||
"1372355769.065812" => "fedora19", #x86_64 DVD ISO
|
||||
"1372402928.663653" => "fedora19", #ppc64 DVD ISO
|
||||
"1386856788.124593" => "fedora20", #x86_64 DVD ISO
|
||||
"1194512200.047708" => "rhas4.6",
|
||||
"1194512327.501046" => "rhas4.6",
|
||||
"1241464993.830723" => "rhas4.8", #x86-64
|
||||
|
||||
"1273608367.051780" => "SL5.5", #x86_64 DVD ISO
|
||||
"1299104542.844706" => "SL6", #x86_64 DVD ISO
|
||||
"1394111947.452332" => "pkvm2.1", # ppc64
|
||||
);
|
||||
my %numdiscs = (
|
||||
"1156364963.862322" => 4,
|
||||
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
package xCAT::data::ibmhwtypes;
|
||||
require Exporter;
|
||||
@EXPORT_OK=qw(parse_group mt2group);
|
||||
use Data::Dumper;
|
||||
my %groups2mtm = (
|
||||
"x3250" => ["2583","4251","4252"],
|
||||
"x3550" => ["7914","7944","7946"],
|
||||
"x3650" => ["7915","7945"],
|
||||
"dx360" => [],
|
||||
"x220" => ["7906"],
|
||||
"x240" => ["8737","7863"],
|
||||
"x440" => ["7917"],
|
||||
"p260" => ["7895"], #789522X, 789523X
|
||||
"p460" => [], #789542X
|
||||
"p470" => ["7954"],
|
||||
);
|
||||
|
||||
%mt2group = ();
|
||||
foreach my $group (keys %groups2mtm) {
|
||||
foreach my $mtm (@{$groups2mtm{$group}}) {
|
||||
$mt2group{$mtm} = $group;
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_group {
|
||||
my $mtm = shift;
|
||||
if ($mtm =~ /xCAT::data/) {
|
||||
$mtm = shift;
|
||||
}
|
||||
if ($mtm =~ /^(\w{4})/) {
|
||||
$mt = $1;
|
||||
if ($mt eq "7895" and $mtm =~ /789542X/i) {
|
||||
return "p460";
|
||||
}
|
||||
return $mt2group{$mt};
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -208,7 +208,7 @@ sub getNic {
|
||||
Arguments : User (root or non-root)
|
||||
Node
|
||||
Returns : Network names
|
||||
Example : my $lans = xCAT::zvmCPUtils->getNetworkNames($node);
|
||||
Example : my $lans = xCAT::zvmCPUtils->getNetworkNames($user, $node);
|
||||
|
||||
=cut
|
||||
|
||||
@@ -260,7 +260,7 @@ sub getNetworkNames {
|
||||
Arguments : User (root or non-root)
|
||||
Node
|
||||
Returns : Array of networks names
|
||||
Example : my @networks = xCAT::zvmCPUtils->getNetworkNamesArray($node);
|
||||
Example : my @networks = xCAT::zvmCPUtils->getNetworkNamesArray($user, $node);
|
||||
|
||||
=cut
|
||||
|
||||
@@ -468,6 +468,7 @@ sub grantVSwitch {
|
||||
|
||||
# Use SMAPI EXEC
|
||||
my $out = `ssh $user\@$hcp "$sudo $dir/smcli Virtual_Network_Vswitch_Set -T SYSTEM -n $vswitchId -I $userId"`;
|
||||
xCAT::zvmUtils->printSyslog("grantVSwitch- ssh $user\@$hcp $sudo $dir/smcli Virtual_Network_Vswitch_Set -T SYSTEM -n $vswitchId -I $userId");
|
||||
$out = xCAT::zvmUtils->trimStr($out);
|
||||
|
||||
# If return string contains 'Done' - Operation was successful
|
||||
@@ -564,6 +565,7 @@ sub smapiFlashCopy {
|
||||
# Use SMAPI EXEC to flash copy
|
||||
my $cmd = '\"' . "CMD=FLASHCOPY $srcId $srcAddr 0 END $tgtId $tgtAddr 0 END" . '\"';
|
||||
my $out = `ssh $user\@$hcp "$sudo $dir/smcli xCAT_Commands_IUO -T $hcpUserId -c $cmd"`;
|
||||
xCAT::zvmUtils->printSyslog("smapiFlashCopy- ssh $user\@$hcp $sudo $dir/smcli xCAT_Commands_IUO -T $hcpUserId -c $cmd");
|
||||
|
||||
$out = xCAT::zvmUtils->trimStr($out);
|
||||
|
||||
@@ -656,14 +658,18 @@ sub purgeReader {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
xCAT::zvmUtils->printSyslog("sudoer:$user zHCP:$hcp sudo:$sudo");
|
||||
|
||||
my $out;
|
||||
if (xCAT::zvmUtils->smapi4xcat($user, $hcp)) {
|
||||
# Use SMAPI EXEC to purge reader
|
||||
my $cmd = '\"' . "CMD=PURGE $userId RDR ALL" . '\"';
|
||||
$out = `ssh $user\@$hcp "$sudo $dir/smcli xCAT_Commands_IUO -T $userId -c $cmd"`;
|
||||
xCAT::zvmUtils->printSyslog("smcli xCAT_Commands_IUO -T $userId -c $cmd");
|
||||
} else {
|
||||
# Purge reader using CP
|
||||
$out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp purge $userId rdr all"`;
|
||||
xCAT::zvmUtils->printSyslog("/sbin/vmcp purge $userId rdr all");
|
||||
}
|
||||
|
||||
$out = xCAT::zvmUtils->trimStr($out);
|
||||
@@ -695,14 +701,18 @@ sub sendCPCmd {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
xCAT::zvmUtils->printSyslog("sudoer:$user zHCP:$hcp sudo:$sudo");
|
||||
|
||||
my $out;
|
||||
if (xCAT::zvmUtils->smapi4xcat($user, $hcp)) {
|
||||
# Use SMAPI EXEC to send command
|
||||
$cmd = '\"' . "CMD=SEND CP $userId " . uc($cmd) . '\"';
|
||||
$out = `ssh $user\@$hcp "$sudo $dir/smcli xCAT_Commands_IUO -T $userId -c $cmd"`;
|
||||
xCAT::zvmUtils->printSyslog("smcli xCAT_Commands_IUO -T $userId -c $cmd");
|
||||
} else {
|
||||
# Send CP command to given user
|
||||
$out = `ssh $user\@$hcp "$sudo /sbin/vmcp send cp $userId $cmd"`;
|
||||
xCAT::zvmUtils->printSyslog("/sbin/vmcp send cp $userId $cmd");
|
||||
}
|
||||
|
||||
$out = xCAT::zvmUtils->trimStr($out);
|
||||
|
||||
+826
-43
@@ -12,6 +12,8 @@ package xCAT::zvmUtils;
|
||||
use xCAT::MsgUtils;
|
||||
use xCAT::Utils;
|
||||
use xCAT::Table;
|
||||
use xCAT::NetworkUtils;
|
||||
use File::Basename;
|
||||
use strict;
|
||||
use warnings;
|
||||
1;
|
||||
@@ -286,8 +288,40 @@ sub printLn {
|
||||
|
||||
# Print string
|
||||
my $rsp;
|
||||
my $type = "I";
|
||||
if ($str =~ m/error/i) { # Set to print error if the string contains error
|
||||
$type = "E";
|
||||
}
|
||||
|
||||
$rsp->{data}->[0] = "$str";
|
||||
xCAT::MsgUtils->message( "I", $rsp, $callback );
|
||||
xCAT::MsgUtils->message( $type, $rsp, $callback );
|
||||
# xCAT::MsgUtils->message( "S", $str ); # Print to syslog
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 printSyslog
|
||||
|
||||
Description : Print a string to syslog
|
||||
Arguments : String
|
||||
Returns : Nothing
|
||||
Example : xCAT::zvmUtils->printSyslog($str);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub printSyslog {
|
||||
|
||||
# Get inputs
|
||||
my ( $class, $str ) = @_;
|
||||
|
||||
# Prepend where this message came from
|
||||
$str = $class . " " . $str;
|
||||
|
||||
# Print string
|
||||
xCAT::MsgUtils->message( "S", $str );
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -483,7 +517,7 @@ sub getIfcfgByNic {
|
||||
foreach (@parms) {
|
||||
|
||||
# If the network file contains the NIC address
|
||||
$out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo cat $_" | grep "$nic"`;
|
||||
$out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo cat $_" | egrep -i "$nic"`;
|
||||
if ($out) {
|
||||
|
||||
# Return network file path
|
||||
@@ -838,6 +872,36 @@ sub checkOutput {
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 checkOutputExtractReason
|
||||
|
||||
Description : Check the return of given output. If bad, extract the reason.
|
||||
Arguments : Output string
|
||||
Reason (passed as a reference)
|
||||
Returns : 0 Good output
|
||||
-1 Bad output
|
||||
Example : my $rtn = xCAT::zvmUtils->checkOutput($callback, $out, \$reason);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub checkOutputExtractReason {
|
||||
my ( $class, $callback, $out, $reason ) = @_;
|
||||
|
||||
# Check output string
|
||||
my @outLn = split("\n", $out);
|
||||
foreach (@outLn) {
|
||||
# If output contains 'ERROR: ', return -1 and pass back the reason.
|
||||
if ($_ =~ /(.*?ERROR: )/) {
|
||||
$$reason = substr($_, index($_, "ERROR: ") + length("ERROR: "));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 getDeviceNode
|
||||
|
||||
Description : Get the device node for a given address
|
||||
@@ -860,14 +924,14 @@ sub getDeviceNode {
|
||||
|
||||
# Determine device node
|
||||
my $out = `ssh $user\@$node "$sudo cat /proc/dasd/devices" | grep ".$tgtAddr("`;
|
||||
my @words = split( ' ', $out );
|
||||
my @words = split(' ', $out);
|
||||
my $tgtDevNode;
|
||||
|
||||
# /proc/dasd/devices look similar to this:
|
||||
# 0.0.0100(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 1802880 blocks, 7042 MB
|
||||
# Look for the string 'is'
|
||||
my $i = 0;
|
||||
while ( $tgtDevNode ne 'is' ) {
|
||||
while ($tgtDevNode ne 'is') {
|
||||
$tgtDevNode = $words[$i];
|
||||
$i++;
|
||||
}
|
||||
@@ -877,6 +941,39 @@ sub getDeviceNode {
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 getDeviceNodeAddr
|
||||
|
||||
Description : Get the virtual device address for a given device node
|
||||
Arguments : User (root or non-root)
|
||||
Node
|
||||
Device node
|
||||
Returns : Virtual device address
|
||||
Example : my $addr = xCAT::zvmUtils->getDeviceNodeAddr($user, $node, $deviceNode);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub getDeviceNodeAddr {
|
||||
my ( $class, $user, $node, $deviceNode ) = @_;
|
||||
|
||||
my $sudo = "sudo";
|
||||
if ($user eq "root") {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
# Find device node and determine virtual address
|
||||
# /proc/dasd/devices look similar to this:
|
||||
# 0.0.0100(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 1802880 blocks, 7042 MB
|
||||
my $addr = `ssh $user\@$node "$sudo cat /proc/dasd/devices" | grep -i "is $deviceNode"`;
|
||||
$addr =~ s/ +/ /g;
|
||||
$addr =~ s/^0.0.([0-9a-f]*).*/$1/;
|
||||
chomp($addr);
|
||||
|
||||
return $addr;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 isAddressUsed
|
||||
|
||||
Description : Check if a given address is used
|
||||
@@ -1058,16 +1155,23 @@ sub createMacAddr {
|
||||
return -1;
|
||||
}
|
||||
|
||||
# Get HCP MAC address
|
||||
# Get the first MAC address found
|
||||
my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q v nic" | grep "MAC:"`;
|
||||
my @lines = split( "\n", $out );
|
||||
my @vars = split( " ", $lines[0] );
|
||||
|
||||
# Extract MAC prefix
|
||||
my $prefix = $vars[1];
|
||||
$prefix = xCAT::zvmUtils->replaceStr( $prefix, "-", "" );
|
||||
$prefix = substr( $prefix, 0, 6 );
|
||||
# Get USER Prefix
|
||||
my $prefix = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q vmlan" | egrep -i "USER Prefix:"`;
|
||||
$prefix =~ s/(.*?)USER Prefix:(.*)/$2/;
|
||||
$prefix =~ s/^\s+//;
|
||||
$prefix =~ s/\s+$//;
|
||||
|
||||
# Get MACADDR Prefix instead if USER Prefix is not defined
|
||||
if (!$prefix) {
|
||||
$prefix = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q vmlan" | egrep -i "MACADDR Prefix:"`;
|
||||
$prefix =~ s/(.*?)MACADDR Prefix:(.*)/$2/;
|
||||
$prefix =~ s/^\s+//;
|
||||
$prefix =~ s/\s+$//;
|
||||
|
||||
if (!$prefix) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
# Generate MAC address of source node
|
||||
my $mac = $prefix . $suffix;
|
||||
@@ -1468,7 +1572,7 @@ sub getFreeAddress {
|
||||
} else {
|
||||
# When the node is down, use zHCP to get its user directory entry
|
||||
# Get HCP
|
||||
my @propNames = ( 'hcp', 'userid' );
|
||||
my @propNames = ('hcp', 'userid');
|
||||
my $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $node, @propNames );
|
||||
my $hcp = $propVals->{'hcp'};
|
||||
|
||||
@@ -1486,9 +1590,9 @@ sub getFreeAddress {
|
||||
}
|
||||
|
||||
# Get all defined device address
|
||||
$allUsedAddr = `cat $allUsedAddr | awk '$1 ~/^($deviceTypesUserDir)/ {print $2}' | sort`;
|
||||
$allUsedAddr = `cat $userDirEntry | awk '$1 ~/^($deviceTypesUserDir)/ {print $2}' | sort`;
|
||||
# Get all linked device address
|
||||
$allUsedAddr .= `cat $allUsedAddr | awk '$1 ~/^(LINK)/ {print $4}' | sort`;
|
||||
$allUsedAddr .= `cat $userDirEntry | awk '$1 ~/^(LINK)/ {print $4}' | sort`;
|
||||
}
|
||||
|
||||
# Loop to get the lowest free address
|
||||
@@ -1538,7 +1642,7 @@ sub getUsedCpuTime {
|
||||
$time =~ s/^\s+//;
|
||||
$time =~ s/\s+$//;
|
||||
if (!$time) {
|
||||
$time = 0;
|
||||
$time = 0;
|
||||
}
|
||||
|
||||
# Not found, return 0
|
||||
@@ -2032,7 +2136,7 @@ sub smapi4xcat {
|
||||
my $out = `ssh $user\@$hcp "$sudo $dir/smcli Query_API_Functional_Level -T $hcpUserId"`;
|
||||
$out = xCAT::zvmUtils->trimStr($out);
|
||||
if ( !($out =~ m/V6.2/i || $out =~ m/V6.1/i || $out =~ m/V5.4/i) ) {
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Check if SMAPI EXEC exists
|
||||
@@ -2133,20 +2237,20 @@ sub querySSI {
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub rExecute {
|
||||
my ( $class, $user, $node, $cmd ) = @_;
|
||||
|
||||
my $out;
|
||||
my $sudo = "sudo";
|
||||
my ( $class, $user, $node, $cmd ) = @_;
|
||||
|
||||
my $out;
|
||||
my $sudo = "sudo";
|
||||
if ($user eq "root") {
|
||||
# Just execute the command if root
|
||||
# Just execute the command if root
|
||||
$out = `ssh $user\@$node "$cmd"`;
|
||||
return $out;
|
||||
}
|
||||
|
||||
# Encapsulate command in single quotes
|
||||
$cmd = "'" . $cmd . "'";
|
||||
$out = `ssh $user\@$node "$sudo sh -c $cmd"`;
|
||||
return $out;
|
||||
# Encapsulate command in single quotes
|
||||
$cmd = "'" . $cmd . "'";
|
||||
$out = `ssh $user\@$node "$sudo sh -c $cmd"`;
|
||||
return $out;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
@@ -2163,8 +2267,8 @@ sub rExecute {
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub getUsedFcpDevices {
|
||||
my ( $class, $user, $hcp ) = @_;
|
||||
|
||||
my ( $class, $user, $hcp ) = @_;
|
||||
|
||||
# Directory where zFCP pools are
|
||||
my $pool = "/var/opt/zhcp/zfcp";
|
||||
|
||||
@@ -2172,15 +2276,15 @@ sub getUsedFcpDevices {
|
||||
if ($user eq "root") {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
# Grep the pools for used or allocated zFCP devices
|
||||
my %usedDevices;
|
||||
my @args;
|
||||
my @devices = split("\n", `ssh $user\@$hcp "$sudo cat $pool/*.conf" | egrep -i "used|allocated"`);
|
||||
foreach (@devices) {
|
||||
@args = split(",", $_);
|
||||
|
||||
# Sample pool configuration file:
|
||||
|
||||
# Grep the pools for used or allocated zFCP devices
|
||||
my %usedDevices;
|
||||
my @args;
|
||||
my @devices = split("\n", `ssh $user\@$hcp "$sudo cat $pool/*.conf" | egrep -i "used|allocated"`);
|
||||
foreach (@devices) {
|
||||
@args = split(",", $_);
|
||||
|
||||
# Sample pool configuration file:
|
||||
# #status,wwpn,lun,size,range,owner,channel,tag
|
||||
# used,1000000000000000,2000000000000110,8g,3B00-3B3F,ihost1,1a23,$root_device$
|
||||
# free,1000000000000000,2000000000000111,,3B00-3B3F,,,
|
||||
@@ -2189,9 +2293,688 @@ sub getUsedFcpDevices {
|
||||
|
||||
# Push used or allocated devices into hash
|
||||
if ($args[6]) {
|
||||
$usedDevices{uc($args[6])} = 1;
|
||||
$usedDevices{uc($args[6])} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return %usedDevices;
|
||||
}
|
||||
|
||||
return %usedDevices;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 establishMount
|
||||
|
||||
Description : Establish an NFS mount point on a zHCP system.
|
||||
Arguments : Sudoer user name
|
||||
Sudo keyword
|
||||
zHCP hostname
|
||||
Local directory to remotely mount
|
||||
Mount access ('ro' for read only, 'rw' for read write)
|
||||
Directory as known to zHCP (out)
|
||||
Returns : 0 - Mounted, or zHCP and MN are on the same system
|
||||
1 - Mount failed
|
||||
Example : establishMount( $callback, $::SUDOER, $::SUDO, $hcp, "$installRoot/$provMethod", "ro", \$remoteDeployDir );
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub establishMount {
|
||||
# Get inputs
|
||||
my ($class, $callback, $sudoer, $sudo, $hcp, $localDir, $access, $mountedPt) = @_;
|
||||
my $out;
|
||||
|
||||
# If the target system is not on this system then establish the NFS mount point.
|
||||
my $hcpIP = xCAT::NetworkUtils->getipaddr( $hcp );
|
||||
if (! defined $hcpIP) {
|
||||
xCAT::zvmUtils->printLn( $callback, "(Error) Unable to obtain the IP address of the hcp node" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $masterIp = xCAT::TableUtils->get_site_Master();
|
||||
if (! defined $masterIp) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$hcp: (Error) Unable to obtain the management node IP address from the site table" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($masterIp eq $hcpIP) {
|
||||
# xCAT MN and zHCP are on the same box and will use the same directory without the need for an NFS mount.
|
||||
$$mountedPt = $localDir;
|
||||
} else {
|
||||
# Determine the hostname for this management node
|
||||
my $masterHostname = Sys::Hostname::hostname();
|
||||
if (! defined $masterHostname) {
|
||||
# For some reason, the xCAT MN's hostname is not known. We pass along the IP address instead.
|
||||
$masterHostname = $masterIp;
|
||||
}
|
||||
|
||||
xCAT::zvmUtils->printSyslog( "establishMount() Preparing the NFS mount point on zHCP ($hcpIP) to xCAT MN $masterHostname($masterIp) for $localDir" );
|
||||
|
||||
# Prepare the staging mount point on zHCP, if they need to be established
|
||||
$$mountedPt = "/mnt/$masterHostname$localDir";
|
||||
my $rc = `ssh $sudoer\@$hcp "$sudo mkdir -p $$mountedPt && mount -t nfs -o $access $masterIp:$localDir $$mountedPt; echo \\\$?"`;
|
||||
|
||||
# Return code = 0 (mount succeeded) or 32 (mount already exists)
|
||||
if ($rc != '0' && $rc != '32') {
|
||||
xCAT::zvmUtils->printLn( $callback, "$hcp: (Error) Unable to establish zHCP mount point: $$mountedPt" );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 getFreeRepoSpace
|
||||
|
||||
Description : Get the free space of image repository under /install
|
||||
Arguments : Node
|
||||
Returns : The available space for /install
|
||||
Example : my $free = getFreeRepoSpace($callback, $node);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub getFreeRepoSpace {
|
||||
# Get inputs
|
||||
my ($class, $user, $node) = @_;
|
||||
|
||||
my $sudo = "sudo";
|
||||
if ($user eq "root") {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
# Check if node is the management node
|
||||
my @entries = xCAT::TableUtils->get_site_attribute("master");
|
||||
my $master = xCAT::zvmUtils->trimStr($entries[0]);
|
||||
my $ip = xCAT::NetworkUtils->getipaddr($node);
|
||||
$ip = xCAT::zvmUtils->trimStr($ip);
|
||||
my $mn = 0;
|
||||
if ($master eq $ip) {
|
||||
# If the master IP and node IP match, then it is the management node
|
||||
my $out = `$sudo /bin/df -h /install | sed 1d`;
|
||||
$out =~ s/\h+/ /g;
|
||||
my @results = split(' ', $out);
|
||||
return ($results[3]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 findAndUpdatezFcpPool
|
||||
|
||||
Description : Find and update a SCSI/FCP device in a given storage pool.
|
||||
xCAT will find and update the SCSI/FCP device in all known pools based on the unique WWPN/LUN combo.
|
||||
Arguments : Message header
|
||||
User (root or non-root)
|
||||
zHCP
|
||||
Storage pool
|
||||
Criteria hash including:
|
||||
- Status (free, reserved, or used)
|
||||
- zFCP channel
|
||||
- WWPN
|
||||
- LUN
|
||||
- Size requested
|
||||
- Owner
|
||||
- Tag
|
||||
Returns : Results hash including:
|
||||
- Return code (0 = Success, -1 = Failure)
|
||||
- zFCP device (if one is requested)
|
||||
- WWPN
|
||||
- LUN
|
||||
Example : my $resultsRef = xCAT::zvmUtils->findAndUpdatezFcpPool($callback, $header, $user, $hcp, $pool, $criteriaRef);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub findAndUpdatezFcpPool {
|
||||
# Get inputs
|
||||
my ($class, $callback, $header, $user, $hcp, $pool, $criteriaRef) = @_;
|
||||
|
||||
# Determine if sudo is used
|
||||
my $sudo = "sudo";
|
||||
if ($user eq "root") {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
# Directory where executables are on zHCP
|
||||
my $dir = "/opt/zhcp/bin";
|
||||
|
||||
# Directory where FCP disk pools are on zHCP
|
||||
my $zfcpDir = "/var/opt/zhcp/zfcp";
|
||||
|
||||
my %results = ('rc' => -1); # Default to error
|
||||
|
||||
# Extract criteria
|
||||
my %criteria = %$criteriaRef;
|
||||
my $status = defined($criteria{status}) ? $criteria{status} : "";
|
||||
my $fcpDevice = defined($criteria{fcp}) ? $criteria{fcp} : "";
|
||||
my $wwpn = defined($criteria{wwpn}) ? $criteria{wwpn} : "";
|
||||
my $lun = defined($criteria{lun}) ? $criteria{lun} : "";
|
||||
my $size = defined($criteria{size}) ? $criteria{size} : "";
|
||||
my $owner = defined($criteria{owner}) ? $criteria{owner} : "";
|
||||
my $tag = defined($criteria{tag}) ? $criteria{tag} : "";
|
||||
|
||||
# Check required arguments: pool, status
|
||||
# If you do not know what to update, why update!
|
||||
if (!$pool && !$status) {
|
||||
return \%results;
|
||||
}
|
||||
|
||||
# Check status
|
||||
if ($status !~ m/^(free|used|reserved)$/i) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: (Error) Status not recognized. Status can be free, used, or reserved.");
|
||||
return \%results;
|
||||
}
|
||||
|
||||
# Check FCP device syntax
|
||||
if ($fcpDevice && ($fcpDevice !~ /^auto/i) && ($fcpDevice =~ /[^0-9a-f]/i)) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: (Error) Invalid FCP channel address $fcpDevice.");
|
||||
return \%results;
|
||||
}
|
||||
|
||||
# Check WWPN and LUN syntax
|
||||
if ( $wwpn && ($wwpn =~ /[^0-9a-f;"]/i) ) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$header: (Error) Invalid world wide portname $wwpn." );
|
||||
return \%results;
|
||||
} if ( $lun && ($lun =~ /[^0-9a-f]/i) ) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$header: (Error) Invalid logical unit number $lun." );
|
||||
return \%results;
|
||||
}
|
||||
|
||||
# Size can be M(egabytes) or G(igabytes). Convert size into MB.
|
||||
my $originSize = $size;
|
||||
if ($size) {
|
||||
if ($size =~ m/G/i) {
|
||||
# Convert to MegaBytes
|
||||
$size =~ s/\D//g;
|
||||
$size = int($size) * 1024
|
||||
} elsif ($size =~ m/M/i || !$size) {
|
||||
# Do nothing
|
||||
} else {
|
||||
xCAT::zvmUtils->printLn( $callback, "$header: (Error) Size not recognized. Size can be M(egabytes) or G(igabytes)." );
|
||||
return \%results;
|
||||
}
|
||||
}
|
||||
|
||||
# Check if WWPN and LUN are given
|
||||
# WWPN can be given as a semi-colon separated list (multipathing)
|
||||
my $useWwpnLun = 0;
|
||||
if ($wwpn && $lun) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: Using given WWPN and LUN");
|
||||
$useWwpnLun = 1;
|
||||
|
||||
# Make sure WWPN and LUN do not have 0x prefix
|
||||
$wwpn = xCAT::zvmUtils->replaceStr($wwpn, "0x", "");
|
||||
$lun = xCAT::zvmUtils->replaceStr($lun, "0x", "");
|
||||
}
|
||||
|
||||
# Find disk pool (create one if non-existent)
|
||||
my $out;
|
||||
if (!(`ssh $user\@$hcp "$sudo test -d $zfcpDir && echo Exists"`)) {
|
||||
# Create pool directory
|
||||
$out = `ssh $user\@$hcp "$sudo mkdir -p $zfcpDir"`;
|
||||
}
|
||||
|
||||
# Find if disk pool exists
|
||||
if (!(`ssh $user\@$hcp "$sudo test -e $zfcpDir/$pool.conf && echo Exists"`)) {
|
||||
# Return if xCAT is expected to find a FCP device, but no disk pool exists.
|
||||
xCAT::zvmUtils->printLn($callback, "$header: (Error) FCP storage pool does not exist");
|
||||
return \%results;
|
||||
}
|
||||
|
||||
# Find a free disk in the pool
|
||||
# FCP devices are contained in /var/opt/zhcp/zfcp/<pool-name>.conf
|
||||
my $range = "";
|
||||
my $sizeFound = "*";
|
||||
my @info;
|
||||
if (!$useWwpnLun) {
|
||||
# Find a suitable pair of WWPN and LUN in device pool based on requested size
|
||||
# Sample pool configuration file:
|
||||
# #status,wwpn,lun,size,range,owner,channel,tag
|
||||
# used,1000000000000000,2000000000000110,8g,3B00-3B3F,ihost1,1a23,$root_device$
|
||||
# free,1000000000000000,2000000000000111,,3B00-3B3F,,,
|
||||
# free,1230000000000000;4560000000000000,2000000000000112,,3B00-3B3F,,,
|
||||
my @devices = split("\n", `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | egrep -i ^free`);
|
||||
$sizeFound = 0;
|
||||
foreach (@devices) {
|
||||
@info = split(',', $_);
|
||||
|
||||
# Check if the size is sufficient. Convert size into MB.
|
||||
if ($info[3] =~ m/G/i) {
|
||||
# Convert to MegaBytes
|
||||
$info[3] =~ s/\D//g;
|
||||
$info[3] = int($info[3]) * 1024
|
||||
} elsif ($info[3] =~ m/M/i) {
|
||||
# Do nothing
|
||||
$info[3] =~ s/\D//g;
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
|
||||
# Find optimal disk based on requested size
|
||||
if ($sizeFound && $info[3] >= $size && $info[3] < $sizeFound) {
|
||||
$sizeFound = $info[3];
|
||||
$wwpn = $info[1];
|
||||
$lun = $info[2];
|
||||
$range = $info[4];
|
||||
} elsif (!$sizeFound && $info[3] >= $size) {
|
||||
$sizeFound = $info[3];
|
||||
$wwpn = $info[1];
|
||||
$lun = $info[2];
|
||||
$range = $info[4];
|
||||
}
|
||||
}
|
||||
|
||||
# Do not continue if no devices can be found
|
||||
if (!$wwpn && !$lun) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: (Error) A suitable device of $size" . "M or larger could not be found");
|
||||
return \%results;
|
||||
}
|
||||
} else {
|
||||
# Find given WWPN and LUN. Do not continue if device is used
|
||||
my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | grep -i "$wwpn,$lun"`;
|
||||
chomp($select);
|
||||
|
||||
@info = split(',', $select);
|
||||
|
||||
if ($size) {
|
||||
if ($info[3] =~ m/G/i) {
|
||||
# Convert to MegaBytes
|
||||
$info[3] =~ s/\D//g;
|
||||
$info[3] = int($info[3]) * 1024
|
||||
} elsif ($info[3] =~ m/M/i) {
|
||||
# Do nothing
|
||||
$info[3] =~ s/\D//g;
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
|
||||
# Do not continue if specified device does not have enough capacity
|
||||
if ($info[3] < $size) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: (Error) FCP device $wwpn/$lun is not large enough");
|
||||
return \%results;
|
||||
}
|
||||
}
|
||||
|
||||
# Find range of the specified disk
|
||||
$range = $info[4];
|
||||
}
|
||||
|
||||
# If there are multiple paths, take the 1st one
|
||||
# Handle multi-pathing in postscript because autoyast/kickstart does not support it.
|
||||
my $origWwpn = $wwpn;
|
||||
if ($wwpn =~ m/;/i) {
|
||||
@info = split(';', $wwpn);
|
||||
$wwpn = xCAT::zvmUtils->trimStr($info[0]);
|
||||
}
|
||||
|
||||
xCAT::zvmUtils->printLn($callback, "$header: Found FCP device 0x$wwpn/0x$lun");
|
||||
|
||||
# Find a free FCP device based on the given range
|
||||
if ($fcpDevice =~ m/^auto/i) {
|
||||
my @ranges;
|
||||
my $min;
|
||||
my $max;
|
||||
my $found = 0;
|
||||
|
||||
if ($range =~ m/;/i) {
|
||||
@ranges = split(';', $range);
|
||||
} else {
|
||||
push(@ranges, $range);
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
# If the node has an eligible FCP device, use it
|
||||
my @deviceList = xCAT::zvmUtils->getDedicates($callback, $user, $owner);
|
||||
foreach (@deviceList) {
|
||||
# Check if this devide is eligible (among the range specified for disk $lun)
|
||||
@info = split(' ', $_);
|
||||
my $candidate = $info[2];
|
||||
foreach (@ranges) {
|
||||
($min, $max) = split('-', $_);
|
||||
if (hex($candidate) >= hex($min) && hex($candidate) <= hex($max)) {
|
||||
$found = 1;
|
||||
$fcpDevice = uc($candidate);
|
||||
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: Found eligible FCP channel $fcpDevice");
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
# If the node has no eligible FCP device, find a free one for it.
|
||||
my %usedDevices = xCAT::zvmUtils->getUsedFcpDevices($user, $hcp);
|
||||
|
||||
my $hcpUserId = xCAT::zvmCPUtils->getUserId($user, $hcp);
|
||||
$hcpUserId =~ tr/a-z/A-Z/;
|
||||
|
||||
# Find a free FCP channel
|
||||
$out = `ssh $user\@$hcp "$sudo $dir/smcli System_WWPN_Query -T $hcpUserId" | egrep -i "FCP device number|Status"`;
|
||||
my @devices = split( "\n", $out );
|
||||
for (my $i = 0; $i < @devices; $i++) {
|
||||
# Extract the device number and status
|
||||
$fcpDevice = $devices[$i];
|
||||
$fcpDevice =~ s/^FCP device number:(.*)/$1/;
|
||||
$fcpDevice =~ s/^\s+//;
|
||||
$fcpDevice =~ s/\s+$//;
|
||||
|
||||
$i++;
|
||||
my $fcpStatus = $devices[$i];
|
||||
$fcpStatus =~ s/^Status:(.*)/$1/;
|
||||
$fcpStatus =~ s/^\s+//;
|
||||
$fcpStatus =~ s/\s+$//;
|
||||
|
||||
# Only look at free FCP devices
|
||||
if ($fcpStatus =~ m/free/i) {
|
||||
# If the device number is within the specified range, exit out of loop
|
||||
# Range: 3B00-3C00;4B00-4C00;5E12-5E12
|
||||
foreach (@ranges) {
|
||||
($min, $max) = split('-', $_);
|
||||
if (hex($fcpDevice) >= hex($min) && hex($fcpDevice) <= hex($max)) {
|
||||
$fcpDevice = uc($fcpDevice);
|
||||
|
||||
# Used found FCP channel if not in use or allocated
|
||||
if (!$usedDevices{$fcpDevice}) {
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Break out of loop if FCP channel is found
|
||||
if ($found) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: Found FCP channel within acceptable range $fcpDevice");
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Do not continue if no FCP channel is found
|
||||
if (!$found) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: (Error) A suitable FCP channel could not be found");
|
||||
return \%results;
|
||||
}
|
||||
}
|
||||
|
||||
# If there are multiple devices (multipathing), take the 1st one
|
||||
if ($fcpDevice) {
|
||||
if ($fcpDevice =~ m/;/i) {
|
||||
@info = split(';', $fcpDevice);
|
||||
$fcpDevice = xCAT::zvmUtils->trimStr($info[0]);
|
||||
}
|
||||
|
||||
# Make sure channel has a length of 4
|
||||
while (length($fcpDevice) < 4) {
|
||||
$fcpDevice = "0" . $fcpDevice;
|
||||
}
|
||||
}
|
||||
|
||||
# Mark WWPN and LUN as used, free, or reserved and set the owner/channel appropriately
|
||||
# This config file keeps track of the owner of each device, which is useful in nodeset
|
||||
$size = $size . "M";
|
||||
my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | grep -i "$lun" | grep -i "$wwpn"`;
|
||||
chomp($select);
|
||||
if ($select) {
|
||||
@info = split(',', $select);
|
||||
|
||||
if (!$info[3]) {
|
||||
$info[3] = $size;
|
||||
}
|
||||
|
||||
# Do not update if WWPN/LUN pair is specified but the pair does not exist
|
||||
if (!($info[1] =~ m/$wwpn/i)) {
|
||||
xCAT::zvmUtils->printLn($callback, "$header: (Error) FCP device $wwpn/$lun does not exists");
|
||||
return \%results;
|
||||
}
|
||||
|
||||
# Entry order: status,wwpn,lun,size,range,owner,channel,tag
|
||||
# The following are never updated: wwpn, lun, size, and range
|
||||
my $update = "$status,$info[1],$info[2],$info[3],$info[4],$owner,$fcpDevice,$tag";
|
||||
my $expression = "'s#" . $select . "#" .$update . "#i'";
|
||||
$out = `ssh $user\@$hcp "$sudo sed --in-place -e $expression $zfcpDir/$pool.conf"`;
|
||||
} else {
|
||||
# Insert device entry into file
|
||||
$out = `ssh $user\@$hcp "$sudo echo \"$status,$origWwpn,$lun,$size,,$owner,$fcpDevice,$tag\" >> $zfcpDir/$pool.conf"`;
|
||||
}
|
||||
|
||||
# Generate results hash
|
||||
%results = (
|
||||
'rc' => 0,
|
||||
'fcp' => $fcpDevice,
|
||||
'wwpn' => $wwpn,
|
||||
'lun' => $lun
|
||||
);
|
||||
return \%results;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 findzFcpDevicePool
|
||||
|
||||
Description : Find the zFCP storage pool that contains the given zFCP device
|
||||
Arguments : User (root or non-root)
|
||||
zHCP
|
||||
WWPN
|
||||
LUN
|
||||
Returns : Storage pool where zFCP device resides
|
||||
Example : my $pool = xCAT::zvmUtils->findzFcpDevicePool($user, $hcp, $wwpn, $lun);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub findzFcpDevicePool {
|
||||
|
||||
# Get inputs
|
||||
my ( $class, $user, $hcp, $wwpn, $lun ) = @_;
|
||||
|
||||
my $sudo = "sudo";
|
||||
if ($user eq "root") {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
# Directory where FCP disk pools are on zHCP
|
||||
my $zfcpDir = "/var/opt/zhcp/zfcp";
|
||||
|
||||
# Find the pool that contains the SCSI/FCP device
|
||||
my @pools = split("\n", `ssh $user\@$hcp "$sudo grep -i -l \"$wwpn,$lun\" $zfcpDir/*.conf"`);
|
||||
my $pool = "";
|
||||
if (scalar(@pools)) {
|
||||
$pool = basename($pools[0]);
|
||||
$pool =~ s/\.[^.]+$//; # Do not use extension
|
||||
}
|
||||
|
||||
return $pool;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 findzFcpDeviceAttr
|
||||
|
||||
Description : Find the zFCP device attributes
|
||||
Arguments : User (root or non-root)
|
||||
zHCP
|
||||
Storage pool
|
||||
WWPN
|
||||
LUN
|
||||
Returns : Architecture of node
|
||||
Example : my $deviceRef = xCAT::zvmUtils->findzFcpDeviceAttr($user, $hcp, $wwpn, $lun);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub findzFcpDeviceAttr {
|
||||
|
||||
# Get inputs
|
||||
my ( $class, $user, $hcp, $pool, $wwpn, $lun ) = @_;
|
||||
|
||||
my $sudo = "sudo";
|
||||
if ($user eq "root") {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
# Directory where FCP disk pools are on zHCP
|
||||
my $zfcpDir = "/var/opt/zhcp/zfcp";
|
||||
|
||||
# Find the SCSI/FCP device
|
||||
# Entry order: status,wwpn,lun,size,range,owner,channel,tag
|
||||
my @info = split("\n", `ssh $user\@$hcp "$sudo grep \"$wwpn,$lun\" $zfcpDir/$pool.conf"`);
|
||||
my $entry = $info[0];
|
||||
chomp($entry);
|
||||
|
||||
# Do not continue if no device is found
|
||||
my %attrs = ();
|
||||
if (!$entry) {
|
||||
return \%attrs;
|
||||
}
|
||||
|
||||
@info = split(',', $entry);
|
||||
%attrs = (
|
||||
'status' => $info[0],
|
||||
'wwpn' => $info[1],
|
||||
'lun' => $info[2],
|
||||
'size' => $info[3],
|
||||
'range' => $info[4],
|
||||
'owner' => $info[5],
|
||||
'fcp' => $info[6],
|
||||
'tag' => $info[7]
|
||||
);
|
||||
|
||||
return \%attrs;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 findUsablezHcpNetwork
|
||||
|
||||
Description : Find a useable NIC shared with the zHCP for a given user Id
|
||||
Arguments : User (root or non-root)
|
||||
zHCP
|
||||
User Id to find a useable NIC on
|
||||
DHCP is used or not (0 or 1)
|
||||
Returns : NIC, device channel, and layer (2 or 3)
|
||||
Example : my ($nic, $channel, $layer) = xCAT::zvmUtils->findUsablezHcpNetwork($user, $hcp, $userId, $dhcp);
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub findUsablezHcpNetwork {
|
||||
# Get inputs
|
||||
my ( $class, $user, $hcp, $userId, $dhcp ) = @_;
|
||||
|
||||
my $sudo = "sudo";
|
||||
if ($user eq "root") {
|
||||
$sudo = "";
|
||||
}
|
||||
|
||||
my $nic = ''; # Usuable NIC on zHCP
|
||||
my $channel = ''; # Device channel where NIC is attached
|
||||
my $layer;
|
||||
my $i;
|
||||
my @words;
|
||||
|
||||
# Get the networks used by the zHCP
|
||||
my @hcpNetworks = xCAT::zvmCPUtils->getNetworkNamesArray($user, $hcp);
|
||||
|
||||
# Search directory entry for network name
|
||||
my $userEntry = `ssh $user\@$hcp "$sudo $::DIR/smcli Image_Query_DM -T $userId" | sed '\$d'`;
|
||||
xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() smcli Image_Query_DM -T $userId");
|
||||
xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() $userEntry");
|
||||
|
||||
my $out = `echo "$userEntry" | grep "NICDEF"`;
|
||||
my @lines = split('\n', $out);
|
||||
|
||||
# Go through each line
|
||||
for ($i = 0; $i < @lines; $i++) {
|
||||
# Go through each network device attached to zHCP
|
||||
foreach (@hcpNetworks) {
|
||||
|
||||
# If network device is found
|
||||
if ($lines[$i] =~ m/ $_/i) {
|
||||
# Get network layer
|
||||
$layer = xCAT::zvmCPUtils->getNetworkLayer($user, $hcp, $_);
|
||||
xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() NIC:$_ layer:$layer");
|
||||
|
||||
# If template using DHCP, layer must be 2
|
||||
if ((!$dhcp && $layer != 2) || (!$dhcp && $layer == 2) || ($dhcp && $layer == 2)) {
|
||||
# Save network name
|
||||
$nic = $_;
|
||||
|
||||
# Get network virtual address
|
||||
@words = split(' ', $lines[$i]);
|
||||
|
||||
# Get virtual address (channel)
|
||||
# Convert subchannel to decimal
|
||||
$channel = sprintf('%d', hex($words[1]));
|
||||
|
||||
xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() Candidate found NIC:$nic channel:$channel layer:$layer");
|
||||
return ($nic, $channel, $layer);
|
||||
} else {
|
||||
# Go to next network available
|
||||
$nic = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If network device is not found
|
||||
if (!$nic) {
|
||||
# Check for user profile
|
||||
my $profileName = `echo "$userEntry" | grep "INCLUDE"`;
|
||||
if ($profileName) {
|
||||
@words = split(' ', xCAT::zvmUtils->trimStr($profileName));
|
||||
|
||||
# Get user profile
|
||||
my $userProfile = xCAT::zvmUtils->getUserProfile($user, $hcp, $words[1]);
|
||||
xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() $userProfile");
|
||||
|
||||
# Get the NICDEF statement containing the HCP network
|
||||
$out = `echo "$userProfile" | grep "NICDEF"`;
|
||||
@lines = split('\n', $out);
|
||||
|
||||
# Go through each line
|
||||
for ($i = 0; $i < @lines; $i++) {
|
||||
# Go through each network device attached to zHCP
|
||||
foreach (@hcpNetworks) {
|
||||
|
||||
# If network device is found
|
||||
if ($lines[$i] =~ m/ $_/i) {
|
||||
# Get network layer
|
||||
$layer = xCAT::zvmCPUtils->getNetworkLayer($user, $hcp, $_);
|
||||
xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() NIC:$_ layer:$layer");
|
||||
|
||||
# If template using DHCP, layer must be 2
|
||||
if ((!$dhcp && $layer != 2) || (!$dhcp && $layer == 2) || ($dhcp && $layer == 2)) {
|
||||
# Save network name
|
||||
$nic = $_;
|
||||
|
||||
# Get network virtual address
|
||||
@words = split(' ', $lines[$i]);
|
||||
|
||||
# Get virtual address (channel)
|
||||
# Convert subchannel to decimal
|
||||
$channel = sprintf('%d', hex($words[1]));
|
||||
|
||||
xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() Candidate found NIC:$nic channel:$channel layer:$layer");
|
||||
return ($nic, $channel, $layer);
|
||||
} else {
|
||||
# Go to next network available
|
||||
$nic = '';
|
||||
}
|
||||
}
|
||||
} # End of foreach
|
||||
} # End of for
|
||||
} # End of if
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
+269
-78
@@ -6,84 +6,275 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
int main() {
|
||||
int serverfd,port;
|
||||
int getpktinfo = 1;
|
||||
struct addrinfo hint, *res;
|
||||
char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
char clientpacket[1024];
|
||||
struct sockaddr_in clientaddr;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsgptr;
|
||||
struct iovec iov[1];
|
||||
unsigned int myip;
|
||||
char *txtptr;
|
||||
iov[0].iov_base = clientpacket;
|
||||
iov[0].iov_len = 1024;
|
||||
memset(&msg,0,sizeof(msg));
|
||||
memset(&clientaddr,0,sizeof(clientaddr));
|
||||
msg.msg_name=&clientaddr;
|
||||
msg.msg_namelen = sizeof(clientaddr);
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control=&cmsg;
|
||||
msg.msg_controllen = sizeof(cmsg);
|
||||
|
||||
|
||||
char bootpmagic[4] = {0x63,0x82,0x53,0x63};
|
||||
int pktsize;
|
||||
int doexit=0;
|
||||
port = 4011;
|
||||
memset(&hint,0,sizeof(hint));
|
||||
hint.ai_family = PF_INET; /* Would've done UNSPEC, but it doesn't work right and this is heavily v4 specific anyway */
|
||||
hint.ai_socktype = SOCK_DGRAM;
|
||||
hint.ai_flags = AI_PASSIVE;
|
||||
getaddrinfo(NULL,"4011",&hint,&res);
|
||||
serverfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (!serverfd) { fprintf(stderr,"That's odd...\n"); }
|
||||
setsockopt(serverfd,IPPROTO_IP,IP_PKTINFO,&getpktinfo,sizeof(getpktinfo));
|
||||
if (bind(serverfd,res->ai_addr ,res->ai_addrlen) < 0) {
|
||||
fprintf(stderr,"Unable to bind 4011");
|
||||
exit(1);
|
||||
}
|
||||
while (!doexit) {
|
||||
pktsize = recvmsg(serverfd,&msg,0);
|
||||
if (pktsize < 320) {
|
||||
continue;
|
||||
}
|
||||
if (clientpacket[0] != 1 || memcmp(clientpacket+0xec,bootpmagic,4)) {
|
||||
continue;
|
||||
}
|
||||
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg,cmsgptr)) {
|
||||
if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) {
|
||||
myip = ((struct in_pktinfo*)(CMSG_DATA(cmsgptr)))->ipi_addr.s_addr;
|
||||
}
|
||||
}
|
||||
clientpacket[0] = 2; //change to a reply
|
||||
myip = htonl(myip); //endian neutral change
|
||||
clientpacket[0x14] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
|
||||
clientpacket[0x15] = (myip>>16)&0xff;
|
||||
clientpacket[0x16] = (myip>>8)&0xff;
|
||||
clientpacket[0x17] = (myip)&0xff;
|
||||
txtptr = clientpacket+0x6c;
|
||||
strncpy(txtptr,"Boot/bootmgfw.efi",128); // keeping 128 in there just in case someone changes the string
|
||||
clientpacket[0xf0]=0x35; //DHCP MSG type
|
||||
clientpacket[0xf1]=0x1; // LEN of 1
|
||||
clientpacket[0xf2]=0x5; //DHCP ACK
|
||||
clientpacket[0xf3]=0x36; //DHCP server identifier
|
||||
clientpacket[0xf4]=0x4; //DHCP server identifier length
|
||||
clientpacket[0xf5] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
|
||||
clientpacket[0xf6] = (myip>>16)&0xff;
|
||||
clientpacket[0xf7] = (myip>>8)&0xff;
|
||||
clientpacket[0xf8] = (myip)&0xff;
|
||||
clientpacket[0xf9] = 0xfc; // dhcp 252 'proxy', but coopeted by bootmgfw, it's actually suggesting the boot config file
|
||||
clientpacket[0xfa] = 9; //length of 9
|
||||
txtptr = clientpacket+0xfb;
|
||||
strncpy(txtptr,"Boot/BCD",8);
|
||||
clientpacket[0x103]=0;
|
||||
clientpacket[0x104]=0xff;
|
||||
sendto(serverfd,clientpacket,pktsize,0,(struct sockaddr*)&clientaddr,sizeof(clientaddr));
|
||||
}
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
|
||||
// the chunk size for each alloc
|
||||
int chunknum = 200;
|
||||
int doreload = 0;
|
||||
int verbose = 0;
|
||||
char logmsg[50];
|
||||
|
||||
// the struct to store the winpe configuration for each node
|
||||
struct nodecfg {
|
||||
char node[50];
|
||||
char data[150];
|
||||
};
|
||||
|
||||
char *data = NULL; // the ptr to the array of all node config
|
||||
int nodenum = 0;
|
||||
|
||||
// trigger the main program to reload configuration file
|
||||
void reload(int sig) {
|
||||
doreload = 1;
|
||||
}
|
||||
// the subroutine which is used to load configuration from
|
||||
// /var/lib/xcat/proxydhcp.cfg to *data
|
||||
void loadcfg () {
|
||||
nodenum = 0;
|
||||
free(data);
|
||||
data = NULL;
|
||||
doreload = 0;
|
||||
|
||||
char *dp = NULL;
|
||||
|
||||
FILE *fp;
|
||||
fp = fopen("/var/lib/xcat/proxydhcp.cfg", "r");
|
||||
if (fp) {
|
||||
int num = chunknum;
|
||||
int rtime = 1;
|
||||
while (num == chunknum) {
|
||||
// realloc the chunknum size of memory each to save memory usage
|
||||
data = realloc(data, sizeof(struct nodecfg) * chunknum * rtime);
|
||||
if (NULL == data) {
|
||||
fprintf (stderr, "Cannot get enough memory.\n");
|
||||
free (data);
|
||||
return;
|
||||
}
|
||||
dp = data + sizeof(struct nodecfg) * chunknum * (rtime - 1);
|
||||
memset(dp, 0, sizeof(struct nodecfg) * chunknum);
|
||||
num = fread(dp, sizeof (struct nodecfg), chunknum, fp);
|
||||
nodenum += num;
|
||||
rtime++;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
// get the path of winpe from configuration file which is stored in *data
|
||||
char *getwinpepath(char *node) {
|
||||
int i;
|
||||
struct nodecfg *nc = (struct nodecfg *)data;
|
||||
for (i=0; i<nodenum;i++) {
|
||||
if (0 == strcmp(nc->node, node)) {
|
||||
return nc->data;
|
||||
}
|
||||
nc++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "-V") == 0) {
|
||||
verbose = 1;
|
||||
setlogmask(LOG_UPTO(LOG_DEBUG));
|
||||
openlog("proxydhcp", LOG_NDELAY, LOG_LOCAL0);
|
||||
}
|
||||
}
|
||||
|
||||
// regist my pid to /var/run/xcat/proxydhcp.pid
|
||||
int pid = getpid();
|
||||
FILE *pidf = fopen ("/var/run/xcat/proxydhcp.pid", "w");
|
||||
if (pidf) {
|
||||
fprintf(pidf, "%d", pid);
|
||||
fclose (pidf);
|
||||
} else {
|
||||
fprintf (stderr, "Cannot open /var/run/xcat/proxydhcp.pid\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load configuration at first start
|
||||
loadcfg();
|
||||
|
||||
// regist signal SIGUSR1 for triggering reload configuration from outside
|
||||
struct sigaction sigact;
|
||||
sigact.sa_handler = &reload;
|
||||
sigaction(SIGUSR1, &sigact, NULL);
|
||||
|
||||
int serverfd,port;
|
||||
int getpktinfo = 1;
|
||||
struct addrinfo hint, *res;
|
||||
char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
char clientpacket[1024];
|
||||
struct sockaddr_in clientaddr;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsgptr;
|
||||
struct iovec iov[1];
|
||||
unsigned int myip, clientip;
|
||||
char *txtptr;
|
||||
iov[0].iov_base = clientpacket;
|
||||
iov[0].iov_len = 1024;
|
||||
memset(&msg,0,sizeof(msg));
|
||||
memset(&clientaddr,0,sizeof(clientaddr));
|
||||
msg.msg_name=&clientaddr;
|
||||
msg.msg_namelen = sizeof(clientaddr);
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control=&cmsg;
|
||||
msg.msg_controllen = sizeof(cmsg);
|
||||
|
||||
char defaultwinpe[20] = "Boot/bootmgfw.efi";
|
||||
char bootpmagic[4] = {0x63,0x82,0x53,0x63};
|
||||
int pktsize;
|
||||
int doexit=0;
|
||||
port = 4011;
|
||||
memset(&hint,0,sizeof(hint));
|
||||
hint.ai_family = PF_INET; /* Would've done UNSPEC, but it doesn't work right and this is heavily v4 specific anyway */
|
||||
hint.ai_socktype = SOCK_DGRAM;
|
||||
hint.ai_flags = AI_PASSIVE;
|
||||
getaddrinfo(NULL,"4011",&hint,&res);
|
||||
serverfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (!serverfd) { fprintf(stderr,"That's odd...\n"); }
|
||||
setsockopt(serverfd,IPPROTO_IP,IP_PKTINFO,&getpktinfo,sizeof(getpktinfo));
|
||||
if (bind(serverfd,res->ai_addr ,res->ai_addrlen) < 0) {
|
||||
fprintf(stderr,"Unable to bind 4011");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
while (!doexit) {
|
||||
// use select to wait for the 4011 request packages coming
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(serverfd, &fds);
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 30;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
int rc;
|
||||
if ((rc = select(serverfd+1,&fds,0,0, &timeout)) <= 0) {
|
||||
if (doreload) {
|
||||
loadcfg();
|
||||
fprintf(stderr, "load in select\n");
|
||||
}
|
||||
if (verbose) {syslog(LOG_DEBUG, "reload /var/lib/xcat/proxydhcp.cfg\n");}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (doreload) {
|
||||
loadcfg();
|
||||
if (verbose) {syslog(LOG_DEBUG, "reload /var/lib/xcat/proxydhcp.cfg\n");}
|
||||
}
|
||||
|
||||
pktsize = recvmsg(serverfd,&msg,0);
|
||||
if (pktsize < 320) {
|
||||
continue;
|
||||
}
|
||||
if (clientpacket[0] != 1 || memcmp(clientpacket+0xec,bootpmagic,4)) {
|
||||
continue;
|
||||
}
|
||||
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg,cmsgptr)) {
|
||||
if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) {
|
||||
myip = ((struct in_pktinfo*)(CMSG_DATA(cmsgptr)))->ipi_addr.s_addr;
|
||||
}
|
||||
}
|
||||
|
||||
// get the ip of dhcp client
|
||||
clientip = 0;
|
||||
int i;
|
||||
for (i = 0; i< 4; i++) {
|
||||
clientip = clientip << 8;
|
||||
clientip += (unsigned char)clientpacket[15-i];
|
||||
}
|
||||
// get the winpe path
|
||||
struct hostent *host = gethostbyaddr(&clientip, sizeof(clientip), AF_INET);
|
||||
char *winpepath = defaultwinpe;
|
||||
if (host) {
|
||||
if (host->h_name) {
|
||||
// remove the domain part from hostname
|
||||
char *place = strstr(host->h_name, ".");
|
||||
if (place) {
|
||||
*place = '\0';
|
||||
}
|
||||
|
||||
winpepath = getwinpepath(host->h_name);
|
||||
if (winpepath == NULL) {
|
||||
winpepath = defaultwinpe;
|
||||
}
|
||||
if (verbose) {
|
||||
sprintf(logmsg, "Received proxydhcp request from %s\n", host->h_name);
|
||||
syslog(LOG_DEBUG, logmsg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
winpepath = defaultwinpe;
|
||||
}
|
||||
|
||||
// get the Vendor class identifier
|
||||
char *arch = NULL;
|
||||
unsigned char *p = clientpacket + 0xf0;
|
||||
while (*p != 0xff && p < (unsigned char *)clientpacket + pktsize) {
|
||||
if (*p == 60) {
|
||||
arch = p + 0x11;
|
||||
break;
|
||||
} else {
|
||||
p += *(p+1) + 2;
|
||||
}
|
||||
}
|
||||
|
||||
char winboot[50]; // the bootload of winpe
|
||||
memset(winboot, 0, 50);
|
||||
if (0 == memcmp(arch, "00000", 5)) { // bios boot mode
|
||||
strcpy(winboot, winpepath);
|
||||
strcat(winboot, "Boot/pxeboot.0");
|
||||
} else if (0 == memcmp(arch, "00007", 5)) { // uefi boot mode
|
||||
strcpy(winboot, winpepath);
|
||||
strcat(winboot, "Boot/bootmgfw.efi");
|
||||
}
|
||||
|
||||
clientpacket[0] = 2; //change to a reply
|
||||
myip = htonl(myip); //endian neutral change
|
||||
clientpacket[0x14] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
|
||||
clientpacket[0x15] = (myip>>16)&0xff;
|
||||
clientpacket[0x16] = (myip>>8)&0xff;
|
||||
clientpacket[0x17] = (myip)&0xff;
|
||||
txtptr = clientpacket+0x6c;
|
||||
strncpy(txtptr, winboot ,128); // keeping 128 in there just in case someone changes the string
|
||||
//strncpy(txtptr,"winboot/new/Boot/bootmgfw.efi",128); // keeping 128 in there just in case someone changes the string
|
||||
//strncpy(txtptr,"Boot/pxeboot.0",128); // keeping 128 in there just in case someone changes the string
|
||||
clientpacket[0xf0]=0x35; //DHCP MSG type
|
||||
clientpacket[0xf1]=0x1; // LEN of 1
|
||||
clientpacket[0xf2]=0x5; //DHCP ACK
|
||||
clientpacket[0xf3]=0x36; //DHCP server identifier
|
||||
clientpacket[0xf4]=0x4; //DHCP server identifier length
|
||||
clientpacket[0xf5] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
|
||||
clientpacket[0xf6] = (myip>>16)&0xff;
|
||||
clientpacket[0xf7] = (myip>>8)&0xff;
|
||||
clientpacket[0xf8] = (myip)&0xff;
|
||||
|
||||
char winBCD[50];
|
||||
strcpy(winBCD, winpepath);
|
||||
strcat(winBCD, "Boot/BCD");
|
||||
clientpacket[0xf9] = 0xfc; // dhcp 252 'proxy', but coopeted by bootmgfw, it's actually suggesting the boot config file
|
||||
clientpacket[0xfa] = strlen(winBCD) + 1; //length of 9
|
||||
txtptr = clientpacket+0xfb;
|
||||
strncpy(txtptr, winBCD, strlen(winBCD));
|
||||
clientpacket[0xfa + strlen(winBCD) + 1] = 0;
|
||||
clientpacket[0xfa + strlen(winBCD) + 2] = 0xff;
|
||||
sendto(serverfd,clientpacket,pktsize,0,(struct sockaddr*)&clientaddr,sizeof(clientaddr));
|
||||
|
||||
if (verbose) {
|
||||
sprintf(logmsg, "Path of bootloader:%s. Path of BCD:%s\n", winboot, winBCD);
|
||||
syslog(LOG_DEBUG, logmsg);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) { closelog();}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* IBM(c) 2013 EPL licens http://www.eclipse.org/legal/epl-v10.html
|
||||
* Jarrod Johnson - jbjohnso@us.ibm.com
|
||||
* This program periodically transmits a udp packet to designated xCAT server
|
||||
* It waits for an 'ok' and then exits
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
int main(int argc, char* argv[]) {
|
||||
int server;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *results,*cur;
|
||||
struct timeval timeout;
|
||||
int canread=0;
|
||||
char buffer[128];
|
||||
srand(time(NULL));
|
||||
memset(&hints,0,sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
fd_set selectset;
|
||||
getaddrinfo(argv[1],argv[2],&hints,&results);
|
||||
server = socket(AF_UNSPEC,SOCK_DGRAM,17);
|
||||
for (cur=results; cur != NULL; cur = cur->ai_next) {
|
||||
server = socket(cur->ai_family,cur->ai_socktype,cur->ai_protocol);
|
||||
if (server == -1) continue;
|
||||
if (connect(server,cur->ai_addr,cur->ai_addrlen) != -1) break;
|
||||
close(server);
|
||||
}
|
||||
FD_ZERO(&selectset);
|
||||
FD_SET(server,&selectset);
|
||||
while (1) {
|
||||
timeout.tv_sec = rand() % 120+60;
|
||||
timeout.tv_usec = rand() % 10000;
|
||||
write(server,"resourcerequest: xcatd\n",strlen("resourcerequest: xcatd\n"));
|
||||
canread = select(FD_SETSIZE,&selectset,NULL,NULL,&timeout);
|
||||
if (canread) {
|
||||
read(server,buffer,sizeof(buffer));
|
||||
if (strncmp(buffer,"resourcerequest: ok",strlen("resourcerequest: ok"))==0) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
# postscript (stateful install) or with the otherpkgs processing of
|
||||
# genimage (stateless/statelite install). This script will install any
|
||||
# gpfs update rpms that exist on the xCAT management node in the
|
||||
# /install/post/gpfs_updates directory.
|
||||
# /install/post/otherpkgs/gpfs_updates directory.
|
||||
# This is necessary because the GPFS updates can ONLY be installed
|
||||
# after the base rpms have been installed, and the update rpms cannot
|
||||
# exist in any rpm repositories used by xCAT otherpkgs processing
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
xcat-openstack-baremetal for Debian
|
||||
-----------------------------------
|
||||
|
||||
<possible notes regarding this package - if none, delete this file>
|
||||
|
||||
-- root <root@unknown> Wed, 12 Mar 2014 01:47:54 -0700
|
||||
@@ -0,0 +1,9 @@
|
||||
xcat-openstack-baremetal for Debian
|
||||
-----------------------------------
|
||||
|
||||
<this file describes information about the source package, see Debian policy
|
||||
manual section 4.14. You WILL either need to modify or delete this file>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
xcat-openstack-baremetal (2.8.4-1) unstable; urgency=low
|
||||
|
||||
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
|
||||
|
||||
-- root <root@unknown> Wed, 12 Mar 2014 01:47:54 -0700
|
||||
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,14 @@
|
||||
Source: xcat-openstack-baremetal
|
||||
Section: admin
|
||||
Priority: extra
|
||||
Maintainer: xCAT <xcat-user@lists.sourceforge.net>
|
||||
Build-Depends: debhelper (>= 8.0.0)
|
||||
Standards-Version: 3.9.4
|
||||
Homepage: http://xcat.sourceforge.net/
|
||||
#Vcs-Git: git://git.debian.org/collab-maint/xcat-openstack-baremetal.git
|
||||
#Vcs-Browser: http://git.debian.org/?p=collab-maint/xcat-openstack-baremetal.git;a=summary
|
||||
|
||||
Package: xcat-openstack-baremetal
|
||||
Architecture: all
|
||||
Depends: xCAT-client
|
||||
Description: Executables and data of the xCAT baremetal driver for OpenStack
|
||||
@@ -0,0 +1,38 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: xcat-openstack-baremetal
|
||||
Source: <url://example.com>
|
||||
|
||||
Files: *
|
||||
Copyright: <years> <put author's name and email here>
|
||||
<years> <likewise for another author>
|
||||
License: <special license>
|
||||
<Put the license of the package here indented by 1 space>
|
||||
<This follows the format of Description: lines in control file>
|
||||
.
|
||||
<Including paragraphs>
|
||||
|
||||
# If you want to use GPL v2 or later for the /debian/* files use
|
||||
# the following clauses, or change it to suit. Delete these two lines
|
||||
Files: debian/*
|
||||
Copyright: 2014 root <root@unknown>
|
||||
License: GPL-2+
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
# Please also look if there are files or directories which have a
|
||||
# different copyright/license attached and list them here.
|
||||
# Please avoid to pick license terms that are more restrictive than the
|
||||
# packaged work, as it may make Debian's contributions unacceptable upstream.
|
||||
@@ -0,0 +1,7 @@
|
||||
opt/xcat/bin
|
||||
opt/xcat/sbin
|
||||
opt/xcat/lib/perl/xCAT_plugin
|
||||
opt/xcat/lib/python/xcat/openstack/baremetal
|
||||
opt/xcat/share/xcat/openstack/postscripts
|
||||
opt/xcat/share/man/man1
|
||||
opt/xcat/share/doc/man1
|
||||
@@ -0,0 +1,2 @@
|
||||
xcat-openstack-baremetal_2.8.4-1_all.deb admin extra
|
||||
xcat-openstack-baremetal_2.8.4-1_all.deb admin extra
|
||||
@@ -0,0 +1,6 @@
|
||||
lib/* opt/xcat/lib/
|
||||
share/xcat/openstack/postscripts/* opt/xcat/share/xcat/openstack/postscripts/
|
||||
share/man/man1/* opt/xcat/share/man/man1/
|
||||
share/doc/man1/* opt/xcat/share/doc/man1/
|
||||
|
||||
|
||||
+5
-8
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# postinst script for xcat-genesis
|
||||
# postinst script for xcat-openstack-baremetal
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
@@ -20,13 +20,10 @@ set -e
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
if [ -f /tmp/xCAT-genesis_upgrade.tmp ];then
|
||||
if [ -f "/proc/cmdline" ]; then # prevent running it during install into chroot image
|
||||
. /etc/profile.d/xcat.sh
|
||||
mknb x86_64
|
||||
fi
|
||||
rm /tmp/xCAT-genesis_upgrade.tmp
|
||||
fi
|
||||
#copy the postscripts under /installl/postscripts directory on MN only
|
||||
if [ -f "/etc/xCATMN" ]; then
|
||||
cp /opt/xcat/share/xcat/openstack/postscripts/* /install/postscripts/
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
# prerm script for xcat-openstack-baremetal
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
#remove postscripts under /installl/postscripts directory on MN only
|
||||
if [ -f "/etc/xCATMN" ]; then
|
||||
for fn in /opt/xcat/share/xcat/openstack/postscripts/*
|
||||
do
|
||||
bn=`basename $fn`
|
||||
rm /install/postscripts/$bn
|
||||
done
|
||||
fi
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
build:
|
||||
pwd
|
||||
`pwd`/xpod2man
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -d
|
||||
|
||||
install:
|
||||
pwd
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installdirs
|
||||
dh_install -X".svn"
|
||||
chmod 444 `pwd`/debian/xcat-openstack-baremetal/opt/xcat/share/man/man1/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack-baremetal/opt/xcat/share/doc/man1/*
|
||||
dh_link
|
||||
|
||||
binary-indep: build install
|
||||
pwd
|
||||
export
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary-arch:
|
||||
pwd
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
@@ -0,0 +1 @@
|
||||
1.0
|
||||
@@ -0,0 +1,201 @@
|
||||
dh_installdirs
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
dh_installdirs
|
||||
dh_install
|
||||
dh_link
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
dh_builddeb
|
||||
@@ -0,0 +1,4 @@
|
||||
opt/xcat/bin/xcatclient opt/xcat/sbin/deploy_ops_bm_node
|
||||
opt/xcat/bin/xcatclient opt/xcat/sbin/cleanup_ops_bm_node
|
||||
opt/xcat/bin/xcatclient opt/xcat/bin/opsaddbmnode
|
||||
opt/xcat/bin/xcatclientnnr opt/xcat/bin/opsaddimage
|
||||
@@ -0,0 +1 @@
|
||||
misc:Depends=
|
||||
@@ -0,0 +1,904 @@
|
||||
# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
package xCAT_plugin::openstack;
|
||||
BEGIN
|
||||
{
|
||||
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
||||
}
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use xCAT::Utils;
|
||||
use xCAT::TableUtils;
|
||||
use xCAT::SvrUtils;
|
||||
use xCAT::NetworkUtils;
|
||||
use xCAT::Table;
|
||||
use Data::Dumper;
|
||||
use File::Path;
|
||||
use File::Copy;
|
||||
use Getopt::Long;
|
||||
Getopt::Long::Configure("bundling");
|
||||
Getopt::Long::Configure("pass_through");
|
||||
|
||||
|
||||
sub handled_commands {
|
||||
return {
|
||||
opsaddbmnode => "openstack", #external command
|
||||
opsaddimage => "openstack", #external command
|
||||
deploy_ops_bm_node => "openstack", #internal command called from the baremetal driver
|
||||
cleanup_ops_bm_node => "openstack", #internal command called from the baremetal driver
|
||||
}
|
||||
}
|
||||
|
||||
sub process_request {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
my $command = $request->{command}->[0];
|
||||
|
||||
if ($command eq "opsaddbmnode") {
|
||||
return opsaddbmnode($request, $callback, $doreq);
|
||||
} elsif ($command eq "opsaddimage") {
|
||||
return opsaddimage($request, $callback, $doreq);
|
||||
} elsif ($command eq "deploy_ops_bm_node") {
|
||||
return deploy_ops_bm_node($request, $callback, $doreq);
|
||||
} elsif ($command eq "cleanup_ops_bm_node") {
|
||||
return cleanup_ops_bm_node($request, $callback, $doreq);
|
||||
} else {
|
||||
$callback->({error=>["Unsupported command: $command."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 opsaddbmnode
|
||||
This function takes the xCAT nodes and register them
|
||||
as the OpenStack baremetal nodes
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub opsaddbmnode {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
|
||||
@ARGV = @{$request->{arg}};
|
||||
Getopt::Long::Configure("bundling");
|
||||
Getopt::Long::Configure("no_pass_through");
|
||||
|
||||
my $help;
|
||||
my $version;
|
||||
my $host;
|
||||
|
||||
if(!GetOptions(
|
||||
'h|help' => \$help,
|
||||
'v|version' => \$version,
|
||||
's=s' => \$host,
|
||||
))
|
||||
{
|
||||
&opsaddbmnode_usage($callback);
|
||||
return 1;
|
||||
}
|
||||
# display the usage if -h or --help is specified
|
||||
if ($help) {
|
||||
&opsaddbmnode_usage($callback);
|
||||
return 0;
|
||||
}
|
||||
# display the version statement if -v or --verison is specified
|
||||
if ($version)
|
||||
{
|
||||
my $rsp={};
|
||||
$rsp->{data}->[0]= xCAT::Utils->Version();
|
||||
$callback->($rsp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!$request->{node}) {
|
||||
$callback->({error=>["Please specify at least one node."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
if (!$host) {
|
||||
$callback->({error=>["Please specify the OpenStack compute host name with -s flag."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $nodes = $request->{node};
|
||||
|
||||
#get node mgt
|
||||
my $nodehmhash;
|
||||
my $nodehmtab = xCAT::Table->new("nodehm");
|
||||
if ($nodehmtab) {
|
||||
$nodehmhash = $nodehmtab->getNodesAttribs($nodes,['power', 'mgt']);
|
||||
}
|
||||
|
||||
#get bmc info for the nodes
|
||||
my $ipmitab = xCAT::Table->new("ipmi", -create => 0);
|
||||
my $tmp_ipmi;
|
||||
if ($ipmitab) {
|
||||
$tmp_ipmi = $ipmitab->getNodesAttribs($nodes, ['bmc','username', 'password'], prefetchcache=>1);
|
||||
#print Dumper($tmp_ipmi);
|
||||
} else {
|
||||
$callback->({error=>["Cannot open the ipmi table."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
|
||||
#get mac for the nodes
|
||||
my $mactab = xCAT::Table->new("mac", -create => 0);
|
||||
my $tmp_mac;
|
||||
if ($mactab) {
|
||||
$tmp_mac = $mactab->getNodesAttribs($nodes, ['mac'], prefetchcache=>1);
|
||||
#print Dumper($tmp_mac);
|
||||
} else {
|
||||
$callback->({error=>["Cannot open the mac table."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
|
||||
#get cpu, memory and disk info for the nodes
|
||||
my $hwinvtab = xCAT::Table->new("hwinv", -create => 0);
|
||||
my $tmp_hwinv;
|
||||
if ($hwinvtab) {
|
||||
$tmp_hwinv = $hwinvtab->getNodesAttribs($nodes, ['cpucount', 'memory', 'disksize'], prefetchcache=>1);
|
||||
#print Dumper($tmp_hwinv);
|
||||
} else {
|
||||
$callback->({error=>["Cannot open the hwinv table."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
|
||||
#get default username and password for bmc
|
||||
my $d_bmcuser;
|
||||
my $d_bmcpasswd;
|
||||
my $passtab = xCAT::Table->new('passwd');
|
||||
if ($passtab) {
|
||||
($tmp_passwd)=$passtab->getAttribs({'key'=>'ipmi'},'username','password');
|
||||
if (defined($tmp_passwd)) {
|
||||
$d_bmcuser = $tmp_passwd->{username};
|
||||
$d_bmcpasswd = $tmp_passwd->{password};
|
||||
}
|
||||
}
|
||||
|
||||
#print "d_bmcuser=$d_bmcuser, d_bmcpasswd=$d_bmcpasswd \n";
|
||||
foreach my $node (@$nodes) {
|
||||
#collect the node infomation needed for each node, some info
|
||||
my $mgt;
|
||||
my $ref_nodehm = $nodehmhash->{$node}->[0];
|
||||
if ($ref_nodehm) {
|
||||
if ($ref_nodehm->{'power'}) {
|
||||
$mgt = $ref_nodehm->{'power'};
|
||||
} elsif ($ref_nodehm->{'mgt'}) {
|
||||
$mgt = $ref_nodehm->{'mgt'};
|
||||
}
|
||||
}
|
||||
|
||||
my ($bmc, $bmc_user, $bmc_password, $mac, $cpu, $memory, $disk);
|
||||
if (($mgt) && ($mgt eq 'ipmi')) {
|
||||
my $ref_ipmi = $tmp_ipmi->{$node}->[0];
|
||||
if ($ref_ipmi) {
|
||||
if (exists($ref_ipmi->{bmc})) {
|
||||
$bmc = $ref_ipmi->{bmc};
|
||||
}
|
||||
if (exists($ref_ipmi->{username})) {
|
||||
$bmc_user = $ref_ipmi->{username};
|
||||
if (exists($ref_ipmi->{password})) {
|
||||
$bmc_password = $ref_ipmi->{password};
|
||||
}
|
||||
} else { #take the default if they cannot be found on ipmi table
|
||||
if ($d_bmcuser) { $bmc_user = $d_bmcuser; }
|
||||
if ($d_bmcpasswd) { $bmc_password = $d_bmcpasswd; }
|
||||
}
|
||||
}
|
||||
} # else { # for hardware control point other than ipmi, just fake it in OpenStack.
|
||||
#$bmc = "0.0.0.0";
|
||||
#$bmc_user = "xCAT";
|
||||
#$bmc_password = "xCAT";
|
||||
#}
|
||||
|
||||
my $ref_mac = $tmp_mac->{$node}->[0];
|
||||
if ($ref_mac) {
|
||||
if (exists($ref_mac->{mac})) {
|
||||
$mac = $ref_mac->{mac};
|
||||
}
|
||||
}
|
||||
|
||||
$ref_hwinv = $tmp_hwinv->{$node}->[0];
|
||||
if ($ref_hwinv) {
|
||||
if (exists($ref_hwinv->{cpucount})) {
|
||||
$cpu = $ref_hwinv->{cpucount};
|
||||
}
|
||||
if (exists($ref_hwinv->{memory})) {
|
||||
$memory = $ref_hwinv->{memory};
|
||||
#TODO: what if the unit is not in MB? We need to convert it to MB
|
||||
$memory =~ s/MB|mb//g;
|
||||
}
|
||||
if (exists($ref_hwinv->{disksize})) {
|
||||
#The format of the the disk size is: sda:250GB,sdb:250GB or just 250GB
|
||||
#We need to get the size of the first one
|
||||
$disk = $ref_hwinv->{disksize};
|
||||
my @a = split(',', $disk);
|
||||
my @b = split(':', $a[0]);
|
||||
if (@b > 1) {
|
||||
$disk = $b[1];
|
||||
} else {
|
||||
$disk = $b[0];
|
||||
}
|
||||
#print "a=@a, b=@b\n";
|
||||
#TODO: what if the unit is not in GB? We need to convert it to MB
|
||||
$disk =~ s/GB|gb//g;
|
||||
}
|
||||
}
|
||||
|
||||
#some info are mendatory
|
||||
if (!$mac) {
|
||||
$callback->({error=>["Mac address is not defined in the mac table for node $node."],errorcode=>[1]});
|
||||
next;
|
||||
}
|
||||
if (!$cpu) {
|
||||
#default cpu count is 1
|
||||
$cpu = 1;
|
||||
}
|
||||
if (!$memory) {
|
||||
#default memory size is 1024MB=1GB
|
||||
$memory = 1024;
|
||||
}
|
||||
if (!$disk) {
|
||||
#default disk size is 1GB
|
||||
$disk = 1;
|
||||
}
|
||||
|
||||
#print "$bmc, $bmc_user, $bmc_password, $mac, $cpu, $memory, $disk\n";
|
||||
|
||||
#call OpenStack command to add the node into the OpenStack as
|
||||
#a baremetal node.
|
||||
my $cmd_tmp = "nova baremetal-node-create";
|
||||
if ($bmc) {
|
||||
#make sure it is an ip address
|
||||
if (($bmc !~ /\d+\.\d+\.\d+\.\d+/) && ($bmc !~ /:/)) {
|
||||
$bmc = xCAT::NetworkUtils->getipaddr($bmc);
|
||||
}
|
||||
$cmd_tmp .= " --pm_address=$bmc";
|
||||
}
|
||||
if ($bmc_user) {
|
||||
$cmd_tmp .= " --pm_user=$bmc_user";
|
||||
}
|
||||
if ($bmc_password) {
|
||||
$cmd_tmp .= " --pm_password=$bmc_password";
|
||||
}
|
||||
$cmd_tmp .= " $host $cpu $memory $disk $mac";
|
||||
|
||||
my $cmd = qq~source \~/openrc;$cmd_tmp~;
|
||||
#print "cmd=$cmd\n";
|
||||
my $output =
|
||||
xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$host], $cmd, 0);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "OpenStack creating baremetal node $node:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 opsaddimage
|
||||
This function takes the xCAT nodes and register them
|
||||
as the OpenStack baremetal nodes
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub opsaddimage {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
|
||||
@ARGV = @{$request->{arg}};
|
||||
Getopt::Long::Configure("bundling");
|
||||
Getopt::Long::Configure("no_pass_through");
|
||||
|
||||
my $help;
|
||||
my $version;
|
||||
#my $cloud;
|
||||
my $ops_img_names;
|
||||
my $controller;
|
||||
|
||||
if(!GetOptions(
|
||||
'h|help' => \$help,
|
||||
'v|version' => \$version,
|
||||
'c=s' => \$controller,
|
||||
'n=s' => \$ops_img_names,
|
||||
))
|
||||
{
|
||||
&opsaddimage_usage($callback);
|
||||
return 1;
|
||||
}
|
||||
# display the usage if -h or --help is specified
|
||||
if ($help) {
|
||||
&opsaddimage_usage($callback);
|
||||
return 0;
|
||||
}
|
||||
# display the version statement if -v or --verison is specified
|
||||
if ($version)
|
||||
{
|
||||
my $rsp={};
|
||||
$rsp->{data}->[0]= xCAT::Utils->Version();
|
||||
$callback->($rsp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (@ARGV ==0) {
|
||||
$callback->({error=>["Please specify an image name or a list of image names."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
|
||||
#make sure the input cloud name is valid.
|
||||
#if (!$cloud) {
|
||||
# $callback->({error=>["Please specify the name of the cloud with -c flag."],errorcode=>[1]});
|
||||
# return 1;
|
||||
#} else {
|
||||
# my $cloudstab = xCAT::Table->new('clouds', -create => 0);
|
||||
# my @et = $cloudstab->getAllAttribs('name', 'controller');
|
||||
# if(@et) {
|
||||
# foreach my $tmp_et (@et) {
|
||||
# if ($tmp_et->{name} eq $cloud) {
|
||||
# if ($tmp_et->{controller}) {
|
||||
# $controller = $tmp_et->{controller};
|
||||
# last;
|
||||
# } else {
|
||||
# $callback->({error=>["Please specify the controller in the clouds table for the cloud: $cloud."],errorcode=>[1]});
|
||||
# return 1;
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
||||
if (!$controller) {
|
||||
$callback->({error=>["Please specify the OpenStack controller node name with -c."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
#}
|
||||
|
||||
#make sure that the images from the command are valid image names
|
||||
@images = split(',', $ARGV[0]);
|
||||
@new_names = ();
|
||||
if ($ops_img_names) {
|
||||
@new_names = split(',', $ops_img_names);
|
||||
}
|
||||
#print "images=@images, new image names=@new_names, controller=$controller\n";
|
||||
|
||||
my $image_hash = {};
|
||||
my $osimgtab = xCAT::Table->new('osimage', -create => 0);
|
||||
my @et = $osimgtab->getAllAttribs('imagename');
|
||||
if(@et) {
|
||||
foreach my $tmp_et (@et) {
|
||||
$image_hash->{$tmp_et->{imagename}}{'xCAT'} = 1;
|
||||
}
|
||||
}
|
||||
my @bad_images;
|
||||
foreach my $image (@images) {
|
||||
if (!exists($image_hash->{$image})) {
|
||||
push @bad_images, $image;
|
||||
}
|
||||
}
|
||||
if (@bad_images > 0) {
|
||||
$callback->({error=>["The following images cannot be found in xCAT osimage table:\n " . join("\n ", @bad_images) . "\n"],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $index=0;
|
||||
foreach my $image (@images) {
|
||||
my $new_name = shift(@new_names);
|
||||
if (!$new_name) {
|
||||
$new_name = $image; #the default new name is xCAT image name
|
||||
}
|
||||
my $cmd_tmp = "glance image-create --name $new_name --public --disk-format qcow2 --container-format bare --property xcat_image_name=\'$image\' < /tmp/$image.qcow2";
|
||||
|
||||
my $cmd = qq~touch /tmp/$image.qcow2;source \~/openrc;$cmd_tmp;rm /tmp/$image.qcow2~;
|
||||
#print "cmd=$cmd\ncontroller=$controller\n";
|
||||
my $output =
|
||||
xCAT::InstUtils->xcmd($callback, $doreq, "xdsh", [$controller], $cmd, 0);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "OpenStack creating image $new_name:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 deploy_ops_bm_node
|
||||
This is a internel command called by OpenStack xCAT-baremetal driver.
|
||||
It prepares the node by adding the config_ops_bm_node postbootscript
|
||||
to the postscript table for the node, then call nodeset and then boot
|
||||
the node up.
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub deploy_ops_bm_node {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
|
||||
@ARGV = @{$request->{arg}};
|
||||
Getopt::Long::Configure("bundling");
|
||||
Getopt::Long::Configure("no_pass_through");
|
||||
|
||||
my $node = $request->{node}->[0];
|
||||
|
||||
my $help;
|
||||
my $version;
|
||||
my $img_name;
|
||||
my $hostname;
|
||||
my $fixed_ip;
|
||||
my $netmask;
|
||||
|
||||
if(!GetOptions(
|
||||
'h|help' => \$help,
|
||||
'v|version' => \$version,
|
||||
'image=s' => \$img_name,
|
||||
'host=s' => \$hostname,
|
||||
'ip=s' => \$fixed_ip,
|
||||
'mask=s' => \$netmask,
|
||||
))
|
||||
{
|
||||
&deploy_ops_bm_node_usage($callback);
|
||||
return 1;
|
||||
}
|
||||
# display the usage if -h or --help is specified
|
||||
if ($help) {
|
||||
&deploy_ops_bm_node_usage($callback);
|
||||
return 0;
|
||||
}
|
||||
# display the version statement if -v or --verison is specified
|
||||
if ($version)
|
||||
{
|
||||
my $rsp={};
|
||||
$rsp->{data}->[0]= xCAT::Utils->Version();
|
||||
$callback->($rsp);
|
||||
return 0;
|
||||
}
|
||||
#print "node=$node, image=$img_name, host=$hostname, ip=$fixed_ip, mask=$netmask\n";
|
||||
|
||||
#validate the image name
|
||||
my $osimagetab = xCAT::Table->new('osimage', -create=>1);
|
||||
my $ref = $osimagetab->getAttribs({imagename => $img_name}, 'imagename');
|
||||
if (!$ref) {
|
||||
$callback->({error=>["Invalid image name: $img_name."],errorcode=>[1]});
|
||||
return 1;
|
||||
}
|
||||
|
||||
#check if the fixed ip is within the xCAT management network.
|
||||
#get the master ip address for the node then check if the master ip and
|
||||
#the OpenStack fixed_ip are on the same subnet.
|
||||
#my $same_nw = 0;
|
||||
#my $master = xCAT::TableUtils->GetMasterNodeName($node);
|
||||
#my $master_ip = xCAT::NetworkUtils->toIP($master);
|
||||
#if (xCAT::NetworkUtils::isInSameSubnet($master_ip, $fixed_ip, $netmask, 0)) {
|
||||
# $same_nw = 1;
|
||||
#}
|
||||
|
||||
|
||||
#add config_ops_bm_node to the node's postbootscript
|
||||
my $script = "config_ops_bm_node $hostname $fixed_ip $netmask";
|
||||
add_postscript($callback, $node, $script);
|
||||
|
||||
#run nodeset
|
||||
my $cmd = qq~osimage=$img_name~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["nodeset"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "nodeset:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#deploy the node now, supported nodehm.mgt values: ipmi, blade,fsp, hmc.
|
||||
my $hmtab = xCAT::Table->new('nodehm');
|
||||
my $hment = $hmtab->getNodeAttribs($node,['mgt']);
|
||||
if ($hment && $hment->{'mgt'}) {
|
||||
my $mgt = $hment->{'mgt'};
|
||||
if ($mgt eq 'ipmi') {
|
||||
deploy_bmc_node($callback, $doreq, $node);
|
||||
} elsif (($mgt eq 'blade') || ($mgt eq 'fsp')) {
|
||||
deploy_blade($callback, $doreq, $node);
|
||||
} elsif ($mgt eq 'hmc') {
|
||||
deploy_hmc_node($callback, $doreq, $node);
|
||||
} else {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "Node $node: nodehm.mgt=$mgt is not supported in the OpenStack cloud.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
#nodehm.mgt must setup for node
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "Node $node: nodehm.mgt cannot be empty in order to deploy.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Deploy a rack-mounted node
|
||||
sub deploy_bmc_node {
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
my $node = shift;
|
||||
|
||||
#set boot order
|
||||
my $cmd = qq~net~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["rsetboot"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "rsetboot:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
}
|
||||
|
||||
#reboot the node
|
||||
my $cmd = qq~boot~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["rpower"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "rpower:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Deploy a blade or fsp controlled node
|
||||
sub deploy_blade {
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
my $node = shift;
|
||||
|
||||
#set boot order
|
||||
my $cmd = qq~net~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["rbootseq"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "rbootseq:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
}
|
||||
|
||||
#reboot the node
|
||||
my $cmd = qq~boot~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["rpower"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "rpower:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Deploy a node controlled by HMC
|
||||
sub deploy_hmc_node {
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
my $node = shift;
|
||||
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["rnetboot"],
|
||||
node => [$node]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "rnetboot:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 cleanup_ops_bm_node
|
||||
This is a internel command called by OpenStack xCAT-baremetal driver.
|
||||
It undoes all the changes made by deploy_ops_bm_node command. It removes
|
||||
the config_ops_bmn_ode postbootscript from the postscript table for the
|
||||
node, removes the alias ip and then power off the node.
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub cleanup_ops_bm_node {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
|
||||
@ARGV = @{$request->{arg}};
|
||||
Getopt::Long::Configure("bundling");
|
||||
Getopt::Long::Configure("no_pass_through");
|
||||
|
||||
my $node = $request->{node}->[0];
|
||||
|
||||
my $help;
|
||||
my $version;
|
||||
my $fixed_ip;
|
||||
|
||||
if(!GetOptions(
|
||||
'h|help' => \$help,
|
||||
'v|version' => \$version,
|
||||
'ip=s' => \$fixed_ip,
|
||||
))
|
||||
{
|
||||
&cleanup_ops_bm_node_usage($callback);
|
||||
return 1;
|
||||
}
|
||||
# display the usage if -h or --help is specified
|
||||
if ($help) {
|
||||
&cleanup_ops_bm_node_usage($callback);
|
||||
return 0;
|
||||
}
|
||||
# display the version statement if -v or --verison is specified
|
||||
if ($version)
|
||||
{
|
||||
my $rsp={};
|
||||
$rsp->{data}->[0]= xCAT::Utils->Version();
|
||||
$callback->($rsp);
|
||||
return 0;
|
||||
}
|
||||
#print "node=$node, ip=$fixed_ip\n";
|
||||
|
||||
#removes the config_ops_bm_node postbootscript from the postscripts table
|
||||
remove_postscript($callback, $node, "config_ops_bm_node");
|
||||
|
||||
|
||||
#run updatenode to remove the ip alias
|
||||
my $cmd = qq~-P deconfig_ops_bm_node $fixed_ip~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["updatenode"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "updatenode:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
}
|
||||
|
||||
#turn the node power off
|
||||
$ssh_ok = 0;
|
||||
my $cmd = qq~stat~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["rpower"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "rpower:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
} else {
|
||||
if ($output !~ /: off/) {
|
||||
#power off the node
|
||||
my $cmd = qq~off~;
|
||||
my $output = xCAT::Utils->runxcmd(
|
||||
{command => ["rpower"],
|
||||
node => [$node],
|
||||
arg => [$cmd]},
|
||||
$doreq, -1, 1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
my $rsp;
|
||||
push @{$rsp->{data}}, "rpower:";
|
||||
push @{$rsp->{data}}, "$output";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
=head3 add_postscript
|
||||
|
||||
It adds the 'config_ops_bm_node' postbootscript to the
|
||||
postscript table for the given node.
|
||||
|
||||
=cut
|
||||
#-------------------------------------------------------
|
||||
sub add_postscript {
|
||||
my $callback=shift;
|
||||
my $node=shift;
|
||||
my $script=shift;
|
||||
#print "script=$script\n";
|
||||
|
||||
my $posttab=xCAT::Table->new("postscripts", -create =>1);
|
||||
my %setup_hash;
|
||||
my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]);
|
||||
my $found=0;
|
||||
if ($ref) {
|
||||
if (exists($ref->{postscripts})) {
|
||||
my @a = split(/,/, $ref->{postscripts});
|
||||
if (grep(/^config_ops_bm_node/, @a)) {
|
||||
$found = 1;
|
||||
if (!grep(/^$script$/, @a)) {
|
||||
#not exact match, must replace it with the new script
|
||||
for (@a) {
|
||||
s/^config_ops_bm_node.*$/$script/;
|
||||
}
|
||||
my $new_post = join(',', @a);
|
||||
$setup_hash{$node}={postscripts=>"$new_post"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (exists($ref->{postbootscripts})) {
|
||||
my $post=$ref->{postbootscripts};
|
||||
my @old_a=split(',', $post);
|
||||
if (grep(/^config_ops_bm_node/, @old_a)) {
|
||||
if (!grep(/^$script$/, @old_a)) {
|
||||
#not exact match, will replace it with new script
|
||||
for (@old_a) {
|
||||
s/^config_ops_bm_node.*$/$script/;
|
||||
}
|
||||
my $new_postboot = join(',', @old_a);
|
||||
$setup_hash{$node}={postbootscripts=>"$new_postboot"};
|
||||
}
|
||||
} else {
|
||||
if (! $found) {
|
||||
$setup_hash{$node}={postbootscripts=>"$post,$script"};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (! $found) {
|
||||
$setup_hash{$node}={postbootscripts=>"$script"};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$setup_hash{$node}={postbootscripts=>"$script"};
|
||||
}
|
||||
|
||||
if (keys(%setup_hash) > 0) {
|
||||
$posttab->setNodesAttribs(\%setup_hash);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
=head3 remove_postscript
|
||||
|
||||
It removes the 'config_ops_bm_node' postbootscript from
|
||||
the postscript table for the given node.
|
||||
|
||||
=cut
|
||||
#-------------------------------------------------------
|
||||
sub remove_postscript {
|
||||
my $callback=shift;
|
||||
my $node=shift;
|
||||
my $script=shift;
|
||||
|
||||
my $posttab=xCAT::Table->new("postscripts", -create =>1);
|
||||
my %setup_hash;
|
||||
my $ref = $posttab->getNodeAttribs($node,[qw(postscripts postbootscripts)]);
|
||||
my $found=0;
|
||||
if ($ref) {
|
||||
if (exists($ref->{postscripts})) {
|
||||
my @old_a = split(/,/, $ref->{postscripts});
|
||||
my @new_a = grep(!/^$script/, @old_a);
|
||||
if (scalar(@new_a) != scalar(@old_a)) {
|
||||
my $new_post = join(',', @new_a);
|
||||
$setup_hash{$node}={postscripts=>"$new_post"};
|
||||
}
|
||||
}
|
||||
|
||||
if (exists($ref->{postbootscripts})) {
|
||||
my @old_b = split(/,/, $ref->{postbootscripts});
|
||||
my @new_b = grep(!/^$script/, @old_b);
|
||||
if (scalar(@new_b) != scalar(@old_b)) {
|
||||
my $new_post = join(',', @new_b);
|
||||
$setup_hash{$node}={postbootscripts=>"$new_post"};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (keys(%setup_hash) > 0) {
|
||||
$posttab->setNodesAttribs(\%setup_hash);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 opsaddbmnode_usage
|
||||
The usage text for opsaddbmnode command.
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub opsaddbmnode_usage {
|
||||
my $cb=shift;
|
||||
my $rsp={};
|
||||
|
||||
$rsp->{data}->[0]= "Usage: opsaddbmnode -h";
|
||||
$rsp->{data}->[1]= " opsaddbmnode -v";
|
||||
$rsp->{data}->[2]= " opsaddbmnode <noderange> -s <service_host>";
|
||||
$cb->($rsp);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 opsaddimage_usage
|
||||
The usage text for opsaddimage command.
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub opsaddimage_usage {
|
||||
my $cb=shift;
|
||||
my $rsp={};
|
||||
|
||||
$rsp->{data}->[0]= "Usage: opsaddimage -h";
|
||||
$rsp->{data}->[1]= " opsaddimage -v";
|
||||
$rsp->{data}->[2]= " opsaddimage <image1,image2...> [-n <new_name1,new_name2...> -c <controller>";
|
||||
$cb->($rsp);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 deploy_ops_bm_node_usage
|
||||
The usage text for deploy_ops_bm_node command.
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub deploy_ops_bm_node_usage {
|
||||
my $cb=shift;
|
||||
my $rsp={};
|
||||
|
||||
$rsp->{data}->[0]= "Usage: deploy_ops_bm_node -h";
|
||||
$rsp->{data}->[1]= " deploy_ops_bm_node -v";
|
||||
$rsp->{data}->[2]= " deploy_ops_bm_node <node> --image <image_name> --host <ops_hostname> --ip <ops_fixed_ip> --mask <netmask>";
|
||||
$cb->($rsp);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
=head3 cleanup_ops_bm_node_usage
|
||||
The usage text cleanup_ops_bm_node command.
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
sub cleanup_ops_bm_node_usage {
|
||||
my $cb=shift;
|
||||
my $rsp={};
|
||||
|
||||
$rsp->{data}->[0]= "Usage: cleanup_ops_bm_node -h";
|
||||
$rsp->{data}->[1]= " cleanup_ops_bm_node -v";
|
||||
$rsp->{data}->[2]= " cleanup_ops_bm_node <node> [--ip <ops_fixed_ip>]";
|
||||
$cb->($rsp);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2012 NTT DOCOMO, INC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from xcat.openstack.baremetal import driver
|
||||
|
||||
BareMetalDriver = driver.xCATBareMetalDriver
|
||||
@@ -0,0 +1,256 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
# coding=utf-8
|
||||
|
||||
"""
|
||||
A driver for Bare-metal platform.
|
||||
"""
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from nova.compute import power_state
|
||||
from nova import context as nova_context
|
||||
from nova import exception
|
||||
from nova.openstack.common import excutils
|
||||
from nova.openstack.common.gettextutils import _
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova.openstack.common import log as logging
|
||||
from nova.virt.baremetal import baremetal_states
|
||||
from nova.virt.baremetal import db
|
||||
from nova.virt.baremetal import driver as bm_driver
|
||||
from nova.virt.baremetal import utils as bm_utils
|
||||
from nova.virt import driver
|
||||
from nova.virt import firewall
|
||||
from nova.virt.libvirt import imagecache
|
||||
from xcat.openstack.baremetal import xcat_driver
|
||||
from xcat.openstack.baremetal import exception as xcat_exception
|
||||
from xcat.openstack.baremetal import power_states
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
CONF.import_opt('use_ipv6', 'nova.netconf')
|
||||
|
||||
|
||||
class xCATBareMetalDriver(bm_driver.BareMetalDriver):
|
||||
"""BareMetal hypervisor driver."""
|
||||
|
||||
def __init__(self, virtapi, read_only=False):
|
||||
super(xCATBareMetalDriver, self).__init__(virtapi)
|
||||
self.xcat = xcat_driver.xCAT()
|
||||
|
||||
def _get_xCAT_image_name(self, image_meta):
|
||||
prop = image_meta.get('properties')
|
||||
xcat_image_name = prop.get('xcat_image_name')
|
||||
if xcat_image_name:
|
||||
return xcat_image_name
|
||||
else:
|
||||
raise xcat_exception.xCATInvalidImageError(image=image_meta.get('name'))
|
||||
|
||||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, network_info=None, block_device_info=None):
|
||||
"""
|
||||
Create a new instance/VM/domain on the virtualization platform.
|
||||
|
||||
Once this successfully completes, the instance should be
|
||||
running (power_state.RUNNING).
|
||||
|
||||
If this fails, any partial instance should be completely
|
||||
cleaned up, and the virtualization platform should be in the state
|
||||
that it was before this call began.
|
||||
|
||||
:param context: security context
|
||||
:param instance: Instance object as returned by DB layer.
|
||||
This function should use the data there to guide
|
||||
the creation of the new instance.
|
||||
:param image_meta: image object returned by nova.image.glance that
|
||||
defines the image from which to boot this instance
|
||||
:param injected_files: User files to inject into instance.
|
||||
:param admin_password: Administrator password to set in instance.
|
||||
:param network_info:
|
||||
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
|
||||
:param block_device_info: Information about block devices to be
|
||||
attached to the instance.
|
||||
"""
|
||||
#import pdb
|
||||
#pdb.set_trace()
|
||||
node_uuid = self._require_node(instance)
|
||||
node = db.bm_node_associate_and_update(context, node_uuid,
|
||||
{'instance_uuid': instance['uuid'],
|
||||
'instance_name': instance['hostname'],
|
||||
'task_state': baremetal_states.BUILDING})
|
||||
|
||||
try:
|
||||
self._plug_vifs(instance, network_info, context=context)
|
||||
self._attach_block_devices(instance, block_device_info)
|
||||
self._start_firewall(instance, network_info)
|
||||
|
||||
macs = self.macs_for_instance(instance)
|
||||
nodename = self.xcat.get_xcat_node_name(macs)
|
||||
imagename = self._get_xCAT_image_name(image_meta)
|
||||
hostname = instance.get('hostname')
|
||||
|
||||
#get the network information for the new node
|
||||
interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6)
|
||||
if CONF.use_ipv6:
|
||||
fixed_ip = interfaces[0].get('address_v6')
|
||||
netmask = interfaces[0].get('netmask_v6')
|
||||
gateway = interfaces[0].get('gateway_v6')
|
||||
else:
|
||||
fixed_ip = interfaces[0].get('address')
|
||||
netmask = interfaces[0].get('netmask')
|
||||
gateway = interfaces[0].get('gateway')
|
||||
#convert netmask from IPAddress to unicode string
|
||||
if netmask:
|
||||
netmask = unicode(netmask)
|
||||
|
||||
#let xCAT install it
|
||||
bm_driver._update_state(context, node, instance, baremetal_states.DEPLOYING)
|
||||
self.xcat.deploy_node(nodename, imagename, hostname, fixed_ip, netmask, gateway)
|
||||
bm_driver._update_state(context, node, instance, baremetal_states.ACTIVE)
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Error occured while deploying instance %(instance)s "
|
||||
"on baremetal node %(node)s: %(error)s") %
|
||||
{'instance': instance['uuid'],
|
||||
'node': node['uuid'],
|
||||
'error':str(e)})
|
||||
bm_driver._update_state(context, node, instance, baremetal_states.ERROR)
|
||||
|
||||
def reboot(self, context, instance, network_info, reboot_type,
|
||||
block_device_info=None, bad_volumes_callback=None):
|
||||
"""Reboot the specified instance.
|
||||
|
||||
After this is called successfully, the instance's state
|
||||
goes back to power_state.RUNNING. The virtualization
|
||||
platform should ensure that the reboot action has completed
|
||||
successfully even in cases in which the underlying domain/vm
|
||||
is paused or halted/stopped.
|
||||
|
||||
:param instance: Instance object as returned by DB layer.
|
||||
:param network_info:
|
||||
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
|
||||
:param reboot_type: Either a HARD or SOFT reboot
|
||||
:param block_device_info: Info pertaining to attached volumes
|
||||
:param bad_volumes_callback: Function to handle any bad volumes
|
||||
encountered
|
||||
"""
|
||||
try:
|
||||
node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid'])
|
||||
macs = self.macs_for_instance(instance)
|
||||
nodename = self.xcat.get_xcat_node_name(macs)
|
||||
self.xcat.reboot_node(nodename)
|
||||
bm_driver._update_state(context, node, instance, baremetal_states.RUNNING)
|
||||
except xcat_exception.xCATCommandError as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Error occured while rebooting instance %(instance)s "
|
||||
"on baremetal node %(node)s: %(error)s") %
|
||||
{'instance': instance['uuid'],
|
||||
'node': node['uuid'],
|
||||
'error':str(e)})
|
||||
bm_driver._update_state(context, node, instance, baremetal_states.ERROR)
|
||||
|
||||
def destroy(self, instance, network_info, block_device_info=None,
|
||||
context=None):
|
||||
"""Destroy (shutdown and delete) the specified instance.
|
||||
|
||||
If the instance is not found (for example if networking failed), this
|
||||
function should still succeed. It's probably a good idea to log a
|
||||
warning in that case.
|
||||
|
||||
:param context: security context
|
||||
:param instance: Instance object as returned by DB layer.
|
||||
:param network_info:
|
||||
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
|
||||
:param block_device_info: Information about block devices that should
|
||||
be detached from the instance.
|
||||
:param destroy_disks: Indicates if disks should be destroyed
|
||||
"""
|
||||
#import pdb
|
||||
#pdb.set_trace()
|
||||
context = nova_context.get_admin_context()
|
||||
try:
|
||||
node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid'])
|
||||
|
||||
except exception.InstanceNotFound:
|
||||
LOG.warning(_("Destroy function called on a non-existing instance %s")
|
||||
% instance['uuid'])
|
||||
return
|
||||
|
||||
try:
|
||||
macs = self.macs_for_instance(instance)
|
||||
nodename = self.xcat.get_xcat_node_name(macs)
|
||||
interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6)
|
||||
fixed_ip=None
|
||||
if interfaces and interfaces[0]:
|
||||
if CONF.use_ipv6:
|
||||
fixed_ip = interfaces[0].get('address_v6')
|
||||
else:
|
||||
fixed_ip = interfaces[0].get('address')
|
||||
if fixed_ip:
|
||||
self.xcat.cleanup_node(nodename, fixed_ip)
|
||||
else:
|
||||
self.xcat.cleanup_node(nodename)
|
||||
except Exception as e:
|
||||
#just log it and move on
|
||||
LOG.warning(_("Destroy called with xCAT error:" + str(e)))
|
||||
|
||||
try:
|
||||
self._detach_block_devices(instance, block_device_info)
|
||||
self._stop_firewall(instance, network_info)
|
||||
self._unplug_vifs(instance, network_info)
|
||||
|
||||
bm_driver._update_state(context, node, None, baremetal_states.DELETED)
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Error occurred while destroying instance %s: %s")
|
||||
% (instance['uuid'], str(e)))
|
||||
bm_driver._update_state(context, node, instance,
|
||||
baremetal_states.ERROR)
|
||||
|
||||
def power_off(self, instance, node=None):
|
||||
"""Power off the specified instance."""
|
||||
macs = self.macs_for_instance(instance)
|
||||
nodename = self.xcat.get_xcat_node_name(macs)
|
||||
self.xcat.power_off_node(nodename)
|
||||
|
||||
|
||||
def power_on(self, context, instance, network_info, block_device_info=None,
|
||||
node=None):
|
||||
"""Power on the specified instance."""
|
||||
macs = self.macs_for_instance(instance)
|
||||
nodename = self.xcat.get_xcat_node_name(macs)
|
||||
self.xcat.power_on_node(nodename)
|
||||
|
||||
|
||||
def get_console_output(self, instance):
|
||||
pass
|
||||
|
||||
def get_info(self, instance):
|
||||
"""Get the current status of an instance, by name (not ID!)
|
||||
|
||||
Returns a dict containing:
|
||||
:state: the running state, one of the power_state codes
|
||||
:max_mem: (int) the maximum memory in KBytes allowed
|
||||
:mem: (int) the memory in KBytes used by the domain
|
||||
:num_cpu: (int) the number of virtual CPUs for the domain
|
||||
:cpu_time: (int) the CPU time used in nanoseconds
|
||||
"""
|
||||
|
||||
node = bm_driver._get_baremetal_node_by_instance_uuid(instance['uuid'])
|
||||
macs = self.macs_for_instance(instance)
|
||||
nodename = self.xcat.get_xcat_node_name(macs)
|
||||
|
||||
ps = self.xcat.get_node_power_state(nodename)
|
||||
if ps == power_states.ON:
|
||||
pstate = power_state.RUNNING
|
||||
elif ps == power_states.OFF:
|
||||
pstate = power_state.SHUTDOWN
|
||||
else:
|
||||
pstate = power_state.NOSTATE
|
||||
|
||||
return {'state': pstate,
|
||||
'max_mem': node['memory_mb'],
|
||||
'mem': node['memory_mb'],
|
||||
'num_cpu': node['cpus'],
|
||||
'cpu_time': 0}
|
||||
@@ -0,0 +1,41 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
"""xCAT baremtal exceptions.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import sys
|
||||
|
||||
from oslo.config import cfg
|
||||
import webob.exc
|
||||
|
||||
from nova.openstack.common import excutils
|
||||
from nova.openstack.common.gettextutils import _
|
||||
from nova.openstack.common import log as logging
|
||||
from nova import safe_utils
|
||||
from nova import exception as nova_exception
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
class xCATException(Exception):
|
||||
errmsg = _("xCAT general exception")
|
||||
|
||||
def __init__(self, errmsg=None, **kwargs):
|
||||
if not errmsg:
|
||||
errmsg = self.errmsg
|
||||
errmsg = errmsg % kwargs
|
||||
|
||||
super(xCATException, self).__init__(errmsg)
|
||||
|
||||
class xCATCommandError(xCATException):
|
||||
errmsg = _("Error returned when calling xCAT command %(cmd)s"
|
||||
" for node %(node)s:%(error)s")
|
||||
|
||||
class xCATInvalidImageError(xCATException):
|
||||
errmsg = _("The image %(image)s is not an xCAT image")
|
||||
|
||||
class xCATDeploymentFailure(xCATException):
|
||||
errmsg = _("xCAT node deployment failed for node %(node)s:%(error)s")
|
||||
|
||||
class xCATRebootFailure(xCATException):
|
||||
errmsg = _("xCAT node rebooting failed for node %(node)s:%(error)s")
|
||||
@@ -0,0 +1,9 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
"""
|
||||
Possible xCAT node power states.
|
||||
"""
|
||||
|
||||
OFF = 'off'
|
||||
ON = 'on'
|
||||
ERROR = 'error'
|
||||
@@ -0,0 +1,260 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
# coding=utf-8
|
||||
|
||||
|
||||
"""
|
||||
Baremetal xCAT power manager.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import stat
|
||||
from oslo.config import cfg
|
||||
import datetime
|
||||
|
||||
from nova import context as nova_context
|
||||
from nova.virt.baremetal import baremetal_states
|
||||
from nova.openstack.common.gettextutils import _
|
||||
from nova.openstack.common import log as logging
|
||||
from nova.openstack.common import loopingcall
|
||||
from nova.openstack.common import timeutils
|
||||
from nova import paths
|
||||
from nova import utils
|
||||
from xcat.openstack.baremetal import exception
|
||||
from xcat.openstack.baremetal import power_states
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# register configuration options
|
||||
xcat_opts = [
|
||||
cfg.IntOpt('deploy_timeout',
|
||||
help='Timeout for node deployment. Default: 0 second (unlimited)',
|
||||
default=0),
|
||||
cfg.IntOpt('reboot_timeout',
|
||||
help='Timeout for rebooting a node. Default: 0 second (unlimited)',
|
||||
default=0),
|
||||
cfg.IntOpt('deploy_checking_interval',
|
||||
help='Checking interval for node deployment. Default: 10 seconds',
|
||||
default=10),
|
||||
cfg.IntOpt('reboot_checking_interval',
|
||||
help='Checking interval for rebooting a node. Default: 5 seconds',
|
||||
default=5),
|
||||
]
|
||||
xcat_group = cfg.OptGroup(name='xcat',
|
||||
title='xCAT Options')
|
||||
CONF = cfg.CONF
|
||||
CONF.register_group(xcat_group)
|
||||
CONF.register_opts(xcat_opts, xcat_group)
|
||||
|
||||
|
||||
class xCAT(object):
|
||||
"""A driver that calls xCAT funcions"""
|
||||
|
||||
def __init__(self):
|
||||
#setup the path for xCAT commands
|
||||
#xcatroot = os.getenv('XCATROOT', '/opt/xcat/')
|
||||
#sys.path.append("%s/bin" % xcatroot)
|
||||
#sys.path.append("%s/sbin" % xcatroot)
|
||||
pass
|
||||
|
||||
def _exec_xcat_command(self, command):
|
||||
"""Calls xCAT command."""
|
||||
args = command.split(" ")
|
||||
out, err = utils.execute(*args, run_as_root=True)
|
||||
LOG.debug(_("xCAT command stdout: '%(out)s', stderr: '%(err)s'"),
|
||||
{'out': out, 'err': err})
|
||||
return out, err
|
||||
|
||||
def get_xcat_node_name(self, macs):
|
||||
"""Get the xcat node name given mac addressed.
|
||||
|
||||
It uses the mac address to search for the node name in xCAT.
|
||||
"""
|
||||
for mac in macs:
|
||||
out, err = self._exec_xcat_command("lsdef -w mac=%s" % mac)
|
||||
if out:
|
||||
return out.split(" ")[0]
|
||||
|
||||
errstr='No node found in xCAT with the following mac address: ' \
|
||||
+ ','.join(macs)
|
||||
LOG.warning(errstr)
|
||||
raise exception.xCATCommandError(errstr)
|
||||
|
||||
|
||||
def deploy_node(self, nodename, imagename, hostname, fixed_ip, netmask, gateway):
|
||||
"""
|
||||
Install the node.
|
||||
|
||||
It calls xCAT command deploy_ops_bmnode which prepares the node
|
||||
by adding the config_ops_bm_node postbootscript to the postscript
|
||||
table for the node, then call nodeset and then boot the node up.
|
||||
"""
|
||||
out, err = self._exec_xcat_command(
|
||||
"deploy_ops_bm_node %(node)s --image %(image)s"
|
||||
" --host %(host)s --ip %(ip)s --mask %(mask)s"
|
||||
% {'node': nodename,
|
||||
'image': imagename,
|
||||
'host': hostname,
|
||||
'ip': fixed_ip,
|
||||
'mask': netmask,
|
||||
})
|
||||
if err:
|
||||
errstr = _("Error returned when calling xCAT deploy_ops_bm_node"
|
||||
" command for node %s:%s") % (nodename, err)
|
||||
LOG.warning(errstr)
|
||||
raise exception.xCATCommandError(errstr)
|
||||
self._wait_for_node_deploy(nodename)
|
||||
|
||||
def cleanup_node(self, nodename, fixed_ip=None):
|
||||
"""
|
||||
Undo all the changes made to the node by deploy_node function.
|
||||
|
||||
It calls xCAT command cleanup_ops_bm_node which removes the
|
||||
config_ops_bm_node postbootscript from the postscript table
|
||||
for the node, removes the alias ip and then power the node off.
|
||||
"""
|
||||
cmd = "cleanup_ops_bm_node %s" % nodename
|
||||
if fixed_ip:
|
||||
cmd += " --ip %s" % fixed_ip
|
||||
out, err = self._exec_xcat_command(cmd)
|
||||
|
||||
if err:
|
||||
errstr = _("Error returned when calling xCAT cleanup_ops_bm_node"
|
||||
" command for node %s:%s") % (nodename, err)
|
||||
LOG.warning(errstr)
|
||||
raise exception.xCATCommandError(errstr)
|
||||
|
||||
def power_on_node(self, nodename):
|
||||
"""Power on the node."""
|
||||
state = self.get_node_power_state(nodename)
|
||||
if state == power_states.ON:
|
||||
LOG.warning(_("Powring on node called, but the node %s "
|
||||
"is already on") % nodename)
|
||||
out, err = self._exec_xcat_command("rpower %s on" % nodename)
|
||||
if err:
|
||||
errstr = _("Error returned when calling xCAT rpower on"
|
||||
" for node %s:%s") % (nodename, err)
|
||||
LOG.warning(errstr)
|
||||
raise exception.xCATCommandError(errstr)
|
||||
else:
|
||||
self._wait_for_node_reboot(nodename)
|
||||
return power_states.ON
|
||||
|
||||
def power_off_node(self, nodename):
|
||||
"""Power off the node."""
|
||||
state = self.get_node_power_state(nodename)
|
||||
if state == power_states.OFF:
|
||||
LOG.warning(_("Powring off node called, but the node %s "
|
||||
"is already off") % nodename)
|
||||
out, err = self._exec_xcat_command("rpower %s off" % nodename)
|
||||
if err:
|
||||
errstr = _("Error returned when calling xCAT rpower off"
|
||||
" for node %s:%s") % (nodename, err)
|
||||
LOG.warning(errstr)
|
||||
raise exception.xCATCommandError(errstr)
|
||||
else:
|
||||
return power_states.OFF
|
||||
|
||||
def reboot_node(self, nodename):
|
||||
"""Reboot the node."""
|
||||
out, err = self._exec_xcat_command("rpower %s boot" % nodename)
|
||||
if err:
|
||||
errstr = _("Error returned when calling xCAT rpower boot"
|
||||
" for node %s:%s") % (nodename, err)
|
||||
LOG.warning(errstr)
|
||||
raise exception.xCATCommandError(errstr)
|
||||
|
||||
self._wait_for_node_reboot(nodename)
|
||||
return power_states.ON
|
||||
|
||||
|
||||
def get_node_power_state(self, nodename):
|
||||
out, err = self._exec_xcat_command("rpower %s stat" % nodename)
|
||||
if err:
|
||||
errstr = _("Error returned when calling xCAT rpower stat"
|
||||
" for node %s:%s") % (nodename, err)
|
||||
LOG.warning(errstr)
|
||||
raise exception.xCATCommandError(errstr)
|
||||
else:
|
||||
state = out.split(":")[1]
|
||||
if state:
|
||||
state = state.strip()
|
||||
if state == 'on':
|
||||
return power_states.ON
|
||||
elif state == 'off':
|
||||
return power_states.OFF
|
||||
|
||||
return power_states.ERROR
|
||||
|
||||
def _wait_for_node_deploy(self, nodename):
|
||||
"""Wait for xCAT node deployment to complete."""
|
||||
locals = {'errstr':''}
|
||||
|
||||
def _wait_for_deploy():
|
||||
out,err = self._exec_xcat_command("nodels %s nodelist.status" % nodename)
|
||||
if err:
|
||||
locals['errstr'] = _("Error returned when quering node status"
|
||||
" for node %s:%s") % (nodename, err)
|
||||
LOG.warning(locals['errstr'])
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
if out:
|
||||
node,status = out.split(": ")
|
||||
status = status.strip()
|
||||
if status == "booted":
|
||||
LOG.info(_("Deployment for node %s completed.")
|
||||
% nodename)
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
if (CONF.xcat.deploy_timeout and
|
||||
timeutils.utcnow() > expiration):
|
||||
locals['errstr'] = _("Timeout while waiting for"
|
||||
" deployment of node %s.") % nodename
|
||||
LOG.warning(locals['errstr'])
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
expiration = timeutils.utcnow() + datetime.timedelta(
|
||||
seconds=CONF.xcat.deploy_timeout)
|
||||
timer = loopingcall.FixedIntervalLoopingCall(_wait_for_deploy)
|
||||
# default check every 10 seconds
|
||||
timer.start(interval=CONF.xcat.deploy_checking_interval).wait()
|
||||
|
||||
if locals['errstr']:
|
||||
raise exception.xCATDeploymentFailure(locals['errstr'])
|
||||
|
||||
|
||||
def _wait_for_node_reboot(self, nodename):
|
||||
"""Wait for xCAT node boot to complete."""
|
||||
locals = {'errstr':''}
|
||||
|
||||
def _wait_for_reboot():
|
||||
out,err = self._exec_xcat_command("nodestat %s" % nodename)
|
||||
if err:
|
||||
locals['errstr'] = _("Error returned when quering node status"
|
||||
" for node %s:%s") % (nodename, err)
|
||||
LOG.warning(locals['errstr'])
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
if out:
|
||||
node,status = out.split(": ")
|
||||
status = status.strip()
|
||||
if status == "sshd":
|
||||
LOG.info(_("Rebooting node %s completed.")
|
||||
% nodename)
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
if (CONF.xcat.reboot_timeout and
|
||||
timeutils.utcnow() > expiration):
|
||||
locals['errstr'] = _("Timeout while waiting for"
|
||||
" rebooting node %s.") % nodename
|
||||
LOG.warning(locals['errstr'])
|
||||
raise loopingcall.LoopingCallDone()
|
||||
|
||||
expiration = timeutils.utcnow() + datetime.timedelta(
|
||||
seconds=CONF.xcat.reboot_timeout)
|
||||
timer = loopingcall.FixedIntervalLoopingCall(_wait_for_reboot)
|
||||
# default check every 5 seconds
|
||||
timer.start(interval=CONF.xcat.reboot_checking_interval).wait()
|
||||
|
||||
if locals['errstr']:
|
||||
raise exception.xCATRebootFailure(locals['errstr'])
|
||||
@@ -0,0 +1,90 @@
|
||||
=head1 NAME
|
||||
|
||||
B<opsaddbmnode> - It adds xCAT baremetal nodes to an OpenStack cloud.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<opsaddbmnode> I<noderange> B<-s> I<service_host>
|
||||
|
||||
B<opsaddbmnode> [B<-h>|B<--help>]
|
||||
|
||||
B<opsaddbmnode> [B<-v>|B<--version>]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<opsaddbmnode> command registers xCAT nodes to an OpenStack cloud. An OpenStack nova baremetal node registration command takes several node attributes:
|
||||
|
||||
=over
|
||||
|
||||
=item BMC ip addresss, user id and password
|
||||
|
||||
=item Name of nova compute host which will control this baremetal node
|
||||
|
||||
=item Number of CPUs in the node
|
||||
|
||||
=item Memory in the node (MB)
|
||||
|
||||
=item Local hard disk in the node (GB)
|
||||
|
||||
=item MAC address to provision the node
|
||||
|
||||
=back
|
||||
|
||||
The opsaddbmnode command pulls the above baremetal node information from xCAT tables and calls "nova baremetal-node-create" to register the baremetal node with the OpenStack cloud.
|
||||
|
||||
Please make sure the following xCAT tables are filled with correct information for the given nodes before calling this command.
|
||||
|
||||
=over
|
||||
|
||||
=item ipmi (for BMC ip addresss, user id and password)
|
||||
|
||||
=item mac (for MAC address)
|
||||
|
||||
=item hwinv (for CPU, memory and disk info.)
|
||||
|
||||
=back
|
||||
|
||||
=head1 Parameters
|
||||
|
||||
I<noderage> is a comma separated node or node group names.
|
||||
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 10
|
||||
|
||||
=item B<-s> The node name of the OpenStack compute host that hosts the baremetal nodes.
|
||||
|
||||
=item B<-h|--help> Display usage message.
|
||||
|
||||
=item B<-v|--version> The Command Version.
|
||||
|
||||
=back
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
0 The command completed successfully.
|
||||
|
||||
1 An error has occurred.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
=over 3
|
||||
|
||||
=item 1
|
||||
|
||||
To register node1, node2 and node3 to OpenStack, sv1 is the compute host.
|
||||
|
||||
opsassbmnode node1,node2,node3 -s sv1
|
||||
|
||||
|
||||
=back
|
||||
|
||||
=head1 FILES
|
||||
|
||||
/opt/xcat/bin/opadddbmnode
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<opsaddimage(1)|opsaddimage.1>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
=head1 NAME
|
||||
|
||||
B<opsaddimage> - It adds or removes nodes for the vlan.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<opsaddimage> I<image1,image2,...> B<-n> I<new_name1,new_name2,...> [B<-c> I<controller>]
|
||||
|
||||
B<opsaddimage> [B<-h>|B<--help>]
|
||||
|
||||
B<opsaddimage> [B<-v>|B<--version>]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<opsaddimage> command adds a list of xCAT images into the OpenStack cloud.
|
||||
|
||||
Under the cover, it creates a fake image and registers the fake image into OpenStack with command B<glance image-create>. It sets the property in the image to indicate that this is an xCAT image and also stores the original xCAT image name in the property for further reference.
|
||||
|
||||
The xCAT image names can be listed using B<lsdef -t osimage> command.
|
||||
|
||||
=head1 Parameters
|
||||
|
||||
I<image1,image1...> a comma separated xCAT images names.
|
||||
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 10
|
||||
|
||||
=item B<-n> a comma separated new image names in the OpenStack. If omitted, the default is the original xCAT image nanme.
|
||||
|
||||
=item B<-c> the node name of the OpenStack controller. This node must be an xCAT managed node.
|
||||
|
||||
=item B<-h|--help> Display usage message.
|
||||
|
||||
=item B<-v|--version> The Command Version.
|
||||
|
||||
=back
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
0 The command completed successfully.
|
||||
|
||||
1 An error has occurred.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
=over 3
|
||||
|
||||
=item 1.
|
||||
|
||||
To register xCAT image rhels6.3-x86_64-install-compute into OpenStack.
|
||||
|
||||
opsaddimage rhels6.3-x86_64-install-compute -c sv2
|
||||
|
||||
=back
|
||||
|
||||
=head1 FILES
|
||||
|
||||
/opt/xcat/bin/opsaddimage
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<opsaddbmnode(1)|opsaddbmnode.1>
|
||||
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
#!/bin/sh
|
||||
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
# xCAT post script for configuring the openstack baremetal node.
|
||||
# The format is:
|
||||
# config_ops_bm_node ops_hostname ops_ip ops_netmask
|
||||
|
||||
|
||||
get_os_type()
|
||||
{
|
||||
#get os type
|
||||
str_os_type=`uname | tr 'A-Z' 'a-z'`
|
||||
str_temp=''
|
||||
if [ "$str_os_type" = "linux" ];then
|
||||
str_temp=`echo $OSVER | grep -E '(sles|suse)'`
|
||||
if [ -f "/etc/debian_version" ];then
|
||||
str_os_type="debian"
|
||||
elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then
|
||||
str_os_type="sles"
|
||||
else
|
||||
str_os_type="redhat"
|
||||
fi
|
||||
else
|
||||
str_os_type="aix"
|
||||
fi
|
||||
echo "$str_os_type"
|
||||
}
|
||||
|
||||
|
||||
setup_ip()
|
||||
{
|
||||
str_os_type=$1
|
||||
str_if_name=$2
|
||||
str_v4ip=$3
|
||||
str_v4mask=$4
|
||||
|
||||
ret=`ifconfig $str_if_name |grep "inet addr" 2>&1`
|
||||
if [ $? -eq 0 ]; then
|
||||
old_ip=`echo $ret|cut -d':' -f2 |cut -d' ' -f1`
|
||||
old_mask=`echo $ret|cut -d':' -f4`
|
||||
#echo "old ip = $old_ip, old mask=$old_mask"
|
||||
if [ "$old_ip" == "$str_v4ip" -a "$old_mask" == "$str_v4mask" ]; then
|
||||
#if nic is up and the address is the same, then donothing
|
||||
#echo "do nothing"
|
||||
exit 0
|
||||
else
|
||||
#bring down the nic and reconstruct it.
|
||||
#echo "bring down the old nic"
|
||||
ifconfig $str_if_name del $old_ip
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$str_os_type" = "sles" ];then
|
||||
str_conf_file="/etc/sysconfig/network/ifcfg-${str_if_name}"
|
||||
if [ -f $str_conf_file ]; then
|
||||
rm $str_conf_file
|
||||
fi
|
||||
echo "DEVICE=${str_if_name}" > $str_conf_file
|
||||
echo "BOOTPROTO=static" >> $str_conf_file
|
||||
echo "IPADDR=${str_v4ip}" >> $str_conf_file
|
||||
echo "NETMASK=${str_v4mask}" >> $str_conf_file
|
||||
echo "NETWORK=''" >> $str_conf_file
|
||||
echo "STARTMODE=onboot" >> $str_conf_file
|
||||
echo "USERCONTROL=no" >> $str_conf_file
|
||||
ifup $str_if_name
|
||||
#debian ubuntu
|
||||
elif [ "$str_os_type" = "debian" ];then
|
||||
str_conf_file="/etc/network/interfaces.d/${str_if_name}"
|
||||
if [ -f $str_conf_file ]; then
|
||||
rm $str_conf_file
|
||||
fi
|
||||
echo "auto ${str_if_name}" > $str_conf_file
|
||||
echo "iface ${str_if_name} inet static" >> $str_conf_file
|
||||
echo " address ${str_v4ip}" >> $str_conf_file
|
||||
echo " netmask ${str_v4mask}" >> $str_conf_file
|
||||
ifconfig $str_if_name up
|
||||
else
|
||||
# Write the info to the ifcfg file for redhat
|
||||
str_conf_file="/etc/sysconfig/network-scripts/ifcfg-${str_if_name}"
|
||||
if [ -f $str_conf_file ]; then
|
||||
rm $str_conf_file
|
||||
fi
|
||||
echo "DEVICE=${str_if_name}" > $str_conf_file
|
||||
echo "BOOTPROTO=static" >> $str_conf_file
|
||||
echo "NM_CONTROLLED=no" >> $str_conf_file
|
||||
echo "IPADDR=${str_v4ip}" >> $str_conf_file
|
||||
echo "NETMASK=${str_v4mask}" >> $str_conf_file
|
||||
echo "ONBOOT=yes" >> $str_conf_file
|
||||
ifup $str_if_name
|
||||
fi
|
||||
}
|
||||
|
||||
#change hostname permanently
|
||||
change_host_name()
|
||||
{
|
||||
str_os_type=$1
|
||||
str_hostname=$2
|
||||
|
||||
hostname $str_hostname
|
||||
|
||||
if [ "$str_os_type" = "sles" ];then
|
||||
echo "Persistently changing the hostname not implemented yet."
|
||||
#debian ubuntu
|
||||
elif [ "$str_os_type" = "debian" ];then
|
||||
conf_file="/etc/hostname"
|
||||
echo "$str_hostname" > $conf_file
|
||||
else
|
||||
conf_file="/etc/sysconfig/network"
|
||||
if [ ! -f $conf_file ]; then
|
||||
touch $conf_file
|
||||
fi
|
||||
grep 'HOSTNAME' $conf_file 2>&1 > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
sed -i "s/HOSTNAME=.*/HOSTNAME=$str_hostname/" $conf_file
|
||||
else
|
||||
echo "HOSTNAME=$str_hostname" >> $conf_file
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
str_os_type=$(get_os_type)
|
||||
echo "os_type=$str_os_type"
|
||||
if [ "$str_os_type" = "aix" ]; then
|
||||
logger -t xcat "config_ops_bm_node dose not support AIX."
|
||||
echo "config_ops_bm_node dose not support AIX."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#change the hostname
|
||||
if [[ -n "$1" ]]; then
|
||||
change_host_name $str_os_type $1
|
||||
fi
|
||||
|
||||
#Add the openstack ip to the node
|
||||
if [[ -n $2 ]]; then
|
||||
ops_ip=$2
|
||||
|
||||
if [[ -z $3 ]]; then
|
||||
logger -t xcat "config_ops_bm_node: Please specify the netmask."
|
||||
echo "config_ops_bm_node: Please specify the netmask."
|
||||
exit 1
|
||||
else
|
||||
ops_mask=$3
|
||||
fi
|
||||
|
||||
#figure out the install nic
|
||||
if [[ -n $MACADDRESS ]]; then
|
||||
pos=0
|
||||
#mac has the following format: 01:02:03:04:05:0E!node5|01:02:03:05:0F!node6-eth1
|
||||
for x in `echo "$MACADDRESS" | tr "|" "\n"`
|
||||
do
|
||||
node=""
|
||||
mac=""
|
||||
pos=$((pos+1))
|
||||
i=`expr index $x !`
|
||||
if [[ $i -gt 0 ]]; then
|
||||
node=`echo ${x##*!}`
|
||||
mac_tmp=`echo ${x%%!*}`
|
||||
else
|
||||
mac_tmp=$x
|
||||
fi
|
||||
|
||||
if [[ $pos -eq 1 ]]; then
|
||||
mac1=$mac_tmp
|
||||
fi
|
||||
|
||||
if [[ "$PRIMARYNIC" = "$mac_tmp" ]]; then
|
||||
mac=$mac_tmp
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
|
||||
if [[ -z $node ]] || [[ "$node" = "$NODE" ]]; then
|
||||
mac=$mac_tmp
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z $mac ]]; then
|
||||
if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
|
||||
mac=$mac1 #if nothing mathes, take the first mac
|
||||
else
|
||||
nic=$PRIMARYNIC #or the primary nic itself is the nic
|
||||
fi
|
||||
fi
|
||||
else
|
||||
logger -t xcat "config_ops_bm_node: no mac addresses are defined in the mac table for the node $NODE"
|
||||
echo "config_ops_bm_node: no mac addresses are defined in the mac table for the node $NODE"
|
||||
index=$((index+1))
|
||||
continue
|
||||
fi
|
||||
echo "mac=$mac"
|
||||
|
||||
#find the nic that has the mac
|
||||
if [[ -z $nic ]]; then
|
||||
#go to each nic to match the mac address
|
||||
ret=`ifconfig |grep -i $mac 2>&1`;
|
||||
if [ $? -eq 0 ]; then
|
||||
nic=`echo $ret |head -n1|cut -d' ' -f 1`
|
||||
else
|
||||
logger -t xcat "config_ops_bm_node: The mac address for the network for $NODE is not defined."
|
||||
echo "config_ops_bm_node: The mac address for the network for $NODE is not defined."
|
||||
fi
|
||||
fi
|
||||
echo "nic=$nic"
|
||||
|
||||
#now setup the ip alias
|
||||
setup_ip $str_os_type $nic:0 $ops_ip $ops_mask
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
# xCAT post script for deconfiguring the openstack baremetal node.
|
||||
# The format is:
|
||||
# deconfig_ops_bm_node ops_ip
|
||||
|
||||
|
||||
get_os_type()
|
||||
{
|
||||
#get os type
|
||||
str_os_type=`uname | tr 'A-Z' 'a-z'`
|
||||
str_temp=''
|
||||
if [ "$str_os_type" = "linux" ];then
|
||||
str_temp=`echo $OSVER | grep -E '(sles|suse)'`
|
||||
if [ -f "/etc/debian_version" ];then
|
||||
str_os_type="debian"
|
||||
elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then
|
||||
str_os_type="sles"
|
||||
else
|
||||
str_os_type="redhat"
|
||||
fi
|
||||
else
|
||||
str_os_type="aix"
|
||||
fi
|
||||
echo "$str_os_type"
|
||||
}
|
||||
|
||||
#change hostname permanently
|
||||
change_host_name()
|
||||
{
|
||||
str_os_type=$1
|
||||
str_hostname=$2
|
||||
|
||||
hostname $str_hostname
|
||||
|
||||
if [ "$str_os_type" = "sles" ];then
|
||||
echo "Persistently changing the hostname not implemented yet."
|
||||
#debian ubuntu
|
||||
elif [ "$str_os_type" = "debian" ];then
|
||||
conf_file="/etc/hostname"
|
||||
echo "$str_hostname" > $conf_file
|
||||
else
|
||||
conf_file="/etc/sysconfig/network"
|
||||
if [ ! -f $conf_file ]; then
|
||||
touch $conf_file
|
||||
fi
|
||||
grep 'HOSTNAME' $conf_file 2>&1 > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
sed -i "s/HOSTNAME=.*/HOSTNAME=$str_hostname/" $conf_file
|
||||
else
|
||||
echo "HOSTNAME=$str_hostname" >> $conf_file
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
str_os_type=$(get_os_type)
|
||||
echo "os_type=$str_os_type"
|
||||
|
||||
if [ $str_os_type == "aix" ]; then
|
||||
logger -t xcat "deconfig_ops_bm_node dose not support AIX."
|
||||
echo "deconfig_ops_bm_node dose not support AIX."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#change the hostname
|
||||
#hostname $NODE
|
||||
change_host_name $str_os_type $NODE
|
||||
|
||||
#remove the openstack ip from the node
|
||||
if [[ -n $1 ]]; then
|
||||
ops_ip=$1
|
||||
nic=$(ip addr | grep $ops_ip | awk '{print $NF}')
|
||||
echo "nic=$nic, ops_ip=$ops_ip"
|
||||
|
||||
ifconfig $nic del $ops_ip
|
||||
|
||||
#delete the configuration file
|
||||
if [ "$str_os_type" = "sles" ]; then
|
||||
str_conf_file="/etc/sysconfig/network/ifcfg-$nic"
|
||||
elif [ "$str_os_type" = "debian" ]; then #debian ubuntu
|
||||
str_conf_file="/etc/network/interfaces.d/$nic"
|
||||
else #redhat
|
||||
str_conf_file="/etc/sysconfig/network-scripts/ifcfg-$nic"
|
||||
fi
|
||||
if [ -f $str_conf_file ]; then
|
||||
rm $str_conf_file
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
Summary: Executables and data of the xCAT baremetal driver for OpenStack
|
||||
Name: xCAT-OpenStack-baremetal
|
||||
Version: %(cat Version)
|
||||
Release: snap%(date +"%Y%m%d%H%M")
|
||||
Epoch: 4
|
||||
License: IBM
|
||||
Group: Applications/System
|
||||
Source: xCAT-OpenStack-baremetal-%{version}.tar.gz
|
||||
Packager: IBM Corp.
|
||||
Vendor: IBM Corp.
|
||||
Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
|
||||
Prefix: /opt/xcat
|
||||
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-root
|
||||
|
||||
%ifos linux
|
||||
BuildArch: noarch
|
||||
%endif
|
||||
|
||||
|
||||
Provides: xCAT-OpenStack-baremetal = %{epoch}:%{version}
|
||||
|
||||
Requires: xCAT-client
|
||||
|
||||
%description
|
||||
xCAT-OpenStack-baremetal provides the baremetal driver for OpenStack.
|
||||
|
||||
%prep
|
||||
%setup -q -n xCAT-OpenStack-baremetal
|
||||
%build
|
||||
|
||||
# Convert pods to man pages and html pages
|
||||
./xpod2man
|
||||
|
||||
%install
|
||||
# The install phase puts all of the files in the paths they should be in when the rpm is
|
||||
# installed on a system. The RPM_BUILD_ROOT is a simulated root file system and usually
|
||||
# has a value like: /var/tmp/xCAT-OpenStack-baremetal-2.0-snap200802270932-root
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/python/xcat/openstack/baremetal
|
||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/openstack/postscripts
|
||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/man/man1
|
||||
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1
|
||||
|
||||
|
||||
set +x
|
||||
|
||||
cp -R lib/* $RPM_BUILD_ROOT/%{prefix}/lib
|
||||
cp share/xcat/openstack/postscripts/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/openstack/postscripts
|
||||
|
||||
|
||||
# These were built dynamically in the build phase
|
||||
cp share/man/man1/* $RPM_BUILD_ROOT/%{prefix}/share/man/man1
|
||||
chmod 444 $RPM_BUILD_ROOT/%{prefix}/share/man/man1/*
|
||||
|
||||
# These were built dynamically during the build phase
|
||||
cp share/doc/man1/* $RPM_BUILD_ROOT/%{prefix}/share/doc/man1
|
||||
chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/doc/man1/*
|
||||
|
||||
# These links get made in the RPM_BUILD_ROOT/prefix area
|
||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/sbin/deploy_ops_bm_node
|
||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/sbin/cleanup_ops_bm_node
|
||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/opsaddbmnode
|
||||
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/opsaddimage
|
||||
|
||||
set -x
|
||||
|
||||
|
||||
%clean
|
||||
# This step does not happen until *after* the %files packaging below
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
#%doc LICENSE.html
|
||||
# Just package everything that has been copied into RPM_BUILD_ROOT
|
||||
%{prefix}
|
||||
|
||||
|
||||
%changelog
|
||||
|
||||
%post
|
||||
#copy the postscripts under /installl/postscripts directory on MN only
|
||||
if [ -f "/etc/xCATMN" ]; then
|
||||
cp $RPM_INSTALL_PREFIX0/share/xcat/openstack/postscripts/* /install/postscripts/
|
||||
fi
|
||||
|
||||
%preun
|
||||
#remove postscripts under /installl/postscripts directory on MN only
|
||||
if [ -f "/etc/xCATMN" ]; then
|
||||
for fn in $RPM_INSTALL_PREFIX0/share/xcat/openstack/postscripts/*
|
||||
do
|
||||
bn=`basename $fn`
|
||||
rm /install/postscripts/$bn
|
||||
done
|
||||
fi
|
||||
exit 0
|
||||
|
||||
|
||||
Executable
+214
@@ -0,0 +1,214 @@
|
||||
#!/usr/bin/perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
# First builds the xCAT summary man page from Synopsis of each man page.
|
||||
# Then converts all of the pod man pages into html (including links to each other)
|
||||
|
||||
# We assume that this script is run in the xCAT-vlan-2.0 dir, so everything is
|
||||
# done relative to that.
|
||||
|
||||
use strict;
|
||||
#use lib '.';
|
||||
use Pod::Man;
|
||||
use Pod::Html;
|
||||
|
||||
my $poddir = 'pods';
|
||||
my $mandir = 'share/man';
|
||||
my $htmldir = 'share/doc';
|
||||
my $cachedir = '/tmp';
|
||||
|
||||
my @pods = getPodList($poddir);
|
||||
#foreach (@pods) { print "$_\n"; } exit;
|
||||
|
||||
# Build the cmd overview page.
|
||||
#writesummarypage("$poddir/man1/xcat.1.pod", @pods);
|
||||
|
||||
# Build the man page for each pod.
|
||||
#mkdir($mandir) or die "Error: could not create $mandir.\n";
|
||||
print "Converting PODs to man pages...\n";
|
||||
foreach my $podfile (@pods) {
|
||||
my $manfile = $podfile;
|
||||
$manfile =~ s/^$poddir/$mandir/; # change the beginning of the path
|
||||
$manfile =~ s/\.pod$//; # change the ending
|
||||
my $mdir = $manfile;
|
||||
$mdir =~ s|/[^/]*$||; # get rid of the basename part
|
||||
if (system("mkdir -p $mdir")) { die "Error: could not create $mdir.\n"; }
|
||||
my ($section) = $podfile =~ /\.(\d+)\.pod$/;
|
||||
convertpod2man($podfile, $manfile, $section);
|
||||
}
|
||||
|
||||
my @dummyPods = createDummyPods($poddir, \@pods);
|
||||
|
||||
# Build the html page for each pod.
|
||||
#mkdir($htmldir) or die "Error: could not create $htmldir.\n";
|
||||
print "Converting PODs to HTML pages...\n";
|
||||
# have to clear the cache, because old entries can cause a problem
|
||||
unlink("$cachedir/pod2htmd.tmp", "$cachedir/pod2htmi.tmp");
|
||||
foreach my $podfile (@pods) {
|
||||
my $htmlfile = $podfile;
|
||||
$htmlfile =~ s/^$poddir/$htmldir/; # change the beginning of the path
|
||||
$htmlfile =~ s/\.pod$/\.html/; # change the ending
|
||||
my $hdir = $htmlfile;
|
||||
$hdir =~ s|/[^/]*$||; # get rid of the basename part
|
||||
if (system("mkdir -p $hdir")) { die "Error: could not create $hdir.\n"; }
|
||||
#print "$podfile, $htmlfile, $poddir, $htmldir\n";
|
||||
convertpod2html($podfile, $htmlfile, $poddir, $htmldir);
|
||||
}
|
||||
|
||||
# Remove the dummy pods
|
||||
unlink @dummyPods;
|
||||
rmdir "$poddir/man7";
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
# To enable linking between the cmd man pages and the db man pages, need to:
|
||||
# grep thru the cmd pods searching for references (L<>) to any section 5 man page
|
||||
# if that pod does not exist, create an empty one that will satisfy pod2html
|
||||
# keep track of all dummy pods created, so they can be removed later
|
||||
sub createDummyPods {
|
||||
my ($poddir, $pods) = @_;
|
||||
my $cmd = "grep -r -E 'L<.+\\([57]\\)\\|.+\\.[57]>' " . $poddir;
|
||||
#print "Running cmd: ", $cmd, "\n";
|
||||
my @lines = `$cmd`;
|
||||
if ($?) { print "Error running: $cmd\n"; print join('', @lines); }
|
||||
#my @lines;
|
||||
#system($cmd);
|
||||
my @dummyPods;
|
||||
foreach my $l (@lines) {
|
||||
#print "$l\n";
|
||||
my @matches = $l =~ /L<([^\(]+)\(([57])\)\|\1\.[57]>/g; # get all the matches in the line
|
||||
# The above line should create the array with every other entry being the man page name
|
||||
# and every other entry is the section # (5 or 7)
|
||||
my $cmd;
|
||||
while ($cmd=shift @matches) {
|
||||
#foreach my $m (@matches) {
|
||||
my $section = shift @matches;
|
||||
my $filename = "$poddir/man$section/$cmd.$section.pod";
|
||||
#print "$filename\n";
|
||||
if (!(grep /^$filename$/, @$pods) && !(grep /^$filename$/, @dummyPods)) { push @dummyPods, $filename; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Create these empty files
|
||||
print "Creating empty linked-to files: ", join(', ', @dummyPods), "\n";
|
||||
mkdir "$poddir/man7";
|
||||
foreach my $d (@dummyPods) {
|
||||
if (!open(TMP, ">>$d")) { warn "Could not create dummy pod file $d ($!)\n"; }
|
||||
else { close TMP; }
|
||||
}
|
||||
|
||||
return @dummyPods;
|
||||
}
|
||||
|
||||
# Recursively get the list of pod man page files.
|
||||
sub getPodList {
|
||||
my $poddir = shift;
|
||||
my @files;
|
||||
|
||||
# 1st get toplevel dir listing
|
||||
opendir(DIR, $poddir) or die "Error: could not read $poddir.\n";
|
||||
my @topdir = grep !/^\./, readdir(DIR); # /
|
||||
close(DIR);
|
||||
|
||||
# Now go thru each subdir (these are man1, man3, etc.)
|
||||
foreach my $mandir (@topdir) {
|
||||
opendir(DIR, "$poddir/$mandir") or die "Error: could not read $poddir/$mandir.\n";
|
||||
my @dir = grep !/^\./, readdir(DIR); # /
|
||||
close(DIR);
|
||||
foreach my $file (@dir) {
|
||||
push @files, "$poddir/$mandir/$file";
|
||||
}
|
||||
}
|
||||
return sort @files;
|
||||
}
|
||||
|
||||
|
||||
# Create the xcat man page that gives a summary description of each xcat cmd.
|
||||
# Not used
|
||||
sub writesummarypage {
|
||||
my $file = shift; # relative path file name of the man page
|
||||
# the rest of @_ contains the pod files that describe each cmd
|
||||
|
||||
open(FILE, ">$file") or die "Error: could not open $file for writing.\n";
|
||||
|
||||
print FILE <<'EOS1';
|
||||
=head1 NAME
|
||||
|
||||
B<xcat> - extreme Cluster Administration Tool.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Extreme Cluster Administration Toolkit (xCAT). xCAT is a scalable distributed computing management
|
||||
and provisioning tool that provides a unified interface for hardware control, discovery, and
|
||||
OS diskful/diskfree deployment.
|
||||
|
||||
|
||||
=head1 XCAT DATABASE
|
||||
|
||||
All of the cluster configuration information is in the xCAT database. See L<xcatdb(5)|xcatdb.5> for
|
||||
descriptions of every table in the database.
|
||||
|
||||
=head1 XCAT COMMANDS
|
||||
|
||||
What follows is a short description of each xCAT command. To get more information about a particular
|
||||
command, see its man page. Note that the commands are listed in alphabetical order B<within each section>,
|
||||
i.e. all the commands in section 1, then the commands in section 3, etc.
|
||||
|
||||
=over 12
|
||||
EOS1
|
||||
|
||||
# extract the summary for each cmd from its man page
|
||||
foreach my $manpage (@_) {
|
||||
my ($sectionnum) = $manpage =~ /\.(\d+)\.pod$/;
|
||||
# Suck in the whole file, then we will parse it.
|
||||
open(MANPAGE, "$manpage") or die "Error: could not open $manpage for reading.\n";
|
||||
my @contents = <MANPAGE>;
|
||||
my $wholemanpage = join('', @contents);
|
||||
close(MANPAGE);
|
||||
# This regex matches: optional space, =head1, space, title, space, cmd, space, description, newline
|
||||
my ($cmd, $description) = $wholemanpage =~ /^\s*=head1\s+\S+\s+(\S+)\s+(.+?)\n/si;
|
||||
if (!defined($cmd)) { print "Warning: $manpage is not in a recognized structure. It will be ignored.\n"; next; }
|
||||
if (!defined($description)) { print "Warning: $manpage does not have a description for $cmd. It will be ignored.\n"; next; }
|
||||
$cmd =~ s/^.<(.+)>$/$1/; # if the cmd name has pod formatting around it, strip it off
|
||||
$description =~ s/^-\s*//; # if the description has a leading hypen, strip it off
|
||||
print FILE "\n=item L<$cmd($sectionnum)|$cmd.$sectionnum>\n\n".$description."\n";
|
||||
}
|
||||
|
||||
# Artificially add the xcattest cmd, because the xCAT-test rpm will add this
|
||||
print FILE "\n=item L<xcattest(1)|xcattest.1>\n\nRun automated xCAT test cases.\n";
|
||||
|
||||
print FILE <<"EOS3";
|
||||
|
||||
=back
|
||||
EOS3
|
||||
|
||||
close FILE;
|
||||
}
|
||||
|
||||
|
||||
# Create the html page for one pod.
|
||||
sub convertpod2html {
|
||||
my ($podfile, $htmlfile, $poddir, $htmldir) = @_;
|
||||
|
||||
#TODO: use --css=<stylesheet> and --title=<pagetitle> to make the pages look better
|
||||
pod2html($podfile,
|
||||
"--outfile=$htmlfile",
|
||||
"--podpath=man1",
|
||||
"--podroot=$poddir",
|
||||
"--htmldir=$htmldir",
|
||||
"--recurse",
|
||||
"--cachedir=$cachedir",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
# Create the man page for one pod.
|
||||
sub convertpod2man {
|
||||
my ($podfile, $manfile, $section) = @_;
|
||||
|
||||
my $parser = Pod::Man->new(section => $section);
|
||||
$parser->parse_from_file($podfile, $manfile);
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
<html xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||
xmlns:w="urn:schemas-microsoft-com:office:word"
|
||||
xmlns="http://www.w3.org/TR/REC-html40">
|
||||
|
||||
<head>
|
||||
<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
|
||||
<meta name=ProgId content=Word.Document>
|
||||
<meta name=Generator content="Microsoft Word 9">
|
||||
<meta name=Originator content="Microsoft Word 9">
|
||||
<title>Eclipse Public License - Version 1.0</title>
|
||||
<!--[if gte mso 9]><xml>
|
||||
<o:DocumentProperties>
|
||||
<o:Revision>2</o:Revision>
|
||||
<o:TotalTime>3</o:TotalTime>
|
||||
<o:Created>2004-03-05T23:03:00Z</o:Created>
|
||||
<o:LastSaved>2004-03-05T23:03:00Z</o:LastSaved>
|
||||
<o:Pages>4</o:Pages>
|
||||
<o:Words>1626</o:Words>
|
||||
<o:Characters>9270</o:Characters>
|
||||
<o:Lines>77</o:Lines>
|
||||
<o:Paragraphs>18</o:Paragraphs>
|
||||
<o:CharactersWithSpaces>11384</o:CharactersWithSpaces>
|
||||
<o:Version>9.4402</o:Version>
|
||||
</o:DocumentProperties>
|
||||
</xml><![endif]--><!--[if gte mso 9]><xml>
|
||||
<w:WordDocument>
|
||||
<w:TrackRevisions/>
|
||||
</w:WordDocument>
|
||||
</xml><![endif]-->
|
||||
<style>
|
||||
<!--
|
||||
/* Font Definitions */
|
||||
@font-face
|
||||
{font-family:Tahoma;
|
||||
panose-1:2 11 6 4 3 5 4 4 2 4;
|
||||
mso-font-charset:0;
|
||||
mso-generic-font-family:swiss;
|
||||
mso-font-pitch:variable;
|
||||
mso-font-signature:553679495 -2147483648 8 0 66047 0;}
|
||||
/* Style Definitions */
|
||||
p.MsoNormal, li.MsoNormal, div.MsoNormal
|
||||
{mso-style-parent:"";
|
||||
margin:0in;
|
||||
margin-bottom:.0001pt;
|
||||
mso-pagination:widow-orphan;
|
||||
font-size:12.0pt;
|
||||
font-family:"Times New Roman";
|
||||
mso-fareast-font-family:"Times New Roman";}
|
||||
p
|
||||
{margin-right:0in;
|
||||
mso-margin-top-alt:auto;
|
||||
mso-margin-bottom-alt:auto;
|
||||
margin-left:0in;
|
||||
mso-pagination:widow-orphan;
|
||||
font-size:12.0pt;
|
||||
font-family:"Times New Roman";
|
||||
mso-fareast-font-family:"Times New Roman";}
|
||||
p.BalloonText, li.BalloonText, div.BalloonText
|
||||
{mso-style-name:"Balloon Text";
|
||||
margin:0in;
|
||||
margin-bottom:.0001pt;
|
||||
mso-pagination:widow-orphan;
|
||||
font-size:8.0pt;
|
||||
font-family:Tahoma;
|
||||
mso-fareast-font-family:"Times New Roman";}
|
||||
@page Section1
|
||||
{size:8.5in 11.0in;
|
||||
margin:1.0in 1.25in 1.0in 1.25in;
|
||||
mso-header-margin:.5in;
|
||||
mso-footer-margin:.5in;
|
||||
mso-paper-source:0;}
|
||||
div.Section1
|
||||
{page:Section1;}
|
||||
-->
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body lang=EN-US style='tab-interval:.5in'>
|
||||
|
||||
<div class=Section1>
|
||||
|
||||
<p align=center style='text-align:center'><b>Eclipse Public License - v 1.0</b>
|
||||
</p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
|
||||
THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE,
|
||||
REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
|
||||
OF THIS AGREEMENT.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>1. DEFINITIONS</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Contribution" means:</span> </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
in the case of the initial Contributor, the initial code and documentation
|
||||
distributed under this Agreement, and<br clear=left>
|
||||
b) in the case of each subsequent Contributor:</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
|
||||
changes to the Program, and</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
|
||||
additions to the Program;</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>where
|
||||
such changes and/or additions to the Program originate from and are distributed
|
||||
by that particular Contributor. A Contribution 'originates' from a Contributor
|
||||
if it was added to the Program by such Contributor itself or anyone acting on
|
||||
such Contributor's behalf. Contributions do not include additions to the
|
||||
Program which: (i) are separate modules of software distributed in conjunction
|
||||
with the Program under their own license agreement, and (ii) are not derivative
|
||||
works of the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Contributor" means any person or
|
||||
entity that distributes the Program.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Licensed Patents " mean patent
|
||||
claims licensable by a Contributor which are necessarily infringed by the use
|
||||
or sale of its Contribution alone or when combined with the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Program" means the Contributions
|
||||
distributed in accordance with this Agreement.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>"Recipient" means anyone who
|
||||
receives the Program under this Agreement, including all Contributors.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>2. GRANT OF RIGHTS</span></b> </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
Subject to the terms of this Agreement, each Contributor hereby grants Recipient
|
||||
a non-exclusive, worldwide, royalty-free copyright license to<span
|
||||
style='color:red'> </span>reproduce, prepare derivative works of, publicly
|
||||
display, publicly perform, distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such derivative works, in source code and object code
|
||||
form.</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
|
||||
Subject to the terms of this Agreement, each Contributor hereby grants
|
||||
Recipient a non-exclusive, worldwide,<span style='color:green'> </span>royalty-free
|
||||
patent license under Licensed Patents to make, use, sell, offer to sell, import
|
||||
and otherwise transfer the Contribution of such Contributor, if any, in source
|
||||
code and object code form. This patent license shall apply to the combination
|
||||
of the Contribution and the Program if, at the time the Contribution is added
|
||||
by the Contributor, such addition of the Contribution causes such combination
|
||||
to be covered by the Licensed Patents. The patent license shall not apply to
|
||||
any other combinations which include the Contribution. No hardware per se is
|
||||
licensed hereunder. </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>c)
|
||||
Recipient understands that although each Contributor grants the licenses to its
|
||||
Contributions set forth herein, no assurances are provided by any Contributor
|
||||
that the Program does not infringe the patent or other intellectual property
|
||||
rights of any other entity. Each Contributor disclaims any liability to Recipient
|
||||
for claims brought by any other entity based on infringement of intellectual
|
||||
property rights or otherwise. As a condition to exercising the rights and
|
||||
licenses granted hereunder, each Recipient hereby assumes sole responsibility
|
||||
to secure any other intellectual property rights needed, if any. For example,
|
||||
if a third party patent license is required to allow Recipient to distribute
|
||||
the Program, it is Recipient's responsibility to acquire that license before
|
||||
distributing the Program.</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>d)
|
||||
Each Contributor represents that to its knowledge it has sufficient copyright
|
||||
rights in its Contribution, if any, to grant the copyright license set forth in
|
||||
this Agreement. </span></p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>3. REQUIREMENTS</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>A Contributor may choose to distribute the
|
||||
Program in object code form under its own license agreement, provided that:</span>
|
||||
</p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
it complies with the terms and conditions of this Agreement; and</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
|
||||
its license agreement:</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
|
||||
effectively disclaims on behalf of all Contributors all warranties and
|
||||
conditions, express and implied, including warranties or conditions of title
|
||||
and non-infringement, and implied warranties or conditions of merchantability
|
||||
and fitness for a particular purpose; </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
|
||||
effectively excludes on behalf of all Contributors all liability for damages,
|
||||
including direct, indirect, special, incidental and consequential damages, such
|
||||
as lost profits; </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iii)
|
||||
states that any provisions which differ from this Agreement are offered by that
|
||||
Contributor alone and not by any other party; and</span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iv)
|
||||
states that source code for the Program is available from such Contributor, and
|
||||
informs licensees how to obtain it in a reasonable manner on or through a
|
||||
medium customarily used for software exchange.<span style='color:blue'> </span></span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>When the Program is made available in source
|
||||
code form:</span> </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
|
||||
it must be made available under this Agreement; and </span></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b) a
|
||||
copy of this Agreement must be included with each copy of the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Contributors may not remove or alter any
|
||||
copyright notices contained within the Program. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Each Contributor must identify itself as the
|
||||
originator of its Contribution, if any, in a manner that reasonably allows
|
||||
subsequent Recipients to identify the originator of the Contribution. </span></p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>4. COMMERCIAL DISTRIBUTION</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Commercial distributors of software may
|
||||
accept certain responsibilities with respect to end users, business partners
|
||||
and the like. While this license is intended to facilitate the commercial use
|
||||
of the Program, the Contributor who includes the Program in a commercial
|
||||
product offering should do so in a manner which does not create potential
|
||||
liability for other Contributors. Therefore, if a Contributor includes the
|
||||
Program in a commercial product offering, such Contributor ("Commercial
|
||||
Contributor") hereby agrees to defend and indemnify every other
|
||||
Contributor ("Indemnified Contributor") against any losses, damages and
|
||||
costs (collectively "Losses") arising from claims, lawsuits and other
|
||||
legal actions brought by a third party against the Indemnified Contributor to
|
||||
the extent caused by the acts or omissions of such Commercial Contributor in
|
||||
connection with its distribution of the Program in a commercial product
|
||||
offering. The obligations in this section do not apply to any claims or Losses
|
||||
relating to any actual or alleged intellectual property infringement. In order
|
||||
to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
|
||||
Contributor in writing of such claim, and b) allow the Commercial Contributor
|
||||
to control, and cooperate with the Commercial Contributor in, the defense and
|
||||
any related settlement negotiations. The Indemnified Contributor may participate
|
||||
in any such claim at its own expense.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>For example, a Contributor might include the
|
||||
Program in a commercial product offering, Product X. That Contributor is then a
|
||||
Commercial Contributor. If that Commercial Contributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance claims and
|
||||
warranties are such Commercial Contributor's responsibility alone. Under this
|
||||
section, the Commercial Contributor would have to defend claims against the
|
||||
other Contributors related to those performance claims and warranties, and if a
|
||||
court requires any other Contributor to pay any damages as a result, the
|
||||
Commercial Contributor must pay those damages.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>5. NO WARRANTY</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
|
||||
AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
|
||||
WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and distributing the
|
||||
Program and assumes all risks associated with its exercise of rights under this
|
||||
Agreement , including but not limited to the risks and costs of program errors,
|
||||
compliance with applicable laws, damage to or loss of data, programs or
|
||||
equipment, and unavailability or interruption of operations. </span></p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>6. DISCLAIMER OF LIABILITY</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
|
||||
AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
|
||||
THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
|
||||
|
||||
<p><b><span style='font-size:10.0pt'>7. GENERAL</span></b> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>If any provision of this Agreement is invalid
|
||||
or unenforceable under applicable law, it shall not affect the validity or
|
||||
enforceability of the remainder of the terms of this Agreement, and without
|
||||
further action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>If Recipient institutes patent litigation
|
||||
against any entity (including a cross-claim or counterclaim in a lawsuit)
|
||||
alleging that the Program itself (excluding combinations of the Program with
|
||||
other software or hardware) infringes such Recipient's patent(s), then such
|
||||
Recipient's rights granted under Section 2(b) shall terminate as of the date
|
||||
such litigation is filed. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>All Recipient's rights under this Agreement
|
||||
shall terminate if it fails to comply with any of the material terms or
|
||||
conditions of this Agreement and does not cure such failure in a reasonable
|
||||
period of time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use and
|
||||
distribution of the Program as soon as reasonably practicable. However,
|
||||
Recipient's obligations under this Agreement and any licenses granted by
|
||||
Recipient relating to the Program shall continue and survive. </span></p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>Everyone is permitted to copy and distribute
|
||||
copies of this Agreement, but in order to avoid inconsistency the Agreement is
|
||||
copyrighted and may only be modified in the following manner. The Agreement
|
||||
Steward reserves the right to publish new versions (including revisions) of
|
||||
this Agreement from time to time. No one other than the Agreement Steward has
|
||||
the right to modify this Agreement. The Eclipse Foundation is the initial
|
||||
Agreement Steward. The Eclipse Foundation may assign the responsibility to
|
||||
serve as the Agreement Steward to a suitable separate entity. Each new version
|
||||
of the Agreement will be given a distinguishing version number. The Program
|
||||
(including Contributions) may always be distributed subject to the version of
|
||||
the Agreement under which it was received. In addition, after a new version of
|
||||
the Agreement is published, Contributor may elect to distribute the Program
|
||||
(including its Contributions) under the new version. Except as expressly stated
|
||||
in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
|
||||
the intellectual property of any Contributor under this Agreement, whether
|
||||
expressly, by implication, estoppel or otherwise. All rights in the Program not
|
||||
expressly granted under this Agreement are reserved.</span> </p>
|
||||
|
||||
<p><span style='font-size:10.0pt'>This Agreement is governed by the laws of the
|
||||
State of New York and the intellectual property laws of the United States of
|
||||
America. No party to this Agreement will bring a legal action under this
|
||||
Agreement more than one year after the cause of action arose. Each party waives
|
||||
its rights to a jury trial in any resulting litigation.</span> </p>
|
||||
|
||||
<p class=MsoNormal><![if !supportEmptyParas]> <![endif]><o:p></o:p></p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Executable
+411
@@ -0,0 +1,411 @@
|
||||
#!/usr/bin/perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
# Builds the xCAT-OpenStack database table man pages from the descriptions that are contained
|
||||
# in the Cloud.pm schema plugin. This script is run during the build of the xCAT-OpenStack rpm, but
|
||||
# is not packaged in the binary form of that rpm.
|
||||
|
||||
# This script is run in the xCAT-OpenStack subdir of the rpm build directory, so everything is
|
||||
# done relative to that.
|
||||
|
||||
# The overview of what this script does is:
|
||||
# - get the table descriptions from lib/perl/xCAT_schema/Clouds.pm and create a summary man page
|
||||
# - iterate thru the tables in lib/perl/xCAT_schema/Clouds.pm and create pods for each
|
||||
# - use the pod2man to convert them to man pages
|
||||
# - use the pod2html to convert them to html pages
|
||||
|
||||
use strict;
|
||||
use lib 'lib/perl';
|
||||
|
||||
use xCAT_schema::Clouds;
|
||||
#use xCAT::Table;
|
||||
use Pod::Man;
|
||||
use Pod::Html;
|
||||
|
||||
my $VERBOSE = 1; # set this to 1 for debugging
|
||||
my $poddir = 'pods';
|
||||
my $mandir = 'share/man';
|
||||
my $htmldir = 'share/doc';
|
||||
my $cachedir = '/tmp';
|
||||
|
||||
my $poddir5 = 'pods/man5';
|
||||
my $poddir7 = 'pods/man7';
|
||||
if (system("mkdir -p $poddir5")) { die "Error: could not create $poddir5.\n"; }
|
||||
if (system("mkdir -p $poddir7")) { die "Error: could not create $poddir7.\n"; }
|
||||
|
||||
# Build the DB overview page.
|
||||
print "Building PODs pages for the database tables...\n";
|
||||
writesummarypage("$poddir5/xcat-openstack-db.5.pod", getTableDescriptions(), getDefRef());
|
||||
|
||||
# Build the pod man page for each object definition
|
||||
my $defspecref = getDefRef();
|
||||
foreach my $defkey (keys %$defspecref) {
|
||||
my $def = $defspecref->{$defkey};
|
||||
my $attrs = $def->{'attrs'};
|
||||
my $podfile = "$poddir7/$defkey.7.pod";
|
||||
verbose("Writing pod file for $defkey");
|
||||
writedefmanpage($podfile, $defkey, $attrs);
|
||||
}
|
||||
|
||||
# Build the pod man page for each table.
|
||||
my $tabspecref = getTableRef();
|
||||
foreach my $tablekey (keys %$tabspecref) {
|
||||
my $table = $tabspecref->{$tablekey};
|
||||
my $summary = $table->{table_desc};
|
||||
my $colorder = $table->{cols};
|
||||
my $descriptions = $table->{descriptions};
|
||||
verbose("Writing pod file for $tablekey");
|
||||
writepodmanpage("$poddir5/$tablekey.5.pod", $tablekey, $summary, $colorder, $descriptions);
|
||||
}
|
||||
|
||||
my @pods = getPodList($poddir);
|
||||
verbose('Pod list:' . "@pods");
|
||||
|
||||
# Build the man page for each pod.
|
||||
print "Converting PODs to man pages...\n";
|
||||
foreach my $podfile (@pods) {
|
||||
my $manfile = $podfile;
|
||||
$manfile =~ s/^$poddir/$mandir/; # change the beginning of the path
|
||||
$manfile =~ s/\.pod$//; # change the ending
|
||||
my $mdir = $manfile;
|
||||
$mdir =~ s|/[^/]*$||; # get rid of the basename part
|
||||
if (system("mkdir -p $mdir")) { die "Error: could not create $mdir.\n"; }
|
||||
my ($section) = $podfile =~ /\.(\d+)\.pod$/;
|
||||
verbose("Converting $podfile to $manfile");
|
||||
convertpod2man($podfile, $manfile, $section);
|
||||
}
|
||||
|
||||
my @dummyPods = createDummyPods($poddir);
|
||||
|
||||
# Build the html page for each pod.
|
||||
print "Converting PODs to HTML pages...\n";
|
||||
# have to clear the cache, because old entries can cause a problem
|
||||
unlink("$cachedir/pod2htmd.tmp", "$cachedir/pod2htmi.tmp");
|
||||
foreach my $podfile (@pods) {
|
||||
my $htmlfile = $podfile;
|
||||
$htmlfile =~ s/^$poddir/$htmldir/; # change the beginning of the path
|
||||
$htmlfile =~ s/\.pod$/\.html/; # change the ending
|
||||
my $hdir = $htmlfile;
|
||||
$hdir =~ s|/[^/]*$||; # get rid of the basename part
|
||||
if (system("mkdir -p $hdir")) { die "Error: could not create $hdir.\n"; }
|
||||
verbose("Converting $podfile to $htmlfile");
|
||||
convertpod2html($podfile, $htmlfile, $poddir, $htmldir);
|
||||
}
|
||||
|
||||
unlink @dummyPods;
|
||||
|
||||
exit;
|
||||
|
||||
# if VERBOSE is on, print out the given string
|
||||
sub verbose { if ($VERBOSE) { print $_[0], "\n"; } }
|
||||
|
||||
sub getDefRef { return \%xCAT_schema::Clouds::defspec; }
|
||||
|
||||
sub getTableRef { return \%xCAT_schema::Clouds::tabspec; }
|
||||
|
||||
# Returns a list of the table names in the xCAT database.
|
||||
sub getTableList { return keys %xCAT_schema::Clouds::tabspec; }
|
||||
|
||||
# Returns a reference to the db schema hash for the specified table.
|
||||
sub getTableSchema { return $xCAT_schema::Clouds::tabspec{$_[0]}; }
|
||||
|
||||
# Return a reference to a hash where each key is the table name and each value is the table description.
|
||||
sub getTableDescriptions {
|
||||
# List each table name and the value for table_desc.
|
||||
my $ret = {};
|
||||
#my @a = keys %{$xCAT_schema::Clouds::tabspec{nodelist}}; print 'a=', @a, "\n";
|
||||
foreach my $t (getTableList()) { $ret->{$t} = getTableSchema($t)->{table_desc}; }
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
# Recursively get the list of pod man page files.
|
||||
sub getPodList {
|
||||
my $poddir = shift;
|
||||
my @files;
|
||||
|
||||
# 1st get toplevel dir listing
|
||||
opendir(DIR, $poddir) or die "Error: could not read $poddir.\n";
|
||||
my @topdir = grep !/^\./, readdir(DIR); # /
|
||||
close(DIR);
|
||||
|
||||
# Now go thru each subdir (these are man1, man3, etc.)
|
||||
foreach my $mandir (@topdir) {
|
||||
opendir(DIR, "$poddir/$mandir") or die "Error: could not read $poddir/$mandir.\n";
|
||||
my @dir = grep !/^\./, readdir(DIR); # /
|
||||
close(DIR);
|
||||
foreach my $file (@dir) {
|
||||
push @files, "$poddir/$mandir/$file";
|
||||
}
|
||||
}
|
||||
return sort @files;
|
||||
}
|
||||
|
||||
|
||||
# Create the html page for one pod.
|
||||
sub convertpod2html {
|
||||
my ($podfile, $htmlfile, $poddir, $htmldir) = @_;
|
||||
|
||||
#TODO: use --css=<stylesheet> and --title=<pagetitle> to make the pages look better
|
||||
pod2html($podfile,
|
||||
"--outfile=$htmlfile",
|
||||
"--podpath=man5:man7",
|
||||
"--podroot=$poddir",
|
||||
"--htmldir=$htmldir",
|
||||
"--recurse",
|
||||
"--cachedir=$cachedir",
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
# Create the man page for one pod.
|
||||
sub convertpod2man {
|
||||
my ($podfile, $manfile, $section) = @_;
|
||||
|
||||
my $parser = Pod::Man->new(section => $section);
|
||||
$parser->parse_from_file($podfile, $manfile);
|
||||
}
|
||||
|
||||
|
||||
# Create the xcat-openstack-db man page that gives a summary description of each table.
|
||||
sub writesummarypage {
|
||||
my $file = shift; # relative path file name of the man page
|
||||
my $descriptions = shift; # a hash containing the description of each table
|
||||
my $defdescriptions = shift; # a hash containing the description of each object definition
|
||||
|
||||
open(FILE, ">$file") or die "Error: could not open $file for writing.\n";
|
||||
|
||||
print FILE <<'EOS1';
|
||||
=head1 NAME
|
||||
|
||||
An overview of the xCAT OpenStack database objects and tables.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The xCAT OpenStack database objects and tables contain user settings for the OpenStack cloud being set up by xCAT.
|
||||
To get more information about a particular table, run man for that table name.
|
||||
The tables and objects can be viewed using B<tabdump>, B<nodels>, or B<lsdef>.
|
||||
The tables and objects can be manipulated directly using B<tabedit>, B<nodech>, or B<chdef>.
|
||||
For more information about the xCAT database and the base tables and objects, see the L<xcatdb(5)|xcatdb.5> man page.
|
||||
|
||||
=head1 XCAT OPENSTACK OBJECT DEFINITIONS
|
||||
|
||||
Because it can get confusing what attributes need to go in what tables, the xCAT database can also
|
||||
be viewed and edited as logical objects, instead of flat tables. Use B<mkdef>, B<chdef>, B<lsdef>,
|
||||
and B<rmdef> to create, change, list, and delete objects.
|
||||
When using these commands, the object attributes will be stored in the same tables, as if you edited
|
||||
the tables by hand. The only difference is that the object commands take care of knowing which tables
|
||||
all of the information should go in.
|
||||
|
||||
To run man for any of the object definitions below, use section 7. For example: B<man 7 node>
|
||||
|
||||
The object types are:
|
||||
|
||||
=over 2
|
||||
EOS1
|
||||
|
||||
foreach my $def (sort keys %$defdescriptions) {
|
||||
if ($def eq 'node') { print FILE "\n=item L<$def(7)|node-openstack.7>\n"; } # can not overwrite the node man page in xcat-core
|
||||
else { print FILE "\n=item L<$def(7)|$def.7>\n"; }
|
||||
}
|
||||
|
||||
print FILE <<"EOS2";
|
||||
|
||||
=back
|
||||
|
||||
=head1 TABLES
|
||||
|
||||
To manipulate the tables directly, use B<nodels(1)>, B<chtab(8)>, B<tabdump(8)>, B<tabedit(8)>,
|
||||
B<nodeadd(8)>, B<nodech(1)>.
|
||||
|
||||
To run man for any of the table descriptions below, use section 5. For example: B<man 5 nodehm>
|
||||
|
||||
The tables are:
|
||||
|
||||
=over 2
|
||||
EOS2
|
||||
|
||||
foreach my $table (sort keys %$descriptions) {
|
||||
print FILE "\n=item L<$table(5)|$table.5>\n\n".$descriptions->{$table}."\n";
|
||||
}
|
||||
|
||||
print FILE <<"EOS3";
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
B<nodels(1)>, B<chtab(8)>, B<tabdump(8)>, B<tabedit(8)>, B<lsdef(1)>, B<mkdef(1)>, B<chdef(1)>, B<rmdef(1)>
|
||||
EOS3
|
||||
|
||||
close FILE;
|
||||
}
|
||||
|
||||
|
||||
# Create the man page for one object definition.
|
||||
sub writedefmanpage {
|
||||
my $file = shift; # relative path file name of the man page
|
||||
my $defname = shift; # name of object
|
||||
my $attrs = shift; # reference to the array of attributes
|
||||
|
||||
# Make exception for the node object, because we can not overwrite the node man page from xcat-core
|
||||
if ($defname eq 'node') { $file = "$poddir7/node-openstack.7.pod"; }
|
||||
|
||||
# Go thru the attributes, collecting the descriptions
|
||||
# Note: this logic is loosely taken from DBobjectdefs.pm
|
||||
my %attrlist; # holds the attr name as the key, and the description & tables as value
|
||||
foreach my $this_attr (@$attrs) {
|
||||
my $attr = $this_attr->{attr_name};
|
||||
my $desc = $this_attr->{description};
|
||||
my ($table, $at) = split(/\./, $this_attr->{tabentry});
|
||||
if (!defined($desc)) {
|
||||
# description key not there, so go to the corresponding
|
||||
# entry in tabspec to get the description
|
||||
my $schema = getTableSchema($table);
|
||||
$desc = $schema->{descriptions}->{$at};
|
||||
}
|
||||
|
||||
# Attr names can appear more than once, if they are in multiple tables.
|
||||
# We will keep track of that based on the table attribute, because that can be duplicated too
|
||||
if (!defined($attrlist{$attr})) {
|
||||
$attrlist{$attr}->{'tables'} = []; # initialize the array, so we can check it below
|
||||
}
|
||||
my $tableattr = "$table.$at";
|
||||
if (!grep(/^$tableattr$/, @{$attrlist{$attr}->{'tables'}})) {
|
||||
# there can be multiple entries that refer to the same table attribute
|
||||
# if this is a new table attribute, then save the attr name and description
|
||||
push @{$attrlist{$attr}->{'tables'}}, $tableattr;
|
||||
push @{$attrlist{$attr}->{'descriptions'}}, $desc;
|
||||
}
|
||||
}
|
||||
|
||||
open(FILE, ">$file") or die "Error: could not open $file for writing.\n";
|
||||
|
||||
print FILE <<"EOS1";
|
||||
=head1 NAME
|
||||
|
||||
B<$defname> - a logical object definition in the xCAT database.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
EOS1
|
||||
|
||||
print FILE "B<$defname Attributes:> I<" . join('>, I<',sort(keys(%attrlist))) . ">\n";
|
||||
|
||||
print FILE <<"EOS2";
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Logical objects of this type are stored in the xCAT database in one or more tables. Use the following commands
|
||||
to manipulate the objects: B<mkdef>, B<chdef>, B<lsdef>, and B<rmdef>. These commands will take care of
|
||||
knowing which tables the object attributes should be stored in. The attribute list below shows, in
|
||||
parentheses, what tables each attribute is stored in.
|
||||
|
||||
=head1 $defname Attributes:
|
||||
|
||||
=over 6
|
||||
|
||||
EOS2
|
||||
|
||||
foreach my $a (sort keys %attrlist) {
|
||||
my $d = join("\nor\n", @{$attrlist{$a}->{'descriptions'}});
|
||||
$d =~ s/\n/\n\n/sg; # if there are newlines, double them so pod sees a blank line, otherwise pod will ignore them
|
||||
my $t = '(' . join(', ',@{$attrlist{$a}->{'tables'}}) . ')';
|
||||
#print FILE "\nB<$a> - $d\n";
|
||||
print FILE "\n=item B<$a> $t\n\n$d\n";
|
||||
}
|
||||
|
||||
print FILE <<"EOS3";
|
||||
|
||||
=back
|
||||
|
||||
EOS3
|
||||
|
||||
if ($defname eq 'node') {
|
||||
print FILE "B<The node attributes listed above are just the ones that the xCAT-OpenStack RPM adds to the node object definition. For the rest of the node attributes from xcat-core, see the L<node(7)|node.7> man page.>\n\n";
|
||||
}
|
||||
|
||||
print FILE <<"EOS4";
|
||||
=head1 SEE ALSO
|
||||
|
||||
B<mkdef(1)>, B<chdef(1)>, B<lsdef(1)>, B<rmdef(1)>
|
||||
EOS4
|
||||
|
||||
close FILE;
|
||||
}
|
||||
|
||||
|
||||
# Create the man page for one table.
|
||||
sub writepodmanpage {
|
||||
my $file = shift; # relative path file name of the man page
|
||||
my $tablename = shift; # name of table
|
||||
my $summary = shift; # description of table
|
||||
my $colorder = shift; # the order in which the table attributes should be presented in
|
||||
my $descriptions = shift; # a hash containing the description of each attribute
|
||||
|
||||
open(FILE, ">$file") or die "Error: could not open $file for writing.\n";
|
||||
|
||||
print FILE <<"EOS1";
|
||||
=head1 NAME
|
||||
|
||||
B<$tablename> - a table in the xCAT database.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
EOS1
|
||||
|
||||
print FILE "B<$tablename Attributes:> I<" . join('>, I<',@$colorder) . ">\n";
|
||||
|
||||
print FILE <<"EOS2";
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
$summary
|
||||
|
||||
=head1 $tablename Attributes:
|
||||
|
||||
=over 10
|
||||
|
||||
EOS2
|
||||
|
||||
foreach my $a (@$colorder) {
|
||||
my $d = $descriptions->{$a};
|
||||
#$d =~ s/\n/\n\n/sg; # if there are newlines, double them so pod sees a blank line, otherwise pod will ignore them
|
||||
#print FILE "\nB<$a> - $d\n";
|
||||
print FILE "\n=item B<$a>\n\n$d\n";
|
||||
}
|
||||
|
||||
print FILE <<"EOS3";
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
B<nodels(1)>, B<chtab(8)>, B<tabdump(8)>, B<tabedit(8)>
|
||||
EOS3
|
||||
|
||||
close FILE;
|
||||
}
|
||||
|
||||
|
||||
# To enable linking between the man pages in xCAT-OpenStack and the xcat-core man pages
|
||||
# we need to create an empty one that will satisfy pod2html.
|
||||
# Returns all dummy pods created, so they can be removed later
|
||||
sub createDummyPods {
|
||||
my $poddir = shift @_;
|
||||
|
||||
# Also add xcattest.1.pod and buildkit.1.pod, because the xcat.1.pod summary page refers to it
|
||||
push @dummyPods, "$poddir/man7/node.7.pod";
|
||||
push @dummyPods, "$poddir/man5/xcatdb.5.pod";
|
||||
|
||||
# Create these empty files
|
||||
print "Creating empty linked-to files: ", join(', ', @dummyPods), "\n";
|
||||
#mkdir "$poddir/man7";
|
||||
foreach my $d (@dummyPods) {
|
||||
if (!open(TMP, ">>$d")) { warn "Could not create dummy pod file $d ($!)\n"; }
|
||||
else { close TMP; }
|
||||
}
|
||||
|
||||
return @dummyPods;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
xcat-openstack (2.9) unstable; urgency=low
|
||||
|
||||
* Initial release
|
||||
|
||||
-- root <root@unknown> Mon, 01 Jul 2013 15:04:41 +0800
|
||||
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -0,0 +1,14 @@
|
||||
Source: xcat-openstack
|
||||
Section: admin
|
||||
Priority: extra
|
||||
Maintainer: xCAT <xcat-user@lists.sourceforge.net>
|
||||
Build-Depends: debhelper (>= 8.0.0)
|
||||
Standards-Version: 3.9.2
|
||||
#Vcs-Git: git://git.debian.org/collab-maint/xcat-openstack.git
|
||||
#Vcs-Browser: http://git.debian.org/?p=collab-maint/xcat-openstack.git;a=summary
|
||||
|
||||
Package: xcat-openstack
|
||||
Architecture: all
|
||||
Depends: xcat
|
||||
Description: Meta-Metapackage for a common, default xCAT management node setup with OpenStack
|
||||
xCAT-OpenStack is an xCAT management node package intended for at-scale management with OpenStack, including hardware management and software management.
|
||||
@@ -0,0 +1,88 @@
|
||||
Eclipse Public License - v 1.0
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
|
||||
b) in the case of each subsequent Contributor:
|
||||
|
||||
i) changes to the Program, and
|
||||
|
||||
ii) additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
|
||||
|
||||
"Contributor" means any person or entity that distributes the Program.
|
||||
|
||||
"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
|
||||
|
||||
"Program" means the Contributions distributed in accordance with this Agreement.
|
||||
|
||||
"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
|
||||
|
||||
b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
|
||||
|
||||
c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
|
||||
|
||||
d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
|
||||
|
||||
a) it complies with the terms and conditions of this Agreement; and
|
||||
|
||||
b) its license agreement:
|
||||
|
||||
i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
|
||||
|
||||
ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
|
||||
|
||||
iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
|
||||
|
||||
iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
|
||||
|
||||
When the Program is made available in source code form:
|
||||
|
||||
a) it must be made available under this Agreement; and
|
||||
|
||||
b) a copy of this Agreement must be included with each copy of the Program.
|
||||
|
||||
Contributors may not remove or alter any copyright notices contained within the Program.
|
||||
|
||||
Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
|
||||
|
||||
For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
|
||||
|
||||
Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
opt/xcat/lib/perl/xCAT_schema
|
||||
opt/xcat/lib/perl/xCAT_plugin
|
||||
opt/xcat/lib/perl/xCAT
|
||||
opt/xcat/share/xcat/mypostscript
|
||||
opt/xcat/share/xcat/templates
|
||||
opt/xcat/sbin
|
||||
opt/xcat/share/man/man5
|
||||
opt/xcat/share/doc/man5
|
||||
opt/xcat/share/man/man7
|
||||
opt/xcat/share/doc/man7
|
||||
install/postscripts
|
||||
@@ -0,0 +1,10 @@
|
||||
lib/perl/xCAT_schema/* opt/xcat/lib/perl/xCAT_schema/
|
||||
lib/perl/xCAT_plugin/* opt/xcat/lib/perl/xCAT_plugin/
|
||||
lib/perl/xCAT/* opt/xcat/lib/perl/xCAT/
|
||||
sbin/* opt/xcat/sbin/
|
||||
share/man/man5/* opt/xcat/share/man/man5/
|
||||
share/doc/man5/* opt/xcat/share/doc/man5/
|
||||
share/man/man7/* opt/xcat/share/man/man7/
|
||||
share/doc/man7/* opt/xcat/share/doc/man7/
|
||||
postscripts/* install/postscripts/
|
||||
share/xcat/* opt/xcat/share/xcat/
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
# postinst script for xCAT
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <postinst> `abort-remove'
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
if [ -f "/proc/cmdline" ];then
|
||||
if [ -f "/opt/xcat/sbin/xcatd" ];then
|
||||
/etc/init.d/xcatd reload
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
build:
|
||||
pwd
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -d
|
||||
|
||||
install:
|
||||
pwd
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installdirs
|
||||
`pwd`/db2man
|
||||
dh_install -X".svn"
|
||||
chmod 755 `pwd`/debian/xcat-openstack/opt/xcat/lib/perl/xCAT_schema
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/lib/perl/xCAT_schema/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/lib/perl/xCAT_plugin/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/lib/perl/xCAT/*
|
||||
chmod 755 `pwd`/debian/xcat-openstack/opt/xcat/sbin/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/share/man/man5/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/share/doc/man5/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/share/man/man7/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/share/doc/man7/*
|
||||
chmod 755 `pwd`/debian/xcat-openstack/install/postscripts/*
|
||||
chmod 644 `pwd`/debian/xcat-openstack/opt/xcat/share/xcat/*
|
||||
dh_link
|
||||
|
||||
binary-indep: build install
|
||||
pwd
|
||||
export
|
||||
dh_installman
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary-arch:
|
||||
pwd
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
@@ -0,0 +1 @@
|
||||
1.0
|
||||
@@ -0,0 +1,168 @@
|
||||
# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
package xCAT::Cloud;
|
||||
|
||||
BEGIN
|
||||
{
|
||||
$::XCATROOT =
|
||||
$ENV{'XCATROOT'} ? $ENV{'XCATROOT'}
|
||||
: -d '/opt/xcat' ? '/opt/xcat'
|
||||
: '/usr';
|
||||
}
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use xCAT::Table;
|
||||
use xCAT::MsgUtils;
|
||||
use xCAT::NodeRange;
|
||||
use xCAT::Utils;
|
||||
use xCAT::TableUtils;
|
||||
#use Data::Dumper;
|
||||
use strict;
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
=head3 getcloudinfo
|
||||
|
||||
This function will be invoked by Postage.pm.
|
||||
get the chef cookbook repository for each cloud from the clouds table, and
|
||||
then get all the node --> cloud from the cloud table. The two type information
|
||||
will be stored in the %info
|
||||
|
||||
If success, return the \%info.
|
||||
|
||||
|
||||
Arguments:
|
||||
none
|
||||
Returns:
|
||||
\%info
|
||||
|
||||
Error:
|
||||
none
|
||||
Example:
|
||||
|
||||
Comments:
|
||||
none
|
||||
|
||||
=cut
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
sub getcloudinfo
|
||||
{
|
||||
my %info = ();
|
||||
|
||||
my $tab = "clouds";
|
||||
my $ptab = xCAT::Table->new($tab);
|
||||
unless ($ptab) {
|
||||
xCAT::MsgUtils->message("E", "Unable to open $tab table");
|
||||
return undef;
|
||||
}
|
||||
my @rs = $ptab->getAllAttribs('name','repository', 'pubinterface');
|
||||
|
||||
foreach my $r ( @rs ) {
|
||||
my $cloud = $r->{'name'};
|
||||
my $repos = $r->{'repository'};
|
||||
my $pubinterface = $r->{'pubinterface'};
|
||||
$info{ $cloud }{repository} = $repos;
|
||||
$info{ $cloud }{pubinterface} = $pubinterface;
|
||||
}
|
||||
|
||||
$tab = "cloud";
|
||||
$ptab = xCAT::Table->new($tab);
|
||||
unless ($ptab) {
|
||||
xCAT::MsgUtils->message("E", "Unable to open $tab table");
|
||||
return undef;
|
||||
}
|
||||
@rs = $ptab->getAllAttribs('node','cloudname');
|
||||
|
||||
my $pre;
|
||||
my $curr;
|
||||
foreach my $r ( @rs ) {
|
||||
my $node = $r->{'node'};
|
||||
my $cloud = $r->{'cloudname'};
|
||||
$info{ $node }{cloud} = $cloud;
|
||||
}
|
||||
|
||||
return \%info;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
=head3 getcloudres
|
||||
|
||||
This function will be invoked by Postage.pm. And it's only for one chef-server.
|
||||
1. get the chef cookbook repository for the clouds on one chef-server.
|
||||
All the clouds's repositoryies on one chef-server should be the same one.
|
||||
2. get the cloud list for one chef-server
|
||||
3. get the cloud name for each node on the same chef-server
|
||||
|
||||
|
||||
Arguments:
|
||||
$cloudinfo_hash -- This is from the getcloudinfo function.
|
||||
$clients -- an array which stores different cloud nodes(chef-client)
|
||||
Returns:
|
||||
$cloudres -- a string including cloud information
|
||||
|
||||
Error:
|
||||
none
|
||||
Example:
|
||||
|
||||
Comments:
|
||||
none
|
||||
|
||||
=cut
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
sub getcloudres
|
||||
{
|
||||
my $cloudinfo_hash = shift;
|
||||
my $node = shift;
|
||||
my $clients = shift;
|
||||
my $cloudres;
|
||||
my $cloudlist;
|
||||
my $repos;
|
||||
if( @$clients == 0 ) {
|
||||
#This should not be a chef-server, and it's a chef-client
|
||||
if( defined($cloudinfo_hash) && defined($cloudinfo_hash->{$node}) ) {
|
||||
my $cloud=$cloudinfo_hash->{$node}->{cloud};
|
||||
my $pubinterface=$cloudinfo_hash->{$cloud}->{pubinterface};
|
||||
$cloudres="PUBINTERFACE='$pubinterface'\nexport PUBINTERFACE\n";
|
||||
}
|
||||
return $cloudres;
|
||||
}
|
||||
foreach my $client (@$clients) {
|
||||
my $cloud;
|
||||
if( defined($cloudinfo_hash) && defined($cloudinfo_hash->{$client}) ) {
|
||||
$cloud = $cloudinfo_hash->{$client}->{cloud};
|
||||
}
|
||||
#$cloudres .= "hput $client cloud $cloud\n";
|
||||
$cloudres .= "HASH".$client."cloud='$cloud'\nexport HASH".$client."cloud\n";
|
||||
if( defined($cloud) ) {
|
||||
if ( $cloudlist !~ $cloud ) {
|
||||
$cloudlist .="$cloud,";
|
||||
}
|
||||
}
|
||||
my $t = $cloudinfo_hash->{$cloud}->{repository};
|
||||
if( !defined($repos) && defined($t) ) {
|
||||
$repos = $t;
|
||||
}
|
||||
if( defined($repos) && ( $repos != $t && "$repos/" != $t && $repos != "$t/" ) ) {
|
||||
xCAT::MsgUtils->message("E", "Two cloud repositories: $repos and $t.\n There should be only one cloud repository one ont chef-server.");
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
chop $cloudlist;
|
||||
$cloudres = "REPOSITORY='$repos'\nexport REPOSITORY\nCLOUDLIST='$cloudlist'\nexport CLOUDLIST\n$cloudres";
|
||||
return $cloudres;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user