Merge pull request #21 from Akilan1999/pass-through-docker-cotainer
Allow client to choose docker container to run on the server side
This commit is contained in:
@@ -19,9 +19,9 @@ 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, ContainerName string) (*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) + "&ContainerName=" + ContainerName
|
||||
resp, err := http.Get(URL)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
@@ -65,6 +65,33 @@ func RemoveContianer(IP string,ID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ViewContainers This function displays all containers available on server side
|
||||
func ViewContainers(IP string)(*docker.DockerContainers, error){
|
||||
// Passes URL with route /ShowImages
|
||||
URL := "http://" + IP + ":" + serverPort + "/ShowImages"
|
||||
resp, err := http.Get(URL)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
|
||||
// Convert response to byte value
|
||||
byteValue, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
|
||||
// Create variable for result response type
|
||||
var Result docker.DockerContainers
|
||||
|
||||
// Adds byte value to docker.DockerContainers struct
|
||||
json.Unmarshal(byteValue, &Result)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
|
||||
return &Result, nil
|
||||
}
|
||||
|
||||
// PrintStartContainer Prints results Generated container
|
||||
func PrintStartContainer(d *docker.DockerVM){
|
||||
fmt.Println("ID : " + fmt.Sprint(d.ID))
|
||||
|
||||
@@ -31,6 +31,7 @@ var CliAction = func(ctx *cli.Context) error {
|
||||
p2p.PrintIpTable()
|
||||
}
|
||||
|
||||
// Add provided IP to the IP table
|
||||
if AddServer != "" {
|
||||
res, err := p2p.ReadIpTable()
|
||||
if err != nil {
|
||||
@@ -52,6 +53,16 @@ var CliAction = func(ctx *cli.Context) error {
|
||||
|
||||
}
|
||||
|
||||
// Displays all images available on the server side
|
||||
if ViewImages != "" {
|
||||
imageRes, err := client.ViewContainers(ViewImages)
|
||||
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
}
|
||||
client.PrettyPrint(imageRes)
|
||||
}
|
||||
|
||||
// Function called to stop and remove server from Docker
|
||||
if RemoveVM != "" && ID != "" {
|
||||
err := client.RemoveContianer(RemoveVM,ID)
|
||||
@@ -70,7 +81,8 @@ var CliAction = func(ctx *cli.Context) error {
|
||||
fmt.Sscanf(Ports, "%d", &PortsInt)
|
||||
}
|
||||
|
||||
imageRes, err := client.StartContainer(CreateVM,PortsInt,GPU)
|
||||
// Calls function to do Api call to start the container on the server side
|
||||
imageRes, err := client.StartContainer(CreateVM,PortsInt,GPU,ContainerName)
|
||||
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
|
||||
15
cmd/flags.go
15
cmd/flags.go
@@ -7,7 +7,9 @@ import (
|
||||
// Variables declared for CLI
|
||||
var (
|
||||
AddServer string
|
||||
ViewImages string
|
||||
CreateVM string
|
||||
ContainerName string
|
||||
Ports string
|
||||
Mode string
|
||||
RemoveVM string
|
||||
@@ -46,12 +48,24 @@ var AppConfigFlags = []cli.Flag{
|
||||
EnvVars: []string{"ADD_SERVER"},
|
||||
Destination: &AddServer,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ViewImages",
|
||||
Usage: "View images available on the server IP address",
|
||||
EnvVars: []string{"VIEW_IMAGES"},
|
||||
Destination: &ViewImages,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "CreateVM",
|
||||
Usage: "Creates Docker container on the selected server",
|
||||
EnvVars: []string{"CREATE_VM"},
|
||||
Destination: &CreateVM,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ContainerName",
|
||||
Usage: "Specifying the container run on the server side",
|
||||
EnvVars: []string{"CONTAINER_NAME"},
|
||||
Destination: &ContainerName,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "RemoveVM",
|
||||
Usage: "Stop and Remove Docker container",
|
||||
@@ -82,6 +96,7 @@ var AppConfigFlags = []cli.Flag{
|
||||
EnvVars: []string{"SPECS"},
|
||||
Destination: &Specs,
|
||||
},
|
||||
|
||||
&cli.BoolFlag{
|
||||
Name: "SetDefaultConfig",
|
||||
Usage: "Sets a default configuration file",
|
||||
|
||||
@@ -9,7 +9,8 @@ var (
|
||||
defaultPath string
|
||||
defaults = map[string]interface{}{
|
||||
"IPTable": "/etc/p2p-rendering/ip_table.json",
|
||||
"DockerFile": "/home/akilan/Documents/p2prendering/p2p-redering-computation/server/docker/containers/docker-ubuntu-sshd/",
|
||||
"DockerContainers": "/home/akilan/Documents/p2prendering/p2p-redering-computation/server/docker/containers/",
|
||||
"DefaultDockerFile": "/home/akilan/Documents/p2prendering/p2p-redering-computation/server/docker/containers/docker-ubuntu-sshd/",
|
||||
"SpeedTestFile":"/etc/p2p-rendering/50.bin",
|
||||
}
|
||||
configName = "config"
|
||||
@@ -19,9 +20,10 @@ var (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
IPTable string
|
||||
DockerFile string
|
||||
SpeedTestFile string
|
||||
IPTable string
|
||||
DockerContainers string
|
||||
DefaultDockerFile string
|
||||
SpeedTestFile string
|
||||
}
|
||||
|
||||
// Exists reports whether the named file or directory exists.
|
||||
@@ -45,7 +47,8 @@ func SetDefaults() error {
|
||||
|
||||
//Setting default paths for the config file
|
||||
defaults["IPTable"] = defaultPath + "p2p/ip_table.json"
|
||||
defaults["DockerFile"] = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
|
||||
defaults["DefaultDockerFile"] = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
|
||||
defaults["DockerContainers"] = defaultPath + "server/docker/containers/"
|
||||
defaults["SpeedTestFile"] = defaultPath + "p2p/50.bin"
|
||||
|
||||
//Paths to search for config file
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Simple Ubuntu 20.04 image
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/lithammer/shortuuid"
|
||||
"github.com/phayes/freeport"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
@@ -33,6 +34,15 @@ type DockerVM struct {
|
||||
GPU string `json:"GPU"`
|
||||
}
|
||||
|
||||
type DockerContainers struct {
|
||||
DockerContainer []DockerContainer `json:"DockerContainer"`
|
||||
}
|
||||
|
||||
type DockerContainer struct {
|
||||
ContainerName string `json:"DockerContainerName"`
|
||||
ContainerDescription string `json:"ContainerDescription"`
|
||||
}
|
||||
|
||||
type ErrorLine struct {
|
||||
Error string `json:"error"`
|
||||
ErrorDetail ErrorDetail `json:"errorDetail"`
|
||||
@@ -44,7 +54,7 @@ type ErrorDetail struct {
|
||||
|
||||
var dockerRegistryUserID = ""
|
||||
|
||||
func BuildRunContainer(NumPorts int, GPU string) (*DockerVM,error) {
|
||||
func BuildRunContainer(NumPorts int, GPU string, ContainerName string) (*DockerVM,error) {
|
||||
//Docker Struct Variable
|
||||
var RespDocker *DockerVM = new(DockerVM)
|
||||
|
||||
@@ -81,7 +91,23 @@ func BuildRunContainer(NumPorts int, GPU string) (*DockerVM,error) {
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
RespDocker.ImagePath = config.DockerFile
|
||||
RespDocker.ImagePath = config.DefaultDockerFile
|
||||
|
||||
if ContainerName != "" {
|
||||
Containers, err := ViewAllContainers()
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
for _, dockerContainer := range Containers.DockerContainer {
|
||||
if dockerContainer.ContainerName == ContainerName {
|
||||
RespDocker.ImagePath = config.DockerContainers + ContainerName + "/"
|
||||
break
|
||||
}
|
||||
}
|
||||
if RespDocker.ImagePath == config.DefaultDockerFile {
|
||||
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
|
||||
}
|
||||
}
|
||||
|
||||
// Gets docker information from env variables
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
@@ -238,7 +264,7 @@ func (d *DockerVM)runContainer(dockerClient *client.Client) error{
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopAndRemoveContainer TODO: Implement and remove docker instance running
|
||||
// StopAndRemoveContainer
|
||||
// Stop and remove a container
|
||||
// Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6)
|
||||
func StopAndRemoveContainer(containername string) error {
|
||||
@@ -266,6 +292,47 @@ func StopAndRemoveContainer(containername string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ViewAllContainers returns all containers runnable and which can be built
|
||||
func ViewAllContainers() (*DockerContainers, error){
|
||||
// Traverse the folder path as per given in the config file
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
|
||||
folders, err := ioutil.ReadDir(config.DockerContainers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Declare variable DockerContainers of type struct
|
||||
var Containers *DockerContainers = new(DockerContainers)
|
||||
|
||||
for _, f := range folders {
|
||||
if f.IsDir() {
|
||||
fmt.Print(f.Name())
|
||||
//Declare variable DockerContainer of type struct
|
||||
var Container DockerContainer
|
||||
|
||||
// Setting container name to folder name
|
||||
Container.ContainerName = f.Name()
|
||||
// Getting Description from file description.txt
|
||||
Description, err := ioutil.ReadFile(config.DockerContainers + "/" + Container.ContainerName + "/description.txt")
|
||||
// if we os.Open returns an error then handle it
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get Description from description.txt
|
||||
Container.ContainerDescription = string(Description)
|
||||
|
||||
Containers.DockerContainer = append(Containers.DockerContainer, Container)
|
||||
}
|
||||
}
|
||||
|
||||
return Containers,nil
|
||||
}
|
||||
|
||||
func print(rd io.Reader) error {
|
||||
var lastLine string
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
func TestDocker(t *testing.T) {
|
||||
//TODO overwrite with custom docker paths
|
||||
resp,err := BuildRunContainer(2,"true")
|
||||
resp,err := BuildRunContainer(2,"true","")
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -15,3 +15,12 @@ func TestDocker(t *testing.T) {
|
||||
|
||||
fmt.Print(resp.VNCPort)
|
||||
}
|
||||
|
||||
func TestViewAllContainers(t *testing.T) {
|
||||
_,err := ViewAllContainers()
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ type Docker struct {
|
||||
|
||||
// Starts container using RPC calls
|
||||
func (l *Listener) StartContainer( reply *Docker) error {
|
||||
fmt.Print("here")
|
||||
vm, err := docker.BuildRunContainer(3,"false")
|
||||
vm, err := docker.BuildRunContainer(3,"false","")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -97,14 +97,15 @@ func Server() error{
|
||||
// Get Number of ports to open and whether to use GPU or not
|
||||
Ports := c.DefaultQuery("ports","0")
|
||||
GPU := c.DefaultQuery("GPU","false")
|
||||
ContainerName := c.DefaultQuery("ContainerName","")
|
||||
var PortsInt int
|
||||
|
||||
// Convert Get Request value to int
|
||||
fmt.Sscanf(Ports, "%d", &PortsInt)
|
||||
|
||||
// Creates container and returns back result to
|
||||
// Creates container and returns-back result to
|
||||
// access container
|
||||
resp, err := docker.BuildRunContainer(PortsInt,GPU)
|
||||
resp, err := docker.BuildRunContainer(PortsInt,GPU,ContainerName)
|
||||
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
@@ -122,6 +123,15 @@ func Server() error{
|
||||
c.String(http.StatusOK, "success")
|
||||
})
|
||||
|
||||
//Show images avaliable
|
||||
r.GET("/ShowImages", func(c *gin.Context) {
|
||||
resp, err := docker.ViewAllContainers()
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
}
|
||||
c.JSON(http.StatusOK, resp)
|
||||
})
|
||||
|
||||
// Future feature
|
||||
/*r.GET("/create_vm/:virtualization", func(c *gin.Context) {
|
||||
virtualization := c.Param("virtualization")
|
||||
|
||||
Reference in New Issue
Block a user