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

Use noVNC via patternfly-react #8894

Merged
merged 2 commits into from
Sep 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"kubernetes-topology-graph": "0.0.24",
"moment": "2.22.2",
"mustache": "2.3.2",
"noVNC": "https://github.com/novnc/noVNC/archive/v0.6.2.tar.gz",
"object-describer": "https://github.com/kubernetes-ui/object-describer.git#v1.0.4",
"patternfly": "3.35.1",
"patternfly-bootstrap-combobox": "1.1.7",
Expand Down
9 changes: 0 additions & 9 deletions pkg/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,14 @@ playground_DATA = \
dist/playground/extra.de.po: pkg/playground/extra.de.po
$(COPY_RULE)

dist/machines/base.css: node_modules/noVNC/include/base.css
$(COPY_RULE)

ovirtdir = $(pkgdatadir)/ovirt
ovirt_DATA = \
dist/ovirt/install.sh \
dist/ovirt/base.css \
$(NULL)

dist/ovirt/install.sh: pkg/ovirt/install.sh
$(COPY_RULE)

dist/ovirt/base.css: node_modules/noVNC/include/base.css
$(COPY_RULE)

metainfodir = ${datarootdir}/metainfo
metainfo_DATA = pkg/sosreport/org.cockpit-project.cockpit-sosreport.metainfo.xml \
pkg/kdump/org.cockpit-project.cockpit-kdump.metainfo.xml \
Expand All @@ -41,8 +34,6 @@ EXTRA_DIST += \
pkg/playground/extra.de.po \
pkg/users/mock \
pkg/lib/qunit-template.html \
node_modules/noVNC/package.json \
node_modules/noVNC/include/base.css \
pkg/ovirt/install.sh \
$(playground_DATA) \
$(pkg_TESTS) \
Expand Down
10 changes: 6 additions & 4 deletions pkg/machines/components/consoles.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
.console-menu {
padding-bottom: 1em;
}

.console-type-select {
width: 19em !important;
}

.vnc-console .console-menu {
display: inline-block;
margin-bottom: -10px;
margin-top: -3px;
}
36 changes: 13 additions & 23 deletions pkg/machines/components/consoles.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import cockpit from 'cockpit';
import * as Select from "cockpit-components-select.jsx";

import SerialConsole from './serialConsole.jsx';
import Vnc, { VncActions } from './vnc.jsx';
import Vnc from './vnc.jsx';
import DesktopConsole from './desktopConsole.jsx';

import { logDebug } from '../helpers.es6';
Expand Down Expand Up @@ -196,36 +196,26 @@ class Consoles extends React.Component {
};

logDebug('Consoles render, this.state.consoleType: ', this.state.consoleType);
let console = null;
let actions = null;

const consoleSelector = (
<ConsoleSelector onChange={this.onConsoleTypeSelected}
isSerialConsole={!!serialConsoleCommand}
selected={this.state.consoleType}
vm={vm} />
);

switch (this.state.consoleType) {
case 'serial-browser':
console = <SerialConsole vmName={vm.name} spawnArgs={serialConsoleCommand} />;
break;
return <SerialConsole vmName={vm.name} spawnArgs={serialConsoleCommand}>{consoleSelector}</SerialConsole>;
case 'vnc-browser':
console = <Vnc vm={vm} consoleDetail={this.state.consoleDetail} />;
actions = <VncActions vm={vm} />;
break;
return <Vnc vm={vm} consoleDetail={this.state.consoleDetail}>{consoleSelector}</Vnc>;
case 'desktop':
console = <DesktopConsole vm={vm} onDesktopConsole={onDesktopConsole} config={config} />;
break;
return <DesktopConsole vm={vm} onDesktopConsole={onDesktopConsole} config={config}>{consoleSelector}</DesktopConsole>;
default:
console = <NoConsoleDefined />;
break;
}

return (
<div>
<span className='console-menu'>
<ConsoleSelector onChange={this.onConsoleTypeSelected}
isSerialConsole={!!serialConsoleCommand}
selected={this.state.consoleType}
vm={vm} />
{actions}
</span>
{console}
</div>
);
return (<NoConsoleDefined />);
}
}
Consoles.propTypes = {
Expand Down
3 changes: 2 additions & 1 deletion pkg/machines/components/desktopConsole.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,10 @@ const ManualConnection = ({ displays, idPrefix }) => {
);
};

const DesktopConsoleDownload = ({ vm, onDesktopConsole, config }) => {
const DesktopConsoleDownload = ({ children, vm, onDesktopConsole, config }) => {
return (
<div>
{children}
<table className='machines-desktop-main'>
<tbody>
<tr>
Expand Down
34 changes: 19 additions & 15 deletions pkg/machines/components/serialConsole.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,28 +121,32 @@ class SerialConsoleCockpit extends React.Component {

render () {
return (
<SerialConsole id={this.props.vmName} ref='serialconsole'
rows={XTERM_ROWS}
cols={XTERM_COLS}
fontFamily={XTERM_FONT_FAMILY}
fontSize={XTERM_FONT_SIZE}
status={this.getStatus()}
onConnect={this.onConnect}
onDisconnect={this.onDisconnect}
onResize={this.onResize}
onData={this.onData}
textDisconnect={_("Disconnect")}
textDisconnected={_("Disconnected from serial console. Click the Reconnect button.")}
textReconnect={_("Reconnect")}
textLoading={_("Loading ...")}
topClassName="" />
<React.Fragment>
{this.props.children}
<SerialConsole id={this.props.vmName} ref='serialconsole'
rows={XTERM_ROWS}
cols={XTERM_COLS}
fontFamily={XTERM_FONT_FAMILY}
fontSize={XTERM_FONT_SIZE}
status={this.getStatus()}
onConnect={this.onConnect}
onDisconnect={this.onDisconnect}
onResize={this.onResize}
onData={this.onData}
textDisconnect={_("Disconnect")}
textDisconnected={_("Disconnected from serial console. Click the Reconnect button.")}
textReconnect={_("Reconnect")}
textLoading={_("Loading ...")}
topClassName="" />
</React.Fragment>
);
}
}

SerialConsoleCockpit.propTypes = {
vmName: PropTypes.string.isRequired,
spawnArgs: PropTypes.array.isRequired,
children: PropTypes.node.isRequired,
};

export default SerialConsoleCockpit;
132 changes: 88 additions & 44 deletions pkg/machines/components/vnc.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,60 +17,104 @@
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react';
import PropTypes from 'prop-types';
import cockpit from 'cockpit';

import { vmId, logDebug } from '../helpers.es6';
import { VncConsole } from '@patternfly/react-console';

import './consoles.css';
import { logDebug } from '../helpers.es6';

const _ = cockpit.gettext;

const Frame = ({ url, novncContainerId }) => {
return (
<iframe src={url} className='machines-console-frame-vnc' frameBorder='0' name={novncContainerId} data-container-id={novncContainerId} title='VNC'>
{_("Your browser does not support iframes.")}
</iframe>
);
};
Frame.propTypes = {
url: PropTypes.string.isRequired,
novncContainerId: PropTypes.string.isRequired,
};

export const VncActions = ({ vm }) => {
const vmIdPrefix = vmId(vm.name);
return (
<span className='console-actions-pf'>
{_("Send shortcut")}
<button className='btn btn-default console-actions-buttons-pf' id={`${vmIdPrefix}-vnc-ctrl-alt-del`}>
Ctrl+Alt+Del
</button>
</span>
);
};

const Vnc = ({ vm, consoleDetail }) => {
if (!consoleDetail) {
logDebug('Vnc component: console detail not yet provided');
return null;
class Vnc extends React.Component {
constructor(props) {
super(props);
this.state = {
path: undefined,
};

this.connect = this.connect.bind(this);
this.onDisconnected = this.onDisconnected.bind(this);
this.onInitFailed = this.onInitFailed.bind(this);
}

connect(props) {
if (this.state.path) { // already initialized
return;
}

// consoleDetail can be retrieved asynchronously (like in pkg/ovirt flow)
const { consoleDetail } = props;
if (!consoleDetail) {
logDebug('Vnc component: console detail not yet provided');
return;
}

cockpit.transport.wait(() => {
const query = JSON.stringify({
payload: "stream",
protocol: "binary",
binary: "raw",
address: consoleDetail.address,
port: parseInt(consoleDetail.tlsPort || consoleDetail.port, 10),
});
this.setState({
path: `cockpit/channel/${cockpit.transport.csrf_token}?${window.btoa(query)}`,
});
});
}

componentWillMount() {
this.connect(this.props);
}

componentWillReceiveProps(nextProps) {
this.connect(nextProps);
}

getEncrypt() {
return window.location.protocol === 'https:';
}

onDisconnected(detail) { // server disconnected
console.info('Connection lost: ', detail);
}

onInitFailed(detail) {
console.error('VncConsole failed to init: ', detail, this);
}

const vmIdPrefix = vmId(vm.name);
const novncContainerId = `${vmIdPrefix}-novnc-frame-container`;
render() {
const { consoleDetail } = this.props;
const { path } = this.state;
if (!consoleDetail || !path) {
// postpone rendering until consoleDetail is known and channel ready
return null;
}

const encrypt = window.location.protocol === "https:";
const port = consoleDetail.tlsPort || consoleDetail.port;
const credentials = consoleDetail.password ? { password: consoleDetail.password } : undefined;
const encrypt = this.getEncrypt();

let params = `?host=${consoleDetail.address}&port=${port}&encrypt=${encrypt}&true_color=1&resize=true&containerId=${encodeURIComponent(vmIdPrefix)}`;
params = consoleDetail.password ? params += `&password=${consoleDetail.password}` : params;
return (
<VncConsole host={window.location.hostname}
port={window.location.port || (encrypt ? '443' : '80')}
path={path}
encrypt={encrypt}
credentials={credentials}
vncLogging='warn'
onDisconnected={this.onDisconnected}
onInitFailed={this.onInitFailed}
textConnecting={_("Connecting")}
textDisconnected={_("Disconnected")}
textSendShortcut={_("Send key")}
textCtrlAltDel={_("Ctrl+Alt+Del")}>
<div className='console-menu'>
{this.props.children}
</div>
</VncConsole>
);
}
}

return (
<div id={novncContainerId} className='machines-console-frame' style={{ height: '100px' }}>
<br />
<Frame url={`vnc.html${params}`} novncContainerId={novncContainerId} />
</div>
);
};
// TODO: define propTypes

export default Vnc;
18 changes: 0 additions & 18 deletions pkg/machines/vnc.css

This file was deleted.

Loading