Servers.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <template>
  2. <page-list
  3. :list="list"
  4. :columns="columns"
  5. :group-actions="groupActions"
  6. :single-actions="singleActions" />
  7. </template>
  8. <script>
  9. import PasswordFetcher from '@Compute/sections/PasswordFetcher'
  10. import { sizestr } from '@/utils/utils'
  11. import {
  12. getProjectTableColumn,
  13. getRegionTableColumn,
  14. getStatusTableColumn,
  15. getBrandTableColumn,
  16. getCopyWithContentTableColumn,
  17. getIpsTableColumn,
  18. getTagTableColumn,
  19. getNameDescriptionTableColumn,
  20. } from '@/utils/common/tableColumn'
  21. import SystemIcon from '@/sections/SystemIcon'
  22. import WindowsMixin from '@/mixins/windows'
  23. import ListMixin from '@/mixins/list'
  24. import { cloudEnabled, cloudUnabledTip } from '@Compute/views/vminstance/utils'
  25. import expectStatus from '@/constants/expectStatus'
  26. const commonUnabled = (value, statusArr = ['sched_fail', 'net_fail', 'disk_fail']) => {
  27. return statusArr.includes(value.status)
  28. }
  29. export default {
  30. name: 'ServersListForGpuSidePage',
  31. mixins: [WindowsMixin, ListMixin],
  32. props: {
  33. data: {
  34. type: Object,
  35. required: true,
  36. },
  37. },
  38. data () {
  39. return {
  40. list: this.$list.createList(this, {
  41. id: 'ServersListForGpuSidePage',
  42. resource: 'servers',
  43. getParams: this.getParam,
  44. filterOptions: {
  45. name: {
  46. label: this.$t('compute.text_228'),
  47. filter: true,
  48. formatter: val => {
  49. return `name.contains("${val}")`
  50. },
  51. },
  52. },
  53. steadyStatus: Object.values(expectStatus.server).flat(),
  54. }),
  55. columns: [
  56. getNameDescriptionTableColumn({
  57. vm: this,
  58. hideField: true,
  59. addLock: true,
  60. addBackup: true,
  61. slotCallback: row => {
  62. return (
  63. <side-page-trigger onTrigger={ () => this.sidePageTriggerHandle(row.id, 'VmInstanceSidePage') }>{ row.name }</side-page-trigger>
  64. )
  65. },
  66. }),
  67. getTagTableColumn({ onManager: this.onManager, resource: 'server', columns: () => this.columns }),
  68. getIpsTableColumn({ field: 'ip', title: 'IP' }),
  69. {
  70. field: 'instance_type',
  71. title: this.$t('compute.text_295'),
  72. showOverflow: 'ellipsis',
  73. minWidth: 120,
  74. sortable: true,
  75. slots: {
  76. default: ({ row }) => {
  77. const ret = []
  78. if (row.instance_type) {
  79. ret.push(<div class='text-truncate' style={{ color: '#0A1F44' }}>{ row.instance_type }</div>)
  80. }
  81. const config = row.vcpu_count + 'C' + sizestr(row.vmem_size, 'M', 1024) + (row.disk ? sizestr(row.disk, 'M', 1024) : '')
  82. return ret.concat(<div class='text-truncate' style={{ color: '#53627C' }}>{ config }</div>)
  83. },
  84. },
  85. },
  86. {
  87. field: 'os_type',
  88. title: this.$t('table.title.os'),
  89. width: 50,
  90. slots: {
  91. default: ({ row }) => {
  92. let name = (row.metadata && row.metadata.os_distribution) ? row.metadata.os_distribution : row.os_type || ''
  93. if (name.includes('Windows') || name.includes('windows')) {
  94. name = 'Windows'
  95. }
  96. const version = (row.metadata && row.metadata.os_version) ? `${row.metadata.os_version}` : ''
  97. const tooltip = (version.includes(name) ? version : `${name} ${version}`) || this.$t('compute.text_339') // 去重
  98. return [
  99. <SystemIcon tooltip={ tooltip } name={ name } />,
  100. ]
  101. },
  102. },
  103. },
  104. {
  105. field: 'password',
  106. title: this.$t('compute.text_340'),
  107. width: 50,
  108. slots: {
  109. default: ({ row }) => {
  110. return [<PasswordFetcher serverId={ row.id } resourceType='servers' />]
  111. },
  112. },
  113. },
  114. {
  115. field: 'secgroups',
  116. title: this.$t('compute.text_105'),
  117. width: 80,
  118. showOverflow: 'ellipsis',
  119. formatter: ({ cellValue = [] }) => {
  120. return cellValue.map(item => item.name).join(',')
  121. },
  122. },
  123. {
  124. field: 'billing_type',
  125. title: this.$t('compute.text_498'),
  126. width: 100,
  127. showOverflow: 'ellipsis',
  128. slots: {
  129. default: ({ row }) => {
  130. const ret = []
  131. if (row.billing_type === 'postpaid') {
  132. ret.push(<div style={{ color: '#0A1F44' }}>{this.$t('billingType.postpaid')}</div>)
  133. } else if (row.billing_type === 'prepaid') {
  134. ret.push(<div style={{ color: '#0A1F44' }}>{this.$t('billingType.postpaid')}</div>)
  135. }
  136. if (row.expired_at) {
  137. const dateArr = this.$moment(row.expired_at).fromNow().split(' ')
  138. const date = dateArr.join(' ')
  139. const seconds = this.$moment(row.expired_at).diff(new Date()) / 1000
  140. const textColor = seconds / 24 / 60 / 60 < 7 ? '#DD2727' : '#53627C'
  141. const text = seconds < 0 ? this.$t('compute.text_499') : this.$t('compute.text_500', [date])
  142. ret.push(<div style={{ color: textColor }}>{ text }</div>)
  143. }
  144. return ret
  145. },
  146. },
  147. },
  148. getStatusTableColumn({ statusModule: 'server' }),
  149. getCopyWithContentTableColumn({ field: 'vpc', title: 'VPC' }),
  150. getCopyWithContentTableColumn({ field: 'host', title: this.$t('compute.text_111'), sortable: true }),
  151. getProjectTableColumn(),
  152. getBrandTableColumn(),
  153. getRegionTableColumn(),
  154. ],
  155. groupActions: [
  156. {
  157. label: this.$t('compute.text_483', [this.$t('dictionary.server')]),
  158. permission: 'server_perform_attach_isolated_device',
  159. action: obj => {
  160. this.createDialog('GpuAttachServerDialog', {
  161. data: [this.data],
  162. title: this.$t('compute.text_483', [this.$t('dictionary.server')]),
  163. columns: this.columns,
  164. refresh: this.refresh,
  165. })
  166. },
  167. meta: obj => {
  168. const ret = { validate: true }
  169. if (this.data.dev_type === 'NIC') {
  170. ret.validate = false
  171. ret.tooltip = this.$t('compute.sriov_device_nic_notsupport')
  172. return ret
  173. }
  174. if (this.data.guest_id) {
  175. ret.validate = false
  176. return ret
  177. }
  178. return ret
  179. },
  180. },
  181. ],
  182. singleActions: [
  183. {
  184. label: this.$t('compute.text_272'),
  185. permission: 'server_perform_start',
  186. action: (obj) => {
  187. this.list.onManager('performAction', {
  188. steadyStatus: 'running',
  189. id: obj.id,
  190. managerArgs: {
  191. action: 'start',
  192. },
  193. })
  194. },
  195. meta: (obj) => {
  196. return {
  197. validate: obj.status === 'ready' && !commonUnabled(obj),
  198. }
  199. },
  200. },
  201. {
  202. label: this.$t('compute.text_273'),
  203. permission: 'server_perform_stop',
  204. action: (obj) => {
  205. this.createDialog('VmShutDownDialog', {
  206. data: [obj],
  207. columns: this.columns,
  208. list: this.list,
  209. })
  210. },
  211. meta: (obj) => {
  212. return {
  213. validate: obj.status === 'running' && !commonUnabled(obj),
  214. }
  215. },
  216. },
  217. {
  218. label: this.$t('compute.text_260', [this.$t('compute.text_113')]),
  219. permission: 'server_perform_detach_isolated_device',
  220. action: obj => {
  221. this.createDialog('DetachGpuDialog', {
  222. data: [obj],
  223. title: this.$t('compute.text_485', [this.$t('compute.text_113')]),
  224. columns: this.columns,
  225. refresh: this.refresh,
  226. name: this.$t('dictionary.server'),
  227. device: this.data,
  228. })
  229. },
  230. meta: obj => {
  231. const ret = { validate: true }
  232. if (this.data.dev_type === 'NIC') {
  233. ret.validate = false
  234. ret.tooltip = this.$t('compute.sriov_device_nic_notsupport')
  235. return ret
  236. }
  237. if (obj.status !== 'ready' && obj.status !== 'running') {
  238. ret.validate = false
  239. ret.tooltip = this.$t('compute.text_489', [this.$t('compute.text_113')])
  240. return ret
  241. }
  242. ret.validate = cloudEnabled('acttachGpu', obj)
  243. ret.tooltip = cloudUnabledTip('acttachGpu', obj)
  244. return ret
  245. },
  246. },
  247. ],
  248. }
  249. },
  250. watch: {
  251. 'data.guest_id': {
  252. handler (val) {
  253. this.list.fetchData()
  254. },
  255. },
  256. },
  257. created () {
  258. this.initSidePageTab('detail')
  259. this.list.fetchData()
  260. },
  261. methods: {
  262. refresh () {
  263. this.$bus.$emit('gpu-sidepage-refresh')
  264. },
  265. getParam () {
  266. return {
  267. 'filter.0': `id.equals(${this.data.guest_id})`,
  268. 'filter.1': 'hypervisor.notin(baremetal,container,pod)',
  269. }
  270. },
  271. },
  272. }
  273. </script>