[Feat] Add Code-Server

This commit is contained in:
Harry-zklcdc 2025-01-15 17:49:32 +08:00
parent 28af2484a9
commit cda872521a
12 changed files with 128 additions and 18 deletions

View File

@ -66,9 +66,13 @@
<Column>
<template #body="{ data }">
<div class="flex gap-2">
<Button v-if="data.status == statusRunning" icon="pi pi-inbox" aria-label="Filter" as="a"
<Button v-if="data.status == statusRunning" icon="pi pi-code" aria-label="Filter" as="a"
:href="'http://' + data.code_server_address" target="_blank" v-tooltip.top="'VSCode Web'" />
<Button v-else icon="pi pi-code" aria-label="Filter" v-tooltip.top="'VSCode Web'" disabled />
<Button v-if="data.status == statusRunning" severity="info" icon="pi pi-inbox" aria-label="Filter" as="a"
:href="'http://' + data.jupyter_address + '/lab'" target="_blank" v-tooltip.top="'Jupter Lab'" />
<Button v-else icon="pi pi-inbox" aria-label="Filter" v-tooltip.top="'Jupter Lab'" disabled />
<Button v-else severity="info" icon="pi pi-inbox" aria-label="Filter" v-tooltip.top="'Jupter Lab'"
disabled />
<Button v-if="data.status == statusRunning" severity="contrast" icon="pi pi-chart-bar" as="a"
:href="'http://' + data.grafana_address + '/public-dashboards/2c510f203876465ba76617510ce3e219'"
target="_blank" v-tooltip.top="'监控'" />

View File

@ -70,9 +70,13 @@
<Column>
<template #body="{ data }">
<div class="flex gap-2">
<Button v-if="data.status == statusRunning" icon="pi pi-inbox" aria-label="Filter" as="a"
<Button v-if="data.status == statusRunning" icon="pi pi-code" aria-label="Filter" as="a"
:href="'http://' + data.code_server_address" target="_blank" v-tooltip.top="'VSCode Web'" />
<Button v-else icon="pi pi-code" aria-label="Filter" v-tooltip.top="'VSCode Web'" disabled />
<Button v-if="data.status == statusRunning" severity="info" icon="pi pi-inbox" aria-label="Filter" as="a"
:href="'http://' + data.jupyter_address + '/lab'" target="_blank" v-tooltip.top="'Jupter Lab'" />
<Button v-else icon="pi pi-inbox" aria-label="Filter" v-tooltip.top="'Jupter Lab'" disabled />
<Button v-else severity="info" icon="pi pi-inbox" aria-label="Filter" v-tooltip.top="'Jupter Lab'"
disabled />
<Button v-if="data.status == statusRunning" severity="contrast" icon="pi pi-chart-bar" as="a"
:href="'http://' + data.grafana_address + '/public-dashboards/2c510f203876465ba76617510ce3e219'"
target="_blank" v-tooltip.top="'监控'" />

View File

@ -39,12 +39,13 @@ type Instances struct {
VolumeName string `json:"volume_name,omitempty" gorm:"type:varchar(255);not null"`
VolumeSize int `json:"volume_size" gorm:"not null"`
SshAddress string `json:"ssh_address" gorm:"type:varchar(255);not null"`
SshPasswd string `json:"ssh_passwd" gorm:"type:varchar(255);not null"`
JupyterAddress string `json:"jupyter_address" gorm:"type:varchar(255);not null"`
TensorBoardAddress string `json:"tensor_board_address" gorm:"type:varchar(255);not null"`
GrafanaAddress string `json:"grafana_address" gorm:"type:varchar(255);not null"`
Status Status `json:"status" gorm:"not null"` // -1: fail, 0: running, 1: paused, 2: stopped, 3: readying
SshAddress string `json:"ssh_address" gorm:"type:varchar(255)"`
SshPasswd string `json:"ssh_passwd" gorm:"type:varchar(255)"`
JupyterAddress string `json:"jupyter_address" gorm:"type:varchar(255)"`
TensorBoardAddress string `json:"tensor_board_address" gorm:"type:varchar(255)"`
GrafanaAddress string `json:"grafana_address" gorm:"type:varchar(255)"`
CodeServerAddress string `json:"code_server_address" gorm:"type:varchar(255)"`
Status Status `json:"status" gorm:"not null"` // Detail in Constants
Label string `json:"label" gorm:"type:varchar(255)"`

View File

@ -22,7 +22,7 @@ func detailHandler(ctx iris.Context) {
instance := models.Instances{
ID: id,
}
result := database.DB.Select("id", "user_id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "tensor_board_address", "grafana_address", "status", "image_name", "created_at").First(&instance)
result := database.DB.Select("id", "user_id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "tensor_board_address", "grafana_address", "code_server_address", "status", "image_name", "created_at").First(&instance)
if result.Error != nil {
l.Error("detail instance error: %v", result.Error)
middleware.Error(ctx, middleware.CodeInstanceDetailError, iris.StatusInternalServerError)

View File

@ -43,7 +43,7 @@ func listHandler(ctx iris.Context) {
return
}
result := database.DB.Limit(limit).Offset(offset).Select("id", "user_id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "jupyter_address", "tensor_board_address", "grafana_address", "status", "image_name", "label", "created_at").Order("id").Find(&instances)
result := database.DB.Limit(limit).Offset(offset).Select("id", "user_id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "jupyter_address", "tensor_board_address", "grafana_address", "code_server_address", "status", "image_name", "label", "created_at").Order("id").Find(&instances)
if result.Error != nil {
l.Error("list instances error: %v", result.Error)
middleware.Error(ctx, middleware.CodeInstanceListError, iris.StatusInternalServerError)

View File

@ -28,7 +28,7 @@ func detailHandler(ctx iris.Context) {
instance := models.Instances{
ID: id,
}
result := database.DB.Where("id = ?", id).Where("user_id = ?", userId).Select("id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "tensor_board_address", "grafana_address", "status", "image_name", "created_at").First(&instance)
result := database.DB.Where("id = ?", id).Where("user_id = ?", userId).Select("id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "tensor_board_address", "grafana_address", "code_server_address", "status", "image_name", "created_at").First(&instance)
if result.Error != nil {
l.Error("detail instance error: %v", result.Error)
middleware.Error(ctx, middleware.CodeInstanceDetailError, iris.StatusInternalServerError)

View File

@ -49,7 +49,7 @@ func listHandler(ctx iris.Context) {
return
}
result := database.DB.Where("user_id = ?", userId).Limit(limit).Offset(offset).Select("id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "jupyter_address", "tensor_board_address", "grafana_address", "status", "image_name", "label", "created_at").Order("id").Find(&instances)
result := database.DB.Where("user_id = ?", userId).Limit(limit).Offset(offset).Select("id", "server_id", "cpu_only", "gpu_count", "volume_size", "ssh_address", "ssh_passwd", "jupyter_address", "tensor_board_address", "grafana_address", "code_server_address", "status", "image_name", "label", "created_at").Order("id").Find(&instances)
if result.Error != nil {
l.Error("list instances error: %v", result.Error)
middleware.Error(ctx, middleware.CodeInstanceListError, iris.StatusInternalServerError)

View File

@ -47,7 +47,10 @@ func Create(instance *models.Instances) (containerName, volumeName string, err e
return "", "", err
}
go SetJupterPassword(server.IP, server.Port, server.Apikey, containerName, instance.SshPasswd)
go func() {
SetJupterPassword(server.IP, server.Port, server.Apikey, containerName, instance.SshPasswd)
SetCodeServerPassword(server.IP, server.Port, server.Apikey, containerName, instance.SshPasswd)
}()
portBindings, err := GetPortForward(server.IP, server.Port, server.Apikey, containerName)
if err != nil {
@ -63,6 +66,7 @@ func Create(instance *models.Instances) (containerName, volumeName string, err e
instance.TensorBoardAddress = server.IP + ":" + portBindings["6007"]
instance.JupyterAddress = server.IP + ":" + portBindings["8888"]
instance.GrafanaAddress = server.IP + ":" + portBindings["3000"]
instance.CodeServerAddress = server.IP + ":" + portBindings["8080"]
instance.Status = 0
result = database.DB.Save(&instance)

View File

@ -42,6 +42,7 @@ func createInstance(ip string, port int, apikey string,
"6007", // TensorBoard
"8888", // Jupyter Notebook
"3000", // Grafana
"8080", // Code-Server
"34567", // Custom Port
},
}

View File

@ -141,3 +141,88 @@ func SetJupterPassword(ip string, port int, apikey string,
return nil
}
func SetCodeServerPassword(ip string, port int, apikey string,
containerName, password string) (err error) {
l.SetFunction("SetCodeServerPassword")
// Set Code-Server Password
data := executeReq{
Cmd: []string{
"sed",
"-i",
"/^password: CHANGETHIS/c\\password: " + password,
"/root/.config/code-server/config.yaml",
},
}
reqBytes, err := json.Marshal(data)
if err != nil {
l.Error("marshal request data error: %v", err)
return
}
c := request.NewRequest().Post().
SetUrl("http://" + ip + ":" + strconv.Itoa(port) + apiPrefix + instancePrefix + "/" + containerName + instanceExecute).
SetAuthorization("Bearer " + apikey).
SetUserAgent("megrez").
SetBody(bytes.NewBuffer(reqBytes))
c.Do()
if c.GetStatusCode() != 200 {
l.Error("set code-server password error: %d", c.GetStatusCode())
return errors.New("set code-server password request error")
}
var res resStruct
err = json.Unmarshal(c.GetBody(), &res)
if err != nil {
l.Error("unmarshal response data error: %v", err)
return err
}
if res.Code != 200 {
l.Error("set code-server password code: %d, error: %s", res.Code, res.Msg)
return errors.New(res.Msg)
}
// Restart Code-Server
data = executeReq{
Cmd: []string{
"service",
"code-server",
"restart",
},
}
reqBytes, err = json.Marshal(data)
if err != nil {
l.Error("marshal request data error: %v", err)
return
}
c = request.NewRequest().Post().
SetUrl("http://" + ip + ":" + strconv.Itoa(port) + apiPrefix + instancePrefix + "/" + containerName + instanceExecute).
SetAuthorization("Bearer " + apikey).
SetUserAgent("megrez").
SetBody(bytes.NewBuffer(reqBytes))
c.Do()
if c.GetStatusCode() != 200 {
l.Error("restart code-server error: %d", c.GetStatusCode())
return errors.New("restart code-server request error")
}
err = json.Unmarshal(c.GetBody(), &res)
if err != nil {
l.Error("unmarshal response data error: %v", err)
return err
}
if res.Code != 200 {
l.Error("restart code-server code: %d, error: %s", res.Code, res.Msg)
return errors.New(res.Msg)
}
return nil
}

View File

@ -95,7 +95,10 @@ func Patch(instance *models.Instances, gpuCount, volumeSize int, cpuOnly bool) (
return err
}
go SetJupterPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
go func() {
SetJupterPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
SetCodeServerPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
}()
portBindings, err := GetPortForward(server.IP, server.Port, server.Apikey, instance.ContainerName)
if err != nil {
@ -140,7 +143,10 @@ func Patch(instance *models.Instances, gpuCount, volumeSize int, cpuOnly bool) (
return err
}
go SetJupterPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
go func() {
SetJupterPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
SetCodeServerPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
}()
portBindings, err := GetPortForward(server.IP, server.Port, server.Apikey, instance.ContainerName)
if err != nil {
@ -152,6 +158,7 @@ func Patch(instance *models.Instances, gpuCount, volumeSize int, cpuOnly bool) (
instance.TensorBoardAddress = server.IP + ":" + portBindings["6007"]
instance.JupyterAddress = server.IP + ":" + portBindings["8888"]
instance.GrafanaAddress = server.IP + ":" + portBindings["3000"]
instance.CodeServerAddress = server.IP + ":" + portBindings["8080"]
instance.CpuOnly = false
instance.GpuCount = gpuCount

View File

@ -48,7 +48,10 @@ func Restart(instance *models.Instances) (err error) {
return err
}
go SetJupterPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
go func() {
SetJupterPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
SetCodeServerPassword(server.IP, server.Port, server.Apikey, instance.ContainerName, instance.SshPasswd)
}()
portBindings, err := GetPortForward(server.IP, server.Port, server.Apikey, instance.ContainerName)
if err != nil {
@ -60,6 +63,7 @@ func Restart(instance *models.Instances) (err error) {
instance.TensorBoardAddress = server.IP + ":" + portBindings["6007"]
instance.JupyterAddress = server.IP + ":" + portBindings["8888"]
instance.GrafanaAddress = server.IP + ":" + portBindings["3000"]
instance.CodeServerAddress = server.IP + ":" + portBindings["8080"]
instance.Status = models.InstanceRunning
result = database.DB.Save(&instance)