TapFlowCreate.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <template>
  2. <base-dialog @cancel="cancelDialog">
  3. <div slot="header">{{$t('compute.add_tap_flow')}}</div>
  4. <div slot="body">
  5. <a-form
  6. v-bind="formItemLayout"
  7. :form="form.fc">
  8. <a-form-item :label="$t('compute.text_228')">
  9. <a-input :placeholder="$t('validator.serverCreateName')" v-decorator="decorators.name" />
  10. </a-form-item>
  11. <a-form-item :label="$t('common.description')">
  12. <a-input :placeholder="$t('scope.text_55')" v-decorator="decorators.description" />
  13. </a-form-item>
  14. <a-form-item :label="$t('compute.tap')">
  15. {{params.tapService.name}}
  16. </a-form-item>
  17. <a-form-item :label="$t('compute.tap_direction')">
  18. <a-radio-group v-decorator="decorators.direction">
  19. <a-radio-button value="BOTH">{{ $t('compute.direction_both') }}</a-radio-button>
  20. <a-radio-button value="IN">{{ $t('compute.direction_in') }}</a-radio-button>
  21. <a-radio-button value="OUT">{{ $t('compute.direction_out') }}</a-radio-button>
  22. </a-radio-group>
  23. </a-form-item>
  24. <a-form-item :label="$t('compute.text_175')">
  25. <a-radio-group v-decorator="decorators.type">
  26. <a-radio-button value="vnic">{{ $t('compute.vnic') }}</a-radio-button>
  27. <a-radio-button value="vswitch">{{ $t('compute.vswitch') }}</a-radio-button>
  28. </a-radio-group>
  29. </a-form-item>
  30. <template v-if="serverType === 'vswitch'">
  31. <a-form-item :label="$t('compute.text_111')">
  32. <base-select
  33. v-decorator="decorators.host_id"
  34. class="w-100"
  35. remote
  36. resource="hosts"
  37. version="v1"
  38. needParams
  39. :params="hostParams"
  40. isDefaultSelect
  41. :select-props="{ placeholder: $t('compute.text_148', [$t('compute.text_111')]) }"
  42. @update:item="hostChange" />
  43. </a-form-item>
  44. <a-form-item :label="$t('compute.text_844')">
  45. <base-select
  46. v-decorator="decorators.wire_id"
  47. class="w-100"
  48. :options="hostWires"
  49. idKey="wire_id"
  50. nameKey="wire"
  51. isDefaultSelect
  52. :select-props="{ placeholder: $t('compute.text_148', [$t('compute.text_844')]) }" />
  53. </a-form-item>
  54. <a-form-item :label="$t('compute.vlan_id')">
  55. <a-input-number :max="4095" :step="1" :min="0" v-decorator="decorators.vlan_id" />
  56. </a-form-item>
  57. </template>
  58. <template v-else>
  59. <a-form-item :label="$t('compute.text_91')">
  60. <base-select
  61. v-decorator="decorators.guest_id"
  62. class="w-100"
  63. remote
  64. resource="servers"
  65. version="v1"
  66. needParams
  67. :params="serverParams"
  68. isDefaultSelect
  69. :select-props="{ placeholder: $t('compute.text_148', [$t('compute.text_91')]) }"
  70. @update:item="serverChange" />
  71. </a-form-item>
  72. <a-form-item :label="$t('compute.vm_mac')">
  73. <base-select
  74. v-decorator="decorators.mac_addr"
  75. class="w-100"
  76. :options="vmMac"
  77. idKey="mac"
  78. nameKey="macLabel"
  79. isDefaultSelect
  80. :select-props="{ placeholder: $t('compute.text_148', [$t('compute.vm_mac')]) }" />
  81. </a-form-item>
  82. </template>
  83. </a-form>
  84. </div>
  85. <div slot="footer">
  86. <a-button type="primary" @click="handleConfirm" :loading="loading">{{ $t('dialog.ok') }}</a-button>
  87. <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
  88. </div>
  89. </base-dialog>
  90. </template>
  91. <script>
  92. import { mapGetters } from 'vuex'
  93. import validateForm from '@/utils/validate'
  94. import DialogMixin from '@/mixins/dialog'
  95. import WindowsMixin from '@/mixins/windows'
  96. export default {
  97. name: 'TapFlowCreateDialog',
  98. mixins: [DialogMixin, WindowsMixin],
  99. data () {
  100. return {
  101. loading: false,
  102. form: {
  103. fc: this.$form.createForm(this, {
  104. onValuesChange: this.handleValuesChange,
  105. }),
  106. fd: {
  107. type: 'vnic',
  108. },
  109. },
  110. currentHost: {},
  111. currentServer: {},
  112. decorators: {
  113. name: [
  114. 'name',
  115. {
  116. initialValue: '',
  117. validateTrigger: ['change', 'blur'],
  118. validateFirst: true,
  119. rules: [
  120. { required: true, message: this.$t('compute.text_210') },
  121. { validator: validateForm('serverCreateName') },
  122. ],
  123. },
  124. ],
  125. description: [
  126. 'description',
  127. ],
  128. direction: [
  129. 'direction',
  130. { initialValue: 'BOTH' },
  131. ],
  132. type: [
  133. 'type',
  134. {
  135. initialValue: 'vnic',
  136. },
  137. ],
  138. host_id: [
  139. 'host_id',
  140. {
  141. rules: [{ required: true, message: this.$t('compute.text_148', [this.$t('compute.text_111')]) }],
  142. },
  143. ],
  144. wire_id: [
  145. 'wire_id',
  146. {
  147. rules: [{ required: true, message: this.$t('compute.text_148', [this.$t('compute.text_844')]) }],
  148. },
  149. ],
  150. vlan_id: ['vlan_id'],
  151. guest_id: [
  152. 'guest_id',
  153. {
  154. rules: [{ required: true, message: this.$t('compute.text_148', [this.$t('compute.text_91')]) }],
  155. },
  156. ],
  157. mac_addr: [
  158. 'mac_addr',
  159. {
  160. rules: [{ required: true, message: this.$t('compute.text_148', [this.$t('compute.vm_mac')]) }],
  161. },
  162. ],
  163. },
  164. formItemLayout: {
  165. wrapperCol: {
  166. span: 18,
  167. },
  168. labelCol: {
  169. span: 4,
  170. },
  171. },
  172. }
  173. },
  174. computed: {
  175. ...mapGetters(['isAdminMode', 'isDomainMode', 'scope']),
  176. serverType () {
  177. return this.form.fd.type
  178. },
  179. hostWires () {
  180. const { nic_info = [] } = this.currentHost
  181. return nic_info.filter(item => item.wire_id)
  182. },
  183. vmMac () {
  184. const { nics = [] } = this.currentServer
  185. return nics.filter(item => item.mac).map(item => {
  186. return {
  187. ...item,
  188. macLabel: `${item.mac}${item.ip_addr ? ` (${item.ip_addr})` : ''}`,
  189. }
  190. })
  191. },
  192. hostParams () {
  193. const ret = {
  194. scope: this.scope,
  195. filter: 'hypervisor.notin(baremetal,container)',
  196. brand: 'OneCloud',
  197. limit: 20,
  198. system: this.isAdminMode,
  199. }
  200. const { type, target_id } = this.params.tapService
  201. if (type === 'host') {
  202. ret.filter = ['hypervisor.notin(baremetal,container)', `id.notin(${target_id})`]
  203. }
  204. return ret
  205. },
  206. serverParams () {
  207. const ret = {
  208. scope: this.scope,
  209. filter: 'hypervisor.notin(baremetal,container)',
  210. brand: 'OneCloud',
  211. limit: 20,
  212. system: this.isAdminMode,
  213. }
  214. const { type, target_id } = this.params.tapService
  215. if (type === 'guest') {
  216. ret.filter = ['hypervisor.notin(baremetal,container)', `id.notin(${target_id})`]
  217. }
  218. return ret
  219. },
  220. },
  221. created () {
  222. this.$m = new this.$Manager('tap_flows', 'v1')
  223. },
  224. methods: {
  225. async handleValuesChange (vm, changedFields) {
  226. this.form.fd = {
  227. ...this.form.fd,
  228. ...changedFields,
  229. }
  230. await this.$nextTick()
  231. if (changedFields.guest_id) {
  232. this.form.fc.setFieldsValue({
  233. mac_addr: '',
  234. })
  235. }
  236. if (changedFields.host_id) {
  237. if (!this.hostWires.some(item => item.wire_id === this.form.fd.wire_id)) {
  238. this.form.fc.setFieldsValue({
  239. wire_id: '',
  240. })
  241. }
  242. }
  243. },
  244. hostChange (data) {
  245. if (this.serverType === 'vswitch') {
  246. this.currentHost = data
  247. } else {
  248. this.currentHost = {}
  249. }
  250. },
  251. serverChange (data) {
  252. if (this.serverType === 'vnic') {
  253. this.currentServer = data
  254. } else {
  255. this.currentServer = {}
  256. }
  257. },
  258. validateForm () {
  259. return new Promise((resolve, reject) => {
  260. this.form.fc.validateFields((err, values) => {
  261. if (!err) {
  262. resolve(values)
  263. } else {
  264. reject(err)
  265. }
  266. })
  267. })
  268. },
  269. doCreate (data) {
  270. return this.$m.create({
  271. data,
  272. })
  273. },
  274. async handleConfirm () {
  275. this.loading = true
  276. try {
  277. const values = await this.validateForm()
  278. this.loading = true
  279. values.tap_id = this.params.tapService.id
  280. await this.doCreate(values)
  281. this.loading = false
  282. this.$bus.$emit('tap-service-refresh')
  283. this.params.success && this.params.success()
  284. this.cancelDialog()
  285. } catch (error) {
  286. this.loading = false
  287. }
  288. },
  289. },
  290. }
  291. </script>