Skip to content

Commit

Permalink
server: Merge source group's connection_check and agent_check to conn…
Browse files Browse the repository at this point in the history
…ection info
  • Loading branch information
ish-hcc committed Sep 29, 2024
1 parent 6adbc98 commit d5f5c94
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 520 deletions.
40 changes: 0 additions & 40 deletions server/dao/sourceGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package dao
import (
"errors"
"github.com/cloud-barista/cm-honeybee/server/db"
"github.com/cloud-barista/cm-honeybee/server/lib/ssh"
"github.com/cloud-barista/cm-honeybee/server/pkg/api/rest/model"
"gorm.io/gorm"
)
Expand Down Expand Up @@ -89,42 +88,3 @@ func SourceGroupDelete(sourceGroup *model.SourceGroup) error {

return nil
}

func SourceGroupCheckConnection(sourceGroup *model.SourceGroup) (*[]model.ConnectionInfo, error) {
connectionInfoList, err := ConnectionInfoGetList(&model.ConnectionInfo{SourceGroupID: sourceGroup.ID}, 0, 0)
if err != nil {
return nil, err
}

for _, connectionInfo := range *connectionInfoList {
oldConnectionInfo, err := ConnectionInfoGet(connectionInfo.ID)
if err != nil {
return nil, err
}

c := &ssh.SSH{
Options: ssh.DefaultSSHOptions(),
}

err = c.NewClientConn(connectionInfo)
if err != nil {
oldConnectionInfo.Status = "Failed"
oldConnectionInfo.FailedMessage = err.Error()
} else {
c.Close()
}

if err == nil {
oldConnectionInfo.Status = "Success"
oldConnectionInfo.FailedMessage = ""
}

err = ConnectionInfoUpdate(oldConnectionInfo)
if err != nil {
return nil, errors.New("Error occurred while updating the connection information. " +
"(ID: " + oldConnectionInfo.ID + ", Error: " + err.Error() + ")")
}
}

return ConnectionInfoGetList(&model.ConnectionInfo{SourceGroupID: sourceGroup.ID}, 0, 0)
}
22 changes: 12 additions & 10 deletions server/lib/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,32 +171,34 @@ func (o *SSH) StopBenchmark(connectionInfo model.ConnectionInfo) error {
return nil
}

func (o *SSH) RunAgent(connectionInfo model.ConnectionInfo) (result string, err error) {
if err = o.NewClientConn(connectionInfo); err != nil {
return "failed", err
func (o *SSH) RunAgent(connectionInfo model.ConnectionInfo) error {
if err := o.NewClientConn(connectionInfo); err != nil {
return err
}
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
return err
}
defer client.Close()
defer func() {
_ = client.Close()
}()

dstPath := "/tmp/"
file := "sourceFiles/copyAgent.sh"

if err = o.copyFileToSFTP(client, file, dstPath); err != nil {
return "failed", err
return 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
return err
}

return o.checkAgentStatus()
Expand Down Expand Up @@ -247,7 +249,7 @@ func (o *SSH) getBenchmarkTypes(types string) []string {
return strings.Split(types, ",")
}

func (o *SSH) checkAgentStatus() (string, error) {
func (o *SSH) checkAgentStatus() error {
tryCount := 30

for i := 0; i < tryCount; i++ {
Expand All @@ -258,13 +260,13 @@ func (o *SSH) checkAgentStatus() (string, error) {
}

if output == "200" {
return "success", nil
return nil
}

time.Sleep(1 * time.Second)
}

return "failed", errors.New("agent health check failed")
return errors.New("agent health check failed")
}

func (o *SSH) SendGetRequestToAgent(connectionInfo model.ConnectionInfo, requestPath string) (string, error) {
Expand Down
91 changes: 74 additions & 17 deletions server/pkg/api/rest/controller/connectionInfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
serverCommon "github.com/cloud-barista/cm-honeybee/server/common"
"github.com/cloud-barista/cm-honeybee/server/dao"
"github.com/cloud-barista/cm-honeybee/server/lib/rsautil"
"github.com/cloud-barista/cm-honeybee/server/lib/ssh"
"github.com/cloud-barista/cm-honeybee/server/pkg/api/rest/common"
"github.com/cloud-barista/cm-honeybee/server/pkg/api/rest/model"
"github.com/google/uuid"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/labstack/echo/v4"
"net/http"
"strconv"
"sync"
)

func checkIPAddress(ipAddress string) error {
Expand Down Expand Up @@ -157,6 +159,55 @@ func CreateConnectionInfo(c echo.Context) error {
return c.JSONPretty(http.StatusOK, connectionInfo, " ")
}

func doGetConnectionInfo(connID string) (*model.ConnectionInfo, error) {
connectionInfo, err := dao.ConnectionInfoGet(connID)
if err != nil {
return nil, err
}

oldConnectionInfo, err := dao.ConnectionInfoGet(connectionInfo.ID)
if err != nil {
return nil, err
}

c := &ssh.SSH{
Options: ssh.DefaultSSHOptions(),
}

err = c.NewClientConn(*connectionInfo)
if err != nil {
oldConnectionInfo.ConnectionStatus = model.ConnectionInfoStatusFailed
oldConnectionInfo.ConnectionFailedMessage = err.Error()
} else {
c.Close()
oldConnectionInfo.ConnectionStatus = model.ConnectionInfoStatusSuccess
oldConnectionInfo.ConnectionFailedMessage = ""
}

err = c.RunAgent(*connectionInfo)
if err != nil {
oldConnectionInfo.AgentStatus = model.ConnectionInfoStatusFailed
oldConnectionInfo.AgentFailedMessage = err.Error()
} else {
c.Close()
oldConnectionInfo.AgentStatus = model.ConnectionInfoStatusSuccess
oldConnectionInfo.AgentFailedMessage = ""
}

err = dao.ConnectionInfoUpdate(oldConnectionInfo)
if err != nil {
return nil, errors.New("Error occurred while updating the connection information. " +
"(ID: " + oldConnectionInfo.ID + ", Error: " + err.Error() + ")")
}

connectionInfo, err = encryptSecrets(connectionInfo)
if err != nil {
return nil, err
}

return connectionInfo, nil
}

// GetConnectionInfo godoc
//
// @ID get-connection-info
Expand Down Expand Up @@ -187,12 +238,7 @@ func GetConnectionInfo(c echo.Context) error {
return common.ReturnErrorMsg(c, "Please provide the connId.")
}

connectionInfo, err := dao.ConnectionInfoGet(connID)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}

connectionInfo, err = encryptSecrets(connectionInfo)
connectionInfo, err := doGetConnectionInfo(connID)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}
Expand All @@ -219,12 +265,7 @@ func GetConnectionInfoDirectly(c echo.Context) error {
return common.ReturnErrorMsg(c, "Please provide the connId.")
}

connectionInfo, err := dao.ConnectionInfoGet(connID)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}

connectionInfo, err = encryptSecrets(connectionInfo)
connectionInfo, err := doGetConnectionInfo(connID)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}
Expand Down Expand Up @@ -283,15 +324,31 @@ func ListConnectionInfo(c echo.Context) error {
}

var encryptedConnectionInfos []model.ConnectionInfo

var encryptedConnectionInfosLock sync.Mutex
var wg sync.WaitGroup
wg.Add(len(*connectionInfos))

for _, ci := range *connectionInfos {
encryptedConnectionInfo, err := encryptSecrets(&ci)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}
go func(connectionInfo model.ConnectionInfo) {
defer func() {
wg.Done()
}()

encryptedConnectionInfos = append(encryptedConnectionInfos, *encryptedConnectionInfo)
encryptedConnectionInfo, err := doGetConnectionInfo(connectionInfo.ID)
if err != nil {
encryptedConnectionInfo.ConnectionStatus = model.ConnectionInfoStatusFailed
encryptedConnectionInfo.ConnectionFailedMessage = err.Error()
}

encryptedConnectionInfosLock.Lock()
encryptedConnectionInfos = append(encryptedConnectionInfos, *encryptedConnectionInfo)
encryptedConnectionInfosLock.Unlock()
}(ci)
}

wg.Wait()

return c.JSONPretty(http.StatusOK, &encryptedConnectionInfos, " ")
}

Expand Down
119 changes: 0 additions & 119 deletions server/pkg/api/rest/controller/sourceGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package controller

import (
"github.com/cloud-barista/cm-honeybee/server/dao"
"github.com/cloud-barista/cm-honeybee/server/lib/ssh"
"github.com/cloud-barista/cm-honeybee/server/pkg/api/rest/common"
"github.com/cloud-barista/cm-honeybee/server/pkg/api/rest/model"
"github.com/google/uuid"
"github.com/jollaman999/utils/logger"
"github.com/labstack/echo/v4"
"net/http"
"sync"
)

// CreateSourceGroup godoc
Expand Down Expand Up @@ -288,120 +286,3 @@ func DeleteSourceGroup(c echo.Context) error {

return c.JSONPretty(http.StatusOK, model.SimpleMsg{Message: "success"}, " ")
}

// CheckConnectionSourceGroup godoc
//
// @ID check-connection-source-group
// @Summary Check Connection SourceGroup
// @Description Check if SSH connection is available for each connection info in source group. Show each status by returning connection info list.
// @Tags [On-premise] SourceGroup
// @Accept json
// @Produce json
// @Param sgId path string true "ID of the SourceGroup"
// @Success 200 {object} []model.ConnectionInfo "Successfully checked SSH connection for the source group"
// @Failure 400 {object} common.ErrorResponse "Sent bad request."
// @Failure 500 {object} common.ErrorResponse "Failed to check SSH connection for the source group"
// @Router /source_group/{sgId}/connection_check [get]
func CheckConnectionSourceGroup(c echo.Context) error {
sgID := c.Param("sgId")
if sgID == "" {
return common.ReturnErrorMsg(c, "Please provide the sgId.")
}

sourceGroup, err := dao.SourceGroupGet(sgID)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}

connectionInfoList, err := dao.SourceGroupCheckConnection(sourceGroup)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}

var encryptedConnectionInfos []model.ConnectionInfo

var encryptedConnectionInfosLock sync.Mutex
var wg sync.WaitGroup
wg.Add(len(*connectionInfoList))
for _, ci := range *connectionInfoList {
go func(connectionInfo model.ConnectionInfo) {
defer func() {
wg.Done()
}()

encryptedConnectionInfo, err := encryptSecrets(&ci)
if err != nil {
connectionInfo.Status = model.ConnectionInfoStatusFailed
connectionInfo.FailedMessage = err.Error()
}

encryptedConnectionInfosLock.Lock()
encryptedConnectionInfos = append(encryptedConnectionInfos, *encryptedConnectionInfo)
encryptedConnectionInfosLock.Unlock()
}(ci)
}
wg.Wait()

return c.JSONPretty(http.StatusOK, encryptedConnectionInfos, " ")
}

// CheckAgentSourceGroup godoc
//
// @ID check-agent-source-group
// @Summary Check Agent SourceGroup
// @Description Check Agent in source group. Show each status by returning agent info list. If no Agent is present on the connected server, the Agent will be automatically installed.
// @Tags [On-premise] SourceGroup
// @Accept json
// @Produce json
// @Param sgId path string true "ID of the SourceGroup"
// @Success 200 {object} []model.AgentInfo "Successfully checked Agent for the source group"
// @Failure 400 {object} common.ErrorResponse "Sent bad request."
// @Failure 500 {object} common.ErrorResponse "Failed to check Agent for the source group"
// @Router /source_group/{sgId}/agent_check [get]
func CheckAgentSourceGroup(c echo.Context) error {
sgID := c.Param("sgId")
if sgID == "" {
return common.ReturnErrorMsg(c, "Please provide the sgId.")
}

sourceGroup, err := dao.SourceGroupGet(sgID)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}

connectionInfoList, err := dao.SourceGroupCheckConnection(sourceGroup)
if err != nil {
return common.ReturnErrorMsg(c, err.Error())
}

var agentInfos []model.AgentInfo

var agentInfosLock sync.Mutex
var wg sync.WaitGroup
wg.Add(len(*connectionInfoList))
for _, ci := range *connectionInfoList {
go func(connectionInfo model.ConnectionInfo) {
defer func() {
wg.Done()
}()

s := &ssh.SSH{
Options: ssh.DefaultSSHOptions(),
}

data, err := s.RunAgent(connectionInfo)
agentInfo := model.AgentInfo{
Connection: connectionInfo.Name,
Result: data,
ErrorMsg: err,
}

agentInfosLock.Lock()
agentInfos = append(agentInfos, agentInfo)
agentInfosLock.Unlock()
}(ci)
}
wg.Wait()

return c.JSONPretty(http.StatusOK, agentInfos, " ")
}
Loading

0 comments on commit d5f5c94

Please sign in to comment.