fix: webconsole adb shell choose access ip (#20583)

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
Jian Qiu
2024-06-20 06:27:45 +08:00
committed by GitHub
parent afa5334f65
commit c4dfd8e97b
3 changed files with 74 additions and 40 deletions
+29
View File
@@ -21,6 +21,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
"unicode"
"yunion.io/x/log"
@@ -443,3 +444,31 @@ func PrefixSplit(pref string) (string, int, error) {
return pref, 32, nil
}
}
func TestTcpPort(ip string, port int, timeoutSecs int, tries int) error {
if timeoutSecs <= 0 {
timeoutSecs = 3
}
if tries <= 0 {
tries = 3
}
address := net.JoinHostPort(ip, fmt.Sprintf("%d", port))
// 3 second timeout
errs := make([]error, 0)
for i := 0; i < tries; i++ {
conn, err := net.DialTimeout("tcp", address, time.Duration(timeoutSecs)*time.Second)
if err != nil {
errs = append(errs, err)
} else {
if conn != nil {
_ = conn.Close()
return nil
} else {
errs = append(errs, errors.Wrap(errors.ErrEmpty, "nil conn"))
}
}
time.Sleep(10 * time.Millisecond)
}
return errors.NewAggregate(errs)
}
+11 -15
View File
@@ -20,14 +20,13 @@ import (
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
o "yunion.io/x/onecloud/pkg/webconsole/options"
)
type SAdbShellInfo struct {
IpAddr string `json:"ip_addr"`
Port int `json:"port"`
HostIp string `json:"host_ip"`
HostPort int `json:"host_port"`
}
type SAdbShellCommand struct {
@@ -37,22 +36,19 @@ type SAdbShellCommand struct {
}
func NewAdbShellCommand(info *SAdbShellInfo, s *mcclient.ClientSession) (*SAdbShellCommand, error) {
if info.IpAddr == "" {
return nil, errors.Wrap(httperrors.ErrInputParameter, "Empty host ip address")
}
if info.Port == 0 {
return nil, errors.Wrap(httperrors.ErrInputParameter, "Empty host port")
}
name := o.Options.AdbPath
cmd := NewBaseCommand(s, name, "-s", fmt.Sprintf("%s:%d", info.IpAddr, info.Port), "shell")
var connStr string
initCmd := exec.Command(name, "connect", fmt.Sprintf("%s:%d", info.HostIp, info.HostPort))
if err := initCmd.Run(); err != nil {
return nil, errors.Wrap(err, "connect adb")
} else {
connStr = fmt.Sprintf("%s:%d", info.HostIp, info.HostPort)
}
cmd := NewBaseCommand(s, name, "-s", connStr, "shell")
tool := &SAdbShellCommand{
BaseCommand: cmd,
Info: info,
}
initCmd := exec.Command(name, "connect", fmt.Sprintf("%s:%d", info.IpAddr, info.Port))
if err := initCmd.Run(); err != nil {
return nil, errors.Wrap(err, "connect adb")
}
return tool, nil
}
@@ -65,7 +61,7 @@ func (c SAdbShellCommand) GetProtocol() string {
}
func (c *SAdbShellCommand) Cleanup() error {
initCmd := exec.Command(o.Options.AdbPath, "disconnect", fmt.Sprintf("%s:%d", c.Info.IpAddr, c.Info.Port))
initCmd := exec.Command(o.Options.AdbPath, "disconnect", fmt.Sprintf("%s:%d", c.Info.HostIp, c.Info.HostPort))
if err := initCmd.Run(); err != nil {
return errors.Wrap(err, "disconnect adb")
}
+34 -25
View File
@@ -18,11 +18,13 @@ import (
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/util/httputils"
@@ -39,6 +41,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient/auth"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/mcclient/modules/k8s"
"yunion.io/x/onecloud/pkg/util/netutils2"
"yunion.io/x/onecloud/pkg/webconsole/command"
"yunion.io/x/onecloud/pkg/webconsole/models"
o "yunion.io/x/onecloud/pkg/webconsole/options"
@@ -102,7 +105,7 @@ func fetchK8sEnv(ctx context.Context, w http.ResponseWriter, r *http.Request) (*
if err != nil {
return nil, httperrors.NewNotFoundError("Not found cluster %q kubeconfig", k8sReq.Cluster)
}
f, err := ioutil.TempFile("", "kubeconfig-")
f, err := os.CreateTemp("", "kubeconfig-")
if err != nil {
return nil, fmt.Errorf("Save kubeconfig error: %v", err)
}
@@ -420,34 +423,27 @@ func handleAdbShell(ctx context.Context, w http.ResponseWriter, r *http.Request)
return
}
phoneIp := ""
adbPort := -1
// {\"container_port\":5555,\"host_port\":23888,\"protocol\":\"tcp\"}
type sPortMapping struct {
ContainerPort int `json:"container_port"`
HostPort int `json:"host_port"`
Protocol string `json:"protocol"`
}
if pmstr, ok := serverDetails.Metadata["port_mappings"]; ok {
pmJson, err := jsonutils.ParseString(pmstr)
if err != nil {
httperrors.GeneralServerError(ctx, w, err)
return
}
portMaps := make([]sPortMapping, 0)
err = pmJson.Unmarshal(&portMaps)
if err != nil {
httperrors.GeneralServerError(ctx, w, err)
return
}
if len(serverDetails.Nics) > 0 {
phoneIp = serverDetails.Nics[0].IpAddr
portMaps := serverDetails.Nics[0].PortMappings
for i := range portMaps {
portMap := portMaps[i]
if portMap.ContainerPort == 5555 && portMap.Protocol == "tcp" {
adbPort = portMap.HostPort
if portMap.Port == 5555 && portMap.Protocol == "tcp" {
adbPort = *portMap.HostPort
break
}
}
var errMsgs []string
if !regutils.MatchIP4Addr(phoneIp) {
errMsgs = append(errMsgs, "invalid phone IP")
}
if adbPort < 0 {
httperrors.GeneralServerError(ctx, w, httperrors.NewNotSupportedError("adb port not found"))
errMsgs = append(errMsgs, "adb port not found")
}
if len(errMsgs) > 0 {
httperrors.GeneralServerError(ctx, w, httperrors.NewNotSupportedError(strings.Join(errMsgs, ";")))
return
}
} else {
@@ -455,9 +451,22 @@ func handleAdbShell(ctx context.Context, w http.ResponseWriter, r *http.Request)
return
}
{
// test phoneIP is accessible
err := netutils2.TestTcpPort(phoneIp, 5555, 3, 3)
if err != nil {
log.Errorf("TestTcpPort %s:%d fail %s", phoneIp, 5555, err)
phoneIp = serverDetails.HostEIP
if len(phoneIp) == 0 {
phoneIp = serverDetails.HostAccessIp
}
} else {
adbPort = 5555
}
}
info := command.SAdbShellInfo{
IpAddr: serverDetails.HostAccessIp,
Port: adbPort,
HostIp: phoneIp,
HostPort: adbPort,
}
cmd, err := command.NewAdbShellCommand(&info, env.ClientSessin)