hosts.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package compute
  15. import (
  16. "context"
  17. "fmt"
  18. "strings"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/log"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/pkg/util/httputils"
  23. "yunion.io/x/pkg/util/printutils"
  24. "yunion.io/x/onecloud/cmd/climc/shell"
  25. "yunion.io/x/onecloud/pkg/mcclient"
  26. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  27. "yunion.io/x/onecloud/pkg/mcclient/options"
  28. "yunion.io/x/onecloud/pkg/mcclient/options/compute"
  29. "yunion.io/x/onecloud/pkg/util/fileutils2"
  30. "yunion.io/x/onecloud/pkg/util/ssh"
  31. )
  32. func init() {
  33. cmd := shell.NewResourceCmd(&modules.Hosts)
  34. cmd.List(&compute.HostListOptions{})
  35. cmd.GetMetadata(&options.BaseIdOptions{})
  36. cmd.GetProperty(&compute.HostStatusStatisticsOptions{})
  37. cmd.Update(&compute.HostUpdateOptions{})
  38. cmd.Perform("ping", &options.BaseIdOptions{})
  39. cmd.Perform("purge", &options.BaseIdOptions{})
  40. cmd.Perform("undo-convert", &options.BaseIdOptions{})
  41. cmd.Perform("maintenance", &options.BaseIdOptions{})
  42. cmd.Perform("unmaintenance", &options.BaseIdOptions{})
  43. cmd.Perform("start", &options.BaseIdOptions{})
  44. cmd.Perform("stop", &options.BaseIdOptions{})
  45. cmd.Perform("reset", &options.BaseIdOptions{})
  46. cmd.BatchDelete(&options.BaseIdsOptions{})
  47. cmd.Perform("remove-all-netifs", &options.BaseIdOptions{})
  48. cmd.Perform("probe-isolated-devices", &options.BaseIdOptions{})
  49. cmd.Perform("class-metadata", &options.ResourceMetadataOptions{})
  50. cmd.Perform("set-class-metadata", &options.ResourceMetadataOptions{})
  51. cmd.PerformClass("validate-ipmi", &compute.HostValidateIPMI{})
  52. cmd.BatchPerform("set-commit-bound", &compute.HostSetCommitBoundOptions{})
  53. cmd.BatchPerform("enable", &options.BaseIdsOptions{})
  54. cmd.BatchPerform("disable", &options.BaseIdsOptions{})
  55. cmd.BatchPerform("syncstatus", &options.BaseIdsOptions{})
  56. cmd.BatchPerform("sync-config", &options.BaseIdsOptions{})
  57. cmd.BatchPerform("prepare", &options.BaseIdsOptions{})
  58. cmd.BatchPerform("ipmi-probe", &options.BaseIdsOptions{})
  59. cmd.BatchPerform("reserve-cpus", &compute.HostReserveCpusOptions{})
  60. cmd.BatchPerform("unreserve-cpus", &options.BaseIdsOptions{})
  61. cmd.BatchPerform("auto-migrate-on-host-down", &compute.HostAutoMigrateOnHostDownOptions{})
  62. cmd.BatchPerform("restart-host-agent", &options.BaseIdsOptions{})
  63. cmd.BatchPerform("set-host-files", &compute.HostSetHostFilesOptions{})
  64. cmd.Get("ipmi", &options.BaseIdOptions{})
  65. cmd.Get("vnc", &options.BaseIdOptions{})
  66. cmd.Get("app-options", &options.BaseIdOptions{})
  67. cmd.Get("isolated-device-numa-stats", &compute.HostIsolatedDeviceNumaStatsOptions{})
  68. cmd.GetWithCustomShow("worker-stats", func(data jsonutils.JSONObject) {
  69. stats, _ := data.GetArray("workers")
  70. printList(&printutils.ListResult{Data: stats}, nil)
  71. }, &options.BaseIdOptions{})
  72. cmd.Get("tap-config", &options.BaseIdOptions{})
  73. cmd.GetWithCustomShow("nics", func(data jsonutils.JSONObject) {
  74. results := printutils.ListResult{}
  75. err := data.Unmarshal(&results)
  76. if err == nil {
  77. printutils.PrintJSONList(&results, []string{
  78. "mac",
  79. "vlan_id",
  80. "interface",
  81. "bridge",
  82. "ip_addr",
  83. "net",
  84. "wire",
  85. })
  86. } else {
  87. fmt.Println("error", err)
  88. }
  89. }, &options.BaseIdOptions{})
  90. cmd.GetWithCustomShow("host-files", func(data jsonutils.JSONObject) {
  91. printObject(data)
  92. }, &options.BaseIdOptions{})
  93. R(&compute.HostShowOptions{}, "host-show", "Show details of a host", func(s *mcclient.ClientSession, args *compute.HostShowOptions) error {
  94. params, err := args.Params()
  95. if err != nil {
  96. return err
  97. }
  98. result, err := modules.Hosts.Get(s, args.ID, params)
  99. if err != nil {
  100. return err
  101. }
  102. resultDict := result.(*jsonutils.JSONDict)
  103. if !args.ShowAll {
  104. if !args.ShowMetadata {
  105. print("ShowMetadata\n")
  106. resultDict.Remove("metadata")
  107. }
  108. if !args.ShowNicInfo {
  109. print("ShowMetadata\n")
  110. resultDict.Remove("nic_info")
  111. }
  112. if !args.ShowSysInfo {
  113. print("ShowSysInfo\n")
  114. resultDict.Remove("sys_info")
  115. }
  116. }
  117. printObject(resultDict)
  118. return nil
  119. })
  120. R(&options.BaseIdOptions{}, "host-logininfo", "Get SSH login information of a host", func(s *mcclient.ClientSession, args *options.BaseIdOptions) error {
  121. i, e := modules.Hosts.PerformAction(s, args.ID, "login-info", nil)
  122. if e != nil {
  123. return e
  124. }
  125. printObject(i)
  126. return nil
  127. })
  128. type HostPropertyOptions struct {
  129. }
  130. R(&HostPropertyOptions{}, "baremetal-register-script", "Get online baremetal register script", func(s *mcclient.ClientSession, args *HostPropertyOptions) error {
  131. result, err := modules.Hosts.Get(s, "bm-start-register-script", nil)
  132. if err != nil {
  133. return err
  134. }
  135. printObject(result)
  136. return nil
  137. })
  138. countFunc := func(s *mcclient.ClientSession, opts *compute.HostListOptions, action string) error {
  139. params, err := options.ListStructToParams(opts)
  140. if err != nil {
  141. return err
  142. }
  143. if opts.Empty {
  144. params.Add(jsonutils.JSONTrue, "is_empty")
  145. } else if opts.Occupied {
  146. params.Add(jsonutils.JSONFalse, "is_empty")
  147. }
  148. if opts.Enabled {
  149. params.Add(jsonutils.NewInt(1), "enabled")
  150. } else if opts.Disabled {
  151. params.Add(jsonutils.NewInt(0), "enabled")
  152. }
  153. if len(opts.Uuid) > 0 {
  154. params.Add(jsonutils.NewString(opts.Uuid), "uuid")
  155. }
  156. if len(opts.Sn) > 0 {
  157. params.Add(jsonutils.NewString(opts.Sn), "sn")
  158. }
  159. result, err := modules.Hosts.Get(s, action, params)
  160. if err != nil {
  161. return err
  162. }
  163. printObject(result)
  164. return nil
  165. }
  166. R(&compute.HostListOptions{}, "host-node-count", "Get host node count", func(s *mcclient.ClientSession, opts *compute.HostListOptions) error {
  167. return countFunc(s, opts, "node-count")
  168. })
  169. R(&compute.HostListOptions{}, "host-type-count", "Get host type count", func(s *mcclient.ClientSession, opts *compute.HostListOptions) error {
  170. return countFunc(s, opts, "host-type-count")
  171. })
  172. type HostSysInfoOpt struct {
  173. options.BaseIdOptions
  174. Key string `help:"The key for extract, e.g. 'cpu_info.processors'"`
  175. Format string `help:"Output format" choices:"yaml|json" default:"yaml"`
  176. }
  177. R(&HostSysInfoOpt{}, "host-sysinfo", "Get host system info", func(s *mcclient.ClientSession, args *HostSysInfoOpt) error {
  178. obj, err := modules.Hosts.Get(s, args.GetId(), nil)
  179. if err != nil {
  180. return err
  181. }
  182. keys := []string{"sys_info"}
  183. if args.Key != "" {
  184. keys = append(keys, strings.Split(args.Key, ".")...)
  185. }
  186. sysInfo, err := obj.Get(keys...)
  187. if err != nil {
  188. return errors.Wrap(err, "Get sys_info")
  189. }
  190. if args.Format == "yaml" {
  191. fmt.Print(sysInfo.YAMLString())
  192. } else {
  193. fmt.Print(sysInfo.PrettyString())
  194. }
  195. return nil
  196. })
  197. type HostConvertOptions struct {
  198. ID string `help:"Host ID or Name"`
  199. Name string `help:"New name of the converted host"`
  200. HOSTTYPE string `help:"Convert host type" choices:"hypervisor|esxi|kubelet|hyperv"`
  201. Image string `help:"Template image to install"`
  202. Raid string `help:"Raid to deploy" choices:"raid0|raid1|raid10|raid5|none"`
  203. RaidConfig []string `help:"Baremetal raid config"`
  204. Disk []string `help:"Disk descriptions" metavar:"DISK"`
  205. Net []string `help:"Network descriptions" metavar:"NETWORK"`
  206. }
  207. R(&HostConvertOptions{}, "host-convert-hypervisor", "Convert a baremetal into a hypervisor", func(s *mcclient.ClientSession, args *HostConvertOptions) error {
  208. params := jsonutils.NewDict()
  209. params.Add(jsonutils.NewString(args.HOSTTYPE), "host_type")
  210. if len(args.Name) > 0 {
  211. params.Add(jsonutils.NewString(args.Name), "name")
  212. }
  213. if len(args.RaidConfig) > 0 && len(args.Raid) > 0 {
  214. return fmt.Errorf("Cannot specifiy raidconfig and raid simultaneously")
  215. } else if len(args.RaidConfig) > 0 {
  216. for i := 0; i < len(args.RaidConfig); i += 1 {
  217. params.Add(jsonutils.NewString(args.RaidConfig[i]), fmt.Sprintf("baremetal_disk_config.%d", i))
  218. }
  219. } else if len(args.Raid) > 0 {
  220. params.Add(jsonutils.NewString(args.Raid), "raid")
  221. }
  222. if len(args.Disk) > 0 && len(args.Image) > 0 {
  223. return fmt.Errorf("Cannot specify disk and image simultaneously")
  224. } else if len(args.Disk) > 0 {
  225. for i := 0; i < len(args.Disk); i += 1 {
  226. params.Add(jsonutils.NewString(args.Disk[i]), fmt.Sprintf("disk.%d", i))
  227. }
  228. } else if len(args.Image) > 0 {
  229. params.Add(jsonutils.NewString(args.Image), "image")
  230. }
  231. if len(args.Net) > 0 {
  232. for i := 0; i < len(args.Net); i += 1 {
  233. params.Add(jsonutils.NewString(args.Net[i]), fmt.Sprintf("net.%d", i))
  234. }
  235. }
  236. result, err := modules.Hosts.PerformAction(s, args.ID, "convert-hypervisor", params)
  237. if err != nil {
  238. return err
  239. }
  240. printObject(result)
  241. return nil
  242. })
  243. type HostAddNetIfOptions struct {
  244. ID string `help:"ID or Name of host"`
  245. WIRE string `help:"ID or Name of wire to attach"`
  246. MAC string `help:"Mac address of NIC"`
  247. INDEX int64 `help:"nic index"`
  248. Type string `help:"Nic type" choices:"admin|ipmi"`
  249. IpAddr string `help:"IP address"`
  250. Ip6Addr string `help:"IPv6 address"`
  251. Bridge string `help:"Bridge of hostwire"`
  252. Interface string `help:"Interface name, eg:eth0, en0"`
  253. VlanId int `help:"Vlan ID"`
  254. }
  255. R(&HostAddNetIfOptions{}, "host-add-netif", "Host add a NIC", func(s *mcclient.ClientSession, args *HostAddNetIfOptions) error {
  256. params := jsonutils.NewDict()
  257. params.Add(jsonutils.NewString(args.WIRE), "wire")
  258. params.Add(jsonutils.NewString(args.MAC), "mac")
  259. params.Add(jsonutils.JSONTrue, "link_up")
  260. params.Add(jsonutils.NewInt(args.INDEX), "index")
  261. if len(args.Type) > 0 {
  262. params.Add(jsonutils.NewString(args.Type), "nic_type")
  263. }
  264. if len(args.IpAddr) > 0 {
  265. params.Add(jsonutils.NewString(args.IpAddr), "ip_addr")
  266. }
  267. if len(args.Ip6Addr) > 0 {
  268. params.Add(jsonutils.NewString(args.Ip6Addr), "ip6_addr")
  269. }
  270. if len(args.Bridge) > 0 {
  271. params.Add(jsonutils.NewString(args.Bridge), "bridge")
  272. }
  273. if len(args.Interface) > 0 {
  274. params.Add(jsonutils.NewString(args.Interface), "interface")
  275. }
  276. addVlanIdToParams(params, args.VlanId)
  277. result, err := modules.Hosts.PerformAction(s, args.ID, "add-netif", params)
  278. if err != nil {
  279. return err
  280. }
  281. printObject(result)
  282. return nil
  283. })
  284. type HostRemoveNetIfOptions struct {
  285. ID string `help:"ID or Name of host"`
  286. MAC string `help:"MAC of NIC to remove"`
  287. VlanId int `help:"Vlan Id"`
  288. }
  289. R(&HostRemoveNetIfOptions{}, "host-remove-netif", "Remove NIC from host", func(s *mcclient.ClientSession, args *HostRemoveNetIfOptions) error {
  290. params := jsonutils.NewDict()
  291. params.Add(jsonutils.NewString(args.MAC), "mac")
  292. addVlanIdToParams(params, args.VlanId)
  293. result, err := modules.Hosts.PerformAction(s, args.ID, "remove-netif", params)
  294. if err != nil {
  295. return err
  296. }
  297. printObject(result)
  298. return nil
  299. })
  300. type HostEnableNetIfOptions struct {
  301. ID string `help:"ID or Name of host"`
  302. MAC string `help:"MAC of NIC to enable"`
  303. Ip string `help:"IPv4 address"`
  304. Ip6 string `help:"IPv6 address"`
  305. Network string `help:"network to connect"`
  306. Reserved bool `help:"fetch IP from reserved pool"`
  307. VlanId int `help:"Vlan ID"`
  308. }
  309. R(&HostEnableNetIfOptions{}, "host-enable-netif", "Enable a network interface for a host", func(s *mcclient.ClientSession, args *HostEnableNetIfOptions) error {
  310. params := jsonutils.NewDict()
  311. params.Add(jsonutils.NewString(args.MAC), "mac")
  312. if len(args.Ip) > 0 {
  313. params.Add(jsonutils.NewString(args.Ip), "ip_addr")
  314. }
  315. if len(args.Ip6) > 0 {
  316. params.Add(jsonutils.NewString(args.Ip6), "ip6_addr")
  317. }
  318. if len(args.Ip) > 0 || len(args.Ip6) > 0 {
  319. if args.Reserved {
  320. params.Add(jsonutils.JSONTrue, "reserve")
  321. }
  322. }
  323. if len(args.Network) > 0 {
  324. params.Add(jsonutils.NewString(args.Network), "network")
  325. }
  326. addVlanIdToParams(params, args.VlanId)
  327. result, err := modules.Hosts.PerformAction(s, args.ID, "enable-netif", params)
  328. if err != nil {
  329. return err
  330. }
  331. printObject(result)
  332. return nil
  333. })
  334. type HostDisableNetIfOptions struct {
  335. ID string `help:"ID or Name of host"`
  336. MAC string `help:"MAC of NIC to disable"`
  337. Reserve bool `help:"Reserve the IP address"`
  338. VlanId int `help:"Vlan Id"`
  339. }
  340. R(&HostDisableNetIfOptions{}, "host-disable-netif", "Disable a network interface", func(s *mcclient.ClientSession, args *HostDisableNetIfOptions) error {
  341. params := jsonutils.NewDict()
  342. params.Add(jsonutils.NewString(args.MAC), "mac")
  343. if args.Reserve {
  344. params.Add(jsonutils.JSONTrue, "reserve")
  345. }
  346. addVlanIdToParams(params, args.VlanId)
  347. result, err := modules.Hosts.PerformAction(s, args.ID, "disable-netif", params)
  348. if err != nil {
  349. return err
  350. }
  351. printObject(result)
  352. return nil
  353. })
  354. type HostCacheImageActionOptions struct {
  355. ID string `help:"ID or name of host"`
  356. IMAGE string `help:"ID or name of image"`
  357. Force bool `help:"Force refresh cache, even if the image exists in cache"`
  358. Format string `help:"image format" choices:"iso|vmdk|qcow2|vhd|tgz"`
  359. }
  360. R(&HostCacheImageActionOptions{}, "host-cache-image", "Ask a host to cache a image", func(s *mcclient.ClientSession, args *HostCacheImageActionOptions) error {
  361. params := jsonutils.NewDict()
  362. params.Add(jsonutils.NewString(args.IMAGE), "image")
  363. if args.Force {
  364. params.Add(jsonutils.JSONTrue, "is_force")
  365. }
  366. host, err := modules.Hosts.PerformAction(s, args.ID, "cache-image", params)
  367. if err != nil {
  368. return err
  369. }
  370. printObject(host)
  371. return nil
  372. })
  373. type HostUncacheImageActionOptions struct {
  374. ID string `help:"ID or name of host"`
  375. IMAGE string `help:"ID or name of image"`
  376. }
  377. R(&HostUncacheImageActionOptions{}, "host-uncache-image", "Ask a host to remove image from a cache", func(s *mcclient.ClientSession, args *HostUncacheImageActionOptions) error {
  378. params := jsonutils.NewDict()
  379. params.Add(jsonutils.NewString(args.IMAGE), "image")
  380. host, err := modules.Hosts.PerformAction(s, args.ID, "uncache-image", params)
  381. if err != nil {
  382. return err
  383. }
  384. printObject(host)
  385. return nil
  386. })
  387. type HostCreateOptions struct {
  388. NAME string `help:"Name of baremetal"`
  389. MAC string `help:"Default MAC address of baremetal"`
  390. Rack string `help:"Rack number of baremetal"`
  391. Slots string `help:"Slots number of baremetal"`
  392. IpmiUser string `help:"IPMI user name"`
  393. IpmiPasswd string `help:"IPMI user password"`
  394. IpmiAddr string `help:"IPMI IP address"`
  395. AccessIp string `help:"Access IP address"`
  396. AccessNet string `help:"Access network"`
  397. AccessWire string `help:"Access wire"`
  398. NoProbe bool `help:"just save the record, do not probe"`
  399. NoBMC bool `help:"No BMC hardware"`
  400. NoPrepare bool `help:"just probe, do not reboot baremetal to prepare"`
  401. DisablePxeBoot bool `help:"set enable_pxe_boot to false, which is true by default"`
  402. Uuid string `help:"host uuid"`
  403. }
  404. R(&HostCreateOptions{}, "host-create", "Create a baremetal host", func(s *mcclient.ClientSession, args *HostCreateOptions) error {
  405. params := jsonutils.NewDict()
  406. params.Add(jsonutils.NewString(args.NAME), "name")
  407. params.Add(jsonutils.NewString(args.MAC), "access_mac")
  408. params.Add(jsonutils.NewString("baremetal"), "host_type")
  409. if len(args.Rack) > 0 {
  410. params.Add(jsonutils.NewString(args.Rack), "rack")
  411. }
  412. if len(args.Slots) > 0 {
  413. params.Add(jsonutils.NewString(args.Slots), "slots")
  414. }
  415. if len(args.IpmiUser) > 0 {
  416. params.Add(jsonutils.NewString(args.IpmiUser), "ipmi_username")
  417. }
  418. if len(args.IpmiPasswd) > 0 {
  419. params.Add(jsonutils.NewString(args.IpmiPasswd), "ipmi_password")
  420. }
  421. if len(args.IpmiAddr) > 0 {
  422. params.Add(jsonutils.NewString(args.IpmiAddr), "ipmi_ip_addr")
  423. }
  424. if len(args.AccessIp) > 0 {
  425. params.Add(jsonutils.NewString(args.AccessIp), "access_ip")
  426. }
  427. if len(args.AccessNet) > 0 {
  428. params.Add(jsonutils.NewString(args.AccessNet), "access_net")
  429. }
  430. if len(args.AccessWire) > 0 {
  431. params.Add(jsonutils.NewString(args.AccessWire), "access_wire")
  432. }
  433. if args.NoProbe {
  434. params.Add(jsonutils.JSONTrue, "no_probe")
  435. }
  436. if args.NoPrepare {
  437. params.Add(jsonutils.JSONTrue, "no_prepare")
  438. }
  439. if args.NoBMC {
  440. params.Add(jsonutils.JSONTrue, "no_bmc")
  441. }
  442. if args.DisablePxeBoot {
  443. params.Add(jsonutils.JSONFalse, "enable_pxe_boot")
  444. }
  445. if len(args.Uuid) > 0 {
  446. params.Add(jsonutils.NewString(args.Uuid), "uuid")
  447. }
  448. result, err := modules.Hosts.Create(s, params)
  449. if err != nil {
  450. return err
  451. }
  452. printObject(result)
  453. return nil
  454. })
  455. type HostUndoPrepaidRecycleOptions struct {
  456. ID string `help:"ID or name of host to undo recycle"`
  457. }
  458. R(&HostUndoPrepaidRecycleOptions{}, "host-undo-recycle", "Pull a prepaid server from recycle pool, so that it will not be shared any more", func(s *mcclient.ClientSession, args *HostUndoPrepaidRecycleOptions) error {
  459. params := jsonutils.NewDict()
  460. result, err := modules.Hosts.PerformAction(s, args.ID, "undo-prepaid-recycle", params)
  461. if err != nil {
  462. return err
  463. }
  464. printObject(result)
  465. return nil
  466. })
  467. type PrepaidRecycleHostRenewOptions struct {
  468. ID string `help:"ID or name of server to renew"`
  469. DURATION string `help:"Duration of renew, ADMIN only command"`
  470. }
  471. R(&PrepaidRecycleHostRenewOptions{}, "host-renew-prepaid-recycle", "Renew a prepaid recycle host", func(s *mcclient.ClientSession, args *PrepaidRecycleHostRenewOptions) error {
  472. params := jsonutils.NewDict()
  473. params.Add(jsonutils.NewString(args.DURATION), "duration")
  474. result, err := modules.Hosts.PerformAction(s, args.ID, "renew-prepaid-recycle", params)
  475. if err != nil {
  476. return err
  477. }
  478. printObject(result)
  479. return nil
  480. })
  481. type HostSpecOptions struct {
  482. ID string `help:"ID or name of host"`
  483. }
  484. R(&HostSpecOptions{}, "host-spec", "Get host spec info", func(s *mcclient.ClientSession, args *HostSpecOptions) error {
  485. spec, err := modules.Hosts.GetSpecific(s, args.ID, "spec", nil)
  486. if err != nil {
  487. return err
  488. }
  489. printObject(spec)
  490. return nil
  491. })
  492. type HostJnlpOptions struct {
  493. ID string `help:"ID or name of host"`
  494. Save string `help:"save xml into this file"`
  495. }
  496. R(&HostJnlpOptions{}, "host-jnlp", "Get host jnlp file contentn", func(s *mcclient.ClientSession, args *HostJnlpOptions) error {
  497. spec, err := modules.Hosts.GetSpecific(s, args.ID, "jnlp", nil)
  498. if err != nil {
  499. return err
  500. }
  501. jnlp, err := spec.GetString("jnlp")
  502. if err != nil {
  503. return err
  504. }
  505. if len(args.Save) > 0 {
  506. return fileutils2.FilePutContents(args.Save, jnlp, false)
  507. } else {
  508. fmt.Println(jnlp)
  509. }
  510. return nil
  511. })
  512. type HostInsertIsoOptions struct {
  513. ID string `help:"ID or name of host" json:"-"`
  514. Image string `help:"ID or name or ISO image name" json:"image"`
  515. Boot bool `help:"Boot from ISO on next reset" json:"boot"`
  516. }
  517. R(&HostInsertIsoOptions{}, "host-insert-iso", "Insert ISO into virtual cd-rom of host", func(s *mcclient.ClientSession, args *HostInsertIsoOptions) error {
  518. params := jsonutils.Marshal(args)
  519. result, err := modules.Hosts.PerformAction(s, args.ID, "insert-iso", params)
  520. if err != nil {
  521. return err
  522. }
  523. printObject(result)
  524. return nil
  525. })
  526. type HostEjectIsoOptions struct {
  527. ID string `help:"ID or name of host" json:"-"`
  528. }
  529. R(&HostEjectIsoOptions{}, "host-eject-iso", "Eject ISO from virtual cd-rom of host", func(s *mcclient.ClientSession, args *HostEjectIsoOptions) error {
  530. params := jsonutils.Marshal(args)
  531. result, err := modules.Hosts.PerformAction(s, args.ID, "eject-iso", params)
  532. if err != nil {
  533. return err
  534. }
  535. printObject(result)
  536. return nil
  537. })
  538. type HostSSHLoginOptions struct {
  539. ID string `help:"ID or name of host"`
  540. Port int `help:"SSH service port" default:"22"`
  541. }
  542. R(&HostSSHLoginOptions{}, "host-ssh", "SSH login of a host", func(s *mcclient.ClientSession, args *HostSSHLoginOptions) error {
  543. i, e := modules.Hosts.PerformAction(s, args.ID, "login-info", nil)
  544. privateKey := ""
  545. if e != nil {
  546. if httputils.ErrorCode(e) == 404 || strings.Contains(e.Error(), "ciphertext too short") {
  547. var err error
  548. privateKey, err = modules.Sshkeypairs.FetchPrivateKeyBySession(context.Background(), s)
  549. if err != nil {
  550. return errors.Wrap(err, "fetch private key")
  551. }
  552. params := jsonutils.NewDict()
  553. params.Add(jsonutils.NewString(string(args.ID)), "ID")
  554. ret, err := modules.Hosts.Get(s, args.ID, params)
  555. if err != nil {
  556. return errors.Wrap(err, "get host by ID")
  557. }
  558. ip, err := ret.GetString("access_ip")
  559. if err != nil {
  560. return errors.Wrap(err, "get the ip of the host")
  561. }
  562. jsonItem := jsonutils.NewDict()
  563. jsonItem.Add(jsonutils.NewString(ip), "ip")
  564. jsonItem.Add(jsonutils.NewString("root"), "username")
  565. jsonItem.Add(jsonutils.NewString(""), "password")
  566. jsonItem.Add(jsonutils.NewInt(22), "port")
  567. i = jsonItem
  568. } else {
  569. return e
  570. }
  571. }
  572. host, err := i.GetString("ip")
  573. if err != nil {
  574. return err
  575. }
  576. user, err := i.GetString("username")
  577. if err != nil {
  578. return err
  579. }
  580. passwd, err := i.GetString("password")
  581. if err != nil {
  582. return err
  583. }
  584. port := 22
  585. if args.Port != 22 {
  586. port = args.Port
  587. }
  588. sshCli, err := ssh.NewClient(host, port, user, passwd, privateKey)
  589. if err != nil {
  590. return err
  591. }
  592. log.Infof("ssh %s:%d", host, port)
  593. if err := sshCli.RunTerminal(); err != nil {
  594. return err
  595. }
  596. return nil
  597. })
  598. type HostChangeOwnerOptions struct {
  599. ID string `help:"ID or name of host" json:"-"`
  600. ProjectDomain string `json:"project_domain" help:"target domain"`
  601. }
  602. R(&HostChangeOwnerOptions{}, "host-change-owner", "Change owner domain of host", func(s *mcclient.ClientSession, args *HostChangeOwnerOptions) error {
  603. if len(args.ProjectDomain) == 0 {
  604. return fmt.Errorf("empty project_domain")
  605. }
  606. params := jsonutils.Marshal(args)
  607. ret, err := modules.Hosts.PerformAction(s, args.ID, "change-owner", params)
  608. if err != nil {
  609. return err
  610. }
  611. printObject(ret)
  612. return nil
  613. })
  614. type HostPublicOptions struct {
  615. ID string `help:"ID or name of host" json:"-"`
  616. Scope string `help:"sharing scope" choices:"system|domain"`
  617. SharedDomains []string `help:"share to domains"`
  618. }
  619. R(&HostPublicOptions{}, "host-public", "Make a host public", func(s *mcclient.ClientSession, args *HostPublicOptions) error {
  620. params := jsonutils.Marshal(args)
  621. result, err := modules.Hosts.PerformAction(s, args.ID, "public", params)
  622. if err != nil {
  623. return err
  624. }
  625. printObject(result)
  626. return nil
  627. })
  628. type HostPrivateOptions struct {
  629. ID string `help:"ID or name of host" json:"-"`
  630. }
  631. R(&HostPrivateOptions{}, "host-private", "Make a host private", func(s *mcclient.ClientSession, args *HostPrivateOptions) error {
  632. params := jsonutils.Marshal(args)
  633. result, err := modules.Hosts.PerformAction(s, args.ID, "private", params)
  634. if err != nil {
  635. return err
  636. }
  637. printObject(result)
  638. return nil
  639. })
  640. type HostChangeOwnerCandidateDomainsOptions struct {
  641. ID string `help:"ID or name of host"`
  642. }
  643. R(&HostChangeOwnerCandidateDomainsOptions{}, "host-change-owner-candidate-domains", "Get change owner candidate domain list", func(s *mcclient.ClientSession, args *HostChangeOwnerCandidateDomainsOptions) error {
  644. result, err := modules.Hosts.GetSpecific(s, args.ID, "change-owner-candidate-domains", nil)
  645. if err != nil {
  646. return err
  647. }
  648. printObject(result)
  649. return nil
  650. })
  651. type HostSetReservedResourceForIsolatedDevice struct {
  652. ID []string `help:"ID or name of host" json:"-"`
  653. ReservedCpu *int `help:"reserved cpu count"`
  654. ReservedMem *int `help:"reserved mem count"`
  655. ReservedStorage *int `help:"reserved storage count"`
  656. }
  657. R(&HostSetReservedResourceForIsolatedDevice{},
  658. "host-set-reserved-resource-for-isolated-device",
  659. "Set reserved resource for isolated device",
  660. func(s *mcclient.ClientSession, args *HostSetReservedResourceForIsolatedDevice) error {
  661. res := modules.Hosts.BatchPerformAction(s, args.ID, "set-reserved-resource-for-isolated-device", jsonutils.Marshal(args))
  662. printBatchResults(res, modules.Hosts.GetColumns(s))
  663. return nil
  664. },
  665. )
  666. }
  667. func addVlanIdToParams(params *jsonutils.JSONDict, vlanId int) {
  668. if vlanId > 1 {
  669. params.Add(jsonutils.NewInt(int64(vlanId)), "vlan_id")
  670. }
  671. }