@rancher/shell 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -148
  2. package/assets/brand/suse/rancher-logo.svg +1 -130
  3. package/assets/images/featured/img1.jpg +0 -0
  4. package/assets/images/featured.jpg +0 -0
  5. package/assets/images/generic-plugin.svg +7 -0
  6. package/assets/styles/themes/_dark.scss +3 -0
  7. package/assets/styles/themes/_light.scss +3 -0
  8. package/assets/styles/themes/_suse.scss +1 -1
  9. package/assets/translations/en-us.yaml +209 -813
  10. package/assets/translations/zh-hans.yaml +28 -792
  11. package/components/ActionMenu.vue +3 -3
  12. package/components/AsyncButton.vue +17 -2
  13. package/components/ButtonDropdown.vue +4 -0
  14. package/components/Carousel.vue +291 -0
  15. package/components/CodeMirror.vue +6 -8
  16. package/components/CommunityLinks.vue +70 -19
  17. package/components/ContainerResourceLimit.vue +14 -0
  18. package/components/CruResource.vue +11 -3
  19. package/components/Dialog.vue +102 -0
  20. package/components/ExplorerMembers.vue +121 -0
  21. package/components/ExplorerProjectsNamespaces.vue +404 -0
  22. package/components/GrafanaDashboard.vue +17 -2
  23. package/components/IconMessage.vue +9 -1
  24. package/components/LocaleSelector.vue +114 -0
  25. package/components/PromptModal.vue +2 -3
  26. package/components/ResourceList/index.vue +1 -1
  27. package/components/ResourceTable.vue +9 -7
  28. package/components/SimpleBox.vue +6 -4
  29. package/components/SingleClusterInfo.vue +1 -1
  30. package/components/SortableTable/index.vue +18 -25
  31. package/components/SortableTable/selection.js +1 -0
  32. package/components/Tabbed/Tab.vue +5 -0
  33. package/components/Tabbed/index.vue +29 -2
  34. package/components/auth/AzureWarning.vue +5 -1
  35. package/components/auth/Principal.vue +2 -1
  36. package/components/auth/RoleDetailEdit.vue +18 -11
  37. package/components/fleet/FleetBundles.vue +8 -3
  38. package/components/fleet/FleetRepos.vue +0 -2
  39. package/components/fleet/FleetSummary.vue +6 -0
  40. package/components/form/KeyValue.vue +80 -58
  41. package/components/form/NameNsDescription.vue +12 -8
  42. package/components/form/NodeScheduling.vue +1 -1
  43. package/components/form/ResourceTabs/index.vue +5 -1
  44. package/components/form/WorkloadPorts.vue +1 -1
  45. package/components/formatter/ClusterLink.vue +3 -7
  46. package/components/formatter/WorkloadHealthScale.vue +1 -1
  47. package/components/nav/Header.vue +9 -9
  48. package/components/nav/NamespaceFilter.vue +10 -7
  49. package/components/nav/TopLevelMenu.vue +10 -65
  50. package/components/nav/WindowManager/ContainerLogs.vue +1 -1
  51. package/config/footer.js +13 -14
  52. package/config/labels-annotations.js +2 -1
  53. package/config/product/explorer.js +5 -4
  54. package/config/product/harvester-manager.js +64 -2
  55. package/config/product/legacy.js +0 -47
  56. package/config/product/manager.js +9 -0
  57. package/config/product/multi-cluster-apps.js +0 -12
  58. package/config/product/settings.js +12 -1
  59. package/config/product/uiplugins.js +17 -0
  60. package/config/settings.js +37 -72
  61. package/config/table-headers.js +0 -1
  62. package/config/types.js +9 -25
  63. package/config/uiplugins.js +60 -0
  64. package/content/docs/en-us/getting-started.md +1 -26
  65. package/core/plugin-routes.ts +34 -22
  66. package/core/plugin.ts +15 -3
  67. package/core/plugins-loader.js +2 -0
  68. package/core/plugins.js +91 -36
  69. package/core/types.ts +7 -1
  70. package/detail/provisioning.cattle.io.cluster.vue +15 -2
  71. package/detail/workload/index.vue +11 -5
  72. package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
  73. package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
  74. package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
  75. package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
  76. package/dialog/DiagnosticTimingsDialog.vue +116 -0
  77. package/{components/dialog → dialog}/DrainNode.vue +0 -0
  78. package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
  79. package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
  80. package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
  81. package/{components/dialog → dialog}/RotateCertificatesDialog.vue +9 -3
  82. package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
  83. package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
  84. package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
  85. package/edit/auth/azuread.vue +44 -6
  86. package/edit/management.cattle.io.project.vue +2 -2
  87. package/edit/namespace.vue +17 -10
  88. package/edit/networking.k8s.io.ingress/index.vue +2 -2
  89. package/edit/persistentvolume/index.vue +3 -0
  90. package/edit/persistentvolumeclaim.vue +1 -0
  91. package/edit/pod.vue +27 -0
  92. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
  93. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +33 -5
  94. package/edit/provisioning.cattle.io.cluster/rke2.vue +76 -5
  95. package/edit/service.vue +8 -6
  96. package/edit/workload/__tests__/Upgrading.test.ts +1 -0
  97. package/edit/workload/index.vue +375 -15
  98. package/edit/workload/mixins/workload.js +62 -7
  99. package/edit/workload/storage/ContainerMountPaths.vue +240 -0
  100. package/edit/workload/storage/Mount.vue +1 -0
  101. package/edit/workload/storage/awsElasticBlockStore.vue +20 -1
  102. package/edit/workload/storage/azureDisk.vue +22 -2
  103. package/edit/workload/storage/azureFile.vue +20 -2
  104. package/edit/workload/storage/csi/index.vue +23 -1
  105. package/edit/workload/storage/gcePersistentDisk.vue +20 -2
  106. package/edit/workload/storage/index.vue +23 -49
  107. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
  108. package/edit/workload/storage/vsphereVolume.vue +11 -1
  109. package/layouts/default.vue +63 -32
  110. package/layouts/error.vue +5 -1
  111. package/layouts/home.vue +14 -5
  112. package/layouts/plain.vue +10 -5
  113. package/list/harvesterhci.io.management.cluster.vue +74 -33
  114. package/list/management.cattle.io.setting.vue +3 -3
  115. package/list/namespace.vue +3 -5
  116. package/list/provisioning.cattle.io.cluster.vue +1 -1
  117. package/machine-config/amazonec2.vue +2 -0
  118. package/machine-config/harvester.vue +100 -51
  119. package/middleware/authenticated.js +56 -52
  120. package/mixins/form-validation.js +1 -1
  121. package/mixins/resource-fetch.js +3 -1
  122. package/models/catalog.cattle.io.uiplugin.js +34 -0
  123. package/models/cluster/node.js +25 -2
  124. package/models/fleet.cattle.io.bundle.js +27 -20
  125. package/models/harvesterhci.io.management.cluster.js +200 -5
  126. package/models/management.cattle.io.cluster.js +1 -1
  127. package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
  128. package/models/management.cattle.io.project.js +23 -2
  129. package/models/namespace.js +19 -3
  130. package/models/pod.js +19 -2
  131. package/models/provisioning.cattle.io.cluster.js +16 -6
  132. package/models/workload.js +9 -246
  133. package/models/workload.service.js +314 -0
  134. package/nuxt.config.js +80 -34
  135. package/package.json +107 -108
  136. package/pages/auth/login.vue +11 -2
  137. package/pages/auth/setup.vue +1 -1
  138. package/pages/c/_cluster/_product/members/index.vue +3 -93
  139. package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
  140. package/pages/c/_cluster/apps/charts/index.vue +46 -1
  141. package/pages/c/_cluster/apps/charts/install.vue +10 -9
  142. package/pages/c/_cluster/explorer/index.vue +72 -9
  143. package/pages/c/_cluster/explorer/tools/index.vue +12 -5
  144. package/pages/c/_cluster/mcapps/index.vue +1 -1
  145. package/pages/c/_cluster/settings/brand.vue +0 -40
  146. package/pages/c/_cluster/settings/links.vue +200 -0
  147. package/pages/c/_cluster/settings/performance.vue +19 -16
  148. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +232 -0
  149. package/pages/c/_cluster/uiplugins/InstallDialog.vue +242 -0
  150. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +284 -0
  151. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +130 -0
  152. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +253 -0
  153. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +115 -0
  154. package/pages/c/_cluster/uiplugins/index.vue +694 -0
  155. package/pages/diagnostic.vue +185 -101
  156. package/pages/docs/_doc.vue +3 -1
  157. package/pages/fail-whale.vue +1 -10
  158. package/pages/home.vue +21 -56
  159. package/pages/index.vue +18 -4
  160. package/pages/prefs.vue +108 -86
  161. package/pages/safeMode.vue +17 -0
  162. package/pages/support/index.vue +23 -15
  163. package/pkg/auto-import.js +44 -7
  164. package/pkg/dynamic-importer.lib.js +4 -0
  165. package/pkg/dynamic-plugin-loader.js +28 -0
  166. package/pkg/import.js +2 -2
  167. package/pkg/model-loader-require.lib.js +3 -0
  168. package/pkg/vue.config.js +9 -6
  169. package/plugins/dashboard-store/model-loader-require.js +12 -0
  170. package/plugins/dashboard-store/model-loader.js +4 -1
  171. package/plugins/dashboard-store/resource-class.js +12 -5
  172. package/plugins/formatters.js +15 -0
  173. package/plugins/plugin.js +56 -4
  174. package/plugins/steve/actions.js +1 -1
  175. package/plugins/steve/index.js +6 -4
  176. package/plugins/steve/mutations.js +1 -1
  177. package/plugins/steve/subscribe.js +89 -56
  178. package/plugins/steve/web-worker.steve-sub-worker.js +24 -15
  179. package/promptRemove/management.cattle.io.globalrole.vue +47 -0
  180. package/promptRemove/management.cattle.io.roletemplate.vue +47 -0
  181. package/promptRemove/mixin/roleDeletionCheck.js +97 -0
  182. package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
  183. package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
  184. package/scripts/build-pkg.sh +48 -2
  185. package/scripts/drone-build-pkg.sh +31 -0
  186. package/scripts/publish-shell.sh +11 -12
  187. package/scripts/serve-pkgs +17 -10
  188. package/scripts/sync-shell-deps +37 -0
  189. package/store/catalog.js +12 -9
  190. package/store/i18n.js +26 -12
  191. package/store/index.js +4 -181
  192. package/store/prefs.js +46 -2
  193. package/store/type-map.js +47 -33
  194. package/store/uiplugins.ts +15 -61
  195. package/utils/__tests__/object.test.ts +0 -24
  196. package/utils/__tests__/selector.test.ts +1 -1
  197. package/utils/cluster.js +1 -1
  198. package/utils/custom-validators.js +1 -12
  199. package/utils/dynamic-importer.js +5 -1
  200. package/utils/grafana.js +2 -6
  201. package/utils/socket.js +41 -20
  202. package/utils/string.js +1 -7
  203. package/utils/validators/formRules/__tests__/index.test.ts +108 -0
  204. package/utils/validators/formRules/index.ts +9 -1
  205. package/utils/validators/setting.js +0 -35
  206. package/yarn-error.log +195 -0
  207. package/components/FilterLabel.vue +0 -254
  208. package/components/HarvesterUpgradeProgressBarList.vue +0 -109
  209. package/components/VMConsoleBar.vue +0 -87
  210. package/components/dialog/harvester/AddHotplugModal.vue +0 -159
  211. package/components/dialog/harvester/BackupModal.vue +0 -117
  212. package/components/dialog/harvester/CloneTemplate.vue +0 -125
  213. package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
  214. package/components/dialog/harvester/ExportImageDialog.vue +0 -152
  215. package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
  216. package/components/dialog/harvester/MigrationDialog.vue +0 -154
  217. package/components/dialog/harvester/RestoreDialog.vue +0 -153
  218. package/components/dialog/harvester/SupportBundle.vue +0 -217
  219. package/components/dialog/harvester/UnplugVolume.vue +0 -108
  220. package/components/form/SerialConsole/index.vue +0 -267
  221. package/components/formatter/AttachVMWithName.vue +0 -46
  222. package/components/formatter/CloudInitType.vue +0 -27
  223. package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
  224. package/components/formatter/HarvesterCPUUsed.vue +0 -122
  225. package/components/formatter/HarvesterDiskState.vue +0 -66
  226. package/components/formatter/HarvesterHostName.vue +0 -66
  227. package/components/formatter/HarvesterIpAddress.vue +0 -90
  228. package/components/formatter/HarvesterMemoryUsed.vue +0 -140
  229. package/components/formatter/HarvesterMigrationState.vue +0 -85
  230. package/components/formatter/HarvesterNodeName.vue +0 -49
  231. package/components/formatter/HarvesterStorageUsed.vue +0 -194
  232. package/components/formatter/HarvesterVmState.vue +0 -123
  233. package/components/nav/HarvesterUpgrade.vue +0 -232
  234. package/components/novnc/NovncConsole.vue +0 -93
  235. package/components/novnc/NovncConsoleItem.vue +0 -89
  236. package/components/novnc/NovncConsoleWrapper.vue +0 -243
  237. package/config/harvester-map.js +0 -44
  238. package/config/harvester-table-headers.js +0 -27
  239. package/config/product/harvester.js +0 -305
  240. package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
  241. package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
  242. package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
  243. package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
  244. package/detail/harvesterhci.io.host/index.vue +0 -243
  245. package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
  246. package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
  247. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
  248. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
  249. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
  250. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
  251. package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
  252. package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
  253. package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
  254. package/edit/harvesterhci.io.host/index.vue +0 -533
  255. package/edit/harvesterhci.io.keypair.vue +0 -112
  256. package/edit/harvesterhci.io.managedchart/index.vue +0 -25
  257. package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
  258. package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
  259. package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
  260. package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
  261. package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
  262. package/edit/harvesterhci.io.setting/index.vue +0 -201
  263. package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
  264. package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
  265. package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
  266. package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
  267. package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
  268. package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
  269. package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
  270. package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
  271. package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
  272. package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
  273. package/edit/harvesterhci.io.volume.vue +0 -195
  274. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
  275. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
  276. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
  277. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
  278. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
  279. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
  280. package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
  281. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
  282. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
  283. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
  284. package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
  285. package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
  286. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
  287. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
  288. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
  289. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
  290. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
  291. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
  292. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
  293. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
  294. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
  295. package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
  296. package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
  297. package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
  298. package/edit/workload/types/Deployment.vue +0 -377
  299. package/edit/workload/types/Generic.vue +0 -295
  300. package/list/harvesterhci.io.cloudtemplate.vue +0 -78
  301. package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
  302. package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
  303. package/list/harvesterhci.io.dashboard/index.vue +0 -752
  304. package/list/harvesterhci.io.host/index.vue +0 -186
  305. package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
  306. package/list/harvesterhci.io.setting.vue +0 -241
  307. package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
  308. package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
  309. package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
  310. package/list/harvesterhci.io.volume.vue +0 -122
  311. package/list/kubevirt.io.virtualmachine.vue +0 -193
  312. package/mixins/harvester-vm/impl.js +0 -267
  313. package/mixins/harvester-vm/index.js +0 -1357
  314. package/models/harvester/configmap.js +0 -32
  315. package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
  316. package/models/harvester/harvesterhci.io.keypair.js +0 -12
  317. package/models/harvester/harvesterhci.io.setting.js +0 -127
  318. package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
  319. package/models/harvester/harvesterhci.io.upgrade.js +0 -226
  320. package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
  321. package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
  322. package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
  323. package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
  324. package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
  325. package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
  326. package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
  327. package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
  328. package/models/harvester/management.cattle.io.managedchart.js +0 -191
  329. package/models/harvester/management.cattle.io.setting.js +0 -40
  330. package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
  331. package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
  332. package/models/harvester/node.js +0 -255
  333. package/models/harvester/persistentvolumeclaim.js +0 -166
  334. package/models/harvester/pod.js +0 -185
  335. package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
  336. package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
  337. package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
  338. package/pages/c/_cluster/harvester/index.vue +0 -24
  339. package/pages/c/_cluster/harvester/support/index.vue +0 -154
  340. package/pages/plugins.vue +0 -387
  341. package/pkg/model-loader.lib.js +0 -3
  342. package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
  343. package/server/verdaccio-middleware.js +0 -56
  344. package/store/harvester-common.js +0 -126
  345. package/utils/validators/vm-datavolumes.js +0 -38
  346. package/utils/validators/vm-image.js +0 -32
  347. package/utils/validators/vm.js +0 -221
@@ -1,850 +0,0 @@
1
- import Vue from 'vue';
2
- import { load } from 'js-yaml';
3
- import { colorForState } from '@shell/plugins/dashboard-store/resource-class';
4
- import { POD, NODE, HCI, PVC } from '@shell/config/types';
5
- import { findBy } from '@shell/utils/array';
6
- import { parseSi } from '@shell/utils/units';
7
- import { get } from '@shell/utils/object';
8
- import { HCI as HCI_ANNOTATIONS } from '@shell/config/labels-annotations';
9
- import { _CLONE } from '@shell/config/query-params';
10
- import SteveModel from '@shell/plugins/steve/steve-class';
11
-
12
- export const OFF = 'Off';
13
-
14
- const VMI_WAITING_MESSAGE = 'The virtual machine is waiting for resources to become available.';
15
- const VM_ERROR = 'VM error';
16
- const STOPPING = 'Stopping';
17
- const WAITING = 'Waiting';
18
- const NOT_READY = 'Not Ready';
19
- const AGENT_CONNECTED = 'AgentConnected';
20
-
21
- const PAUSED = 'Paused';
22
- const PAUSED_VM_MODAL_MESSAGE = 'This VM has been paused. If you wish to unpause it, please click the Unpause button below. For further details, please check with your system administrator.';
23
-
24
- const POD_STATUS_NOT_SCHEDULABLE = 'POD_NOT_SCHEDULABLE';
25
- const POD_STATUS_CONTAINER_FAILING = 'POD_CONTAINER_FAILING';
26
- // eslint-disable-next-line no-unused-vars
27
- const POD_STATUS_NOT_READY = 'POD_NOT_READY';
28
-
29
- const POD_STATUS_FAILED = 'POD_FAILED';
30
- const POD_STATUS_CRASHLOOP_BACKOFF = 'POD_CRASHLOOP_BACKOFF';
31
- const POD_STATUS_UNKNOWN = 'POD_STATUS_UNKNOWN';
32
-
33
- const POD_STATUS_ALL_ERROR = [
34
- POD_STATUS_NOT_SCHEDULABLE,
35
- POD_STATUS_CONTAINER_FAILING,
36
- POD_STATUS_FAILED,
37
- POD_STATUS_CRASHLOOP_BACKOFF,
38
- POD_STATUS_UNKNOWN,
39
- ];
40
-
41
- const POD_STATUS_COMPLETED = 'POD_STATUS_COMPLETED';
42
- const POD_STATUS_SUCCEEDED = 'POD_STATUS_SUCCEEDED';
43
- const POD_STATUS_RUNNING = 'POD_STATUS_RUNNING';
44
-
45
- const POD_STATUS_ALL_READY = [
46
- POD_STATUS_RUNNING,
47
- POD_STATUS_COMPLETED,
48
- POD_STATUS_SUCCEEDED,
49
- ];
50
-
51
- const RunStrategy = {
52
- Always: 'Always',
53
- RerunOnFailure: 'RerunOnFailure',
54
- Halted: 'Halted',
55
- Manual: 'Manual',
56
- };
57
-
58
- const StateChangeRequest = {
59
- Start: 'Start',
60
- Stop: 'Stop',
61
- };
62
-
63
- const STARTING_MESSAGE =
64
- 'This virtual machine will start shortly. Preparing storage, networking, and compute resources.';
65
-
66
- const VMIPhase = {
67
- Pending: 'Pending',
68
- Scheduling: 'Scheduling',
69
- Scheduled: 'Scheduled',
70
- Running: 'Running',
71
- Succeeded: 'Succeeded',
72
- Failed: 'Failed',
73
- Unknown: 'Unknown',
74
- };
75
-
76
- const IgnoreMessages = ['pod has unbound immediate PersistentVolumeClaims'];
77
-
78
- export default class VirtVm extends SteveModel {
79
- get availableActions() {
80
- const out = super._availableActions;
81
-
82
- return [
83
- {
84
- action: 'stopVM',
85
- enabled: !!this.actions?.stop,
86
- icon: 'icon icon-close',
87
- label: this.t('harvester.action.stop'),
88
- bulkable: true,
89
- },
90
- {
91
- action: 'pauseVM',
92
- enabled: !!this.actions?.pause,
93
- icon: 'icon icon-pause',
94
- label: this.t('harvester.action.pause'),
95
- },
96
- {
97
- action: 'unpauseVM',
98
- enabled: !!this.actions?.unpause,
99
- icon: 'icon icon-spinner',
100
- label: this.t('harvester.action.unpause'),
101
- },
102
- {
103
- action: 'restartVM',
104
- enabled: !!this.actions?.restart,
105
- icon: 'icon icon-refresh',
106
- label: this.t('harvester.action.restart'),
107
- bulkable: true,
108
- },
109
- {
110
- action: 'softrebootVM',
111
- enabled: !!this.actions?.softreboot,
112
- icon: 'icon icon-refresh',
113
- label: this.t('harvester.action.softreboot'),
114
- },
115
- {
116
- action: 'startVM',
117
- enabled: !!this.actions?.start,
118
- icon: 'icon icon-play',
119
- label: this.t('harvester.action.start'),
120
- bulkable: true,
121
- },
122
- {
123
- action: 'backupVM',
124
- enabled: !!this.actions?.backup,
125
- icon: 'icon icon-backup',
126
- label: this.t('harvester.action.backup'),
127
- },
128
- {
129
- action: 'restoreVM',
130
- enabled: !!this.actions?.restore,
131
- icon: 'icon icon-backup-restore',
132
- label: this.t('harvester.action.restore'),
133
- },
134
- {
135
- action: 'ejectCDROM',
136
- enabled: !!this.actions?.ejectCdRom,
137
- icon: 'icon icon-delete',
138
- label: this.t('harvester.action.ejectCDROM'),
139
- },
140
- {
141
- action: 'migrateVM',
142
- enabled: !!this.actions?.migrate,
143
- icon: 'icon icon-copy',
144
- label: this.t('harvester.action.migrate'),
145
- },
146
- {
147
- action: 'abortMigrationVM',
148
- enabled: !!this.actions?.abortMigration,
149
- icon: 'icon icon-close',
150
- label: this.t('harvester.action.abortMigration'),
151
- },
152
- {
153
- action: 'addHotplug',
154
- enabled: !!this.actions?.addVolume,
155
- icon: 'icon icon-plus',
156
- label: this.t('harvester.action.addHotplug'),
157
- },
158
- {
159
- action: 'createTemplate',
160
- enabled: !!this.actions?.createTemplate,
161
- icon: 'icon icon-copy',
162
- label: this.t('harvester.action.createTemplate'),
163
- },
164
- {
165
- action: 'openLogs',
166
- enabled: !!this.links.view,
167
- icon: 'icon icon-fw icon-chevron-right',
168
- label: this.t('harvester.action.viewlogs'),
169
- total: 1,
170
- },
171
- ...out
172
- ];
173
- }
174
-
175
- applyDefaults(resources = this, realMode) {
176
- const spec = {
177
- runStrategy: 'RerunOnFailure',
178
- template: {
179
- metadata: { annotations: {} },
180
- spec: {
181
- domain: {
182
- machine: { type: '' },
183
- cpu: {
184
- cores: null,
185
- sockets: 1,
186
- threads: 1
187
- },
188
- devices: {
189
- inputs: [{
190
- bus: 'usb',
191
- name: 'tablet',
192
- type: 'tablet'
193
- }],
194
- interfaces: [{
195
- masquerade: {},
196
- model: 'virtio',
197
- name: 'default'
198
- }],
199
- disks: [],
200
- },
201
- resources: {
202
- limits: {
203
- memory: null,
204
- cpu: ''
205
- }
206
- },
207
- features: { acpi: { enabled: true } },
208
- },
209
- evictionStrategy: 'LiveMigrate',
210
- hostname: '',
211
- networks: [{
212
- name: 'default',
213
- pod: {}
214
- }],
215
- volumes: []
216
- }
217
- }
218
- };
219
-
220
- if (realMode !== _CLONE) {
221
- Vue.set(this.metadata, 'annotations', { [HCI_ANNOTATIONS.VOLUME_CLAIM_TEMPLATE]: '[]' });
222
- Vue.set(this, 'spec', spec);
223
- }
224
- }
225
-
226
- cleanForNew() {
227
- this.$dispatch(`cleanForNew`, this);
228
-
229
- this.spec.template.spec.hostname = '';
230
- const interfaces = this.spec.template.spec.domain.devices?.interfaces || [];
231
-
232
- for (let i = 0; i < interfaces.length; i++) {
233
- if (interfaces[i].macAddress) {
234
- interfaces[i].macAddress = '';
235
- }
236
- }
237
- }
238
-
239
- restartVM() {
240
- this.doActionGrowl('restart', {});
241
- }
242
-
243
- softrebootVM() {
244
- this.doActionGrowl('softreboot', {});
245
- }
246
-
247
- openLogs() {
248
- this.$dispatch('wm/open', {
249
- id: `${ this.id }-logs`,
250
- label: this.nameDisplay,
251
- icon: 'file',
252
- component: 'ContainerLogs',
253
- attrs: { pod: this.podResource }
254
- }, { root: true });
255
- }
256
-
257
- backupVM(resources = this) {
258
- this.$dispatch('promptModal', {
259
- resources,
260
- component: 'harvester/BackupModal'
261
- });
262
- }
263
-
264
- unplugVolume(diskName) {
265
- const resources = this;
266
-
267
- this.$dispatch('promptModal', {
268
- resources,
269
- diskName,
270
- component: 'harvester/UnplugVolume'
271
- });
272
- }
273
-
274
- restoreVM(resources = this) {
275
- this.$dispatch('promptModal', {
276
- resources,
277
- component: 'harvester/RestoreDialog'
278
- });
279
- }
280
-
281
- get machineType() {
282
- return this.spec?.template?.spec?.domain?.machine?.type || '';
283
- }
284
-
285
- get realAttachNodeName() {
286
- const vmi = this.$getters['byId'](HCI.VMI, this.id);
287
- const nodeName = vmi?.status?.nodeName;
288
- const node = this.$getters['byId'](NODE, nodeName);
289
-
290
- return node?.nameDisplay || '';
291
- }
292
-
293
- get nodeName() {
294
- const vmi = this.$getters['byId'](HCI.VMI, this.id);
295
- const nodeName = vmi?.status?.nodeName;
296
- const node = this.$getters['byId'](NODE, nodeName);
297
-
298
- return node?.id;
299
- }
300
-
301
- pauseVM() {
302
- this.doActionGrowl('pause', {});
303
- }
304
-
305
- unpauseVM() {
306
- this.doActionGrowl('unpause', {});
307
- }
308
-
309
- stopVM() {
310
- this.doActionGrowl('stop', {});
311
- }
312
-
313
- startVM() {
314
- this.doActionGrowl('start', {});
315
- }
316
-
317
- migrateVM(resources = this) {
318
- this.$dispatch('promptModal', {
319
- resources,
320
- component: 'harvester/MigrationDialog'
321
- });
322
- }
323
-
324
- ejectCDROM(resources = this) {
325
- this.$dispatch('promptModal', {
326
- resources,
327
- component: 'harvester/EjectCDROMDialog'
328
- });
329
- }
330
-
331
- abortMigrationVM() {
332
- this.doActionGrowl('abortMigration', {});
333
- }
334
-
335
- createTemplate(resources = this) {
336
- this.$dispatch('promptModal', {
337
- resources,
338
- component: 'harvester/CloneTemplate'
339
- });
340
- }
341
-
342
- addHotplug(resources = this) {
343
- this.$dispatch('promptModal', {
344
- resources,
345
- component: 'harvester/AddHotplugModal'
346
- });
347
- }
348
-
349
- get networksName() {
350
- const interfaces = this.spec.template.spec.domain.devices?.interfaces || [];
351
-
352
- return interfaces.map(I => I.name);
353
- }
354
-
355
- get isOff() {
356
- return !this.isVMExpectedRunning ? { status: OFF } : null;
357
- }
358
-
359
- get isWaitingForVMI() {
360
- if (this && this.isVMExpectedRunning && !this.isVMCreated) {
361
- return { status: WAITING, message: VMI_WAITING_MESSAGE };
362
- }
363
-
364
- return null;
365
- }
366
-
367
- get isVMExpectedRunning() {
368
- if (!this?.spec) {
369
- return false;
370
- }
371
- const { running = null, runStrategy = null } = this.spec;
372
- const conditions = this?.status?.conditions || [];
373
-
374
- if (running) {
375
- return true;
376
- }
377
-
378
- if (runStrategy !== null) {
379
- let changeRequests;
380
-
381
- switch (runStrategy) {
382
- case RunStrategy.Halted:
383
- return false;
384
- case RunStrategy.Always:
385
- return true;
386
- case RunStrategy.RerunOnFailure:
387
- if (this.status?.printableStatus === 'ErrorUnschedulable' && conditions.find(C => C.message && C.message.includes(IgnoreMessages))) {
388
- return true;
389
- }
390
-
391
- return ['Starting', 'Running'].includes(this.status?.printableStatus);
392
- case RunStrategy.Manual:
393
- default:
394
- changeRequests = new Set(
395
- (this.status?.stateChangeRequests || []).map(chRequest => chRequest?.action),
396
- );
397
-
398
- if (changeRequests.has(StateChangeRequest.Stop)) {
399
- return false;
400
- }
401
- if (changeRequests.has(StateChangeRequest.Start)) {
402
- return true;
403
- }
404
-
405
- if (changeRequests.size === 0 ) {
406
- return ['Starting', 'Running'].includes(this.status?.printableStatus);
407
- }
408
-
409
- return this.isVMCreated; // if there is no change request we can assume created is representing running (current and expected)
410
- }
411
- }
412
-
413
- return false;
414
- }
415
-
416
- get podResource() {
417
- const vmiResource = this.$rootGetters['harvester/byId'](HCI.VMI, this.id);
418
- const podList = this.$rootGetters['harvester/all'](POD);
419
-
420
- return podList.find( (P) => {
421
- return vmiResource?.metadata?.name && vmiResource?.metadata?.name === P.metadata?.ownerReferences?.[0].name;
422
- });
423
- }
424
-
425
- get isPaused() {
426
- const conditions = this.vmi?.status?.conditions || [];
427
- const isPause = conditions.filter(cond => cond.type === PAUSED).length > 0;
428
-
429
- return isPause ? {
430
- status: PAUSED,
431
- message: PAUSED_VM_MODAL_MESSAGE
432
- } : null;
433
- }
434
-
435
- get isVMError() {
436
- const conditions = get(this, 'status.conditions');
437
- const vmFailureCond = findBy(conditions, 'type', 'Failure');
438
-
439
- if (vmFailureCond) {
440
- return {
441
- status: VM_ERROR,
442
- detailedMessage: vmFailureCond.message,
443
- };
444
- }
445
-
446
- return null;
447
- }
448
-
449
- get vmi() {
450
- const vmis = this.$rootGetters['harvester/all'](HCI.VMI);
451
-
452
- return vmis.find(VMI => VMI.id === this.id);
453
- }
454
-
455
- get isError() {
456
- const conditions = get(this.vmi, 'status.conditions');
457
- const vmiFailureCond = findBy(conditions, 'type', 'Failure');
458
-
459
- if (vmiFailureCond) {
460
- return { status: 'VMI error', detailedMessage: vmiFailureCond.message };
461
- }
462
-
463
- if ((this.vmi || this.isVMCreated) && this.podResource) {
464
- // const podStatus = this.podResource.getPodStatus;
465
-
466
- // if (POD_STATUS_ALL_ERROR.includes(podStatus?.status)) {
467
- // return {
468
- // ...podStatus,
469
- // status: 'LAUNCHER_POD_ERROR',
470
- // pod: this.podResource,
471
- // };
472
- // }
473
- }
474
-
475
- return this?.vmi?.status?.phase;
476
- }
477
-
478
- get isRunning() {
479
- const conditions = get(this.vmi, 'status.conditions');
480
- const isVMIReady = findBy(conditions, 'type', 'Ready')?.status === 'True';
481
-
482
- if (this.vmi?.status?.phase === VMIPhase.Running && isVMIReady) {
483
- return { status: VMIPhase.Running };
484
- }
485
-
486
- return null;
487
- }
488
-
489
- get isNotReady() {
490
- const conditions = get(this.vmi, 'status.conditions');
491
- const VMIReadyCondition = findBy(conditions, 'type', 'Ready');
492
-
493
- if (VMIReadyCondition?.status === 'False' && this.vmi?.status?.phase === VMIPhase.Running) {
494
- return { status: NOT_READY };
495
- }
496
-
497
- return null;
498
- }
499
-
500
- get isBeingStopped() {
501
- if (this && !this.isVMExpectedRunning && this.isVMCreated && this.vmi?.status?.phase !== VMIPhase.Succeeded) {
502
- return { status: STOPPING };
503
- }
504
-
505
- return null;
506
- }
507
-
508
- get isStarting() {
509
- if (this.isVMExpectedRunning && this.isVMCreated) {
510
- // created but not yet ready
511
- if (this.podResource) {
512
- const podStatus = this.podResource.getPodStatus;
513
-
514
- if (!POD_STATUS_ALL_READY.includes(podStatus?.status)) {
515
- return {
516
- ...podStatus,
517
- status: 'Starting',
518
- message: STARTING_MESSAGE,
519
- detailedMessage: podStatus?.message,
520
- pod: this.podResource,
521
- };
522
- }
523
- }
524
-
525
- return {
526
- status: 'Starting', message: STARTING_MESSAGE, pod: this.podResource
527
- };
528
- }
529
-
530
- return null;
531
- }
532
-
533
- get otherState() {
534
- const state = (this.vmi && [VMIPhase.Scheduling, VMIPhase.Scheduled].includes(this.vmi?.status?.phase) && {
535
- status: 'Starting',
536
- message: STARTING_MESSAGE,
537
- }) ||
538
- (this.vmi && this.vmi.status?.phase === VMIPhase.Pending && {
539
- status: 'VMI_WAITING',
540
- message: VMI_WAITING_MESSAGE,
541
- }) ||
542
- (this.vmi && this.vmi?.status?.phase === VMIPhase.Failed && { status: 'VMI_ERROR' }) ||
543
- ((this.isVMExpectedRunning && !this.isVMCreated) && { status: 'Pending' }) ||
544
- { status: 'UNKNOWN' };
545
-
546
- return state;
547
- }
548
-
549
- get isVMCreated() {
550
- return !!this?.status?.created;
551
- }
552
-
553
- get getDataVolumeTemplates() {
554
- return get(this, 'spec.volumeClaimTemplates') === null ? [] : this.spec.volumeClaimTemplates;
555
- }
556
-
557
- restoreState(vmResource = this, id) {
558
- if (!id) {
559
- id = `${ this.metadata.namespace }/${ get(vmResource, `metadata.annotations."${ HCI_ANNOTATIONS.RESTORE_NAME }"`) }`;
560
- }
561
- const allRestore = this.$rootGetters['harvester/all'](HCI.RESTORE);
562
-
563
- const restoreResource = allRestore.find(O => O.id === id);
564
-
565
- if (!restoreResource) {
566
- return true;
567
- }
568
-
569
- return restoreResource?.isComplete;
570
- }
571
-
572
- get actualState() {
573
- if (!this.restoreState()) {
574
- return 'Restoring';
575
- }
576
-
577
- if (this?.metadata?.deletionTimestamp) {
578
- return 'Terminating';
579
- }
580
-
581
- if (!!this?.vmi?.migrationState && this.vmi.migrationState.status !== 'Failed') {
582
- return this.vmi.migrationState.status;
583
- }
584
-
585
- const state =
586
- this.isPaused?.status ||
587
- this.isVMError?.status ||
588
- this.isBeingStopped?.status ||
589
- this.isOff?.status ||
590
- this.isError?.status ||
591
- this.isRunning?.status ||
592
- this.isNotReady?.status ||
593
- this.isStarting?.status ||
594
- this.isWaitingForVMI?.state ||
595
- this.otherState?.status;
596
-
597
- return state;
598
- }
599
-
600
- get warningMessage() {
601
- const conditions = get(this, 'status.conditions');
602
- const vmFailureCond = findBy(conditions, 'type', 'Failure');
603
-
604
- if (vmFailureCond) {
605
- return {
606
- status: VM_ERROR,
607
- message: vmFailureCond.message,
608
- };
609
- }
610
-
611
- const vmiConditions = get(this.vmi, 'status.conditions');
612
- const vmiFailureCond = findBy(vmiConditions, 'type', 'Failure');
613
-
614
- if (vmiFailureCond) {
615
- return { status: 'VMI error', detailedMessage: vmiFailureCond.message };
616
- }
617
-
618
- if ((this.vmi || this.isVMCreated) && this.podResource) {
619
- const podStatus = this.podResource.getPodStatus;
620
-
621
- if (POD_STATUS_ALL_ERROR.includes(podStatus?.status)) {
622
- return {
623
- ...podStatus,
624
- status: 'LAUNCHER_POD_ERROR',
625
- pod: this.podResource,
626
- };
627
- }
628
- }
629
-
630
- return null;
631
- }
632
-
633
- get migrationMessage() {
634
- if (!!this?.vmi?.migrationState && this.vmi.migrationState.status === 'Failed') {
635
- return {
636
- ...this.actualState,
637
- message: this.t('harvester.modal.migration.failedMessage')
638
- };
639
- }
640
-
641
- return null;
642
- }
643
-
644
- get stateDisplay() {
645
- return this.actualState;
646
- }
647
-
648
- get stateColor() {
649
- const state = this.actualState;
650
-
651
- return colorForState(state);
652
- }
653
-
654
- get networkIps() {
655
- let networkData = '';
656
- const out = [];
657
- const arrVolumes = this.spec.template?.spec?.volumes || [];
658
-
659
- arrVolumes.forEach((V) => {
660
- if (V.cloudInitNoCloud) {
661
- networkData = V.cloudInitNoCloud.networkData;
662
- }
663
- });
664
-
665
- try {
666
- const newInitScript = load(networkData);
667
-
668
- if (newInitScript?.config && Array.isArray(newInitScript.config)) {
669
- const config = newInitScript.config;
670
-
671
- config.forEach((O) => {
672
- if (O?.subnets && Array.isArray(O.subnets)) {
673
- const subnets = O.subnets;
674
-
675
- subnets.forEach((S) => {
676
- if (S.address) {
677
- out.push(S.address);
678
- }
679
- });
680
- }
681
- });
682
- }
683
- } catch (err) {
684
-
685
- }
686
-
687
- return out;
688
- }
689
-
690
- get warningCount() {
691
- return this.resourcesStatus.warningCount;
692
- }
693
-
694
- get errorCount() {
695
- return this.resourcesStatus.errorCount;
696
- }
697
-
698
- get resourcesStatus() {
699
- const vmList = this.$rootGetters['harvester/all'](HCI.VM);
700
- let warningCount = 0;
701
- let errorCount = 0;
702
-
703
- vmList.forEach((vm) => {
704
- const status = vm.actualState;
705
-
706
- if (status === VM_ERROR) {
707
- errorCount += 1;
708
- } else if (status === 'Stopping' || status === 'Waiting' || status === 'Pending' || status === 'Starting' || status === 'Terminating') {
709
- warningCount += 1;
710
- }
711
- });
712
-
713
- return {
714
- warningCount,
715
- errorCount
716
- };
717
- }
718
-
719
- get volumeClaimTemplates() {
720
- let out = [];
721
-
722
- try {
723
- out = JSON.parse(this.metadata?.annotations?.[HCI_ANNOTATIONS.VOLUME_CLAIM_TEMPLATE]);
724
- } catch (e) {}
725
-
726
- return out;
727
- }
728
-
729
- get persistentVolumeClaimName() {
730
- const volumes = this.spec.template.spec.volumes || [];
731
-
732
- return volumes.map((O) => {
733
- return O?.persistentVolumeClaim?.claimName;
734
- }).filter( name => !!name);
735
- }
736
-
737
- get rootImageId() {
738
- let imageId = '';
739
- const pvcs = this.$rootGetters[`harvester/all`](PVC) || [];
740
-
741
- const volumes = this.spec.template.spec.volumes || [];
742
-
743
- const firstVolumeName = volumes[0]?.persistentVolumeClaim?.claimName;
744
- const isNoExistingVolume = this.volumeClaimTemplates.find((volume) => {
745
- return firstVolumeName === volume?.metadata?.name;
746
- });
747
-
748
- if (!isNoExistingVolume) {
749
- const existingVolume = pvcs.find(P => P.id === `${ this.metadata.namespace }/${ firstVolumeName }`);
750
-
751
- if (existingVolume) {
752
- return existingVolume?.metadata?.annotations?.['harvesterhci.io/imageId'];
753
- }
754
- }
755
-
756
- this.volumeClaimTemplates.find( (volume) => {
757
- imageId = volume?.metadata?.annotations?.['harvesterhci.io/imageId'];
758
-
759
- return !!imageId;
760
- });
761
-
762
- return imageId;
763
- }
764
-
765
- get restoreName() {
766
- return get(this, `metadata.annotations."${ HCI_ANNOTATIONS.RESTORE_NAME }"`) || '';
767
- }
768
-
769
- get customValidationRules() {
770
- const rules = [
771
- {
772
- nullable: false,
773
- path: 'metadata.name',
774
- required: true,
775
- minLength: 1,
776
- maxLength: 63,
777
- translationKey: 'harvester.fields.name'
778
- },
779
- {
780
- nullable: false,
781
- path: 'spec.template.spec.domain.cpu.cores',
782
- min: 1,
783
- required: true,
784
- translationKey: 'harvester.fields.cpu',
785
- },
786
- {
787
- nullable: false,
788
- path: 'spec.template.spec.domain.resources.limits.memory',
789
- required: true,
790
- translationKey: 'harvester.fields.memory',
791
- },
792
- {
793
- nullable: false,
794
- path: 'spec.template.spec',
795
- validators: ['vmNetworks'],
796
- },
797
- {
798
- nullable: false,
799
- path: 'spec',
800
- validators: [`vmDisks`],
801
- },
802
- ];
803
-
804
- return rules;
805
- }
806
-
807
- get attachNetwork() {
808
- const networks = this.spec?.template?.spec?.networks || [];
809
- const hasMultus = networks.find( N => N.multus);
810
-
811
- return !!hasMultus;
812
- }
813
-
814
- get memorySort() {
815
- const memory = this?.spec?.template?.spec?.domain?.resources?.requests?.memory || 0;
816
-
817
- const formatSize = parseSi(memory);
818
-
819
- return parseInt(formatSize);
820
- }
821
-
822
- get ingoreVMMessage() {
823
- const ignoreConditions = [{
824
- name: 'unavailable',
825
- error: false,
826
- vmState: this.actualState === PAUSED
827
- }];
828
-
829
- const state = this.metadata?.state;
830
-
831
- return ignoreConditions.find(condition => condition.name === state?.name && condition.error === state?.error && condition.vmState) ||
832
- IgnoreMessages.find(M => super.stateDescription?.includes(M)) ||
833
- this.isOff;
834
- }
835
-
836
- get stateDescription() {
837
- return this.ingoreVMMessage ? '' : super.stateDescription;
838
- }
839
-
840
- get displayMemory() {
841
- return this.spec.template.spec.domain.resources?.limits?.memory || this.spec.template.spec.domain.resources?.requests?.memory;
842
- }
843
-
844
- get isQemuInstalled() {
845
- const conditions = this.vmi?.status?.conditions || [];
846
- const qemu = conditions.find(cond => cond.type === AGENT_CONNECTED);
847
-
848
- return qemu?.status === 'True';
849
- }
850
- }