Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/compute/cloud/common/disk.tsx
Views: 687
import { useEffect, useState } from "react";1import { Icon } from "@cocalc/frontend/components/icon";2import { A } from "@cocalc/frontend/components/A";3import { Alert, Button, InputNumber, Select, Space, Switch } from "antd";4import { SELECTOR_WIDTH } from "@cocalc/frontend/compute/google-cloud-config";5import { commas, currency, round2up } from "@cocalc/util/misc";6import {7markup,8hyperdiskCostParams,9DEFAULT_HYPERDISK_BALANCED_IOPS,10DEFAULT_HYPERDISK_BALANCED_THROUGHPUT,11} from "@cocalc/util/compute/cloud/google-cloud/compute-cost";1213interface Props {14setConfig;15configuration;16disabled?: boolean;17priceData;18state;19// if noType is shown, do not render anything related to disk types20noType?: boolean;21minSizeGb: number;22maxSizeGb: number;23computeDiskCost;24extraHelp?;25beforeBody?;26rate?;27}2829export default function Disk(props: Props) {30const {31setConfig,32configuration,33disabled,34priceData,35state = "deprovisioned",36noType,37minSizeGb,38maxSizeGb,39computeDiskCost,40extraHelp,41beforeBody,42rate,43} = props;44const [help, setHelp] = useState<boolean>(false);45const [newDiskSizeGb, setNewDiskSizeGb] = useState<number | null>(46configuration.diskSizeGb ?? minSizeGb,47);48const [newDiskType, setNewDiskType] = useState<string | null>(49configuration.diskType ?? "pd-standard",50);51useEffect(() => {52setNewDiskSizeGb(configuration.diskSizeGb ?? minSizeGb);53setNewDiskType(configuration.diskType ?? "pd-standard");54}, [configuration]);5556useEffect(() => {57if (newDiskSizeGb == null) {58return;59}60const min = minSizeGb;61if (newDiskSizeGb < min) {62setNewDiskSizeGb(min);63}64}, [configuration.image]);6566useEffect(() => {67const min = minSizeGb;68if ((newDiskSizeGb ?? 0) < min) {69setConfig({70diskSizeGb: min,71});72setNewDiskSizeGb(min);73}74}, [configuration.acceleratorType]);7576const { requiredMachineTypes, supportedMachineTypes } = priceData?.extra?.[77"hyperdisk-balanced"78] ?? { requiredMachineTypes: [], supportedMachineTypes: [] };79const machineType = configuration.machineType?.split("-")[0];8081return (82<div>83<div style={{ color: "#666", marginBottom: "5px" }}>84<Switch85size="small"86checkedChildren={"Help"}87unCheckedChildren={"Help"}88style={{ float: "right" }}89checked={help}90onChange={(val) => setHelp(val)}91/>92<b>93<Icon name="disk-drive" /> Persistent Disk Storage94</b>95</div>96{help && (97<Alert98showIcon99style={{ margin: "15px 0" }}100type="info"101message={"Persistent Disk Storage"}102description={103<div style={{ color: "#666", margin: "10px 0" }}>104<p>105You are charged for storage as long as the server is provisioned106(even if it is off).{" "}107<b>108If you run out of credit or hit your spending limit and don't109pay, then the disk will be automatically deleted.110</b>111</p>112<p>113While the server is running,{" "}114<i>115you can increase the disk size <b>without</b> restarting the116server117</i>118, and it will resize within a minute. You do not have to119manually do anything (e.g., reboot or use command line tools)120after increasing the disk size.121</p>122{extraHelp}123</div>124}125/>126)}{" "}127{beforeBody}128<p>129Configure the size of the persistent disk130{noType131? ""132: " and the type of storage, which determines how fast the disk is"}133.134</p>135<Space direction="vertical">136<InputNumber137style={{ width: SELECTOR_WIDTH }}138disabled={disabled}139min={140state == "deprovisioned"141? minSizeGb142: configuration.diskSizeGb ?? minSizeGb143}144max={maxSizeGb}145value={newDiskSizeGb}146addonAfter="GB"147onChange={(diskSizeGb) => {148setNewDiskSizeGb(diskSizeGb);149}}150onBlur={() => {151if (state == "deprovisioned") {152// only set on blur or every keystroke rerenders and cause loss of focus.153setConfig({154diskSizeGb: newDiskSizeGb ?? minSizeGb,155});156}157}}158/>159{state != "deprovisioned" &&160!disabled &&161newDiskSizeGb != null &&162(configuration.diskSizeGb ?? minSizeGb) != newDiskSizeGb && (163<Button164type="primary"165onClick={() => {166setConfig({167diskSizeGb: newDiskSizeGb,168});169}}170>171Enlarge by{" "}172{newDiskSizeGb - (configuration.diskSizeGb ?? minSizeGb)}{" "}173GB (additional cost{" "}174{rate ? <> at {rate} </> : undefined} is 175{currency(176computeDiskCost({177configuration: {178...configuration,179diskSizeGb:180newDiskSizeGb - (configuration.diskSizeGb ?? minSizeGb),181},182priceData,183}) * 730,184)}185/month)186</Button>187)}188</Space>189<div style={{ color: "#666", margin: "10px 0" }}>190Set the size between{" "}191{state == "deprovisioned" ? (192<Button193size="small"194onClick={() => {195setConfig({196diskSizeGb: minSizeGb,197});198}}199>200{minSizeGb} GB201</Button>202) : (203<>{minSizeGb} GB</>204)}{" "}205and {commas(maxSizeGb)} GB.206{state != "deprovisioned" && (207<>208{" "}209<b>210You can increase the disk size at any time, even while the VM is211running.{" "}212</b>213You <b>cannot decrease the size</b>, without first deprovisioning214the server.215</>216)}217</div>218{!noType && (219<div>220<Space>221<Select222style={{ width: SELECTOR_WIDTH }}223disabled={224disabled || (state ?? "deprovisioned") != "deprovisioned"225}226value={newDiskType}227onChange={(diskType) => {228setNewDiskType(diskType);229setConfig({ diskType: diskType ?? "pd-standard" });230}}231options={[232{233disabled: requiredMachineTypes.includes(machineType),234value: "pd-balanced",235label: (236<div>237Balanced (SSD) disk{" "}238<div style={{ fontFamily: "monospace", float: "right" }}>239{currency(240markup({241cost:242priceData.disks["pd-balanced"]?.prices[243configuration.region244] * 730,245priceData,246}),247)}248/GB per month249</div>250</div>251),252},253{254disabled: requiredMachineTypes.includes(machineType),255value: "pd-ssd",256label: (257<div>258Performance (SSD) disk{" "}259<div style={{ fontFamily: "monospace", float: "right" }}>260{currency(261markup({262cost:263priceData.disks["pd-ssd"]?.prices[264configuration.region265] * 730,266priceData,267}),268)}269/GB per month270</div>271</div>272),273},274{275disabled: requiredMachineTypes.includes(machineType),276value: "pd-standard",277label: (278<div>279Standard (HDD) disk{" "}280<div style={{ fontFamily: "monospace", float: "right" }}>281{currency(282markup({283cost:284priceData.disks["pd-standard"]?.prices[285configuration.region286] * 730,287priceData,288}),289)}290/GB per month291</div>292</div>293),294},295{296disabled: !supportedMachineTypes.includes(machineType),297value: "hyperdisk-balanced",298label: (299<div>300Hyperdisk301<div style={{ fontFamily: "monospace", float: "right" }}>302<HyperdiskCost303region={configuration.region}304priceData={priceData}305/>306</div>307</div>308),309},310]}311></Select>312{configuration.diskType != "hyperdisk-balanced" && (313<div style={{ marginLeft: "15px" }}>314<b>Total Cost for {commas(configuration.diskSizeGb)} GB:</b>{" "}315{currency(316markup({317cost:318configuration.diskSizeGb *319priceData.disks[configuration.diskType]?.prices[320configuration.region321],322priceData,323}),324)}325/hour or{" "}326{currency(327markup({328cost:329configuration.diskSizeGb *330priceData.disks[configuration.diskType]?.prices[331configuration.region332] *333730,334priceData,335}),336)}337/month338</div>339)}340</Space>341342{newDiskType == "pd-standard" && (343<div style={{ marginTop: "10px", color: "#666" }}>344<b>WARNING:</b> Small standard disks are slow. Expect an extra34510s-30s of startup time and slower application start. Balanced346disks are much faster.347</div>348)}349{newDiskType == "hyperdisk-balanced" && (350<HyperdiskInfo351diskSizeGb={configuration.diskSizeGb}352priceData={priceData}353region={configuration.region}354style={{ marginTop: "15px" }}355/>356)}357</div>358)}359</div>360);361}362363function HyperdiskCost({ region, priceData }) {364const { capacity, iops, throughput } = hyperdiskCostParams({365region,366priceData,367});368const costProvisioned = markup({369cost:370iops * DEFAULT_HYPERDISK_BALANCED_IOPS +371throughput * DEFAULT_HYPERDISK_BALANCED_THROUGHPUT,372priceData,373});374return (375<div>376{currency(730 * costProvisioned)} +{" "}377{currency(378markup({379cost: capacity * 730,380priceData,381}),382)}383/GB per month384</div>385);386}387388function HyperdiskInfo({ priceData, style, region, diskSizeGb }) {389const { capacity, iops, throughput } = hyperdiskCostParams({390region,391priceData,392});393const { requiredMachineTypes, supportedMachineTypes } =394priceData.extra["hyperdisk-balanced"];395const costProvisioned = markup({396cost:397iops * DEFAULT_HYPERDISK_BALANCED_IOPS +398throughput * DEFAULT_HYPERDISK_BALANCED_THROUGHPUT,399priceData,400});401const costCapacity = markup({ cost: capacity * diskSizeGb, priceData });402// NOTE: I did benchmarks and you get about 12MB/s even with 32 cpus.403// I think th bandwidth is capped by iops/256 = 3000/256 = 11.71875,404// even though the google docs say it's the min of that and some other405// huge number (i.e., the docs are backwards and wrong).406// https://cloud.google.com/compute/docs/disks/hyperdisks#hyperdisks407// "Min throughput The greater of IOPS divided by 256 or 140 MBps"408// But it should be "lesser" not "greater"!409return (410<Alert411style={style}412showIcon413type="info"414message={"Balanced Hyperdisks"}415description={416<>417Balanced hyperdisks provide {commas(DEFAULT_HYPERDISK_BALANCED_IOPS)}{" "}418<A href="https://cloud.google.com/compute/docs/disks/hyperdisks#hyperdisks">419IOPS420</A>{" "}421for any size disk. They can be used with machine types{" "}422{supportedMachineTypes.join(", ")} and are required for{" "}423{requiredMachineTypes.join(", ")}. The monthly cost is a fixed424provisioning cost, plus a cost per GB of data:425<div style={{ textAlign: "center", marginTop: "10px" }}>426{currency(costProvisioned * 730)}... + 427{diskSizeGb} GB ×{" "}428{currency(429markup({430cost: capacity * 730,431priceData,432}),433)}434.../GB per month ~ 435{currency(round2up(730 * (costProvisioned + costCapacity)))} per436month437</div>438</>439}440/>441);442}443444445