Line data Source code
1 : /*
2 : * Copyright (C) 2021 Red Hat, Inc.
3 : * SPDX-License-Identifier: LGPL-2.1-or-later
4 : */
5 :
6 341 : import cockpit from "cockpit";
7 341 : import React from "react";
8 :
9 : import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
10 : import { ClipboardCopy } from "@patternfly/react-core/dist/esm/components/ClipboardCopy/index.js";
11 : import { Page, PageSection } from "@patternfly/react-core/dist/esm/components/Page/index.js";
12 : import { Stack } from "@patternfly/react-core/dist/esm/layouts/Stack/index.js";
13 : import { ExclamationCircleIcon } from "@patternfly/react-icons";
14 :
15 : import { EmptyStatePanel } from "cockpit-components-empty-state";
16 :
17 : import { codes } from "./hosts_dialog.jsx";
18 : import { Machine } from "./machines/machines";
19 :
20 341 : const _ = cockpit.gettext;
21 :
22 3 : export const EarlyFailure = () => {
23 3 : let ca_cert_url = null;
24 3 : if (window.navigator.userAgent.indexOf("Safari") >= 0)
25 3 : ca_cert_url = window.sessionStorage.getItem("CACertUrl");
26 :
27 3 : return (
28 3 : <div id="early-failure" className="early-failure">
29 3 : <Page className="pf-m-no-sidebar">
30 3 : <PageSection hasBodyWrapper={false}>
31 3 : <EmptyStatePanel icon={ExclamationCircleIcon}
32 3 : title={ _("Connection failed") }
33 3 : paragraph={
34 3 : <Stack hasGutter>
35 3 : <div>{_("There was an unexpected error while connecting to the machine.")}</div>
36 3 : <div>{_("Messages related to the failure might be found in the journal:")}</div>
37 3 : <ClipboardCopy isReadOnly hoverTip={_("Copy")} clickTip={_("Copied")}>journalctl -u cockpit</ClipboardCopy>
38 1 : {ca_cert_url && <div id="safari-cert-help">
39 1 : <div>{_("Safari users need to import and trust the certificate of the self-signing CA:")}</div>
40 1 : <Button variant="link" component="a" id="safari-cert" href={ca_cert_url} download>ca.cer</Button>
41 1 : </div>}
42 3 : </Stack>
43 3 : } />
44 3 : </PageSection>
45 3 : </Page>
46 3 : </div>
47 : );
48 3 : };
49 :
50 16 : const EarlyFailureReady = ({
51 16 : loading = false,
52 16 : title,
53 16 : paragraph,
54 16 : reconnect = false,
55 16 : troubleshoot = false,
56 0 : onTroubleshoot = () => {},
57 0 : onReconnect = () => {},
58 16 : } : {
59 : loading?: boolean,
60 : title: string,
61 : paragraph: string,
62 : reconnect?: boolean,
63 : troubleshoot?: boolean,
64 : onTroubleshoot?: () => void,
65 : onReconnect?: () => void,
66 16 : }) => {
67 16 : return (
68 16 : <div id="early-failure-ready" className="curtains-ct">
69 16 : <Page className="pf-m-no-sidebar">
70 16 : <PageSection hasBodyWrapper={false}>
71 8 : <EmptyStatePanel {... !loading ? { icon: ExclamationCircleIcon } : {} }
72 16 : loading={loading}
73 16 : title={title}
74 16 : action={<>
75 16 : {reconnect &&
76 11 : <Button id="machine-reconnect" onClick={onReconnect}>
77 11 : {_("Reconnect")}
78 11 : </Button>}
79 16 : {troubleshoot &&
80 8 : <Button id="machine-troubleshoot" onClick={onTroubleshoot}>
81 8 : {_("Log in")}
82 8 : </Button>}
83 16 : </>}
84 16 : paragraph={paragraph} />
85 16 : </PageSection>
86 16 : </Page>
87 16 : </div>
88 : );
89 16 : };
90 :
91 3 : export const Disconnected = ({
92 3 : problem
93 3 : } : {
94 : problem: string
95 3 : }) => {
96 3 : return (
97 3 : <EarlyFailureReady title={_("Disconnected")}
98 3 : reconnect
99 0 : onReconnect={() => {
100 0 : cockpit.sessionStorage.clear();
101 0 : window.location.reload();
102 0 : }}
103 3 : paragraph={cockpit.message(problem)} />
104 : );
105 3 : };
106 :
107 13 : export const MachineTroubleshoot = ({
108 13 : machine,
109 13 : onClick
110 13 : } : {
111 : machine: Machine,
112 : onClick: () => void
113 13 : }) => {
114 13 : const connecting = (machine.state == "connecting");
115 13 : let title;
116 13 : let message;
117 3 : if (machine.restarting) {
118 3 : title = _("The machine is rebooting");
119 3 : message = "";
120 3 : } else if (connecting) {
121 12 : title = _("Connecting to the machine");
122 12 : message = "";
123 8 : } else {
124 9 : title = _("Not connected to host");
125 8 : if (machine.problem == "not-found") {
126 8 : message = _("Cannot connect to an unknown host");
127 7 : } else {
128 8 : const error = machine.problem || machine.state;
129 8 : if (error)
130 4 : message = cockpit.message(error);
131 : else
132 8 : message = "";
133 8 : }
134 9 : }
135 :
136 13 : let troubleshooting = false;
137 :
138 8 : if (!machine.restarting && (machine.problem === "no-host" || (machine.problem && machine.problem in codes))) {
139 8 : troubleshooting = true;
140 8 : }
141 :
142 13 : const restarting = !!machine.restarting;
143 8 : const reconnect = !connecting && machine.problem != "not-found" && !troubleshooting;
144 :
145 13 : return (
146 9 : <EarlyFailureReady loading={connecting || restarting}
147 13 : title={title}
148 13 : reconnect={reconnect}
149 13 : troubleshoot={troubleshooting}
150 13 : onTroubleshoot={onClick}
151 13 : onReconnect={onClick}
152 13 : paragraph={message} />
153 : );
154 13 : };
|