singleActions.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. import { mapGetters } from 'vuex'
  2. // import { Base64 } from 'js-base64'
  3. import qs from 'qs'
  4. import expectStatus from '@/constants/expectStatus'
  5. import { getDomainChangeOwnerAction, getSetPublicAction, getEnabledSwitchActions } from '@/utils/common/tableActions'
  6. import i18n from '@/locales'
  7. import { SMART_SSH_FORM_DECORATORS } from '@Compute/constants'
  8. import { canIpmiProbe } from '../utils/status'
  9. import { solWebConsole, jnlpConsole } from '../../../utils/webconsole'
  10. export default {
  11. destroyed () {
  12. this.manager = null
  13. },
  14. computed: {
  15. ...mapGetters(['userInfo', 'auth', 'common']),
  16. enableMFA () {
  17. return this.userInfo.enable_mfa && this.auth.auth.system_totp_on
  18. },
  19. enableWaterMark () {
  20. const { globalConfig = {} } = this.common
  21. const { enable_watermark = true } = globalConfig
  22. return enable_watermark
  23. },
  24. },
  25. created () {
  26. this.webconsoleManager = new this.$Manager('webconsole', 'v1')
  27. this.singleActions = [
  28. {
  29. label: i18n.t('compute.text_567'),
  30. permission: 'hosts_perform_login_info',
  31. actions: obj => {
  32. const ret = []
  33. if (obj.host_type === 'baremetal') {
  34. ret.push(solWebConsole(this.webconsoleManager, obj, this.openWebConsole, this.createDialog))
  35. }
  36. let ips = (obj.server_ips || '').split(',').filter(item => !!item)
  37. if (obj.access_ip) {
  38. ips = [obj.access_ip, ...ips]
  39. }
  40. const openWebConsole = (params) => {
  41. this.webconsoleManager.performAction(params).then(({ data }) => {
  42. const connectParams = qs.parse(data.connect_params)
  43. // 验证账号密码
  44. if (connectParams.is_need_login === 'true') {
  45. this.createDialog('SshAuthDialog', {
  46. manager: this.webconsoleManager,
  47. params,
  48. errorMsg: connectParams.login_error_message,
  49. data: { name: obj.name, ip: params.action },
  50. success: (data) => {
  51. this.openWebConsole(obj, data, 'ws')
  52. },
  53. })
  54. return
  55. }
  56. // 无需验证账号密码
  57. this.openWebConsole(obj, data, 'ws')
  58. })
  59. }
  60. const actionGenerator = ip => {
  61. return (_) => {
  62. const success = () => {
  63. const params = {
  64. action: ip,
  65. data: {},
  66. id: 'ssh',
  67. }
  68. openWebConsole(params)
  69. }
  70. if (this.enableMFA) {
  71. this.createDialog('SecretVertifyDialog', {
  72. success,
  73. })
  74. } else {
  75. success()
  76. }
  77. }
  78. }
  79. Array.from(new Set(ips)).forEach(ip => {
  80. const meta = () => ({ validate: true })
  81. ret.push({
  82. label: `SSH ${ip}`,
  83. action: actionGenerator(ip),
  84. meta,
  85. render: (obj, params, h) => {
  86. let styleObj = {
  87. padding: '0 10px',
  88. fontSize: '12px',
  89. }
  90. const isRunning = obj.status === 'running'
  91. if (!isRunning) {
  92. styleObj = {
  93. ...styleObj,
  94. cursor: 'not-allowed',
  95. color: 'rgba(0, 0, 0, 0.25)',
  96. }
  97. }
  98. const sshConnectHandle = () => {
  99. const success = () => {
  100. openWebConsole({
  101. action: ip,
  102. data: {},
  103. id: 'ssh',
  104. })
  105. }
  106. if (this.enableMFA) {
  107. this.createDialog('SecretVertifyDialog', {
  108. success,
  109. })
  110. } else {
  111. success()
  112. }
  113. }
  114. const sshSettingInfoHandle = () => {
  115. this.createDialog('SmartFormDialog', {
  116. title: i18n.t('compute.custom_ssh_connect', ['SSH']),
  117. data: [obj],
  118. callback: async (data) => {
  119. const pms = {
  120. action: ip,
  121. data: { port: data.port, username: data.username, password: data.password },
  122. id: 'ssh',
  123. }
  124. openWebConsole(pms)
  125. },
  126. decorators: SMART_SSH_FORM_DECORATORS,
  127. })
  128. }
  129. return <a-tooltip placement="left" title={!isRunning ? i18n.t('compute.text_1282') : ''}>
  130. <span style={styleObj} class='d-flex justify-content-between align-items-center'>
  131. <span onClick={isRunning ? sshConnectHandle : () => { }}>{`SSH ${ip}`}</span>
  132. {
  133. isRunning ? <span>
  134. <a-tooltip title={i18n.t('compute.custom_ssh_connect', ['SSH'])}>
  135. <a-icon class="ml-2" type="edit" onClick={isRunning ? sshSettingInfoHandle : () => { }} />
  136. </a-tooltip>
  137. </span> : null
  138. }
  139. </span>
  140. </a-tooltip>
  141. },
  142. })
  143. })
  144. ret.push({ ...jnlpConsole(new this.$Manager('hosts', 'v2'), obj, this.createDialog), permission: 'server_get_jnlp' })
  145. return ret
  146. },
  147. },
  148. {
  149. label: i18n.t('compute.text_352'),
  150. actions: (obj) => {
  151. return [
  152. ...getEnabledSwitchActions(Object.assign({}, this, { resource: 'physicalmachine' }), obj, ['hosts_perform_enable', 'hosts_perform_disable'], { resourceName: this.$t('dictionary.physicalmachine') }),
  153. {
  154. label: i18n.t('compute.text_541'),
  155. permission: 'hosts_perform_set_schedtag',
  156. action: () => {
  157. this.createDialog('HostsAdjustLabelDialog', {
  158. data: [obj],
  159. columns: this.columns,
  160. name: this.$t('dictionary.physicalmachine'),
  161. })
  162. },
  163. },
  164. {
  165. label: i18n.t('compute.perform_sync_status'),
  166. permission: 'hosts_perform_syncstatus',
  167. action: () => {
  168. this.onManager('performAction', {
  169. id: obj.id,
  170. steadyStatus: Object.values(expectStatus.host).flat(),
  171. managerArgs: {
  172. action: 'syncstatus',
  173. },
  174. })
  175. },
  176. meta: () => {
  177. if (obj.status === 'ready') {
  178. return {
  179. validate: false,
  180. tooltip: i18n.t('compute.text_850'),
  181. }
  182. }
  183. return {
  184. validate: true,
  185. }
  186. },
  187. },
  188. getDomainChangeOwnerAction(this, {
  189. name: this.$t('dictionary.physicalmachine'),
  190. resource: 'hosts',
  191. }, {
  192. permission: 'hosts_perform_change_owner',
  193. }),
  194. getSetPublicAction(this, {
  195. name: this.$t('dictionary.physicalmachine'),
  196. scope: 'domain',
  197. resource: 'hosts',
  198. }, {
  199. permission: 'hosts_perform_public',
  200. }),
  201. {
  202. label: i18n.t('compute.text_298'),
  203. permission: 'server_create',
  204. action: () => {
  205. let wire_id = ''
  206. if (obj.nic_info) {
  207. const arr = obj.nic_info.filter(item => {
  208. return item.nic_type !== 'ipmi' && item.wire_id
  209. })
  210. arr.map(item => {
  211. wire_id += `${item.wire_id},`
  212. })
  213. wire_id = wire_id.substr(0, wire_id.length - 1)
  214. }
  215. this.$router.push({
  216. path: '/baremetal/create',
  217. query: {
  218. id: obj.id,
  219. type: 'baremetal',
  220. zone_id: obj.zone_id,
  221. host_id: obj.id,
  222. region_id: obj.cloudregion_id,
  223. domain_id: obj.domain_id,
  224. wire_id,
  225. cloud_env: obj.cloud_env || 'onpremise',
  226. },
  227. })
  228. },
  229. meta: () => {
  230. if (!obj.is_baremetal) {
  231. return {
  232. validate: false,
  233. }
  234. }
  235. if (obj.host_type !== 'baremetal') {
  236. return {
  237. validate: false,
  238. }
  239. }
  240. if (obj.server_id) {
  241. return {
  242. validate: false,
  243. }
  244. }
  245. if (!obj.enabled) {
  246. return {
  247. validate: false,
  248. tooltip: i18n.t('compute.text_851'),
  249. }
  250. }
  251. if (['running', 'ready'].indexOf(obj.status) < 0) {
  252. return {
  253. validate: false,
  254. tooltip: i18n.t('compute.text_852'),
  255. }
  256. }
  257. return {
  258. validate: true,
  259. }
  260. },
  261. },
  262. {
  263. label: i18n.t('compute.text_828'),
  264. permission: 'hosts_perform_convert_hypervisor',
  265. action: () => {
  266. this.createDialog('HostsConvertDialog', {
  267. data: [obj],
  268. columns: this.columns,
  269. onManager: this.onManager,
  270. refresh: this.refresh,
  271. })
  272. },
  273. meta: () => {
  274. if (!obj.is_baremetal) {
  275. return {
  276. validate: false,
  277. }
  278. }
  279. if (obj.host_type !== 'baremetal') {
  280. return {
  281. validate: false,
  282. }
  283. }
  284. if (obj.server_id) {
  285. return {
  286. validate: false,
  287. }
  288. }
  289. if (!obj.enabled) {
  290. return {
  291. validate: false,
  292. tooltip: i18n.t('compute.text_851'),
  293. }
  294. }
  295. if (['running', 'ready'].indexOf(obj.status) < 0) {
  296. return {
  297. validate: false,
  298. tooltip: i18n.t('compute.text_852'),
  299. }
  300. }
  301. if (obj.spec && !obj.spec.disk) {
  302. return {
  303. validate: false,
  304. tooltip: i18n.t('compute.host_convert'),
  305. }
  306. }
  307. return {
  308. validate: true,
  309. }
  310. },
  311. },
  312. {
  313. label: i18n.t('compute.host_ipmi_probe'),
  314. permission: 'hosts_perform_ipmi_probe',
  315. action: () => {
  316. this.onManager('performAction', {
  317. id: obj.id,
  318. steadyStatus: Object.values(expectStatus.host).flat(),
  319. managerArgs: {
  320. action: 'ipmi-probe',
  321. },
  322. })
  323. },
  324. meta: () => ({ validate: canIpmiProbe(obj) }),
  325. },
  326. {
  327. label: i18n.t('compute.host_prepare'),
  328. permission: 'hosts_perform_prepare',
  329. action: () => {
  330. this.onManager('performAction', {
  331. id: obj.id,
  332. steadyStatus: Object.values(expectStatus.host).flat(),
  333. managerArgs: {
  334. action: 'prepare',
  335. },
  336. })
  337. },
  338. meta: () => ({ validate: obj.can_prepare }),
  339. },
  340. {
  341. label: i18n.t('compute.text_272'),
  342. permission: 'hosts_perform_start',
  343. action: () => {
  344. this.onManager('performAction', {
  345. id: obj.id,
  346. steadyStatus: Object.values(expectStatus.host).flat(),
  347. managerArgs: {
  348. action: 'start',
  349. },
  350. })
  351. },
  352. meta: () => {
  353. if (obj.server_id && obj.host_type === 'baremetal') {
  354. return {
  355. validate: false,
  356. }
  357. }
  358. return {
  359. validate: obj.status === 'ready',
  360. }
  361. },
  362. },
  363. {
  364. label: i18n.t('compute.text_273'),
  365. permission: 'hosts_perform_stop',
  366. action: () => {
  367. this.onManager('performAction', {
  368. id: obj.id,
  369. steadyStatus: Object.values(expectStatus.host).flat(),
  370. managerArgs: {
  371. action: 'stop',
  372. },
  373. })
  374. },
  375. meta: () => {
  376. if (!obj.is_baremetal) {
  377. return {
  378. validate: false,
  379. }
  380. }
  381. if (obj.server_id && obj.host_type === 'baremetal') {
  382. return {
  383. validate: false,
  384. }
  385. }
  386. if (obj.status !== 'running') {
  387. return {
  388. validate: false,
  389. }
  390. }
  391. return {
  392. validate: true,
  393. }
  394. },
  395. },
  396. {
  397. label: i18n.t('compute.text_550'),
  398. permission: 'hosts_perform_maintenance',
  399. action: () => {
  400. this.onManager('performAction', {
  401. id: obj.id,
  402. steadyStatus: Object.values(expectStatus.host).flat(),
  403. managerArgs: {
  404. action: 'maintenance',
  405. },
  406. })
  407. },
  408. meta: () => {
  409. if (obj.server) {
  410. return {
  411. validate: false,
  412. }
  413. }
  414. if (!obj.is_baremetal) {
  415. return {
  416. validate: false,
  417. }
  418. }
  419. if (!obj.server_id) {
  420. return {
  421. validate: false,
  422. }
  423. }
  424. if (obj.is_maintenance) {
  425. return {
  426. validate: false,
  427. }
  428. }
  429. if (['running', 'ready'].indexOf(obj.status) < 0) {
  430. return {
  431. validate: false,
  432. tooltip: i18n.t('compute.text_853'),
  433. }
  434. }
  435. return {
  436. validate: true,
  437. }
  438. },
  439. },
  440. {
  441. label: i18n.t('compute.text_559'),
  442. permission: 'hosts_perform_unmaintenance',
  443. action: () => {
  444. this.onManager('performAction', {
  445. id: obj.id,
  446. steadyStatus: Object.values(expectStatus.host).flat(),
  447. managerArgs: {
  448. action: 'unmaintenance',
  449. },
  450. })
  451. },
  452. meta: () => {
  453. if (obj.server) {
  454. return {
  455. validate: false,
  456. }
  457. }
  458. if (!obj.is_baremetal) {
  459. return {
  460. validate: false,
  461. }
  462. }
  463. if (!obj.server_id) {
  464. return {
  465. validate: false,
  466. }
  467. }
  468. if (!obj.is_maintenance) {
  469. return {
  470. validate: false,
  471. }
  472. }
  473. if (['running', 'ready'].indexOf(obj.status) < 0) {
  474. return {
  475. validate: false,
  476. tooltip: i18n.t('compute.text_853'),
  477. }
  478. }
  479. return {
  480. validate: true,
  481. }
  482. },
  483. },
  484. {
  485. label: i18n.t('compute.perform_delete'),
  486. permission: 'hosts_delete',
  487. action: () => {
  488. this.createDialog('DeleteResDialog', {
  489. name: this.$t('dictionary.physicalmachine'),
  490. vm: this,
  491. data: [obj],
  492. columns: this.columns,
  493. onManager: this.onManager,
  494. title: i18n.t('compute.perform_delete'),
  495. })
  496. },
  497. meta: () => {
  498. return {
  499. validate: this.$getDeleteResult(obj).validate,
  500. tooltip: this.$getDeleteResult(obj).validate ? '' : i18n.t('compute.text_854'),
  501. }
  502. },
  503. },
  504. ]
  505. },
  506. },
  507. ]
  508. },
  509. methods: {
  510. openWebConsole (obj, data, protocol) {
  511. this.$openWebConsole(data)
  512. },
  513. },
  514. }