feat(xo-web/vm/console): direct connection to SSH button (#4415)

This commit is contained in:
Nicolas Raynaud 2019-09-17 12:02:33 +02:00 committed by Pierre Donias
parent ae6cc8eea3
commit 2b0f1b6aab
3 changed files with 83 additions and 7 deletions

View File

@ -8,6 +8,7 @@
> Users must be able to say: “Nice enhancement, I'm eager to test it”
- [VM/disks] Don't hide disks that are attached to the same VM twice [#4400](https://github.com/vatesfr/xen-orchestra/issues/4400) (PR [#4414](https://github.com/vatesfr/xen-orchestra/pull/4414))
- [VM/console] Add a button to connect to the VM via the local SSH client (PR [#4415](https://github.com/vatesfr/xen-orchestra/pull/4415))
### Bug fixes

View File

@ -984,11 +984,18 @@ const messages = {
// ----- VM console tab -----
copyToClipboardLabel: 'Copy',
ctrlAltDelButtonLabel: 'Ctrl+Alt+Del',
ctrlAltDelConfirmation: 'Send Ctrl+Alt+Del to VM?',
multilineCopyToClipboard: 'Multiline copy',
tipLabel: 'Tip:',
hideHeaderTooltip: 'Hide info',
showHeaderTooltip: 'Show info',
sendToClipboard: 'Send to clipboard',
sshRootTooltip: 'Connect using external SSH tool as root',
sshRootLabel: 'SSH',
sshUserTooltip: 'Connect using external SSH tool as user…',
sshUserLabel: 'SSH as…',
sshUsernameLabel: 'SSH user name',
sshNeedClientTools: 'No IP address reported by client tools',
// ----- VM container tab -----
containerName: 'Name',

View File

@ -3,6 +3,7 @@ import ActionButton from 'action-button'
import Button from 'button'
import Component from 'base-component'
import CopyToClipboard from 'react-copy-to-clipboard'
import cookies from 'cookies-js'
import debounce from 'lodash/debounce'
import getEventValue from 'get-event-value'
import Icon from 'icon'
@ -13,7 +14,7 @@ import React from 'react'
import Tooltip from 'tooltip'
import { isVmRunning, resolveUrl } from 'xo'
import { Col, Container, Row } from 'grid'
import { confirm } from 'modal'
import { confirm, form } from 'modal'
import {
CpuSparkLines,
MemorySparkLines,
@ -61,7 +62,13 @@ export default class TabConsole extends Component {
this._toggleMinimalLayout()
}
}
_sendCtrlAltDel = () => {
_sendCtrlAltDel = async () => {
await confirm({
icon: 'vm-keyboard',
title: _('ctrlAltDelButtonLabel'),
body: _('ctrlAltDelConfirmation'),
})
this.refs.noVnc.sendCtrlAltDel()
}
@ -91,9 +98,40 @@ export default class TabConsole extends Component {
this.setState({ minimalLayout: !this.state.minimalLayout })
}
_openSsh = (username = 'root') => {
window.location = `ssh://${encodeURIComponent(username)}@${
this.props.vm.addresses['0/ip']
}`
}
_openSshMore = async () => {
const cookieKey = `${this.props.vm.uuid}/ssh-user-name`
const username = await form({
defaultValue: cookies.get(cookieKey) || 'root',
header: _('sshUsernameLabel'),
render: ({ value, onChange }) => (
<div>
<input
type='text'
className='form-control'
onChange={onChange}
value={value}
/>
</div>
),
})
if (username !== (cookies.get(cookieKey) || 'root')) {
// seems to be seconds
const expires = 31 * 3600 * 24
cookies.set(cookieKey, username, { expires })
}
this._openSsh(username)
}
render() {
const { statsOverview, vm } = this.props
const { minimalLayout, scale } = this.state
const canSsh = vm.addresses && vm.addresses['0/ip']
if (!isVmRunning(vm)) {
return (
@ -161,12 +199,42 @@ export default class TabConsole extends Component {
</span>
</div>
</Col>
<Col mediumSize={2}>
<Button onClick={this._sendCtrlAltDel}>
<Icon icon='vm-keyboard' /> {_('ctrlAltDelButtonLabel')}
</Button>
<Col mediumSize={5} largeSize={3}>
<div className='btn-group'>
<span className='input-group-btn'>
<ActionButton
handler={this._openSsh}
tooltip={
canSsh ? _('sshRootTooltip') : _('sshNeedClientTools')
}
disabled={!canSsh}
icon='remote'
>
{_('sshRootLabel')}
</ActionButton>
</span>
<span className='input-group-btn'>
<ActionButton
handler={this._openSshMore}
tooltip={
canSsh ? _('sshUserTooltip') : _('sshNeedClientTools')
}
disabled={!canSsh}
icon='remote'
>
{_('sshUserLabel')}
</ActionButton>
</span>
<span className='input-group-btn'>
<ActionButton
handler={this._sendCtrlAltDel}
tooltip={_('ctrlAltDelButtonLabel')}
icon='vm-keyboard'
/>
</span>
</div>
</Col>
<Col mediumSize={3}>
<Col mediumSize={2} className='hidden-lg-down'>
<input
className='form-control'
max={3}