added docker templating and introducted possbility to change the baseimage name
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -21,6 +21,8 @@ generate/Test
|
|||||||
#ignore windows exe files
|
#ignore windows exe files
|
||||||
*.exe
|
*.exe
|
||||||
dist/
|
dist/
|
||||||
|
# Ignore any sort of logs
|
||||||
|
logs/
|
||||||
|
|
||||||
# ignore docker image files
|
# ignore docker image files
|
||||||
server/docker/containers/
|
server/docker/containers/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ var (
|
|||||||
// From the selected server IP address
|
// From the selected server IP address
|
||||||
// TODO: Test cases for this function
|
// TODO: Test cases for this function
|
||||||
// Calls URL ex: http://0.0.0.0:8088/startcontainer?ports=0&GPU=false&ContainerName=docker-ubuntu-sshd
|
// Calls URL ex: http://0.0.0.0:8088/startcontainer?ports=0&GPU=false&ContainerName=docker-ubuntu-sshd
|
||||||
func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*docker.DockerVM, error) {
|
func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string, baseImage string) (*docker.DockerVM, error) {
|
||||||
// Passes URL with number of TCP ports to allocated and to give GPU access to the docker container
|
// Passes URL with number of TCP ports to allocated and to give GPU access to the docker container
|
||||||
var URL string
|
var URL string
|
||||||
//version := p2p.Ip4or6(IP)
|
//version := p2p.Ip4or6(IP)
|
||||||
@@ -33,7 +33,7 @@ func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*d
|
|||||||
//if version == "version 6" {
|
//if version == "version 6" {
|
||||||
// URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
|
// URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
|
||||||
//} else {
|
//} else {
|
||||||
URL = "http://" + IP + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
|
URL = "http://" + IP + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName + "&BaseImage=" + baseImage
|
||||||
//}
|
//}
|
||||||
|
|
||||||
resp, err := http.Get(URL)
|
resp, err := http.Get(URL)
|
||||||
|
|||||||
476
cmd/action.go
476
cmd/action.go
@@ -1,277 +1,277 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/client"
|
"github.com/Akilan1999/p2p-rendering-computation/client"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
|
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/p2p"
|
"github.com/Akilan1999/p2p-rendering-computation/p2p"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/plugin"
|
"github.com/Akilan1999/p2p-rendering-computation/plugin"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/server"
|
"github.com/Akilan1999/p2p-rendering-computation/server"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var CliAction = func(ctx *cli.Context) error {
|
var CliAction = func(ctx *cli.Context) error {
|
||||||
if Server {
|
if Server {
|
||||||
_, err := server.Server()
|
_, err := server.Server()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
//server.Rpc()
|
//server.Rpc()
|
||||||
for {
|
for {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Listing servers and also updates IP tables (Default 3 hops)
|
//Listing servers and also updates IP tables (Default 3 hops)
|
||||||
if UpdateServerList {
|
if UpdateServerList {
|
||||||
err := clientIPTable.UpdateIpTableListClient()
|
err := clientIPTable.UpdateIpTableListClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
// Reads from ip table and passes it
|
// Reads from ip table and passes it
|
||||||
// on to struct print function
|
// on to struct print function
|
||||||
//Servers, err := p2p.ReadIpTable()
|
//Servers, err := p2p.ReadIpTable()
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// return err
|
// return err
|
||||||
//}
|
//}
|
||||||
//client.PrettyPrint(Servers)
|
//client.PrettyPrint(Servers)
|
||||||
p2p.PrintIpTable()
|
p2p.PrintIpTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Displays the IP table
|
// Displays the IP table
|
||||||
if ServerList {
|
if ServerList {
|
||||||
// Reads from ip table and passes it
|
// Reads from ip table and passes it
|
||||||
// on to struct print function
|
// on to struct print function
|
||||||
//Servers, err := p2p.ReadIpTable()
|
//Servers, err := p2p.ReadIpTable()
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// return err
|
// return err
|
||||||
//}
|
//}
|
||||||
p2p.PrintIpTable()
|
p2p.PrintIpTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add provided IP to the IP table
|
// Add provided IP to the IP table
|
||||||
if AddServer != "" {
|
if AddServer != "" {
|
||||||
res, err := p2p.ReadIpTable()
|
res, err := p2p.ReadIpTable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create variable of type IpAddress and set IP address
|
//Create variable of type IpAddress and set IP address
|
||||||
// to it
|
// to it
|
||||||
var IpAddr p2p.IpAddress
|
var IpAddr p2p.IpAddress
|
||||||
|
|
||||||
//Checking if the address is a ipv4
|
//Checking if the address is a ipv4
|
||||||
// or ipv6 address
|
// or ipv6 address
|
||||||
ip4Orip6 := p2p.Ip4or6(AddServer)
|
ip4Orip6 := p2p.Ip4or6(AddServer)
|
||||||
if ip4Orip6 == "version 6" {
|
if ip4Orip6 == "version 6" {
|
||||||
IpAddr.Ipv6 = AddServer
|
IpAddr.Ipv6 = AddServer
|
||||||
} else {
|
} else {
|
||||||
IpAddr.Ipv4 = AddServer
|
IpAddr.Ipv4 = AddServer
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a server port is provided then set it
|
// If a server port is provided then set it
|
||||||
if Ports != "" {
|
if Ports != "" {
|
||||||
IpAddr.ServerPort = Ports
|
IpAddr.ServerPort = Ports
|
||||||
} else {
|
} else {
|
||||||
IpAddr.ServerPort = "8088"
|
IpAddr.ServerPort = "8088"
|
||||||
}
|
}
|
||||||
// Append IP address to variable result which
|
// Append IP address to variable result which
|
||||||
// is a list
|
// is a list
|
||||||
res.IpAddress = append(res.IpAddress, IpAddr)
|
res.IpAddress = append(res.IpAddress, IpAddr)
|
||||||
// Adds the new server IP to the iptable
|
// Adds the new server IP to the iptable
|
||||||
res.WriteIpTable()
|
res.WriteIpTable()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Displays all images available on the server side
|
// Displays all images available on the server side
|
||||||
if ViewImages != "" {
|
if ViewImages != "" {
|
||||||
imageRes, err := client.ViewContainers(ViewImages)
|
imageRes, err := client.ViewContainers(ViewImages)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
client.PrettyPrint(imageRes)
|
client.PrettyPrint(imageRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function called to stop and remove server from Docker
|
// Function called to stop and remove server from Docker
|
||||||
if RemoveVM != "" {
|
if RemoveVM != "" {
|
||||||
if ID == "" {
|
if ID == "" {
|
||||||
fmt.Println("provide container ID via --ID or --id")
|
fmt.Println("provide container ID via --ID or --id")
|
||||||
} else {
|
} else {
|
||||||
err := client.RemoveContianer(RemoveVM, ID)
|
err := client.RemoveContianer(RemoveVM, ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Call function to create Docker container
|
//Call function to create Docker container
|
||||||
if CreateVM != "" {
|
if CreateVM != "" {
|
||||||
|
|
||||||
var PortsInt int
|
var PortsInt int
|
||||||
|
|
||||||
if Ports != "" {
|
if Ports != "" {
|
||||||
// Convert Get Request value to int
|
// Convert Get Request value to int
|
||||||
fmt.Sscanf(Ports, "%d", &PortsInt)
|
fmt.Sscanf(Ports, "%d", &PortsInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calls function to do Api call to start the container on the server side
|
// Calls function to do Api call to start the container on the server side
|
||||||
imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName)
|
imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
client.PrettyPrint(imageRes)
|
client.PrettyPrint(imageRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Call if specs flag is called
|
//Call if specs flag is called
|
||||||
if Specs != "" {
|
if Specs != "" {
|
||||||
specs, err := client.GetSpecs(Specs)
|
specs, err := client.GetSpecs(Specs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretty print
|
// Pretty print
|
||||||
client.PrettyPrint(specs)
|
client.PrettyPrint(specs)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sets default paths to the config file
|
//Sets default paths to the config file
|
||||||
if SetDefaultConfig {
|
if SetDefaultConfig {
|
||||||
_, err := generate.SetDefaults("P2PRC", false, nil, false)
|
_, err := generate.SetDefaults("P2PRC", false, nil, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//If the network interface flag is called
|
//If the network interface flag is called
|
||||||
// Then all the network interfaces are displayed
|
// Then all the network interfaces are displayed
|
||||||
if NetworkInterface {
|
if NetworkInterface {
|
||||||
err := p2p.ViewNetworkInterface()
|
err := p2p.ViewNetworkInterface()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the view plugin flag is called then display all
|
// If the view plugin flag is called then display all
|
||||||
// plugins available
|
// plugins available
|
||||||
if ViewPlugin {
|
if ViewPlugin {
|
||||||
plugins, err := plugin.DetectPlugins()
|
plugins, err := plugin.DetectPlugins()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
client.PrettyPrint(plugins)
|
client.PrettyPrint(plugins)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the flag Tracked Container is called or the flag
|
// If the flag Tracked Container is called or the flag
|
||||||
// --tc
|
// --tc
|
||||||
if TrackedContainers {
|
if TrackedContainers {
|
||||||
err, trackedContainers := client.ViewTrackedContainers()
|
err, trackedContainers := client.ViewTrackedContainers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
client.PrettyPrint(trackedContainers)
|
client.PrettyPrint(trackedContainers)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Executing plugin when the plugin flag is called
|
//Executing plugin when the plugin flag is called
|
||||||
// --plugin
|
// --plugin
|
||||||
if ExecutePlugin != "" {
|
if ExecutePlugin != "" {
|
||||||
// To execute plugin requires the container ID or group ID provided when being executed
|
// To execute plugin requires the container ID or group ID provided when being executed
|
||||||
if ID != "" {
|
if ID != "" {
|
||||||
err := plugin.CheckRunPlugin(ExecutePlugin, ID)
|
err := plugin.CheckRunPlugin(ExecutePlugin, ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Success")
|
fmt.Println("Success")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("provide container ID via --ID or --id")
|
fmt.Println("provide container ID via --ID or --id")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing function to create new group
|
// Executing function to create new group
|
||||||
// Creates new group and outputs JSON file
|
// Creates new group and outputs JSON file
|
||||||
if CreateGroup {
|
if CreateGroup {
|
||||||
group, err := client.CreateGroup()
|
group, err := client.CreateGroup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
client.PrettyPrint(group)
|
client.PrettyPrint(group)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions to be performed when the
|
// Actions to be performed when the
|
||||||
// group flag is called
|
// group flag is called
|
||||||
// --group <Group ID>
|
// --group <Group ID>
|
||||||
if Group != "" {
|
if Group != "" {
|
||||||
// Remove container from group based on group ID provided
|
// Remove container from group based on group ID provided
|
||||||
// --rmcgroup --id <contianer id>
|
// --rmcgroup --id <contianer id>
|
||||||
if RemoveContainerGroup && ID != "" {
|
if RemoveContainerGroup && ID != "" {
|
||||||
group, err := client.RemoveContainerGroup(ID, Group)
|
group, err := client.RemoveContainerGroup(ID, Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
client.PrettyPrint(group)
|
client.PrettyPrint(group)
|
||||||
}
|
}
|
||||||
} else if ID != "" { // Add container to group based on group ID provided
|
} else if ID != "" { // Add container to group based on group ID provided
|
||||||
// --id <Container ID>
|
// --id <Container ID>
|
||||||
group, err := client.AddContainerToGroup(ID, Group)
|
group, err := client.AddContainerToGroup(ID, Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
client.PrettyPrint(group)
|
client.PrettyPrint(group)
|
||||||
}
|
}
|
||||||
} else { // View all information about current group
|
} else { // View all information about current group
|
||||||
group, err := client.GetGroup(Group)
|
group, err := client.GetGroup(Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
client.PrettyPrint(group)
|
client.PrettyPrint(group)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute function to remove entire group
|
// Execute function to remove entire group
|
||||||
// when remove group flag is called
|
// when remove group flag is called
|
||||||
// --rmgroup
|
// --rmgroup
|
||||||
if RemoveGroup != "" {
|
if RemoveGroup != "" {
|
||||||
err := client.RemoveGroup(RemoveGroup)
|
err := client.RemoveGroup(RemoveGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Group Removed")
|
fmt.Println("Group Removed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute Function to view all groups
|
// Execute Function to view all groups
|
||||||
if Groups {
|
if Groups {
|
||||||
groups, err := client.ReadGroup()
|
groups, err := client.ReadGroup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
client.PrettyPrint(groups)
|
client.PrettyPrint(groups)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
|
||||||
if PullPlugin != "" {
|
if PullPlugin != "" {
|
||||||
err := plugin.DownloadPlugin(PullPlugin)
|
err := plugin.DownloadPlugin(PullPlugin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Success")
|
fmt.Println("Success")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if RemovePlugin != "" {
|
if RemovePlugin != "" {
|
||||||
err := plugin.DeletePlugin(RemovePlugin)
|
err := plugin.DeletePlugin(RemovePlugin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Success")
|
fmt.Println("Success")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ var (
|
|||||||
ViewImages string
|
ViewImages string
|
||||||
CreateVM string
|
CreateVM string
|
||||||
ContainerName string
|
ContainerName string
|
||||||
|
BaseImage string
|
||||||
Ports string
|
Ports string
|
||||||
Server bool
|
Server bool
|
||||||
RemoveVM string
|
RemoveVM string
|
||||||
@@ -89,6 +90,13 @@ var AppConfigFlags = []cli.Flag{
|
|||||||
EnvVars: []string{"CONTAINER_NAME"},
|
EnvVars: []string{"CONTAINER_NAME"},
|
||||||
Destination: &ContainerName,
|
Destination: &ContainerName,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "BaseImage",
|
||||||
|
Aliases: []string{"bi"},
|
||||||
|
Usage: "Specifying the docker base image to template the dockerfile",
|
||||||
|
EnvVars: []string{"CONTAINER_NAME"},
|
||||||
|
Destination: &BaseImage,
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "RemoveVM",
|
Name: "RemoveVM",
|
||||||
Aliases: []string{"rm"},
|
Aliases: []string{"rm"},
|
||||||
|
|||||||
229
config/config.go
229
config/config.go
@@ -1,52 +1,53 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
//defaultPath string
|
//defaultPath string
|
||||||
defaults = map[string]interface{}{}
|
defaults = map[string]interface{}{}
|
||||||
configName = "config"
|
configName = "config"
|
||||||
configType = "json"
|
configType = "json"
|
||||||
configFile = "config.json"
|
configFile = "config.json"
|
||||||
configPaths []string
|
configPaths []string
|
||||||
defaultEnvName = "P2PRC"
|
defaultEnvName = "P2PRC"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
MachineName string
|
MachineName string
|
||||||
IPTable string
|
IPTable string
|
||||||
DockerContainers string
|
DockerContainers string
|
||||||
DefaultDockerFile string
|
DefaultDockerFile string
|
||||||
SpeedTestFile string
|
DockerRunLogs string
|
||||||
IPV6Address string
|
SpeedTestFile string
|
||||||
PluginPath string
|
IPV6Address string
|
||||||
TrackContainersPath string
|
PluginPath string
|
||||||
ServerPort string
|
TrackContainersPath string
|
||||||
GroupTrackContainersPath string
|
ServerPort string
|
||||||
FRPServerPort string
|
GroupTrackContainersPath string
|
||||||
BehindNAT string
|
FRPServerPort string
|
||||||
CustomConfig interface{}
|
BehindNAT string
|
||||||
//NetworkInterface string
|
CustomConfig interface{}
|
||||||
//NetworkInterfaceIPV6Index int
|
//NetworkInterface string
|
||||||
|
//NetworkInterfaceIPV6Index int
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPathP2PRC Getting P2PRC Directory from environment variable
|
// GetPathP2PRC Getting P2PRC Directory from environment variable
|
||||||
func GetPathP2PRC(Envname string) (string, error) {
|
func GetPathP2PRC(Envname string) (string, error) {
|
||||||
if Envname != "" {
|
if Envname != "" {
|
||||||
err := SetEnvName(Envname)
|
err := SetEnvName(Envname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
curDir := os.Getenv(defaultEnvName)
|
curDir := os.Getenv(defaultEnvName)
|
||||||
if curDir == "" {
|
if curDir == "" {
|
||||||
return curDir, nil
|
return curDir, nil
|
||||||
}
|
}
|
||||||
return curDir + "/", nil
|
return curDir + "/", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEnvName Sets the environment name
|
// SetEnvName Sets the environment name
|
||||||
@@ -54,103 +55,103 @@ func GetPathP2PRC(Envname string) (string, error) {
|
|||||||
// your environment variable
|
// your environment variable
|
||||||
// This is useful when extending the use case of P2PRC
|
// This is useful when extending the use case of P2PRC
|
||||||
func SetEnvName(EnvName string) error {
|
func SetEnvName(EnvName string) error {
|
||||||
defaultEnvName = EnvName
|
defaultEnvName = EnvName
|
||||||
// Handling error to be implemented only if needed
|
// Handling error to be implemented only if needed
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEnvName() string {
|
func GetEnvName() string {
|
||||||
return defaultEnvName
|
return defaultEnvName
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigInit Pass environment name as an optional parameter
|
// ConfigInit Pass environment name as an optional parameter
|
||||||
func ConfigInit(defaultsParameter map[string]interface{}, CustomConfig interface{}, envNameOptional ...string) (*Config, error) {
|
func ConfigInit(defaultsParameter map[string]interface{}, CustomConfig interface{}, envNameOptional ...string) (*Config, error) {
|
||||||
if len(envNameOptional) > 0 {
|
if len(envNameOptional) > 0 {
|
||||||
defaultEnvName = envNameOptional[0]
|
defaultEnvName = envNameOptional[0]
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
////Setting current directory to default path
|
////Setting current directory to default path
|
||||||
//defaultPath, err := GetPathP2PRC(defaultEnvName)
|
//defaultPath, err := GetPathP2PRC(defaultEnvName)
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// return nil, err
|
// return nil, err
|
||||||
//}
|
//}
|
||||||
////Paths to search for config file
|
////Paths to search for config file
|
||||||
//configPaths = append(configPaths, defaultPath)
|
//configPaths = append(configPaths, defaultPath)
|
||||||
//
|
//
|
||||||
////Add all possible configurations paths
|
////Add all possible configurations paths
|
||||||
//for _, v := range configPaths {
|
//for _, v := range configPaths {
|
||||||
// viper.AddConfigPath(v)
|
// viper.AddConfigPath(v)
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
////Read config file
|
////Read config file
|
||||||
//if err := viper.ReadInConfig(); err != nil {
|
//if err := viper.ReadInConfig(); err != nil {
|
||||||
// // If the error thrown is config file not found
|
// // If the error thrown is config file not found
|
||||||
// //Sets default configuration to viper
|
// //Sets default configuration to viper
|
||||||
// for k, v := range defaults {
|
// for k, v := range defaults {
|
||||||
// viper.SetDefault(k, v)
|
// viper.SetDefault(k, v)
|
||||||
// }
|
// }
|
||||||
// viper.SetConfigName(configName)
|
// viper.SetConfigName(configName)
|
||||||
// viper.SetConfigFile(configFile)
|
// viper.SetConfigFile(configFile)
|
||||||
// viper.SetConfigType(configType)
|
// viper.SetConfigType(configType)
|
||||||
//
|
//
|
||||||
// if err = viper.WriteConfig(); err != nil {
|
// if err = viper.WriteConfig(); err != nil {
|
||||||
// return nil, err
|
// return nil, err
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//// Adds configuration to the struct
|
//// Adds configuration to the struct
|
||||||
//var config Config
|
//var config Config
|
||||||
//if err := viper.Unmarshal(&config); err != nil {
|
//if err := viper.Unmarshal(&config); err != nil {
|
||||||
// return nil, err
|
// return nil, err
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//return &config, nil
|
//return &config, nil
|
||||||
|
|
||||||
defaultPath, err := GetPathP2PRC(defaultEnvName)
|
defaultPath, err := GetPathP2PRC(defaultEnvName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open our jsonFile
|
// Open our jsonFile
|
||||||
jsonFile, err := os.Open(defaultPath + configFile)
|
jsonFile, err := os.Open(defaultPath + configFile)
|
||||||
// if we os.Open returns an error then handle it
|
// if we os.Open returns an error then handle it
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// defer the closing of our jsonFile so that we can parse it later on
|
// defer the closing of our jsonFile so that we can parse it later on
|
||||||
defer jsonFile.Close()
|
defer jsonFile.Close()
|
||||||
|
|
||||||
byteValue, _ := ioutil.ReadAll(jsonFile)
|
byteValue, _ := ioutil.ReadAll(jsonFile)
|
||||||
|
|
||||||
var config Config
|
var config Config
|
||||||
json.Unmarshal(byteValue, &config)
|
json.Unmarshal(byteValue, &config)
|
||||||
|
|
||||||
if CustomConfig != nil {
|
if CustomConfig != nil {
|
||||||
// Convert Custom Config to byte
|
// Convert Custom Config to byte
|
||||||
customConfigByte, err := json.Marshal(config.CustomConfig)
|
customConfigByte, err := json.Marshal(config.CustomConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Again map the byte to the CustomConfig interface
|
// Again map the byte to the CustomConfig interface
|
||||||
json.Unmarshal(customConfigByte, &CustomConfig)
|
json.Unmarshal(customConfigByte, &CustomConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &config, nil
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WriteConfig() error {
|
func (c *Config) WriteConfig() error {
|
||||||
//Getting Current Directory from environment variable
|
//Getting Current Directory from environment variable
|
||||||
//curDir := os.Getenv("REMOTEGAMING")
|
//curDir := os.Getenv("REMOTEGAMING")
|
||||||
|
|
||||||
defaultPath, err := GetPathP2PRC(defaultEnvName)
|
defaultPath, err := GetPathP2PRC(defaultEnvName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
file, _ := json.MarshalIndent(c, "", " ")
|
file, _ := json.MarshalIndent(c, "", " ")
|
||||||
|
|
||||||
_ = ioutil.WriteFile(defaultPath+"config.json", file, 0644)
|
_ = ioutil.WriteFile(defaultPath+"config.json", file, 0644)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
package generate
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaults = map[string]interface{}{}
|
defaults = map[string]interface{}{}
|
||||||
configPaths []string
|
configPaths []string
|
||||||
defaultEnvName = "P2PRC"
|
defaultEnvName = "P2PRC"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPathP2PRC Getting P2PRC Directory from environment variable
|
// GetPathP2PRC Getting P2PRC Directory from environment variable
|
||||||
func GetPathP2PRC() (string, error) {
|
func GetPathP2PRC() (string, error) {
|
||||||
curDir := os.Getenv(defaultEnvName)
|
curDir := os.Getenv(defaultEnvName)
|
||||||
return curDir + "/", nil
|
return curDir + "/", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEnvName Sets the environment name
|
// SetEnvName Sets the environment name
|
||||||
@@ -22,110 +22,111 @@ func GetPathP2PRC() (string, error) {
|
|||||||
// your environment variable
|
// your environment variable
|
||||||
// This is useful when extending the use case of P2PRC
|
// This is useful when extending the use case of P2PRC
|
||||||
func SetEnvName(EnvName string) error {
|
func SetEnvName(EnvName string) error {
|
||||||
if EnvName != "" {
|
if EnvName != "" {
|
||||||
defaultEnvName = EnvName
|
defaultEnvName = EnvName
|
||||||
}
|
}
|
||||||
// Handling error to be implemented only if needed
|
// Handling error to be implemented only if needed
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentPath Getting P2PRC Directory from environment variable
|
// GetCurrentPath Getting P2PRC Directory from environment variable
|
||||||
func GetCurrentPath() (string, error) {
|
func GetCurrentPath() (string, error) {
|
||||||
curDir := os.Getenv("PWD")
|
curDir := os.Getenv("PWD")
|
||||||
return curDir + "/", nil
|
return curDir + "/", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults This function to be called only during a
|
// SetDefaults This function to be called only during a
|
||||||
// make install
|
// make install
|
||||||
func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, NoBoilerPlate bool, ConfigUpdate ...*config.Config) (*config.Config, error) {
|
func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, NoBoilerPlate bool, ConfigUpdate ...*config.Config) (*config.Config, error) {
|
||||||
//Setting current directory to default path
|
//Setting current directory to default path
|
||||||
defaultPath, err := GetCurrentPath()
|
defaultPath, err := GetCurrentPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Env name
|
// Set Env name
|
||||||
err = config.SetEnvName(envName)
|
err = config.SetEnvName(envName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
////Creates ip_table.json in the json directory
|
////Creates ip_table.json in the json directory
|
||||||
//err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json")
|
//err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json")
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// return err
|
// return err
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
////Creates a copy of trackcontainers.json in the appropriate directory
|
////Creates a copy of trackcontainers.json in the appropriate directory
|
||||||
//err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json")
|
//err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json")
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// return err
|
// return err
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
////Creates a copy of trackcontainers.json in the appropriate directory
|
////Creates a copy of trackcontainers.json in the appropriate directory
|
||||||
//err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json")
|
//err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json")
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// return err
|
// return err
|
||||||
//}
|
//}
|
||||||
|
|
||||||
var Defaults config.Config
|
var Defaults config.Config
|
||||||
|
|
||||||
if len(ConfigUpdate) == 0 {
|
if len(ConfigUpdate) == 0 {
|
||||||
//Setting default paths for the config file
|
//Setting default paths for the config file
|
||||||
Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json"
|
Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json"
|
||||||
Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
|
Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
|
||||||
Defaults.DockerContainers = defaultPath + "server/docker/containers/"
|
Defaults.DockerContainers = defaultPath + "server/docker/containers/"
|
||||||
Defaults.SpeedTestFile = defaultPath + "p2p/50.bin"
|
Defaults.SpeedTestFile = defaultPath + "p2p/50.bin"
|
||||||
Defaults.IPV6Address = ""
|
Defaults.IPV6Address = ""
|
||||||
Defaults.PluginPath = defaultPath + "plugin/deploy"
|
Defaults.PluginPath = defaultPath + "plugin/deploy"
|
||||||
Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json"
|
Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json"
|
||||||
Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
|
Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
|
||||||
Defaults.ServerPort = "8088"
|
Defaults.ServerPort = "8088"
|
||||||
Defaults.FRPServerPort = "True"
|
Defaults.FRPServerPort = "True"
|
||||||
Defaults.CustomConfig = CustomConfig
|
Defaults.CustomConfig = CustomConfig
|
||||||
Defaults.BehindNAT = "True"
|
Defaults.BehindNAT = "True"
|
||||||
// Random name generator
|
Defaults.DockerRunLogs = "/tmp/"
|
||||||
hostname, err := os.Hostname()
|
// Random name generator
|
||||||
if err != nil {
|
hostname, err := os.Hostname()
|
||||||
return nil, err
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
Defaults.MachineName = hostname
|
Defaults.MachineName = hostname
|
||||||
} else {
|
} else {
|
||||||
Defaults = *ConfigUpdate[0]
|
Defaults = *ConfigUpdate[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
//defaults["NetworkInterface"] = "wlp0s20f3"
|
//defaults["NetworkInterface"] = "wlp0s20f3"
|
||||||
//defaults["NetworkInterfaceIPV6Index"] = "2"
|
//defaults["NetworkInterfaceIPV6Index"] = "2"
|
||||||
|
|
||||||
//Paths to search for config file
|
//Paths to search for config file
|
||||||
configPaths = append(configPaths, defaultPath)
|
configPaths = append(configPaths, defaultPath)
|
||||||
|
|
||||||
if fileExists(defaultPath+"config.json") && forceDefault {
|
if fileExists(defaultPath+"config.json") && forceDefault {
|
||||||
err := os.Remove(defaultPath + "config.json")
|
err := os.Remove(defaultPath + "config.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write defaults to the config file
|
// write defaults to the config file
|
||||||
err = Defaults.WriteConfig()
|
err = Defaults.WriteConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//Calling configuration file
|
//Calling configuration file
|
||||||
Config, err := config.ConfigInit(defaults, nil, envName)
|
Config, err := config.ConfigInit(defaults, nil, envName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !NoBoilerPlate {
|
if !NoBoilerPlate {
|
||||||
err = GenerateFiles()
|
err = GenerateFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Config, nil
|
return Config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,202 +1,230 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"encoding/json"
|
||||||
"encoding/json"
|
"errors"
|
||||||
"errors"
|
"fmt"
|
||||||
"fmt"
|
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/google/uuid"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/lithammer/shortuuid"
|
||||||
"github.com/docker/docker/client"
|
"github.com/otiai10/copy"
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/phayes/freeport"
|
||||||
"github.com/docker/go-connections/nat"
|
"io"
|
||||||
"github.com/lithammer/shortuuid"
|
"io/ioutil"
|
||||||
"github.com/phayes/freeport"
|
"os"
|
||||||
"io"
|
"os/exec"
|
||||||
"io/ioutil"
|
"text/template"
|
||||||
"os/exec"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DockerVM struct {
|
type DockerVM struct {
|
||||||
SSHUsername string `json:"SSHUsername"`
|
SSHUsername string `json:"SSHUsername"`
|
||||||
SSHPassword string `json:"SSHPassword"`
|
SSHPassword string `json:"SSHPassword"`
|
||||||
ID string `json:"ID"`
|
ID string `json:"ID"`
|
||||||
TagName string `json:"TagName"`
|
TagName string `json:"TagName"`
|
||||||
ImagePath string `json:"ImagePath"`
|
ImagePath string `json:"ImagePath"`
|
||||||
Ports Ports `json:"Ports"`
|
Ports Ports `json:"Ports"`
|
||||||
GPU string `json:"GPU"`
|
GPU string `json:"GPU"`
|
||||||
|
TempPath string
|
||||||
|
BaseImage string
|
||||||
|
LogsPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
type DockerContainers struct {
|
type DockerContainers struct {
|
||||||
DockerContainer []DockerContainer `json:"DockerContainer"`
|
DockerContainer []DockerContainer `json:"DockerContainer"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DockerContainer struct {
|
type DockerContainer struct {
|
||||||
ContainerName string `json:"DockerContainerName"`
|
ContainerName string `json:"DockerContainerName"`
|
||||||
ContainerDescription string `json:"ContainerDescription"`
|
ContainerDescription string `json:"ContainerDescription"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ports struct {
|
type Ports struct {
|
||||||
PortSet []Port `json:"Port"`
|
PortSet []Port `json:"Port"`
|
||||||
}
|
}
|
||||||
type Port struct {
|
type Port struct {
|
||||||
PortName string `json:"PortName"`
|
PortName string `json:"PortName"`
|
||||||
InternalPort int `json:"InternalPort"`
|
InternalPort int `json:"InternalPort"`
|
||||||
Type string `json:"Type"`
|
Type string `json:"Type"`
|
||||||
ExternalPort int `json:"ExternalPort"`
|
ExternalPort int `json:"ExternalPort"`
|
||||||
IsUsed bool `json:"IsUsed"`
|
IsUsed bool `json:"IsUsed"`
|
||||||
Description string `json:"Description"`
|
Description string `json:"Description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrorLine struct {
|
type ErrorLine struct {
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
ErrorDetail ErrorDetail `json:"errorDetail"`
|
ErrorDetail ErrorDetail `json:"errorDetail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrorDetail struct {
|
type ErrorDetail struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dockerRegistryUserID = ""
|
var dockerRegistryUserID = ""
|
||||||
|
|
||||||
// BuildRunContainer Function is incharge to invoke building and running contianer and also allocating external
|
// BuildRunContainer Function is incharge to invoke building and running contianer and also allocating external
|
||||||
// ports
|
// ports
|
||||||
func BuildRunContainer(NumPorts int, GPU string, ContainerName string) (*DockerVM, error) {
|
func BuildRunContainer(NumPorts int, GPU string, ContainerName string, baseImage string) (*DockerVM, error) {
|
||||||
//Docker Struct Variable
|
//Docker Struct Variable
|
||||||
var RespDocker *DockerVM = new(DockerVM)
|
var RespDocker *DockerVM = new(DockerVM)
|
||||||
|
|
||||||
// Sets if GPU is selected or not
|
// Sets if GPU is selected or not
|
||||||
RespDocker.GPU = GPU
|
RespDocker.GPU = GPU
|
||||||
|
|
||||||
// Sets Free port to Struct
|
// Sets Free port to Struct
|
||||||
//RespDocker.SSHPort = Ports[0]
|
//RespDocker.SSHPort = Ports[0]
|
||||||
//RespDocker.VNCPort = Ports[1]
|
//RespDocker.VNCPort = Ports[1]
|
||||||
// Sets appropriate username and password to the
|
// Sets appropriate username and password to the
|
||||||
// variables in the struct
|
// variables in the struct
|
||||||
RespDocker.SSHUsername = "master"
|
RespDocker.SSHUsername = "master"
|
||||||
RespDocker.SSHPassword = "password"
|
RespDocker.SSHPassword = "password"
|
||||||
//RespDocker.VNCPassword = "vncpassword"
|
//RespDocker.BaseImage = "ubuntu:20.04"
|
||||||
|
//RespDocker.VNCPassword = "vncpassword"
|
||||||
|
|
||||||
//Default parameters
|
//Default parameters
|
||||||
RespDocker.TagName = "p2p-ubuntu"
|
RespDocker.TagName = "p2p-ubuntu"
|
||||||
// Get Path from config
|
// Get Path from config
|
||||||
config, err := config.ConfigInit(nil, nil)
|
config, err := config.ConfigInit(nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
RespDocker.ImagePath = config.DefaultDockerFile
|
RespDocker.ImagePath = config.DefaultDockerFile
|
||||||
|
RespDocker.LogsPath = config.DockerRunLogs
|
||||||
|
|
||||||
// We are checking if the container name is not nil and not equal to the default one used
|
// We are checking if the container name is not nil and not equal to the default one used
|
||||||
// which is docker-ubuntu-sshd
|
// which is docker-ubuntu-sshd
|
||||||
if ContainerName != "" && ContainerName != "docker-ubuntu-sshd" {
|
if ContainerName != "" && ContainerName != "docker-ubuntu-sshd" {
|
||||||
Containers, err := ViewAllContainers()
|
Containers, err := ViewAllContainers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dockerContainer := range Containers.DockerContainer {
|
for _, dockerContainer := range Containers.DockerContainer {
|
||||||
if dockerContainer.ContainerName == ContainerName {
|
if dockerContainer.ContainerName == ContainerName {
|
||||||
RespDocker.ImagePath = config.DockerContainers + ContainerName + "/"
|
RespDocker.ImagePath = config.DockerContainers + ContainerName + "/"
|
||||||
RespDocker.TagName = ContainerName
|
RespDocker.TagName = ContainerName
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if RespDocker.ImagePath == config.DefaultDockerFile {
|
if RespDocker.ImagePath == config.DefaultDockerFile {
|
||||||
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
|
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/ports.json")
|
// Checking if the base image is provided
|
||||||
if err != nil {
|
if baseImage != "" {
|
||||||
return nil, err
|
RespDocker.BaseImage = baseImage
|
||||||
}
|
} else {
|
||||||
|
RespDocker.BaseImage = "ubuntu:20.04"
|
||||||
|
}
|
||||||
|
|
||||||
// Number of perts we want to open + number of ports required inside the
|
// Template docker with the base image provided
|
||||||
// docker container
|
err = RespDocker.TemplateDockerContainer()
|
||||||
count := NumPorts + len(PortsInformation.PortSet)
|
if err != nil {
|
||||||
// Creates number of ports
|
return nil, err
|
||||||
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
|
// Template the DockerFile and point to the temp location
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builds docker image
|
PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/" + RespDocker.TagName + "/ports.json")
|
||||||
err = RespDocker.imageBuild(cli)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Runs docker contianer
|
// Number of perts we want to open + number of ports required inside the
|
||||||
err = RespDocker.runContainer(cli)
|
// 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
|
||||||
|
|
||||||
if err != nil {
|
// Gets docker information from env variables
|
||||||
return nil, err
|
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
}
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return RespDocker, nil
|
// Builds docker image
|
||||||
|
err = RespDocker.imageBuild(cli)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runs docker contianer
|
||||||
|
err = RespDocker.runContainer(cli)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return RespDocker, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds docker image (TODO: relative path for Dockerfile deploy)
|
// Builds docker image (TODO: relative path for Dockerfile deploy)
|
||||||
func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
|
func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
|
||||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
|
//ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
|
||||||
//defer cancel()
|
//defer cancel()
|
||||||
|
|
||||||
tar, err := archive.TarWithOptions(d.ImagePath, &archive.TarOptions{})
|
var cmd bytes.Buffer
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := types.ImageBuildOptions{
|
cmd.WriteString("docker build -t " + d.TagName + " " + d.ImagePath + "/" + d.TagName)
|
||||||
Dockerfile: "Dockerfile",
|
//"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
|
||||||
Tags: []string{d.TagName},
|
cmdStr := cmd.String()
|
||||||
Remove: true,
|
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
|
||||||
}
|
if err != nil {
|
||||||
res, err := dockerClient.ImageBuild(ctx, tar, opts)
|
return err
|
||||||
if err != nil {
|
}
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer res.Body.Close()
|
//tar, err := archive.TarWithOptions(d.ImagePath+"/"+d.TagName, &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
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//defer res.Body.Close()
|
||||||
|
//
|
||||||
|
//err = print(res.Body)
|
||||||
|
//if err != nil {
|
||||||
|
// return err
|
||||||
|
//}
|
||||||
|
|
||||||
err = print(res.Body)
|
return nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts container and assigns port numbers
|
// Starts container and assigns port numbers
|
||||||
@@ -205,200 +233,273 @@ func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
|
|||||||
// -p 3443:6901 -p 3453:22 -p 3434:3434 -p 3245:3245 -v=/opt/data:/data
|
// -p 3443:6901 -p 3453:22 -p 3434:3434 -p 3245:3245 -v=/opt/data:/data
|
||||||
// p2p-ubuntu /start > /dev/null
|
// p2p-ubuntu /start > /dev/null
|
||||||
func (d *DockerVM) runContainer(dockerClient *client.Client) error {
|
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
|
// 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
|
// CPU and uses a shell script for GPU call because till this point of
|
||||||
// implementation docker api does not support the flag "--gpu all"
|
// implementation docker api does not support the flag "--gpu all"
|
||||||
if d.GPU != "true" {
|
//if d.GPU != "true" {
|
||||||
//Exposed ports for docker config file
|
// //Exposed ports for docker config file
|
||||||
var ExposedPort nat.PortSet
|
// var ExposedPort nat.PortSet
|
||||||
|
//
|
||||||
|
// 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),
|
||||||
|
// // },
|
||||||
|
// //},
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// 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{}{}
|
||||||
|
//
|
||||||
|
// 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,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// res, err := dockerClient.ContainerCreate(ctx, config, hostConfig,
|
||||||
|
// nil, nil, "")
|
||||||
|
//
|
||||||
|
// // Set response ID
|
||||||
|
// d.ID = res.ID
|
||||||
|
//
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// err = dockerClient.ContainerStart(ctx, res.ID, types.ContainerStartOptions{})
|
||||||
|
//
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//} else {
|
||||||
|
// Generate Random ID
|
||||||
|
id := shortuuid.New()
|
||||||
|
d.ID = id
|
||||||
|
|
||||||
ExposedPort = nat.PortSet{
|
var cmd bytes.Buffer
|
||||||
"22/tcp": struct{}{},
|
cmd.WriteString("docker run -d=true --name=" + id + " --restart=always ")
|
||||||
//"6901/tcp": struct{}{},
|
if d.GPU == "true" {
|
||||||
}
|
cmd.WriteString("--gpus all ")
|
||||||
|
}
|
||||||
|
|
||||||
// Port forwarding for VNC and SSH ports
|
for i := range d.Ports.PortSet {
|
||||||
PortForwarding := nat.PortMap{
|
cmd.WriteString("-p " + fmt.Sprint(d.Ports.PortSet[i].ExternalPort) + ":" + fmt.Sprint(d.Ports.PortSet[i].InternalPort) + " ")
|
||||||
//"22/tcp": []nat.PortBinding{
|
}
|
||||||
// {
|
cmd.WriteString("-v=/tmp:/data " + d.TagName + " > /dev/null")
|
||||||
// HostIP: "0.0.0.0",
|
//"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
|
||||||
// HostPort: fmt.Sprint(d.SSHPort),
|
cmdStr := cmd.String()
|
||||||
// },
|
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
|
||||||
//},
|
if err != nil {
|
||||||
//"6901/tcp": []nat.PortBinding{
|
return err
|
||||||
// {
|
}
|
||||||
// HostIP: "0.0.0.0",
|
//}
|
||||||
// HostPort: fmt.Sprint(d.VNCPort),
|
return nil
|
||||||
// },
|
|
||||||
//},
|
|
||||||
}
|
|
||||||
|
|
||||||
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{}{}
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := dockerClient.ContainerCreate(ctx, config, hostConfig,
|
|
||||||
nil, nil, "")
|
|
||||||
|
|
||||||
// Set response ID
|
|
||||||
d.ID = res.ID
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dockerClient.ContainerStart(ctx, res.ID, types.ContainerStartOptions{})
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopAndRemoveContainer
|
// StopAndRemoveContainer
|
||||||
// Stop and remove a container
|
// Stop and remove a container
|
||||||
// Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6)
|
// Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6)
|
||||||
func StopAndRemoveContainer(containername string) error {
|
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
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//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
|
||||||
|
//}
|
||||||
|
|
||||||
// Gets docker information from env variables
|
// stop docker container
|
||||||
client, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
var stop bytes.Buffer
|
||||||
if err != nil {
|
stop.WriteString("docker stop " + containername)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = client.ContainerStop(ctx, containername, nil); err != nil {
|
cmdStr := stop.String()
|
||||||
return err
|
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
|
||||||
}
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
removeOptions := types.ContainerRemoveOptions{
|
// remove docker container
|
||||||
RemoveVolumes: true,
|
var remove bytes.Buffer
|
||||||
Force: true,
|
remove.WriteString("docker remove " + containername)
|
||||||
}
|
|
||||||
|
|
||||||
if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil {
|
cmdStr = remove.String()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
_, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ViewAllContainers returns all containers runnable and which can be built
|
// ViewAllContainers returns all containers runnable and which can be built
|
||||||
func ViewAllContainers() (*DockerContainers, error) {
|
func ViewAllContainers() (*DockerContainers, error) {
|
||||||
// Traverse the deploy path as per given in the config file
|
// Traverse the deploy path as per given in the config file
|
||||||
config, err := config.ConfigInit(nil, nil)
|
config, err := config.ConfigInit(nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
folders, err := ioutil.ReadDir(config.DockerContainers)
|
folders, err := ioutil.ReadDir(config.DockerContainers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//Declare variable DockerContainers of type struct
|
//Declare variable DockerContainers of type struct
|
||||||
var Containers *DockerContainers = new(DockerContainers)
|
var Containers *DockerContainers = new(DockerContainers)
|
||||||
|
|
||||||
for _, f := range folders {
|
for _, f := range folders {
|
||||||
if f.IsDir() {
|
if f.IsDir() {
|
||||||
//Declare variable DockerContainer of type struct
|
//Declare variable DockerContainer of type struct
|
||||||
var Container DockerContainer
|
var Container DockerContainer
|
||||||
|
|
||||||
// Setting container name to deploy name
|
// Setting container name to deploy name
|
||||||
Container.ContainerName = f.Name()
|
Container.ContainerName = f.Name()
|
||||||
// Getting Description from file description.txt
|
// Getting Description from file description.txt
|
||||||
Description, err := ioutil.ReadFile(config.DockerContainers + "/" + Container.ContainerName + "/description.txt")
|
Description, err := ioutil.ReadFile(config.DockerContainers + "/" + Container.ContainerName + "/description.txt")
|
||||||
// if we os.Open returns an error then handle it
|
// if we os.Open returns an error then handle it
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Description from description.txt
|
// Get Description from description.txt
|
||||||
Container.ContainerDescription = string(Description)
|
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 {
|
func print(rd io.Reader) error {
|
||||||
var lastLine string
|
var lastLine string
|
||||||
|
|
||||||
scanner := bufio.NewScanner(rd)
|
scanner := bufio.NewScanner(rd)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
lastLine = scanner.Text()
|
lastLine = scanner.Text()
|
||||||
}
|
}
|
||||||
|
|
||||||
errLine := &ErrorLine{}
|
errLine := &ErrorLine{}
|
||||||
json.Unmarshal([]byte(lastLine), errLine)
|
json.Unmarshal([]byte(lastLine), errLine)
|
||||||
if errLine.Error != "" {
|
if errLine.Error != "" {
|
||||||
return errors.New(errLine.Error)
|
return errors.New(errLine.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenPortsFile(filename string) (*Ports, error) {
|
func OpenPortsFile(filename string) (*Ports, error) {
|
||||||
buf, err := ioutil.ReadFile(filename)
|
buf, err := ioutil.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &Ports{}
|
c := &Ports{}
|
||||||
err = json.Unmarshal(buf, c)
|
err = json.Unmarshal(buf, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("in file %q: %v", filename, err)
|
return nil, fmt.Errorf("in file %q: %v", filename, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateDockerContainer This function templates the docker container
|
||||||
|
// with the base docker image to use
|
||||||
|
func (d *DockerVM) TemplateDockerContainer() error {
|
||||||
|
err := d.CopyToTmpContainer()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parses the site.yml file in the tmp directory
|
||||||
|
t, err := template.ParseFiles(d.ImagePath + "/" + d.TagName + "/Dockerfile")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// opens the output file
|
||||||
|
f, err := os.Create(d.ImagePath + "/" + d.TagName + "/Dockerfile")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
image := d.BaseImage
|
||||||
|
|
||||||
|
// Pass in Docker Base Image
|
||||||
|
err = t.Execute(f, image)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyToTmpContainer Creates a copy of the docker folder
|
||||||
|
func (d *DockerVM) CopyToTmpContainer() error {
|
||||||
|
// generate rand to UUID this is debug the ansible file if needed
|
||||||
|
id := uuid.New()
|
||||||
|
// copies the plugin to the tmp directory
|
||||||
|
err := copy.Copy(d.ImagePath+"/", d.LogsPath+id.String()+"_"+d.TagName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the plugin execution to the tmp location
|
||||||
|
d.TagName = id.String() + "_" + d.TagName
|
||||||
|
// removing slash
|
||||||
|
d.ImagePath = d.LogsPath[:len(d.LogsPath)-1]
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
|
|
||||||
"net"
|
|
||||||
"net/rpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
port = "8089"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Listener int
|
|
||||||
|
|
||||||
type Docker struct {
|
|
||||||
docker *docker.DockerVM
|
|
||||||
}
|
|
||||||
|
|
||||||
// Starts container using RPC calls
|
|
||||||
func (l *Listener) StartContainer(reply *Docker) error {
|
|
||||||
vm, err := docker.BuildRunContainer(3, "false", "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("Receive: %v\n", vm)
|
|
||||||
*reply = Docker{vm}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Rpc() {
|
|
||||||
rpcServer, err := net.ResolveTCPAddr("tcp", "0.0.0.0:"+port)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
inbound, err := net.ListenTCP("tcp", rpcServer)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
listener := new(Listener)
|
|
||||||
rpc.Register(listener)
|
|
||||||
rpc.Accept(inbound)
|
|
||||||
}
|
|
||||||
387
server/server.go
387
server/server.go
@@ -1,239 +1,240 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/p2p"
|
"github.com/Akilan1999/p2p-rendering-computation/p2p"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
|
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
|
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Server() (*gin.Engine, error) {
|
func Server() (*gin.Engine, error) {
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
//Get Server port based on the config file
|
//Get Server port based on the config file
|
||||||
config, err := config.ConfigInit(nil, nil)
|
config, err := config.ConfigInit(nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// update IPTable with new port and ip address and update ip table
|
// update IPTable with new port and ip address and update ip table
|
||||||
var ProxyIpAddr p2p.IpAddress
|
var ProxyIpAddr p2p.IpAddress
|
||||||
var lowestLatencyIpAddress p2p.IpAddress
|
var lowestLatencyIpAddress p2p.IpAddress
|
||||||
|
|
||||||
// Gets default information of the server
|
// Gets default information of the server
|
||||||
r.GET("/server_info", func(c *gin.Context) {
|
r.GET("/server_info", func(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, ServerInfo())
|
c.JSON(http.StatusOK, ServerInfo())
|
||||||
})
|
})
|
||||||
|
|
||||||
// Speed test with 50 mbps
|
// Speed test with 50 mbps
|
||||||
r.GET("/50", func(c *gin.Context) {
|
r.GET("/50", func(c *gin.Context) {
|
||||||
// Get Path from config
|
// Get Path from config
|
||||||
c.File(config.SpeedTestFile)
|
c.File(config.SpeedTestFile)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Route build to do a speed test
|
// Route build to do a speed test
|
||||||
r.GET("/upload", func(c *gin.Context) {
|
r.GET("/upload", func(c *gin.Context) {
|
||||||
file, _ := c.FormFile("file")
|
file, _ := c.FormFile("file")
|
||||||
|
|
||||||
// Upload the file to specific dst.
|
// Upload the file to specific dst.
|
||||||
// c.SaveUploadedFile(file, 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
|
//Gets Ip Table from server node
|
||||||
r.POST("/IpTable", func(c *gin.Context) {
|
r.POST("/IpTable", func(c *gin.Context) {
|
||||||
// Getting IPV4 address of client
|
// Getting IPV4 address of client
|
||||||
var ClientHost p2p.IpAddress
|
var ClientHost p2p.IpAddress
|
||||||
|
|
||||||
if p2p.Ip4or6(c.ClientIP()) == "version 6" {
|
if p2p.Ip4or6(c.ClientIP()) == "version 6" {
|
||||||
ClientHost.Ipv6 = c.ClientIP()
|
ClientHost.Ipv6 = c.ClientIP()
|
||||||
} else {
|
} else {
|
||||||
ClientHost.Ipv4 = c.ClientIP()
|
ClientHost.Ipv4 = c.ClientIP()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variable to store IP table information
|
// Variable to store IP table information
|
||||||
var IPTable p2p.IpAddresses
|
var IPTable p2p.IpAddresses
|
||||||
|
|
||||||
// Receive file from POST request
|
// Receive file from POST request
|
||||||
body, err := c.FormFile("json")
|
body, err := c.FormFile("json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusOK, fmt.Sprint(err))
|
c.String(http.StatusOK, fmt.Sprint(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
open, err := body.Open()
|
open, err := body.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusOK, fmt.Sprint(err))
|
c.String(http.StatusOK, fmt.Sprint(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open received file
|
// Open received file
|
||||||
file, err := ioutil.ReadAll(open)
|
file, err := ioutil.ReadAll(open)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusOK, fmt.Sprint(err))
|
c.String(http.StatusOK, fmt.Sprint(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
json.Unmarshal(file, &IPTable)
|
json.Unmarshal(file, &IPTable)
|
||||||
|
|
||||||
//Add Client IP address to IPTable struct
|
//Add Client IP address to IPTable struct
|
||||||
IPTable.IpAddress = append(IPTable.IpAddress, ClientHost)
|
IPTable.IpAddress = append(IPTable.IpAddress, ClientHost)
|
||||||
|
|
||||||
// Runs speed test to return only servers in the IP table pingable
|
// Runs speed test to return only servers in the IP table pingable
|
||||||
err = IPTable.SpeedTestUpdatedIPTable()
|
err = IPTable.SpeedTestUpdatedIPTable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusOK, fmt.Sprint(err))
|
c.String(http.StatusOK, fmt.Sprint(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads IP addresses from ip table
|
// Reads IP addresses from ip table
|
||||||
IpAddresses, err := p2p.ReadIpTable()
|
IpAddresses, err := p2p.ReadIpTable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusOK, fmt.Sprint(err))
|
c.String(http.StatusOK, fmt.Sprint(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, IpAddresses)
|
c.JSON(http.StatusOK, IpAddresses)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Starts docker container in server
|
// Starts docker container in server
|
||||||
r.GET("/startcontainer", func(c *gin.Context) {
|
r.GET("/startcontainer", func(c *gin.Context) {
|
||||||
// Get Number of ports to open and whether to use GPU or not
|
// Get Number of ports to open and whether to use GPU or not
|
||||||
Ports := c.DefaultQuery("ports", "0")
|
Ports := c.DefaultQuery("ports", "0")
|
||||||
GPU := c.DefaultQuery("GPU", "false")
|
GPU := c.DefaultQuery("GPU", "false")
|
||||||
ContainerName := c.DefaultQuery("ContainerName", "")
|
ContainerName := c.DefaultQuery("ContainerName", "")
|
||||||
var PortsInt int
|
BaseImage := c.DefaultQuery("BaseImage", "")
|
||||||
|
var PortsInt int
|
||||||
|
|
||||||
// Convert Get Request value to int
|
// Convert Get Request value to int
|
||||||
fmt.Sscanf(Ports, "%d", &PortsInt)
|
fmt.Sscanf(Ports, "%d", &PortsInt)
|
||||||
|
|
||||||
// Creates container and returns-back result to
|
// Creates container and returns-back result to
|
||||||
// access container
|
// access container
|
||||||
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName)
|
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName, BaseImage)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that FRP is triggered only if a proxy address is provided
|
// 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 {
|
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)
|
resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||||
}
|
}
|
||||||
fmt.Println(resp)
|
fmt.Println(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, resp)
|
c.JSON(http.StatusOK, resp)
|
||||||
})
|
})
|
||||||
|
|
||||||
//Remove container
|
//Remove container
|
||||||
r.GET("/RemoveContainer", func(c *gin.Context) {
|
r.GET("/RemoveContainer", func(c *gin.Context) {
|
||||||
ID := c.DefaultQuery("id", "0")
|
ID := c.DefaultQuery("id", "0")
|
||||||
if err := docker.StopAndRemoveContainer(ID); err != nil {
|
if err := docker.StopAndRemoveContainer(ID); err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||||
}
|
}
|
||||||
c.String(http.StatusOK, "success")
|
c.String(http.StatusOK, "success")
|
||||||
})
|
})
|
||||||
|
|
||||||
//Show images available
|
//Show images available
|
||||||
r.GET("/ShowImages", func(c *gin.Context) {
|
r.GET("/ShowImages", func(c *gin.Context) {
|
||||||
resp, err := docker.ViewAllContainers()
|
resp, err := docker.ViewAllContainers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, resp)
|
c.JSON(http.StatusOK, resp)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Request for port no from Server with address
|
// Request for port no from Server with address
|
||||||
r.GET("/FRPPort", func(c *gin.Context) {
|
r.GET("/FRPPort", func(c *gin.Context) {
|
||||||
port, err := frp.StartFRPProxyFromRandom()
|
port, err := frp.StartFRPProxyFromRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
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
|
// If there is a proxy port specified
|
||||||
// then starts the FRP server
|
// then starts the FRP server
|
||||||
//if config.FRPServerPort != "0" {
|
//if config.FRPServerPort != "0" {
|
||||||
// go frp.StartFRPProxyFromRandom()
|
// go frp.StartFRPProxyFromRandom()
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// TODO check if IPV6 or Proxy port is specified
|
// TODO check if IPV6 or Proxy port is specified
|
||||||
// if not update current entry as proxy address
|
// if not update current entry as proxy address
|
||||||
// with appropriate port on IP Table
|
// with appropriate port on IP Table
|
||||||
if config.BehindNAT == "True" {
|
if config.BehindNAT == "True" {
|
||||||
// Remove nodes currently not pingable
|
// Remove nodes currently not pingable
|
||||||
clientIPTable.RemoveOfflineNodes()
|
clientIPTable.RemoveOfflineNodes()
|
||||||
|
|
||||||
table, err := p2p.ReadIpTable()
|
table, err := p2p.ReadIpTable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var lowestLatency int64
|
var lowestLatency int64
|
||||||
// random large number
|
// random large number
|
||||||
lowestLatency = 10000000
|
lowestLatency = 10000000
|
||||||
|
|
||||||
for i, _ := range table.IpAddress {
|
for i, _ := range table.IpAddress {
|
||||||
// Checks if the ping is the lowest and if the following node is acting as a proxy
|
// 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 && table.IpAddress[i].ProxyPort != "" {
|
||||||
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
|
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
|
||||||
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
||||||
lowestLatencyIpAddress = table.IpAddress[i]
|
lowestLatencyIpAddress = table.IpAddress[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an identified node
|
// If there is an identified node
|
||||||
if lowestLatency != 10000000 {
|
if lowestLatency != 10000000 {
|
||||||
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
|
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Create 3 second delay to allow FRP server to start
|
// Create 3 second delay to allow FRP server to start
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
// Starts FRP as a client with
|
// Starts FRP as a client with
|
||||||
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, config.ServerPort, "")
|
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, config.ServerPort, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// updating with the current proxy address
|
// updating with the current proxy address
|
||||||
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
||||||
ProxyIpAddr.ServerPort = proxyPort
|
ProxyIpAddr.ServerPort = proxyPort
|
||||||
ProxyIpAddr.Name = config.MachineName
|
ProxyIpAddr.Name = config.MachineName
|
||||||
ProxyIpAddr.NAT = "False"
|
ProxyIpAddr.NAT = "False"
|
||||||
ProxyIpAddr.EscapeImplementation = "FRP"
|
ProxyIpAddr.EscapeImplementation = "FRP"
|
||||||
|
|
||||||
// append the following to the ip table
|
// append the following to the ip table
|
||||||
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
|
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
|
||||||
// write information back to the IP Table
|
// write information back to the IP Table
|
||||||
err = table.WriteIpTable()
|
err = table.WriteIpTable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// update ip table
|
// update ip table
|
||||||
go func() error {
|
go func() error {
|
||||||
err := clientIPTable.UpdateIpTableListClient()
|
err := clientIPTable.UpdateIpTableListClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run gin server on the specified port
|
// Run gin server on the specified port
|
||||||
go r.Run(":" + config.ServerPort)
|
go r.Run(":" + config.ServerPort)
|
||||||
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user