Skip to content

Commit

Permalink
feat(xo-web/proxy): register an existing proxy (#6556)
Browse files Browse the repository at this point in the history
  • Loading branch information
MathieuRA authored and ByScripts committed Dec 14, 2022
1 parent 9626f59 commit 44cba14
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- [OVA export] Speed up OVA generation by 2. Generated file will be bigger (as big as uncompressed XVA) (PR [#6487](https://github.com/vatesfr/xen-orchestra/pull/6487))
- [Settings/Users] Add `Remove` button to delete OTP of users from the admin panel [Forum#6521](https://xcp-ng.org/forum/topic/6521/remove-totp-on-a-user-account) (PR [#6541](https://github.com/vatesfr/xen-orchestra/pull/6541))
- [Plugin/transport-nagios] XO now reports backed up VMs invidually with the VM name label used as _host_ and backup job name used as _service_
- [Proxies] Ability to register an existing proxy (PR [#6556](https://github.com/vatesfr/xen-orchestra/pull/6556))

### Bug fixes

Expand Down
9 changes: 8 additions & 1 deletion packages/xo-web/src/common/intl/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const messages = {
addCustomField: 'Add custom field',
editCustomField: 'Edit custom field',
deleteCustomField: 'Delete custom field',
onlyAvailableXoaUsers: 'Only available to XOA users',

// ----- Modals -----
alertOk: 'OK',
Expand Down Expand Up @@ -1332,6 +1333,7 @@ const messages = {
vmCoresPerSocketExceedsSocketsLimit: 'The selected value exceeds the sockets limit ({maxSockets, number})',
vmHaDisabled: 'Disabled',
vmMemoryLimitsLabel: 'Memory limits (min/max)',
vmUuid: 'VM UUID',
vmVgpu: 'vGPU',
vmVgpus: 'GPUs',
vmVgpuNone: 'None',
Expand Down Expand Up @@ -2471,7 +2473,6 @@ const messages = {
proxyUnknownVm: 'Unknown proxy VM.',

// ----- proxies -----
deployProxyDisabled: 'Only available to XOA users',
forgetProxyApplianceTitle: 'Forget prox{n, plural, one {y} other {ies}}',
forgetProxyApplianceMessage: 'Are you sure you want to forget {n, number} prox{n, plural, one {y} other {ies}}?',
forgetProxies: 'Forget proxy(ies)',
Expand All @@ -2482,11 +2483,16 @@ const messages = {
redeployProxy: 'Redeploy proxy',
redeployProxyAction: 'Redeploy this proxy',
redeployProxyWarning: 'This action will destroy the old proxy VM',
registerProxy: 'Register a proxy',
noProxiesAvailable: 'No proxies available',
checkProxyHealth: 'Test your proxy',
updateProxyApplianceSettings: 'Update appliance settings',
urlNotFound: 'URL not found',
proxyAuthToken: 'Authentication token',
proxyConnectionFailedAfterRegistrationMessage: 'Unable to connect to this proxy. Do you want to forget it?',
proxyCopyUrl: 'Copy proxy URL',
proxyError: 'Proxy error',
proxyOptionalVmUuid: 'VM UUID is optional but recommended.',
proxyTestSuccess: 'Test passed for {name}',
proxyTestSuccessMessage: 'The proxy appears to work correctly',
proxyTestFailed: 'Test failed for {name}',
Expand All @@ -2505,6 +2511,7 @@ const messages = {
'The upgrade will interrupt {nJobs, number} running backup job{nJobs, plural, one {} other {s}}. Do you want to continue?',
proxiesNeedUpgrade: 'Some proxies need to be upgraded.',
upgradeNeededForProxies: 'Some proxies need to be upgraded. Click here to get more information.',
xoProxyConcreteGuide: 'XO Proxy: a concrete guide',

// ----- Utils -----
secondsFormat: '{seconds, plural, one {# second} other {# seconds}}',
Expand Down
34 changes: 34 additions & 0 deletions packages/xo-web/src/common/xo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import invoke from '../invoke'
import Icon from '../icon'
import logError from '../log-error'
import NewAuthTokenModal from './new-auth-token-modal'
import RegisterProxyModal from './register-proxy-modal'
import renderXoItem, { renderXoItemFromId, Vm } from '../render-xo-item'
import store from 'store'
import { alert, chooseAction, confirm } from '../modal'
Expand Down Expand Up @@ -3306,6 +3307,37 @@ export const deployProxyAppliance = (license, sr, { network, proxy, ...props } =
...props,
})::tap(subscribeProxies.forceRefresh)

export const registerProxy = async () => {
const getStringOrUndefined = string => (string.trim() === '' ? undefined : string)

const { address, authenticationToken, name, vmUuid } = await confirm({
body: <RegisterProxyModal />,
icon: 'connect',
title: _('registerProxy'),
})

const proxyId = await registerProxyApplicance({
address: getStringOrUndefined(address),
authenticationToken: getStringOrUndefined(authenticationToken),
name: getStringOrUndefined(name),
vmUuid: getStringOrUndefined(vmUuid),
})
const _isProxyWorking = await isProxyWorking(proxyId).catch(err => {
console.error('isProxyWorking error:', err)
return false
})
if (!_isProxyWorking) {
await confirm({
body: _('proxyConnectionFailedAfterRegistrationMessage'),
title: _('proxyError'),
})
await forgetProxyAppliances([proxyId])
}
}

export const registerProxyApplicance = proxyInfo =>
_call('proxy.register', proxyInfo)::tap(subscribeProxies.forceRefresh)

export const editProxyAppliance = (proxy, { vm, ...props }) =>
_call('proxy.update', {
id: resolveId(proxy),
Expand Down Expand Up @@ -3365,6 +3397,8 @@ export const checkProxyHealth = async proxy => {
)
}

export const isProxyWorking = async proxy => (await _call('proxy.checkHealth', { id: resolveId(proxy) })).success

// Audit plugin ---------------------------------------------------------

const METHOD_NOT_FOUND_CODE = -32601
Expand Down
68 changes: 68 additions & 0 deletions packages/xo-web/src/common/xo/register-proxy-modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import _ from 'intl'
import Component from 'base-component'
import Icon from 'icon'
import React from 'react'
import SingleLineRow from 'single-line-row'
import { Col, Container } from 'grid'
import { Input as DebounceInput } from 'debounce-input-decorator'

export default class RegisterProxyModal extends Component {
state = {
address: '',
authenticationToken: '',
name: '',
vmUuid: '',
}
get value() {
return this.state
}

render() {
const { address, authenticationToken, name, vmUuid } = this.state
return (
<Container>
<a href='https://xen-orchestra.com/blog/xo-proxy-a-concrete-guide/' rel='noopener noreferrer'>
<Icon icon='info' /> {_('xoProxyConcreteGuide')}
</a>
<SingleLineRow className='mt-1'>
<Col size={6}>{_('proxyAuthToken')}</Col>
<Col size={6}>
<DebounceInput
className='form-control'
onChange={this.linkState('authenticationToken')}
value={authenticationToken}
/>
</Col>
</SingleLineRow>
<SingleLineRow className='mt-1'>
<Col size={6}>{_('name')}</Col>
<Col size={6}>
<DebounceInput className='form-control' onChange={this.linkState('name')} value={name} />
</Col>
</SingleLineRow>
<SingleLineRow className='mt-1'>
<Col size={6}>{_('address')}</Col>
<Col size={6}>
<DebounceInput
className='form-control'
onChange={this.linkState('address')}
placeholder='192.168.2.20[:4343]'
value={address}
/>
</Col>
</SingleLineRow>
<SingleLineRow className='mt-1'>
<Col size={6}>{_('vmUuid')}</Col>
<Col size={6}>
<DebounceInput className='form-control' onChange={this.linkState('vmUuid')} value={vmUuid} />
</Col>
</SingleLineRow>
<SingleLineRow className='mt-1'>
<Col className='text-info'>
<Icon icon='info' /> {_('proxyOptionalVmUuid')}
</Col>
</SingleLineRow>
</Container>
)
}
}
14 changes: 13 additions & 1 deletion packages/xo-web/src/xo-app/proxies/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
forgetProxyAppliances,
getLicenses,
getProxyApplianceUpdaterState,
registerProxy,
subscribeProxies,
upgradeProxyAppliance,
EXPIRES_SOON_DELAY,
Expand Down Expand Up @@ -322,10 +323,21 @@ const Proxies = decorate([
handler={effects.deployProxy}
icon='proxy'
size='large'
tooltip={state.isFromSource ? _('deployProxyDisabled') : undefined}
tooltip={state.isFromSource ? _('onlyAvailableXoaUsers') : undefined}
>
{_('deployProxy')}
</ActionButton>
<ActionButton
className='ml-1'
btnStyle='success'
disabled={state.isFromSource}
handler={registerProxy}
icon='connect'
size='large'
tooltip={state.isFromSource ? _('onlyAvailableXoaUsers') : undefined}
>
{_('registerProxy')}
</ActionButton>
</div>
<NoObjects
actions={ACTIONS}
Expand Down

0 comments on commit 44cba14

Please sign in to comment.