singleActions.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. import { mapGetters } from 'vuex'
  2. // import { Base64 } from 'js-base64'
  3. import qs from 'qs'
  4. import { disableDeleteAction } from '@/utils/common/tableActions'
  5. import expectStatus from '@/constants/expectStatus'
  6. import i18n from '@/locales'
  7. import { SMART_SSH_FORM_DECORATORS } from '@Compute/constants'
  8. import { commonUnabled, cloudEnabled, cloudUnabledTip } from '../../vminstance/utils'
  9. import { solWebConsole, jnlpConsole } from '../../../utils/webconsole'
  10. import { hostServerActions } from '../../../utils/hostActions'
  11. export default {
  12. computed: {
  13. ...mapGetters(['isAdminMode', 'isDomainMode', 'userInfo', 'auth', 'common']),
  14. enableMFA () {
  15. return this.userInfo.enable_mfa && this.auth.auth.system_totp_on
  16. },
  17. enableWaterMark () {
  18. const { globalConfig = {} } = this.common
  19. const { enable_watermark = true } = globalConfig
  20. return enable_watermark
  21. },
  22. },
  23. destroyed () {
  24. this.webconsoleManager = null
  25. },
  26. created () {
  27. this.webconsoleManager = new this.$Manager('webconsole', 'v1')
  28. this.singleActions = [
  29. {
  30. label: i18n.t('compute.text_341'),
  31. permission: 'server_get_vnc',
  32. actions: obj => {
  33. let ret = []
  34. ret.push(solWebConsole(this.webconsoleManager, obj, this.openWebConsole, this.createDialog))
  35. const openWebConsole = (params) => {
  36. this.webconsoleManager.performAction(params).then(({ data }) => {
  37. const connectParams = qs.parse(data.connect_params)
  38. // 验证账号密码
  39. if (connectParams.is_need_login === 'true') {
  40. this.createDialog('SshAuthDialog', {
  41. manager: this.webconsoleManager,
  42. params,
  43. errorMsg: connectParams.login_error_message,
  44. data: { name: obj.name, ip: params.action, id: obj.id, resource: 'servers' },
  45. success: (data) => {
  46. this.openWebConsole(obj, data, 'ws')
  47. },
  48. })
  49. return
  50. }
  51. // 无需验证账号密码
  52. this.openWebConsole(obj, data, 'ws')
  53. })
  54. }
  55. const mapIpActions = (ipArr, type) => {
  56. if (!['IP SSH', 'EIP SSH'].includes(type)) throw Error(i18n.t('compute.text_343'))
  57. const options = []
  58. ipArr.forEach(v => {
  59. const meta = () => {
  60. const ret = {
  61. validate: true,
  62. tooltip: null,
  63. }
  64. if (obj.os_type === 'Windows') {
  65. ret.tooltip = i18n.t('compute.text_344')
  66. ret.validate = false
  67. return ret
  68. }
  69. if (obj.provider === 'OneCloud') {
  70. ret.validate = obj.power_states === 'on'
  71. ret.tooltip = obj.power_states === 'on' ? '' : i18n.t('compute.power_states_check_tip', [i18n.t('compute.text_92'), `【${i18n.t('compute.text_574')}】`])
  72. } else {
  73. ret.validate = obj.power_states === 'unknown' ? cloudEnabled(type, obj) : obj.power_states === 'on'
  74. ret.tooltip = obj.power_states === 'unknown' ? cloudUnabledTip(type, obj) : (obj.power_states === 'on' ? '' : i18n.t('compute.power_states_check_tip', [i18n.t('compute.text_92'), `【${i18n.t('compute.text_574')}】`]))
  75. if (cloudEnabled(type, obj) === false) {
  76. ret.validate = false
  77. ret.tooltip = cloudUnabledTip(type, obj)
  78. }
  79. }
  80. return ret
  81. }
  82. options.push({
  83. label: `SSH ${v}`,
  84. action: () => {
  85. const success = () => {
  86. const params = {
  87. id: 'ssh',
  88. action: v,
  89. data: {},
  90. }
  91. openWebConsole(params)
  92. }
  93. if (this.enableMFA) {
  94. this.createDialog('SecretVertifyDialog', {
  95. success,
  96. })
  97. } else {
  98. success()
  99. }
  100. },
  101. meta,
  102. render: (obj, params, h) => {
  103. let styleObj = {
  104. padding: '0 10px',
  105. fontSize: '12px',
  106. }
  107. const isRunning = obj.power_states === 'on'
  108. if (!isRunning) {
  109. styleObj = {
  110. ...styleObj,
  111. cursor: 'not-allowed',
  112. color: 'rgba(0, 0, 0, 0.25)',
  113. }
  114. }
  115. const sshConnectHandle = () => {
  116. const success = () => {
  117. openWebConsole({
  118. action: v,
  119. data: { },
  120. id: 'ssh',
  121. })
  122. }
  123. if (this.enableMFA) {
  124. this.createDialog('SecretVertifyDialog', {
  125. success,
  126. })
  127. } else {
  128. success()
  129. }
  130. }
  131. const sshSettingInfoHandle = () => {
  132. this.createDialog('SmartFormDialog', {
  133. title: i18n.t('compute.custom_ssh_connect', ['SSH']),
  134. data: [obj],
  135. callback: async (data) => {
  136. const pms = {
  137. action: v,
  138. data: { port: data.port, username: data.username, password: data.password },
  139. id: 'ssh',
  140. }
  141. openWebConsole(pms)
  142. },
  143. decorators: SMART_SSH_FORM_DECORATORS,
  144. })
  145. }
  146. return <a-tooltip placement="left" title={!isRunning ? meta().tooltip : ''}>
  147. <span style={styleObj} class='d-flex justify-content-between align-items-center'>
  148. <span onClick={isRunning ? sshConnectHandle : () => { }}>{`SSH ${v}`}</span>
  149. {
  150. isRunning ? <span>
  151. <a-tooltip title={i18n.t('compute.custom_ssh_connect', ['SSH'])}>
  152. <a-icon class="ml-2" type="edit" onClick={isRunning ? sshSettingInfoHandle : () => { }} />
  153. </a-tooltip>
  154. </span> : null
  155. }
  156. </span>
  157. </a-tooltip>
  158. },
  159. })
  160. // options.push({
  161. // label: i18n.t('compute.text_345', [v]),
  162. // action: () => {
  163. // this.createDialog('SmartFormDialog', {
  164. // title: i18n.t('compute.text_346'),
  165. // data: [obj],
  166. // callback: async (data) => {
  167. // const success = () => {
  168. // const params = {
  169. // action: v,
  170. // data,
  171. // id: 'ssh',
  172. // }
  173. // openWebConsole(params)
  174. // }
  175. // if (this.enableMFA) {
  176. // this.createDialog('SecretVertifyDialog', {
  177. // success,
  178. // })
  179. // } else {
  180. // success()
  181. // }
  182. // },
  183. // decorators: {
  184. // port: [
  185. // 'port',
  186. // {
  187. // validateFirst: true,
  188. // rules: [
  189. // { required: true, message: i18n.t('compute.text_347') },
  190. // {
  191. // validator: (rule, value, _callback) => {
  192. // const num = parseFloat(value)
  193. // if (!/^\d+$/.test(value) || !num || num > 65535) {
  194. // _callback(i18n.t('compute.text_348'))
  195. // }
  196. // _callback()
  197. // },
  198. // },
  199. // ],
  200. // },
  201. // {
  202. // label: i18n.t('compute.text_349'),
  203. // placeholder: i18n.t('compute.text_350'),
  204. // },
  205. // ],
  206. // },
  207. // })
  208. // },
  209. // meta,
  210. // })
  211. })
  212. return options
  213. }
  214. let eips = (obj.eip || '').split(',').filter(item => !!item)
  215. let ips = (obj.ips || '').split(',').filter(item => !!item)
  216. eips = eips.length ? mapIpActions(eips, 'EIP SSH') : []
  217. ips = ips.length ? mapIpActions(ips, 'IP SSH') : []
  218. ret = ret.concat(eips).concat(ips)
  219. ret.push({ ...jnlpConsole(new this.$Manager('servers', 'v2'), obj, this.createDialog), permission: 'server_get_jnlp' })
  220. return ret
  221. },
  222. meta: (obj) => {
  223. let ret = {
  224. validate: true,
  225. tooltip: null,
  226. }
  227. ret = this.$isValidateResourceLock(obj)
  228. return ret
  229. },
  230. },
  231. {
  232. label: i18n.t('compute.text_352'),
  233. actions: (obj) => {
  234. return [
  235. {
  236. label: i18n.t('compute.text_353'),
  237. submenus: hostServerActions(this.onManager, obj, this, false),
  238. },
  239. {
  240. label: i18n.t('compute.text_356'),
  241. submenus: [
  242. {
  243. label: i18n.t('compute.text_357'),
  244. permission: 'server_perform_rebuild_root',
  245. action: () => {
  246. this.createDialog('VmRebuildRootDialog', {
  247. data: [obj],
  248. columns: this.columns,
  249. onManager: this.onManager,
  250. })
  251. },
  252. meta: () => {
  253. const ret = {
  254. validate: true,
  255. tooltip: null,
  256. }
  257. if (obj.metadata.is_fake_baremetal_server === 'true') {
  258. ret.tooltip = i18n.t('compute.tooltip.check_fake_baremetal_server')
  259. ret.validate = false
  260. return ret
  261. }
  262. if (obj.status !== 'ready' && obj.status !== 'admin') {
  263. ret.tooltip = i18n.t('compute.text_358')
  264. ret.validate = false
  265. return ret
  266. }
  267. if (commonUnabled(obj)) return ret
  268. ret.validate = cloudEnabled('rebuildRoot', { ...obj, brand: 'baremetal' })
  269. ret.tooltip = cloudUnabledTip('rebuildRoot', { ...obj, brand: 'baremetal' })
  270. return ret
  271. },
  272. },
  273. {
  274. label: i18n.t('compute.perform_sync_status'),
  275. permission: 'server_perform_syncstatus',
  276. action: () => {
  277. this.onManager('performAction', {
  278. steadyStatus: Object.values(expectStatus.server).flat(),
  279. id: obj.id,
  280. managerArgs: {
  281. action: 'syncstatus',
  282. },
  283. })
  284. },
  285. },
  286. {
  287. label: this.$t('compute.perform_change_owner', [this.$t('dictionary.project')]),
  288. permission: 'server_perform_change_owner',
  289. action: () => {
  290. this.createDialog('ChangeOwenrDialog', {
  291. data: [obj],
  292. columns: this.columns,
  293. onManager: this.onManager,
  294. resource: 'servers',
  295. })
  296. },
  297. meta: () => {
  298. const ret = {
  299. validate: false,
  300. tooltip: null,
  301. }
  302. if (commonUnabled(obj)) return ret
  303. ret.validate = true
  304. return ret
  305. },
  306. },
  307. {
  308. label: i18n.t('compute.text_359'),
  309. permission: 'server_create',
  310. action: () => {
  311. this.createDialog('VmCloneDialog', {
  312. data: [obj],
  313. columns: this.columns,
  314. onManager: this.onManager,
  315. type: 'baremetal',
  316. })
  317. },
  318. meta: () => {
  319. const ret = {
  320. validate: true,
  321. tooltip: null,
  322. }
  323. if (obj.metadata.is_fake_baremetal_server === 'true') {
  324. ret.tooltip = i18n.t('compute.tooltip.check_fake_baremetal_server')
  325. ret.validate = false
  326. return ret
  327. }
  328. return ret
  329. },
  330. },
  331. ],
  332. },
  333. {
  334. label: i18n.t('compute.text_360'),
  335. submenus: [
  336. {
  337. label: i18n.t('compute.text_276'),
  338. permission: 'server_perform_deploy',
  339. action: () => {
  340. this.createDialog('VmResetPasswordDialog', {
  341. data: [obj],
  342. columns: this.columns,
  343. onManager: this.onManager,
  344. })
  345. },
  346. meta: () => {
  347. const ret = {
  348. validate: true,
  349. tooltip: null,
  350. }
  351. if (obj.metadata.is_fake_baremetal_server === 'true') {
  352. ret.tooltip = i18n.t('compute.tooltip.check_fake_baremetal_server')
  353. ret.validate = false
  354. return ret
  355. }
  356. if (obj.keypair_id && obj.keypair_id.toLowerCase() !== 'none') {
  357. ret.tooltip = i18n.t('compute.text_277')
  358. ret.validate = false
  359. return ret
  360. }
  361. if (commonUnabled(obj)) return ret
  362. ret.validate = cloudEnabled('resetPassword', { ...obj, brand: 'baremetal' })
  363. ret.tooltip = cloudUnabledTip('resetPassword', { ...obj, brand: 'baremetal' })
  364. return ret
  365. },
  366. },
  367. {
  368. label: i18n.t('compute.text_361'),
  369. permission: 'server_perform_deploy',
  370. action: () => {
  371. this.createDialog('VmBindKeypairDialog', {
  372. data: [obj],
  373. columns: this.columns,
  374. onManager: this.onManager,
  375. })
  376. },
  377. meta: () => {
  378. const ret = {
  379. validate: true,
  380. tooltip: null,
  381. }
  382. if (obj.metadata.is_fake_baremetal_server === 'true') {
  383. ret.tooltip = i18n.t('compute.tooltip.check_fake_baremetal_server')
  384. ret.validate = false
  385. return ret
  386. }
  387. if (obj.os_type === 'Windows') {
  388. ret.tooltip = i18n.t('compute.text_362')
  389. ret.validate = false
  390. return ret
  391. }
  392. if (obj.keypair) {
  393. ret.tooltip = i18n.t('compute.text_363')
  394. ret.validate = false
  395. return ret
  396. }
  397. if (commonUnabled(obj)) return ret
  398. ret.validate = cloudEnabled('bindKeyPair', obj)
  399. ret.tooltip = cloudUnabledTip('bindKeyPair', obj)
  400. return ret
  401. },
  402. },
  403. {
  404. label: i18n.t('compute.text_364'),
  405. permission: 'server_perform_deploy',
  406. action: () => {
  407. this.createDialog('VmUnbindKeypairDialog', {
  408. data: [obj],
  409. columns: this.columns,
  410. onManager: this.onManager,
  411. })
  412. },
  413. meta: () => {
  414. const ret = {
  415. validate: true,
  416. tooltip: null,
  417. }
  418. if (obj.metadata.is_fake_baremetal_server === 'true') {
  419. ret.tooltip = i18n.t('compute.tooltip.check_fake_baremetal_server')
  420. ret.validate = false
  421. return ret
  422. }
  423. if (obj.os_type === 'Windows') {
  424. ret.tooltip = i18n.t('compute.text_362')
  425. ret.validate = false
  426. return ret
  427. }
  428. if (!obj.keypair) {
  429. ret.tooltip = i18n.t('compute.text_365')
  430. ret.validate = false
  431. return ret
  432. }
  433. if (commonUnabled(obj)) return ret
  434. ret.validate = cloudEnabled('unBindKeyPair', obj)
  435. ret.tooltip = cloudUnabledTip('unBindKeyPair', obj)
  436. return ret
  437. },
  438. },
  439. ],
  440. },
  441. {
  442. label: i18n.t('compute.text_96'),
  443. submenus: [
  444. {
  445. label: i18n.t('compute.text_366'),
  446. permission: 'server_perform_insertiso',
  447. action: () => {
  448. this.createDialog('VmMountIsoDialog', {
  449. data: [obj],
  450. columns: this.columns,
  451. onManager: this.onManager,
  452. refresh: this.refresh,
  453. })
  454. },
  455. meta: () => {
  456. return {
  457. validate: obj.cdrom_support && !obj.cdrom,
  458. }
  459. },
  460. },
  461. {
  462. label: i18n.t('compute.text_367'),
  463. permission: 'server_perform_ejectiso',
  464. action: () => {
  465. this.createDialog('VmUnmountIsoDialog', {
  466. data: [obj],
  467. columns: this.columns,
  468. onManager: this.onManager,
  469. refresh: this.refresh,
  470. })
  471. },
  472. meta: () => {
  473. return {
  474. validate: obj.cdrom_support && obj.cdrom,
  475. }
  476. },
  477. },
  478. ],
  479. },
  480. {
  481. label: i18n.t('compute.perform_delete'),
  482. submenus: [
  483. disableDeleteAction(this),
  484. {
  485. label: i18n.t('compute.perform_delete'),
  486. permission: 'server_delete',
  487. action: () => {
  488. this.createDialog('DeleteResDialog', {
  489. vm: this,
  490. data: [obj],
  491. columns: this.columns,
  492. onManager: this.onManager,
  493. title: i18n.t('compute.perform_delete'),
  494. success: () => {
  495. this.destroySidePages()
  496. },
  497. })
  498. },
  499. meta: () => {
  500. const ret = {
  501. validate: false,
  502. tooltip: null,
  503. }
  504. if (this.isAdminMode && obj.billing_type === 'prepaid') {
  505. ret.tooltip = i18n.t('compute.text_285')
  506. return ret
  507. }
  508. if (!obj.can_delete) {
  509. ret.tooltip = i18n.t('compute.text_284')
  510. return ret
  511. }
  512. ret.validate = true
  513. return ret
  514. },
  515. },
  516. ],
  517. },
  518. ]
  519. },
  520. meta: (obj) => {
  521. let ret = {
  522. validate: true,
  523. tooltip: null,
  524. }
  525. ret = this.$isValidateResourceLock(obj)
  526. return ret
  527. },
  528. },
  529. ]
  530. },
  531. methods: {
  532. openWebConsole (obj, data, protocol) {
  533. this.$openWebConsole(data)
  534. },
  535. },
  536. }