Skip to content

Commit

Permalink
feat: 接入 scowd (#1193)
Browse files Browse the repository at this point in the history
完成 scow 对接 scowd 一期的改造,主要完成 HPC 文件和桌面相关功能改造

---------

Co-authored-by: Chen Junda <[email protected]>
  • Loading branch information
Miracle575 and ddadaal authored Jun 18, 2024
1 parent 5b6af87 commit 806f778
Show file tree
Hide file tree
Showing 37 changed files with 5,943 additions and 4,014 deletions.
8 changes: 8 additions & 0 deletions .changeset/brown-boats-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@scow/portal-server": minor
"@scow/scowd-protos": minor
"@scow/lib-scowd": minor
"@scow/cli": minor
---

增加 HPC 文件和桌面功能的 scowd 支持
5 changes: 5 additions & 0 deletions .changeset/tricky-cooks-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@scow/config": minor
---

增加 scowd 配置
5 changes: 5 additions & 0 deletions .changeset/wise-buses-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@scow/grpc-api": minor
---

获取配置时返回 scowd 的配置
17 changes: 15 additions & 2 deletions apps/cli/src/compose/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,28 @@ export const createComposeSpec = (config: InstallConfigSchema) => {
// PORTAL
if (config.portal) {

const configPath = "/etc/scow";

const portalBasePath = join(BASE_PATH, PORTAL_PATH);

const scowdSslCaCertPath = config.scowd?.ssl?.caCertPath ?
join(configPath, config.scowd.ssl.caCertPath) : "";
const scowdSslScowCertPath = config.scowd?.ssl?.scowCertPath ?
join(configPath, config.scowd.ssl.scowCertPath) : "";
const scowdSslScowPrivateKeyPath = config.scowd?.ssl?.scowPrivateKeyPath ?
join(configPath, config.scowd.ssl.scowPrivateKeyPath) : "";

composeSpec.volumes["portal_data"] = {};

addService("portal-server", {
image: scowImage,
environment: {
SCOW_LAUNCH_APP: "portal-server",
PORTAL_BASE_PATH: portalBasePath,
SCOWD_SSL_ENABLED: String(config.scowd?.ssl?.enabled ?? false),
SCOWD_SSL_CA_CERT_PATH: scowdSslCaCertPath,
SCOWD_SSL_SCOW_CERT_PATH: scowdSslScowCertPath,
SCOWD_SSL_SCOW_PRIVATE_KEY_PATH: scowdSslScowPrivateKeyPath,
MIS_DEPLOYED: config.mis ? "true" : "false",
MIS_SERVER_URL: config.mis ? "mis-server:5000" : "",
...serviceLogEnv,
Expand All @@ -258,7 +271,7 @@ export const createComposeSpec = (config: InstallConfigSchema) => {
ports: config.portal.portMappings?.portalServer ? { [config.portal.portMappings.portalServer]: 5000 } : {},
volumes: {
"/etc/hosts": "/etc/hosts",
"./config": "/etc/scow",
"./config": configPath,
"~/.ssh": "/root/.ssh",
"portal_data":"/var/lib/scow/portal",
},
Expand Down Expand Up @@ -286,7 +299,7 @@ export const createComposeSpec = (config: InstallConfigSchema) => {
ports: {},
volumes: {
"/etc/hosts": "/etc/hosts",
"./config": "/etc/scow",
"./config": configPath,
},
});

Expand Down
15 changes: 15 additions & 0 deletions apps/cli/src/config/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ export const InstallConfigSchema = Type.Object({
image: Type.Optional(Type.String({ description: "镜像", default: "mirrors.pku.edu.cn/pkuhpc-icode/scow" })),
imageTag: Type.String({ description: "镜像tag", default: "master" }),

scowd: Type.Optional(Type.Object({
ssl: Type.Optional(Type.Object({
enabled: Type.Boolean({ description: "到 SCOWD 的连接是否启动SSL", default: false }),
caCertPath: Type.String({ description: "SCOWD CA根证书路径, 相对 config 的默认目录", default: "./scowd/certs/ca.crt" }),
scowCertPath: Type.String({
description: "SCOWD CA签名的 SCOW 证书路径, 相对 config 的默认目录",
default: "./scowd/certs/scow.crt",
}),
scowPrivateKeyPath: Type.String({
description: "SCOWD CA签名的 SCOW 私钥路径, 相对 config 的默认目录",
default: "./scowd/certs/scow.key",
}),
}, { description: "scowd 全局 ssl 相关配置" })),
}, { description: "全局 scowd 相关配置" })),

log: Type.Object({
level: Type.String({ description: "日志级别", default: "info" }),
pretty: Type.Boolean({ description: "日志格式", default: false }),
Expand Down
7 changes: 5 additions & 2 deletions apps/portal-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,22 @@
"license": "Mulan PSL v2",
"repository": "https://github.com/PKUHPC/SCOW",
"dependencies": {
"@connectrpc/connect": "1.4.0",
"@ddadaal/tsgrpc-common": "0.2.5",
"@ddadaal/tsgrpc-server": "0.19.5",
"@ddadaal/tsgrpc-client": "0.17.7",
"@grpc/grpc-js": "1.10.6",
"@scow/config": "workspace:*",
"@scow/lib-config": "workspace:*",
"@scow/lib-scheduler-adapter": "workspace:*",
"@scow/lib-scowd": "workspace:*",
"@scow/lib-server": "workspace:*",
"@scow/lib-ssh": "workspace:*",
"@scow/protos": "workspace:*",
"@scow/rich-error-model": "workspace:*",
"@scow/scheduler-adapter-protos": "workspace:*",
"@scow/lib-scheduler-adapter": "workspace:*",
"@scow/scowd-protos": "workspace:*",
"@scow/utils": "workspace:*",
"@scow/rich-error-model": "workspace:*",
"@sinclair/typebox": "0.32.20",
"dayjs": "1.11.10",
"dotenv": "16.4.5",
Expand Down
5 changes: 3 additions & 2 deletions apps/portal-server/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ export async function createServer() {
}

await server.register(appServiceServer);
await server.register(desktopServiceServer);
await server.register(jobServiceServer);
await server.register(fileServiceServer);
await server.register(shellServiceServer);
await server.register(staticConfigServiceServer);
await server.register(runtimeConfigServiceServer);
await server.register(dashboardServiceServer);
await server.register(fileServiceServer);
await server.register(desktopServiceServer);


if (process.env.NODE_ENV === "production") {
await checkClustersRootUserLogin(server.logger);
Expand Down
70 changes: 70 additions & 0 deletions apps/portal-server/src/clusterops/api/desktop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { Logger } from "ts-log";

export interface CreateDesktopRequest {
loginNode: string;
userId: string;
wm: string;
desktopName: string;
}

export interface CreateDesktopReply {
host: string;
port: number;
password: string;
}

export interface KillDesktopRequest {
loginNode: string;
userId: string;
displayId: number;
}

export interface KillDesktopReply {}

export interface ConnectToDesktopRequest {
loginNode: string;
userId: string;
displayId: number;
}

export interface ConnectToDesktopReply {
host: string;
port: number;
password: string;
}

export interface ListUserDesktopsRequest {
userId: string;
loginNode: string;
}

export interface Desktop {
displayId: number;
desktopName: string;
wm: string;
createTime?: string;
}

export interface ListUserDesktopsReply {
host: string;
desktops: Desktop[]
}

export interface DesktopOps {
createDesktop(req: CreateDesktopRequest, logger: Logger): Promise<CreateDesktopReply>;
killDesktop(req: KillDesktopRequest, logger: Logger): Promise<KillDesktopReply>;
connectToDesktop(req: ConnectToDesktopRequest, logger: Logger): Promise<ConnectToDesktopReply>;
listUserDesktops(req: ListUserDesktopsRequest, logger: Logger): Promise<ListUserDesktopsReply>;
}
162 changes: 162 additions & 0 deletions apps/portal-server/src/clusterops/api/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { ReaderExtensions } from "@ddadaal/tsgrpc-common";
import { ObjectWritable } from "@grpc/grpc-js/build/src/object-stream";
import { Logger } from "ts-log";

export interface CopyRequest {
userId: string;
fromPath: string;
toPath: string;
}

export interface CopyReply {}

export interface MoveRequest {
userId: string;
fromPath: string;
toPath: string;
}

export interface MoveReply {}

export interface ExistsRequest {
userId: string;
path: string;
}

export interface ExistsReply {
exists: boolean;
}


export interface CreateFileRequest {
userId: string;
path: string;
}

export interface CreateFileReply {}

export interface DeleteDirectoryRequest {
userId: string;
path: string;
}

export interface DeleteDirectoryReply {}

export interface DeleteFileRequest {
userId: string;
path: string;
}

export interface DeleteFileReply {}

export interface ReadDirectoryRequest {
userId: string;
path: string;
updateAccessTime?: boolean
}

export interface FileInfo {
name: string;
type: FileInfo_FileType;
mtime: string;
mode: number;
size: number;
}

export enum FileInfo_FileType {
FILE = 0,
DIR = 1,
}

export interface ReadDirectoryReply {
results: FileInfo[];
}


export interface GetHomeDirectoryRequest {
userId: string;
}

export interface GetHomeDirectoryReply {
path: string;
}

export interface MakeDirectoryRequest {
userId: string;
path: string;
}

export interface MakeDirectoryReply {}

export interface DownloadRequest {
userId: string;
path: string;
call: ObjectWritable<{ chunk: Uint8Array }>
}

export interface DownloadReply {}

interface UploadRequest_Info {
userId: string;
path: string;
}

interface UploadRequest_ReadStream {
message?: { $case: "info"; info: UploadRequest_Info } | { $case: "chunk"; chunk: Uint8Array } | undefined
}

export interface UploadRequest {
userId: string;
path: string;
call: ReaderExtensions<UploadRequest_ReadStream>
}

export interface UploadReply {
writtenBytes: number;
}

export interface GetFileMetadataRequest {
userId: string;
path: string;
}

export interface GetFileMetadataReply {
size: number;
type: string;
}

export interface FileOps {
copy(req: CopyRequest, logger: Logger): Promise<CopyReply>;
move(req: MoveRequest, logger: Logger): Promise<MoveReply>;
exists(req: ExistsRequest, logger: Logger): Promise<ExistsReply>;

createFile(req: CreateFileRequest, logger: Logger): Promise<CreateFileReply>;
deleteFile(req: DeleteFileRequest, logger: Logger): Promise<DeleteFileReply>;

readDirectory(req: ReadDirectoryRequest, logger: Logger): Promise<ReadDirectoryReply>;
deleteDirectory(req: DeleteDirectoryRequest, logger: Logger): Promise<DeleteDirectoryReply>;
getHomeDirectory(req: GetHomeDirectoryRequest, logger: Logger): Promise<GetHomeDirectoryReply>;
makeDirectory(req: MakeDirectoryRequest, logger: Logger): Promise<MakeDirectoryReply>;

upload(req: UploadRequest, logger: Logger): Promise<UploadReply>;
download(req: DownloadRequest, logger: Logger): Promise<DownloadReply>;

getFileMetadata(req: GetFileMetadataRequest, logger: Logger): Promise<GetFileMetadataReply>;

// StartFileTransfer(req: StartFileTransferRequest, logger: Logger): Promise<StartFileTransferReply>;
// QueryFileTransfer(req: QueryFileTransferRequest, logger: Logger): Promise<QueryFileTransferReply>;
// TerminateFileTransfer(req: TerminateFileTransferRequest, logger: Logger): Promise<TerminateFileTransferReply>;
// CheckTransferKey(req: CheckTransferKeyRequest, logger: Logger): Promise<CheckTransferKeyReply>;
}
4 changes: 4 additions & 0 deletions apps/portal-server/src/clusterops/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
*/

import { AppOps } from "src/clusterops/api/app";
import { DesktopOps } from "src/clusterops/api/desktop";
import { FileOps } from "src/clusterops/api/file";
import { JobOps } from "src/clusterops/api/job";

export interface ClusterOps {
app: AppOps;
job: JobOps;
desktop: DesktopOps;
file: FileOps;
}
Loading

0 comments on commit 806f778

Please sign in to comment.