servers.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  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. "encoding/json"
  18. "fmt"
  19. "io/ioutil"
  20. "net"
  21. "os"
  22. "path/filepath"
  23. "gopkg.in/yaml.v2"
  24. "yunion.io/x/jsonutils"
  25. "yunion.io/x/log"
  26. "yunion.io/x/pkg/util/printutils"
  27. "yunion.io/x/onecloud/cmd/climc/shell"
  28. billing_api "yunion.io/x/onecloud/pkg/apis/billing"
  29. "yunion.io/x/onecloud/pkg/apis/compute"
  30. "yunion.io/x/onecloud/pkg/mcclient"
  31. "yunion.io/x/onecloud/pkg/mcclient/modulebase"
  32. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  33. "yunion.io/x/onecloud/pkg/mcclient/modules/image"
  34. "yunion.io/x/onecloud/pkg/mcclient/modules/scheduler"
  35. baseoptions "yunion.io/x/onecloud/pkg/mcclient/options"
  36. options "yunion.io/x/onecloud/pkg/mcclient/options/compute"
  37. "yunion.io/x/onecloud/pkg/util/fileutils2"
  38. "yunion.io/x/onecloud/pkg/util/ssh"
  39. )
  40. func init() {
  41. cmd := shell.NewResourceCmd(&modules.Servers)
  42. cmd.List(new(options.ServerListOptions))
  43. cmd.Show(new(options.ServerShowOptions))
  44. cmd.BatchDeleteWithParam(new(options.ServerDeleteOptions))
  45. cmd.BatchPerform("cancel-delete", new(options.ServerCancelDeleteOptions))
  46. cmd.BatchPut(new(options.ServerUpdateOptions))
  47. cmd.GetMetadata(new(options.ServerIdOptions))
  48. cmd.Perform("clone", new(options.ServerCloneOptions))
  49. cmd.Perform("change-billing-type", new(options.ServerChangeBillingTypeOptions))
  50. cmd.BatchPerform("start", new(options.ServerStartOptions))
  51. cmd.BatchPerform("syncstatus", new(options.ServerIdsOptions))
  52. cmd.BatchPerform("sync", new(options.ServerIdsOptions))
  53. cmd.Perform("switch-to-backup", new(options.ServerSwitchToBackupOptions))
  54. cmd.BatchPerform("reconcile-backup", new(options.ServerIdsOptions))
  55. cmd.Perform("create-backup", new(options.ServerCreateBackupOptions))
  56. cmd.BatchPerform("start-backup", new(options.ServerIdsOptions))
  57. cmd.Perform("delete-backup", new(options.ServerDeleteBackupOptions))
  58. cmd.BatchPerform("stop", new(options.ServerStopOptions))
  59. cmd.BatchPerform("suspend", new(options.ServerIdsOptions))
  60. cmd.BatchPerform("resume", new(options.ServerIdsOptions))
  61. cmd.BatchPerform("reset", new(options.ServerResetOptions))
  62. cmd.BatchPerform("restart", new(options.ServerRestartOptions))
  63. cmd.BatchPerform("purge", new(options.ServerIdsOptions))
  64. cmd.BatchPerform("convert-to-kvm", new(options.ServerConvertToKvmOptions))
  65. cmd.PrintObjectYAML().Perform("migrate-forecast", new(options.ServerMigrateForecastOptions))
  66. cmd.Perform("migrate", new(options.ServerMigrateOptions))
  67. cmd.Perform("live-migrate", new(options.ServerLiveMigrateOptions))
  68. cmd.BatchPerform("cancel-live-migrate", new(options.ServerIdsOptions))
  69. cmd.Perform("set-live-migrate-params", new(options.ServerSetLiveMigrateParamsOptions))
  70. cmd.Perform("modify-src-check", new(options.ServerModifySrcCheckOptions))
  71. cmd.Perform("set-secgroup", new(options.ServerSecGroupsOptions))
  72. cmd.Perform("add-secgroup", new(options.ServerSecGroupsOptions))
  73. cmd.Perform("assign-secgroup", new(options.ServerSecGroupOptions))
  74. cmd.Perform("assign-admin-secgroup", new(options.ServerSecGroupOptions))
  75. cmd.Perform("revoke-secgroup", new(options.ServerSecGroupOptions))
  76. cmd.Perform("revoke-admin-secgroup", new(options.ServerIdOptions))
  77. cmd.Perform("save-image", new(options.ServerSaveImageOptions))
  78. cmd.Perform("save-guest-image", new(options.ServerSaveGuestImageOptions))
  79. cmd.Perform("change-owner", new(options.ServerChangeOwnerOptions))
  80. cmd.Perform("rebuild-root", new(options.ServerRebuildRootOptions))
  81. cmd.Perform("change-config", new(options.ServerChangeConfigOptions))
  82. cmd.Perform("ejectiso", new(options.ServerIdOptions))
  83. cmd.Perform("sendkeys", new(options.ServerSendKeyOptions))
  84. cmd.Perform("deploy", new(options.ServerDeployOptions))
  85. cmd.Perform("associate-eip", new(options.ServerAssociateEipOptions))
  86. cmd.Perform("dissociate-eip", new(options.ServerDissociateEipOptions))
  87. cmd.Perform("renew", new(options.ServerRenewOptions))
  88. cmd.Perform("io-throttle", new(options.ServerIoThrottle))
  89. cmd.Perform("publicip-to-eip", new(options.ServerPublicipToEip))
  90. cmd.Perform("set-auto-renew", new(options.ServerSetAutoRenew))
  91. cmd.Perform("save-template", new(options.ServerSaveImageOptions))
  92. cmd.Perform("remote-update", new(options.ServerRemoteUpdateOptions))
  93. cmd.Perform("create-eip", &options.ServerCreateEipOptions{})
  94. cmd.Perform("make-sshable", &options.ServerMakeSshableOptions{})
  95. cmd.Perform("migrate-network", &options.ServerMigrateNetworkOptions{})
  96. cmd.Perform("set-sshport", &options.ServerSetSshportOptions{})
  97. cmd.Perform("have-agent", &options.ServerHaveAgentOptions{})
  98. cmd.Perform("change-disk-storage", &options.ServerChangeDiskStorageOptions{})
  99. cmd.Perform("change-storage", &options.ServerChangeStorageOptions{})
  100. cmd.PerformClass("batch-user-metadata", &options.ServerBatchMetadataOptions{})
  101. cmd.PerformClass("batch-set-user-metadata", &options.ServerBatchMetadataOptions{})
  102. cmd.Perform("user-metadata", &baseoptions.ResourceMetadataOptions{})
  103. cmd.Perform("set-user-metadata", &baseoptions.ResourceMetadataOptions{})
  104. cmd.Perform("probe-isolated-devices", &options.ServerIdOptions{})
  105. cmd.Perform("cpuset", &options.ServerCPUSetOptions{})
  106. cmd.Perform("cpuset-remove", &options.ServerIdOptions{})
  107. cmd.Perform("calculate-record-checksum", &options.ServerIdOptions{})
  108. cmd.Perform("set-class-metadata", &baseoptions.ResourceMetadataOptions{})
  109. cmd.Perform("monitor", &options.ServerMonitorOptions{})
  110. cmd.BatchPerform("enable-memclean", new(options.ServerIdsOptions))
  111. cmd.Perform("qga-set-password", &options.ServerQgaSetPassword{})
  112. cmd.Perform("qga-command", &options.ServerQgaCommand{})
  113. cmd.Perform("qga-ping", &options.ServerQgaPing{})
  114. cmd.Perform("qga-guest-info-task", &options.ServerQgaGuestInfoTask{})
  115. cmd.Perform("qga-get-network", &options.ServerQgaGetNetwork{})
  116. cmd.Perform("set-password", &options.ServerSetPasswordOptions{})
  117. cmd.Perform("set-boot-index", &options.ServerSetBootIndexOptions{})
  118. cmd.Perform("reset-nic-traffic-limit", &options.ServerNicTrafficLimitOptions{})
  119. cmd.Perform("set-nic-traffic-limit", &options.ServerNicTrafficLimitOptions{})
  120. cmd.Perform("add-sub-ips", &options.ServerAddSubIpsOptions{})
  121. cmd.Perform("update-sub-ips", &options.ServerUpdateSubIpsOptions{})
  122. cmd.BatchPerform("restore-virtual-isolated-devices", &options.ServerIdsOptions{})
  123. cmd.BatchPerform("set-os-info", &options.ServerSetOSInfoOptions{})
  124. cmd.BatchPerform("start-rescue", &options.ServerStartOptions{})
  125. cmd.BatchPerform("stop-rescue", &options.ServerStartOptions{})
  126. cmd.BatchPerform("sync-os-info", &options.ServerIdsOptions{})
  127. cmd.BatchPerform("set-root-disk-matcher", &options.ServerSetRootDiskMatcher{})
  128. cmd.Perform("disable-auto-merge-snapshot", &options.ServerDisableAutoMergeSnapshot{})
  129. cmd.BatchPerform("set-tpm", &options.ServerSetTpmOptions{})
  130. cmd.Perform("set-kickstart", &options.ServerKickstartConfigOptions{})
  131. cmd.Perform("delete-kickstart", &options.ServerIdOptions{})
  132. cmd.Perform("kickstart-complete", &options.ServerKickstartCompleteOptions{})
  133. cmd.Get("kickstart", new(options.ServerIdOptions))
  134. cmd.Get("vnc", new(options.ServerVncOptions))
  135. cmd.Get("modification-types", new(options.ServerIdOptions))
  136. cmd.Get("desc", new(options.ServerIdOptions))
  137. cmd.Get("status", new(options.ServerIdOptions))
  138. cmd.Get("iso", new(options.ServerIdOptions))
  139. cmd.Get("create-params", new(options.ServerIdOptions))
  140. cmd.Get("sshable", new(options.ServerIdOptions))
  141. cmd.Get("make-sshable-cmd", new(options.ServerIdOptions))
  142. cmd.Get("change-owner-candidate-domains", new(options.ServerChangeOwnerCandidateDomainsOptions))
  143. cmd.Get("change-owner-candidate-domains", new(options.ServerChangeOwnerCandidateDomainsOptions))
  144. cmd.Get("cpuset-cores", new(options.ServerIdOptions))
  145. cmd.Get("sshport", new(options.ServerIdOptions))
  146. cmd.Get("qemu-info", new(options.ServerIdOptions))
  147. cmd.Get("hardware-info", new(options.ServerIdOptions))
  148. cmd.Get("screen-dump-show", new(options.ServerScreenDumpOptions))
  149. cmd.Get("numa-info", new(options.ServerIdOptions))
  150. cmd.BatchPerform("screen-dump", new(options.ServerIdsOptions))
  151. cmd.Perform("set-network-num-queues", new(options.ServerSetNetworkNumQueues))
  152. cmd.Perform("set-network-secgroup", new(options.ServerNetworkSecGroupsOptions))
  153. cmd.Perform("add-network-secgroup", new(options.ServerNetworkSecGroupsOptions))
  154. cmd.Perform("revoke-network-secgroup", new(options.ServerNetworkSecGroupsOptions))
  155. cmd.GetProperty(&options.ServerStatusStatisticsOptions{})
  156. cmd.GetProperty(&options.ServerProjectStatisticsOptions{})
  157. cmd.GetProperty(&options.ServerDomainStatisticsOptions{})
  158. cmd.GetProperty(&options.ServerGetPropertyTagValuePairOptions{})
  159. cmd.GetProperty(&options.ServerGetPropertyTagValueTreeOptions{})
  160. cmd.GetProperty(&options.ServerGetPropertyProjectTagValuePairOptions{})
  161. cmd.GetProperty(&options.ServerGetPropertyProjectTagValueTreeOptions{})
  162. cmd.GetProperty(&options.ServerGetPropertyDomainTagValuePairOptions{})
  163. cmd.GetProperty(&options.ServerGetPropertyDomainTagValueTreeOptions{})
  164. type ServerTaskShowOptions struct {
  165. ID string `help:"ID or name of server" json:"-"`
  166. Since string `help:"show tasks since this time point"`
  167. Open bool `help:"show tasks that are not completed" json:"-"`
  168. Complete bool `help:"show tasks that has been completed" json:"-"`
  169. }
  170. R(&ServerTaskShowOptions{}, "server-tasks", "Show tasks of a server", func(s *mcclient.ClientSession, opts *ServerTaskShowOptions) error {
  171. params, err := baseoptions.StructToParams(opts)
  172. if err != nil {
  173. return err
  174. }
  175. if opts.Open {
  176. params.Add(jsonutils.JSONTrue, "is_open")
  177. } else if opts.Complete {
  178. params.Add(jsonutils.JSONFalse, "is_open")
  179. }
  180. result, err := modules.Servers.GetSpecific(s, opts.ID, "tasks", params)
  181. if err != nil {
  182. return err
  183. }
  184. tasks, err := result.GetArray("tasks")
  185. if err != nil {
  186. return err
  187. }
  188. listResult := printutils.ListResult{}
  189. listResult.Data = tasks
  190. printList(&listResult, nil)
  191. return nil
  192. })
  193. R(&baseoptions.ResourceMetadataOptions{}, "server-set-metadata", "Set raw metadata of a server", func(s *mcclient.ClientSession, opts *baseoptions.ResourceMetadataOptions) error {
  194. params, err := opts.Params()
  195. if err != nil {
  196. return err
  197. }
  198. result, err := modules.Servers.PerformAction(s, opts.ID, "metadata", params)
  199. if err != nil {
  200. return err
  201. }
  202. printObject(result)
  203. return nil
  204. })
  205. R(&options.ServerCreateFromInstanceSnapshot{}, "server-create-from-instance-snapshot", "server create from instance snapshot",
  206. func(s *mcclient.ClientSession, opts *options.ServerCreateFromInstanceSnapshot) error {
  207. params := &compute.ServerCreateInput{}
  208. params.InstanceSnapshotId = opts.InstaceSnapshotId
  209. params.Name = opts.NAME
  210. params.AutoStart = opts.AutoStart
  211. params.Eip = opts.Eip
  212. params.EipChargeType = billing_api.ParseNetChargeType(opts.EipChargeType)
  213. params.EipBw = opts.EipBw
  214. server, err := modules.Servers.Create(s, params.JSON(params))
  215. if err != nil {
  216. return err
  217. }
  218. printObject(server)
  219. return nil
  220. },
  221. )
  222. R(&options.ServerCreateOptions{}, "server-create", "Create a server", func(s *mcclient.ClientSession, opts *options.ServerCreateOptions) error {
  223. params, err := opts.Params()
  224. if err != nil {
  225. return err
  226. }
  227. count := params.Count
  228. if baseoptions.BoolV(opts.DryRun) {
  229. listFields := []string{"id", "name", "capacity", "count", "score", "capacity_details", "score_details"}
  230. input, err := opts.ToScheduleInput()
  231. if err != nil {
  232. return err
  233. }
  234. result, err := scheduler.SchedManager.Test(s, input)
  235. if err != nil {
  236. return err
  237. }
  238. printList(modulebase.JSON2ListResult(result), listFields)
  239. return nil
  240. }
  241. taskNotify := baseoptions.BoolV(opts.TaskNotify)
  242. if taskNotify {
  243. s.PrepareTask()
  244. }
  245. if count > 1 {
  246. results := modules.Servers.BatchCreate(s, params.JSON(params), count)
  247. printBatchResults(results, modules.Servers.GetColumns(s))
  248. } else {
  249. server, err := modules.Servers.Create(s, params.JSON(params))
  250. if err != nil {
  251. return err
  252. }
  253. printObject(server)
  254. }
  255. if taskNotify {
  256. s.WaitTaskNotify()
  257. }
  258. return nil
  259. })
  260. R(&options.ServerLoginInfoOptions{}, "server-logininfo", "Get login info of a server", func(s *mcclient.ClientSession, opts *options.ServerLoginInfoOptions) error {
  261. params := jsonutils.NewDict()
  262. if len(opts.Key) > 0 {
  263. privateKey, e := ioutil.ReadFile(opts.Key)
  264. if e != nil {
  265. return e
  266. }
  267. params.Add(jsonutils.NewString(string(privateKey)), "private_key")
  268. }
  269. i, e := modules.Servers.PerformAction(s, opts.ID, "login-info", params)
  270. if e != nil {
  271. return e
  272. }
  273. printObject(i)
  274. return nil
  275. })
  276. type ServerDiskSnapshotOptions struct {
  277. SERVER string `help:"server ID or Name"`
  278. DISK string `help:"create snapshot disk id"`
  279. SNAPSHOTNAME string `help:"Snapshot name"`
  280. }
  281. R(&ServerDiskSnapshotOptions{}, "server-disk-create-snapshot", "Task server disk snapshot", func(s *mcclient.ClientSession, args *ServerDiskSnapshotOptions) error {
  282. params := jsonutils.NewDict()
  283. params.Set("disk_id", jsonutils.NewString(args.DISK))
  284. params.Set("name", jsonutils.NewString(args.SNAPSHOTNAME))
  285. srv, err := modules.Servers.PerformAction(s, args.SERVER, "disk-snapshot", params)
  286. if err != nil {
  287. return err
  288. }
  289. printObject(srv)
  290. return nil
  291. })
  292. type ServerInsertISOOptions struct {
  293. ID string `help:"server ID or Name"`
  294. ISO string `help:"Glance image ID of the ISO"`
  295. }
  296. R(&ServerInsertISOOptions{}, "server-insert-iso", "Insert an ISO image into server's cdrom", func(s *mcclient.ClientSession, opts *ServerInsertISOOptions) error {
  297. img, err := image.Images.Get(s, opts.ISO, nil)
  298. if err != nil {
  299. return err
  300. }
  301. imgId, err := img.GetString("id")
  302. if err != nil {
  303. return err
  304. }
  305. params := jsonutils.NewDict()
  306. params.Add(jsonutils.NewString(imgId), "image_id")
  307. result, err := modules.Servers.PerformAction(s, opts.ID, "insertiso", params)
  308. if err != nil {
  309. return err
  310. }
  311. printObject(result)
  312. return nil
  313. })
  314. type ServerUserDataOptions struct {
  315. ID string `help:"ID or name of server"`
  316. FILE string `help:"Path to user data file"`
  317. }
  318. R(&ServerUserDataOptions{}, "server-set-user-data", "Update server user_data", func(s *mcclient.ClientSession, args *ServerUserDataOptions) error {
  319. params := jsonutils.NewDict()
  320. content, err := ioutil.ReadFile(args.FILE)
  321. if err != nil {
  322. return err
  323. }
  324. params.Add(jsonutils.NewString(string(content)), "user_data")
  325. result, err := modules.Servers.PerformAction(s, args.ID, "user-data", params)
  326. if err != nil {
  327. return err
  328. }
  329. printObject(result)
  330. return nil
  331. })
  332. type ServerAddExtraOption struct {
  333. ID string `help:"ID or name of server"`
  334. KEY string `help:"Option key"`
  335. VALUE string `help:"Option value"`
  336. }
  337. R(&ServerAddExtraOption{}, "server-add-extra-options", "Add server extra options", func(s *mcclient.ClientSession, args *ServerAddExtraOption) error {
  338. params := jsonutils.NewDict()
  339. params.Add(jsonutils.NewString(args.KEY), "key")
  340. params.Add(jsonutils.NewString(args.VALUE), "value")
  341. result, err := modules.Servers.PerformAction(s, args.ID, "set-extra-option", params)
  342. if err != nil {
  343. return err
  344. }
  345. printObject(result)
  346. return nil
  347. })
  348. type ServerRemoveExtraOption struct {
  349. ID string `help:"ID or name of server"`
  350. KEY string `help:"Option key"`
  351. Value string `help:"Option value"`
  352. }
  353. R(&ServerRemoveExtraOption{}, "server-remove-extra-options", "Remove server extra options", func(s *mcclient.ClientSession, args *ServerRemoveExtraOption) error {
  354. params := jsonutils.NewDict()
  355. params.Add(jsonutils.NewString(args.KEY), "key")
  356. if len(args.Value) > 0 {
  357. params.Add(jsonutils.NewString(args.Value), "value")
  358. }
  359. result, err := modules.Servers.PerformAction(s, args.ID, "del-extra-option", params)
  360. if err != nil {
  361. return err
  362. }
  363. printObject(result)
  364. return nil
  365. })
  366. R(&options.ServerPrepaidRecycleOptions{}, "server-enable-recycle", "Put a prepaid server into recycle pool, so that it can be shared", func(s *mcclient.ClientSession, args *options.ServerPrepaidRecycleOptions) error {
  367. params := jsonutils.NewDict()
  368. if args.AutoDelete {
  369. params.Add(jsonutils.JSONTrue, "auto_delete")
  370. }
  371. result, err := modules.Servers.PerformAction(s, args.ID, "prepaid-recycle", params)
  372. if err != nil {
  373. return err
  374. }
  375. printObject(result)
  376. return nil
  377. })
  378. R(&options.ServerPrepaidRecycleOptions{}, "server-disable-recycle", "Pull a prepaid server from recycle pool, so that it will not be shared anymore", func(s *mcclient.ClientSession, args *options.ServerPrepaidRecycleOptions) error {
  379. params := jsonutils.NewDict()
  380. result, err := modules.Servers.PerformAction(s, args.ID, "undo-prepaid-recycle", params)
  381. if err != nil {
  382. return err
  383. }
  384. printObject(result)
  385. return nil
  386. })
  387. type ServerImportOptions struct {
  388. LOCATION string `help:"Server desc file location, should be desc file or workspace directory"`
  389. HOST string `help:"Host id or name for this server"`
  390. }
  391. R(&ServerImportOptions{}, "server-import", "Import a server by desc file", func(s *mcclient.ClientSession, args *ServerImportOptions) error {
  392. var descFiles []string
  393. err := filepath.Walk(args.LOCATION, func(path string, info os.FileInfo, err error) error {
  394. if err != nil {
  395. return err
  396. }
  397. if info.IsDir() {
  398. return nil
  399. }
  400. if info.Name() == "desc" {
  401. descFiles = append(descFiles, path)
  402. }
  403. return nil
  404. })
  405. if err != nil {
  406. return fmt.Errorf("Find desc files: %v", err)
  407. }
  408. importF := func(desc string) error {
  409. ret, err := ioutil.ReadFile(desc)
  410. if err != nil {
  411. return fmt.Errorf("Read file %s: %v", desc, err)
  412. }
  413. jsonObj, err := jsonutils.Parse(ret)
  414. if err != nil {
  415. return fmt.Errorf("Parse %s to json: %v", string(ret), err)
  416. }
  417. params := jsonObj.(*jsonutils.JSONDict)
  418. disks, err := params.GetArray("disks")
  419. if err != nil || len(disks) == 0 {
  420. return fmt.Errorf("Desc %s not have disks, skip it", desc)
  421. }
  422. params.Add(jsonutils.NewString(args.HOST), "host_id")
  423. // project may not exists
  424. params.Remove("tenant")
  425. params.Remove("tenant_id")
  426. _, err = modules.Servers.PerformClassAction(s, "import", params)
  427. if err != nil {
  428. return err
  429. }
  430. //printObject(result)
  431. return nil
  432. }
  433. for _, descFile := range descFiles {
  434. if err := importF(descFile); err != nil {
  435. log.Errorf("Import %s error: %v", descFile, err)
  436. }
  437. }
  438. return nil
  439. })
  440. type ServersImportFromLibvirtOptions struct {
  441. CONFIG_FILE string `help:"File Path describing servers from libvirt"`
  442. }
  443. type Servers struct {
  444. Mac string `yaml:"mac"`
  445. Ip string `yaml:"ip"`
  446. }
  447. type Hosts struct {
  448. HostIp string `yaml:"host_ip"`
  449. XmlFilePath string `yaml:"xml_file_path"`
  450. MonitorPath string `yaml:"monitor_path"`
  451. Servers []Servers `yaml:"servers"`
  452. }
  453. type LibvirtImportOptions struct {
  454. Hosts []Hosts `yaml:"hosts"`
  455. }
  456. R(&ServersImportFromLibvirtOptions{}, "servers-import-from-libvirt", "Import servers from libvrt", func(s *mcclient.ClientSession, args *ServersImportFromLibvirtOptions) error {
  457. var (
  458. rawConfig []byte
  459. err error
  460. )
  461. rawConfig, err = ioutil.ReadFile(args.CONFIG_FILE)
  462. if err != nil {
  463. return fmt.Errorf("Read config file %s error: %s", args.CONFIG_FILE, err)
  464. }
  465. var (
  466. params []jsonutils.JSONObject
  467. config = &compute.SLibvirtImportConfig{}
  468. )
  469. // Try parse as json first
  470. {
  471. err = json.Unmarshal(rawConfig, config)
  472. if err != nil {
  473. goto YAML
  474. }
  475. for i := 0; i < len(config.Hosts); i++ {
  476. if nIp := net.ParseIP(config.Hosts[i].HostIp); nIp == nil {
  477. return fmt.Errorf("Parse host ip %s failed", config.Hosts[i].HostIp)
  478. }
  479. for _, server := range config.Hosts[i].Servers {
  480. for mac, ip := range server.MacIp {
  481. if _, err := net.ParseMAC(mac); err != nil {
  482. return fmt.Errorf("Parse mac %s error %s", mac, err)
  483. }
  484. if nIp := net.ParseIP(ip); nIp == nil {
  485. return fmt.Errorf("Parse ip %s failed", ip)
  486. }
  487. }
  488. }
  489. }
  490. goto REQUEST
  491. }
  492. YAML: // Try Parse as yaml
  493. {
  494. yamlConfig := &LibvirtImportOptions{}
  495. err = yaml.Unmarshal(rawConfig, yamlConfig)
  496. if err != nil {
  497. return err
  498. }
  499. config.Hosts = make([]compute.SLibvirtHostConfig, len(yamlConfig.Hosts))
  500. for i := 0; i < len(yamlConfig.Hosts); i++ {
  501. if nIp := net.ParseIP(yamlConfig.Hosts[i].HostIp); nIp == nil {
  502. return fmt.Errorf("Parse host ip %s failed", yamlConfig.Hosts[i].HostIp)
  503. }
  504. config.Hosts[i].HostIp = yamlConfig.Hosts[i].HostIp
  505. config.Hosts[i].XmlFilePath = yamlConfig.Hosts[i].XmlFilePath
  506. config.Hosts[i].Servers = make([]compute.SLibvirtServerConfig, len(yamlConfig.Hosts[i].Servers))
  507. config.Hosts[i].MonitorPath = yamlConfig.Hosts[i].MonitorPath
  508. for j := 0; j < len(yamlConfig.Hosts[i].Servers); j++ {
  509. config.Hosts[i].Servers[j].MacIp = make(map[string]string)
  510. mac := yamlConfig.Hosts[i].Servers[j].Mac
  511. _, err := net.ParseMAC(mac)
  512. if err != nil {
  513. return fmt.Errorf("Parse mac address %s error %s", mac, err)
  514. }
  515. ip := yamlConfig.Hosts[i].Servers[j].Ip
  516. nIp := net.ParseIP(ip)
  517. if len(nIp) == 0 {
  518. return fmt.Errorf("Parse ip address %s failed", ip)
  519. }
  520. config.Hosts[i].Servers[j].MacIp[mac] = ip
  521. }
  522. }
  523. }
  524. REQUEST:
  525. params, err = jsonutils.Marshal(config.Hosts).GetArray()
  526. if err != nil {
  527. return err
  528. }
  529. //for i := 0; i < len(params); i++ {
  530. // val := jsonutils.NewDict()
  531. // val.Set(modules.Servers.KeywordPlural, params[i])
  532. // params[i] = val
  533. //}
  534. results := modules.Servers.BatchPerformClassAction(s, "import-from-libvirt", params)
  535. printBatchResults(results, modules.Servers.GetColumns(s))
  536. return nil
  537. })
  538. type ServerExportVirtInstallCommand struct {
  539. ID string `help:"Server Id" json:"-"`
  540. LibvirtBridge string `help:"Libvirt default bridge" json:"libvirt_bridge"`
  541. ExtraCmdline []string `help:"Extra virt-install arguments add to script, eg:'--extra-args ...', '--console ...'" json:"extra_cmdline"`
  542. }
  543. R(&ServerExportVirtInstallCommand{}, "server-export-virt-install-command", "Export virt-install command line from existing guest", func(s *mcclient.ClientSession, args *ServerExportVirtInstallCommand) error {
  544. params := jsonutils.NewDict()
  545. if len(args.LibvirtBridge) > 0 {
  546. params.Set("libvirt_bridge", jsonutils.NewString(args.LibvirtBridge))
  547. }
  548. if len(args.ExtraCmdline) > 0 {
  549. params.Set("extra_cmdline", jsonutils.NewStringArray(args.ExtraCmdline))
  550. }
  551. result, err := modules.Servers.GetSpecific(s, args.ID, "virt-install", params)
  552. if err != nil {
  553. return err
  554. }
  555. printObject(result)
  556. return nil
  557. })
  558. R(&options.ServerIdOptions{}, "server-remote-nics", "Show remote nics of a server", func(s *mcclient.ClientSession, opts *options.ServerIdOptions) error {
  559. result, err := modules.Servers.GetSpecific(s, opts.ID, "remote-nics", nil)
  560. if err != nil {
  561. return err
  562. }
  563. listResult := printutils.ListResult{}
  564. listResult.Data, _ = result.GetArray()
  565. printList(&listResult, nil)
  566. return nil
  567. })
  568. type ServerSyncFixNicsOptions struct {
  569. ID string `help:"ID or name of VM" json:"-"`
  570. IP []string `help:"IP address of each NIC" json:"ip"`
  571. }
  572. R(&ServerSyncFixNicsOptions{}, "server-sync-fix-nics", "Fix missing IP for each nics after syncing VNICS", func(s *mcclient.ClientSession, opts *ServerSyncFixNicsOptions) error {
  573. params := jsonutils.Marshal(opts)
  574. result, err := modules.Servers.PerformAction(s, opts.ID, "sync-fix-nics", params)
  575. if err != nil {
  576. return err
  577. }
  578. printObject(result)
  579. return nil
  580. })
  581. type ServerResizeDiskOptions struct {
  582. Server string `help:"ID or name of VM" json:"-" optional:"false" positional:"true"`
  583. Disk string `help:"ID or name of disk to resize" json:"disk" optional:"false" positional:"true"`
  584. Size string `help:"new size of disk in MB" json:"size" optional:"false" positional:"true"`
  585. }
  586. R(&ServerResizeDiskOptions{}, "server-resize-disk", "Resize attached disk of a server", func(s *mcclient.ClientSession, args *ServerResizeDiskOptions) error {
  587. params := jsonutils.Marshal(args)
  588. result, err := modules.Servers.PerformAction(s, args.Server, "resize-disk", params)
  589. if err != nil {
  590. return err
  591. }
  592. printObject(result)
  593. return nil
  594. })
  595. type ServerGroupsOptions struct {
  596. ID string `help:"ID or name of VM"`
  597. Group []string `help:"ids or names of group"`
  598. }
  599. R(&ServerGroupsOptions{}, "server-join-groups", "Join multiple groups", func(s *mcclient.ClientSession,
  600. opts *ServerGroupsOptions) error {
  601. params, err := baseoptions.StructToParams(opts)
  602. if err != nil {
  603. return err
  604. }
  605. server, err := modules.Servers.PerformAction(s, opts.ID, "bind-groups", params)
  606. if err != nil {
  607. return err
  608. }
  609. printObject(server)
  610. return nil
  611. })
  612. R(&ServerGroupsOptions{}, "server-leave-groups", "Leave multiple groups", func(s *mcclient.ClientSession,
  613. opts *ServerGroupsOptions) error {
  614. params, err := baseoptions.StructToParams(opts)
  615. if err != nil {
  616. return err
  617. }
  618. server, err := modules.Servers.PerformAction(s, opts.ID, "unbind-groups", params)
  619. if err != nil {
  620. return err
  621. }
  622. printObject(server)
  623. return nil
  624. })
  625. type ServerQemuParams struct {
  626. ID string `help:"ID or name of VM"`
  627. DisableIsaSerial string `help:"disable isa serial device" choices:"true|false"`
  628. DisablePvpanic string `help:"disable pvpanic device" choices:"true|false"`
  629. DisableUsbKbd string `help:"disable usb kbd" choices:"true|false"`
  630. UsbControllerType string `help:"usb controller type" choices:"usb-ehci|qemu-xhci"`
  631. }
  632. R(&ServerQemuParams{}, "server-set-qemu-params", "config qemu params", func(s *mcclient.ClientSession,
  633. opts *ServerQemuParams) error {
  634. params := jsonutils.NewDict()
  635. if len(opts.DisableIsaSerial) > 0 {
  636. params.Set("disable_isa_serial", jsonutils.NewString(opts.DisableIsaSerial))
  637. }
  638. if len(opts.DisablePvpanic) > 0 {
  639. params.Set("disable_pvpanic", jsonutils.NewString(opts.DisablePvpanic))
  640. }
  641. if len(opts.DisableUsbKbd) > 0 {
  642. params.Set("disable_usb_kbd", jsonutils.NewString(opts.DisableUsbKbd))
  643. }
  644. if len(opts.UsbControllerType) > 0 {
  645. params.Set("usb_controller_type", jsonutils.NewString(opts.UsbControllerType))
  646. }
  647. result, err := modules.Servers.PerformAction(s, opts.ID, "set-qemu-params", params)
  648. if err != nil {
  649. return err
  650. }
  651. printObject(result)
  652. return nil
  653. })
  654. type ServerCreateSnapshot struct {
  655. ID string `help:"ID or name of VM" json:"-"`
  656. SNAPSHOT string `help:"Instance snapshot name" json:"name"`
  657. WithMemory bool `help:"Save memory state" json:"with_memory"`
  658. }
  659. R(&ServerCreateSnapshot{}, "instance-snapshot-create", "create instance snapshot", func(s *mcclient.ClientSession, opts *ServerCreateSnapshot) error {
  660. params := jsonutils.Marshal(opts)
  661. result, err := modules.Servers.PerformAction(s, opts.ID, "instance-snapshot", params)
  662. if err != nil {
  663. return err
  664. }
  665. printObject(result)
  666. return nil
  667. })
  668. type ServerCreateBackup struct {
  669. ID string `help:"ID or name of VM" json:"-"`
  670. BACKUP string `help:"Instance backup name" json:"name"`
  671. BACKUPSTORAGEID string `help:"backup storage id" json:"backup_storage_id"`
  672. }
  673. R(&ServerCreateBackup{}, "server-create-instance-backup", "create instance backup", func(s *mcclient.ClientSession, opts *ServerCreateBackup) error {
  674. params := jsonutils.Marshal(opts)
  675. result, err := modules.Servers.PerformAction(s, opts.ID, "instance-backup", params)
  676. if err != nil {
  677. return err
  678. }
  679. printObject(result)
  680. return nil
  681. })
  682. type ServerSnapshotAndClone struct {
  683. ID string `help:"ID or name of VM" json:"-"`
  684. NAME string `help:"Newly instance name" json:"name"`
  685. AutoStart bool `help:"Auto start new guest"`
  686. AllowDelete bool `help:"Allow new guest delete" json:"-"`
  687. Count int `help:"Guest count"`
  688. }
  689. R(&ServerSnapshotAndClone{}, "instance-snapshot-and-clone", "create instance snapshot and clone new instance", func(s *mcclient.ClientSession, opts *ServerSnapshotAndClone) error {
  690. params := jsonutils.Marshal(opts)
  691. dictParams := params.(*jsonutils.JSONDict)
  692. if opts.AllowDelete {
  693. dictParams.Set("disable_delete", jsonutils.JSONFalse)
  694. }
  695. result, err := modules.Servers.PerformAction(s, opts.ID, "snapshot-and-clone", dictParams)
  696. if err != nil {
  697. return err
  698. }
  699. printObject(result)
  700. return nil
  701. })
  702. type ServerRollBackSnapshot struct {
  703. ID string `help:"ID or name of VM" json:"-"`
  704. InstanceSnapshot string `help:"Instance snapshot id or name" json:"instance_snapshot"`
  705. WithMemory bool `help:"Memory restore" json:"with_memory"`
  706. AutoStart bool `help:"Auto start VM"`
  707. }
  708. R(&ServerRollBackSnapshot{}, "instance-snapshot-reset", "reset instance snapshot", func(s *mcclient.ClientSession, opts *ServerRollBackSnapshot) error {
  709. params := jsonutils.Marshal(opts)
  710. result, err := modules.Servers.PerformAction(s, opts.ID, "instance-snapshot-reset", params)
  711. if err != nil {
  712. return err
  713. }
  714. printObject(result)
  715. return nil
  716. })
  717. type ServerJnlpOptions struct {
  718. ID string `help:"ID or name of server"`
  719. Save string `help:"save xml into this file"`
  720. }
  721. R(&ServerJnlpOptions{}, "server-jnlp", "Get baremetal server jnlp file contentn", func(s *mcclient.ClientSession, args *ServerJnlpOptions) error {
  722. spec, err := modules.Servers.GetSpecific(s, args.ID, "jnlp", nil)
  723. if err != nil {
  724. return err
  725. }
  726. jnlp, err := spec.GetString("jnlp")
  727. if err != nil {
  728. return err
  729. }
  730. if len(args.Save) > 0 {
  731. return fileutils2.FilePutContents(args.Save, jnlp, false)
  732. } else {
  733. fmt.Println(jnlp)
  734. }
  735. return nil
  736. })
  737. R(&options.ServerSSHLoginOptions{}, "server-ssh", "Use SSH login a server", func(s *mcclient.ClientSession, opts *options.ServerSSHLoginOptions) error {
  738. srv, err := modules.Servers.Get(s, opts.ID, nil)
  739. if err != nil {
  740. return err
  741. }
  742. srvid, err := srv.GetString("id")
  743. if err != nil {
  744. return err
  745. }
  746. eip, err := srv.GetString("eip")
  747. if err != nil && err.Error() != "Get: key not found" {
  748. return err
  749. }
  750. vpcid, err := srv.GetString("vpc_id")
  751. if err != nil {
  752. return err
  753. }
  754. address := make([]string, 0)
  755. nics, err := srv.GetArray("nics")
  756. if err != nil {
  757. return err
  758. }
  759. for _, nic := range nics {
  760. if addr, err := nic.GetString("ip_addr"); err == nil {
  761. address = append(address, addr)
  762. }
  763. }
  764. if len(address) == 0 {
  765. return fmt.Errorf("Not found ip address from server %s", opts.ID)
  766. }
  767. privateKey := ""
  768. params := jsonutils.NewDict()
  769. if len(opts.Key) > 0 {
  770. key, e := ioutil.ReadFile(opts.Key)
  771. if e != nil {
  772. return e
  773. }
  774. params.Add(jsonutils.NewString(string(key)), "private_key")
  775. privateKey = string(key)
  776. }
  777. i, e := modules.Servers.PerformAction(s, srvid, "login-info", params)
  778. if e != nil {
  779. return e
  780. }
  781. passwd, err := i.GetString("password")
  782. if err != nil && !opts.UseCloudroot {
  783. return err
  784. }
  785. if opts.Password != "" {
  786. passwd = opts.Password
  787. }
  788. user, err := i.GetString("username")
  789. if err != nil && !opts.UseCloudroot {
  790. return err
  791. }
  792. if opts.User != "" {
  793. user = opts.User
  794. }
  795. port := 22
  796. if opts.Port != 22 {
  797. port = opts.Port
  798. }
  799. var forwardItem *forwardInfo = nil
  800. host := address[0]
  801. if opts.Host != "" {
  802. host = opts.Host
  803. } else {
  804. if eip != "" {
  805. host = eip
  806. } else {
  807. if vpcid != "default" {
  808. forwardItem, err = openForward(s, srvid)
  809. if err != nil {
  810. return err
  811. }
  812. host = forwardItem.ProxyAddr
  813. port = forwardItem.ProxyPort
  814. }
  815. }
  816. }
  817. if opts.UseCloudroot {
  818. var err error
  819. privateKey, err = modules.Sshkeypairs.FetchPrivateKeyBySession(context.Background(), s)
  820. if err != nil {
  821. return err
  822. }
  823. passwd = ""
  824. user = "cloudroot"
  825. }
  826. var sshCli *ssh.Client
  827. err = nil
  828. for ; sshCli == nil; sshCli, err = ssh.NewClient(host, port, user, passwd, privateKey) {
  829. if err == nil {
  830. continue
  831. }
  832. if opts.Host != "" {
  833. return err
  834. }
  835. if forwardItem != nil {
  836. closeForward(s, srvid, forwardItem)
  837. return err
  838. } else {
  839. if vpcid != "default" {
  840. forwardItem, e = openForward(s, srvid)
  841. if e != nil {
  842. return e
  843. }
  844. host = forwardItem.ProxyAddr
  845. port = forwardItem.ProxyPort
  846. }
  847. }
  848. }
  849. log.Infof("ssh %s:%d", host, port)
  850. if err := sshCli.RunTerminal(); err != nil {
  851. if forwardItem != nil {
  852. closeForward(s, srvid, forwardItem)
  853. }
  854. return err
  855. }
  856. if forwardItem != nil {
  857. closeForward(s, srvid, forwardItem)
  858. }
  859. return nil
  860. })
  861. }