From 2292a08364942b401f49374de427ce6ca99ca34c Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 15 Dec 2023 21:15:36 +0800 Subject: [PATCH] fix: webconsole display information control --- cmd/climc/shell/compute/webconsole.go | 5 + pkg/apis/identity/consts.go | 1 - pkg/apis/webconsole/types.go | 1 + pkg/webconsole/options/options.go | 17 +-- pkg/webconsole/service/handlers.go | 37 ++++-- pkg/webconsole/session/display_info.go | 125 +++++++++++++++++++ pkg/webconsole/session/remote_console.go | 18 +++ pkg/webconsole/session/remote_console_rdp.go | 16 ++- pkg/webconsole/session/resolve_sshinfo.go | 40 +++--- pkg/webconsole/session/session.go | 19 ++- pkg/webconsole/session/ssh_session.go | 24 ++++ 11 files changed, 264 insertions(+), 39 deletions(-) create mode 100644 pkg/webconsole/session/display_info.go diff --git a/cmd/climc/shell/compute/webconsole.go b/cmd/climc/shell/compute/webconsole.go index a80de28621..34119efc45 100644 --- a/cmd/climc/shell/compute/webconsole.go +++ b/cmd/climc/shell/compute/webconsole.go @@ -32,6 +32,11 @@ import ( func init() { handleResult := func(s *mcclient.ClientSession, opt o.WebConsoleOptions, obj jsonutils.JSONObject) error { + if obj.Contains("access_url") { + accessUrl, _ := obj.GetString("access_url") + fmt.Println("AccessURL:", accessUrl) + return nil + } if opt.WebconsoleUrl == "" { resp, err := identity.ServicesV3.GetSpecific(s, "common", "config", nil) if err != nil { diff --git a/pkg/apis/identity/consts.go b/pkg/apis/identity/consts.go index 6c2e4860b6..455311d8e0 100644 --- a/pkg/apis/identity/consts.go +++ b/pkg/apis/identity/consts.go @@ -116,7 +116,6 @@ var ( "ignore_nonrunning_guests", "platform_name", "enable_cloud_shell", - "enable_watermark", "platform_names", }, } diff --git a/pkg/apis/webconsole/types.go b/pkg/apis/webconsole/types.go index dc4e7d1f0d..bcbadf7c26 100644 --- a/pkg/apis/webconsole/types.go +++ b/pkg/apis/webconsole/types.go @@ -22,6 +22,7 @@ import ( ) type ServerRemoteConsoleResponse struct { + AccessUrl string `json:"access_url"` ConnectParams string `json:"connect_params"` Session string `json:"session,omitempty"` diff --git a/pkg/webconsole/options/options.go b/pkg/webconsole/options/options.go index c4c604566f..6b0f443ede 100644 --- a/pkg/webconsole/options/options.go +++ b/pkg/webconsole/options/options.go @@ -25,13 +25,16 @@ type WebConsoleOptions struct { common_options.DBOptions - KubectlPath string `help:"kubectl binary path used to connect k8s cluster" default:"/usr/bin/kubectl"` - IpmitoolPath string `help:"ipmitool binary path used to connect baremetal sol" default:"/usr/bin/ipmitool"` - EnableAutoLogin bool `help:"allow webconsole to log in directly with the cloudroot public key" default:"false"` - ApsaraConsoleAddr string `help:"Apsara console addr" default:"https://xxxx.com.cn/module/ecs/vnc/index.html"` - AliyunConsoleAddr string `help:"Aliyun vnc addr" default:"https://ecs.console.aliyun.com/vnc/index.htm"` - SshSessionTimeoutMinutes int `help:"ssh timeout session" default:"-1"` - RdpSessionTimeoutMinutes int `help:"rdp timeout session" default:"-1"` + KubectlPath string `help:"kubectl binary path used to connect k8s cluster" default:"/usr/bin/kubectl"` + IpmitoolPath string `help:"ipmitool binary path used to connect baremetal sol" default:"/usr/bin/ipmitool"` + EnableAutoLogin bool `help:"allow webconsole to log in directly with the cloudroot public key" default:"false"` + ApsaraConsoleAddr string `help:"Apsara console addr" default:"https://xxxx.com.cn/module/ecs/vnc/index.html"` + AliyunConsoleAddr string `help:"Aliyun vnc addr" default:"https://ecs.console.aliyun.com/vnc/index.htm"` + + SshSessionTimeoutMinutes int `help:"ssh timeout session" default:"-1"` + RdpSessionTimeoutMinutes int `help:"rdp timeout session" default:"-1"` + + EnableWatermark bool `help:"enable water mark" default:"true"` } func OnOptionsChange(oldO, newO interface{}) bool { diff --git a/pkg/webconsole/service/handlers.go b/pkg/webconsole/service/handlers.go index a035c693da..dfd1529716 100644 --- a/pkg/webconsole/service/handlers.go +++ b/pkg/webconsole/service/handlers.go @@ -25,6 +25,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/pkg/errors" "yunion.io/x/pkg/gotypes" + "yunion.io/x/pkg/util/httputils" "yunion.io/x/pkg/util/regutils" webconsole_api "yunion.io/x/onecloud/pkg/apis/webconsole" @@ -185,13 +186,14 @@ func handleSshShell(ctx context.Context, w http.ResponseWriter, r *http.Request) } idStr := env.Params[""] if !regutils.MatchIPAddr(idStr) { - ip, port, err := session.ResolveServerSSHIPPortById(ctx, env.ClientSessin, idStr, sshConnInfo.IP, sshConnInfo.Port) + ip, port, guestDetails, err := session.ResolveServerSSHIPPortById(ctx, env.ClientSessin, idStr, sshConnInfo.IP, sshConnInfo.Port) if err != nil { httperrors.GeneralServerError(ctx, w, err) return } sshConnInfo.IP = ip sshConnInfo.Port = port + sshConnInfo.GuestDetails = guestDetails } else { // directly ssh IP should be deprecated gradually sshConnInfo.IP = idStr @@ -201,7 +203,7 @@ func handleSshShell(ctx context.Context, w http.ResponseWriter, r *http.Request) } func handleSshSession(ctx context.Context, session *session.SSshSession, w http.ResponseWriter) { - handleDataSession(ctx, session, w, nil, false) + handleDataSession(ctx, session, w, "ws", nil, false) } func handleBaremetalShell(ctx context.Context, w http.ResponseWriter, r *http.Request) { @@ -269,8 +271,12 @@ func handleServerRemoteConsole(ctx context.Context, w http.ResponseWriter, r *ht session.HUAWEI, session.HCS, session.APSARA, session.JDCLOUD, session.CLOUDPODS, session.PROXMOX: responsePublicCloudConsole(ctx, info, w) - case session.VNC, session.SPICE, session.WMKS: - handleDataSession(ctx, info, w, url.Values{"password": {info.GetPassword()}}, true) + case session.VNC: + handleDataSession(ctx, info, w, "no-vnc", url.Values{"password": {info.GetPassword()}}, true) + case session.SPICE: + handleDataSession(ctx, info, w, "spice", url.Values{"password": {info.GetPassword()}}, true) + case session.WMKS: + handleDataSession(ctx, info, w, "wmks", url.Values{"password": {info.GetPassword()}}, true) default: httperrors.NotAcceptableError(ctx, w, "Unspported remote console protocol: %s", info.Protocol) } @@ -289,7 +295,7 @@ func handleServerRemoteRDPConsole(ctx context.Context, w http.ResponseWriter, r httperrors.GeneralServerError(ctx, w, err) return } - handleDataSession(ctx, info, w, url.Values{"password": {info.GetPassword()}}, true) + handleDataSession(ctx, info, w, "rdp", url.Values{"password": {info.GetPassword()}}, true) } func responsePublicCloudConsole(ctx context.Context, info *session.RemoteConsoleInfo, w http.ResponseWriter) { @@ -304,21 +310,36 @@ func responsePublicCloudConsole(ctx context.Context, info *session.RemoteConsole sendJSON(w, resp.JSON(resp)) } -func handleDataSession(ctx context.Context, sData session.ISessionData, w http.ResponseWriter, connParams url.Values, b64Encode bool) { +func handleDataSession(ctx context.Context, sData session.ISessionData, w http.ResponseWriter, base string, connParams url.Values, b64Encode bool) { s, err := session.Manager.Save(sData) if err != nil { httperrors.GeneralServerError(ctx, w, err) return } - params, err := s.GetConnectParams(connParams) + dispInfo, err := sData.GetDisplayInfo(ctx) if err != nil { httperrors.GeneralServerError(ctx, w, err) return } + params, err := s.GetConnectParams(connParams, dispInfo) + if err != nil { + httperrors.GeneralServerError(ctx, w, err) + return + } + + var accessUrl string + { + dataVal := url.Values{} + dataVal.Add("data", base64.StdEncoding.EncodeToString([]byte(params))) + accessUrl = httputils.JoinPath(o.Options.ApiServer, fmt.Sprintf("web-console/%s?%s", base, dataVal.Encode())) + } + if b64Encode { params = base64.StdEncoding.EncodeToString([]byte(params)) } + resp := webconsole_api.ServerRemoteConsoleResponse{ + AccessUrl: accessUrl, ConnectParams: params, Session: s.Id, } @@ -326,7 +347,7 @@ func handleDataSession(ctx context.Context, sData session.ISessionData, w http.R } func handleCommandSession(ctx context.Context, cmd command.ICommand, w http.ResponseWriter) { - handleDataSession(ctx, session.WrapCommandSession(cmd), w, nil, false) + handleDataSession(ctx, session.WrapCommandSession(cmd), w, "tty", nil, false) } func sendJSON(w http.ResponseWriter, body jsonutils.JSONObject) { diff --git a/pkg/webconsole/session/display_info.go b/pkg/webconsole/session/display_info.go new file mode 100644 index 0000000000..dbcac8125f --- /dev/null +++ b/pkg/webconsole/session/display_info.go @@ -0,0 +1,125 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package session + +import ( + "context" + "net/url" + + "yunion.io/x/pkg/errors" + + compute_api "yunion.io/x/onecloud/pkg/apis/compute" + identity_api "yunion.io/x/onecloud/pkg/apis/identity" + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/mcclient/auth" + "yunion.io/x/onecloud/pkg/mcclient/modules/compute" + "yunion.io/x/onecloud/pkg/mcclient/modules/identity" + "yunion.io/x/onecloud/pkg/webconsole/options" +) + +type SDisplayInfo struct { + WaterMark string `json:"water_mark"` + InstanceName string `json:"instance_name"` + Ips string `json:"ips"` + + Hypervisor string `json:"hypervisor"` + OsType string `json:"os_type"` + OsName string `json:"os_name"` + OsArch string `json:"os_arch"` + OsDistribution string `json:"os_distribution"` +} + +func (dispInfo *SDisplayInfo) fetchGuestInfo(guestDetails *compute_api.ServerDetails) { + dispInfo.Hypervisor = guestDetails.Hypervisor + dispInfo.OsName = guestDetails.OsName + dispInfo.OsType = guestDetails.OsType + dispInfo.OsArch = guestDetails.OsArch + dispInfo.OsDistribution = guestDetails.Metadata[compute_api.VM_METADATA_OS_DISTRO] + dispInfo.InstanceName = guestDetails.Name + dispInfo.Ips = guestDetails.IPs +} + +func (dispInfo *SDisplayInfo) populateParams(params url.Values) url.Values { + if options.Options.EnableWatermark && len(dispInfo.WaterMark) > 0 { + params["water_mark"] = []string{dispInfo.WaterMark} + } + if len(dispInfo.InstanceName) > 0 { + params["instance_name"] = []string{dispInfo.InstanceName} + } + if len(dispInfo.Ips) > 0 { + params["ips"] = []string{dispInfo.Ips} + } + if len(dispInfo.Hypervisor) > 0 { + params["hypervisor"] = []string{dispInfo.Hypervisor} + } + if len(dispInfo.OsType) > 0 { + params["os_type"] = []string{dispInfo.OsType} + } + if len(dispInfo.OsName) > 0 { + params["os_name"] = []string{dispInfo.OsName} + } + if len(dispInfo.OsArch) > 0 { + params["os_arch"] = []string{dispInfo.OsArch} + } + if len(dispInfo.OsDistribution) > 0 { + params["os_distribution"] = []string{dispInfo.OsDistribution} + } + + return params +} + +func fetchWaterMark(userInfo *identity_api.UserDetails) string { + info := userInfo.Name + if len(userInfo.Displayname) > 0 { + info += " (" + userInfo.Displayname + ")" + } + info += "
" + if len(userInfo.Mobile) > 0 { + info += userInfo.Mobile + } else if len(userInfo.Email) > 0 { + info += userInfo.Email + } else { + info += userInfo.Id + } + return info +} + +func fetchUserInfo(ctx context.Context, s *mcclient.ClientSession) (*identity_api.UserDetails, error) { + usrObj, err := identity.UsersV3.GetById(auth.GetAdminSession(ctx, s.GetRegion()), s.GetUserId(), nil) + if err != nil { + return nil, errors.Wrap(err, "GetById") + } + + usr := identity_api.UserDetails{} + err = usrObj.Unmarshal(&usr) + if err != nil { + return nil, errors.Wrap(err, "Unmarshal") + } + + return &usr, nil +} + +func FetchServerInfo(ctx context.Context, s *mcclient.ClientSession, sid string) (*compute_api.ServerDetails, error) { + guestInfo, err := compute.Servers.Get(s, sid, nil) + if err != nil { + return nil, errors.Wrapf(err, "GetById %s", sid) + } + guestDetails := compute_api.ServerDetails{} + err = guestInfo.Unmarshal(&guestDetails) + if err != nil { + return nil, errors.Wrap(err, "Unmarshal guest info") + } + return &guestDetails, nil +} diff --git a/pkg/webconsole/session/remote_console.go b/pkg/webconsole/session/remote_console.go index 69ac093960..d7e459ded8 100644 --- a/pkg/webconsole/session/remote_console.go +++ b/pkg/webconsole/session/remote_console.go @@ -15,12 +15,14 @@ package session import ( + "context" "fmt" "net/url" "os/exec" "yunion.io/x/cloudmux/pkg/cloudprovider" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" api "yunion.io/x/onecloud/pkg/apis/webconsole" "yunion.io/x/onecloud/pkg/mcclient" @@ -211,3 +213,19 @@ func (info *RemoteConsoleInfo) getApsaraURL() (string, error) { func (info *RemoteConsoleInfo) GetRecordObject() *recorder.Object { return nil } + +func (info *RemoteConsoleInfo) GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error) { + userInfo, err := fetchUserInfo(ctx, info.GetClientSession()) + if err != nil { + return nil, errors.Wrap(err, "fetchUserInfo") + } + guestDetails, err := FetchServerInfo(ctx, info.GetClientSession(), info.Id) + if err != nil { + return nil, errors.Wrap(err, "FetchServerInfo") + } + + dispInfo := SDisplayInfo{} + dispInfo.WaterMark = fetchWaterMark(userInfo) + dispInfo.fetchGuestInfo(guestDetails) + return &dispInfo, nil +} diff --git a/pkg/webconsole/session/remote_console_rdp.go b/pkg/webconsole/session/remote_console_rdp.go index 83adf0514f..b7e6b29b45 100644 --- a/pkg/webconsole/session/remote_console_rdp.go +++ b/pkg/webconsole/session/remote_console_rdp.go @@ -22,6 +22,7 @@ import ( "yunion.io/x/pkg/errors" "yunion.io/x/pkg/gotypes" + compute_api "yunion.io/x/onecloud/pkg/apis/compute" api "yunion.io/x/onecloud/pkg/apis/webconsole" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" @@ -36,6 +37,8 @@ type RemoteRDPConsoleInfo struct { Password string ConnectionId string + guestDetails *compute_api.ServerDetails + Width int Height int Dpi int @@ -54,7 +57,7 @@ func NewRemoteRDPConsoleInfoByCloud(ctx context.Context, s *mcclient.ClientSessi info.Port = 3389 } var err error - info.Host, info.Port, err = resolveServerIPPortById(ctx, s, serverId, info.Host, info.Port) + info.Host, info.Port, info.guestDetails, err = resolveServerIPPortById(ctx, s, serverId, info.Host, info.Port) if err != nil { return nil, errors.Wrap(err, "resolveServerIPPortById") } @@ -118,3 +121,14 @@ func (info *RemoteRDPConsoleInfo) GetId() string { func (info *RemoteRDPConsoleInfo) GetRecordObject() *recorder.Object { return nil } + +func (info *RemoteRDPConsoleInfo) GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error) { + userInfo, err := fetchUserInfo(ctx, info.GetClientSession()) + if err != nil { + return nil, errors.Wrap(err, "fetchUserInfo") + } + dispInfo := SDisplayInfo{} + dispInfo.WaterMark = fetchWaterMark(userInfo) + dispInfo.fetchGuestInfo(info.guestDetails) + return &dispInfo, nil +} diff --git a/pkg/webconsole/session/resolve_sshinfo.go b/pkg/webconsole/session/resolve_sshinfo.go index 39b6bf3bd1..dcc039728d 100644 --- a/pkg/webconsole/session/resolve_sshinfo.go +++ b/pkg/webconsole/session/resolve_sshinfo.go @@ -36,24 +36,21 @@ type SSshConnectionInfo struct { KeepUsername bool `json:"keep_username"` Password string `json:"password"` Name string `json:"name"` + + GuestDetails *compute_api.ServerDetails } -func ResolveServerSSHIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, error) { +func ResolveServerSSHIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, *compute_api.ServerDetails, error) { if port <= 0 { port = 22 } return resolveServerIPPortById(ctx, s, id, ip, port) } -func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, error) { - guestInfo, err := compute.Servers.Get(s, id, nil) +func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, *compute_api.ServerDetails, error) { + guestDetails, err := FetchServerInfo(ctx, s, id) if err != nil { - return "", 0, errors.Wrapf(err, "GetById %s", id) - } - guestDetails := compute_api.SGuest{} - err = guestInfo.Unmarshal(&guestDetails) - if err != nil { - return "", 0, errors.Wrap(err, "Unmarshal guest info") + return "", 0, nil, errors.Wrap(err, "fetchServerInfo") } // list all nic of a server input := compute_api.GuestnetworkListInput{} @@ -63,11 +60,11 @@ func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id input.ServerFilterListInput.Scope = "max" result, err := compute.Servernetworks.List(s, jsonutils.Marshal(input)) if err != nil { - return "", 0, errors.Wrap(err, "Servernetworks.List") + return "", 0, nil, errors.Wrap(err, "Servernetworks.List") } if result.Total == 0 { // not nic found!!! - return "", 0, errors.Wrap(httperrors.ErrNotFound, "no nic on server") + return "", 0, nil, errors.Wrap(httperrors.ErrNotFound, "no nic on server") } // find nics @@ -75,20 +72,20 @@ func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id if result.Total == 1 { err := result.Data[0].Unmarshal(&guestNicDetails) if err != nil { - return "", 0, errors.Wrap(err, "Unmarshal guest network info") + return "", 0, nil, errors.Wrap(err, "Unmarshal guest network info") } if len(ip) > 0 && ip != guestNicDetails.EipAddr && ip != guestNicDetails.IpAddr && ip != guestNicDetails.Ip6Addr { - return "", 0, errors.Wrapf(httperrors.ErrInputParameter, "ip %s not match with server", ip) + return "", 0, nil, errors.Wrapf(httperrors.ErrInputParameter, "ip %s not match with server", ip) } } else { if len(ip) == 0 { - return "", 0, errors.Wrap(httperrors.ErrInputParameter, "must specify ip") + return "", 0, nil, errors.Wrap(httperrors.ErrInputParameter, "must specify ip") } find := false for _, gnJson := range result.Data { err := gnJson.Unmarshal(&guestNicDetails) if err != nil { - return "", 0, errors.Wrap(err, "Unmarshal guest network info") + return "", 0, nil, errors.Wrap(err, "Unmarshal guest network info") } if ip == guestNicDetails.EipAddr || ip == guestNicDetails.IpAddr || ip == guestNicDetails.Ip6Addr { find = true @@ -96,7 +93,7 @@ func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id } } if !find { - return "", 0, errors.Wrap(httperrors.ErrInputParameter, "ip specified not match with server") + return "", 0, nil, errors.Wrap(httperrors.ErrInputParameter, "ip specified not match with server") } } @@ -107,20 +104,23 @@ func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id } else if len(guestNicDetails.IpAddr) > 0 { ip = guestNicDetails.IpAddr } else { - return "", 0, errors.Wrap(httperrors.ErrNotSupported, "no valid ipv4 addr") + return "", 0, nil, errors.Wrap(httperrors.ErrNotSupported, "no valid ipv4 addr") } } if ip == guestNicDetails.Ip6Addr { - return "", 0, errors.Wrap(httperrors.ErrNotSupported, "ipv6 not supported") + return "", 0, nil, errors.Wrap(httperrors.ErrNotSupported, "ipv6 not supported") } if ip == guestNicDetails.IpAddr && len(guestNicDetails.MappedIpAddr) > 0 { // need to do open forward - return acquireForward(ctx, s, guestDetails.Id, ip, "tcp", port) + ip, port, err = acquireForward(ctx, s, guestDetails.Id, ip, "tcp", port) + if err != nil { + return "", 0, nil, errors.Wrap(err, "acquireForward") + } } - return ip, port, nil + return ip, port, guestDetails, nil } type sForwardInfo struct { diff --git a/pkg/webconsole/session/session.go b/pkg/webconsole/session/session.go index eca8c42d49..e06a7eef75 100644 --- a/pkg/webconsole/session/session.go +++ b/pkg/webconsole/session/session.go @@ -15,6 +15,7 @@ package session import ( + "context" "fmt" "math/rand" "net/url" @@ -102,6 +103,7 @@ type ISessionData interface { command.ICommand IsNeedLogin() (bool, error) GetId() string + GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error) } type RandomSessionData struct { @@ -124,6 +126,17 @@ func (s *RandomSessionData) IsNeedLogin() (bool, error) { return false, nil } +func (s *RandomSessionData) GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error) { + userInfo, err := fetchUserInfo(ctx, s.GetClientSession()) + if err != nil { + return nil, errors.Wrap(err, "fetchUserInfo") + } + dispInfo := SDisplayInfo{} + dispInfo.WaterMark = fetchWaterMark(userInfo) + dispInfo.InstanceName = s.GetCommand().String() + return &dispInfo, nil +} + type SSession struct { ISessionData Id string @@ -133,11 +146,13 @@ type SSession struct { recorder recorder.Recoder } -func (s *SSession) GetConnectParams(params url.Values) (string, error) { +func (s *SSession) GetConnectParams(params url.Values, dispInfo *SDisplayInfo) (string, error) { if params == nil { - params = url.Values(make(map[string][]string)) + params = url.Values{} } + params = dispInfo.populateParams(params) + apiUrl, err := url.Parse(o.Options.ApiServer) if err != nil { return "", errors.Errorf("invalid api_server url: %s", o.Options.ApiServer) diff --git a/pkg/webconsole/session/ssh_session.go b/pkg/webconsole/session/ssh_session.go index 744576a4a9..3aad7516f0 100644 --- a/pkg/webconsole/session/ssh_session.go +++ b/pkg/webconsole/session/ssh_session.go @@ -27,6 +27,7 @@ import ( "yunion.io/x/pkg/errors" "yunion.io/x/pkg/util/stringutils" + compute_api "yunion.io/x/onecloud/pkg/apis/compute" api "yunion.io/x/onecloud/pkg/apis/webconsole" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/webconsole/helper" @@ -48,6 +49,8 @@ type SSshSession struct { // 保持原有 Username ,不实用 cloudroot 的同时使用 PrivateKey KeepUsername bool Password string + + guestDetails *compute_api.ServerDetails } func NewSshSession(ctx context.Context, us *mcclient.ClientSession, conn SSshConnectionInfo) *SSshSession { @@ -60,6 +63,8 @@ func NewSshSession(ctx context.Context, us *mcclient.ClientSession, conn SSshCon Username: conn.Username, KeepUsername: conn.KeepUsername, Password: conn.Password, + + guestDetails: conn.GuestDetails, } if conn.Port <= 0 { ret.Port = 22 @@ -132,3 +137,22 @@ func (s *SSshSession) IsNeedLogin() (bool, error) { func (s *SSshSession) Scan(d byte, send func(msg string)) { } + +func (s *SSshSession) GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error) { + userInfo, err := fetchUserInfo(ctx, s.GetClientSession()) + if err != nil { + return nil, errors.Wrap(err, "fetchUserInfo") + } + dispInfo := SDisplayInfo{} + dispInfo.WaterMark = fetchWaterMark(userInfo) + if s.guestDetails != nil { + dispInfo.fetchGuestInfo(s.guestDetails) + } else { + dispInfo.Ips = s.Host + if len(s.name) > 0 { + dispInfo.InstanceName = s.name + } + } + + return &dispInfo, nil +}