Skip to content

Commit

Permalink
server: api: rest: SSH Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
taking authored and ish-hcc committed Aug 29, 2024
1 parent 3cfe1aa commit be18ba5
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 149 deletions.
242 changes: 100 additions & 142 deletions server/lib/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@ import (
"encoding/json"
"errors"
"fmt"
"strconv"
"strconv"
"strings"
"time"
"time"

"github.com/jollaman999/utils/logger"
"github.com/jollaman999/utils/logger"

"github.com/cloud-barista/cm-honeybee/server/pkg/api/rest/model"

"io"
"log"
"os"
"path/filepath"

Expand Down Expand Up @@ -53,24 +52,23 @@ func DefaultSSHOptions() Options {
if err != nil {
fmt.Printf("failed to determine user home directory: %v\n", err)
}
options := Options{
return Options{
SSHPort: 22,
SSHUsername: defaultUsername(),
SSHPassword: "",
IdentityFilePath: filepath.Join(homeDir, ".ssh", "id_rsa"),
IdentityFilePathProvided: false,
}
return options
}

func (o *SSH) NewClientConn(connectionInfo model.ConnectionInfo) error {
addr := fmt.Sprintf("%s:%d", connectionInfo.IPAddress, connectionInfo.SSHPort)

sshConfig := &ssh.ClientConfig{
User: connectionInfo.User,
Auth: o.getAuthMethods(connectionInfo),
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: time.Second * 5,
User: connectionInfo.User,
Auth: o.getAuthMethods(connectionInfo),
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: 5 * time.Second,
}

client, err := ssh.Dial("tcp", addr, sshConfig)
Expand All @@ -87,204 +85,170 @@ func (o *SSH) NewClientConn(connectionInfo model.ConnectionInfo) error {
}

func (o *SSH) RunBenchmark(connectionInfo model.ConnectionInfo, types string) (string, error) {
err := o.NewClientConn(connectionInfo)
if err != nil {
if err := o.NewClientConn(connectionInfo); err != nil {
return "", err
}
defer func() {
o.Close()
}()
defer o.Close()

// SFTP Client 설정
client, err := sftp.NewClient(o.Options.client)
if err != nil {
logger.Println(logger.ERROR, true, "Failed to SFTP Connect: "+err.Error())
return "", err
}
defer func() {
_ = client.Close()
}()
defer client.Close()

dstPath := "/tmp/"

files := []string{"sourceFiles/milkyway", "sourceFiles/milkyway.sh"}

for _, file := range files {
fileContents, err := sourceFiles.ReadFile(file)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to read source file: "+err.Error())
return "", err
}

dstFilePath := filepath.Join(dstPath, strings.Split(file, "/")[1])
dstFile, err := client.Create(dstFilePath)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to create destination file: "+err.Error())
return "", err
}

logger.Println(logger.DEBUG, true, "SSH: Copying "+file+" to "+dstFilePath)
_, err = io.Copy(dstFile, bytes.NewReader(fileContents))
if err != nil {
log.Fatal("SSH: Failed to File Copy: ", err)
}

output, err := o.RunCmd("chmod +x " + dstFilePath)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to run command: "+
output+" (Error: "+err.Error())
return "", err
}

_ = dstFile.Close()
if err := o.copyFilesToSFTP(client, files, dstPath); err != nil {
return "", err
}

var typesArr []string
if types == "" {
typesArr = []string{
"cpus",
"cpum",
"memR",
"memW",
"fioR",
"fioW",
/*, "dbR", "dbW"*/
}
} else {
typesArr = strings.Split(types, ",")
typesArr := o.getBenchmarkTypes(types)
benchmarkData, err := o.BenchRunCmd(connectionInfo, typesArr)
if err != nil {
return "", err
}

benchmarkData, _ := o.BenchRunCmd(connectionInfo, typesArr)
benchmarkDataToJSON, _ := json.Marshal(benchmarkData)

return string(benchmarkDataToJSON), nil
}

func (o *SSH) BenchRunCmd(connectionInfo model.ConnectionInfo, types []string) ([]model.Benchmark, error){
err := o.NewClientConn(connectionInfo)
if err != nil {
func (o *SSH) BenchRunCmd(connectionInfo model.ConnectionInfo, types []string) ([]model.Benchmark, error) {
if err := o.NewClientConn(connectionInfo); err != nil {
return nil, err
}
defer func() {
o.Close()
}()
defer o.Close()

commands := "/tmp/milkyway.sh --run "
var BenchmarkList []model.Benchmark

for i, t := range types {
logger.Printf(logger.DEBUG, true, "SSH: Benchmark Progressing - [%d/%d] %s...\n", i+1, len(types), t)
output, err := o.RunCmd(commands + t)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to run command: "+output+" (Error: "+err.Error()+")")
if err := o.runBenchmarkCommand(commands+t, &BenchmarkList, t, i, len(types)); err != nil {
return nil, err
}
logger.Println(logger.DEBUG, true, "SSH: Benchmark Output: "+output)
}

var response Response
err = json.Unmarshal([]byte(output), &response)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to unmarshal output: "+err.Error())
return nil, err
}
logger.Println(logger.DEBUG, true, "SSH: Benchmark Result : ", BenchmarkList)
return BenchmarkList, nil
}

benchmarkInfo := model.Benchmark{
Type: t,
Data: response.Data,
}
BenchmarkList = append(BenchmarkList, benchmarkInfo)
func (o *SSH) runBenchmarkCommand(cmd string, BenchmarkList *[]model.Benchmark, t string, i, total int) error {
logger.Printf(logger.DEBUG, true, "SSH: Benchmark Progressing - [%d/%d] %s...\n", i+1, total, t)
output, err := o.RunCmd(cmd)
if err != nil {
logger.Println(logger.DEBUG, true, "Failed to run command : ", err)
return err
}
logger.Println(logger.DEBUG, true, "SSH: Benchmark Output: "+output)

logger.Println(logger.DEBUG, true, "SSH: Benchmark Result : ", BenchmarkList)
var response Response
if err := json.Unmarshal([]byte(output), &response); err != nil {
logger.Println(logger.DEBUG, true, "Failed to unmarshal output", err)
return err
}

return BenchmarkList, nil
*BenchmarkList = append(*BenchmarkList, model.Benchmark{Type: t, Data: response.Data})
return nil
}

func (o *SSH) StopBenchmark(connectionInfo model.ConnectionInfo) error {
err := o.NewClientConn(connectionInfo)
if err != nil {
if err := o.NewClientConn(connectionInfo); err != nil {
return err
}
defer func() {
o.Close()
}()
defer o.Close()

commands := "/tmp/milkyway.sh --stop"

logger.Println(logger.DEBUG, true, "SSH: Benchmark Stopping..")
output, err := o.RunCmd(commands)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to run command: "+
output+" (Error: "+err.Error())
if _, err := o.RunCmd(commands); err != nil {
logger.Println(logger.DEBUG, true, "Failed to run command : ", err)
return err
}
logger.Println(logger.DEBUG, true, "SSH: Benchmark Stopped")

return nil
}

func (o *SSH) RunAgent(connectionInfo model.ConnectionInfo) (string, error) {
err := o.NewClientConn(connectionInfo)
if err != nil {
if err := o.NewClientConn(connectionInfo); err != nil {
return "failed", err
}
defer func() {
o.Close()
}()
defer o.Close()

// SFTP Client 설정
client, err := sftp.NewClient(o.Options.client)
if err != nil {
logger.Println(logger.ERROR, true, "Failed to SFTP Connect: "+err.Error())
return "failed", err
}
defer func() {
_ = client.Close()
}()
defer client.Close()

dstPath := "/tmp/"

file := "sourceFiles/copyAgent.sh"

fileContents, err := sourceFiles.ReadFile(file)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to read source file: "+err.Error())
return "failed", err
}
if err := o.copyFileToSFTP(client, file, dstPath); err != nil {
return "failed", err
}

dstFilePath := filepath.Join(dstPath, strings.Split(file, "/")[1])
dstFile, err := client.Create(dstFilePath)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to create destination file: "+err.Error())
return "failed", err
}
commands := "/tmp/copyAgent.sh"
logger.Printf(logger.DEBUG, true, "SSH: copyAgent Progressing...\n")
if _, err := o.RunCmd("sudo " + commands); err != nil {
logger.Println(logger.DEBUG, true, "Failed to run command : ", err)
return "failed", err
}

logger.Println(logger.DEBUG, true, "SSH: Copying "+file+" to "+dstFilePath)
_, err = io.Copy(dstFile, bytes.NewReader(fileContents))
if err != nil {
log.Fatal("SSH: Failed to File Copy: ", err)
}
return o.checkAgentStatus()
}

output, err := o.RunCmd("chmod +x " + dstFilePath)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to run command: "+
output+" (Error: "+err.Error())
return "failed", err
func (o *SSH) copyFilesToSFTP(client *sftp.Client, files []string, dstPath string) error {
for _, file := range files {
if err := o.copyFileToSFTP(client, file, dstPath); err != nil {
return err
}
}
return nil
}

_ = dstFile.Close()

commands := "/tmp/copyAgent.sh"
func (o *SSH) copyFileToSFTP(client *sftp.Client, file, dstPath string) error {
fileContents, err := sourceFiles.ReadFile(file)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to read source file: "+err.Error())
return err
}

logger.Printf(logger.DEBUG, true, "SSH: copyAgent Progressing...\n")
output, err = o.RunCmd("sudo " + commands)
dstFilePath := filepath.Join(dstPath, filepath.Base(file))
dstFile, err := client.Create(dstFilePath)
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to run command: "+
output+" (Error: "+err.Error())
return "failed", err
logger.Println(logger.ERROR, true, "SSH: Failed to create destination file: "+err.Error())
return err
}
defer dstFile.Close()

logger.Println(logger.DEBUG, true, "SSH: Copying "+file+" to "+dstFilePath)
if _, err := io.Copy(dstFile, bytes.NewReader(fileContents)); err != nil {
logger.Println(logger.ERROR, true, "Failed to File Copy", err)
return nil
}

if _, err := o.RunCmd("chmod +x " + dstFilePath); err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to run command: ", err)
return nil
}

output, err = o.RunCmd("curl -o /dev/null -w '%{http_code}' -X GET http://localhost:8082/honeybee-agent/readyz -H 'accept: application/json'")
return nil
}

func (o *SSH) getBenchmarkTypes(types string) []string {
if types == "" {
return []string{"cpus", "cpum", "memR", "memW", "fioR", "fioW"}
}
return strings.Split(types, ",")
}

func (o *SSH) checkAgentStatus() (string, error) {
output, err := o.RunCmd("curl -o /dev/null -w '%{http_code}' -X GET http://localhost:8082/honeybee-agent/readyz -H 'accept: application/json'")
if err != nil {
logger.Println(logger.ERROR, true, "SSH: Failed to run command: "+
output+" (Error: "+err.Error())
Expand All @@ -294,10 +258,8 @@ func (o *SSH) RunAgent(connectionInfo model.ConnectionInfo) (string, error) {
if output == "200" {
return "success", nil
}

return "failed", nil
}

func (o *SSH) getAuthMethods(connectionInfo model.ConnectionInfo) []ssh.AuthMethod {
var methods []ssh.AuthMethod

Expand Down Expand Up @@ -351,13 +313,9 @@ func (o *SSH) RunCmd(cmd string) (string, error) {
if err != nil {
return "", fmt.Errorf("failed to create session: %s", err)
}
defer func() {
_ = session.Close()
}()

var output bytes.Buffer
var stderr bytes.Buffer
defer session.Close()

var output, stderr bytes.Buffer
session.Stdout = &output
session.Stderr = &stderr

Expand Down
8 changes: 1 addition & 7 deletions server/pkg/api/rest/controller/benchmarkInfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,7 @@ func GetBenchmarkInfo(c echo.Context) error {
return common.ReturnErrorMsg(c, "Failed to get information of the benchmark.")
}

logger.Println(logger.ERROR, true, "savedBenchmarkInfo : ", savedBenchmarkInfo)

// var benchmark model.Benchmark
// err = json.Unmarshal([]byte(savedBenchmarkInfo.BenchmarkData), &benchmark)
// if err != nil {
// return common.ReturnInternalError(c, err, "Error occurred while parsing software list.")
// }
logger.Println(logger.INFO, true, "savedBenchmarkInfo : ", savedBenchmarkInfo)

return c.JSONPretty(http.StatusOK, savedBenchmarkInfo, " ")
}
Expand Down

0 comments on commit be18ba5

Please sign in to comment.