diff --git a/.gitignore b/.gitignore index 801c83c..bdd6c8e 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ generate/Test #ignore windows exe files *.exe dist/ +# Ignore any sort of logs +logs/ # ignore docker image files server/docker/containers/ diff --git a/client/container.go b/client/container.go index 647b84d..056acf4 100644 --- a/client/container.go +++ b/client/container.go @@ -19,7 +19,7 @@ var ( // From the selected server IP address // TODO: Test cases for this function // 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 var URL string //version := p2p.Ip4or6(IP) @@ -33,7 +33,7 @@ func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*d //if version == "version 6" { // URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName //} 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) diff --git a/cmd/action.go b/cmd/action.go index fe3fe57..5af1566 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -1,277 +1,277 @@ package cmd import ( - "fmt" - "github.com/Akilan1999/p2p-rendering-computation/client" - "github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable" - "github.com/Akilan1999/p2p-rendering-computation/config/generate" - "github.com/Akilan1999/p2p-rendering-computation/p2p" - "github.com/Akilan1999/p2p-rendering-computation/plugin" - "github.com/Akilan1999/p2p-rendering-computation/server" - "github.com/urfave/cli/v2" + "fmt" + "github.com/Akilan1999/p2p-rendering-computation/client" + "github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable" + "github.com/Akilan1999/p2p-rendering-computation/config/generate" + "github.com/Akilan1999/p2p-rendering-computation/p2p" + "github.com/Akilan1999/p2p-rendering-computation/plugin" + "github.com/Akilan1999/p2p-rendering-computation/server" + "github.com/urfave/cli/v2" ) var CliAction = func(ctx *cli.Context) error { - if Server { - _, err := server.Server() - if err != nil { - fmt.Print(err) - } - //server.Rpc() - for { + if Server { + _, err := server.Server() + if err != nil { + fmt.Print(err) + } + //server.Rpc() + for { - } - } + } + } - //Listing servers and also updates IP tables (Default 3 hops) - if UpdateServerList { - err := clientIPTable.UpdateIpTableListClient() - if err != nil { - fmt.Print(err) - } - // Reads from ip table and passes it - // on to struct print function - //Servers, err := p2p.ReadIpTable() - //if err != nil { - // return err - //} - //client.PrettyPrint(Servers) - p2p.PrintIpTable() - } + //Listing servers and also updates IP tables (Default 3 hops) + if UpdateServerList { + err := clientIPTable.UpdateIpTableListClient() + if err != nil { + fmt.Print(err) + } + // Reads from ip table and passes it + // on to struct print function + //Servers, err := p2p.ReadIpTable() + //if err != nil { + // return err + //} + //client.PrettyPrint(Servers) + p2p.PrintIpTable() + } - // Displays the IP table - if ServerList { - // Reads from ip table and passes it - // on to struct print function - //Servers, err := p2p.ReadIpTable() - //if err != nil { - // return err - //} - p2p.PrintIpTable() - } + // Displays the IP table + if ServerList { + // Reads from ip table and passes it + // on to struct print function + //Servers, err := p2p.ReadIpTable() + //if err != nil { + // return err + //} + p2p.PrintIpTable() + } - // Add provided IP to the IP table - if AddServer != "" { - res, err := p2p.ReadIpTable() - if err != nil { - fmt.Println(err) - } + // Add provided IP to the IP table + if AddServer != "" { + res, err := p2p.ReadIpTable() + if err != nil { + fmt.Println(err) + } - //Create variable of type IpAddress and set IP address - // to it - var IpAddr p2p.IpAddress + //Create variable of type IpAddress and set IP address + // to it + var IpAddr p2p.IpAddress - //Checking if the address is a ipv4 - // or ipv6 address - ip4Orip6 := p2p.Ip4or6(AddServer) - if ip4Orip6 == "version 6" { - IpAddr.Ipv6 = AddServer - } else { - IpAddr.Ipv4 = AddServer - } + //Checking if the address is a ipv4 + // or ipv6 address + ip4Orip6 := p2p.Ip4or6(AddServer) + if ip4Orip6 == "version 6" { + IpAddr.Ipv6 = AddServer + } else { + IpAddr.Ipv4 = AddServer + } - // If a server port is provided then set it - if Ports != "" { - IpAddr.ServerPort = Ports - } else { - IpAddr.ServerPort = "8088" - } - // Append IP address to variable result which - // is a list - res.IpAddress = append(res.IpAddress, IpAddr) - // Adds the new server IP to the iptable - res.WriteIpTable() + // If a server port is provided then set it + if Ports != "" { + IpAddr.ServerPort = Ports + } else { + IpAddr.ServerPort = "8088" + } + // Append IP address to variable result which + // is a list + res.IpAddress = append(res.IpAddress, IpAddr) + // Adds the new server IP to the iptable + res.WriteIpTable() - } + } - // Displays all images available on the server side - if ViewImages != "" { - imageRes, err := client.ViewContainers(ViewImages) + // Displays all images available on the server side + if ViewImages != "" { + imageRes, err := client.ViewContainers(ViewImages) - if err != nil { - fmt.Print(err) - } - client.PrettyPrint(imageRes) - } + if err != nil { + fmt.Print(err) + } + client.PrettyPrint(imageRes) + } - // Function called to stop and remove server from Docker - if RemoveVM != "" { - if ID == "" { - fmt.Println("provide container ID via --ID or --id") - } else { - err := client.RemoveContianer(RemoveVM, ID) - if err != nil { - fmt.Print(err) - } - } - } + // Function called to stop and remove server from Docker + if RemoveVM != "" { + if ID == "" { + fmt.Println("provide container ID via --ID or --id") + } else { + err := client.RemoveContianer(RemoveVM, ID) + if err != nil { + fmt.Print(err) + } + } + } - //Call function to create Docker container - if CreateVM != "" { + //Call function to create Docker container + if CreateVM != "" { - var PortsInt int + var PortsInt int - if Ports != "" { - // Convert Get Request value to int - fmt.Sscanf(Ports, "%d", &PortsInt) - } + if Ports != "" { + // Convert Get Request value to int + fmt.Sscanf(Ports, "%d", &PortsInt) + } - // Calls function to do Api call to start the container on the server side - imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName) + // Calls function to do Api call to start the container on the server side + imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage) - if err != nil { - fmt.Print(err) - } - client.PrettyPrint(imageRes) - } + if err != nil { + fmt.Print(err) + } + client.PrettyPrint(imageRes) + } - //Call if specs flag is called - if Specs != "" { - specs, err := client.GetSpecs(Specs) - if err != nil { - return err - } + //Call if specs flag is called + if Specs != "" { + specs, err := client.GetSpecs(Specs) + if err != nil { + return err + } - // Pretty print - client.PrettyPrint(specs) - } + // Pretty print + client.PrettyPrint(specs) + } - //Sets default paths to the config file - if SetDefaultConfig { - _, err := generate.SetDefaults("P2PRC", false, nil, false) - if err != nil { - fmt.Print(err) - } - } + //Sets default paths to the config file + if SetDefaultConfig { + _, err := generate.SetDefaults("P2PRC", false, nil, false) + if err != nil { + fmt.Print(err) + } + } - //If the network interface flag is called - // Then all the network interfaces are displayed - if NetworkInterface { - err := p2p.ViewNetworkInterface() - if err != nil { - fmt.Print(err) - } - } + //If the network interface flag is called + // Then all the network interfaces are displayed + if NetworkInterface { + err := p2p.ViewNetworkInterface() + if err != nil { + fmt.Print(err) + } + } - // If the view plugin flag is called then display all - // plugins available - if ViewPlugin { - plugins, err := plugin.DetectPlugins() - if err != nil { - fmt.Print(err) - } - client.PrettyPrint(plugins) - } + // If the view plugin flag is called then display all + // plugins available + if ViewPlugin { + plugins, err := plugin.DetectPlugins() + if err != nil { + fmt.Print(err) + } + client.PrettyPrint(plugins) + } - // If the flag Tracked Container is called or the flag - // --tc - if TrackedContainers { - err, trackedContainers := client.ViewTrackedContainers() - if err != nil { - fmt.Print(err) - } - client.PrettyPrint(trackedContainers) - } + // If the flag Tracked Container is called or the flag + // --tc + if TrackedContainers { + err, trackedContainers := client.ViewTrackedContainers() + if err != nil { + fmt.Print(err) + } + client.PrettyPrint(trackedContainers) + } - //Executing plugin when the plugin flag is called - // --plugin - if ExecutePlugin != "" { - // To execute plugin requires the container ID or group ID provided when being executed - if ID != "" { - err := plugin.CheckRunPlugin(ExecutePlugin, ID) - if err != nil { - fmt.Println(err) - } else { - fmt.Println("Success") - } - } else { - fmt.Println("provide container ID via --ID or --id") - } + //Executing plugin when the plugin flag is called + // --plugin + if ExecutePlugin != "" { + // To execute plugin requires the container ID or group ID provided when being executed + if ID != "" { + err := plugin.CheckRunPlugin(ExecutePlugin, ID) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("Success") + } + } else { + fmt.Println("provide container ID via --ID or --id") + } - } + } - // Executing function to create new group - // Creates new group and outputs JSON file - if CreateGroup { - group, err := client.CreateGroup() - if err != nil { - return err - } - client.PrettyPrint(group) - } + // Executing function to create new group + // Creates new group and outputs JSON file + if CreateGroup { + group, err := client.CreateGroup() + if err != nil { + return err + } + client.PrettyPrint(group) + } - // Actions to be performed when the - // group flag is called - // --group - if Group != "" { - // Remove container from group based on group ID provided - // --rmcgroup --id - if RemoveContainerGroup && ID != "" { - group, err := client.RemoveContainerGroup(ID, Group) - if err != nil { - fmt.Println(err) - } else { - client.PrettyPrint(group) - } - } else if ID != "" { // Add container to group based on group ID provided - // --id - group, err := client.AddContainerToGroup(ID, Group) - if err != nil { - fmt.Println(err) - } else { - client.PrettyPrint(group) - } - } else { // View all information about current group - group, err := client.GetGroup(Group) - if err != nil { - fmt.Println(err) - } else { - client.PrettyPrint(group) - } - } - } + // Actions to be performed when the + // group flag is called + // --group + if Group != "" { + // Remove container from group based on group ID provided + // --rmcgroup --id + if RemoveContainerGroup && ID != "" { + group, err := client.RemoveContainerGroup(ID, Group) + if err != nil { + fmt.Println(err) + } else { + client.PrettyPrint(group) + } + } else if ID != "" { // Add container to group based on group ID provided + // --id + group, err := client.AddContainerToGroup(ID, Group) + if err != nil { + fmt.Println(err) + } else { + client.PrettyPrint(group) + } + } else { // View all information about current group + group, err := client.GetGroup(Group) + if err != nil { + fmt.Println(err) + } else { + client.PrettyPrint(group) + } + } + } - // Execute function to remove entire group - // when remove group flag is called - // --rmgroup - if RemoveGroup != "" { - err := client.RemoveGroup(RemoveGroup) - if err != nil { - fmt.Println(err) - } else { - fmt.Println("Group Removed") - } - } + // Execute function to remove entire group + // when remove group flag is called + // --rmgroup + if RemoveGroup != "" { + err := client.RemoveGroup(RemoveGroup) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("Group Removed") + } + } - // Execute Function to view all groups - if Groups { - groups, err := client.ReadGroup() - if err != nil { - fmt.Println(err) - } else { - client.PrettyPrint(groups) - } - } + // Execute Function to view all groups + if Groups { + groups, err := client.ReadGroup() + if err != nil { + fmt.Println(err) + } else { + client.PrettyPrint(groups) + } + } - //-------------------------------- + //-------------------------------- - if PullPlugin != "" { - err := plugin.DownloadPlugin(PullPlugin) - if err != nil { - fmt.Println(err) - } else { - fmt.Println("Success") - } - } + if PullPlugin != "" { + err := plugin.DownloadPlugin(PullPlugin) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("Success") + } + } - if RemovePlugin != "" { - err := plugin.DeletePlugin(RemovePlugin) - if err != nil { - fmt.Println(err) - } else { - fmt.Println("Success") - } - } + if RemovePlugin != "" { + err := plugin.DeletePlugin(RemovePlugin) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("Success") + } + } - return nil + return nil } diff --git a/cmd/flags.go b/cmd/flags.go index 250ad1a..b031c4b 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -10,6 +10,7 @@ var ( ViewImages string CreateVM string ContainerName string + BaseImage string Ports string Server bool RemoveVM string @@ -89,6 +90,13 @@ var AppConfigFlags = []cli.Flag{ EnvVars: []string{"CONTAINER_NAME"}, 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{ Name: "RemoveVM", Aliases: []string{"rm"}, diff --git a/config/config.go b/config/config.go index 91a3fa4..dc1749c 100644 --- a/config/config.go +++ b/config/config.go @@ -1,52 +1,53 @@ package config import ( - "encoding/json" - "io/ioutil" - "os" + "encoding/json" + "io/ioutil" + "os" ) var ( - //defaultPath string - defaults = map[string]interface{}{} - configName = "config" - configType = "json" - configFile = "config.json" - configPaths []string - defaultEnvName = "P2PRC" + //defaultPath string + defaults = map[string]interface{}{} + configName = "config" + configType = "json" + configFile = "config.json" + configPaths []string + defaultEnvName = "P2PRC" ) type Config struct { - MachineName string - IPTable string - DockerContainers string - DefaultDockerFile string - SpeedTestFile string - IPV6Address string - PluginPath string - TrackContainersPath string - ServerPort string - GroupTrackContainersPath string - FRPServerPort string - BehindNAT string - CustomConfig interface{} - //NetworkInterface string - //NetworkInterfaceIPV6Index int + MachineName string + IPTable string + DockerContainers string + DefaultDockerFile string + DockerRunLogs string + SpeedTestFile string + IPV6Address string + PluginPath string + TrackContainersPath string + ServerPort string + GroupTrackContainersPath string + FRPServerPort string + BehindNAT string + CustomConfig interface{} + //NetworkInterface string + //NetworkInterfaceIPV6Index int } // GetPathP2PRC Getting P2PRC Directory from environment variable func GetPathP2PRC(Envname string) (string, error) { - if Envname != "" { - err := SetEnvName(Envname) - if err != nil { - return "", err - } - } - curDir := os.Getenv(defaultEnvName) - if curDir == "" { - return curDir, nil - } - return curDir + "/", nil + if Envname != "" { + err := SetEnvName(Envname) + if err != nil { + return "", err + } + } + curDir := os.Getenv(defaultEnvName) + if curDir == "" { + return curDir, nil + } + return curDir + "/", nil } // SetEnvName Sets the environment name @@ -54,103 +55,103 @@ func GetPathP2PRC(Envname string) (string, error) { // your environment variable // This is useful when extending the use case of P2PRC func SetEnvName(EnvName string) error { - defaultEnvName = EnvName - // Handling error to be implemented only if needed - return nil + defaultEnvName = EnvName + // Handling error to be implemented only if needed + return nil } func GetEnvName() string { - return defaultEnvName + return defaultEnvName } // ConfigInit Pass environment name as an optional parameter func ConfigInit(defaultsParameter map[string]interface{}, CustomConfig interface{}, envNameOptional ...string) (*Config, error) { - if len(envNameOptional) > 0 { - defaultEnvName = envNameOptional[0] - } - // - ////Setting current directory to default path - //defaultPath, err := GetPathP2PRC(defaultEnvName) - //if err != nil { - // return nil, err - //} - ////Paths to search for config file - //configPaths = append(configPaths, defaultPath) - // - ////Add all possible configurations paths - //for _, v := range configPaths { - // viper.AddConfigPath(v) - //} - // - ////Read config file - //if err := viper.ReadInConfig(); err != nil { - // // If the error thrown is config file not found - // //Sets default configuration to viper - // for k, v := range defaults { - // viper.SetDefault(k, v) - // } - // viper.SetConfigName(configName) - // viper.SetConfigFile(configFile) - // viper.SetConfigType(configType) - // - // if err = viper.WriteConfig(); err != nil { - // return nil, err - // } - //} - // - //// Adds configuration to the struct - //var config Config - //if err := viper.Unmarshal(&config); err != nil { - // return nil, err - //} - // - //return &config, nil + if len(envNameOptional) > 0 { + defaultEnvName = envNameOptional[0] + } + // + ////Setting current directory to default path + //defaultPath, err := GetPathP2PRC(defaultEnvName) + //if err != nil { + // return nil, err + //} + ////Paths to search for config file + //configPaths = append(configPaths, defaultPath) + // + ////Add all possible configurations paths + //for _, v := range configPaths { + // viper.AddConfigPath(v) + //} + // + ////Read config file + //if err := viper.ReadInConfig(); err != nil { + // // If the error thrown is config file not found + // //Sets default configuration to viper + // for k, v := range defaults { + // viper.SetDefault(k, v) + // } + // viper.SetConfigName(configName) + // viper.SetConfigFile(configFile) + // viper.SetConfigType(configType) + // + // if err = viper.WriteConfig(); err != nil { + // return nil, err + // } + //} + // + //// Adds configuration to the struct + //var config Config + //if err := viper.Unmarshal(&config); err != nil { + // return nil, err + //} + // + //return &config, nil - defaultPath, err := GetPathP2PRC(defaultEnvName) - if err != nil { - return nil, err - } + defaultPath, err := GetPathP2PRC(defaultEnvName) + if err != nil { + return nil, err + } - // Open our jsonFile - jsonFile, err := os.Open(defaultPath + configFile) - // if we os.Open returns an error then handle it - if err != nil { - return nil, err - } + // Open our jsonFile + jsonFile, err := os.Open(defaultPath + configFile) + // if we os.Open returns an error then handle it + if err != nil { + return nil, err + } - // defer the closing of our jsonFile so that we can parse it later on - defer jsonFile.Close() + // defer the closing of our jsonFile so that we can parse it later on + defer jsonFile.Close() - byteValue, _ := ioutil.ReadAll(jsonFile) + byteValue, _ := ioutil.ReadAll(jsonFile) - var config Config - json.Unmarshal(byteValue, &config) + var config Config + json.Unmarshal(byteValue, &config) - if CustomConfig != nil { - // Convert Custom Config to byte - customConfigByte, err := json.Marshal(config.CustomConfig) - if err != nil { - return nil, err - } + if CustomConfig != nil { + // Convert Custom Config to byte + customConfigByte, err := json.Marshal(config.CustomConfig) + if err != nil { + return nil, err + } - // Again map the byte to the CustomConfig interface - json.Unmarshal(customConfigByte, &CustomConfig) - } + // Again map the byte to the CustomConfig interface + json.Unmarshal(customConfigByte, &CustomConfig) + } - return &config, nil + return &config, nil } func (c *Config) WriteConfig() error { - //Getting Current Directory from environment variable - //curDir := os.Getenv("REMOTEGAMING") + //Getting Current Directory from environment variable + //curDir := os.Getenv("REMOTEGAMING") - defaultPath, err := GetPathP2PRC(defaultEnvName) - if err != nil { - return err - } + defaultPath, err := GetPathP2PRC(defaultEnvName) + if err != nil { + return err + } - file, _ := json.MarshalIndent(c, "", " ") + file, _ := json.MarshalIndent(c, "", " ") - _ = ioutil.WriteFile(defaultPath+"config.json", file, 0644) - return nil + _ = ioutil.WriteFile(defaultPath+"config.json", file, 0644) + return nil } diff --git a/config/generate/generate.go b/config/generate/generate.go index 6c95792..06a6131 100644 --- a/config/generate/generate.go +++ b/config/generate/generate.go @@ -1,20 +1,20 @@ package generate import ( - "github.com/Akilan1999/p2p-rendering-computation/config" - "os" + "github.com/Akilan1999/p2p-rendering-computation/config" + "os" ) var ( - defaults = map[string]interface{}{} - configPaths []string - defaultEnvName = "P2PRC" + defaults = map[string]interface{}{} + configPaths []string + defaultEnvName = "P2PRC" ) // GetPathP2PRC Getting P2PRC Directory from environment variable func GetPathP2PRC() (string, error) { - curDir := os.Getenv(defaultEnvName) - return curDir + "/", nil + curDir := os.Getenv(defaultEnvName) + return curDir + "/", nil } // SetEnvName Sets the environment name @@ -22,110 +22,111 @@ func GetPathP2PRC() (string, error) { // your environment variable // This is useful when extending the use case of P2PRC func SetEnvName(EnvName string) error { - if EnvName != "" { - defaultEnvName = EnvName - } - // Handling error to be implemented only if needed - return nil + if EnvName != "" { + defaultEnvName = EnvName + } + // Handling error to be implemented only if needed + return nil } // GetCurrentPath Getting P2PRC Directory from environment variable func GetCurrentPath() (string, error) { - curDir := os.Getenv("PWD") - return curDir + "/", nil + curDir := os.Getenv("PWD") + return curDir + "/", nil } // SetDefaults This function to be called only during a // make install func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, NoBoilerPlate bool, ConfigUpdate ...*config.Config) (*config.Config, error) { - //Setting current directory to default path - defaultPath, err := GetCurrentPath() - if err != nil { - return nil, err - } + //Setting current directory to default path + defaultPath, err := GetCurrentPath() + if err != nil { + return nil, err + } - // Set Env name - err = config.SetEnvName(envName) - if err != nil { - return nil, err - } + // Set Env name + err = config.SetEnvName(envName) + if err != nil { + return nil, err + } - ////Creates ip_table.json in the json directory - //err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json") - //if err != nil { - // return err - //} - // - ////Creates a copy of trackcontainers.json in the appropriate directory - //err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json") - //if err != nil { - // return err - //} - // - ////Creates a copy of trackcontainers.json in the appropriate directory - //err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json") - //if err != nil { - // return err - //} + ////Creates ip_table.json in the json directory + //err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json") + //if err != nil { + // return err + //} + // + ////Creates a copy of trackcontainers.json in the appropriate directory + //err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json") + //if err != nil { + // return err + //} + // + ////Creates a copy of trackcontainers.json in the appropriate directory + //err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json") + //if err != nil { + // return err + //} - var Defaults config.Config + var Defaults config.Config - if len(ConfigUpdate) == 0 { - //Setting default paths for the config file - Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json" - Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/" - Defaults.DockerContainers = defaultPath + "server/docker/containers/" - Defaults.SpeedTestFile = defaultPath + "p2p/50.bin" - Defaults.IPV6Address = "" - Defaults.PluginPath = defaultPath + "plugin/deploy" - Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json" - Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json" - Defaults.ServerPort = "8088" - Defaults.FRPServerPort = "True" - Defaults.CustomConfig = CustomConfig - Defaults.BehindNAT = "True" - // Random name generator - hostname, err := os.Hostname() - if err != nil { - return nil, err - } + if len(ConfigUpdate) == 0 { + //Setting default paths for the config file + Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json" + Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/" + Defaults.DockerContainers = defaultPath + "server/docker/containers/" + Defaults.SpeedTestFile = defaultPath + "p2p/50.bin" + Defaults.IPV6Address = "" + Defaults.PluginPath = defaultPath + "plugin/deploy" + Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json" + Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json" + Defaults.ServerPort = "8088" + Defaults.FRPServerPort = "True" + Defaults.CustomConfig = CustomConfig + Defaults.BehindNAT = "True" + Defaults.DockerRunLogs = "/tmp/" + // Random name generator + hostname, err := os.Hostname() + if err != nil { + return nil, err + } - Defaults.MachineName = hostname - } else { - Defaults = *ConfigUpdate[0] - } + Defaults.MachineName = hostname + } else { + Defaults = *ConfigUpdate[0] + } - //defaults["NetworkInterface"] = "wlp0s20f3" - //defaults["NetworkInterfaceIPV6Index"] = "2" + //defaults["NetworkInterface"] = "wlp0s20f3" + //defaults["NetworkInterfaceIPV6Index"] = "2" - //Paths to search for config file - configPaths = append(configPaths, defaultPath) + //Paths to search for config file + configPaths = append(configPaths, defaultPath) - if fileExists(defaultPath+"config.json") && forceDefault { - err := os.Remove(defaultPath + "config.json") - if err != nil { - return nil, err - } - } + if fileExists(defaultPath+"config.json") && forceDefault { + err := os.Remove(defaultPath + "config.json") + if err != nil { + return nil, err + } + } - // write defaults to the config file - err = Defaults.WriteConfig() - if err != nil { - return nil, err - } + // write defaults to the config file + err = Defaults.WriteConfig() + if err != nil { + return nil, err + } - //Calling configuration file - Config, err := config.ConfigInit(defaults, nil, envName) - if err != nil { - return nil, err - } + //Calling configuration file + Config, err := config.ConfigInit(defaults, nil, envName) + if err != nil { + return nil, err + } - if !NoBoilerPlate { - err = GenerateFiles() - if err != nil { - return nil, err - } - } + if !NoBoilerPlate { + err = GenerateFiles() + if err != nil { + return nil, err + } + } - return Config, nil + return Config, nil } diff --git a/server/docker/docker.go b/server/docker/docker.go index 987edea..4eb5731 100644 --- a/server/docker/docker.go +++ b/server/docker/docker.go @@ -1,202 +1,230 @@ 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" + "encoding/json" + "errors" + "fmt" + "github.com/Akilan1999/p2p-rendering-computation/config" + "github.com/docker/docker/client" + "github.com/google/uuid" + "github.com/lithammer/shortuuid" + "github.com/otiai10/copy" + "github.com/phayes/freeport" + "io" + "io/ioutil" + "os" + "os/exec" + "text/template" ) 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"` + TempPath string + BaseImage string + LogsPath string } 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 = "" // 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) +func BuildRunContainer(NumPorts int, GPU string, ContainerName string, baseImage string) (*DockerVM, error) { + //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.BaseImage = "ubuntu:20.04" + //RespDocker.VNCPassword = "vncpassword" - //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 + //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 + RespDocker.LogsPath = config.DockerRunLogs - // 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 - } + // Checking if the base image is provided + if baseImage != "" { + RespDocker.BaseImage = baseImage + } else { + RespDocker.BaseImage = "ubuntu:20.04" + } - // 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 + // Template docker with the base image provided + err = RespDocker.TemplateDockerContainer() + 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 - } + // Template the DockerFile and point to the temp location - // Builds docker image - err = RespDocker.imageBuild(cli) - if err != nil { - return nil, err - } + PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/" + RespDocker.TagName + "/ports.json") + if err != nil { + return nil, err + } - // Runs docker contianer - err = RespDocker.runContainer(cli) + // 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 - 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 + } - 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) 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 - } + var cmd bytes.Buffer - opts := types.ImageBuildOptions{ - Dockerfile: "Dockerfile", - Tags: []string{d.TagName}, - Remove: true, - } - res, err := dockerClient.ImageBuild(ctx, tar, opts) - if err != nil { - return err - } + cmd.WriteString("docker build -t " + d.TagName + " " + d.ImagePath + "/" + d.TagName) + //"-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 + } - 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) - if err != nil { - return err - } - - return nil + return nil } // 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 // 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{}{}, + // } + // + // // 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{ - "22/tcp": struct{}{}, - //"6901/tcp": struct{}{}, - } + var cmd bytes.Buffer + cmd.WriteString("docker run -d=true --name=" + id + " --restart=always ") + if d.GPU == "true" { + cmd.WriteString("--gpus all ") + } - // 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 - - 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 + 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=/tmp:/data " + d.TagName + " > /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 + //} + // + //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 - client, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if err != nil { - return err - } + // stop docker container + var stop bytes.Buffer + stop.WriteString("docker stop " + containername) - if err = client.ContainerStop(ctx, containername, nil); err != nil { - return err - } + cmdStr := stop.String() + _, err := exec.Command("/bin/sh", "-c", cmdStr).Output() + if err != nil { + return err + } - removeOptions := types.ContainerRemoveOptions{ - RemoveVolumes: true, - Force: true, - } + // remove docker container + var remove bytes.Buffer + remove.WriteString("docker remove " + containername) - if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil { - return err - } + cmdStr = remove.String() - 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 func ViewAllContainers() (*DockerContainers, error) { - // Traverse the deploy path as per given in the config file - config, err := config.ConfigInit(nil, 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 +} + +// 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 } diff --git a/server/rpc.go b/server/rpc.go deleted file mode 100644 index 7619a13..0000000 --- a/server/rpc.go +++ /dev/null @@ -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) -} diff --git a/server/server.go b/server/server.go index f665cde..0dce4f2 100644 --- a/server/server.go +++ b/server/server.go @@ -1,239 +1,240 @@ 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, 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", "") + BaseImage := c.DefaultQuery("BaseImage", "") + 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, BaseImage) - 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" { - // Remove nodes currently not pingable - clientIPTable.RemoveOfflineNodes() + // 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" { + // Remove nodes currently not pingable + clientIPTable.RemoveOfflineNodes() - table, err := p2p.ReadIpTable() - if err != nil { - return nil, err - } + 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 && table.IpAddress[i].NAT != "" { - 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 && table.IpAddress[i].NAT != "" { + 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 - err = table.WriteIpTable() - if err != nil { - return nil, err - } - // update ip table - go func() error { - err := clientIPTable.UpdateIpTableListClient() - if err != nil { - fmt.Println(err) - return err - } - return nil - }() - } + // append the following to the ip table + table.IpAddress = append(table.IpAddress, ProxyIpAddr) + // write information back to the IP Table + err = table.WriteIpTable() + if err != nil { + return nil, err + } + // update ip table + go func() error { + err := clientIPTable.UpdateIpTableListClient() + if err != nil { + fmt.Println(err) + return err + } + return nil + }() + } - } + } - // 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 }