Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(xo-web/proxy): register an existing proxy #6556

Merged
merged 13 commits into from
Nov 29, 2022
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

- [Remotes] Prevent remote path from ending with `xo-vm-backups` as it's usually a mistake
- [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))
- [Proxy] Ability to connect to an existing proxy from the `Proxies` view (PR [#6556](https://github.com/vatesfr/xen-orchestra/pull/6556))
Rajaa-BARHTAOUI marked this conversation as resolved.
Show resolved Hide resolved
julien-f marked this conversation as resolved.
Show resolved Hide resolved

### Bug fixes

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

// ----- Modals -----
alertOk: 'OK',
Expand Down Expand Up @@ -1331,6 +1332,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 @@ -2470,7 +2472,8 @@ const messages = {
proxyUnknownVm: 'Unknown proxy VM.',

// ----- proxies -----
deployProxyDisabled: 'Only available to XOA users',
connectProxy: 'Connect a proxy',
doYouWantForgetIt: 'Do you want to forget it?',
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 @@ -2485,7 +2488,9 @@ const messages = {
checkProxyHealth: 'Test your proxy',
updateProxyApplianceSettings: 'Update appliance settings',
urlNotFound: 'URL not found',
proxyAuthToken: 'Authentication token',
proxyCopyUrl: 'Copy proxy URL',
proxyError: 'Proxy error',
proxyTestSuccess: 'Test passed for {name}',
proxyTestSuccessMessage: 'The proxy appears to work correctly',
proxyTestFailed: 'Test failed for {name}',
Expand Down
4 changes: 4 additions & 0 deletions packages/xo-web/src/common/xo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3303,6 +3303,8 @@ export const deployProxyAppliance = (license, sr, { network, proxy, ...props } =
...props,
})::tap(subscribeProxies.forceRefresh)

export const connectProxyAppliance = proxyInfo => _call('proxy.register', proxyInfo)::tap(subscribeProxies.forceRefresh)
pdonias marked this conversation as resolved.
Show resolved Hide resolved

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

export const isProxyWorking = async proxy => (await _call('proxy.checkHealth', { id: resolveId(proxy) })).success
Rajaa-BARHTAOUI marked this conversation as resolved.
Show resolved Hide resolved

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

const METHOD_NOT_FOUND_CODE = -32601
Expand Down
55 changes: 55 additions & 0 deletions packages/xo-web/src/xo-app/proxies/connect-proxy-modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import _ from 'intl'
import Component from 'base-component'
import React from 'react'
import SingleLineRow from 'single-line-row'
import { Col, Container } from 'grid'
import { Input as DebounceInput } from 'debounce-input-decorator'
Rajaa-BARHTAOUI marked this conversation as resolved.
Show resolved Hide resolved

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

render() {
const { address, authenticationToken, name, vmUuid } = this.state
return (
<Container>
<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')} value={address} />
</Col>
</SingleLineRow>
{_('or')}
Rajaa-BARHTAOUI marked this conversation as resolved.
Show resolved Hide resolved
julien-f marked this conversation as resolved.
Show resolved Hide resolved
<SingleLineRow>
<Col size={6}>{_('vmUuid')}</Col>
<Col size={6}>
<DebounceInput className='form-control' onChange={this.linkState('vmUuid')} value={vmUuid} />
</Col>
</SingleLineRow>
</Container>
)
}
}
37 changes: 36 additions & 1 deletion packages/xo-web/src/xo-app/proxies/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,21 @@ import { Vm } from 'render-xo-item'
import { withRouter } from 'react-router'
import {
checkProxyHealth,
connectProxyAppliance,
destroyProxyAppliances,
editProxyAppliance,
forgetProxyAppliances,
getLicenses,
getProxyApplianceUpdaterState,
isProxyWorking,
subscribeProxies,
upgradeProxyAppliance,
EXPIRES_SOON_DELAY,
} from 'xo'

import Page from '../page'

import ConnectProxyModal from './connect-proxy-modal'
import deployProxy from './deploy-proxy'
import { updateApplianceSettings } from './update-appliance-settings'

Expand Down Expand Up @@ -282,6 +285,27 @@ const Proxies = decorate([
async deployProxy({ fetchProxyUpgrades }, proxy) {
return fetchProxyUpgrades([await deployProxy(proxy)])
},
async connectProxy() {
Rajaa-BARHTAOUI marked this conversation as resolved.
Show resolved Hide resolved
const connectProxyInfo = await confirm({
body: <ConnectProxyModal />,
icon: 'connect',
title: _('connectProxy'),
})

const proxyId = await connectProxyAppliance(connectProxyInfo)
if (!(await isProxyWorking(proxyId))) {
pdonias marked this conversation as resolved.
Show resolved Hide resolved
await confirm({
body: (
<div>
<p>{_('proxyTestFailedConnectionIssueMessage')}</p>
<p>{_('doYouWantForgetIt')}</p>
</div>
),
title: _('proxyError'),
})
await forgetProxyAppliances([proxyId])
}
},
async upgradeAppliance({ fetchProxyUpgrades }, id, options) {
try {
await upgradeProxyAppliance(id, options)
Expand Down Expand Up @@ -322,10 +346,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={effects.connectProxy}
icon='connect'
size='large'
tooltip={state.isFromSource ? _('onlyAvailableXoaUsers') : undefined}
>
{_('connectProxy')}
</ActionButton>
</div>
<NoObjects
actions={ACTIONS}
Expand Down