config abstraction changes added
This commit is contained in:
@@ -1,64 +1,64 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/lithammer/shortuuid"
|
||||
"github.com/phayes/freeport"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"time"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/lithammer/shortuuid"
|
||||
"github.com/phayes/freeport"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DockerVM struct {
|
||||
SSHUsername string `json:"SSHUsername"`
|
||||
SSHPassword string `json:"SSHPassword"`
|
||||
ID string `json:"ID"`
|
||||
TagName string `json:"TagName"`
|
||||
ImagePath string `json:"ImagePath"`
|
||||
Ports Ports `json:"Ports"`
|
||||
GPU string `json:"GPU"`
|
||||
SSHUsername string `json:"SSHUsername"`
|
||||
SSHPassword string `json:"SSHPassword"`
|
||||
ID string `json:"ID"`
|
||||
TagName string `json:"TagName"`
|
||||
ImagePath string `json:"ImagePath"`
|
||||
Ports Ports `json:"Ports"`
|
||||
GPU string `json:"GPU"`
|
||||
}
|
||||
|
||||
type DockerContainers struct {
|
||||
DockerContainer []DockerContainer `json:"DockerContainer"`
|
||||
DockerContainer []DockerContainer `json:"DockerContainer"`
|
||||
}
|
||||
|
||||
type DockerContainer struct {
|
||||
ContainerName string `json:"DockerContainerName"`
|
||||
ContainerDescription string `json:"ContainerDescription"`
|
||||
ContainerName string `json:"DockerContainerName"`
|
||||
ContainerDescription string `json:"ContainerDescription"`
|
||||
}
|
||||
|
||||
type Ports struct {
|
||||
PortSet []Port `json:"Port"`
|
||||
PortSet []Port `json:"Port"`
|
||||
}
|
||||
type Port struct {
|
||||
PortName string `json:"PortName"`
|
||||
InternalPort int `json:"InternalPort"`
|
||||
Type string `json:"Type"`
|
||||
ExternalPort int `json:"ExternalPort"`
|
||||
IsUsed bool `json:"IsUsed"`
|
||||
Description string `json:"Description"`
|
||||
PortName string `json:"PortName"`
|
||||
InternalPort int `json:"InternalPort"`
|
||||
Type string `json:"Type"`
|
||||
ExternalPort int `json:"ExternalPort"`
|
||||
IsUsed bool `json:"IsUsed"`
|
||||
Description string `json:"Description"`
|
||||
}
|
||||
|
||||
type ErrorLine struct {
|
||||
Error string `json:"error"`
|
||||
ErrorDetail ErrorDetail `json:"errorDetail"`
|
||||
Error string `json:"error"`
|
||||
ErrorDetail ErrorDetail `json:"errorDetail"`
|
||||
}
|
||||
|
||||
type ErrorDetail struct {
|
||||
Message string `json:"message"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
var dockerRegistryUserID = ""
|
||||
@@ -66,137 +66,137 @@ var dockerRegistryUserID = ""
|
||||
// BuildRunContainer Function is incharge to invoke building and running contianer and also allocating external
|
||||
// ports
|
||||
func BuildRunContainer(NumPorts int, GPU string, ContainerName string) (*DockerVM, error) {
|
||||
//Docker Struct Variable
|
||||
var RespDocker *DockerVM = new(DockerVM)
|
||||
//Docker Struct Variable
|
||||
var RespDocker *DockerVM = new(DockerVM)
|
||||
|
||||
// Sets if GPU is selected or not
|
||||
RespDocker.GPU = GPU
|
||||
// Sets if GPU is selected or not
|
||||
RespDocker.GPU = GPU
|
||||
|
||||
// Sets Free port to Struct
|
||||
//RespDocker.SSHPort = Ports[0]
|
||||
//RespDocker.VNCPort = Ports[1]
|
||||
// Sets appropriate username and password to the
|
||||
// variables in the struct
|
||||
RespDocker.SSHUsername = "master"
|
||||
RespDocker.SSHPassword = "password"
|
||||
//RespDocker.VNCPassword = "vncpassword"
|
||||
// Sets Free port to Struct
|
||||
//RespDocker.SSHPort = Ports[0]
|
||||
//RespDocker.VNCPort = Ports[1]
|
||||
// Sets appropriate username and password to the
|
||||
// variables in the struct
|
||||
RespDocker.SSHUsername = "master"
|
||||
RespDocker.SSHPassword = "password"
|
||||
//RespDocker.VNCPassword = "vncpassword"
|
||||
|
||||
//Default parameters
|
||||
RespDocker.TagName = "p2p-ubuntu"
|
||||
// Get Path from config
|
||||
config, err := config.ConfigInit(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
RespDocker.ImagePath = config.DefaultDockerFile
|
||||
//Default parameters
|
||||
RespDocker.TagName = "p2p-ubuntu"
|
||||
// Get Path from config
|
||||
config, err := config.ConfigInit(nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
RespDocker.ImagePath = config.DefaultDockerFile
|
||||
|
||||
// We are checking if the container name is not nil and not equal to the default one used
|
||||
// which is docker-ubuntu-sshd
|
||||
if ContainerName != "" && ContainerName != "docker-ubuntu-sshd" {
|
||||
Containers, err := ViewAllContainers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// We are checking if the container name is not nil and not equal to the default one used
|
||||
// which is docker-ubuntu-sshd
|
||||
if ContainerName != "" && ContainerName != "docker-ubuntu-sshd" {
|
||||
Containers, err := ViewAllContainers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, dockerContainer := range Containers.DockerContainer {
|
||||
if dockerContainer.ContainerName == ContainerName {
|
||||
RespDocker.ImagePath = config.DockerContainers + ContainerName + "/"
|
||||
RespDocker.TagName = ContainerName
|
||||
break
|
||||
}
|
||||
}
|
||||
if RespDocker.ImagePath == config.DefaultDockerFile {
|
||||
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
|
||||
}
|
||||
}
|
||||
for _, dockerContainer := range Containers.DockerContainer {
|
||||
if dockerContainer.ContainerName == ContainerName {
|
||||
RespDocker.ImagePath = config.DockerContainers + ContainerName + "/"
|
||||
RespDocker.TagName = ContainerName
|
||||
break
|
||||
}
|
||||
}
|
||||
if RespDocker.ImagePath == config.DefaultDockerFile {
|
||||
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
|
||||
}
|
||||
}
|
||||
|
||||
PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/ports.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/ports.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Number of perts we want to open + number of ports required inside the
|
||||
// docker container
|
||||
count := NumPorts + len(PortsInformation.PortSet)
|
||||
// Creates number of ports
|
||||
OpenPorts, err := freeport.GetFreePorts(count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Allocate external ports to ports available in the ports.json file
|
||||
for i := range PortsInformation.PortSet {
|
||||
// Setting external ports
|
||||
PortsInformation.PortSet[i].ExternalPort = OpenPorts[i]
|
||||
PortsInformation.PortSet[i].IsUsed = true
|
||||
}
|
||||
//Length of Ports allocated from thr port file
|
||||
portFileLength := len(PortsInformation.PortSet)
|
||||
// Allocate New ports the user wants to generate
|
||||
for i := 0; i < NumPorts; i++ {
|
||||
var TempPort Port
|
||||
TempPort.PortName = "AutoGen Port"
|
||||
TempPort.Type = "tcp"
|
||||
TempPort.InternalPort = OpenPorts[portFileLength+i]
|
||||
TempPort.ExternalPort = OpenPorts[portFileLength+i]
|
||||
TempPort.Description = "Auto generated TCP port"
|
||||
TempPort.IsUsed = false
|
||||
//Append temp port to port information
|
||||
PortsInformation.PortSet = append(PortsInformation.PortSet, TempPort)
|
||||
}
|
||||
// Setting ports to the docker VM struct
|
||||
RespDocker.Ports = *PortsInformation
|
||||
// Number of perts we want to open + number of ports required inside the
|
||||
// docker container
|
||||
count := NumPorts + len(PortsInformation.PortSet)
|
||||
// Creates number of ports
|
||||
OpenPorts, err := freeport.GetFreePorts(count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Allocate external ports to ports available in the ports.json file
|
||||
for i := range PortsInformation.PortSet {
|
||||
// Setting external ports
|
||||
PortsInformation.PortSet[i].ExternalPort = OpenPorts[i]
|
||||
PortsInformation.PortSet[i].IsUsed = true
|
||||
}
|
||||
//Length of Ports allocated from thr port file
|
||||
portFileLength := len(PortsInformation.PortSet)
|
||||
// Allocate New ports the user wants to generate
|
||||
for i := 0; i < NumPorts; i++ {
|
||||
var TempPort Port
|
||||
TempPort.PortName = "AutoGen Port"
|
||||
TempPort.Type = "tcp"
|
||||
TempPort.InternalPort = OpenPorts[portFileLength+i]
|
||||
TempPort.ExternalPort = OpenPorts[portFileLength+i]
|
||||
TempPort.Description = "Auto generated TCP port"
|
||||
TempPort.IsUsed = false
|
||||
//Append temp port to port information
|
||||
PortsInformation.PortSet = append(PortsInformation.PortSet, TempPort)
|
||||
}
|
||||
// Setting ports to the docker VM struct
|
||||
RespDocker.Ports = *PortsInformation
|
||||
|
||||
// Gets docker information from env variables
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Gets docker information from env variables
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Builds docker image
|
||||
err = RespDocker.imageBuild(cli)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Builds docker image
|
||||
err = RespDocker.imageBuild(cli)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Runs docker contianer
|
||||
err = RespDocker.runContainer(cli)
|
||||
// Runs docker contianer
|
||||
err = RespDocker.runContainer(cli)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return RespDocker, nil
|
||||
return RespDocker, nil
|
||||
|
||||
}
|
||||
|
||||
// Builds docker image (TODO: relative path for Dockerfile deploy)
|
||||
func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
|
||||
//defer cancel()
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
|
||||
//defer cancel()
|
||||
|
||||
tar, err := archive.TarWithOptions(d.ImagePath, &archive.TarOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tar, err := archive.TarWithOptions(d.ImagePath, &archive.TarOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts := types.ImageBuildOptions{
|
||||
Dockerfile: "Dockerfile",
|
||||
Tags: []string{d.TagName},
|
||||
Remove: true,
|
||||
}
|
||||
res, err := dockerClient.ImageBuild(ctx, tar, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts := types.ImageBuildOptions{
|
||||
Dockerfile: "Dockerfile",
|
||||
Tags: []string{d.TagName},
|
||||
Remove: true,
|
||||
}
|
||||
res, err := dockerClient.ImageBuild(ctx, tar, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
defer res.Body.Close()
|
||||
|
||||
err = print(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = print(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Starts container and assigns port numbers
|
||||
@@ -205,200 +205,200 @@ func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
|
||||
// -p 3443:6901 -p 3453:22 -p 3434:3434 -p 3245:3245 -v=/opt/data:/data
|
||||
// p2p-ubuntu /start > /dev/null
|
||||
func (d *DockerVM) runContainer(dockerClient *client.Client) error {
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
|
||||
|
||||
// The first mode runs using the Docker Api. As the API supports using
|
||||
// CPU and uses a shell script for GPU call because till this point of
|
||||
// implementation docker api does not support the flag "--gpu all"
|
||||
if d.GPU != "true" {
|
||||
//Exposed ports for docker config file
|
||||
var ExposedPort nat.PortSet
|
||||
// The first mode runs using the Docker Api. As the API supports using
|
||||
// CPU and uses a shell script for GPU call because till this point of
|
||||
// implementation docker api does not support the flag "--gpu all"
|
||||
if d.GPU != "true" {
|
||||
//Exposed ports for docker config file
|
||||
var ExposedPort nat.PortSet
|
||||
|
||||
ExposedPort = nat.PortSet{
|
||||
"22/tcp": struct{}{},
|
||||
//"6901/tcp": struct{}{},
|
||||
}
|
||||
ExposedPort = nat.PortSet{
|
||||
"22/tcp": struct{}{},
|
||||
//"6901/tcp": struct{}{},
|
||||
}
|
||||
|
||||
// Port forwarding for VNC and SSH ports
|
||||
PortForwarding := nat.PortMap{
|
||||
//"22/tcp": []nat.PortBinding{
|
||||
// {
|
||||
// HostIP: "0.0.0.0",
|
||||
// HostPort: fmt.Sprint(d.SSHPort),
|
||||
// },
|
||||
//},
|
||||
//"6901/tcp": []nat.PortBinding{
|
||||
// {
|
||||
// HostIP: "0.0.0.0",
|
||||
// HostPort: fmt.Sprint(d.VNCPort),
|
||||
// },
|
||||
//},
|
||||
}
|
||||
// Port forwarding for VNC and SSH ports
|
||||
PortForwarding := nat.PortMap{
|
||||
//"22/tcp": []nat.PortBinding{
|
||||
// {
|
||||
// HostIP: "0.0.0.0",
|
||||
// HostPort: fmt.Sprint(d.SSHPort),
|
||||
// },
|
||||
//},
|
||||
//"6901/tcp": []nat.PortBinding{
|
||||
// {
|
||||
// HostIP: "0.0.0.0",
|
||||
// HostPort: fmt.Sprint(d.VNCPort),
|
||||
// },
|
||||
//},
|
||||
}
|
||||
|
||||
for i := range d.Ports.PortSet {
|
||||
// Parameters "tcp or udp", external port
|
||||
Port, err := nat.NewPort(d.Ports.PortSet[i].Type, fmt.Sprint(d.Ports.PortSet[i].InternalPort))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range d.Ports.PortSet {
|
||||
// Parameters "tcp or udp", external port
|
||||
Port, err := nat.NewPort(d.Ports.PortSet[i].Type, fmt.Sprint(d.Ports.PortSet[i].InternalPort))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Exposed Ports
|
||||
ExposedPort[Port] = struct{}{}
|
||||
// Exposed Ports
|
||||
ExposedPort[Port] = struct{}{}
|
||||
|
||||
PortForwarding[Port] = []nat.PortBinding{
|
||||
{
|
||||
HostIP: "0.0.0.0",
|
||||
HostPort: fmt.Sprint(d.Ports.PortSet[i].ExternalPort),
|
||||
},
|
||||
}
|
||||
}
|
||||
PortForwarding[Port] = []nat.PortBinding{
|
||||
{
|
||||
HostIP: "0.0.0.0",
|
||||
HostPort: fmt.Sprint(d.Ports.PortSet[i].ExternalPort),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
config := &container.Config{
|
||||
Image: d.TagName,
|
||||
Entrypoint: []string{"/start"},
|
||||
Volumes: map[string]struct{}{"/opt/data:/data": {}},
|
||||
ExposedPorts: ExposedPort,
|
||||
}
|
||||
hostConfig := &container.HostConfig{
|
||||
PortBindings: PortForwarding,
|
||||
}
|
||||
config := &container.Config{
|
||||
Image: d.TagName,
|
||||
Entrypoint: []string{"/start"},
|
||||
Volumes: map[string]struct{}{"/opt/data:/data": {}},
|
||||
ExposedPorts: ExposedPort,
|
||||
}
|
||||
hostConfig := &container.HostConfig{
|
||||
PortBindings: PortForwarding,
|
||||
}
|
||||
|
||||
res, err := dockerClient.ContainerCreate(ctx, config, hostConfig,
|
||||
nil, nil, "")
|
||||
res, err := dockerClient.ContainerCreate(ctx, config, hostConfig,
|
||||
nil, nil, "")
|
||||
|
||||
// Set response ID
|
||||
d.ID = res.ID
|
||||
// Set response ID
|
||||
d.ID = res.ID
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = dockerClient.ContainerStart(ctx, res.ID, types.ContainerStartOptions{})
|
||||
err = dockerClient.ContainerStart(ctx, res.ID, types.ContainerStartOptions{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Generate Random ID
|
||||
id := shortuuid.New()
|
||||
d.ID = id
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Generate Random ID
|
||||
id := shortuuid.New()
|
||||
d.ID = id
|
||||
|
||||
var cmd bytes.Buffer
|
||||
cmd.WriteString("docker run -d=true --name=" + id + " --restart=always --gpus all ")
|
||||
for i := range d.Ports.PortSet {
|
||||
cmd.WriteString("-p " + fmt.Sprint(d.Ports.PortSet[i].ExternalPort) + ":" + fmt.Sprint(d.Ports.PortSet[i].InternalPort) + " ")
|
||||
}
|
||||
cmd.WriteString("-v=/opt/data:/data " + d.TagName + " /start > /dev/null")
|
||||
//"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
|
||||
cmdStr := cmd.String()
|
||||
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
var cmd bytes.Buffer
|
||||
cmd.WriteString("docker run -d=true --name=" + id + " --restart=always --gpus all ")
|
||||
for i := range d.Ports.PortSet {
|
||||
cmd.WriteString("-p " + fmt.Sprint(d.Ports.PortSet[i].ExternalPort) + ":" + fmt.Sprint(d.Ports.PortSet[i].InternalPort) + " ")
|
||||
}
|
||||
cmd.WriteString("-v=/opt/data:/data " + d.TagName + " /start > /dev/null")
|
||||
//"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
|
||||
cmdStr := cmd.String()
|
||||
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopAndRemoveContainer
|
||||
// Stop and remove a container
|
||||
// Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6)
|
||||
func StopAndRemoveContainer(containername string) error {
|
||||
ctx := context.Background()
|
||||
ctx := context.Background()
|
||||
|
||||
// Gets docker information from env variables
|
||||
client, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 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
|
||||
}
|
||||
if err = client.ContainerStop(ctx, containername, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
removeOptions := types.ContainerRemoveOptions{
|
||||
RemoveVolumes: true,
|
||||
Force: true,
|
||||
}
|
||||
removeOptions := types.ContainerRemoveOptions{
|
||||
RemoveVolumes: true,
|
||||
Force: true,
|
||||
}
|
||||
|
||||
if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// ViewAllContainers returns all containers runnable and which can be built
|
||||
func ViewAllContainers() (*DockerContainers, error) {
|
||||
// Traverse the deploy path as per given in the config file
|
||||
config, err := config.ConfigInit(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Traverse the deploy path as per given in the config file
|
||||
config, err := config.ConfigInit(nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
folders, err := ioutil.ReadDir(config.DockerContainers)
|
||||
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)
|
||||
//Declare variable DockerContainers of type struct
|
||||
var Containers *DockerContainers = new(DockerContainers)
|
||||
|
||||
for _, f := range folders {
|
||||
if f.IsDir() {
|
||||
//Declare variable DockerContainer of type struct
|
||||
var Container DockerContainer
|
||||
for _, f := range folders {
|
||||
if f.IsDir() {
|
||||
//Declare variable DockerContainer of type struct
|
||||
var Container DockerContainer
|
||||
|
||||
// Setting container name to deploy 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
|
||||
}
|
||||
// Setting container name to deploy 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)
|
||||
// Get Description from description.txt
|
||||
Container.ContainerDescription = string(Description)
|
||||
|
||||
Containers.DockerContainer = append(Containers.DockerContainer, Container)
|
||||
}
|
||||
}
|
||||
Containers.DockerContainer = append(Containers.DockerContainer, Container)
|
||||
}
|
||||
}
|
||||
|
||||
return Containers, nil
|
||||
return Containers, nil
|
||||
}
|
||||
|
||||
func print(rd io.Reader) error {
|
||||
var lastLine string
|
||||
var lastLine string
|
||||
|
||||
scanner := bufio.NewScanner(rd)
|
||||
for scanner.Scan() {
|
||||
lastLine = scanner.Text()
|
||||
}
|
||||
scanner := bufio.NewScanner(rd)
|
||||
for scanner.Scan() {
|
||||
lastLine = scanner.Text()
|
||||
}
|
||||
|
||||
errLine := &ErrorLine{}
|
||||
json.Unmarshal([]byte(lastLine), errLine)
|
||||
if errLine.Error != "" {
|
||||
return errors.New(errLine.Error)
|
||||
}
|
||||
errLine := &ErrorLine{}
|
||||
json.Unmarshal([]byte(lastLine), errLine)
|
||||
if errLine.Error != "" {
|
||||
return errors.New(errLine.Error)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func OpenPortsFile(filename string) (*Ports, error) {
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Ports{}
|
||||
err = json.Unmarshal(buf, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in file %q: %v", filename, err)
|
||||
}
|
||||
c := &Ports{}
|
||||
err = json.Unmarshal(buf, c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in file %q: %v", filename, err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
return c, nil
|
||||
}
|
||||
|
||||
362
server/server.go
362
server/server.go
@@ -1,226 +1,226 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/p2p"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/p2p"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
|
||||
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Server() (*gin.Engine, error) {
|
||||
r := gin.Default()
|
||||
r := gin.Default()
|
||||
|
||||
//Get Server port based on the config file
|
||||
config, err := config.ConfigInit(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//Get Server port based on the config file
|
||||
config, err := config.ConfigInit(nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// update IPTable with new port and ip address and update ip table
|
||||
var ProxyIpAddr p2p.IpAddress
|
||||
var lowestLatencyIpAddress p2p.IpAddress
|
||||
// update IPTable with new port and ip address and update ip table
|
||||
var ProxyIpAddr p2p.IpAddress
|
||||
var lowestLatencyIpAddress p2p.IpAddress
|
||||
|
||||
// Gets default information of the server
|
||||
r.GET("/server_info", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, ServerInfo())
|
||||
})
|
||||
// Gets default information of the server
|
||||
r.GET("/server_info", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, ServerInfo())
|
||||
})
|
||||
|
||||
// Speed test with 50 mbps
|
||||
r.GET("/50", func(c *gin.Context) {
|
||||
// Get Path from config
|
||||
c.File(config.SpeedTestFile)
|
||||
})
|
||||
// Speed test with 50 mbps
|
||||
r.GET("/50", func(c *gin.Context) {
|
||||
// Get Path from config
|
||||
c.File(config.SpeedTestFile)
|
||||
})
|
||||
|
||||
// Route build to do a speed test
|
||||
r.GET("/upload", func(c *gin.Context) {
|
||||
file, _ := c.FormFile("file")
|
||||
// Route build to do a speed test
|
||||
r.GET("/upload", func(c *gin.Context) {
|
||||
file, _ := c.FormFile("file")
|
||||
|
||||
// Upload the file to specific dst.
|
||||
// c.SaveUploadedFile(file, dst)
|
||||
// Upload the file to specific dst.
|
||||
// c.SaveUploadedFile(file, dst)
|
||||
|
||||
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
|
||||
})
|
||||
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
|
||||
})
|
||||
|
||||
//Gets Ip Table from server node
|
||||
r.POST("/IpTable", func(c *gin.Context) {
|
||||
// Getting IPV4 address of client
|
||||
var ClientHost p2p.IpAddress
|
||||
//Gets Ip Table from server node
|
||||
r.POST("/IpTable", func(c *gin.Context) {
|
||||
// Getting IPV4 address of client
|
||||
var ClientHost p2p.IpAddress
|
||||
|
||||
if p2p.Ip4or6(c.ClientIP()) == "version 6" {
|
||||
ClientHost.Ipv6 = c.ClientIP()
|
||||
} else {
|
||||
ClientHost.Ipv4 = c.ClientIP()
|
||||
}
|
||||
if p2p.Ip4or6(c.ClientIP()) == "version 6" {
|
||||
ClientHost.Ipv6 = c.ClientIP()
|
||||
} else {
|
||||
ClientHost.Ipv4 = c.ClientIP()
|
||||
}
|
||||
|
||||
// Variable to store IP table information
|
||||
var IPTable p2p.IpAddresses
|
||||
// Variable to store IP table information
|
||||
var IPTable p2p.IpAddresses
|
||||
|
||||
// Receive file from POST request
|
||||
body, err := c.FormFile("json")
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
// Receive file from POST request
|
||||
body, err := c.FormFile("json")
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
// Open file
|
||||
open, err := body.Open()
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
// Open file
|
||||
open, err := body.Open()
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
// Open received file
|
||||
file, err := ioutil.ReadAll(open)
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
// Open received file
|
||||
file, err := ioutil.ReadAll(open)
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
json.Unmarshal(file, &IPTable)
|
||||
json.Unmarshal(file, &IPTable)
|
||||
|
||||
//Add Client IP address to IPTable struct
|
||||
IPTable.IpAddress = append(IPTable.IpAddress, ClientHost)
|
||||
//Add Client IP address to IPTable struct
|
||||
IPTable.IpAddress = append(IPTable.IpAddress, ClientHost)
|
||||
|
||||
// Runs speed test to return only servers in the IP table pingable
|
||||
err = IPTable.SpeedTestUpdatedIPTable()
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
// Runs speed test to return only servers in the IP table pingable
|
||||
err = IPTable.SpeedTestUpdatedIPTable()
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
// Reads IP addresses from ip table
|
||||
IpAddresses, err := p2p.ReadIpTable()
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
// Reads IP addresses from ip table
|
||||
IpAddresses, err := p2p.ReadIpTable()
|
||||
if err != nil {
|
||||
c.String(http.StatusOK, fmt.Sprint(err))
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, IpAddresses)
|
||||
})
|
||||
c.JSON(http.StatusOK, IpAddresses)
|
||||
})
|
||||
|
||||
// Starts docker container in server
|
||||
r.GET("/startcontainer", func(c *gin.Context) {
|
||||
// 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
|
||||
// Starts docker container in server
|
||||
r.GET("/startcontainer", func(c *gin.Context) {
|
||||
// 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)
|
||||
// Convert Get Request value to int
|
||||
fmt.Sscanf(Ports, "%d", &PortsInt)
|
||||
|
||||
// Creates container and returns-back result to
|
||||
// access container
|
||||
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName)
|
||||
// Creates container and returns-back result to
|
||||
// access container
|
||||
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName)
|
||||
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
}
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
}
|
||||
|
||||
// Ensures that FRP is triggered only if a proxy address is provided
|
||||
if ProxyIpAddr.Ipv4 != "" && c.Request.Host != "localhost:"+config.ServerPort && c.Request.Host != "0.0.0.0:"+config.ServerPort {
|
||||
resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
}
|
||||
fmt.Println(resp)
|
||||
}
|
||||
// Ensures that FRP is triggered only if a proxy address is provided
|
||||
if ProxyIpAddr.Ipv4 != "" && c.Request.Host != "localhost:"+config.ServerPort && c.Request.Host != "0.0.0.0:"+config.ServerPort {
|
||||
resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
}
|
||||
fmt.Println(resp)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, resp)
|
||||
})
|
||||
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")
|
||||
})
|
||||
//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")
|
||||
})
|
||||
|
||||
//Show images available
|
||||
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)
|
||||
})
|
||||
//Show images available
|
||||
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)
|
||||
})
|
||||
|
||||
// Request for port no from Server with address
|
||||
r.GET("/FRPPort", func(c *gin.Context) {
|
||||
port, err := frp.StartFRPProxyFromRandom()
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
}
|
||||
// Request for port no from Server with address
|
||||
r.GET("/FRPPort", func(c *gin.Context) {
|
||||
port, err := frp.StartFRPProxyFromRandom()
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
}
|
||||
|
||||
c.String(http.StatusOK, strconv.Itoa(port))
|
||||
})
|
||||
c.String(http.StatusOK, strconv.Itoa(port))
|
||||
})
|
||||
|
||||
// If there is a proxy port specified
|
||||
// then starts the FRP server
|
||||
//if config.FRPServerPort != "0" {
|
||||
// go frp.StartFRPProxyFromRandom()
|
||||
//}
|
||||
// If there is a proxy port specified
|
||||
// then starts the FRP server
|
||||
//if config.FRPServerPort != "0" {
|
||||
// go frp.StartFRPProxyFromRandom()
|
||||
//}
|
||||
|
||||
// TODO check if IPV6 or Proxy port is specified
|
||||
// if not update current entry as proxy address
|
||||
// with appropriate port on IP Table
|
||||
if config.BehindNAT == "True" {
|
||||
table, err := p2p.ReadIpTable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO check if IPV6 or Proxy port is specified
|
||||
// if not update current entry as proxy address
|
||||
// with appropriate port on IP Table
|
||||
if config.BehindNAT == "True" {
|
||||
table, err := p2p.ReadIpTable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var lowestLatency int64
|
||||
// random large number
|
||||
lowestLatency = 10000000
|
||||
var lowestLatency int64
|
||||
// random large number
|
||||
lowestLatency = 10000000
|
||||
|
||||
for i, _ := range table.IpAddress {
|
||||
// Checks if the ping is the lowest and if the following node is acting as a proxy
|
||||
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
|
||||
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency {
|
||||
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
||||
lowestLatencyIpAddress = table.IpAddress[i]
|
||||
}
|
||||
}
|
||||
for i, _ := range table.IpAddress {
|
||||
// Checks if the ping is the lowest and if the following node is acting as a proxy
|
||||
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
|
||||
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency {
|
||||
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
||||
lowestLatencyIpAddress = table.IpAddress[i]
|
||||
}
|
||||
}
|
||||
|
||||
// If there is an identified node
|
||||
if lowestLatency != 10000000 {
|
||||
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Create 3 second delay to allow FRP server to start
|
||||
time.Sleep(1 * time.Second)
|
||||
// Starts FRP as a client with
|
||||
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, config.ServerPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If there is an identified node
|
||||
if lowestLatency != 10000000 {
|
||||
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Create 3 second delay to allow FRP server to start
|
||||
time.Sleep(1 * time.Second)
|
||||
// Starts FRP as a client with
|
||||
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, config.ServerPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// updating with the current proxy address
|
||||
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
||||
ProxyIpAddr.ServerPort = proxyPort
|
||||
ProxyIpAddr.Name = config.MachineName
|
||||
ProxyIpAddr.NAT = "False"
|
||||
ProxyIpAddr.EscapeImplementation = "FRP"
|
||||
// updating with the current proxy address
|
||||
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
||||
ProxyIpAddr.ServerPort = proxyPort
|
||||
ProxyIpAddr.Name = config.MachineName
|
||||
ProxyIpAddr.NAT = "False"
|
||||
ProxyIpAddr.EscapeImplementation = "FRP"
|
||||
|
||||
// append the following to the ip table
|
||||
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
|
||||
// write information back to the IP Table
|
||||
table.WriteIpTable()
|
||||
// update ip table
|
||||
go clientIPTable.UpdateIpTableListClient()
|
||||
}
|
||||
// append the following to the ip table
|
||||
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
|
||||
// write information back to the IP Table
|
||||
table.WriteIpTable()
|
||||
// update ip table
|
||||
go clientIPTable.UpdateIpTableListClient()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Run gin server on the specified port
|
||||
go r.Run(":" + config.ServerPort)
|
||||
// Run gin server on the specified port
|
||||
go r.Run(":" + config.ServerPort)
|
||||
|
||||
return r, nil
|
||||
return r, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user