in src/panels/KaitoModelsPanel.ts [199:316]
private async handleDeployKaitoRequest(
model: string,
yaml: string,
gpu: string,
webview: MessageSink<ToWebViewMsgDef>,
) {
this.cancelTokens.set(model, false);
this.handleResetStateRequest(webview);
// This prevents the user from redeploying while pre-deployment checks are being performed
if (this.checksInProgress) {
return;
}
try {
this.checksInProgress = true;
let quotaAvailable = false;
let getResult = null;
let readyStatus = { kaitoWorkspaceReady: false, kaitoGPUProvisionerReady: false };
await longRunning(`Validating KAITO workspace status`, async () => {
// Returns an object with the status of the kaito pods
const kaitoPods = await getKaitoPods(
this.sessionProvider,
this.kubectl,
this.subscriptionId,
this.resourceGroupName,
this.clusterName,
);
readyStatus = await kaitoPodStatus(this.clusterName, kaitoPods, this.kubectl, this.kubeConfigFilePath);
});
if (!readyStatus.kaitoWorkspaceReady || !readyStatus.kaitoGPUProvisionerReady) {
this.checksInProgress = false;
return;
}
// Catches if the user cancelled deployment at this point
if (this.cancelTokens.get(model)) {
this.handleDeploymentCancellation(model);
return;
}
await longRunning(`Checking if workspace exists...`, async () => {
const getCommand = `get workspace workspace-${model}`;
getResult = await invokeKubectlCommand(this.kubectl, this.kubeConfigFilePath, getCommand);
});
if (getResult === null || failed(getResult)) {
// Deployment cancellation check
if (this.cancelTokens.get(model)) {
this.handleDeploymentCancellation(model);
return;
}
await longRunning(`Verifying available subscription quota for deployment...`, async () => {
const [gpuFamily, requiredCPUs] = this.parseGPU(gpu);
void requiredCPUs;
const computeClient = getComputeManagementClient(this.sessionProvider, this.subscriptionId);
const containerServiceClient = getAksClient(this.sessionProvider, this.subscriptionId);
const cluster = await containerServiceClient.managedClusters.get(
this.resourceGroupName,
this.clusterName,
);
const quotas = computeClient.usageOperations.list(cluster.location);
let foundQuota = null;
foundQuota = await this.findMatchingQuota(quotas, gpuFamily);
if (!foundQuota || !this.isQuotaSufficient(foundQuota, requiredCPUs)) {
this.promptForQuotaIncrease();
} else {
quotaAvailable = true;
}
});
} else {
quotaAvailable = true;
}
if (!quotaAvailable) {
this.checksInProgress = false;
return;
}
// Deployment cancellation check
if (this.cancelTokens.get(model)) {
this.handleDeploymentCancellation(model);
return;
}
// Deploying model
const deploymentResult = await deployModel(yaml, this.kubectl, this.kubeConfigFilePath);
if (failed(deploymentResult)) {
vscode.window.showErrorMessage(`Error deploying 'workspace-${model}': ${deploymentResult.error}`);
this.checksInProgress = false;
return;
}
// Final checksInProgress set to false to allow for future deployments
this.checksInProgress = false;
} catch (error) {
this.checksInProgress = false;
vscode.window.showErrorMessage(`Error during deployment: ${error}`);
}
// end state updates if user cancelled out of view
if (this.cancelTokens.get(model)) {
vscode.window.showErrorMessage(`Deployment cancelled for ${model}`);
return;
}
// if cancel token is set for any other model, just return maybe?
this.updateProgress(model, webview);
let progress = await this.getProgress(model);
// Continuously polls deployment progress until completion, cancellation, or panel disposal.
while (
!this.nullIsFalse(progress.workspaceReady) &&
!this.cancelTokens.get(model) &&
existsSync(this.kubeConfigFilePath)
) {
// Error handling is done via updateProgress
progress = await this.updateProgress(model, webview);
// 5 second delay between each check
await new Promise((resolve) => setTimeout(resolve, 5000));
}
if (this.cancelTokens.get(model)) {
await this.handleResetStateRequest(webview);
} else {
await this.updateProgress(model, webview);
}
}