From 568784b9921fe62653a992ada3348a60d89e5b28 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Sat, 29 Dec 2018 18:43:17 +0300 Subject: [PATCH] Added check for active DHCP before enable --- client/src/__locales/en.json | 2 +- client/src/actions/index.js | 102 ++++++++++----- client/src/api/Api.js | 8 +- client/src/components/Settings/Dhcp/Form.js | 86 +------------ .../src/components/Settings/Dhcp/Interface.js | 113 +++++++++++++++++ client/src/components/Settings/Dhcp/index.js | 116 +++++++++++++----- client/src/components/Settings/Settings.css | 4 + client/src/reducers/index.js | 1 + 8 files changed, 282 insertions(+), 150 deletions(-) create mode 100644 client/src/components/Settings/Dhcp/Interface.js diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 243ed012..fac7ceaa 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -1,5 +1,5 @@ { - "refresh_status": "Refresh status", + "check_dhcp_servers": "Check for DHCP servers", "save_config": "Save config", "enabled_dhcp": "DHCP server enabled", "disabled_dhcp": "DHCP server disabled", diff --git a/client/src/actions/index.js b/client/src/actions/index.js index 20ef3766..949e3a5d 100644 --- a/client/src/actions/index.js +++ b/client/src/actions/index.js @@ -553,31 +553,14 @@ export const getDhcpInterfaces = () => async (dispatch) => { } }; -export const setDhcpConfigRequest = createAction('SET_DHCP_CONFIG_REQUEST'); -export const setDhcpConfigSuccess = createAction('SET_DHCP_CONFIG_SUCCESS'); -export const setDhcpConfigFailure = createAction('SET_DHCP_CONFIG_FAILURE'); - -export const setDhcpConfig = config => async (dispatch) => { - dispatch(setDhcpConfigRequest()); - try { - await apiClient.setDhcpConfig(config); - dispatch(getDhcpStatus()); - dispatch(addSuccessToast('dhcp_config_saved')); - dispatch(setDhcpConfigSuccess()); - } catch (error) { - dispatch(addErrorToast({ error })); - dispatch(setDhcpConfigFailure()); - } -}; - export const findActiveDhcpRequest = createAction('FIND_ACTIVE_DHCP_REQUEST'); export const findActiveDhcpSuccess = createAction('FIND_ACTIVE_DHCP_SUCCESS'); export const findActiveDhcpFailure = createAction('FIND_ACTIVE_DHCP_FAILURE'); -export const findActiveDhcp = () => async (dispatch) => { +export const findActiveDhcp = name => async (dispatch) => { dispatch(findActiveDhcpRequest()); try { - const activeDhcp = await apiClient.findActiveDhcp(); + const activeDhcp = await apiClient.findActiveDhcp(name); dispatch(findActiveDhcpSuccess(activeDhcp)); } catch (error) { dispatch(addErrorToast({ error })); @@ -585,27 +568,84 @@ export const findActiveDhcp = () => async (dispatch) => { } }; +export const setDhcpConfigRequest = createAction('SET_DHCP_CONFIG_REQUEST'); +export const setDhcpConfigSuccess = createAction('SET_DHCP_CONFIG_SUCCESS'); +export const setDhcpConfigFailure = createAction('SET_DHCP_CONFIG_FAILURE'); + +// TODO rewrite findActiveDhcp part +export const setDhcpConfig = config => async (dispatch) => { + dispatch(setDhcpConfigRequest()); + try { + if (config.interface_name) { + dispatch(findActiveDhcpRequest()); + try { + const activeDhcp = await apiClient.findActiveDhcp(config.interface_name); + dispatch(findActiveDhcpSuccess(activeDhcp)); + + if (!activeDhcp.found) { + await apiClient.setDhcpConfig(config); + dispatch(addSuccessToast('dhcp_config_saved')); + dispatch(setDhcpConfigSuccess()); + dispatch(getDhcpStatus()); + } else { + dispatch(addErrorToast({ error: 'dhcp_found' })); + } + } catch (error) { + dispatch(addErrorToast({ error })); + dispatch(findActiveDhcpFailure()); + } + } else { + await apiClient.setDhcpConfig(config); + dispatch(addSuccessToast('dhcp_config_saved')); + dispatch(setDhcpConfigSuccess()); + dispatch(getDhcpStatus()); + } + } catch (error) { + dispatch(addErrorToast({ error })); + dispatch(setDhcpConfigFailure()); + } +}; + export const toggleDhcpRequest = createAction('TOGGLE_DHCP_REQUEST'); export const toggleDhcpFailure = createAction('TOGGLE_DHCP_FAILURE'); export const toggleDhcpSuccess = createAction('TOGGLE_DHCP_SUCCESS'); +// TODO rewrite findActiveDhcp part export const toggleDhcp = config => async (dispatch) => { dispatch(toggleDhcpRequest()); - let successMessage = ''; - try { - if (config.enabled) { - successMessage = 'disabled_dhcp'; + if (config.enabled) { + dispatch(addSuccessToast('disabled_dhcp')); + try { await apiClient.setDhcpConfig({ ...config, enabled: false }); - } else { - successMessage = 'enabled_dhcp'; - await apiClient.setDhcpConfig({ ...config, enabled: true }); + dispatch(toggleDhcpSuccess()); + dispatch(getDhcpStatus()); + } catch (error) { + dispatch(addErrorToast({ error })); + dispatch(toggleDhcpFailure()); } + } else { + dispatch(findActiveDhcpRequest()); + try { + const activeDhcp = await apiClient.findActiveDhcp(config.interface_name); + dispatch(findActiveDhcpSuccess(activeDhcp)); - dispatch(addSuccessToast(successMessage)); - dispatch(toggleDhcpSuccess()); - } catch (error) { - dispatch(addErrorToast({ error })); - dispatch(toggleDhcpFailure()); + if (!activeDhcp.found) { + try { + await apiClient.setDhcpConfig({ ...config, enabled: true }); + dispatch(toggleDhcpSuccess()); + dispatch(getDhcpStatus()); + } catch (error) { + dispatch(addErrorToast({ error })); + dispatch(toggleDhcpFailure()); + } + dispatch(addSuccessToast('enabled_dhcp')); + } else { + dispatch(addErrorToast({ error: 'dhcp_found' })); + } + } catch (error) { + dispatch(addErrorToast({ error })); + dispatch(findActiveDhcpFailure()); + } } }; diff --git a/client/src/api/Api.js b/client/src/api/Api.js index 2bb0277a..4592fae7 100644 --- a/client/src/api/Api.js +++ b/client/src/api/Api.js @@ -328,8 +328,12 @@ export default class Api { return this.makeRequest(path, method, parameters); } - findActiveDhcp() { + findActiveDhcp(name) { const { path, method } = this.DHCP_FIND_ACTIVE; - return this.makeRequest(path, method); + const parameters = { + data: name, + headers: { 'Content-Type': 'text/plain' }, + }; + return this.makeRequest(path, method, parameters); } } diff --git a/client/src/components/Settings/Dhcp/Form.js b/client/src/components/Settings/Dhcp/Form.js index 14455b1b..9fc497d2 100644 --- a/client/src/components/Settings/Dhcp/Form.js +++ b/client/src/components/Settings/Dhcp/Form.js @@ -1,7 +1,6 @@ import React, { Fragment } from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; -import { Field, reduxForm, formValueSelector } from 'redux-form'; +import { Field, reduxForm } from 'redux-form'; import { withNamespaces, Trans } from 'react-i18next'; import flow from 'lodash/flow'; @@ -45,88 +44,17 @@ const renderField = ({ ); -const renderInterfaces = (interfaces => ( - Object.keys(interfaces).map((item) => { - const option = interfaces[item]; - const { name } = option; - const onlyIPv6 = option.ip_addresses.every(ip => ip.includes(':')); - let interfaceIP = option.ip_addresses[0]; - - if (!onlyIPv6) { - option.ip_addresses.forEach((ip) => { - if (!ip.includes(':')) { - interfaceIP = ip; - } - }); - } - - return ( - - ); - }) -)); - -const renderInterfaceValues = (interfaceValues => ( - -)); - -let Form = (props) => { +const Form = (props) => { const { t, handleSubmit, pristine, submitting, - interfaces, - processing, - interfaceValue, } = props; return (
-
- {!processing && interfaces && -
-
-
- - - - {renderInterfaces(interfaces)} - -
-
- {interfaceValue && -
- {renderInterfaceValues(interfaces[interfaceValue])} -
- } -
- } -
-
@@ -211,20 +139,10 @@ Form.propTypes = { submitting: PropTypes.bool, interfaces: PropTypes.object, processing: PropTypes.bool, - interfaceValue: PropTypes.string, initialValues: PropTypes.object, t: PropTypes.func, }; -const selector = formValueSelector('dhcpForm'); - -Form = connect((state) => { - const interfaceValue = selector(state, 'interface_name'); - return { - interfaceValue, - }; -})(Form); - export default flow([ withNamespaces(), reduxForm({ form: 'dhcpForm' }), diff --git a/client/src/components/Settings/Dhcp/Interface.js b/client/src/components/Settings/Dhcp/Interface.js new file mode 100644 index 00000000..fe4206a7 --- /dev/null +++ b/client/src/components/Settings/Dhcp/Interface.js @@ -0,0 +1,113 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { Field, reduxForm, formValueSelector } from 'redux-form'; +import { withNamespaces, Trans } from 'react-i18next'; +import flow from 'lodash/flow'; + +const renderInterfaces = (interfaces => ( + Object.keys(interfaces).map((item) => { + const option = interfaces[item]; + const { name } = option; + const onlyIPv6 = option.ip_addresses.every(ip => ip.includes(':')); + let interfaceIP = option.ip_addresses[0]; + + if (!onlyIPv6) { + option.ip_addresses.forEach((ip) => { + if (!ip.includes(':')) { + interfaceIP = ip; + } + }); + } + + return ( + + ); + }) +)); + +const renderInterfaceValues = (interfaceValues => ( +
    +
  • + MTU: + {interfaceValues.mtu} +
  • +
  • + dhcp_hardware_address: + {interfaceValues.hardware_address} +
  • +
  • + dhcp_ip_addresses: + { + interfaceValues.ip_addresses + .map(ip => {ip}) + } +
  • +
+)); + +let Interface = (props) => { + const { + t, + handleChange, + interfaces, + processing, + interfaceValue, + enabled, + } = props; + + return ( + + {!processing && interfaces && +
+
+
+ + + + {renderInterfaces(interfaces)} + +
+
+ {interfaceValue && +
+ {renderInterfaceValues(interfaces[interfaceValue])} +
+ } +
+ } +
+ + ); +}; + +Interface.propTypes = { + handleChange: PropTypes.func, + interfaces: PropTypes.object, + processing: PropTypes.bool, + interfaceValue: PropTypes.string, + initialValues: PropTypes.object, + enabled: PropTypes.bool, + t: PropTypes.func, +}; + +const selector = formValueSelector('dhcpInterface'); + +Interface = connect((state) => { + const interfaceValue = selector(state, 'interface_name'); + return { + interfaceValue, + }; +})(Interface); + +export default flow([ + withNamespaces(), + reduxForm({ form: 'dhcpInterface' }), +])(Interface); diff --git a/client/src/components/Settings/Dhcp/index.js b/client/src/components/Settings/Dhcp/index.js index d18a9b93..3beb136f 100644 --- a/client/src/components/Settings/Dhcp/index.js +++ b/client/src/components/Settings/Dhcp/index.js @@ -5,6 +5,7 @@ import { Trans, withNamespaces } from 'react-i18next'; import Form from './Form'; import Leases from './Leases'; +import Interface from './Interface'; import Card from '../../ui/Card'; class Dhcp extends Component { @@ -12,27 +13,80 @@ class Dhcp extends Component { this.props.setDhcpConfig(values); }; - handleRefresh = () => { - this.props.findActiveDhcp(); + handleFormChange = (value) => { + this.props.setDhcpConfig(value); + } + + handleToggle = (config) => { + this.props.toggleDhcp(config); + this.props.findActiveDhcp(config.interface_name); } getToggleDhcpButton = () => { - const { config } = this.props.dhcp; - const buttonText = config.enabled ? 'dhcp_disable' : 'dhcp_enable'; - const buttonClass = config.enabled ? 'btn-gray' : 'btn-success'; + const { config, active } = this.props.dhcp; + const activeDhcpFound = active && active.found; + const filledConfig = Object.keys(config).every((key) => { + if (key === 'enabled') { + return true; + } + + return config[key]; + }); + + if (config.enabled) { + return ( + + ); + } return ( ); } + getActiveDhcpMessage = () => { + const { active } = this.props.dhcp; + + if (active) { + if (active.error) { + return ( +
+ {active.error} +
+ ); + } + + return ( + + {active.found ? ( +
+ dhcp_found +
+ ) : ( +
+ dhcp_not_found +
+ )} +
+ ); + } + + return ''; + } + render() { const { t, dhcp } = this.props; const statusButtonClass = classnames({ @@ -42,14 +96,20 @@ class Dhcp extends Component { return ( - {!dhcp.processing && - -
-
+ +
+ {!dhcp.processing && + +
@@ -57,29 +117,21 @@ class Dhcp extends Component {
{this.getToggleDhcpButton()}
- {dhcp.active && -
- {dhcp.active.found ? ( - - dhcp_found - - ) : ( - dhcp_not_found - )} -
- } -
-
- - } + {this.getActiveDhcpMessage()} + + } +
+
{!dhcp.processing && dhcp.config.enabled &&
diff --git a/client/src/components/Settings/Settings.css b/client/src/components/Settings/Settings.css index 22e15b16..a4ff2394 100644 --- a/client/src/components/Settings/Settings.css +++ b/client/src/components/Settings/Settings.css @@ -44,3 +44,7 @@ .interface__ip:last-child:after { content: ""; } + +.dhcp { + min-height: 450px; +} diff --git a/client/src/reducers/index.js b/client/src/reducers/index.js index 53ba15ca..fc202a0b 100644 --- a/client/src/reducers/index.js +++ b/client/src/reducers/index.js @@ -304,6 +304,7 @@ const dhcp = handleActions({ config: { enabled: false, }, + active: null, leases: [], });