mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #19013 from swordqiu/automated-cherry-pick-of-#19012-upstream-release-3.11
Automated cherry pick of #19012: fix: webconsole display information control
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -116,7 +116,6 @@ var (
|
||||
"ignore_nonrunning_guests",
|
||||
"platform_name",
|
||||
"enable_cloud_shell",
|
||||
"enable_watermark",
|
||||
"platform_names",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
)
|
||||
|
||||
type ServerRemoteConsoleResponse struct {
|
||||
AccessUrl string `json:"access_url"`
|
||||
ConnectParams string `json:"connect_params"`
|
||||
Session string `json:"session,omitempty"`
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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["<ip>"]
|
||||
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) {
|
||||
|
||||
@@ -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 += "<br/>"
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user