fix(webconsole): support host ssh (#19387)

This commit is contained in:
屈轩
2024-02-01 10:58:19 +08:00
committed by GitHub
parent 84f88b705b
commit d6925ac5a9
5 changed files with 86 additions and 7 deletions
+2 -1
View File
@@ -75,8 +75,9 @@ type WebConsoleSshOptions struct {
Ip string `help:"IP to connect if multiple IPs on server"`
Port int `help:"Remote server port"`
Username string `help:"Remote server username"`
KeepUsername bool `help:"Keep remove username`
KeepUsername bool `help:"Keep remove username"`
Password string `help:"Remote server password"`
ResourceType string `help:"Resource Type" choices:"host|server"`
}
func (opt *WebConsoleSshOptions) Params() (*jsonutils.JSONDict, error) {
+46 -6
View File
@@ -186,14 +186,54 @@ func handleSshShell(ctx context.Context, w http.ResponseWriter, r *http.Request)
}
idStr := env.Params["<ip>"]
if !regutils.MatchIPAddr(idStr) {
ip, port, guestDetails, err := session.ResolveServerSSHIPPortById(ctx, env.ClientSessin, idStr, sshConnInfo.IP, sshConnInfo.Port)
if err != nil {
httperrors.GeneralServerError(ctx, w, err)
var tryServer = func() error {
ip, port, guestDetails, err := session.ResolveServerSSHIPPortById(ctx, env.ClientSessin, idStr, sshConnInfo.IP, sshConnInfo.Port)
if err != nil {
return err
}
sshConnInfo.IP = ip
sshConnInfo.Port = port
sshConnInfo.GuestDetails = guestDetails
return nil
}
var tryHost = func() error {
ip, port, hostDetails, err := session.ResolveHostSSHIPPortById(ctx, env.ClientSessin, idStr, sshConnInfo.IP, sshConnInfo.Port)
if err != nil {
return err
}
sshConnInfo.IP = ip
sshConnInfo.Port = port
sshConnInfo.HostDetails = hostDetails
return nil
}
switch sshConnInfo.ResourceType {
case "server":
err = tryServer()
if err != nil {
httperrors.GeneralServerError(ctx, w, err)
return
}
case "host":
err = tryHost()
if err != nil {
httperrors.GeneralServerError(ctx, w, err)
return
}
default:
for _, try := range []func() error{
tryServer,
tryHost,
} {
err = try()
if err == nil {
s := session.NewSshSession(ctx, env.ClientSessin, sshConnInfo)
handleSshSession(ctx, s, w)
return
}
}
httperrors.NewResourceNotFoundError("%s not found", idStr)
return
}
sshConnInfo.IP = ip
sshConnInfo.Port = port
sshConnInfo.GuestDetails = guestDetails
} else {
// directly ssh IP should be deprecated gradually
sshConnInfo.IP = idStr
+20
View File
@@ -51,6 +51,13 @@ func (dispInfo *SDisplayInfo) fetchGuestInfo(guestDetails *compute_api.ServerDet
dispInfo.Ips = guestDetails.IPs
}
func (dispInfo *SDisplayInfo) fetchHostInfo(hostDetails *compute_api.HostDetails) {
dispInfo.Hypervisor = hostDetails.HostType
dispInfo.OsArch = hostDetails.CpuArchitecture
dispInfo.InstanceName = hostDetails.Name
dispInfo.Ips = hostDetails.AccessIp
}
func (dispInfo *SDisplayInfo) populateParams(params url.Values) url.Values {
if options.Options.EnableWatermark && len(dispInfo.WaterMark) > 0 {
params["water_mark"] = []string{dispInfo.WaterMark}
@@ -123,3 +130,16 @@ func FetchServerInfo(ctx context.Context, s *mcclient.ClientSession, sid string)
}
return &guestDetails, nil
}
func FetchHostInfo(ctx context.Context, s *mcclient.ClientSession, id string) (*compute_api.HostDetails, error) {
hostInfo, err := compute.Hosts.Get(s, id, nil)
if err != nil {
return nil, errors.Wrapf(err, "GetById %s", id)
}
hostDetails := compute_api.HostDetails{}
err = hostInfo.Unmarshal(&hostDetails)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal guest info")
}
return &hostDetails, nil
}
+14
View File
@@ -36,8 +36,10 @@ type SSshConnectionInfo struct {
KeepUsername bool `json:"keep_username"`
Password string `json:"password"`
Name string `json:"name"`
ResourceType string `json:"resource_type" choices:"host|server"`
GuestDetails *compute_api.ServerDetails
HostDetails *compute_api.HostDetails
}
func ResolveServerSSHIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, *compute_api.ServerDetails, error) {
@@ -125,6 +127,18 @@ func resolveServerIPPortById(ctx context.Context, s *mcclient.ClientSession, id
return ip, port, guestDetails, nil
}
func ResolveHostSSHIPPortById(ctx context.Context, s *mcclient.ClientSession, id string, ip string, port int) (string, int, *compute_api.HostDetails, error) {
if port <= 0 {
port = 22
}
hostDetails, err := FetchHostInfo(ctx, s, id)
if err != nil {
return "", 0, nil, errors.Wrap(err, "fetchServerInfo")
}
return hostDetails.AccessIp, port, hostDetails, nil
}
type sForwardInfo struct {
ProxyAddr string `json:"proxy_addr"`
ProxyPort int `json:"proxy_port"`
+4
View File
@@ -51,6 +51,7 @@ type SSshSession struct {
Password string
guestDetails *compute_api.ServerDetails
hostDetails *compute_api.HostDetails
}
func NewSshSession(ctx context.Context, us *mcclient.ClientSession, conn SSshConnectionInfo) *SSshSession {
@@ -65,6 +66,7 @@ func NewSshSession(ctx context.Context, us *mcclient.ClientSession, conn SSshCon
Password: conn.Password,
guestDetails: conn.GuestDetails,
hostDetails: conn.HostDetails,
}
if conn.Port <= 0 {
ret.Port = 22
@@ -147,6 +149,8 @@ func (s *SSshSession) GetDisplayInfo(ctx context.Context) (*SDisplayInfo, error)
dispInfo.WaterMark = fetchWaterMark(userInfo)
if s.guestDetails != nil {
dispInfo.fetchGuestInfo(s.guestDetails)
} else if s.hostDetails != nil {
dispInfo.fetchHostInfo(s.hostDetails)
} else {
dispInfo.Ips = s.Host
if len(s.name) > 0 {