diff --git a/client/ServerSpecs.go b/client/ServerSpecs.go index e732b61..7b3b8c1 100644 --- a/client/ServerSpecs.go +++ b/client/ServerSpecs.go @@ -8,6 +8,9 @@ import ( "net/http" ) +// GetSpecs Gets Specs from the server such CPU, GPU usage +// and other basic information which helps set a +// cluster of computer func GetSpecs(IP string)(*server.SysInfo,error) { URL := "http://" + IP + ":" + serverPort + "/server_info" resp, err := http.Get(URL) @@ -33,7 +36,8 @@ func GetSpecs(IP string)(*server.SysInfo,error) { return &serverSpecsResult, nil } -// print the contents of the obj +// PrettyPrint print the contents of the obj ( +// Reference: https://stackoverflow.com/questions/24512112/how-to-print-struct-variables-in-console func PrettyPrint(data interface{}) { var p []byte // var err := error diff --git a/client/container.go b/client/container.go index 2c7bbe5..f37d945 100644 --- a/client/container.go +++ b/client/container.go @@ -19,10 +19,13 @@ var client = http.Client{} // StartContainer Start container using REST api Implementation // From the selected server IP address // TODO: Test cases for this function -func StartContainer(Ip string, NumPorts int, GPU bool) (*docker.DockerVM ,error) { +func StartContainer(IP string, NumPorts int, GPU bool) (*docker.DockerVM ,error) { // Passes URL with number of TCP ports to allocated and to give GPU access to the docker container - URL := "http://" + Ip + ":" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + URL := "http://" + IP + ":" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) resp, err := http.Get(URL) + if err != nil { + return nil,err + } // Convert response to byte value byteValue, err := ioutil.ReadAll(resp.Body) @@ -42,6 +45,26 @@ func StartContainer(Ip string, NumPorts int, GPU bool) (*docker.DockerVM ,error) return &dockerResult, nil } +// RemoveContianer Stops and removes container from the server +func RemoveContianer(IP string,ID string) error { + URL := "http://" + IP + ":" + serverPort + "/RemoveContainer?id=" + ID + resp, err := http.Get(URL) + if err != nil { + return err + } + + // Convert response to byte value + byteValue, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + if string(byteValue[:]) == "success" { + fmt.Println("success") + } + return nil +} + // PrintStartContainer Prints results Generated container func PrintStartContainer(d *docker.DockerVM){ fmt.Println("ID : " + fmt.Sprint(d.ID)) diff --git a/cmd/action.go b/cmd/action.go index ffafda7..de03e0e 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -26,8 +26,16 @@ var CliAction = func(ctx *cli.Context) error { p2p.PrintIpTable() } + // Function called to stop and remove server from Docker + if RemoveVM != "" && ID != "" { + err := client.RemoveContianer(RemoveVM,ID) + if err != nil { + fmt.Print(err) + } + } + //Call function to create Docker container - if IpAddress != "" { + if CreateVM != "" { var PortsInt int PortsInt = 0 @@ -37,7 +45,7 @@ var CliAction = func(ctx *cli.Context) error { fmt.Sscanf(Ports, "%d", &PortsInt) } - imageRes, err := client.StartContainer(IpAddress,PortsInt,GPU) + imageRes, err := client.StartContainer(CreateVM,PortsInt,GPU) if err != nil { fmt.Print(err) diff --git a/cmd/flags.go b/cmd/flags.go index 02d5745..b8abb56 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -6,10 +6,12 @@ import ( // Variables declared for CLI var ( - IpAddress string - Ports string - Mode string - Specs string + CreateVM string + Ports string + Mode string + RemoveVM string + ID string + Specs string GPU bool ListServers bool ) @@ -33,13 +35,25 @@ var AppConfigFlags = []cli.Flag{ Name: "CreateVM", Usage: "Creates Docker container on the selected server", EnvVars: []string{"CREATE_VM"}, - Destination: &IpAddress, + Destination: &CreateVM, + }, + &cli.StringFlag{ + Name: "RemoveVM", + Usage: "Stop and Remove Docker container", + EnvVars: []string{"REMOVE_VM"}, + Destination: &RemoveVM, + }, + &cli.StringFlag{ + Name: "ID", + Usage: "Docker Container ID", + EnvVars: []string{"ID"}, + Destination: &ID, }, &cli.StringFlag{ Name: "Ports", Usage: "Number of ports to open for the Docker Container", EnvVars: []string{"NUM_PORTS"}, - Destination: &Ports, + Destination: &ID, }, &cli.BoolFlag{ Name: "GPU", diff --git a/server/docker/docker.go b/server/docker/docker.go index 136a0f0..239ae7e 100644 --- a/server/docker/docker.go +++ b/server/docker/docker.go @@ -231,8 +231,33 @@ func (d *DockerVM)runContainer(dockerClient *client.Client) error{ return nil } -// TODO: Implement and remove docker instance running +// StopAndRemoveContainer TODO: Implement and remove docker instance running +// Stop and remove a container +// Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6) +func StopAndRemoveContainer(containername string) error { + ctx := context.Background() + // Gets docker information from env variables + client, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return err + } + + if err = client.ContainerStop(ctx, containername, nil); err != nil { + return err + } + + removeOptions := types.ContainerRemoveOptions{ + RemoveVolumes: true, + Force: true, + } + + if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil { + return err + } + + return nil +} func print(rd io.Reader) error { var lastLine string diff --git a/server/server.go b/server/server.go index 4b25969..6ce8cfa 100644 --- a/server/server.go +++ b/server/server.go @@ -94,13 +94,21 @@ func Server() error{ resp, err := docker.BuildRunContainer(PortsInt,GPU) if err != nil { - c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) } c.JSON(http.StatusOK, resp) }) + //Remove container + r.GET("/RemoveContainer", func(c *gin.Context) { + ID := c.DefaultQuery("id","0") + if err := docker.StopAndRemoveContainer(ID); err != nil { + c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) + } + c.String(http.StatusOK, "success") + }) + // Future feature /*r.GET("/create_vm/:virtualization", func(c *gin.Context) { virtualization := c.Param("virtualization")