Skip to content

Commit

Permalink
fix(webconsole,apigateway): execute container command by climc ssh way (
Browse files Browse the repository at this point in the history
  • Loading branch information
zexi authored Dec 16, 2024
1 parent 753a7ee commit 472c5f8
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 19 deletions.
24 changes: 24 additions & 0 deletions pkg/apis/webconsole/climc_ssh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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 webconsole

type ClimcSshInfo struct {
IpAddr string `json:"ip_addr"`
Username string `json:"username"`
Command string `json:"command"`
Args []string `json:"args"`
Env map[string]string `json:"env"`
DisplayInfo *SK8sShellDisplayInfo `json:"display_info"`
}
43 changes: 34 additions & 9 deletions pkg/mcclient/modules/webconsole/mod_webconsole.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,15 @@ type CloudShellRequest struct {
}

func (m WebConsoleManager) DoCloudShell(s *mcclient.ClientSession, _ jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return m.doCloudSshShell(s, nil)
return m.doCloudSshShell(s, nil, "", nil, nil)
}

func (m WebConsoleManager) climcSshConnect(s *mcclient.ClientSession, hostname string) (jsonutils.JSONObject, error) {
func (m WebConsoleManager) climcSshConnect(s *mcclient.ClientSession, hostname string, command string, args []string, env map[string]string, info *webconsole_api.SK8sShellDisplayInfo) (jsonutils.JSONObject, error) {
if hostname == "" {
hostname = "climc"
}
// maybe running in docker compose environment, so try to use ssh way
data, err := m.DoClimcSshConnect(s, hostname, 22)
data, err := m.DoClimcSshConnect(s, hostname, 22, command, args, env, info)
if err != nil {
return nil, errors.Wrap(err, "DoClimcSshConnect")
}
Expand Down Expand Up @@ -197,7 +197,28 @@ func (m WebConsoleManager) doActionWithClimcPod(
}

func (m WebConsoleManager) doCloudShell(s *mcclient.ClientSession, info *webconsole_api.SK8sShellDisplayInfo, cmd string, args ...string) (jsonutils.JSONObject, error) {
return m.doActionWithClimcPod(s, func(s *mcclient.ClientSession, clusterId string, pod jsonutils.JSONObject) (jsonutils.JSONObject, error) {
endpointType := "internal"
authUrl, err := s.GetServiceURL("identity", endpointType)
if err != nil {
return nil, httperrors.NewNotFoundError("auth_url not found")
}
env := map[string]string{
"OS_AUTH_TOKEN": s.GetToken().GetTokenString(),
"OS_PROJECT_NAME": s.GetProjectName(),
"OS_PROJECT_DOMAIN": s.GetProjectDomain(),
"OS_AUTH_URL": authUrl,
"OS_ENDPOINT_TYPE": endpointType,
"YUNION_USE_CACHED_TOKEN": "false",
"YUNION_INSECURE": "true",
"OS_USERNAME": "",
"OS_PASSWORD": "",
"OS_DOMAIN_NAME": "",
"OS_ACCESS_KEY": "",
"OS_SECRET_KEY": "",
"OS_TRY_TERM_WIDTH": "false",
}
return m.doCloudSshShell(s, info, cmd, args, env)
/*return m.doActionWithClimcPod(s, func(s *mcclient.ClientSession, clusterId string, pod jsonutils.JSONObject) (jsonutils.JSONObject, error) {
req := webconsole_api.SK8sShellRequest{}
req.Cluster = clusterId
req.Namespace = "onecloud"
Expand Down Expand Up @@ -230,22 +251,22 @@ func (m WebConsoleManager) doCloudShell(s *mcclient.ClientSession, info *webcons
return nil, errors.Wrapf(err, "get pod name from: %s", pod.String())
}
return m.DoK8sConnect(s, podName, "shell", jsonutils.Marshal(req))
})
})*/
}

func (m WebConsoleManager) doCloudSshShell(s *mcclient.ClientSession, info *webconsole_api.SK8sShellDisplayInfo) (jsonutils.JSONObject, error) {
func (m WebConsoleManager) doCloudSshShell(s *mcclient.ClientSession, info *webconsole_api.SK8sShellDisplayInfo, command string, args []string, env map[string]string) (jsonutils.JSONObject, error) {
data, err := m.doActionWithClimcPod(s, func(s *mcclient.ClientSession, clusterId string, pod jsonutils.JSONObject) (jsonutils.JSONObject, error) {
podIP, err := pod.GetString("podIP")
if err != nil {
return nil, errors.Wrap(err, "get podIP")
}
return m.climcSshConnect(s, podIP)
return m.climcSshConnect(s, podIP, command, args, env, info)
})
errs := []error{}
if err != nil {
errs = append(errs, err)
// try climc ssh
data, err := m.climcSshConnect(s, "")
data, err := m.climcSshConnect(s, "", command, args, env, info)
if err != nil {
errs = append(errs, err)
return nil, errors.NewAggregate(errs)
Expand Down Expand Up @@ -276,13 +297,17 @@ func (m WebConsoleManager) DoServerRDPConnect(s *mcclient.ClientSession, id stri
return m.DoConnect(s, "server-rdp", id, "", params)
}

func (m WebConsoleManager) DoClimcSshConnect(s *mcclient.ClientSession, ip string, port int) (jsonutils.JSONObject, error) {
func (m WebConsoleManager) DoClimcSshConnect(s *mcclient.ClientSession, ip string, port int, command string, args []string, env map[string]string, info *webconsole_api.SK8sShellDisplayInfo) (jsonutils.JSONObject, error) {
data := jsonutils.Marshal(map[string]interface{}{
"username": "root",
"keep_username": true,
"ip_addr": ip,
"port": port,
"name": "climc",
"env": env,
"command": command,
"args": args,
"display_info": info,
})
body := jsonutils.NewDict()
body.Set("webconsole", data)
Expand Down
34 changes: 26 additions & 8 deletions pkg/webconsole/command/climc_ssh_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,20 @@ import (

"yunion.io/x/pkg/errors"

"yunion.io/x/onecloud/pkg/apis/webconsole"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/webconsole/helper"
)

type ClimcSshInfo struct {
IpAddr string `json:"ip_addr"`
Username string `json:"username"`
}

type ClimcSshCommand struct {
*BaseCommand
Info *ClimcSshInfo
Info *webconsole.ClimcSshInfo
s *mcclient.ClientSession
keyFile string
buffer []byte
}

func NewClimcSshCommand(info *ClimcSshInfo, s *mcclient.ClientSession) (*ClimcSshCommand, error) {
func NewClimcSshCommand(info *webconsole.ClimcSshInfo, s *mcclient.ClientSession) (*ClimcSshCommand, error) {
if info.IpAddr == "" {
return nil, fmt.Errorf("Empty host ip address")
}
Expand Down Expand Up @@ -74,16 +70,24 @@ func NewClimcSshCommand(info *ClimcSshInfo, s *mcclient.ClientSession) (*ClimcSs
"YUNION_USE_CACHED_TOKEN": "false",
"OS_TRY_TERM_WIDTH": "false",
}
if len(info.Env) != 0 {
env = info.Env
}
envCmd := ""
for k, v := range env {
envCmd = fmt.Sprintf("%s export %s=%s", envCmd, k, v)
}
execCmd := "exec bash"
if info.Command != "" {
execCmd = info.Command
execCmd = fmt.Sprintf("%s %s", execCmd, strings.Join(info.Args, " "))
}
sshArgs := []string{
"-t", // force pseudo-terminal allocation
"-o", "StrictHostKeyChecking=no",
"-i", filename,
fmt.Sprintf("%s@%s", info.Username, info.IpAddr),
fmt.Sprintf("'%s && exec bash'", envCmd),
fmt.Sprintf("'%s && %s'", envCmd, execCmd),
}
sshCmd := fmt.Sprintf("ssh %s", strings.Join(sshArgs, " "))
args := []string{"-c", sshCmd}
Expand All @@ -104,6 +108,20 @@ func (c ClimcSshCommand) GetCommand() *exec.Cmd {
return cmd
}

func (c ClimcSshCommand) GetInstanceName() string {
if c.Info.DisplayInfo == nil {
return ""
}
return c.Info.DisplayInfo.InstanceName
}

func (c ClimcSshCommand) GetIPs() []string {
if c.Info.DisplayInfo == nil {
return nil
}
return c.Info.DisplayInfo.IPs
}

func (c ClimcSshCommand) GetProtocol() string {
return PROTOCOL_TTY
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/webconsole/server/tty_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ func initSocketHandler(so socketio.Socket, p *session.Pty) {
}

func cleanUp(so socketio.Socket, p *session.Pty) {
defer func() {
if err := recover(); err != nil {
log.Errorf("recover error: %v", err)
}
}()
so.Disconnect()
p.Stop()
p.Exit = true
Expand Down
2 changes: 1 addition & 1 deletion pkg/webconsole/service/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ func handleClimcShell(ctx context.Context, w http.ResponseWriter, r *http.Reques
httperrors.GeneralServerError(ctx, w, err)
return
}
info := command.ClimcSshInfo{}
info := webconsole_api.ClimcSshInfo{}
err = env.Body.Unmarshal(&info)
if err != nil {
httperrors.GeneralServerError(ctx, w, err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/webconsole/session/pty_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (p *Pty) Stop() (err error) {
}()
defer func() {
if p.Cmd != nil && p.Cmd.Process != nil {
log.Debugf("[%s] stop cmd", p.Session.Id)
log.Debugf("[%s] stop cmd: %s", p.Session.Id, p.Cmd.String())
err := p.Cmd.Process.Signal(os.Kill)
if err != nil {
errs = append(errs, err)
Expand Down

0 comments on commit 472c5f8

Please sign in to comment.