diff --git a/src/config/section/network.js b/src/config/section/network.js index 150aa461d..0ddfc3d19 100644 --- a/src/config/section/network.js +++ b/src/config/section/network.js @@ -44,6 +44,10 @@ export default { name: 'egress.rules', component: () => import('@/views/network/EgressRulesTab.vue'), show: (record) => { return record.type === 'Isolated' && !('vpcid' in record) && 'listEgressFirewallRules' in store.getters.apis } + }, { + name: 'lb.config', + component: () => import('@/views/network/LbConfigTab.vue'), + show: (record) => { return record.type === 'Isolated' && !('vpcid' in record) && 'listEgressFirewallRules' in store.getters.apis } }, { name: 'public.ip.addresses', component: () => import('@/views/network/IpAddressesTab.vue'), diff --git a/src/locales/en.json b/src/locales/en.json index fa54ea1c4..8d3f77b31 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -632,6 +632,7 @@ "label.crosszones": "Cross Zones", "label.currency": "Currency", "label.current": "isCurrent", +"label.currentsslcert": "Current SSL Certificate", "label.currentpassword": "Current Password", "label.custom": "Custom", "label.custom.disk.offering": "Custom Disk Offering", @@ -1212,6 +1213,11 @@ "label.lb.algorithm.roundrobin": "Round-robin", "label.lb.algorithm.source": "Source", "label.lb.cookie": "LbCookie", +"label.lb.config": "LB Configs", +"label.lb.configuration": "Configuration", +"label.lb.config.name": "Lb Config name", +"label.lb.config.default.value": "Default value", +"label.lb.config.value": "Value", "label.lb.protocol.http": "HTTP", "label.lb.protocol.ssl": "SSL", "label.lb.protocol.tcp.proxy": "TCP-proxy", @@ -1966,6 +1972,7 @@ "label.ssh.key.pairs": "SSH Key Pairs", "label.sshkeypair": "New SSH Key Pair", "label.sshkeypairs": "SSH keypairs", +"label.ssl": "SSL", "label.sslcertificates": "SSL Certificates", "label.standard.us.keyboard": "Standard (US) keyboard", "label.start": "Start", @@ -2443,6 +2450,7 @@ "message.add.ip.range.direct.network": "Add an IP range to direct network in zone ", "message.add.ip.range.to.pod": "

Add an IP range to pod:

", "message.add.iprange.processing": "Adding IP Range...", +"message.add.lbconfig.processing": "Adding new load balancer config", "message.add.load.balancer": "Add a load balancer to zone", "message.add.load.balancer.under.ip": "The load balancer rule has been added under IP:", "message.add.network": "Add a new network for zone: ", @@ -2832,6 +2840,7 @@ "message.failed.to.add": "Failed to add", "message.failed.to.assign.vms": "Failed to assign VMs", "message.failed.to.remove": "Failed to remove", +"message.failed.to.remove.lbconfig": "Failed to remove load balancer config", "message.generate.keys": "Please confirm that you would like to generate new keys for this user.", "message.gslb.delete.confirm": "Please confirm you want to delete this GSLB", "message.gslb.lb.remove.confirm": "Please confirm you want to remove load balancing from GSLB", @@ -2993,6 +3002,8 @@ "message.remove.instance.failed": "Failed to remove instance", "message.remove.instance.processing": "Removing...", "message.remove.iprange.processing": "Removing IP Range...", +"message.remove.lbconfig.processing": "Removing load balancer config", +"message.remove.lbconfig.failed": "Failed to remove Load Balancer Config", "message.remove.ldap": "Are you sure you want to delete the LDAP configuration?", "message.remove.nic.processing": "Removing NIC...", "message.remove.port.forward.failed": "Removing Port Forwarding rule failed", @@ -3085,6 +3096,7 @@ "message.success.create.keypair": "Successfully created SSH key pair", "message.success.create.kubernetes.cluter": "Successfully created Kubernetes cluster", "message.success.create.l2.network": "Successfully created L2 network", +"message.success.create.lbconfig": "Successfully created load balancer config", "message.success.create.snapshot.from.vmsnapshot": "Successfully created Snapshot from VM snapshot", "message.success.create.user": "Successfully created user", "message.success.create.volume": "Successfully created volume", @@ -3113,6 +3125,7 @@ "message.success.remove.instance.rule": "Successfully removed instance from rule", "message.success.remove.ip": "Successfully removed IP", "message.success.remove.iprange": "Successfully removed IP Range", +"message.success.remove.lbconfig": "Successfully removed load balancer config", "message.success.remove.nic": "Successfully removed", "message.success.remove.port.forward": "Successfully removed Port Forwarding rule", "message.success.remove.rule": "Successfully deleted rule", diff --git a/src/views/network/LbConfigTab.vue b/src/views/network/LbConfigTab.vue new file mode 100644 index 000000000..d64c31f27 --- /dev/null +++ b/src/views/network/LbConfigTab.vue @@ -0,0 +1,366 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + + + + + diff --git a/src/views/network/LoadBalancing.vue b/src/views/network/LoadBalancing.vue index 9e6949b88..962999777 100644 --- a/src/views/network/LoadBalancing.vue +++ b/src/views/network/LoadBalancing.vue @@ -50,8 +50,15 @@ {{ $t('label.tcp.proxy') }} {{ $t('label.tcp') }} {{ $t('label.udp') }} + {{ $t('label.ssl') }} +
+
{{ $t('label.sslcertificates') }}
+ + SSl Certificate + +
{{ $t('label.add.vms') }}
@@ -82,6 +89,16 @@ {{ returnStickinessLabel(record.id) }} + + @@ -394,6 +531,7 @@ export default { data () { return { loading: true, + visible: true, lbRules: [], newTagsForm: this.$form.createForm(this), tagsModalVisible: false, @@ -426,14 +564,43 @@ export default { publicport: '', protocol: 'tcp', virtualmachineid: [], - vmguestip: [] + vmguestip: [], + sslcert: '' + }, + sslcerts: { + loading: false, + data: [] }, + selectedSsl: { + name: '', + id: null + }, + addSslCertModalVisible: false, + showAssignedSsl: false, addVmModalVisible: false, addVmModalLoading: false, addVmModalNicLoading: false, + addLbConfigVisible: false, + addLbConfigModalLoading: false, + currentAccountId: null, + assignedSslCert: 'None', + buttonVisible: false, + deleteSslButtonVisible: true, + addSslButtonVisible: true, + lbConfig: { + scope: 'LoadBalancerRule', + name: '', + description: null, + defaultvalue: null, + value: null, + forced: 'true' + }, vms: [], nics: [], + lbConfigs: [], + savedLbConfigs: [], totalCount: 0, + totalCountLbConfig: 0, page: 1, pageSize: 10, columns: [ @@ -465,6 +632,14 @@ export default { title: this.$t('label.action.configure.stickiness'), scopedSlots: { customRender: 'stickiness' } }, + { + title: this.$t('label.lb.configuration'), + scopedSlots: { customRender: 'configuration' } + }, + { + title: this.$t('label.sslcertificates'), + scopedSlots: { customRender: 'sslcert' } + }, { title: this.$t('label.add.vms'), scopedSlots: { customRender: 'add' } @@ -474,6 +649,28 @@ export default { scopedSlots: { customRender: 'actions' } } ], + lbconfigColumns: [ + { + title: this.$t('label.lb.config.name'), + dataIndex: 'name' + }, + { + title: this.$t('label.description'), + dataIndex: 'description' + }, + { + title: this.$t('label.lb.config.default.value'), + dataIndex: 'defaultvalue' + }, + { + title: this.$t('label.lb.config.value'), + dataIndex: 'value' + }, + { + title: this.$t('label.action'), + scopedSlots: { customRender: 'actions' } + } + ], tiers: { loading: false, data: [] @@ -581,6 +778,139 @@ export default { this.loading = false }) }, + fetchSslCerts () { + this.sslcerts.loading = true + this.sslcerts.data = [] + // Firt get the account id + api('listAccounts', { + name: this.resource.account, + domainid: this.resource.domainid + }).then(json => { + const accounts = json.listaccountsresponse.account || [] + if (accounts.length > 0) { + // Now fetch all the ssl certs for this account + this.currentAccountId = accounts[0].id + api('listSslCerts', { + accountid: this.currentAccountId + }).then(json => { + if (json.listsslcertsresponse.sslcert && json.listsslcertsresponse.sslcert.length > 0) { + this.selectedSsl.name = json.listsslcertsresponse.sslcert[0].name + this.selectedSsl.id = json.listsslcertsresponse.sslcert[0].id + json.listsslcertsresponse.sslcert.forEach(entry => this.sslcerts.data.push(entry)) + } + }).catch(error => { + this.$notifyError(error) + }) + } + }).catch(error => { + this.$notifyError(error) + }).finally(() => { + this.sslcerts.loading = false + }) + if (this.selectedRule !== null) { + this.getCurrentlyAssignedSslCert() + } + }, + getCurrentlyAssignedSslCert () { + api('listSslCerts', { + accountid: this.currentAccountId, + lbruleid: this.selectedRule.id + }).then(json => { + if (json.listsslcertsresponse.sslcert && json.listsslcertsresponse.sslcert.length > 0) { + this.assignedSslCert = json.listsslcertsresponse.sslcert[0].name + this.deleteSslButtonVisible = true + } else { + this.assignedSslCert = 'None' + this.deleteSslButtonVisible = false + } + }).catch(error => { + this.$notifyError(error) + }) + }, + selectssl (e) { + this.selectedSsl.id = e + }, + handleAddSslCert (data) { + this.addSslCert(data, this.selectedSsl.id) + }, + addSslTolbRule () { + this.visible = false + this.addSslCert(this.selectedRule.id, this.selectedSsl.id) + }, + addSslCert (lbRuleId, certId) { + this.disableSslAddDeleteButtons() + api('assignCertToLoadBalancer', { + lbruleid: lbRuleId, + certid: certId, + forced: true + }).then(response => { + this.$pollJob({ + jobId: response.assigncerttoloadbalancerresponse.jobid, + successMessage: `Successfully assigned Ssl certificate`, + successMethod: () => { + if (this.selectedRule !== null) { + this.getCurrentlyAssignedSslCert() + } + this.enableSslAddDeleteButtons() + }, + errorMessage: 'Failed to assign ssl certificate', + errorMethod: () => { + }, + loadingMessage: `Assigning ssl certificate...`, + catchMessage: 'Error encountered while fetching async job result addSslTolbRule', + catchMethod: (e) => { + this.closeModal() + } + }) + }).catch(error => { + this.$notifyError(error) + }).finally(() => { + }) + }, + removeSslFromLbRule () { + this.disableSslAddDeleteButtons() + api('removeCertFromLoadBalancer', { + lbruleid: this.selectedRule.id + }).then(response => { + this.$pollJob({ + jobId: response.removecertfromloadbalancerresponse.jobid, + successMessage: `Successfully removed Ssl certificate`, + successMethod: () => { + this.visible = true + this.getCurrentlyAssignedSslCert() + this.enableSslAddDeleteButtons() + }, + errorMessage: 'Failed to remove ssl certificate', + errorMethod: () => { + this.visible = true + }, + loadingMessage: `Removing ssl certificate...`, + catchMessage: 'Error encountered while fetching async job result', + catchMethod: () => { + this.closeModal() + } + }) + }).catch(error => { + this.$notifyError(error) + }).finally(() => { + }) + }, + populateValues () { + for (let i = 0; i < this.lbConfigs.length; i++) { + if (this.lbConfig.name === this.lbConfigs[i].name) { + this.lbConfig.description = this.lbConfigs[i].description + this.lbConfig.defaultvalue = this.lbConfigs[i].defaultvalue + } + } + }, + enableSslAddDeleteButtons () { + this.deleteSslButtonVisible = true + this.addSslButtonVisible = true + }, + disableSslAddDeleteButtons () { + this.addSslButtonVisible = false + this.deleteSslButtonVisible = false + }, fetchLBRuleInstances () { for (const rule of this.lbRules) { this.loading = true @@ -859,6 +1189,32 @@ export default { handleStickinessMethodSelectChange (e) { this.stickinessPolicyMethod = e }, + handleDeleteLoadBalancerConfig (rule) { + this.addLbConfigModalLoading = true + api('deleteLoadBalancerConfig', { + id: rule.id + }).then(response => { + this.$pollJob({ + jobId: response.deleteloadbalancerconfigresponse.jobid, + successMessage: `Successfully removed load balancer config`, + successMethod: () => { + this.fetchSavedLbConfigs() + }, + errorMessage: 'Failed to remove load balancer config', + errorMethod: () => { + this.fetchSavedLbConfigs() + }, + loadingMessage: `Removing load balancer config...`, + catchMessage: 'Error encountered while fetching async job result', + catchMethod: () => { + this.fetchSavedLbConfigs() + } + }) + }).catch(error => { + this.$notifyError(error) + this.fetchSavedLbConfigs() + }) + }, handleDeleteInstanceFromRule (instance, rule, ip) { this.loading = true api('removeFromLoadBalancerRule', { @@ -966,6 +1322,83 @@ export default { this.loading = false }) }, + handleOpenAddConfiguration () { + api('listLoadBalancerConfigs', { + listAll: true, + scope: 'LoadBalancerRule', + loadbalancerid: this.selectedRule.id + }).then(response => { + this.lbConfigs = response.listloadbalancerconfigsresponse.loadbalancerconfig + this.addLbConfigVisible = true + const tempLbConfig = response.listloadbalancerconfigsresponse.loadbalancerconfig[0] + this.lbConfig.name = tempLbConfig.name + this.lbConfig.description = tempLbConfig.description + this.lbConfig.defaultvalue = tempLbConfig.defaultvalue + }).catch(error => { + this.$notifyError(error) + this.closeModal() + }) + this.fetchSavedLbConfigs() + }, + handleAddNewLbConfig () { + if (!this.lbConfig.value) { + this.$refs.lbconfigValue.classList.add('error') + return + } else { + this.$refs.lbconfigValue.classList.remove('error') + } + this.addLbConfigModalLoading = true + api('createLoadBalancerConfig', { + scope: 'LoadBalancerRule', + name: this.lbConfig.name, + value: this.lbConfig.value, + forced: 'true', + loadbalancerid: this.selectedRule.id + }).then(response => { + this.$pollJob({ + jobId: response.createloadbalancerconfigresponse.jobid, + successMessage: this.$t('message.success.create.lbconfig'), + successMethod: () => { + this.fetchSavedLbConfigs() + }, + errorMessage: this.$t('message.failed.to.remove.lbconfig'), + errorMethod: () => { + this.fetchSavedLbConfigs() + }, + loadingMessage: this.$t('message.add.lbconfig.processing'), + catchMessage: this.$t('error.fetching.async.job.result'), + catchMethod: () => { + this.fetchSavedLbConfigs() + } + }) + this.addLbConfigModalLoading = true + }).catch(error => { + this.$notifyError(error) + this.fetchSavedLbConfigs() + }) + this.lbConfig.value = null + }, + fetchSavedLbConfigs () { + api('listLoadBalancerConfigs', { + scope: 'LoadBalancerRule', + loadbalancerid: this.selectedRule.id + }).then(response => { + this.savedLbConfigs = response.listloadbalancerconfigsresponse.loadbalancerconfig + this.totalCountLbConfig = response.listloadbalancerconfigsresponse.count || 0 + }).catch(error => { + this.$notifyError(error) + this.loading = false + }) + this.addLbConfigModalLoading = false + }, + handleOpenAddSslCertModal () { + this.addSslCertModalVisible = true + if (this.selectedRule) { + this.showAssignedSsl = true + this.buttonVisible = true + } + this.fetchSslCerts() + }, handleOpenAddVMModal () { if (!this.selectedRule) { if (!this.newRule.name) { @@ -1045,7 +1478,6 @@ export default { }, handleAssignToLBRule (data) { const vmIDIpMap = {} - let count = 0 let innerCount = 0 this.newRule.vmguestip.forEach(ip => { @@ -1074,6 +1506,9 @@ export default { successMethod: () => { this.parentFetchData() this.parentToggleLoading() + if (this.selectedSsl.id !== null) { + this.handleAddSslCert(data) + } this.fetchData() this.closeModal() }, @@ -1137,6 +1572,11 @@ export default { this.editRuleModalLoading = false this.addVmModalLoading = false this.addVmModalNicLoading = false + this.addLbConfigVisible = false + this.addSslCertModalVisible = false + this.showAssignedSsl = false + this.buttonVisible = false + this.savedLbConfigs = [] this.vms = [] this.nics = [] this.addVmModalVisible = false