diff --git a/src/api/rest/docs/docs.go b/src/api/rest/docs/docs.go index 37e7ede4b..2e4ebd8af 100644 --- a/src/api/rest/docs/docs.go +++ b/src/api/rest/docs/docs.go @@ -1,4 +1,5 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT +// Package docs GENERATED BY SWAG; DO NOT EDIT +// This file was generated by swaggo/swag package docs import "github.com/swaggo/swag" @@ -7429,34 +7430,6 @@ const docTemplate = `{ } } }, - "mcir.CustomImageStatus": { - "type": "string", - "enum": [ - "Available", - "Unavailable" - ], - "x-enum-varnames": [ - "MyImageAvailable", - "MyImageUnavailable" - ] - }, - "mcir.DiskStatus": { - "type": "string", - "enum": [ - "Creating", - "Available", - "Attached", - "Deleting", - "Error" - ], - "x-enum-varnames": [ - "DiskCreating", - "DiskAvailable", - "DiskAttached", - "DiskDeleting", - "DiskError" - ] - }, "mcir.FilterSpecsByRangeRequest": { "type": "object", "properties": { @@ -7722,11 +7695,7 @@ const docTemplate = `{ }, "iid": { "description": "Fields for response", - "allOf": [ - { - "$ref": "#/definitions/common.IID" - } - ] + "$ref": "#/definitions/common.IID" }, "keyValueList": { "type": "array", @@ -7877,11 +7846,7 @@ const docTemplate = `{ "example": "aws-ap-southeast-1-1" }, "status": { - "allOf": [ - { - "$ref": "#/definitions/mcir.CustomImageStatus" - } - ], + "type": "string", "example": "Available" }, "systemLabel": { @@ -7971,11 +7936,7 @@ const docTemplate = `{ }, "status": { "description": "Available, Unavailable, Attached, ...", - "allOf": [ - { - "$ref": "#/definitions/mcir.DiskStatus" - } - ], + "type": "string", "example": "Available" }, "systemLabel": { @@ -8682,11 +8643,7 @@ const docTemplate = `{ }, "postCommand": { "description": "PostCommand is field for providing command to VMs after its creation. example:\"wget https://raw.githubusercontent.com/cloud-barista/cb-tumblebug/main/scripts/setweb.sh -O ~/setweb.sh; chmod +x ~/setweb.sh; sudo ~/setweb.sh\"", - "allOf": [ - { - "$ref": "#/definitions/mcis.McisCmdReq" - } - ] + "$ref": "#/definitions/mcis.McisCmdReq" }, "vmDynamicReq": { "$ref": "#/definitions/mcis.TbVmDynamicReq" @@ -8959,8 +8916,13 @@ const docTemplate = `{ ], "properties": { "command": { - "type": "string", - "example": "client_ip=$(echo $SSH_CLIENT | awk '{print $1}'); echo SSH client IP is: $client_ip" + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "client_ip=$(echo $SSH_CLIENT | awk '{print $1}'); echo SSH client IP is: $client_ip" + ] }, "userName": { "type": "string", @@ -9418,45 +9380,17 @@ const docTemplate = `{ } } }, - "mcis.RestPostCmdMcisResponse": { - "type": "object", - "properties": { - "mcisId": { - "type": "string" - }, - "result": { - "type": "string" - }, - "vmId": { - "type": "string" - }, - "vmIp": { - "type": "string" - } - } - }, "mcis.RestPostCmdMcisResponseWrapper": { "type": "object", "properties": { - "resultArray": { + "results": { "type": "array", "items": { - "$ref": "#/definitions/mcis.RestPostCmdMcisResponse" + "$ref": "#/definitions/mcis.SshCmdResult" } } } }, - "mcis.SpiderImageType": { - "type": "string", - "enum": [ - "PublicImage", - "MyImage" - ], - "x-enum-varnames": [ - "PublicImage", - "MyImage" - ] - }, "mcis.SpiderVMInfo": { "type": "object", "properties": { @@ -9478,11 +9412,7 @@ const docTemplate = `{ }, "iid": { "description": "Fields for response", - "allOf": [ - { - "$ref": "#/definitions/common.IID" - } - ] + "$ref": "#/definitions/common.IID" }, "imageIId": { "$ref": "#/definitions/common.IID" @@ -9491,7 +9421,7 @@ const docTemplate = `{ "type": "string" }, "imageType": { - "$ref": "#/definitions/mcis.SpiderImageType" + "type": "string" }, "keyPairIId": { "$ref": "#/definitions/common.IID" @@ -9527,11 +9457,7 @@ const docTemplate = `{ }, "region": { "description": "ex) {us-east1, us-east1-c} or {ap-northeast-2}", - "allOf": [ - { - "$ref": "#/definitions/mcis.RegionInfo" - } - ] + "$ref": "#/definitions/mcis.RegionInfo" }, "rootDeviceName": { "description": "\"/dev/sda1\", ...", @@ -9566,11 +9492,7 @@ const docTemplate = `{ }, "subnetIID": { "description": "AWS, ex) subnet-8c4a53e4", - "allOf": [ - { - "$ref": "#/definitions/common.IID" - } - ] + "$ref": "#/definitions/common.IID" }, "subnetName": { "type": "string" @@ -9594,6 +9516,33 @@ const docTemplate = `{ } } }, + "mcis.SshCmdResult": { + "type": "object", + "properties": { + "err": {}, + "mcisId": { + "type": "string" + }, + "stderr": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "stdout": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vmId": { + "type": "string" + }, + "vmIp": { + "type": "string" + } + } + }, "mcis.StatusCountInfo": { "type": "object", "properties": { @@ -10009,19 +9958,11 @@ const docTemplate = `{ }, "healthChecker": { "description": "HealthChecker", - "allOf": [ - { - "$ref": "#/definitions/mcis.TbNLBHealthCheckerReq" - } - ] + "$ref": "#/definitions/mcis.TbNLBHealthCheckerReq" }, "listener": { "description": "Frontend", - "allOf": [ - { - "$ref": "#/definitions/mcis.NLBListenerReq" - } - ] + "$ref": "#/definitions/mcis.NLBListenerReq" }, "scope": { "description": "REGION(V) | GLOBAL", @@ -10034,11 +9975,7 @@ const docTemplate = `{ }, "targetGroup": { "description": "Backend", - "allOf": [ - { - "$ref": "#/definitions/mcis.TbNLBTargetGroupReq" - } - ] + "$ref": "#/definitions/mcis.TbNLBTargetGroupReq" }, "type": { "description": "PUBLIC(V) | INTERNAL", @@ -10237,11 +10174,7 @@ const docTemplate = `{ }, "region": { "description": "AWS, ex) {us-east1, us-east1-c} or {ap-northeast-2}", - "allOf": [ - { - "$ref": "#/definitions/mcis.RegionInfo" - } - ] + "$ref": "#/definitions/mcis.RegionInfo" }, "rootDeviceName": { "type": "string" @@ -10638,8 +10571,6 @@ var SwaggerInfo = &swag.Spec{ Description: "CB-Tumblebug REST API", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, - LeftDelim: "{{", - RightDelim: "}}", } func init() { diff --git a/src/api/rest/docs/swagger.json b/src/api/rest/docs/swagger.json index f4ee5c4b4..2e0170064 100644 --- a/src/api/rest/docs/swagger.json +++ b/src/api/rest/docs/swagger.json @@ -7422,34 +7422,6 @@ } } }, - "mcir.CustomImageStatus": { - "type": "string", - "enum": [ - "Available", - "Unavailable" - ], - "x-enum-varnames": [ - "MyImageAvailable", - "MyImageUnavailable" - ] - }, - "mcir.DiskStatus": { - "type": "string", - "enum": [ - "Creating", - "Available", - "Attached", - "Deleting", - "Error" - ], - "x-enum-varnames": [ - "DiskCreating", - "DiskAvailable", - "DiskAttached", - "DiskDeleting", - "DiskError" - ] - }, "mcir.FilterSpecsByRangeRequest": { "type": "object", "properties": { @@ -7715,11 +7687,7 @@ }, "iid": { "description": "Fields for response", - "allOf": [ - { - "$ref": "#/definitions/common.IID" - } - ] + "$ref": "#/definitions/common.IID" }, "keyValueList": { "type": "array", @@ -7870,11 +7838,7 @@ "example": "aws-ap-southeast-1-1" }, "status": { - "allOf": [ - { - "$ref": "#/definitions/mcir.CustomImageStatus" - } - ], + "type": "string", "example": "Available" }, "systemLabel": { @@ -7964,11 +7928,7 @@ }, "status": { "description": "Available, Unavailable, Attached, ...", - "allOf": [ - { - "$ref": "#/definitions/mcir.DiskStatus" - } - ], + "type": "string", "example": "Available" }, "systemLabel": { @@ -8675,11 +8635,7 @@ }, "postCommand": { "description": "PostCommand is field for providing command to VMs after its creation. example:\"wget https://raw.githubusercontent.com/cloud-barista/cb-tumblebug/main/scripts/setweb.sh -O ~/setweb.sh; chmod +x ~/setweb.sh; sudo ~/setweb.sh\"", - "allOf": [ - { - "$ref": "#/definitions/mcis.McisCmdReq" - } - ] + "$ref": "#/definitions/mcis.McisCmdReq" }, "vmDynamicReq": { "$ref": "#/definitions/mcis.TbVmDynamicReq" @@ -8952,8 +8908,13 @@ ], "properties": { "command": { - "type": "string", - "example": "client_ip=$(echo $SSH_CLIENT | awk '{print $1}'); echo SSH client IP is: $client_ip" + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "client_ip=$(echo $SSH_CLIENT | awk '{print $1}'); echo SSH client IP is: $client_ip" + ] }, "userName": { "type": "string", @@ -9411,45 +9372,17 @@ } } }, - "mcis.RestPostCmdMcisResponse": { - "type": "object", - "properties": { - "mcisId": { - "type": "string" - }, - "result": { - "type": "string" - }, - "vmId": { - "type": "string" - }, - "vmIp": { - "type": "string" - } - } - }, "mcis.RestPostCmdMcisResponseWrapper": { "type": "object", "properties": { - "resultArray": { + "results": { "type": "array", "items": { - "$ref": "#/definitions/mcis.RestPostCmdMcisResponse" + "$ref": "#/definitions/mcis.SshCmdResult" } } } }, - "mcis.SpiderImageType": { - "type": "string", - "enum": [ - "PublicImage", - "MyImage" - ], - "x-enum-varnames": [ - "PublicImage", - "MyImage" - ] - }, "mcis.SpiderVMInfo": { "type": "object", "properties": { @@ -9471,11 +9404,7 @@ }, "iid": { "description": "Fields for response", - "allOf": [ - { - "$ref": "#/definitions/common.IID" - } - ] + "$ref": "#/definitions/common.IID" }, "imageIId": { "$ref": "#/definitions/common.IID" @@ -9484,7 +9413,7 @@ "type": "string" }, "imageType": { - "$ref": "#/definitions/mcis.SpiderImageType" + "type": "string" }, "keyPairIId": { "$ref": "#/definitions/common.IID" @@ -9520,11 +9449,7 @@ }, "region": { "description": "ex) {us-east1, us-east1-c} or {ap-northeast-2}", - "allOf": [ - { - "$ref": "#/definitions/mcis.RegionInfo" - } - ] + "$ref": "#/definitions/mcis.RegionInfo" }, "rootDeviceName": { "description": "\"/dev/sda1\", ...", @@ -9559,11 +9484,7 @@ }, "subnetIID": { "description": "AWS, ex) subnet-8c4a53e4", - "allOf": [ - { - "$ref": "#/definitions/common.IID" - } - ] + "$ref": "#/definitions/common.IID" }, "subnetName": { "type": "string" @@ -9587,6 +9508,33 @@ } } }, + "mcis.SshCmdResult": { + "type": "object", + "properties": { + "err": {}, + "mcisId": { + "type": "string" + }, + "stderr": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "stdout": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vmId": { + "type": "string" + }, + "vmIp": { + "type": "string" + } + } + }, "mcis.StatusCountInfo": { "type": "object", "properties": { @@ -10002,19 +9950,11 @@ }, "healthChecker": { "description": "HealthChecker", - "allOf": [ - { - "$ref": "#/definitions/mcis.TbNLBHealthCheckerReq" - } - ] + "$ref": "#/definitions/mcis.TbNLBHealthCheckerReq" }, "listener": { "description": "Frontend", - "allOf": [ - { - "$ref": "#/definitions/mcis.NLBListenerReq" - } - ] + "$ref": "#/definitions/mcis.NLBListenerReq" }, "scope": { "description": "REGION(V) | GLOBAL", @@ -10027,11 +9967,7 @@ }, "targetGroup": { "description": "Backend", - "allOf": [ - { - "$ref": "#/definitions/mcis.TbNLBTargetGroupReq" - } - ] + "$ref": "#/definitions/mcis.TbNLBTargetGroupReq" }, "type": { "description": "PUBLIC(V) | INTERNAL", @@ -10230,11 +10166,7 @@ }, "region": { "description": "AWS, ex) {us-east1, us-east1-c} or {ap-northeast-2}", - "allOf": [ - { - "$ref": "#/definitions/mcis.RegionInfo" - } - ] + "$ref": "#/definitions/mcis.RegionInfo" }, "rootDeviceName": { "type": "string" diff --git a/src/api/rest/docs/swagger.yaml b/src/api/rest/docs/swagger.yaml index d8bf602bc..fe100556f 100644 --- a/src/api/rest/docs/swagger.yaml +++ b/src/api/rest/docs/swagger.yaml @@ -185,28 +185,6 @@ definitions: connectionName: type: string type: object - mcir.CustomImageStatus: - enum: - - Available - - Unavailable - type: string - x-enum-varnames: - - MyImageAvailable - - MyImageUnavailable - mcir.DiskStatus: - enum: - - Creating - - Available - - Attached - - Deleting - - Error - type: string - x-enum-varnames: - - DiskCreating - - DiskAvailable - - DiskAttached - - DiskDeleting - - DiskError mcir.FilterSpecsByRangeRequest: properties: connectionName: @@ -379,8 +357,7 @@ definitions: description: Windows7, Ubuntu etc. type: string iid: - allOf: - - $ref: '#/definitions/common.IID' + $ref: '#/definitions/common.IID' description: Fields for response keyValueList: items: @@ -484,9 +461,8 @@ definitions: example: aws-ap-southeast-1-1 type: string status: - allOf: - - $ref: '#/definitions/mcir.CustomImageStatus' example: Available + type: string systemLabel: description: SystemLabel is for describing the MCIR in a keyword (any string can be used) for special System purpose @@ -549,10 +525,9 @@ definitions: example: aws-ap-southeast-1-datadisk type: string status: - allOf: - - $ref: '#/definitions/mcir.DiskStatus' description: Available, Unavailable, Attached, ... example: Available + type: string systemLabel: description: SystemLabel is for describing the MCIR in a keyword (any string can be used) for special System purpose @@ -1043,8 +1018,7 @@ definitions: example: random type: string postCommand: - allOf: - - $ref: '#/definitions/mcis.McisCmdReq' + $ref: '#/definitions/mcis.McisCmdReq' description: PostCommand is field for providing command to VMs after its creation. example:"wget https://raw.githubusercontent.com/cloud-barista/cb-tumblebug/main/scripts/setweb.sh -O ~/setweb.sh; chmod +x ~/setweb.sh; sudo ~/setweb.sh" @@ -1228,9 +1202,12 @@ definitions: mcis.McisCmdReq: properties: command: - example: 'client_ip=$(echo $SSH_CLIENT | awk ''{print $1}''); echo SSH client - IP is: $client_ip' - type: string + example: + - 'client_ip=$(echo $SSH_CLIENT | awk ''{print $1}''); echo SSH client IP + is: $client_ip' + items: + type: string + type: array userName: example: cb-user type: string @@ -1546,32 +1523,13 @@ definitions: host: type: string type: object - mcis.RestPostCmdMcisResponse: - properties: - mcisId: - type: string - result: - type: string - vmId: - type: string - vmIp: - type: string - type: object mcis.RestPostCmdMcisResponseWrapper: properties: - resultArray: + results: items: - $ref: '#/definitions/mcis.RestPostCmdMcisResponse' + $ref: '#/definitions/mcis.SshCmdResult' type: array type: object - mcis.SpiderImageType: - enum: - - PublicImage - - MyImage - type: string - x-enum-varnames: - - PublicImage - - MyImage mcis.SpiderVMInfo: properties: cspid: @@ -1586,15 +1544,14 @@ definitions: type: string type: array iid: - allOf: - - $ref: '#/definitions/common.IID' + $ref: '#/definitions/common.IID' description: Fields for response imageIId: $ref: '#/definitions/common.IID' imageName: type: string imageType: - $ref: '#/definitions/mcis.SpiderImageType' + type: string keyPairIId: $ref: '#/definitions/common.IID' keyPairName: @@ -1618,8 +1575,7 @@ definitions: publicIP: type: string region: - allOf: - - $ref: '#/definitions/mcis.RegionInfo' + $ref: '#/definitions/mcis.RegionInfo' description: ex) {us-east1, us-east1-c} or {ap-northeast-2} rootDeviceName: description: '"/dev/sda1", ...' @@ -1644,8 +1600,7 @@ definitions: startTime: type: string subnetIID: - allOf: - - $ref: '#/definitions/common.IID' + $ref: '#/definitions/common.IID' description: AWS, ex) subnet-8c4a53e4 subnetName: type: string @@ -1662,6 +1617,24 @@ definitions: vpcname: type: string type: object + mcis.SshCmdResult: + properties: + err: {} + mcisId: + type: string + stderr: + additionalProperties: + type: string + type: object + stdout: + additionalProperties: + type: string + type: object + vmId: + type: string + vmIp: + type: string + type: object mcis.StatusCountInfo: properties: countCreating: @@ -1970,12 +1943,10 @@ definitions: description: type: string healthChecker: - allOf: - - $ref: '#/definitions/mcis.TbNLBHealthCheckerReq' + $ref: '#/definitions/mcis.TbNLBHealthCheckerReq' description: HealthChecker listener: - allOf: - - $ref: '#/definitions/mcis.NLBListenerReq' + $ref: '#/definitions/mcis.NLBListenerReq' description: Frontend scope: description: REGION(V) | GLOBAL @@ -1985,8 +1956,7 @@ definitions: example: REGION type: string targetGroup: - allOf: - - $ref: '#/definitions/mcis.TbNLBTargetGroupReq' + $ref: '#/definitions/mcis.TbNLBTargetGroupReq' description: Backend type: description: PUBLIC(V) | INTERNAL @@ -2143,8 +2113,7 @@ definitions: publicIP: type: string region: - allOf: - - $ref: '#/definitions/mcis.RegionInfo' + $ref: '#/definitions/mcis.RegionInfo' description: AWS, ex) {us-east1, us-east1-c} or {ap-northeast-2} rootDeviceName: type: string diff --git a/src/api/rest/server/mcis/benchmark.go b/src/api/rest/server/mcis/benchmark.go index 3fdbf726a..f8f1adc3f 100644 --- a/src/api/rest/server/mcis/benchmark.go +++ b/src/api/rest/server/mcis/benchmark.go @@ -53,16 +53,11 @@ func RestPostInstallBenchmarkAgentToMcis(c echo.Context) error { return c.JSON(http.StatusInternalServerError, &mapA) } - content := RestPostCmdMcisResponseWrapper{} + content := SshCmdResultWrapper{} for _, v := range resultArray { - resultTmp := RestPostCmdMcisResponse{} - resultTmp.McisId = mcisId - resultTmp.VmId = v.VmId - resultTmp.VmIp = v.VmIp - resultTmp.Result = v.Result - content.ResultArray = append(content.ResultArray, resultTmp) + content.Results = append(content.Results, v) } diff --git a/src/api/rest/server/mcis/remoteCommand.go b/src/api/rest/server/mcis/remoteCommand.go index 1d744ac32..8245f37f1 100644 --- a/src/api/rest/server/mcis/remoteCommand.go +++ b/src/api/rest/server/mcis/remoteCommand.go @@ -26,15 +26,8 @@ type RestPostCmdMcisVmResponse struct { Result string `json:"result"` } -type RestPostCmdMcisResponse struct { - McisId string `json:"mcisId"` - VmId string `json:"vmId"` - VmIp string `json:"vmIp"` - Result string `json:"result"` -} - -type RestPostCmdMcisResponseWrapper struct { - ResultArray []RestPostCmdMcisResponse `json:"resultArray"` +type SshCmdResultWrapper struct { + Results []mcis.SshCmdResult `json:"results"` } // RestPostCmdMcis godoc @@ -48,7 +41,7 @@ type RestPostCmdMcisResponseWrapper struct { // @Param mcisCmdReq body mcis.McisCmdReq true "MCIS Command Request" // @Param subGroupId query string false "subGroupId to apply the command only for VMs in subGroup of MCIS" default() // @Param vmId query string false "vmId to apply the command only for a VM in MCIS" default() -// @Success 200 {object} RestPostCmdMcisResponseWrapper +// @Success 200 {object} SshCmdResultWrapper // @Failure 404 {object} common.SimpleMsg // @Failure 500 {object} common.SimpleMsg // @Router /ns/{nsId}/cmd/mcis/{mcisId} [post] @@ -70,16 +63,10 @@ func RestPostCmdMcis(c echo.Context) error { return c.JSON(http.StatusInternalServerError, &mapA) } - content := RestPostCmdMcisResponseWrapper{} + content := SshCmdResultWrapper{} for _, v := range resultArray { - - resultTmp := RestPostCmdMcisResponse{} - resultTmp.McisId = mcisId - resultTmp.VmId = v.VmId - resultTmp.VmIp = v.VmIp - resultTmp.Result = v.Result - content.ResultArray = append(content.ResultArray, resultTmp) + content.Results = append(content.Results, v) } common.PrintJsonPretty(content) diff --git a/src/core/mcis/benchmark.go b/src/core/mcis/benchmark.go index 17de7d054..06841a09b 100644 --- a/src/core/mcis/benchmark.go +++ b/src/core/mcis/benchmark.go @@ -106,7 +106,7 @@ func InstallBenchmarkAgentToMcis(nsId string, mcisId string, req *McisCmdReq, op } // Replace given parameter with the installation cmd - req.Command = cmd + req.Command = append(req.Command, cmd) sshCmdResult, err := RemoteCommandToMcis(nsId, mcisId, "", "", req) diff --git a/src/core/mcis/monitoring.go b/src/core/mcis/monitoring.go index 798e00d5c..9c9d7d1db 100644 --- a/src/core/mcis/monitoring.go +++ b/src/core/mcis/monitoring.go @@ -260,13 +260,13 @@ func CallMonitoringAsync(wg *sync.WaitGroup, nsID string, mcisID string, mcisSer if err != nil || errStr != "" { common.CBLog.Error("[Monitoring Agent deployment errors] " + errStr) - sshResultTmp.Result = errStr + sshResultTmp.Stderr[0] = errStr sshResultTmp.Err = err *returnResult = append(*returnResult, sshResultTmp) vmInfoTmp.MonAgentStatus = "failed" } else { fmt.Println("Result: " + result) - sshResultTmp.Result = result + sshResultTmp.Stdout[0] = result sshResultTmp.Err = nil *returnResult = append(*returnResult, sshResultTmp) vmInfoTmp.MonAgentStatus = "installed" @@ -344,7 +344,7 @@ func InstallMonitorAgentToMcis(nsId string, mcisId string, mcisServiceType strin resultTmp.McisId = mcisId resultTmp.VmId = v.VmId resultTmp.VmIp = v.VmIp - resultTmp.Result = v.Result + resultTmp.Result = v.Stdout[0] content.ResultArray = append(content.ResultArray, resultTmp) } diff --git a/src/core/mcis/network.go b/src/core/mcis/network.go index ff27bd136..879e1ef51 100644 --- a/src/core/mcis/network.go +++ b/src/core/mcis/network.go @@ -127,7 +127,7 @@ func ConfigureCloudAdaptiveNetwork(nsId string, mcisId string, netReq *NetworkRe // Replace given parameter with the installation cmd mcisCmdReq := McisCmdReq{} mcisCmdReq.UserName = "cb-user" // this MCIS user name is temporal code. Need to improve. - mcisCmdReq.Command = command + mcisCmdReq.Command = append(mcisCmdReq.Command, command) //// Install the cb-network agent to MCIS // sshCmdResults, err := installCBNetworkAgentToMcis(nsId, mcisId, mcisCmdReq) @@ -182,7 +182,7 @@ func ConfigureCloudAdaptiveNetwork(nsId string, mcisId string, netReq *NetworkRe tempContent.McisId = mcisId tempContent.VmId = result.VmId tempContent.VmIp = result.VmIp - tempContent.Result = result.Result + tempContent.Result = result.Stdout[0] contents.ResultArray = append(contents.ResultArray, tempContent) } @@ -394,27 +394,22 @@ func installCBNetworkAgentToVM(nsId, mcisId, vmId string, mcisCmdReq McisCmdReq) // Just logging the error (but it is net a faultal ) common.CBLog.Info(err) } - fmt.Println("") - fmt.Println("[SSH] " + mcisId + "." + vmId + "(" + vmIp + ")" + " with userName: " + userName) - fmt.Println("[CMD] " + mcisCmdReq.Command) - fmt.Println("") - result, err := RunRemoteCommand(vmIp, sshPort, userName, sshKey, mcisCmdReq.Command) + stdout, stderr, err := RunRemoteCommand(vmIp, sshPort, userName, sshKey, mcisCmdReq.Command) sshResultTmp := SshCmdResult{} sshResultTmp.McisId = "" sshResultTmp.VmId = vmId sshResultTmp.VmIp = vmIp + sshResultTmp.Stdout = stdout + sshResultTmp.Stderr = stderr if err != nil { - sshResultTmp.Result = ("[ERROR: " + err.Error() + "]\n " + *result) sshResultTmp.Err = err } else { fmt.Println("[Begin] SSH Output") - fmt.Println(*result) + fmt.Println(sshResultTmp.Stdout) fmt.Println("[end] SSH Output") - - sshResultTmp.Result = *result sshResultTmp.Err = nil } diff --git a/src/core/mcis/nlb.go b/src/core/mcis/nlb.go index 3cd123fbc..78b5b0929 100644 --- a/src/core/mcis/nlb.go +++ b/src/core/mcis/nlb.go @@ -343,13 +343,16 @@ func CreateMcSwNlb(nsId string, mcisId string, req *TbNLBReq, option string) (Tb // Deploy SW NLB cmd := common.RuntimeConf.Nlbsw.CommandNlbPrepare - _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmd}) + var cmds []string + cmds = append(cmds, cmd) + + _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmds}) if err != nil { common.CBLog.Error(err) return emptyObj, err } cmd = common.RuntimeConf.Nlbsw.CommandNlbDeploy + " " + mcisId + " " + common.ToLower(req.Listener.Protocol) + " " + req.Listener.Port - _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmd}) + _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmds}) if err != nil { common.CBLog.Error(err) return emptyObj, err @@ -367,7 +370,7 @@ func CreateMcSwNlb(nsId string, mcisId string, req *TbNLBReq, option string) (Tb for _, k := range v.McisVmAccessInfo { cmd = common.RuntimeConf.Nlbsw.CommandNlbAddTargetNode + " " + k.VmId + " " + k.PublicIP + " " + req.TargetGroup.Port - _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmd}) + _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmds}) if err != nil { common.CBLog.Error(err) return emptyObj, err @@ -377,7 +380,7 @@ func CreateMcSwNlb(nsId string, mcisId string, req *TbNLBReq, option string) (Tb } cmd = common.RuntimeConf.Nlbsw.CommandNlbApplyConfig - _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmd}) + _, err = RemoteCommandToMcis(nsId, nlbMcisId, "", "", &McisCmdReq{Command: cmds}) if err != nil { common.CBLog.Error(err) return emptyObj, err diff --git a/src/core/mcis/orchestration.go b/src/core/mcis/orchestration.go index 142173c95..423a61d16 100644 --- a/src/core/mcis/orchestration.go +++ b/src/core/mcis/orchestration.go @@ -348,9 +348,9 @@ func OrchestrationController() { } common.PrintJsonPretty(result) - nullMcisCmdReq := McisCmdReq{} - if autoAction.PostCommand != nullMcisCmdReq { - fmt.Println("[Post Command to VM] " + autoAction.PostCommand.Command) + if len(autoAction.PostCommand.Command) != 0 { + fmt.Print("[Post Command to VM] ") + fmt.Println(autoAction.PostCommand.Command) _, cmdErr := RemoteCommandToMcis(nsId, mcisPolicyTmp.Id, common.ToLower(autoAction.VmDynamicReq.Name), "", &autoAction.PostCommand) if cmdErr != nil { mcisPolicyTmp.Policy[policyIndex].Status = AutoStatusError diff --git a/src/core/mcis/remoteCommand.go b/src/core/mcis/remoteCommand.go index 993a8f27d..e10c89bdc 100644 --- a/src/core/mcis/remoteCommand.go +++ b/src/core/mcis/remoteCommand.go @@ -33,8 +33,8 @@ var sshDefaultUserName = []string{"cb-user", "ubuntu", "root", "ec2-user"} // McisCmdReq is struct for remote command type McisCmdReq struct { - UserName string `json:"userName" example:"cb-user" default:""` - Command string `json:"command" validate:"required" example:"client_ip=$(echo $SSH_CLIENT | awk '{print $1}'); echo SSH client IP is: $client_ip"` + UserName string `json:"userName" example:"cb-user" default:""` + Command []string `json:"command" validate:"required" example:"client_ip=$(echo $SSH_CLIENT | awk '{print $1}'); echo SSH client IP is: $client_ip"` } // TbMcisCmdReqStructLevelValidation is func to validate fields in McisCmdReq @@ -51,11 +51,12 @@ func TbMcisCmdReqStructLevelValidation(sl validator.StructLevel) { // SshCmdResult is struct for SshCmd Result type SshCmdResult struct { // Tumblebug - McisId string `json:"mcisId"` - VmId string `json:"vmId"` - VmIp string `json:"vmIp"` - Result string `json:"result"` - Err error `json:"err"` + McisId string `json:"mcisId"` + VmId string `json:"vmId"` + VmIp string `json:"vmIp"` + Stdout map[int]string `json:"stdout"` + Stderr map[int]string `json:"stderr"` + Err error `json:"err"` } // RemoteCommandToMcis is func to command to all VMs in MCIS by SSH @@ -163,9 +164,8 @@ func RemoteCommandToMcis(nsId string, mcisId string, subGroupId string, vmId str } // RunRemoteCommand is func to execute a SSH command to a VM (sync call) -func RunRemoteCommand(nsId string, mcisId string, vmId string, givenUserName string, cmd string) (*string, error) { +func RunRemoteCommand(nsId string, mcisId string, vmId string, givenUserName string, cmds []string) (map[int]string, map[int]string, error) { - var result string // use privagte IP of the target VM _, targetVmIP, targetSshPort := GetVmIp(nsId, mcisId, vmId) targetUserName, targetPrivateKey, err := VerifySshUserName(nsId, mcisId, vmId, targetVmIP, targetSshPort, givenUserName) @@ -174,7 +174,7 @@ func RunRemoteCommand(nsId string, mcisId string, vmId string, givenUserName str bastionNodes, err := GetBastionNodes(nsId, mcisId, vmId) if err != nil { common.CBLog.Error(err) - return &result, err + return map[int]string{}, map[int]string{}, err } bastionNode := bastionNodes.VmId[0] // use public IP of the bastion VM @@ -189,7 +189,9 @@ func RunRemoteCommand(nsId string, mcisId string, vmId string, givenUserName str } fmt.Println("[SSH] " + mcisId + "." + vmId + "(" + targetVmIP + ")" + " with userName: " + targetUserName) - fmt.Println("[CMD] " + cmd) + for i, v := range cmds { + fmt.Println("[SSH] cmd[" + fmt.Sprint(i) + "]: " + v) + } // Set VM SSH config (targetEndpoint, userName, Private Key) targetEndpoint := fmt.Sprintf("%s:%s", targetVmIP, targetSshPort) @@ -200,22 +202,23 @@ func RunRemoteCommand(nsId string, mcisId string, vmId string, givenUserName str } // Execute SSH - result, err = runSSH(bastionSshInfo, targetSshInfo, cmd) + stdoutResults, stderrResults, err := runSSH(bastionSshInfo, targetSshInfo, cmds) if err != nil { - return &result, err + fmt.Printf("Error executing commands: %s\n", err) + return stdoutResults, stderrResults, err } - return &result, nil + return stdoutResults, stderrResults, nil } // RunRemoteCommandAsync is func to execute a SSH command to a VM (async call) -func RunRemoteCommandAsync(wg *sync.WaitGroup, nsId string, mcisId string, vmId string, givenUserName string, cmd string, returnResult *[]SshCmdResult) { +func RunRemoteCommandAsync(wg *sync.WaitGroup, nsId string, mcisId string, vmId string, givenUserName string, cmd []string, returnResult *[]SshCmdResult) { - defer wg.Done() //goroutin sync done + defer wg.Done() //goroutine sync done vmIP, _, _ := GetVmIp(nsId, mcisId, vmId) // RunRemoteCommand - result, err := RunRemoteCommand(nsId, mcisId, vmId, givenUserName, cmd) + stdoutResults, stderrResults, err := RunRemoteCommand(nsId, mcisId, vmId, givenUserName, cmd) sshResultTmp := SshCmdResult{} sshResultTmp.McisId = mcisId @@ -223,19 +226,20 @@ func RunRemoteCommandAsync(wg *sync.WaitGroup, nsId string, mcisId string, vmId sshResultTmp.VmIp = vmIP if err != nil { - sshResultTmp.Result = ("[ERROR: " + err.Error() + "]\n " + *result) + sshResultTmp.Stdout = stdoutResults + sshResultTmp.Stderr = stderrResults sshResultTmp.Err = err *returnResult = append(*returnResult, sshResultTmp) } else { fmt.Println("[Begin] SSH Output") - fmt.Println(*result) - fmt.Println("[end] SSH Output") + fmt.Println(stdoutResults) + fmt.Println("[End] SSH Output") - sshResultTmp.Result = *result + sshResultTmp.Stdout = stdoutResults + sshResultTmp.Stderr = stderrResults sshResultTmp.Err = nil *returnResult = append(*returnResult, sshResultTmp) } - } // VerifySshUserName is func to verify SSH username @@ -423,11 +427,15 @@ type sshInfo struct { } // runSSH func execute a command by SSH -func runSSH(bastionInfo sshInfo, targetInfo sshInfo, cmd string) (string, error) { +func runSSH(bastionInfo sshInfo, targetInfo sshInfo, cmds []string) (map[int]string, map[int]string, error) { + + stdoutMap := make(map[int]string) + stderrMap := make(map[int]string) + // Parse the private key for the bastion host bastionSigner, err := ssh.ParsePrivateKey(bastionInfo.PrivateKey) if err != nil { - return "", err + return stdoutMap, stderrMap, err } // Create an SSH client configuration for the bastion host @@ -442,7 +450,7 @@ func runSSH(bastionInfo sshInfo, targetInfo sshInfo, cmd string) (string, error) // Parse the private key for the target host targetSigner, err := ssh.ParsePrivateKey(targetInfo.PrivateKey) if err != nil { - return "", err + return stdoutMap, stderrMap, err } // Create an SSH client configuration for the target host @@ -457,19 +465,19 @@ func runSSH(bastionInfo sshInfo, targetInfo sshInfo, cmd string) (string, error) // Setup the bastion host connection bastionClient, err := ssh.Dial("tcp", bastionInfo.EndPoint, bastionConfig) if err != nil { - return "", err + return stdoutMap, stderrMap, err } defer bastionClient.Close() // Setup the actual SSH client through the bastion host conn, err := bastionClient.Dial("tcp", targetInfo.EndPoint) if err != nil { - return "", err + return stdoutMap, stderrMap, err } ncc, chans, reqs, err := ssh.NewClientConn(conn, targetInfo.EndPoint, targetConfig) if err != nil { - return "", err + return stdoutMap, stderrMap, err } client := ssh.NewClient(ncc, chans, reqs) defer client.Close() @@ -477,23 +485,36 @@ func runSSH(bastionInfo sshInfo, targetInfo sshInfo, cmd string) (string, error) // Create a new SSH session session, err := client.NewSession() if err != nil { - return "", err + return stdoutMap, stderrMap, err } defer session.Close() - // Capture the output - var stdoutBuf, stderrBuf bytes.Buffer - session.Stdout = &stdoutBuf - session.Stderr = &stderrBuf + // Run the commands + for i, cmd := range cmds { + // Create a new SSH session for each command + session, err := client.NewSession() + if err != nil { + return stdoutMap, stderrMap, err + } + defer session.Close() - // Run the command - err = session.Run(cmd) - if err != nil { - return stdoutBuf.String(), fmt.Errorf("(%s)\nStderr: %s", err, stderrBuf.String()) + // Capture the output + var stdoutBuf, stderrBuf bytes.Buffer + session.Stdout = &stdoutBuf + session.Stderr = &stderrBuf + + // Run the command + err = session.Run(cmd) + if err != nil { + stderrMap[i] = fmt.Sprintf("(%s)\nStderr: %s", err, stderrBuf.String()) + break // Stop if the command fails + } + + stdoutMap[i] = stdoutBuf.String() + stderrMap[i] = stderrBuf.String() } - // Return the output - return stdoutBuf.String(), nil + return stdoutMap, stderrMap, nil } // BastionInfo is struct for bastion info