-
Notifications
You must be signed in to change notification settings - Fork 594
/
VMConsoles.tsx
222 lines (207 loc) · 7.42 KB
/
VMConsoles.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
import * as React from 'react';
import { AccessConsoles } from '@patternfly/react-console';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionToggle,
Alert,
AlertActionCloseButton,
Button,
ClipboardCopy,
Stack,
StackItem,
} from '@patternfly/react-core';
import { Trans, useTranslation } from 'react-i18next';
import { LoadingInline } from '@console/internal/components/utils';
import { ConsoleType } from '../../../constants/vm/console-type';
import { VMStatus } from '../../../constants/vm/vm-status';
import { CloudInitDataHelper } from '../../../k8s/wrapper/vm/cloud-init-data-helper';
import { VolumeWrapper } from '../../../k8s/wrapper/vm/volume-wrapper';
import { isWindows } from '../../../selectors/vm/combined';
import {
getCloudInitVolume,
getIsGraphicsConsoleAttached,
getIsSerialConsoleAttached,
} from '../../../selectors/vm/selectors';
import { isVMIPaused, isVMIRunning } from '../../../selectors/vmi';
import { VMStatusBundle } from '../../../statuses/vm/types';
import { VMIKind, VMKind } from '../../../types/vm';
import { CLOUD_INIT_MISSING_USERNAME } from '../../../utils/strings';
import SerialConsoleConnector from './connectors/SerialConsoleConnector';
import VncConsoleConnector from './connectors/VncConsoleConnector';
import DesktopViewerSelector from './DesktopViewerSelector';
const VMIsDown: React.FC = () => (
<div className="co-m-pane__body">
<div className="kubevirt-vm-consoles__loading">
This Virtual Machine is down. Please start it to access its console.
</div>
</div>
);
const VMIsStarting: React.FC = () => (
<div className="co-m-pane__body">
<div className="kubevirt-vm-consoles__loading">
<LoadingInline />
This Virtual Machine is starting up. The console will be available soon.
</div>
</div>
);
const VMNotReady: React.FC = () => {
const { t } = useTranslation();
return (
<div className="co-m-pane__body">
<div className="kubevirt-vm-consoles__loading">
{t('kubevirt-plugin~This Virtual Machine is migrating and cannot be started at the moment')}
</div>
</div>
);
};
const getAvailableType = (showVNCOption, showSerialOption) => {
if (showVNCOption) {
return ConsoleType.VNC;
}
return showSerialOption ? ConsoleType.SERIAL : null;
};
const VMConsoles: React.FC<VMConsolesProps> = ({
vm,
vmi,
vmStatusBundle,
type,
showOpenInNewWindow = true,
renderVNCConsole,
}) => {
const { t } = useTranslation();
const [showAlert, setShowAlert] = React.useState(true);
const [showCredentials, setShowCredentials] = React.useState<boolean>(false);
const showVNCOption = getIsGraphicsConsoleAttached(vm) !== false && renderVNCConsole;
const showSerialOption = getIsSerialConsoleAttached(vm) !== false;
const [consoleType, setConsoleType] = React.useState(
type || getAvailableType(showVNCOption, showSerialOption),
);
const cloudInitVolume = getCloudInitVolume(vm);
const data = new VolumeWrapper(cloudInitVolume).getCloudInitNoCloud();
const cloudInitHelper = new CloudInitDataHelper(data);
const cloudInitUsername = cloudInitHelper.get('user');
const cloudInitPassword = cloudInitHelper.get('password');
if (!isVMIRunning(vmi)) {
if (vmStatusBundle?.status?.isMigrating()) {
return <VMNotReady />;
}
return vmStatusBundle?.status === VMStatus.STARTING ||
vmStatusBundle?.status === VMStatus.VMI_WAITING ||
(vmStatusBundle?.status?.isImporting() && vm.spec.running) ? (
<VMIsStarting />
) : (
<VMIsDown />
);
}
const vmName = vm?.metadata?.name || vmi?.metadata?.name;
const namespace = vm?.metadata?.namespace || vmi?.metadata?.namespace;
const typeNotSupported =
(!showVNCOption && type === ConsoleType.VNC) ||
(!showSerialOption && type === ConsoleType.SERIAL);
// const consoleType = typeNotSupported || type == null ? getAvailableType() : type;
const isPaused = isVMIPaused(((vm as any) as VMIKind) || vmi);
return (
<Stack hasGutter>
{showOpenInNewWindow && consoleType && (
<StackItem>
<Button
variant="secondary"
onClick={() =>
window.open(
`/k8s/ns/${namespace}/virtualmachineinstances/${vmName}/standaloneconsole?type=${consoleType.toString()}`,
`${vmName}-console`,
'modal=yes,alwaysRaised=yes,width=1024,height=768',
)
}
>
{t('kubevirt-plugin~Open Console in New Window')}
</Button>
</StackItem>
)}
{cloudInitPassword && (
<StackItem>
<Accordion>
<AccordionItem>
<AccordionToggle
id="cloudinit-credentials"
onClick={() => setShowCredentials(!showCredentials)}
isExpanded={showCredentials}
>
{t('kubevirt-plugin~Guest login credentials')}
</AccordionToggle>
<AccordionContent isHidden={!showCredentials}>
<Trans ns="kubevirt-plugin">
The following credentials for this operating system were created via{' '}
<strong>cloud-init</strong>. If unsuccessful, cloud-init could be improperly
configured. Please contact the image provider for more information.
</Trans>
<p>
<strong>{t('kubevirt-plugin~User name:')} </strong>{' '}
{cloudInitUsername || CLOUD_INIT_MISSING_USERNAME}
{' '}
<strong>{t('kubevirt-plugin~Password:')} </strong>{' '}
<ClipboardCopy variant="inline-compact" isCode>
{cloudInitPassword}
</ClipboardCopy>
</p>
</AccordionContent>
</AccordionItem>
</Accordion>
</StackItem>
)}
{typeNotSupported && showAlert && (
<StackItem>
<Alert
isInline
variant="danger"
actionClose={<AlertActionCloseButton onClose={() => setShowAlert(false)} />}
title={t(
'kubevirt-plugin~Selected type {{typeName}} is unsupported. Falling back to a supported type',
{ typeName: type.toPatternflyLabel() },
)}
/>
</StackItem>
)}
{!renderVNCConsole && (
<StackItem>
<Alert
isInline
variant="danger"
title={t('kubevirt-plugin~Console is open in another tab/window')}
/>
</StackItem>
)}
{isPaused && (
<StackItem>
<Alert
isInline
variant="warning"
title={t(
'kubevirt-plugin~Virtual machine is paused. Console will be active after unpause',
)}
/>
</StackItem>
)}
<StackItem>
<AccessConsoles preselectedType={consoleType?.toPatternflyLabel()}>
{showSerialOption && <SerialConsoleConnector vmi={vmi} setConsoleType={setConsoleType} />}
{showVNCOption && <VncConsoleConnector vmi={vmi} setConsoleType={setConsoleType} />}
{isWindows(vm) && (
<DesktopViewerSelector vm={vm} vmi={vmi} setConsoleType={setConsoleType} />
)}
</AccessConsoles>
</StackItem>
</Stack>
);
};
type VMConsolesProps = {
vm: VMKind;
vmi?: VMIKind;
vmStatusBundle: VMStatusBundle;
type?: ConsoleType;
showOpenInNewWindow?: boolean;
renderVNCConsole?: boolean;
};
export default VMConsoles;