Disabled speedtest in standalone mode (#1278)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
@@ -121,6 +121,7 @@ export const IAM_SCOPES = {
|
||||
ADMIN_CREATE_POLICY: "admin:CreatePolicy",
|
||||
ADMIN_DELETE_POLICY: "admin:DeletePolicy",
|
||||
ADMIN_ATTACH_USER_OR_GROUP_POLICY: "admin:AttachUserOrGroupPolicy",
|
||||
ADMIN_HEAL_ACTION: "admin:Heal",
|
||||
S3_ALL_ACTIONS: "s3:*",
|
||||
ADMIN_ALL_ACTIONS: "admin:*",
|
||||
};
|
||||
@@ -179,6 +180,7 @@ export const IAM_PERMISSIONS = {
|
||||
IAM_SCOPES.ADMIN_GET_POLICY,
|
||||
IAM_SCOPES.ADMIN_LIST_USER_POLICIES,
|
||||
IAM_SCOPES.ADMIN_LIST_USERS,
|
||||
IAM_SCOPES.ADMIN_HEAL_ACTION,
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ interface ISettingsCard {
|
||||
classes: any;
|
||||
configuration: IElement;
|
||||
prefix?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
@@ -53,6 +54,11 @@ const styles = (theme: Theme) =>
|
||||
"&:hover": {
|
||||
backgroundColor: "#FBFAFA",
|
||||
},
|
||||
"&.disabled": {
|
||||
backgroundColor: "#F9F9F9",
|
||||
color: "#ababab",
|
||||
cursor: "not-allowed"
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -60,11 +66,14 @@ const SettingsCard = ({
|
||||
classes,
|
||||
configuration,
|
||||
prefix = "settings",
|
||||
disabled = false,
|
||||
}: ISettingsCard) => {
|
||||
return (
|
||||
<Link
|
||||
to={`/${prefix}/${configuration.configuration_id}`}
|
||||
className={classes.configurationLink}
|
||||
to={
|
||||
disabled ? `/${prefix}` : `/${prefix}/${configuration.configuration_id}`
|
||||
}
|
||||
className={`${classes.configurationLink} ${disabled ? "disabled" : ""}`}
|
||||
>
|
||||
{configuration.icon}
|
||||
{configuration.configuration_label}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { HorizontalBar } from "react-chartjs-2";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
@@ -40,6 +41,10 @@ import {
|
||||
inlineCheckboxes,
|
||||
searchField,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
IAM_SCOPES,
|
||||
} from "../../../common/SecureComponent/permissions";
|
||||
import { AppState } from "../../../store";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import CheckboxWrapper from "../Common/FormComponents/CheckboxWrapper/CheckboxWrapper";
|
||||
@@ -47,6 +52,7 @@ import PageHeader from "../Common/PageHeader/PageHeader";
|
||||
import api from "../../../common/api";
|
||||
import BackLink from "../../../common/BackLink";
|
||||
import PageLayout from "../Common/Layout/PageLayout";
|
||||
import SecureComponent from "../../../common/SecureComponent/SecureComponent";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -273,128 +279,134 @@ const Heal = ({ classes, distributedSetup }: IHeal) => {
|
||||
<PageHeader label="Heal" />
|
||||
<BackLink to="/tools" label="Return to Tools" />
|
||||
<PageLayout>
|
||||
<Grid xs={12} className={classes.formBox}>
|
||||
<Grid item xs={12} className={classes.actionsTray}>
|
||||
<FormControl variant="outlined" className={classes.bucketField}>
|
||||
<Select
|
||||
label="Bucket"
|
||||
id="bucket-name"
|
||||
name="bucket-name"
|
||||
value={bucketName}
|
||||
onChange={(e) => {
|
||||
setBucketName(e.target.value as string);
|
||||
}}
|
||||
className={classes.searchField}
|
||||
input={<SelectStyled />}
|
||||
displayEmpty
|
||||
>
|
||||
<MenuItem value="" key={`select-bucket-name-default`}>
|
||||
Select Bucket
|
||||
</MenuItem>
|
||||
{bucketNames.map((option) => (
|
||||
<MenuItem
|
||||
value={option.value}
|
||||
key={`select-bucket-name-${option.label}`}
|
||||
>
|
||||
{option.label}
|
||||
<SecureComponent
|
||||
scopes={[IAM_SCOPES.ADMIN_HEAL_ACTION]}
|
||||
resource={CONSOLE_UI_RESOURCE}
|
||||
RenderError={<Redirect to={"/"} />}
|
||||
>
|
||||
<Grid xs={12} className={classes.formBox}>
|
||||
<Grid item xs={12} className={classes.actionsTray}>
|
||||
<FormControl variant="outlined" className={classes.bucketField}>
|
||||
<Select
|
||||
label="Bucket"
|
||||
id="bucket-name"
|
||||
name="bucket-name"
|
||||
value={bucketName}
|
||||
onChange={(e) => {
|
||||
setBucketName(e.target.value as string);
|
||||
}}
|
||||
className={classes.searchField}
|
||||
input={<SelectStyled />}
|
||||
displayEmpty
|
||||
>
|
||||
<MenuItem value="" key={`select-bucket-name-default`}>
|
||||
Select Bucket
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<TextField
|
||||
label="Prefix"
|
||||
className={classes.prefixField}
|
||||
id="prefix-resource"
|
||||
disabled={false}
|
||||
InputProps={{
|
||||
disableUnderline: true,
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setPrefix(e.target.value);
|
||||
}}
|
||||
variant="standard"
|
||||
/>
|
||||
{bucketNames.map((option) => (
|
||||
<MenuItem
|
||||
value={option.value}
|
||||
key={`select-bucket-name-${option.label}`}
|
||||
>
|
||||
{option.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<TextField
|
||||
label="Prefix"
|
||||
className={classes.prefixField}
|
||||
id="prefix-resource"
|
||||
disabled={false}
|
||||
InputProps={{
|
||||
disableUnderline: true,
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setPrefix(e.target.value);
|
||||
}}
|
||||
variant="standard"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.inlineCheckboxes}>
|
||||
<CheckboxWrapper
|
||||
name="recursive"
|
||||
id="recursive"
|
||||
classes={classes}
|
||||
value="recursive"
|
||||
checked={recursive}
|
||||
onChange={(e) => {
|
||||
setRecursive(e.target.checked);
|
||||
}}
|
||||
disabled={false}
|
||||
label="Recursive"
|
||||
/>
|
||||
<CheckboxWrapper
|
||||
name="forceStart"
|
||||
id="forceStart"
|
||||
classes={classes}
|
||||
value="forceStart"
|
||||
checked={forceStart}
|
||||
onChange={(e) => {
|
||||
setForceStart(e.target.checked);
|
||||
}}
|
||||
disabled={false}
|
||||
label="Force Start"
|
||||
/>
|
||||
<CheckboxWrapper
|
||||
name="forceStop"
|
||||
id="forceStop"
|
||||
classes={classes}
|
||||
value="forceStop"
|
||||
checked={forceStop}
|
||||
onChange={(e) => {
|
||||
setForceStop(e.target.checked);
|
||||
}}
|
||||
disabled={false}
|
||||
label="Force Stop"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.buttonBar}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={start}
|
||||
onClick={() => setStart(true)}
|
||||
>
|
||||
Start
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.inlineCheckboxes}>
|
||||
<CheckboxWrapper
|
||||
name="recursive"
|
||||
id="recursive"
|
||||
classes={classes}
|
||||
value="recursive"
|
||||
checked={recursive}
|
||||
onChange={(e) => {
|
||||
setRecursive(e.target.checked);
|
||||
<Grid item xs={12} className={classes.graphContainer}>
|
||||
<HorizontalBar
|
||||
data={data}
|
||||
width={80}
|
||||
height={30}
|
||||
options={{
|
||||
title: {
|
||||
display: true,
|
||||
text: "Item's Health Status [%]",
|
||||
fontSize: 20,
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: "right",
|
||||
},
|
||||
}}
|
||||
disabled={false}
|
||||
label="Recursive"
|
||||
/>
|
||||
<CheckboxWrapper
|
||||
name="forceStart"
|
||||
id="forceStart"
|
||||
classes={classes}
|
||||
value="forceStart"
|
||||
checked={forceStart}
|
||||
onChange={(e) => {
|
||||
setForceStart(e.target.checked);
|
||||
}}
|
||||
disabled={false}
|
||||
label="Force Start"
|
||||
/>
|
||||
<CheckboxWrapper
|
||||
name="forceStop"
|
||||
id="forceStop"
|
||||
classes={classes}
|
||||
value="forceStop"
|
||||
checked={forceStop}
|
||||
onChange={(e) => {
|
||||
setForceStop(e.target.checked);
|
||||
}}
|
||||
disabled={false}
|
||||
label="Force Stop"
|
||||
/>
|
||||
<Grid item xs={12} className={classes.scanInfo}>
|
||||
<div className={classes.scanData}>
|
||||
<strong>Size scanned:</strong> {hStatus.sizeScanned}
|
||||
</div>
|
||||
<div className={classes.scanData}>
|
||||
<strong>Objects healed:</strong> {hStatus.objectsHealed} /{" "}
|
||||
{hStatus.objectsScanned}
|
||||
</div>
|
||||
<div className={classes.scanData}>
|
||||
<strong>Healing time:</strong> {hStatus.healDuration}s
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.buttonBar}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={start}
|
||||
onClick={() => setStart(true)}
|
||||
>
|
||||
Start
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.graphContainer}>
|
||||
<HorizontalBar
|
||||
data={data}
|
||||
width={80}
|
||||
height={30}
|
||||
options={{
|
||||
title: {
|
||||
display: true,
|
||||
text: "Item's Health Status [%]",
|
||||
fontSize: 20,
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: "right",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Grid item xs={12} className={classes.scanInfo}>
|
||||
<div className={classes.scanData}>
|
||||
<strong>Size scanned:</strong> {hStatus.sizeScanned}
|
||||
</div>
|
||||
<div className={classes.scanData}>
|
||||
<strong>Objects healed:</strong> {hStatus.objectsHealed} /{" "}
|
||||
{hStatus.objectsScanned}
|
||||
</div>
|
||||
<div className={classes.scanData}>
|
||||
<strong>Healing time:</strong> {hStatus.healDuration}s
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</SecureComponent>
|
||||
</PageLayout>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket";
|
||||
import { Button, CircularProgress, Grid } from "@mui/material";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Button, CircularProgress, Grid } from "@mui/material";
|
||||
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
||||
import moment from "moment/moment";
|
||||
import PageHeader from "../Common/PageHeader/PageHeader";
|
||||
@@ -31,6 +33,12 @@ import {
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import { wsProtocol } from "../../../utils/wsUtils";
|
||||
import { SpeedTestResponse } from "./types";
|
||||
import { AppState } from "../../../store";
|
||||
import { SpeedtestIcon } from "../../../icons";
|
||||
import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
IAM_SCOPES,
|
||||
} from "../../../common/SecureComponent/permissions";
|
||||
import STResults from "./STResults";
|
||||
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import BackLink from "../../../common/BackLink";
|
||||
@@ -38,9 +46,12 @@ import ProgressBarWrapper from "../Common/ProgressBarWrapper/ProgressBarWrapper"
|
||||
import InputUnitMenu from "../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import CheckboxWrapper from "../Common/FormComponents/CheckboxWrapper/CheckboxWrapper";
|
||||
import PageLayout from "../Common/Layout/PageLayout";
|
||||
import HelpBox from "../../../common/HelpBox";
|
||||
import SecureComponent from "../../../common/SecureComponent/SecureComponent";
|
||||
|
||||
interface ISpeedtest {
|
||||
classes: any;
|
||||
distributedSetup: boolean;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
@@ -74,7 +85,7 @@ const styles = (theme: Theme) =>
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
|
||||
const Speedtest = ({ classes }: ISpeedtest) => {
|
||||
const Speedtest = ({ classes, distributedSetup }: ISpeedtest) => {
|
||||
const [start, setStart] = useState<boolean>(false);
|
||||
|
||||
const [currStatus, setCurrStatus] = useState<SpeedTestResponse[] | null>(
|
||||
@@ -182,179 +193,235 @@ const Speedtest = ({ classes }: ISpeedtest) => {
|
||||
setSpeedometerValue(percToDisplay);
|
||||
}, [start, currentValue, topDate, totalSeconds]);
|
||||
|
||||
if (!distributedSetup) {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeader label="Speedtest" />
|
||||
<BackLink to="/tools" label="Return to Tools" />
|
||||
<PageLayout>
|
||||
<Grid
|
||||
container
|
||||
justifyContent={"center"}
|
||||
alignContent={"center"}
|
||||
alignItems={"center"}
|
||||
>
|
||||
<Grid item xs={8}>
|
||||
<HelpBox
|
||||
title={"Speedtest not available"}
|
||||
iconComponent={<SpeedtestIcon />}
|
||||
help={
|
||||
<Fragment>
|
||||
This feature is not available for a single-disk setup.
|
||||
<br />
|
||||
Please deploy a server in{" "}
|
||||
<a
|
||||
href="https://docs.min.io/minio/baremetal/installation/deploy-minio-distributed.html?ref=con"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Distributed Mode
|
||||
</a>{" "}
|
||||
to use this feature.
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</PageLayout>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeader label="Speedtest" />
|
||||
<BackLink to="/tools" label="Return to Tools" />
|
||||
|
||||
<PageLayout>
|
||||
<Grid item xs={12} className={classes.boxy}>
|
||||
<Grid container>
|
||||
<Grid item>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setCurrStatus(null);
|
||||
setStart(true);
|
||||
}}
|
||||
color="primary"
|
||||
type="button"
|
||||
variant={
|
||||
currStatus !== null && !start ? "contained" : "outlined"
|
||||
}
|
||||
className={`${classes.buttonBackground} ${classes.speedStart}`}
|
||||
disabled={duration.trim() === "" || size.trim() === "" || start}
|
||||
>
|
||||
{!start && (
|
||||
<Fragment>
|
||||
{currStatus !== null ? "Retest" : "Start"}
|
||||
</Fragment>
|
||||
)}
|
||||
{start ? "Start" : ""}
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item md={9} sm={12} className={classes.progressContainer}>
|
||||
<div className={classes.stepProgressText}>
|
||||
{start ? (
|
||||
"Speedtest in progress..."
|
||||
) : (
|
||||
<Fragment>
|
||||
{currStatus && !start ? "Done!" : "Start a new test"}
|
||||
</Fragment>
|
||||
)}
|
||||
{start && <CircularProgress size={15} />}
|
||||
</div>
|
||||
<div>
|
||||
<ProgressBarWrapper
|
||||
value={speedometerValue}
|
||||
ready={currStatus !== null && !start}
|
||||
indeterminate={autotune && start}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item className={classes.advancedButton}>
|
||||
<button
|
||||
onClick={() => {
|
||||
setAdvancedOpen(!advancedOpen);
|
||||
}}
|
||||
className={classes.advancedConfiguration}
|
||||
>
|
||||
{advancedOpen ? "Hide" : "Show"} advanced options{" "}
|
||||
<span
|
||||
className={
|
||||
advancedOpen ? classes.advancedOpen : classes.advancedClosed
|
||||
<SecureComponent
|
||||
scopes={[IAM_SCOPES.ADMIN_HEAL_ACTION]}
|
||||
resource={CONSOLE_UI_RESOURCE}
|
||||
RenderError={
|
||||
<Redirect to={'/'} />
|
||||
}
|
||||
>
|
||||
<Grid item xs={12} className={classes.boxy}>
|
||||
<Grid container>
|
||||
<Grid item>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setCurrStatus(null);
|
||||
setStart(true);
|
||||
}}
|
||||
color="primary"
|
||||
type="button"
|
||||
variant={
|
||||
currStatus !== null && !start ? "contained" : "outlined"
|
||||
}
|
||||
className={`${classes.buttonBackground} ${classes.speedStart}`}
|
||||
disabled={
|
||||
duration.trim() === "" || size.trim() === "" || start
|
||||
}
|
||||
>
|
||||
<ArrowForwardIosIcon />
|
||||
</span>
|
||||
</button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
className={`${classes.advancedContent} ${
|
||||
advancedOpen ? "open" : ""
|
||||
}`}
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
<CheckboxWrapper
|
||||
checked={autotune}
|
||||
onChange={(e) => setAutotune(e.target.checked)}
|
||||
id={"autotune"}
|
||||
name={"autotune"}
|
||||
label={"Enable Autotune"}
|
||||
tooltip={
|
||||
"Autotune gets the maximum stats for the system by running with multiple configurations at once. \
|
||||
This configuration is enabled by default and disables the rest of available options"
|
||||
}
|
||||
value="true"
|
||||
disabled={start}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3} className={classes.advancedOption}>
|
||||
<InputBoxWrapper
|
||||
id={"duration"}
|
||||
name={"duration"}
|
||||
label={"Duration"}
|
||||
onChange={(e) => {
|
||||
setDuration(e.target.value);
|
||||
}}
|
||||
value={duration}
|
||||
disabled={start || autotune}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"duration-unit"}
|
||||
onUnitChange={setDurationUnit}
|
||||
unitSelected={durationUnit}
|
||||
unitsList={[
|
||||
{ label: "miliseconds", value: "ms" },
|
||||
{ label: "seconds", value: "s" },
|
||||
]}
|
||||
disabled={start || autotune}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3} className={classes.advancedOption}>
|
||||
<InputBoxWrapper
|
||||
id={"size"}
|
||||
name={"size"}
|
||||
label={"Object Size"}
|
||||
onChange={(e) => {
|
||||
setSize(e.target.value);
|
||||
}}
|
||||
value={size}
|
||||
disabled={start || autotune}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={setSizeUnit}
|
||||
unitSelected={sizeUnit}
|
||||
unitsList={[
|
||||
{ label: "KB", value: "KB" },
|
||||
{ label: "MB", value: "MB" },
|
||||
{ label: "GB", value: "GB" },
|
||||
]}
|
||||
disabled={start || autotune}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3} className={classes.advancedOption}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id={"concurrent"}
|
||||
name={"concurrent"}
|
||||
label={"Concurrent Requests"}
|
||||
onChange={(e) => {
|
||||
setConcurrent(e.target.value);
|
||||
}}
|
||||
value={concurrent}
|
||||
disabled={start || autotune}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container className={classes.multiModule}>
|
||||
<Grid item xs={12}>
|
||||
<Fragment>
|
||||
<Grid item xs={12}>
|
||||
{currStatus !== null && (
|
||||
{!start && (
|
||||
<Fragment>
|
||||
<STResults
|
||||
results={currStatus}
|
||||
start={start}
|
||||
autotune={autotune}
|
||||
/>
|
||||
{currStatus !== null ? "Retest" : "Start"}
|
||||
</Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
</Fragment>
|
||||
{start ? "Start" : ""}
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item md={9} sm={12} className={classes.progressContainer}>
|
||||
<div className={classes.stepProgressText}>
|
||||
{start ? (
|
||||
"Speedtest in progress..."
|
||||
) : (
|
||||
<Fragment>
|
||||
{currStatus && !start ? "Done!" : "Start a new test"}
|
||||
</Fragment>
|
||||
)}
|
||||
{start && <CircularProgress size={15} />}
|
||||
</div>
|
||||
<div>
|
||||
<ProgressBarWrapper
|
||||
value={speedometerValue}
|
||||
ready={currStatus !== null && !start}
|
||||
indeterminate={autotune && start}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item className={classes.advancedButton}>
|
||||
<button
|
||||
onClick={() => {
|
||||
setAdvancedOpen(!advancedOpen);
|
||||
}}
|
||||
className={classes.advancedConfiguration}
|
||||
>
|
||||
{advancedOpen ? "Hide" : "Show"} advanced options{" "}
|
||||
<span
|
||||
className={
|
||||
advancedOpen
|
||||
? classes.advancedOpen
|
||||
: classes.advancedClosed
|
||||
}
|
||||
>
|
||||
<ArrowForwardIosIcon />
|
||||
</span>
|
||||
</button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
className={`${classes.advancedContent} ${
|
||||
advancedOpen ? "open" : ""
|
||||
}`}
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
<CheckboxWrapper
|
||||
checked={autotune}
|
||||
onChange={(e) => setAutotune(e.target.checked)}
|
||||
id={"autotune"}
|
||||
name={"autotune"}
|
||||
label={"Enable Autotune"}
|
||||
tooltip={
|
||||
"Autotune gets the maximum stats for the system by running with multiple configurations at once. \
|
||||
This configuration is enabled by default and disables the rest of available options"
|
||||
}
|
||||
value="true"
|
||||
disabled={start}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3} className={classes.advancedOption}>
|
||||
<InputBoxWrapper
|
||||
id={"duration"}
|
||||
name={"duration"}
|
||||
label={"Duration"}
|
||||
onChange={(e) => {
|
||||
setDuration(e.target.value);
|
||||
}}
|
||||
value={duration}
|
||||
disabled={start || autotune}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"duration-unit"}
|
||||
onUnitChange={setDurationUnit}
|
||||
unitSelected={durationUnit}
|
||||
unitsList={[
|
||||
{ label: "miliseconds", value: "ms" },
|
||||
{ label: "seconds", value: "s" },
|
||||
]}
|
||||
disabled={start || autotune}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3} className={classes.advancedOption}>
|
||||
<InputBoxWrapper
|
||||
id={"size"}
|
||||
name={"size"}
|
||||
label={"Object Size"}
|
||||
onChange={(e) => {
|
||||
setSize(e.target.value);
|
||||
}}
|
||||
value={size}
|
||||
disabled={start || autotune}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={setSizeUnit}
|
||||
unitSelected={sizeUnit}
|
||||
unitsList={[
|
||||
{ label: "KB", value: "KB" },
|
||||
{ label: "MB", value: "MB" },
|
||||
{ label: "GB", value: "GB" },
|
||||
]}
|
||||
disabled={start || autotune}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={3} className={classes.advancedOption}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id={"concurrent"}
|
||||
name={"concurrent"}
|
||||
label={"Concurrent Requests"}
|
||||
onChange={(e) => {
|
||||
setConcurrent(e.target.value);
|
||||
}}
|
||||
value={concurrent}
|
||||
disabled={start || autotune}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container className={classes.multiModule}>
|
||||
<Grid item xs={12}>
|
||||
<Fragment>
|
||||
<Grid item xs={12}>
|
||||
{currStatus !== null && (
|
||||
<Fragment>
|
||||
<STResults
|
||||
results={currStatus}
|
||||
start={start}
|
||||
autotune={autotune}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
</Fragment>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</SecureComponent>
|
||||
</PageLayout>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(Speedtest);
|
||||
const mapState = (state: AppState) => ({
|
||||
distributedSetup: state.system.distributedSetup,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
export default connector(withStyles(styles)(Speedtest));
|
||||
|
||||
@@ -88,6 +88,7 @@ const ToolsList = ({ classes }: IConfigurationOptions) => {
|
||||
prefix={"tools"}
|
||||
configuration={element}
|
||||
key={`configItem-${element.configuration_label}`}
|
||||
disabled={element.disabled || false}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -58,4 +58,5 @@ export interface IElement {
|
||||
configuration_id: string;
|
||||
configuration_label: string;
|
||||
icon?: any;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ import {
|
||||
WatchIcon,
|
||||
} from "../../../icons";
|
||||
import SpeedtestIcon from "../../../icons/SpeedtestIcon";
|
||||
import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
IAM_SCOPES,
|
||||
} from "../../../common/SecureComponent/permissions";
|
||||
import {
|
||||
hasPermission,
|
||||
} from "../../../common/SecureComponent/SecureComponent";
|
||||
|
||||
export const configurationElements: IElement[] = [
|
||||
{
|
||||
@@ -50,6 +57,9 @@ export const configurationElements: IElement[] = [
|
||||
icon: <HealIcon />,
|
||||
configuration_id: "heal",
|
||||
configuration_label: "heal",
|
||||
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
|
||||
IAM_SCOPES.ADMIN_HEAL_ACTION,
|
||||
]),
|
||||
},
|
||||
{
|
||||
icon: <DiagnosticsIcon />,
|
||||
@@ -60,5 +70,8 @@ export const configurationElements: IElement[] = [
|
||||
icon: <SpeedtestIcon />,
|
||||
configuration_id: "speedtest",
|
||||
configuration_label: "Speedtest",
|
||||
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
|
||||
IAM_SCOPES.ADMIN_HEAL_ACTION,
|
||||
]),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -116,10 +116,6 @@ func (c wsConn) readMessage() (messageType int, p []byte, err error) {
|
||||
// on the path.
|
||||
// Request should come like ws://<host>:<port>/ws/<api>
|
||||
func serveWS(w http.ResponseWriter, req *http.Request) {
|
||||
upgrader.CheckOrigin = func(r *http.Request) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Perform authentication before upgrading to a Websocket Connection
|
||||
// authenticate WS connection with Console
|
||||
session, err := auth.GetClaimsFromTokenInRequest(req)
|
||||
|
||||
Reference in New Issue
Block a user