diff --git a/releasenotes/notes/Update-Editing-Health-Monitor-90ff623bcdb06f3b.yaml b/releasenotes/notes/Update-Editing-Health-Monitor-90ff623bcdb06f3b.yaml new file mode 100644 index 00000000..2c7236b1 --- /dev/null +++ b/releasenotes/notes/Update-Editing-Health-Monitor-90ff623bcdb06f3b.yaml @@ -0,0 +1,10 @@ +--- +features: + - | + Update editing health monitor for load balancer: + + * Fix remove health monitor. + + * Support editing admin_state_up when editing health monitor. + + * Support display admin_state_up info in the heath monitor info card in the listener detail page. diff --git a/src/locales/en.json b/src/locales/en.json index 5bed07e8..46df6eb0 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -998,7 +998,6 @@ "Fingerprint": "Fingerprint", "Finish Resize": "Finish Resize", "Finland": "Finland", - "First time edit automatically creates health monitor When pool does not have a health monitor": "First time edit automatically creates health monitor When pool does not have a health monitor", "Fixed IP": "Fixed IP", "Fixed IP Address": "Fixed IP Address", "Fixed IPs": "Fixed IPs", diff --git a/src/locales/ko-kr.json b/src/locales/ko-kr.json index d1344f16..2ef7422c 100644 --- a/src/locales/ko-kr.json +++ b/src/locales/ko-kr.json @@ -998,7 +998,6 @@ "Fingerprint": "", "Finish Resize": "Resize 완료", "Finland": "", - "First time edit automatically creates health monitor When pool does not have a health monitor": "Pool에 Heath monitor가 없을 때 처음 편집하면 Heath monitor가 자동으로 생성됩니다.", "Fixed IP": "고정 IP", "Fixed IP Address": "고정 IP 주소", "Fixed IPs": "고정 IP", diff --git a/src/locales/zh-hans.json b/src/locales/zh-hans.json index ea101206..3381c8ba 100644 --- a/src/locales/zh-hans.json +++ b/src/locales/zh-hans.json @@ -998,7 +998,6 @@ "Fingerprint": "指纹", "Finish Resize": "完成调整", "Finland": "芬兰", - "First time edit automatically creates health monitor When pool does not have a health monitor": "资源池无健康检查器时,首次编辑会自动创建健康检查器", "Fixed IP": "内网IP", "Fixed IP Address": "内网IP地址", "Fixed IPs": "内网IP", diff --git a/src/pages/network/containers/LoadBalancers/Listener/Actions/CreatePool.jsx b/src/pages/network/containers/LoadBalancers/Listener/Actions/CreatePool.jsx index 51536d6f..79ebb237 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Actions/CreatePool.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Actions/CreatePool.jsx @@ -40,7 +40,8 @@ export class CreatePool extends ModalAction { static policy = 'os_load-balancer_api:pool:post'; static allowed = async (item, containerProps) => { - let { detail: lbDetail } = containerProps || {}; + const { detail } = containerProps || {}; + let lbDetail = item.loadBalancer || detail; if (!lbDetail) { lbDetail = await globalLbaasStore.pureFetchDetail(item.loadbalancers[0]); } diff --git a/src/pages/network/containers/LoadBalancers/Listener/Actions/DeleteListener.jsx b/src/pages/network/containers/LoadBalancers/Listener/Actions/DeleteListener.jsx index c7967b35..79d6ca90 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Actions/DeleteListener.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Actions/DeleteListener.jsx @@ -40,7 +40,8 @@ export default class DeleteAction extends ConfirmAction { policy = 'os_load-balancer_api:listener:delete'; allowed = async (item, containerProps) => { - let { detail: lbDetail } = containerProps || {}; + const { detail } = containerProps || {}; + let lbDetail = item.loadBalancer || detail; if (!lbDetail) { lbDetail = await globalLbaasStore.pureFetchDetail(item.loadbalancers[0]); } diff --git a/src/pages/network/containers/LoadBalancers/Listener/Actions/DeletePool.jsx b/src/pages/network/containers/LoadBalancers/Listener/Actions/DeletePool.jsx index 430aaa69..2d13ce7c 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Actions/DeletePool.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Actions/DeletePool.jsx @@ -40,7 +40,8 @@ export default class DeletePoolAction extends ConfirmAction { policy = 'os_load-balancer_api:pool:delete'; allowedCheckFunc = async (item, containerProps) => { - let { detail: lbDetail } = containerProps || {}; + const { detail } = containerProps || {}; + let lbDetail = item.loadBalancer || detail; if (!lbDetail) { lbDetail = await globalLbaasStore.pureFetchDetail(item.loadbalancers[0]); } diff --git a/src/pages/network/containers/LoadBalancers/Listener/Actions/Edit.jsx b/src/pages/network/containers/LoadBalancers/Listener/Actions/Edit.jsx index a91f3da3..0f0920fa 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Actions/Edit.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Actions/Edit.jsx @@ -31,7 +31,8 @@ export class Edit extends Base { static policy = 'os_load-balancer_api:listener:put'; static allowed = async (item, containerProps) => { - let { detail: lbDetail } = containerProps || {}; + const { detail } = containerProps || {}; + let lbDetail = item.loadBalancer || detail; if (!lbDetail) { lbDetail = await globalLbaasStore.pureFetchDetail(item.loadbalancers[0]); } diff --git a/src/pages/network/containers/LoadBalancers/Listener/Actions/EditHealthMonitor.jsx b/src/pages/network/containers/LoadBalancers/Listener/Actions/EditHealthMonitor.jsx index ad627b55..cfaa2006 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Actions/EditHealthMonitor.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Actions/EditHealthMonitor.jsx @@ -20,14 +20,17 @@ import globalHealthMonitorStore, { import { healthProtocols } from 'resources/octavia/lb'; import { PoolStore } from 'stores/octavia/pool'; import globalLbaasStore from 'stores/octavia/loadbalancer'; +import { ListenerStore } from 'stores/octavia/listener'; export class EditHealthMonitor extends ModalAction { init() { this.store = new HealthMonitorStore(); + this.listenerStore = new ListenerStore(); this.poolStore = new PoolStore(); this.state = { - defaultData: true, - admin_state_up: false, + enableHealthMonitor: false, + dataLoading: true, + healthMonitor: null, }; } @@ -58,31 +61,40 @@ export class EditHealthMonitor extends ModalAction { } get defaultValue() { - const { operating_status, type, delay, timeout, max_retries } = - this.store.detail; - const { defaultData, admin_state_up } = this.state; - if (defaultData && operating_status && this.formRef.current) { - this.formRef.current.setFieldsValue({ - admin_state_up, - operating_status, - type, - delay, - timeout, - max_retries, - }); - this.setState({ defaultData: false }); + const { healthMonitor } = this.state; + if (!healthMonitor) { + return { + delay: 5, + timeout: 3, + max_retries: 3, + enableHealthMonitor: false, + admin_state_up: true, + }; } + const { + admin_state_up, + operating_status, + type, + delay, + timeout, + max_retries, + } = healthMonitor; return { - delay: 5, - timeout: 3, - max_retries: 3, + enableHealthMonitor: true, + admin_state_up, + operating_status, + type, + delay, + timeout, + max_retries, }; } static policy = 'os_load-balancer_api:healthmonitor:put'; static allowed = async (item, containerProps) => { - let { detail: lbDetail } = containerProps || {}; + const { detail } = containerProps || {}; + let lbDetail = item.loadBalancer || detail; if (!lbDetail) { lbDetail = await globalLbaasStore.pureFetchDetail(item.loadbalancers[0]); } @@ -94,52 +106,45 @@ export class EditHealthMonitor extends ModalAction { }; async getHealthMonitor() { - const { default_pool_id } = this.item; - const pool = await this.poolStore.fetchDetail({ id: default_pool_id }); - const { healthmonitor_id } = pool; - if (healthmonitor_id) { - const { admin_state_up } = await this.store.fetchDetail({ - id: healthmonitor_id, - }); - this.setState({ admin_state_up }); - this.formRef.current.setFieldsValue({ admin_state_up }); - } - } - - get tips() { - const { healthmonitor_id } = this.poolStore.detail || {}; - if (!healthmonitor_id) { - return t( - 'First time edit automatically creates health monitor When pool does not have a health monitor' - ); - } - return ''; + const detail = await this.listenerStore.fetchDetail(this.item); + const { healthMonitor } = detail; + this.setState( + { + healthMonitor, + enableHealthMonitor: !!healthMonitor, + dataLoading: false, + }, + () => { + this.updateDefaultValue(); + } + ); } get formItems() { - const { admin_state_up } = this.state; - const { healthmonitor_id } = this.poolStore.detail || {}; + const { enableHealthMonitor, dataLoading, healthMonitor } = this.state; + if (dataLoading) { + return [ + { + name: 'loading', + type: 'loading', + }, + ]; + } return [ { - name: 'admin_state_up', + name: 'enableHealthMonitor', label: t('Enable Health Monitor'), type: 'radio', required: true, - // onlyRadio: true, - // isWrappedValue: true, options: [ { label: t('Yes'), value: true, }, - ...(healthmonitor_id - ? [ - { - label: t('No'), - value: false, - }, - ] - : []), + { + label: t('No'), + value: false, + }, ], }, { @@ -147,9 +152,9 @@ export class EditHealthMonitor extends ModalAction { label: t('HealthMonitor Type'), type: 'select', options: this.filteredProtocolOptions, - hidden: !admin_state_up && healthmonitor_id, + hidden: !enableHealthMonitor, required: true, - disabled: !!healthmonitor_id, + disabled: !!healthMonitor, }, { name: 'delay', @@ -157,7 +162,7 @@ export class EditHealthMonitor extends ModalAction { type: 'input-int', min: 0, extra: t('Maximum interval time for each health check response'), - hidden: !admin_state_up && healthmonitor_id, + hidden: !enableHealthMonitor, required: true, }, { @@ -168,7 +173,7 @@ export class EditHealthMonitor extends ModalAction { extra: t( 'The timeout period of waiting for the return of the health check request, the check timeout will be judged as a check failure' ), - hidden: !admin_state_up && healthmonitor_id, + hidden: !enableHealthMonitor, required: true, }, { @@ -179,21 +184,39 @@ export class EditHealthMonitor extends ModalAction { extra: t( 'That is, after how many consecutive failures of the health check, the health check status of the back-end cloud server is changed from normal to abnormal' ), - hidden: !admin_state_up && healthmonitor_id, + hidden: !enableHealthMonitor, required: true, }, + { + name: 'admin_state_up', + label: t('Admin State Up'), + type: 'switch', + tip: t('Defines the admin state of the health monitor.'), + hidden: !enableHealthMonitor, + }, ]; } onSubmit = (values) => { const { default_pool_id } = this.item; - const { healthmonitor_id: id } = this.poolStore.detail || {}; + const { healthMonitor } = this.state; + const { id } = healthMonitor || {}; + const { enableHealthMonitor, type, ...others } = values; if (id) { - const { type, ...others } = values; + if (!enableHealthMonitor) { + return globalHealthMonitorStore.delete({ id }); + } return globalHealthMonitorStore.edit({ id }, others); } - values.pool_id = default_pool_id; - return globalHealthMonitorStore.create(values); + if (!enableHealthMonitor) { + return Promise.resolve(); + } + const data = { + type, + ...others, + pool_id: default_pool_id, + }; + return globalHealthMonitorStore.create(data); }; } diff --git a/src/pages/network/containers/LoadBalancers/Listener/Actions/EditPoolInfo.jsx b/src/pages/network/containers/LoadBalancers/Listener/Actions/EditPoolInfo.jsx index a2310ffc..fb35b8df 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Actions/EditPoolInfo.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Actions/EditPoolInfo.jsx @@ -63,7 +63,8 @@ export class EditPoolInfo extends ModalAction { static policy = 'os_load-balancer_api:pool:put'; static allowed = async (item, containerProps) => { - let { detail: lbDetail } = containerProps || {}; + const { detail } = containerProps || {}; + let lbDetail = item.loadBalancer || detail; if (!lbDetail) { lbDetail = await globalLbaasStore.pureFetchDetail(item.loadbalancers[0]); } diff --git a/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx b/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx index 1680fd0a..f98cba6e 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx @@ -13,38 +13,12 @@ // limitations under the License. import { inject, observer } from 'mobx-react'; -import globalListenerStore from 'stores/octavia/listener'; import Base from 'containers/BaseDetail'; -import { HealthMonitorStore } from 'stores/octavia/health-monitor'; import { getInsertHeaderCard } from 'resources/octavia/lb'; import { isEmpty } from 'lodash'; import { algorithmDict } from 'resources/octavia/pool'; export class BaseDetail extends Base { - componentDidMount() { - this.fetchData(); - const { default_pool: { healthmonitor_id } = {} } = this.detailData; - if (healthmonitor_id) { - this.fetchHealthMonitor(); - } - } - - get shouldFetchDetail() { - return true; - } - - init() { - this.store = globalListenerStore; - this.healthmonitorStore = new HealthMonitorStore(); - } - - fetchHealthMonitor = async () => { - const { - default_pool: { healthmonitor_id }, - } = this.detailData; - await this.healthmonitorStore.fetchDetail({ id: healthmonitor_id }); - }; - get leftCards() { const cards = [this.PoolInfo, this.healthMonitor]; const { insert_headers = {} } = this.detailData; @@ -100,32 +74,39 @@ export class BaseDetail extends Base { } get healthMonitor() { - const healthmonitor = this.healthmonitorStore.detail || {}; - const { admin_state_up, type, delay, timeout, max_retries } = healthmonitor; + const healthMonitor = this.detailData.healthMonitor || {}; + const { type, delay, timeout, max_retries, admin_state_up } = healthMonitor; const options = [ { label: t('Enable Health Monitor'), - content: admin_state_up ? t('Yes') : t('No'), - }, - { - label: t('Health Monitor Type'), - content: admin_state_up ? type : '-', - }, - { - label: t('Delay Interval(s)'), - content: admin_state_up ? delay : '-', - }, - { - label: t('Timeout(s)'), - content: admin_state_up ? timeout : '-', - }, - { - label: t('Max Retries'), - content: admin_state_up ? max_retries : '-', + content: !isEmpty(healthMonitor) ? t('Yes') : t('No'), }, ]; - if (Object.keys(healthmonitor).length === 0) { - options[0].content = '-'; + if (!isEmpty(healthMonitor)) { + options.push( + ...[ + { + label: t('Health Monitor Type'), + content: type, + }, + { + label: t('Delay Interval(s)'), + content: delay, + }, + { + label: t('Timeout(s)'), + content: timeout, + }, + { + label: t('Max Retries'), + content: max_retries, + }, + { + label: t('Admin State Up'), + content: admin_state_up ? t('On') : t('Off'), + }, + ] + ); } return { title: t('Health Monitor'), diff --git a/src/pages/network/containers/LoadBalancers/Listener/Detail/index.jsx b/src/pages/network/containers/LoadBalancers/Listener/Detail/index.jsx index 07d4ab27..378a4477 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Detail/index.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Detail/index.jsx @@ -78,6 +78,10 @@ export class ListenerDetail extends Base { ]; } + get forceLoadingTabs() { + return ['detail']; + } + get tabs() { const tabs = [ { diff --git a/src/pages/network/containers/LoadBalancers/StepCreateComponents/HealthMonitorStep/index.jsx b/src/pages/network/containers/LoadBalancers/StepCreateComponents/HealthMonitorStep/index.jsx index 29596fff..f04d31d6 100644 --- a/src/pages/network/containers/LoadBalancers/StepCreateComponents/HealthMonitorStep/index.jsx +++ b/src/pages/network/containers/LoadBalancers/StepCreateComponents/HealthMonitorStep/index.jsx @@ -122,6 +122,7 @@ export class HealthMonitorStep extends Base { label: t('Admin State Up'), type: 'switch', tip: t('Defines the admin state of the health monitor.'), + hidden: !enableHealthMonitor, }, ]; } diff --git a/src/stores/octavia/listener.js b/src/stores/octavia/listener.js index 78ac3db5..e3396808 100644 --- a/src/stores/octavia/listener.js +++ b/src/stores/octavia/listener.js @@ -24,6 +24,14 @@ export class ListenerStore extends Base { return client.octavia.pools; } + get healthMonitorClient() { + return client.octavia.healthMonitors; + } + + get lbClient() { + return client.octavia.loadbalancers; + } + get listFilterByProject() { return true; } @@ -66,11 +74,21 @@ export class ListenerStore extends Base { caCertificateId: caId, sniCertificateId: sniId, }); + const { loadbalancers = [] } = item; + const { loadbalancer } = await this.lbClient.show(loadbalancers[0].id); + item.loadBalancer = loadbalancer; if (default_pool_id) { // pool attach listener or loadbalancer ? try { - const res = await this.poolClient.show(default_pool_id); - item.default_pool = res.pool; + const { pool } = await this.poolClient.show(default_pool_id); + item.default_pool = pool; + const { healthmonitor_id } = pool; + if (healthmonitor_id) { + const { healthmonitor } = await this.healthMonitorClient.show( + healthmonitor_id + ); + item.healthMonitor = healthmonitor; + } return item; } catch (err) { return item;