112 lines
4.2 KiB
Go
112 lines
4.2 KiB
Go
package oci
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/oracle/oci-go-sdk/v65/core"
|
|
)
|
|
|
|
// ConsoleConnection 是实例控制台连接。VNC 连接串在本地建立 SSH 隧道后,
|
|
// 用 VNC 客户端连 localhost:5900 即可(串口控制台直接执行 ConnectionString)。
|
|
type ConsoleConnection struct {
|
|
ID string `json:"id"`
|
|
InstanceID string `json:"instanceId"`
|
|
LifecycleState string `json:"lifecycleState"`
|
|
ConnectionString string `json:"connectionString"` // 串口控制台 SSH 命令
|
|
VncConnectionString string `json:"vncConnectionString"` // VNC over SSH 隧道命令
|
|
}
|
|
|
|
// CreateConsoleConnection 实现 Client:为实例创建控制台连接并等待就绪,
|
|
// 返回包含 VNC/串口连接串的对象;等待超时返回当前状态(可稍后再查列表)。
|
|
func (c *RealClient) CreateConsoleConnection(ctx context.Context, cred Credentials, region, instanceID, sshPublicKey string) (ConsoleConnection, error) {
|
|
cc, err := c.computeClient(cred, region)
|
|
if err != nil {
|
|
return ConsoleConnection{}, err
|
|
}
|
|
resp, err := cc.CreateInstanceConsoleConnection(ctx, core.CreateInstanceConsoleConnectionRequest{
|
|
CreateInstanceConsoleConnectionDetails: core.CreateInstanceConsoleConnectionDetails{
|
|
InstanceId: &instanceID,
|
|
PublicKey: &sshPublicKey,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return ConsoleConnection{}, fmt.Errorf("create console connection: %w", err)
|
|
}
|
|
return c.waitConsoleConnectionActive(ctx, cc, deref(resp.Id))
|
|
}
|
|
|
|
// waitConsoleConnectionActive 轮询等待控制台连接 ACTIVE,最长约 60 秒。
|
|
func (c *RealClient) waitConsoleConnectionActive(ctx context.Context, cc core.ComputeClient, connectionID string) (ConsoleConnection, error) {
|
|
var last ConsoleConnection
|
|
for i := 0; i < 30; i++ {
|
|
resp, err := cc.GetInstanceConsoleConnection(ctx, core.GetInstanceConsoleConnectionRequest{
|
|
InstanceConsoleConnectionId: &connectionID,
|
|
})
|
|
if err != nil {
|
|
return last, fmt.Errorf("poll console connection: %w", err)
|
|
}
|
|
last = toConsoleConnection(resp.InstanceConsoleConnection)
|
|
if last.LifecycleState == string(core.InstanceConsoleConnectionLifecycleStateActive) {
|
|
return last, nil
|
|
}
|
|
select {
|
|
case <-ctx.Done():
|
|
return last, fmt.Errorf("poll console connection: %w", ctx.Err())
|
|
case <-time.After(2 * time.Second):
|
|
}
|
|
}
|
|
return last, nil
|
|
}
|
|
|
|
// ListConsoleConnections 实现 Client:列出实例的控制台连接。
|
|
func (c *RealClient) ListConsoleConnections(ctx context.Context, cred Credentials, region, instanceID string) ([]ConsoleConnection, error) {
|
|
cc, err := c.computeClient(cred, region)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// 控制台连接记录在实例所在 compartment,先取实例定位,传租户根会漏查
|
|
instResp, err := cc.GetInstance(ctx, core.GetInstanceRequest{InstanceId: &instanceID})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("get instance %s: %w", instanceID, err)
|
|
}
|
|
resp, err := cc.ListInstanceConsoleConnections(ctx, core.ListInstanceConsoleConnectionsRequest{
|
|
CompartmentId: hostCompartment(cred, deref(instResp.CompartmentId)),
|
|
InstanceId: &instanceID,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list console connections: %w", err)
|
|
}
|
|
connections := make([]ConsoleConnection, 0, len(resp.Items))
|
|
for _, item := range resp.Items {
|
|
connections = append(connections, toConsoleConnection(item))
|
|
}
|
|
return connections, nil
|
|
}
|
|
|
|
// DeleteConsoleConnection 实现 Client:删除控制台连接。
|
|
func (c *RealClient) DeleteConsoleConnection(ctx context.Context, cred Credentials, region, connectionID string) error {
|
|
cc, err := c.computeClient(cred, region)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = cc.DeleteInstanceConsoleConnection(ctx, core.DeleteInstanceConsoleConnectionRequest{
|
|
InstanceConsoleConnectionId: &connectionID,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("delete console connection %s: %w", connectionID, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func toConsoleConnection(conn core.InstanceConsoleConnection) ConsoleConnection {
|
|
return ConsoleConnection{
|
|
ID: deref(conn.Id),
|
|
InstanceID: deref(conn.InstanceId),
|
|
LifecycleState: string(conn.LifecycleState),
|
|
ConnectionString: deref(conn.ConnectionString),
|
|
VncConnectionString: deref(conn.VncConnectionString),
|
|
}
|
|
}
|