105 Commits

Author SHA1 Message Date
ce7fa2ccf3 Haskell bindings 2024-09-30 18:22:05 +01:00
4115451875 Haskell bindings 2024-09-30 18:21:50 +01:00
3a40e687a5 work in progress haskell bindings 2024-07-26 21:48:04 +01:00
aa4b18f39d added make clean 2024-03-27 08:28:18 +00:00
f9fb225b91 Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2024-03-27 08:06:44 +00:00
7a5cb2f1e3 changes to go.mod 2024-03-27 08:06:23 +00:00
Akilan Selvacoumar
8ff61422d7 Merge pull request #111 from cr2007/docs-markdown-alerts
Adds Alerts Markdown Support
2024-03-14 10:45:30 +00:00
CSK
0c86c6e673 Adds Markdown Alerts for Notes
Reference: https://github.com/orgs/community/discussions/16925

And adds some minor fixes
2024-03-12 14:41:29 +04:00
CSK
00629b604f Adds hyperlink for creating new issue
And some minor fixes in the README.md file
2024-03-12 13:55:37 +04:00
72484da67b Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2024-02-23 17:50:11 +00:00
7f1e9cbbae added base abstraction functions and docs to P2PRC 2024-02-23 17:49:55 +00:00
Akilan Selvacoumar
c14a0521c9 Update README.md for extending server. 2024-02-10 22:18:46 +00:00
504cdb41cf added easier use of abstractions 2024-02-10 22:05:47 +00:00
c815ed34d7 fixed mapPort for abstractions 2024-02-10 19:59:46 +00:00
60c4bba380 changing root node 2024-01-10 03:55:11 +00:00
3a2cb47b6e Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2023-12-22 00:14:09 +00:00
8c708c6f11 added map port and baremetal mode 2023-12-22 00:13:57 +00:00
83653866e6 added support for baremetal mode 2023-12-20 04:35:04 +00:00
Akilan Selvacoumar
9c94f20ea8 Update README.md 2023-12-16 03:35:20 +00:00
Akilan Selvacoumar
18ae29946d Update README.md 2023-12-16 03:33:17 +00:00
Akilan Selvacoumar
05936a5486 Update README.md 2023-12-16 03:26:56 +00:00
Akilan Selvacoumar
7d5e5cb619 Update README.md 2023-12-16 03:08:03 +00:00
Akilan Selvacoumar
04eea717a6 Update README.md 2023-12-16 03:05:06 +00:00
Akilan Selvacoumar
b6db9147c8 Update README.md 2023-12-16 03:03:49 +00:00
Akilan Selvacoumar
599f7ba2c6 Update README.md 2023-12-16 03:02:03 +00:00
Akilan Selvacoumar
38a05d6ab5 Update README.md 2023-12-16 03:01:10 +00:00
Akilan Selvacoumar
ea08b5c3ea Update Bindings.md 2023-12-16 02:57:44 +00:00
Akilan Selvacoumar
1c496d8be1 Update Bindings.md 2023-12-16 02:55:54 +00:00
Akilan Selvacoumar
a4b9634dc2 Update Bindings.md 2023-12-16 02:39:22 +00:00
Akilan Selvacoumar
65b90d7ce9 Update Bindings.md 2023-12-16 02:17:25 +00:00
Akilan Selvacoumar
95ab45bf62 Update Bindings.md 2023-12-16 02:08:26 +00:00
751f1b15a6 added binding docs 2023-12-15 18:33:28 +00:00
8ccdcaefb5 Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2023-12-15 17:16:10 +00:00
213838715b fixed adding public key as parameter when spawning a container 2023-12-15 17:15:57 +00:00
Akilan Selvacoumar
f899b4e6bb Update README.md 2023-12-15 03:45:00 +00:00
2704caa5e4 added public-private keys for all docker containers 2023-12-15 03:42:06 +00:00
2b6c7a5963 added support to generate Public and Private keys 2023-12-15 02:08:11 +00:00
b78c009f9f modifed shared object calls for python bindings 2023-11-16 15:17:05 +00:00
708eacd1db added support for python bindings 2023-11-10 21:00:24 +00:00
979e856272 pushed changes relating P2PRC changes for python bindings 2023-11-10 18:17:28 +00:00
614a3412c5 pushed changes relating P2PRC changes for python bindings 2023-11-10 18:17:15 +00:00
ea90348fd2 added shared starter tests and added to Makefile to add compile .h and .so files 2023-10-05 17:07:21 +01:00
Akilan Selvacoumar
a07c91c888 Merge pull request #107 from xecarlox94/master
modifying nix config
2023-09-27 17:40:48 +01:00
636646b0a1 modifying nix files, adding adding building, and docker (VIM as well) 2023-09-27 17:38:50 +01:00
3933b29979 merged pull request 2023-09-27 17:28:28 +01:00
96e755bc19 added flag to add custom metadata 2023-09-27 17:27:52 +01:00
Akilan Selvacoumar
7f0a43625b Merge pull request #106 from xecarlox94/master
adding nix shell development environment
2023-09-27 16:29:16 +01:00
29eff7a3af adding nix shell development environment, tested 2023-09-27 16:27:17 +01:00
7ed25ef4b3 added JSON response for IPTables 2023-09-27 15:27:25 +01:00
6b287f2cf1 added docker templating and introducted possbility to change the baseimage name 2023-08-23 22:45:46 +01:00
dfa8713aea fixed tracked container issue 2023-07-29 15:42:05 +01:00
263275d80c remove nodes not pingable 2023-07-15 00:07:14 +01:00
9caf6cde07 saving current changes 2023-07-14 17:54:56 +01:00
d71bd991b0 modified README files and changed version to v2.0.0 2023-07-14 16:51:48 +01:00
e21465b1eb modified README files and changed version to v2.0.0 2023-07-14 16:49:43 +01:00
fb606cf4ff merged from master 2023-07-14 16:31:17 +01:00
136243d6a5 added new IPTable entries 2023-07-14 16:30:20 +01:00
Akilan Selvacoumar
2f6116993b Merge pull request #101 from cr2007/master
Updates the `CITATION.cff` file
2023-07-11 10:27:35 +01:00
Chandrashekhar R
0665a82815 Merge branch 'Akilan1999:master' into master 2023-07-07 09:31:33 +04:00
Chandrashekhar R
a7d741909c Updates the version, release date in CITATION.cff 2023-07-07 09:31:25 +04:00
Akilan Selvacoumar
232c13aca0 Merge pull request #100 from cr2007/master
Polishes up the Documentation
2023-07-06 15:39:38 +01:00
Chandrashekhar R
70aa82a946 Adds buttons to go to the previous/next section of documentation 2023-07-06 14:24:42 +04:00
Akilan Selvacoumar
8f4c2623e3 Update ConfigImplementation.md 2023-06-08 16:50:50 +01:00
Akilan Selvacoumar
a038bf9f20 Update CliImplementation.md 2023-06-08 16:49:27 +01:00
Akilan Selvacoumar
683e20953b Update ServerImplementation.md 2023-06-08 16:43:59 +01:00
Akilan Selvacoumar
8e6a6e246c Update P2PImplementation.md 2023-06-08 16:41:42 +01:00
Akilan Selvacoumar
06e5e1e67f Update ClientImplementation.md 2023-06-08 16:07:38 +01:00
Akilan Selvacoumar
2b191af951 Update ClientImplementation.md 2023-06-08 16:06:38 +01:00
Akilan Selvacoumar
85ac36d51b Update Client.md 2023-06-08 16:04:28 +01:00
Akilan Selvacoumar
64225b85b7 Update Client.md 2023-06-08 16:02:28 +01:00
Akilan Selvacoumar
66b26c5ea2 Update Introduction.md 2023-06-08 16:01:29 +01:00
4d2b903a0f updated docs 2023-06-08 03:39:05 +01:00
Akilan Selvacoumar
5ac033403f Merge pull request #97 from Akilan1999/approprirate-abstractions
Appropriate abstractions
2023-06-07 23:49:39 +01:00
d52aca3d14 fixed spelling mistakes 2023-06-07 23:49:15 +01:00
05c9f52e6d added improved docs for P2PRC abstractions 2023-06-07 23:42:56 +01:00
732b31fafa go fmt the entire project and added possbility to start a server with a TURN connection with a custom remote connection 2023-04-22 12:43:22 +01:00
5edf1f801b added default ip address for ip table 2023-04-22 11:24:04 +01:00
4e025bdc70 changed back root ip address 2023-04-14 10:57:58 +01:00
3bcba8a3e2 fixed iptable directory changes 2023-04-14 10:54:24 +01:00
Akilan Selvacoumar
97d10918b1 Merge pull request #95 from farhansolodev/approprirate-abstractions
few small fixes
2023-04-03 21:21:30 +01:00
farhansolodev
d3181d272e revert paths 2023-04-04 00:17:52 +04:00
Farhan Alvi
0550a35df1 Update ip_table.json 2023-04-03 22:55:16 +04:00
farhansolodev
7984f72db1 better wording 2023-04-03 22:50:11 +04:00
farhansolodev
806b499e72 more explicit --rm instructions + erroring out if no --id provided 2023-04-03 22:48:57 +04:00
farhansolodev
cf1e7c6d6f wrong container json file paths 2023-04-03 21:05:57 +04:00
farhansolodev
86aaba23c4 hardcoded default path incorrect 2023-04-03 06:17:19 +04:00
farhansolodev
53bef115b0 fix cyclic dependancy + duplicate test 2023-04-03 06:16:29 +04:00
farhansolodev
fbbb23c13a dead code 2023-04-03 06:15:56 +04:00
farhansolodev
f0496f8184 ran go mod tidy right after cloning 2023-04-03 06:15:45 +04:00
69c0aa5cb1 config abstraction changes added 2023-03-22 09:43:40 +00:00
Akilan Selvacoumar
88dddd0230 Merge pull request #94 from Akilan1999/documentation-NAT-tarversal
Documentation nat tarversal
2023-03-22 07:03:41 +00:00
c9f007a652 base MD file added for NAT traversal 2023-03-22 07:03:04 +00:00
3b70ff5879 pushed changes for base NAT traversal changes 2023-03-14 17:31:50 +00:00
Akilan Selvacoumar
6161b0afa3 Merge pull request #93 from Akilan1999/abstracted-functions
modified server specs to return type ServerSpec instead of interface.
2023-02-24 22:42:31 +00:00
4268b5a637 modified server specs 2023-02-24 22:36:16 +00:00
Akilan Selvacoumar
60a00cbb57 Merge pull request #92 from Akilan1999/abstracted-functions
changes to configuration
2023-02-24 02:54:10 +00:00
35b9e7ea33 changes to configuration 2023-02-24 02:53:30 +00:00
Akilan Selvacoumar
e965adf798 Merge pull request #91 from Akilan1999/flexible-server
Flexible server
2023-02-22 23:12:28 +00:00
1428d324b1 modified README file 2023-02-22 23:10:09 +00:00
c646a1389e added other abstractions documentation to P2PRC 2023-02-22 23:08:11 +00:00
be9de346e5 removed duplicate docker folder 2023-02-22 17:13:51 +00:00
73e62ba0fa docker files 2023-02-22 17:10:14 +00:00
60500620db added base abstraction functions 2023-02-22 03:15:49 +00:00
4dac4234ad added config flixble system 2023-02-22 02:46:11 +00:00
c7a665fdc8 added new module 2023-02-14 20:33:30 +00:00
95 changed files with 3508 additions and 3294 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

25
.gitignore vendored
View File

@@ -11,23 +11,30 @@ config.json
#ignore generated iptables
p2p/iptable/
!p2p/iptable/.gitkeep
#ignore plugins added
plugin/deploy/
!plugin/deploy/.gitkeep
#ignore track container file
client/trackcontainers/
!client/trackcontainers/.gitkeep
# Test generated files
generate/p2prctest
!generate/p2prctest/.gitkeep
generate/Test
!generate/Test/.gitkeep
#ignore windows exe files
*.exe
dist/
# Ignore any sort of logs
logs/
#MACOS .idea file
.DS_Store
.gitkeep
# ignore docker image files
server/docker/containers/
*.h
*.so
# generic folder to ignore
export/
# Any testing file
test*
# Ignore public and private keys
p2prc.publicKey
p2prc.privateKey

170
Bindings/Client.go Normal file
View File

@@ -0,0 +1,170 @@
package main
import "C"
import (
"encoding/json"
"fmt"
"time"
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
// The Client package where data-types
// are manually converted to the
// to a string so that it can
// be export
// --------------------------------- Container Control ----------------------------------------
//export StartContainer
func StartContainer(IP *C.char) (output *C.char) {
container, err := abstractions.StartContainer(C.GoString(IP))
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
//export RemoveContainer
func RemoveContainer(IP *C.char, ID *C.char) (output *C.char) {
err := abstractions.RemoveContainer(C.GoString(IP), C.GoString(ID))
if err != nil {
return C.CString(err.Error())
}
return C.CString("Success")
}
// --------------------------------- Plugin Control ----------------------------------------
// DEPRECATED
////export ViewPlugin
//func ViewPlugin() (output *C.char) {
// plugins, err := plugin.DetectPlugins()
// if err != nil {
// return C.CString(err.Error())
// }
// return ConvertStructToJSONString(plugins)
//}
//
////export PullPlugin
//func PullPlugin(pluginUrl string) (output *C.char) {
// err := plugin.DownloadPlugin(pluginUrl)
// if err != nil {
// return C.CString(err.Error())
// }
// return C.CString("Success")
//}
//
////export DeletePlugin
//func DeletePlugin(pluginName string) (output *C.char) {
// err := plugin.DeletePlugin(pluginName)
// if err != nil {
// return C.CString(err.Error())
// }
// return C.CString("Success")
//}
//
////export ExecutePlugin
//func ExecutePlugin(pluginname string, ContainerID string) (output *C.char) {
// err := plugin.RunPluginContainer(pluginname, ContainerID)
// if err != nil {
// return C.CString(err.Error())
// }
// return C.CString("Success")
//}
// --------------------------------- Get Specs ----------------------------------------
//export GetSpecs
func GetSpecs(IP *C.char) (output *C.char) {
specs, err := abstractions.GetSpecs(C.GoString(IP))
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(specs)
}
//export Init
func Init(customConfig *C.char) (output *C.char) {
init, err := abstractions.Init(C.GoString(customConfig))
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(init)
}
// --------------------------------- P2P Controls -----------------------------------
//export ViewIPTable
func ViewIPTable() (output *C.char) {
table, err := abstractions.ViewIPTable()
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(table)
}
//export UpdateIPTable
func UpdateIPTable() (output *C.char) {
err := abstractions.UpdateIPTable()
if err != nil {
return C.CString(err.Error())
}
return C.CString("Success")
}
//export EscapeFirewall
func EscapeFirewall(HostOutsideNATIP *C.char, HostOutsideNATPort *C.char, internalPort *C.char) (output *C.char) {
// Get free port from P2PRC server node
serverPort, err := frp.GetFRPServerPort("http://" + C.GoString(HostOutsideNATIP) + ":" + C.GoString(HostOutsideNATPort))
if err != nil {
return C.CString(err.Error())
}
time.Sleep(5 * time.Second)
ExposedPort, err := frp.StartFRPClientForServer(C.GoString(HostOutsideNATIP)+":"+C.GoString(HostOutsideNATPort), serverPort, C.GoString(internalPort), "")
if err != nil {
return C.CString(err.Error())
}
return C.CString(ExposedPort)
}
//export MapPort
func MapPort(Port *C.char) *C.char {
fmt.Println(C.GoString(Port))
entireAddress, _, err := abstractions.MapPort(C.GoString(Port))
if err != nil {
return C.CString(err.Error())
}
return C.CString(entireAddress)
}
// --------------------------------- Controlling Server ----------------------------------------
//export Server
func Server() (output *C.char) {
_, err := abstractions.Start()
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString("")
}
// --------------------------------- Helper Functions ----------------------------------------
func ConvertStructToJSONString(Struct interface{}) *C.char {
jsonBytes, err := json.Marshal(Struct)
if err != nil {
return C.CString(err.Error())
}
// Convert the JSON bytes to a string
return C.CString(string(jsonBytes))
}
func main() {}

BIN
Bindings/python/.DS_Store vendored Normal file

Binary file not shown.

11
Bindings/python/p2prc.py Normal file
View File

@@ -0,0 +1,11 @@
import ctypes
p2prc = ctypes.CDLL("SharedOBjects/p2prc.so")
p2prc.Init("")
def StartServer():
# Starting P2PRC as a server mode
p2prc.Server()
for _ in iter(int, 1):
pass

View File

@@ -5,5 +5,5 @@ authors:
given-names: Akilan
title: P2PRC
license: "GPL-2.0"
version: 1.0.0
date-released: 2021-07-22
version: 2.0.0
date-released: 2023-06-08

BIN
Docs/.DS_Store vendored Normal file

Binary file not shown.

20
Docs/Abstractions.md Normal file
View File

@@ -0,0 +1,20 @@
# Abstractions
| [◀ Previous](Installation.md) | [Next ▶](Implementation.md) |
|:-----------:|---------|
The Abstractions package consists of black-boxed functions for P2PRC.
## Functions
- ```Init(<Project name>)```: Initializes P2PRC with all the needed configurations.
- ```Start()```: Starts p2prc as a server and makes it possible to extend by adding other routes and functionality to P2PRC.
- ```MapPort(<port no>)```: On the local machine the port you want to export to world.
- ```StartContainer(<ip address>)```: The machine on the p2p network where you want to spin up a docker container.
- ```RemoveContainer(<ip address>,<container id>)```: Terminate container based on the IP address and container name.
- ```GetSpecs(<ip address>)```: Get specs of a machine on the network based on the IP address.
- ```ViewIPTable()```: View the IP table which about nodes in the network.
- ```UpdateIPTable()```: Force update IP table to learn about new nodes faster.
---
### Next Chapter: [Implementation](Implementation.md)

139
Docs/Bindings.md Normal file
View File

@@ -0,0 +1,139 @@
# Language Bindings
[Language bindings](https://en.wikipedia.org/wiki/Language_binding) refers to wrappers to bridge 2 programming languages. This is used in P2PRC to extend calling P2PRC functions in other programming languages. Currently this is done by generating ```.so``` and ```.h``` from the Go compiler.
<br>
## How to build shared object files
#### The easier way
```bash
# Run
make sharedObjects
```
#### Or the direct way
```bash
# Run
cd Bindings && go build -buildmode=c-shared -o p2prc.so
```
#### If successfully built:
```bash
# Enter into the Bindings directory
cd Bindings
# List files
ls
# Find files
p2prc.h p2prc.so
```
<br>
## Workings under the hood
Below are a sample set of commands to
open the bindings implementation.
```
# run
cd Bindings/
# list files
ls
# search for file
Client.go
```
### In Client go
There a few things to notice which are different from
your standard Go programs:
#### 1. We import "C" which means [Cgo](https://pkg.go.dev/cmd/cgo) is required.
```go
import "C"
```
#### 2. All functions which are required to be called from other programming languages have comment such as.
```go
//export <function name>
// ------------ Example ----------------
// The function below allows to externally
// to call the P2PRC function to start containers
// in a specific node in the know list of nodes
// in the p2p network.
// Note: the comment "//export StartContainer".
//export StartContainer
func StartContainer(IP string) (output *C.char) {
container, err := client.StartContainer(IP, 0, false, "", "")
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
```
#### 3. While looking through the file (If 2 files are compared it is pretty trivial to notice a common structure).
```go
// --------- Example ------------
//export StartContainer
func StartContainer(IP string) (output *C.char) {
container, err := client.StartContainer(IP, 0, false, "", "")
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
//export ViewPlugin
func ViewPlugin() (output *C.char) {
plugins, err := plugin.DetectPlugins()
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(plugins)
}
```
#### It is easy to notice that:
- ```ConvertStructToJSONString(<go object>)```: This is a helper function that convert
a go object to JSON string initially and converts it to ```CString```.
- ```(output *C.char)```: This is the return type for most of the functions.
#### A Pseudo code to refer to the common function implementation shape could be represented as:
```
func <Function name> (output *C.char) {
<response>,<error> := <P2PRC function name>(<parameters if needed>)
if <error> != nil {
return C.CString(<error>.Error())
}
return ConvertStructToJSONString(<response>)
}
```
<br>
## Current languages supported
- Python
### Build sample python program
The easier way
```bash
# Run
make python
# Expected ouput
Output is in the Directory Bindings/python/export/
# Run
cd Bindings/python/export/
# list files
ls
# Expected output
SharedObjects/ p2prc.py
```
Above shows a generated folder which consists of a folder
called "SharedObjects/" which consists of ```p2prc.so```
and ```p2prc.h``` files. ```p2prc.py``` refers to a
sample python script calling P2PRC go functions.
To start an any project to extend P2PRC with python,
This generated folder can copied and created as a new
git repo for P2PRC extensions scripted or used a reference
point as proof of concept that P2PRC can be called from
other programming languages.

View File

@@ -6,7 +6,7 @@ commands as possible. The cli was built using the library called urfave cli v2 .
major files created named as flags.go and actions.go.
### Flags.go
The flags .go file is responsible to create the appropriate flags for the cli. There are 2 types of flags
called boolean and string as described in Fig 5.3.1. Each of the flags outputs are assigned to a
called boolean and string. Each of the flags outputs are assigned to a
variable to be handled. The flags can also detect environment variables set. This feature is useful
because if the user wants to call certain flags in a repeated sequence it only has to be initialized
once.
@@ -14,4 +14,4 @@ once.
### Actions.go
The actions.go file is implemented to call the appropriate functions when the flags are called. It
interacts directly with the modules in the project. Action.go checks if variables
are not empty string or the boolean value is true.
are not empty string or the boolean value is true.

View File

@@ -1,25 +1,13 @@
# Client Module
This module is incharge of communicating with the server and receiving the appropriate information back from the server.
Note: To [read more about the functions](https://pkg.go.dev/git.sr.ht/~akilan1999/p2p-rendering-computation@v0.0.0-20210404191839-6a046babcb02/client)
## Functions of the Client Module
- [Interact with the Server Api](#functions-of-the-client-module)
<!-- - [Interact with the Server Api](#functions-of-the-client-module) -->
- [Decision maker on how the ip table is created or updated](#decision-maker-on-how-the-ip-table-is-created-or-updated)
## Interact with the Server Api
This sections talks about the functionality implemented till now.
- The client can start docker containers using the function StartContainer.
This functions calls the route:
```
http://<server IP address>:<server port>/startcontainer
```
TODO: Outputs and how it's printed
## Decision maker on how the IP table is created or updated
- Does a local speedtest to verify and see if the server IP's in the IP table
are pingable.
- Downloads the Servers IP table.
- Tries to ping the servers IP Table addresses.
- If it's pingable then it's added as a new entry in the IP table.
- The following steps occurs in the clients IP table.

View File

@@ -1,5 +1,10 @@
# Client Module Implementation
The Client Module interacts with the P2P module and Server Module. It is responsible for interacting with the server module and appropriately updating the IP table on the client side. It connects to the server using the server's REST Apis. It is also the primary decision maker on how the IP table is updated is on the client side. This is because each user can have requirements like how many number of hops they would want to do to update their IP table. Hops is the number of times the client is going to download the IP table from different servers ,once it gets the IP tables from the previous servers.
![Visual demonstration of hops](images/NumOfHops.png)
![UML diagram of client module](images/clientmoduleArch.png)
## Topics
1. [Updating the IP table](#updating-the-IP-table)
2. [Reading server specifications](#reading-server-specifications)
@@ -78,8 +83,6 @@ show a sample structure of file ```grouptrackcontainer.json```.
```
The default path to the container tracker is ```client/trackcontainers/grouptrackcontainer.json```.
### Note:
The group id will be auto-generated and will have its own prefix in the start which will mostly be ```grp<UUID>```.
When a container is removed using the command. ```p2prc --rm <IP Address> --id <Container id>```. It will be automatically deleted
from the groups it exists in.
> [!NOTE]
> The group id will be auto-generated and will have its own prefix in the start which will mostly be ```grp<UUID>```.
> When a container is removed using the command. ```p2prc --rm <IP Address> --id <Container id>```. It will be automatically deleted from the groups it exists in.

View File

@@ -13,9 +13,19 @@ JSON format.
```json
{
"dockerfile": "/<path>/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/",
"iptable": "/<path>/p2p-rendering-computation/p2p/ip_table.json",
"speedtestfile": "/<path>/p2p-rendering-computation/p2p/50.bin"
"MachineName": "pc-74-120.customer.ask4.lan",
"IPTable": "/Users/akilan/Documents/p2p-rendering-computation/p2p/iptable/ip_table.json",
"DockerContainers": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/",
"DefaultDockerFile": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/",
"SpeedTestFile": "/Users/akilan/Documents/p2p-rendering-computation/p2p/50.bin",
"IPV6Address": "",
"PluginPath": "/Users/akilan/Documents/p2p-rendering-computation/plugin/deploy",
"TrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/trackcontainers.json",
"ServerPort": "8088",
"GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json",
"FRPServerPort": "True",
"BehindNAT": "True",
"CustomConfig": null
}
```

View File

@@ -1,116 +0,0 @@
# Generate Module
P2PRC is a great layer of abstraction. This means that in many cases it is not an end product but rather
a tool that customized as an end product. An example would be writing your own billing module to monetize
the computation power available. The generate module copies the current with the appropriate git histories
and keeps only the go files which would be useful to edit. To use the generate module the user will need
to have a go compiler present in his computer. Due to the introduction of this module there will 2 releases:
- Regular Release (Consists of only the build binary and cli command cannot access the generate module)
- Developer Release (Consists of important Go files and the cli can access the generate module)
## How does this work ?
### [Struct information](https://github.com/Akilan1999/p2p-rendering-computation/blob/9d69aed8ce0fe5273aaff2828f7d51c3d5ac2ce4/generate/generate.go#L19)
- ### ```Generate.go```:
This file creates a local copy of P2PRC from where the CLI was called from.
This go file also does various stuff like instruction of file should be ignored when copying and
which of should not be. Now let's understand this. Below is a sample code which does the following:
```go
//----------------------------------------------------------------
// Action performed:
// - Ensuring main.go file exists
// - Skipping all .go files apart from the ones listed above
// - Skipping .idea/ directory
// - Skipping Makefile file
//----------------------------------------------------------------
Options.Skip = func(src string) (bool, error) {
switch {
case strings.HasSuffix(src, "main.go"):
return false, nil
case strings.HasSuffix(src, ".go"):
return true, nil
case strings.HasSuffix(src, ".idea"):
return true, nil
case strings.HasSuffix(src, "Makefile"):
return true, nil
default:
return false, nil
}
}
// Doing the copy
err = copy.Copy("<P2PRC folder you want to copy from>", "<PATH to the directory>", Options)
```
Unfortunately currently this will have to be manually edited in the ```Generate.go``` file. When using the generate
module the user also creates their own Go module which is the modified version of P2PRC. This means
if the 1 modified package is using another modified package then the appropriate import have to be modified
in the file where the import is called:
Ex:
```go
//Sample Project module name = Test
//Package names:
//- Test/Genius
//- Test/GeGeGenuis
//
// When we call the generate function with the new project with the module name = MicDrop
// The new package name would be:
// - MicDrop/Genius
// - MicDrop/GeGeGenuis
// Test/Genius code depends on the package Test/GeGeGenuis
import (
"Test/GeGeGenuis"
)
// When we create a new module with the copy of the
// existing project we need change:
import (
"MicDrop/GeGeGenuis"
)
```
To do this we have built functions which can modify import names in the Go file provided.
To customize the use case of your generate module you would need to manually add your own
imports which are supposed to be replaced and in which files they are supposed to be replaced
in.
```go
// 1.0 - Test/Genius.go -> GeGeGenuis module
// a is struct of type NewProject
a.FileNameAST = "<path to project to copy from>/Test/Genius.go"
// Get AST information of the file
err := a.GetASTGoFile()
if err != nil {
return err
}
// Change the appropriate Go file
err = a.ChangeImports("Test/GeGeGenuis", "MicDrop/GeGeGenuis")
if err != nil {
return err
}
// Writes the change to the appropriate file
err = a.WriteGoAst()
if err != nil {
return err
}
```
Higher order of execution of ```Generate.go```:
1. Copy entire P2PRC project and ignores files which are not meant to be copied
2. The folder name will be based on the new project name and the module name based on the new
module name provided.
3. Modifies the appropriate imports in the project as instructed in the code.
4. Creates a commit with the new changes in the new project.
- ### ``` modifyGenerate.go```:
This a really simple implementation where we replace the imports
in certain files as instructed from ```generate.go```. To do we create an AST (i.e Abstract Syntax tree)
from new file we want to change the imports in. AST create a tree structure of expression. To change the
import we can just traverse to the appropriate expression and change the value of that expression in
the case of modifying imports. This approach is more simple than using templates.

View File

@@ -1,20 +1,23 @@
# Implementation
# Implementation
| [◀ Previous](Introduction.md) | [Back to TOC](README.md) |
|:-----------:|---------|
This chapter describes how the project was built. It talks in depth of the implementation
performed to give a better understanding of the project.
## Programming langauge used
The programming language used for this project was Golang. The reason Go lang was chosen was
because it is a compiled language.
The programming language used for this project was [Golang](https://go.dev/). The reason Go lang was chosen was
because it is a compiled language.<br>
The entire codebase is just a single binary file. When
distributing to other linux distributing the only requirement would be the binary file to run the
code. It is easy to write independant modules and be monolithic at the sametime using Go. Using
Go.mod makes it very easy to handle external libraries and modularise code. The go.mod name for
the project is git.sr.ht/~akilan1999/p2p-rendering-computation.
code. It is easy to write independant modules and be monolithic at the sametime using Go.<br>
Using Go.mod makes it very easy to handle external libraries and modularise code. The go.mod name for
the project is [git.sr.ht/~akilan1999/p2p-rendering-computation](https://git.sr.ht/~akilan1999/p2p-rendering-computation).
## [Cli Module](CliImplementation.md)
## [Config Module](ConfigImplementation.md)
## [Server Module](ServerImplementation.md)
## [Client Module](ClientImplementation.md)
## [P2P Module](P2PImplementation.md)
## [Plugin Module](PluginImplementation.md)
## [Generate Module](GenerateImplementation.md)
- ## [Cli Module](CliImplementation.md)
- ## [Config Module](ConfigImplementation.md)
- ## [Server Module](ServerImplementation.md)
- ## [Client Module](ClientImplementation.md)
- ## [P2P Module](P2PImplementation.md)
- ## [Plugin Module](PluginImplementation.md)
- ## [Generate Module](GenerateImplementation.md)

View File

@@ -1,9 +1,12 @@
# Installation
# Installation
| [◀ Previous](Introduction.md) | [Next ▶](Abstractions.md) |
|:-----------:|---------|
Over here we will cover the basic steps to get the server and client side running.
## Alpha release install
https://github.com/Akilan1999/p2p-rendering-computation/releases/tag/v1.0.0-alpha
## Latest release install
https://github.com/Akilan1999/p2p-rendering-computation/releases
## Install from Github master branch
@@ -39,7 +42,7 @@ To set up P2PRC on Windows, simply run this batch file.
.\install.bat
```
### Add appropriate paths to .bashrc
### Add appropriate paths to `.bashrc`
```
export P2PRC=/<PATH>/p2p-rendering-computation
export PATH=/<PATH>/p2p-rendering-computation:${PATH}
@@ -65,7 +68,7 @@ USAGE:
p2prc [global options] command [command options] [arguments...]
VERSION:
1.0.0
2.0.0
COMMANDS:
help, h Shows a list of commands or help for one command
@@ -78,7 +81,8 @@ GLOBAL OPTIONS:
--ViewImages value, --vi value View images available on the server IP address [$VIEW_IMAGES]
--CreateVM value, --touch value Creates Docker container on the selected server [$CREATE_VM]
--ContainerName value, --cn value Specifying the container run on the server side [$CONTAINER_NAME]
--RemoveVM value, --rm value Stop and Remove Docker container [$REMOVE_VM]
--BaseImage value, --bi value Specifying the docker base image to template the dockerfile [$CONTAINER_NAME]
--RemoveVM value, --rm value Stop and Remove Docker container (IP:port) accompanied by container ID via --ID or --id [$REMOVE_VM]
--ID value, --id value Docker Container ID [$ID]
--Ports value, -p value Number of ports to open for the Docker Container [$NUM_PORTS]
--GPU, --gpu Create Docker Containers to access GPU (default: false) [$USE_GPU]
@@ -86,10 +90,23 @@ GLOBAL OPTIONS:
--SetDefaultConfig, --dc Sets a default configuration file (default: false) [$SET_DEFAULT_CONFIG]
--NetworkInterfaces, --ni Shows the network interface in your computer (default: false) [$NETWORK_INTERFACE]
--ViewPlugins, --vp Shows plugins available to be executed (default: false) [$VIEW_PLUGIN]
--TrackedContainers, --tc View containers which have been created from the client side (default: false) [$TRACKED_CONTAINERS]
--TrackedContainers, --tc View (currently running) containers which have been created from the client side (default: false) [$TRACKED_CONTAINERS]
--ExecutePlugin value, --plugin value Plugin which needs to be executed [$EXECUTE_PLUGIN]
--CreateGroup, --cgroup Creates a new group (default: false) [$CREATE_GROUP]
--Group value, --group value group flag with argument group ID [$GROUP]
--Groups, --groups View all groups (default: false) [$GROUPS]
--RemoveContainerGroup, --rmcgroup Remove specific container in the group (default: false) [$REMOVE_CONTAINER_GROUP]
--RemoveGroup value, --rmgroup value Removes the entire group [$REMOVE_GROUP]
--MAPPort value, --mp value Maps port for a specific port provided as the parameter [$MAPPORT]
--DomainName value, --dn value While mapping ports allows to set a domain name to create a mapping in the proxy server [$DOMAINNAME]
--Generate value, --gen value Generates a new copy of P2PRC which can be modified based on your needs [$GENERATE]
--ModuleName value, --mod value New go project module name [$MODULENAME]
--PullPlugin value, --pp value Pulls plugin from git repos [$PULLPLUGIN]
--RemovePlugin value, --rp value Removes plugin [$REMOVEPLUGIN]
--AddMetaData value, --amd value Adds metadata about the current node in the p2p network which is then propagated through the network [$ADDMETADATA]
--help, -h show help (default: false)
--version, -v print the version (default: false)
```
<br>
@@ -101,7 +118,7 @@ GLOBAL OPTIONS:
# Using basic commands
### Start as a server
Do ensure you have docker installed for this
Do ensure you have Docker installed for this
```
p2prc -s
```
@@ -195,6 +212,16 @@ p2prc --pp <repo link>
p2prc --rp <plugin name>
```
### Added custom metadata about the current node
```
p2prc --amd "custom metadata"
```
### Map port
```
p2prc --mp <internal port no from your machine> --dn <domain name you want the port linked to>
```
<br>
--------------
@@ -209,24 +236,18 @@ This feature is still Under Development:
- Ansible:
- Debian/ubuntu: ```sudo apt install ansible```
- Others: [Installation link](https://ansible-tips-and-tricks.readthedocs.io/en/latest/ansible/install/)
#### Set ansible host_key_checking to false
- On linux
- ```sudo nano /etc/ansible/ansible.cfg```: Open the following file. If this file is not found then where
ever the file ```ansible.cfg``` is located.
- Add or uncomment ```host_key_checking = False```
#### Run Test Cases
- Generate Test Case Ansible file
- ```make testcases```
- Enter inside plugin directory and run tests.
Note: That docker needs to installed and needs to run without
sudo. Refer the section install Docker.
- ```cd plugin```
- ```go test .```
- Enter inside plugin directory and run tests.<br>
> [!NOTE]
> That docker needs to installed and needs to run without
> sudo. Refer the section [Install Docker](#install-docker).
> - ```cd plugin```
> - ```go test .```
---
### Next Chapter: [Abstractions](Abstractions.md)

View File

@@ -1,5 +1,8 @@
# Chapter 1: Introduction
| [◀ Back to TOC](README.md) | [Next ▶](Installation.md) |
|:-----------:|---------|
## Abstract
This project focuses on creating a framework on running heavy tasks that a regular computer
cannot run easily such as graphically demanding video games, rendering 3D animations , protein
@@ -21,7 +24,7 @@ run these heavy tasks can be really useful. Ethically speaking this is leading t
computing power similar to what is happening in the web server area. By using peer to peer
principles it is possible to remove the monopolisation factor and increase the bandwidth between
the client and server.
<!--
## Aim
This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to
act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will
@@ -33,4 +36,8 @@ or virtual environments across selected nodes.
rendering tools and tools to batch any sort of tasks.
- Creating p2p network
- Server to create a containerised environment
- The client node to run tasks on Server containerised node
- The client node to run tasks on Server containerised node -->
---
### Next Chapter: [Installation](Installation.md)

37
Docs/NAT-Traveral.md Normal file
View File

@@ -0,0 +1,37 @@
# NAT Traversal
P2PRC currently supports TURN for NAT traversal.
## TURN
The current TURN implementation used is FRP. The TURN server is also required when
a P2PRC node is acting as a Server. The TURN server is determined based on the Node
with the least amount of latency based on the Nodes available on the IPTable.
Once a TURN server is determined there are 2 actions performed. The first one is
```/FRPPort``` to the TURN server to receive a port which is used to generate the external
port from the TURN server. The flow below describes the workflow.
### Client mode
- Call ```/FRPPort```
```
http://<turn server ip>:<server port no>/FRPport
```
- Call the TURN server in the following manner. The following is a sample code snippet below.
```go
import (
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
func main() {
serverPort, err := frp.GetFRPServerPort("http://" + <lowestLatencyIpAddress.Ipv4> + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return nil, err
}
// Create 1 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, <the port you want to expose externally>)
if err != nil {
return nil, err
}
}
```

View File

@@ -19,11 +19,9 @@ In this repository the P2P module has been designed from sratch at the point of
## Responsibility
- To perform speed test to determine best node to connect
- To ensure the IP table has nodes which are pingable
- Using techniques such as [UPNP](https://en.wikipedia.org/wiki/Universal_Plug_and_Play). Still under development
- Port Forwarding (To be introducted in a future release)
- Taking to nodes behind NAT. [More about the implementation](NAT-Traversal)...
## Note:
If you are running in server mode it is recommended to use [DMZ](https://routerguide.net/when-and-how-to-setup-dmz-host-for-home-use/) to bypass the [NAT](https://en.wikipedia.org/wiki/Network_address_translation).
> [!NOTE]
> If you are running in server mode it is recommended to use [DMZ](https://routerguide.net/when-and-how-to-setup-dmz-host-for-home-use/) to bypass the [NAT](https://en.wikipedia.org/wiki/Network_address_translation).

View File

@@ -1,10 +1,20 @@
# P2P Module Implementation
The P2P module (i.e Peer to Peer Module) is responsible for storing the IP table and interacting
with the IP table. In the following implementation of the P2P module ,the IP table stores
information about servers available in the network. The other functionality the P2P module takes
care of is doing the appropriate speed tests to the servers in the IP table. This is for informing the
users about nodes which are close by and nodes which have quicker uploads and downloads
speeds. The module is responsible to ensure that there are no duplicate server IPs in the IP table
and to remove all server IPs which are not pingable.
![UML diagram of P2P module](images/p2pmoduleArch.png)
The peer to peer implementation was built from scratch. This is because other peer to peer
libraries were on the implementation of the Distributed hash table. At the current moment all
those heavy features are not needed because the objective is to search and list all possible servers
available. The limitation being that to be a part of the network the user has to know at least 1
server and has to have DMZ enabled from the router if the user wants to act as a server out of the
users local network. The advantage of building from scratch makes the module super light and
server. The advantage of building from scratch makes the module super light and
possibility for custom functions and structs. The sub topics below will mention the
implementations of each functionality in depth.
@@ -23,27 +33,53 @@ path of the IP table json file is received from the configuration module.
"latency": "<latency>",
"download": "<download>",
"upload": "<upload>"
"port no": "<server port no>"
"port no": "<server port no>",
}
]
}
```
## Speed Test
The speed test functions populate the fields which are latency, download, upload speed. Before the
speed test begins for each server IP address. The p2p module ensures that each server IP address
is pingable. If the server IP address is not pingable then it removes that IP address from the struct.
### Latency
The latency is measured in milliseconds. The route /server_info is called from the
server and time it takes to provide a json response is recorded.
### Download speed
The download speed is measured as (<file size>/<time taken to
download>)*8. This gives the result in megabits per second. The file downloaded is a 50 mb
auto generated file.
## NAT Traversal
P2PRC currently supports TURN for NAT traversal.
## TURN
The current TURN implementation used is FRP. The TURN server is also required when
a P2PRC node is acting as a Server. The TURN server is determined based on the Node
with the least amount of latency based on the Nodes available on the IPTable.
Once a TURN server is determined there are 2 actions performed. The first one is
```/FRPPort``` to the TURN server to receive a port which is used to generate the external
port from the TURN server. The flow below describes the workflow.
### Client mode
- Call ```/FRPPort```
```
http://<turn server ip>:<server port no>/FRPport
```
- Call the TURN server in the following manner. The following is a sample code snippet below.
```go
import (
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
func main() {
serverPort, err := frp.GetFRPServerPort("http://" + <lowestLatencyIpAddress.Ipv4> + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return nil, err
}
// Create 1 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, <the port you want to expose externally>)
if err != nil {
return nil, err
}
}
```
### Upload speed
The upload speed is measured as (<file size>/<time taken to upload>)*8. This
gives the results in megabits per second. The file uploaded is a 50 mb auto generated file.
The route /upload is called from the server side to upload the file.

View File

@@ -54,22 +54,23 @@ nodes to execute Ansible instructions. In this project this file needs to be set
go code or binary will populate this file automatically with the appropriate information required to connect to local or
remote containers.
#### Note: Add as exactly specified below
```
all:
vars:
ansible_python_interpreter: /usr/bin/python3 // Path to your python 3 interpreter
main:
hosts:
host1:
// Note: These values will be automatically overwritten
// by the Go functions
ansible_host: 0.0.0.0
ansible_port: 39269
ansible_user: master
ansible_ssh_pass: password
ansible_sudo_pass: password
```
> [!NOTE]
> Add as exactly specified below:
> ```
>all:
> vars:
> ansible_python_interpreter: /usr/bin/python3 // Path to your python 3 interpreter
>main:
> hosts:
> host1:
> // Note: These values will be automatically overwritten
> // by the Go functions
> ansible_host: 0.0.0.0
> ansible_port: 39269
> ansible_user: master
> ansible_ssh_pass: password
> ansible_sudo_pass: password
>```
## Ports.json
The ```ports.json``` file is intended to mention the number of ports required

View File

@@ -1,35 +0,0 @@
# Problems in implementation
### Number of Devices in the network:
The current implementation has the major flaw which is that
the server has to be in port 8088 to detected in the public
network. As we know most personal networks have a single IP
address. This means we cannot have duplicate ports. A fix can
be to mention the open port on the IP table file.
(Ex: Possible feild to be added)
```
{
"ip_address": [
{
"ipv4": "localhost",
"latency": 14981051,
"download": 8142.122540206258,
"upload": 3578.766512629995,
"port": 8088
}
]
}
```
### Broadcast of container specs
At the moment the container specs are not broadcasted rather
just the machines specs and this module has yet to be tested
rigorously.
### Intergration with GPU
Certain machines have GPUs present in them which provide a
huge advantage for those who want to do rendering and certain
sort of computation. The Aim is to only allow it to be compatible
with Nvidia. But an better idea would be to provide compatability
with multiple GPU providers.

View File

@@ -2,10 +2,11 @@
# Table of contents
1. [Introduction](Introduction.md)
2. [Installation](Installation.md)
3. [Design Architecture](DesignArchtectureIntro.md)
3. [Abstractions](Abstractions.md)
<!-- 3. [Design Architecture](DesignArchtectureIntro.md)
1. [Client Module](ClientArchitecture.md)
2. [P2P Module](P2PArchitecture.md)
3. [Server Module](ServerArchitecture.md)
3. [Server Module](ServerArchitecture.md) -->
4. [Implementation](Implementation.md)
1. [Client Module](ClientImplementation.md)
2. [P2P Module](P2PImplementation.md)
@@ -13,6 +14,6 @@
4. [Config Module](ConfigImplementation.md)
5. [Cli Module](CliImplementation.md)
6. [Plugin Module](PluginImplementation.md)
7. [Generate Module](GenerateImplementation.md)
5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues)
7. [Language bindings](Bindings.md)
<!-- 5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues) -->

View File

@@ -4,6 +4,14 @@ This section focuses on an in-depth understanding of the server module implement
understand the architecture of the server module refer. The server module can be split
into various sections. Each section will provide information on how a certain feature works.
The server module takes care of setting and removing the virtualization environment (i.e
containers) for accessing and doing the appropriate computation. It also interacts with the peer to
peer module to update the IP table on the server side. The server module
accesses information regarding CPU and GPU specifications of the machine running the server
module. To do Speed tests the server has routes which allows it to upload and download a 50mb.
![UML diagram of server module](images/servermoduleArch.png)
## Web framework
The web framework used for the server module is called Gin. The reason Gin was chosen is due to
its wide use and strong documentation available on the official github repository. The default

View File

@@ -9,3 +9,12 @@ testcases:
run:
go run main.go
sharedObjects:
sh build-bindings.sh
python:
sh build-python-package.sh
clean:
go clean -modcache
rm -fr .go-build vendor result*

View File

@@ -1,3 +1,6 @@
> [!NOTE]
> Fixing documentation to latest changes. If you have any questions setting up P2PRC either [create an issue](https://github.com/Akilan1999/p2p-rendering-computation/issues/new/choose) or send me an email (me AT akilan dot io).
> Currently HEAD is always intended to stay on a working state. It is recommended to always use HEAD in your go.mod file.
<h1 align="center">
<br>
@@ -18,20 +21,40 @@ The main aim of this project was to create a custom peer to peer network. The us
client has total flexibility on how to batch the tasks and the user acting as the server has complete
flexibility on tracking the container's usages and killing the containers at any point of time.
## Gophers talk
[![IMAGE ALT TEXT](https://i.ytimg.com/vi/ovcZLEhQxWk/hqdefault.jpg)](https://www.youtube.com/watch?v=ovcZLEhQxWk "P2PRC - Gophers monthly talk")
## Latest tutorial
[![IMAGE ALT TEXT](https://i.ytimg.com/vi/OMwCpedu5cs/hqdefault.jpg)](https://www.youtube.com/watch?v=OMwCpedu5cs")
<br>
## Table of contents
## Table of contents in the current README
1. [Introduction](#Introduction)
2. [Installation](#Installation.md)
2. [Installation](#extend-your-application-with-p2prc)
3. [Design Architecture](#Design-Architecture)
4. [Implementation](#Implementation)
5. [Find out more](#Find-out-more)
<br>
# Table of contents in the Docs folder
1. [Introduction](Docs/Introduction.md)
2. [Installation](Docs/Installation.md)
3. [Abstractions](Docs/Abstractions.md)
<!-- 3. [Design Architecture](DesignArchtectureIntro.md)
1. [Client Module](ClientArchitecture.md)
2. [P2P Module](P2PArchitecture.md)
3. [Server Module](ServerArchitecture.md) -->
4. [Implementation](Docs/Implementation.md)
1. [Client Module](Docs/ClientImplementation.md)
2. [P2P Module](Docs/P2PImplementation.md)
3. [Server Module](Docs/ServerImplementation.md)
4. [Config Module](Docs/ConfigImplementation.md)
5. [Cli Module](Docs/CliImplementation.md)
6. [Plugin Module](Docs/PluginImplementation.md)
7. [Language Bindings](Docs/Bindings.md)
<!-- 5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues) -->
<br>
## Introduction
This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will be developed, which comes bundled with a p2p module and possible to execute docker containers or virtual environments across selected nodes.
@@ -45,6 +68,44 @@ This project aims to create a peer to peer (p2p) network, where a user can use t
<br>
## Extend your application with P2PRC
```go
package main
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
)
func main() {
_, err := abstractions.Init(nil)
if err != nil {
fmt.Println(err)
return
}
// start p2prc
_, err = abstractions.Start()
if err != nil {
fmt.Println(err)
return
}
// Run server till termination
for {
}
}
```
### Export once this is added export P2PRC as environment paths
```
export P2PRC=<PROJECT PATH>
export PATH=<PROJECT PATH>:${PATH}
```
[Read more](Docs/Abstractions.md) ...
## Installation from source
1. Ensure the Go compiler is installed
```
@@ -101,4 +162,3 @@ or just providing feedback on new features to build or even just curious about
[![Support Server](https://discordapp.com/api/guilds/854397492795277322/widget.png?style=banner2)](https://discord.gg/b4nRGTjYqy)
[![Star History Chart](https://api.star-history.com/svg?repos=Akilan1999/p2p-rendering-computation&type=Date)](https://github.com/Gaurav-Gosain)

88
abstractions/base.go Normal file
View File

@@ -0,0 +1,88 @@
package abstractions
import "C"
import (
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
Config "github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/server"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"github.com/gin-gonic/gin"
"os"
)
// Init Initialises p2prc
func Init(customConfig interface{}) (config *Config.Config, err error) {
// Get config file path
// Checks P2PRC path initially
// - Get PATH if environment varaible
path, err := Config.GetPathP2PRC("P2PRC")
if err != nil {
return
}
// check if the config file exists
if _, err = os.Stat(path + "config.json"); err != nil {
// Initialize with base p2prc config files
// set the config file with default paths
config, err = generate.SetDefaults("P2PRC", false, customConfig, false)
if err != nil {
return
}
} else {
// If the configs are available then use them over generating new ones.
config, err = Config.ConfigInit(nil, nil)
if err != nil {
return
}
}
return
}
// Start p2prc in a server mode
func Start() (*gin.Engine, error) {
engine, err := server.Server()
if err != nil {
return nil, err
}
return engine, nil
}
// MapPort Creates a reverse proxy connection and maps the appropriate port
func MapPort(port string) (entireAddres string, mapPort string, err error) {
entireAddres, mapPort, err = server.MapPort(port)
return
}
// StartContainer Starts docker container on the remote machine
func StartContainer(IP string) (container *docker.DockerVM, err error) {
container, err = client.StartContainer(IP, 0, false, "", "")
return
}
// RemoveContainer Removes docker container based on the IP address and ID
// provided
func RemoveContainer(IP string, ID string) error {
return client.RemoveContianer(IP, ID)
}
// GetSpecs Get spec information about the remote server
func GetSpecs(IP string) (specs *server.SysInfo, err error) {
specs, err = client.GetSpecs(IP)
return
}
// ViewIPTable View information of nodes in the network
func ViewIPTable() (table *p2p.IpAddresses, err error) {
table, err = p2p.ReadIpTable()
return
}
// UpdateIPTable Force updates IP tables based on new
// new nodes discovered in the network
func UpdateIPTable() (err error) {
return clientIPTable.UpdateIpTableListClient()
}

BIN
artwork/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -4,13 +4,11 @@
## Pure HTML Version of the p2prc Logo :)
![p2prc Logo](https://user-images.githubusercontent.com/55647468/204634868-07e94b6d-65f5-4446-a11f-7a14f11edff9.png)
> Note: To change the size of the logo simply edit the CSS variable of `--size` under the `style` tag!
> [!NOTE]
> To change the size of the logo simply edit the CSS variable of `--size` under the `style` tag!
---
### Embedding the HTML as a `foreignObject` element inside an SVG directly
![](embed.svg)

BIN
artwork/p2prc-logos/.DS_Store vendored Normal file

Binary file not shown.

1
build-bindings.sh Normal file
View File

@@ -0,0 +1 @@
cd Bindings && go build -buildmode=c-shared -o p2prc.so

28
build-python-package.sh Normal file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/bash
# Create export directory for python
mkdir Bindings/python/export
# Creating SharedObjects directory for python
mkdir Bindings/python/export/SharedObjects
sh build-bindings.sh
cp Bindings/p2prc.h Bindings/python/export/SharedObjects/
cp Bindings/p2prc.so Bindings/python/export/SharedObjects/
cp Bindings/python/p2prc.py Bindings/python/export/
echo "Output is in the Directory Bindings/python/export/"
# Architectures for Linux
#archs=(amd64 arm64)
#
#for arch in ${archs[@]}
#do
# mkdir Bindings/python/export/SharedObjects/linux-${arch}
# cd Bindings/
# env GOOS=linux GOARCH=${arch} go build -buildmode=c-shared -o python/export/SharedObjects/linux-${arch}/p2prc.so
# echo "GOOS=linux GOARCH=${arch} go build -buildmode=c-shared -o python/export/SharedObjects/linux-${arch}/p2prc.so"
# cd ..
#done

View File

@@ -1,310 +1,310 @@
package client
import (
"encoding/json"
"errors"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/google/uuid"
"io/ioutil"
"os"
"encoding/json"
"errors"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/google/uuid"
"io/ioutil"
"os"
)
// Groups Data Structure type
type Groups struct {
GroupList []*Group `json:"Groups"`
GroupList []*Group `json:"Groups"`
}
// Group Information about a single group
type Group struct {
ID string `json:"ID"`
TrackContainerList []*TrackContainer `json:"TrackContainer"`
// Sneaky as required only when removing the element
// Set when GetGroup function is called
index int
ID string `json:"ID"`
TrackContainerList []*TrackContainer `json:"TrackContainer"`
// Sneaky as required only when removing the element
// Set when GetGroup function is called
index int
}
// CreateGroup Creates a new group to add a set of track containers
func CreateGroup() (*Group, error) {
// Creating variable of type new group
var NewGroup Group
// Generate new UUID for group ID
id := uuid.New()
// Add new group id and prepend with the string "grp"
// The reason this is done is to differentiate between a
// group ID and docker container ID
NewGroup.ID = "grp" + id.String()
// Adding the new group to the
// GroupTrackContainer File
err := NewGroup.AddGroupToFile()
if err != nil {
return nil, err
}
// Creating variable of type new group
var NewGroup Group
// Generate new UUID for group ID
id := uuid.New()
// Add new group id and prepend with the string "grp"
// The reason this is done is to differentiate between a
// group ID and docker container ID
NewGroup.ID = "grp" + id.String()
// Adding the new group to the
// GroupTrackContainer File
err := NewGroup.AddGroupToFile()
if err != nil {
return nil, err
}
return &NewGroup, nil
return &NewGroup, nil
}
// RemoveGroup Removes group based on the group ID provided
func RemoveGroup(GroupID string) error {
// Read group information from the
//grouptrackcontainer json file
groups, err := ReadGroup()
if err != nil {
return err
}
// Gets Group struct based on group ID
// provided
group, err := GetGroup(GroupID)
if err != nil {
return err
}
// Remove Group struct from the groups variable
groups.GroupList = append(groups.GroupList[:group.index], groups.GroupList[group.index+1:]...)
// Read group information from the
//grouptrackcontainer json file
groups, err := ReadGroup()
if err != nil {
return err
}
// Gets Group struct based on group ID
// provided
group, err := GetGroup(GroupID)
if err != nil {
return err
}
// Remove Group struct from the groups variable
groups.GroupList = append(groups.GroupList[:group.index], groups.GroupList[group.index+1:]...)
// Write new groups to the grouptrackcontainer json file
err = groups.WriteGroup()
if err != nil {
return err
}
// Write new groups to the grouptrackcontainer json file
err = groups.WriteGroup()
if err != nil {
return err
}
return nil
return nil
}
// AddContainerToGroup Adds container information to the Group based on the Group ID
func AddContainerToGroup(ContainerID string, GroupID string) (*Group, error) {
// Gets container information based on container ID provided
containerInfo, err := GetContainerInformation(ContainerID)
if err != nil {
return nil, err
}
// Gets group information based on the group ID provided
group, err := GetGroup(GroupID)
if err != nil {
return nil, err
}
// Adds container information the group
group.AddContainer(containerInfo)
// Gets container information based on container ID provided
containerInfo, err := GetContainerInformation(ContainerID)
if err != nil {
return nil, err
}
// Gets group information based on the group ID provided
group, err := GetGroup(GroupID)
if err != nil {
return nil, err
}
// Adds container information the group
group.AddContainer(containerInfo)
// Get Groups information from reading the grouptrackcontainer.json file
groups, err := ReadGroup()
if err != nil {
return nil, err
}
// Updating specific element in the group list with the added container
groups.GroupList[group.index] = group
// Write groups information on the grouptrackcontainer.json file
err = groups.WriteGroup()
if err != nil {
return nil, err
}
// Get Groups information from reading the grouptrackcontainer.json file
groups, err := ReadGroup()
if err != nil {
return nil, err
}
// Updating specific element in the group list with the added container
groups.GroupList[group.index] = group
// Write groups information on the grouptrackcontainer.json file
err = groups.WriteGroup()
if err != nil {
return nil, err
}
return group, nil
return group, nil
}
// RemoveContainerGroup Remove Container from the group ID specified
func RemoveContainerGroup(ContainerID string, GroupID string) (*Group, error) {
// Get container information based on container ID provided
containerInfo, err := GetContainerInformation(ContainerID)
if err != nil {
return nil, err
}
// Gets group information based on the group ID provided
group, err := GetGroup(GroupID)
if err != nil {
return nil, err
}
// Remove container from the appropriate group
err = group.RemoveContainerGroup(containerInfo)
if err != nil {
return nil, err
}
// Get Groups information from reading the grouptrackcontainer.json file
groups, err := ReadGroup()
if err != nil {
return nil, err
}
// Updating specific element in the group list with the remove container
groups.GroupList[group.index] = group
// Write groups information on the grouptrackcontainer.json file
err = groups.WriteGroup()
if err != nil {
return nil, err
}
// Get container information based on container ID provided
containerInfo, err := GetContainerInformation(ContainerID)
if err != nil {
return nil, err
}
// Gets group information based on the group ID provided
group, err := GetGroup(GroupID)
if err != nil {
return nil, err
}
// Remove container from the appropriate group
err = group.RemoveContainerGroup(containerInfo)
if err != nil {
return nil, err
}
// Get Groups information from reading the grouptrackcontainer.json file
groups, err := ReadGroup()
if err != nil {
return nil, err
}
// Updating specific element in the group list with the remove container
groups.GroupList[group.index] = group
// Write groups information on the grouptrackcontainer.json file
err = groups.WriteGroup()
if err != nil {
return nil, err
}
return group, nil
return group, nil
}
// RemoveContainerGroups Remove Container from groups (i.e which ever groups has information
// about that container). This is mostly called when a container is deleted or removed from
// the tracked container list
func RemoveContainerGroups(ContainerID string) error {
// Get container information based on container ID provided
containerInfo, err := GetContainerInformation(ContainerID)
if err != nil {
return err
}
// Get Groups information from reading the grouptrackcontainer.json file
groups, err := ReadGroup()
if err != nil {
return err
}
// Removes container information from all groups it is found in
err = groups.RemoveContainerGroups(containerInfo)
if err != nil {
return err
}
// Write groups information on the grouptrackcontainer.json file
err = groups.WriteGroup()
if err != nil {
return err
}
// Get container information based on container ID provided
containerInfo, err := GetContainerInformation(ContainerID)
if err != nil {
return err
}
// Get Groups information from reading the grouptrackcontainer.json file
groups, err := ReadGroup()
if err != nil {
return err
}
// Removes container information from all groups it is found in
err = groups.RemoveContainerGroups(containerInfo)
if err != nil {
return err
}
// Write groups information on the grouptrackcontainer.json file
err = groups.WriteGroup()
if err != nil {
return err
}
return nil
return nil
}
// GetGroup Gets group information based on
// group id provided
func GetGroup(GroupID string) (*Group, error) {
// Read group information from the
//grouptrackcontainer json file
groups, err := ReadGroup()
if err != nil {
return nil, err
}
// Iterate through the set of groups and
// if the group ID matches then return it
for i, group := range groups.GroupList {
if group.ID == GroupID {
group.index = i
return group, nil
}
}
// Read group information from the
//grouptrackcontainer json file
groups, err := ReadGroup()
if err != nil {
return nil, err
}
// Iterate through the set of groups and
// if the group ID matches then return it
for i, group := range groups.GroupList {
if group.ID == GroupID {
group.index = i
return group, nil
}
}
return nil, errors.New("Group not found. ")
return nil, errors.New("Group not found. ")
}
// AddGroupToFile Adds Group struct to the GroupTrackContainer File
func (grp *Group) AddGroupToFile() error {
// Gets all group information from the
// GroupTrackContainer JSON file
groups, err := ReadGroup()
if err != nil {
return err
}
// Appending the newly created group
groups.GroupList = append(groups.GroupList, grp)
// Writing Group information to the GroupTrackContainer
// JSON file
err = groups.WriteGroup()
if err != nil {
return err
}
// Gets all group information from the
// GroupTrackContainer JSON file
groups, err := ReadGroup()
if err != nil {
return err
}
// Appending the newly created group
groups.GroupList = append(groups.GroupList, grp)
// Writing Group information to the GroupTrackContainer
// JSON file
err = groups.WriteGroup()
if err != nil {
return err
}
return nil
return nil
}
// ReadGroup Function reads grouptrackcontainers.json and converts
// result to Groups
func ReadGroup() (*Groups, error) {
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
return nil, err
}
jsonFile, err := os.Open(config.GroupTrackContainersPath)
// 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()
// read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile)
// we initialize our Users array
var groups Groups
// we unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &groups)
return &groups, nil
// Get Path from config
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
jsonFile, err := os.Open(config.GroupTrackContainersPath)
// 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()
// read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile)
// we initialize our Users array
var groups Groups
// we unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &groups)
return &groups, nil
}
// WriteGroup Function to write type Groups to the grouptrackcontainers.json file
func (grp *Groups) WriteGroup() error {
file, err := json.MarshalIndent(grp, "", " ")
if err != nil {
return err
}
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
return err
}
// Writes to the appropriate file
err = ioutil.WriteFile(config.GroupTrackContainersPath, file, 0644)
if err != nil {
return err
}
return nil
file, err := json.MarshalIndent(grp, "", " ")
if err != nil {
return err
}
// Get Path from config
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
// Writes to the appropriate file
err = ioutil.WriteFile(config.GroupTrackContainersPath, file, 0644)
if err != nil {
return err
}
return nil
}
// AddContainer Adds a container to the Tracked container list of the group
func (grp *Group) AddContainer(Container *TrackContainer) error {
grp.TrackContainerList = append(grp.TrackContainerList, Container)
return nil
grp.TrackContainerList = append(grp.TrackContainerList, Container)
return nil
}
// RemoveContainerGroup Removes container information from the group
func (grp *Group) RemoveContainerGroup(Container *TrackContainer) error {
// Iterating through all container in the Group of Tracked Container
for i, container := range grp.TrackContainerList {
// If the container ID matches then remove the container from the group
if container.Id == Container.Id {
grp.TrackContainerList = append(grp.TrackContainerList[:i], grp.TrackContainerList[i+1:]...)
}
}
return nil
// Iterating through all container in the Group of Tracked Container
for i, container := range grp.TrackContainerList {
// If the container ID matches then remove the container from the group
if container.Id == Container.Id {
grp.TrackContainerList = append(grp.TrackContainerList[:i], grp.TrackContainerList[i+1:]...)
}
}
return nil
}
// RemoveContainerGroups removes container found in all groups
func (grp *Groups) RemoveContainerGroups(Container *TrackContainer) error {
// Iterating through all groups
for i, group := range grp.GroupList {
// Removes the container in the following group
// if it exists
err := group.RemoveContainerGroup(Container)
if err != nil {
return err
}
// Set group information to list groups
grp.GroupList[i] = group
}
return nil
// Iterating through all groups
for i, group := range grp.GroupList {
// Removes the container in the following group
// if it exists
err := group.RemoveContainerGroup(Container)
if err != nil {
return err
}
// Set group information to list groups
grp.GroupList[i] = group
}
return nil
}
// ModifyContainerGroups Modifies container information is all groups
// available
func (TC *TrackContainer) ModifyContainerGroups() error {
group, err := ReadGroup()
if err != nil {
return err
}
// Iterate though all groups and modify the container
// information in groups where the modified container
// ID matches
for i, _ := range group.GroupList {
// Checking in each group if the modified container ID exists
for j, _ := range group.GroupList[i].TrackContainerList {
// If there is match then change them
if group.GroupList[i].TrackContainerList[j].Id == TC.Id {
group.GroupList[i].TrackContainerList[j] = TC
}
}
}
group, err := ReadGroup()
if err != nil {
return err
}
// Iterate though all groups and modify the container
// information in groups where the modified container
// ID matches
for i, _ := range group.GroupList {
// Checking in each group if the modified container ID exists
for j, _ := range group.GroupList[i].TrackContainerList {
// If there is match then change them
if group.GroupList[i].TrackContainerList[j].Id == TC.Id {
group.GroupList[i].TrackContainerList[j] = TC
}
}
}
// Write modified result to the Groups track container JSON file
err = group.WriteGroup()
if err != nil {
return err
}
// Write modified result to the Groups track container JSON file
err = group.WriteGroup()
if err != nil {
return err
}
return nil
return nil
}

32
client/MAPPort.go Normal file
View File

@@ -0,0 +1,32 @@
package client
import (
"github.com/Akilan1999/p2p-rendering-computation/config"
"io/ioutil"
"net/http"
)
func MAPPort(port string) (string, error) {
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return "", err
}
//if version == "version 6" {
URL := "http://0.0.0.0:" + Config.ServerPort + "/MAPPort?port=" + port
//} else {
// URL = "http://" + IP + ":" + serverPort + "/server_info"
//}
resp, err := http.Get(URL)
if err != nil {
return "", err
}
// Convert response to byte value
byteValue, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(byteValue), nil
}

View File

@@ -1,149 +1,149 @@
package client
import (
"encoding/json"
"errors"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"io/ioutil"
"os"
"encoding/json"
"errors"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"io/ioutil"
"os"
)
// TrackContainers This struct stores arrays of current containers running
type TrackContainers struct {
TrackContainerList []TrackContainer `json:"TrackContainer"`
TrackContainerList []TrackContainer `json:"TrackContainer"`
}
// TrackContainer Stores information of current containers
type TrackContainer struct {
Id string `json:"ID"`
Container *docker.DockerVM `json:"Container"`
IpAddress string `json:"IpAddress"`
Id string `json:"ID"`
Container *docker.DockerVM `json:"Container"`
IpAddress string `json:"IpAddress"`
}
// AddTrackContainer Adds new container which has been added to the track container
func AddTrackContainer(d *docker.DockerVM, ipAddress string) error {
// Checking if pointer d is null
if d == nil {
return errors.New("d is nil")
}
//Get config information to derive paths for track containers json file
config, err := config.ConfigInit()
if err != nil {
return err
}
// Checking if pointer d is null
if d == nil {
return errors.New("d is nil")
}
//Get config information to derive paths for track containers json file
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
// Getting information about the file trackcontainers.json file
stat, err := os.Stat(config.TrackContainersPath)
if err != nil {
return err
}
// Initialize variable for TrackContainers
var trackContainers TrackContainers
// If the trackcontainers.json file is not empty then
// Read from that file
if stat.Size() != 0 {
// Reads tracked container file
trackContainersFile, err := ReadTrackContainers(config.TrackContainersPath)
if err != nil {
return err
}
trackContainers = *trackContainersFile
}
// Getting information about the file trackcontainers.json file
stat, err := os.Stat(config.TrackContainersPath)
if err != nil {
return err
}
// Initialize variable for TrackContainers
var trackContainers TrackContainers
// If the trackcontainers.json file is not empty then
// Read from that file
if stat.Size() != 0 {
// Reads tracked container file
trackContainersFile, err := ReadTrackContainers(config.TrackContainersPath)
if err != nil {
return err
}
trackContainers = *trackContainersFile
}
// Initialize new variable with type struct TrackContainers and
// add container struct and ip address
var trackContainer TrackContainer
trackContainer.Id = d.ID
trackContainer.Container = d
trackContainer.IpAddress = ipAddress
// Initialize new variable with type struct TrackContainers and
// add container struct and ip address
var trackContainer TrackContainer
trackContainer.Id = d.ID
trackContainer.Container = d
trackContainer.IpAddress = ipAddress
// Adds new container as passed in the parameter to the struct
if &trackContainer == nil {
return errors.New("trackContainer variable is nil")
}
trackContainers.TrackContainerList = append(trackContainers.TrackContainerList, trackContainer)
// Adds new container as passed in the parameter to the struct
if &trackContainer == nil {
return errors.New("trackContainer variable is nil")
}
trackContainers.TrackContainerList = append(trackContainers.TrackContainerList, trackContainer)
// write modified information to the tracked json file
data, err := json.MarshalIndent(trackContainers, "", "\t")
if err != nil {
return err
}
err = ioutil.WriteFile(config.TrackContainersPath, data, 0777)
if err != nil {
return err
}
// write modified information to the tracked json file
data, err := json.MarshalIndent(trackContainers, "", "\t")
if err != nil {
return err
}
err = ioutil.WriteFile(config.TrackContainersPath, data, 0777)
if err != nil {
return err
}
return nil
return nil
}
// RemoveTrackedContainer This function removos tracked container from the trackcontainer JSON file
func RemoveTrackedContainer(id string) error {
//Get config information to derive paths for track containers json file
config, err := config.ConfigInit()
if err != nil {
return err
}
// Getting tracked container struct
trackedContainers, err := ReadTrackContainers(config.TrackContainersPath)
// Storing index of element to remove
var removeElement int
removeElement = -1
for i := range trackedContainers.TrackContainerList {
if trackedContainers.TrackContainerList[i].Id == id {
removeElement = i
break
}
}
// Checks if the element to be removed has been detected
if removeElement == -1 {
return errors.New("Container ID not found in the tracked list")
}
// Remove the detected element from the struct
trackedContainers.TrackContainerList = append(trackedContainers.TrackContainerList[:removeElement], trackedContainers.TrackContainerList[removeElement+1:]...)
//Get config information to derive paths for track containers json file
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
// Getting tracked container struct
trackedContainers, err := ReadTrackContainers(config.TrackContainersPath)
// Storing index of element to remove
var removeElement int
removeElement = -1
for i := range trackedContainers.TrackContainerList {
if trackedContainers.TrackContainerList[i].Id == id {
removeElement = i
break
}
}
// Checks if the element to be removed has been detected
if removeElement == -1 {
return errors.New("Container ID not found in the tracked list")
}
// Remove the detected element from the struct
trackedContainers.TrackContainerList = append(trackedContainers.TrackContainerList[:removeElement], trackedContainers.TrackContainerList[removeElement+1:]...)
// write modified information to the tracked json file
data, err := json.MarshalIndent(trackedContainers, "", "\t")
if err != nil {
return err
}
err = ioutil.WriteFile(config.TrackContainersPath, data, 0777)
if err != nil {
return err
}
// write modified information to the tracked json file
data, err := json.MarshalIndent(trackedContainers, "", "\t")
if err != nil {
return err
}
err = ioutil.WriteFile(config.TrackContainersPath, data, 0777)
if err != nil {
return err
}
return nil
return nil
}
// ViewTrackedContainers View Containers currently tracked
func ViewTrackedContainers() (error, *TrackContainers) {
config, err := config.ConfigInit()
if err != nil {
return err, nil
}
trackedContianers, err := ReadTrackContainers(config.TrackContainersPath)
if err != nil {
return err, nil
}
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err, nil
}
trackedContianers, err := ReadTrackContainers(config.TrackContainersPath)
if err != nil {
return err, nil
}
return nil, trackedContianers
return nil, trackedContianers
}
// ReadTrackContainers Reads containers which are currently tracked
func ReadTrackContainers(filename string) (*TrackContainers, error) {
buf, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
buf, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
c := &TrackContainers{}
err = json.Unmarshal(buf, c)
if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err)
}
c := &TrackContainers{}
err = json.Unmarshal(buf, c)
if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err)
}
return c, nil
return c, nil
}
//func ModifyTrackContainers()
@@ -151,70 +151,70 @@ func ReadTrackContainers(filename string) (*TrackContainers, error) {
// GetContainerInformation gets information about container based on
// container ID provided
func GetContainerInformation(ID string) (*TrackContainer, error) {
// Getting the current containers
err, CurrentContainers := ViewTrackedContainers()
if err != nil {
return nil, err
}
// Iterating through all tracked containers to get the container information
// of the ID passed through the function parameter
for _, container := range CurrentContainers.TrackContainerList {
if container.Container.ID == ID {
return &container, nil
}
}
return nil, errors.New("Container not found. ")
// Getting the current containers
err, CurrentContainers := ViewTrackedContainers()
if err != nil {
return nil, err
}
// Iterating through all tracked containers to get the container information
// of the ID passed through the function parameter
for _, container := range CurrentContainers.TrackContainerList {
if container.Container.ID == ID {
return &container, nil
}
}
return nil, errors.New("Container not found. ")
}
// ModifyContainerInformation Modifies information inside the container
func (TC *TrackContainer) ModifyContainerInformation() error {
// Gets all the information of tracker containers
err, t := ViewTrackedContainers()
if err != nil {
return err
}
// Find the element where the containers match and
// change them
for i, container := range t.TrackContainerList {
if TC.Id == container.Id {
t.TrackContainerList[i] = *TC
break
}
}
// Write the modified information to the file
// write modified information to the tracked json file
err = t.WriteContainers()
if err != nil {
return err
}
// Gets all the information of tracker containers
err, t := ViewTrackedContainers()
if err != nil {
return err
}
// Find the element where the containers match and
// change them
for i, container := range t.TrackContainerList {
if TC.Id == container.Id {
t.TrackContainerList[i] = *TC
break
}
}
// Write the modified information to the file
// write modified information to the tracked json file
err = t.WriteContainers()
if err != nil {
return err
}
return nil
return nil
}
// WriteContainers Write information back to the config file
func (TC *TrackContainers) WriteContainers() error {
// Initialize config file
config, err := config.ConfigInit()
// write modified information to the tracked json file
data, err := json.MarshalIndent(TC, "", "\t")
if err != nil {
return err
}
err = ioutil.WriteFile(config.TrackContainersPath, data, 0777)
if err != nil {
return err
}
// Initialize config file
config, err := config.ConfigInit(nil, nil)
// write modified information to the tracked json file
data, err := json.MarshalIndent(TC, "", "\t")
if err != nil {
return err
}
err = ioutil.WriteFile(config.TrackContainersPath, data, 0777)
if err != nil {
return err
}
return nil
return nil
}
// CheckID Checks if the ID belongs to a group or a single container
func CheckID(ID string) (string, error) {
// For group checks if the 1st characters is "grp"
if ID[0:3] == "grp" {
return "group", nil
} else {
return "container", nil
}
return "", nil
// For group checks if the 1st characters is "grp"
if ID[0:3] == "grp" {
return "group", nil
} else {
return "container", nil
}
return "", nil
}

View File

@@ -0,0 +1,40 @@
package clientIPTable
import (
"errors"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
)
func AddCustomInformationToIPTable(text string) error {
// Get config information
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
// Get IPTable information
table, err := p2p.ReadIpTable()
if err != nil {
return err
}
found := false
for i, _ := range table.IpAddress {
if table.IpAddress[i].Name == Config.MachineName {
table.IpAddress[i].CustomInformation = text
found = true
}
}
if found {
table.WriteIpTable()
// update IPTable after modified entry
UpdateIpTableListClient()
} else {
return errors.New("start server with p2prc -s as the server is currently not running")
}
return nil
}

View File

@@ -1,16 +1,16 @@
package clientIPTable
import (
"encoding/json"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"sync"
"encoding/json"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"sync"
)
var mu sync.Mutex
@@ -18,136 +18,145 @@ var mu sync.Mutex
// UpdateIpTable Does the following to update it's IP table
func UpdateIpTable(IpAddress string, serverPort string, wg *sync.WaitGroup) error {
config, err := config.ConfigInit()
if err != nil {
return err
}
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
client := http.Client{}
client := http.Client{}
var resp []byte
var resp []byte
version := p2p.Ip4or6(IpAddress)
if version == "version 6" {
resp, err = UploadMultipartFile(client, "http://["+IpAddress+"]:"+serverPort+"/IpTable", "json", config.IPTable)
if err != nil {
return err
}
} else {
resp, err = UploadMultipartFile(client, "http://"+IpAddress+":"+serverPort+"/IpTable", "json", config.IPTable)
if err != nil {
return err
}
}
version := p2p.Ip4or6(IpAddress)
if version == "version 6" {
resp, err = UploadMultipartFile(client, "http://["+IpAddress+"]:"+serverPort+"/IpTable", "json", config.IPTable)
if err != nil {
return err
}
} else {
resp, err = UploadMultipartFile(client, "http://"+IpAddress+":"+serverPort+"/IpTable", "json", config.IPTable)
if err != nil {
return err
}
}
if resp == nil {
return nil
}
if resp == nil {
return nil
}
//resp, err := SendPostRequest("http://"+IpAddress+":8088/IpTable",
// config.IPTable,
// "json")
//
//if err != nil {
// return err
//}
//resp, err := SendPostRequest("http://"+IpAddress+":8088/IpTable",
// config.IPTable,
// "json")
//
//if err != nil {
// return err
//}
var ipStruct p2p.IpAddresses
json.Unmarshal(resp, &ipStruct)
var ipStruct p2p.IpAddresses
json.Unmarshal(resp, &ipStruct)
// Updates IP table based on information provided
// by the server
if len(ipStruct.IpAddress) > 0 {
err = ipStruct.SpeedTestUpdatedIPTable()
if err != nil {
return err
}
}
// Updates IP table based on information provided
// by the server
if len(ipStruct.IpAddress) > 0 {
err = ipStruct.SpeedTestUpdatedIPTable()
if err != nil {
return err
}
}
err = ipStruct.WriteIpTable()
if err != nil {
return err
}
err = ipStruct.WriteIpTable()
if err != nil {
return err
}
wg.Done()
wg.Done()
return nil
return nil
}
// UpdateIpTableListClient updates IP tables (Default 3 hops) based on server information available
// on the ip tables
func UpdateIpTableListClient() error {
// Get config information
Config, err := config.ConfigInit()
if err != nil {
return err
}
// Get config information
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
// Ensure that the IP Table has Node pingable
err = p2p.LocalSpeedTestIpTable()
if err != nil {
return err
}
// Ensure that the IP Table has Node pingable
err = p2p.LocalSpeedTestIpTable()
if err != nil {
return err
}
// IP addresses to not append to struct due to
// duplication
// IP addresses to not append to struct due to
// duplication
Addresses, err := p2p.ReadIpTable()
var DoNotRead p2p.IpAddresses
Addresses, err := p2p.ReadIpTable()
var DoNotRead p2p.IpAddresses
currentIPV4, err := p2p.CurrentPublicIP()
if err != nil {
return err
}
currentIPV4, err := p2p.CurrentPublicIP()
if err != nil {
return err
}
var w sync.WaitGroup
var w sync.WaitGroup
// Run loop 2 times
for i := 0; i < 2; i++ {
// Gets information from IP table
Addresses, err = p2p.ReadIpTable()
if err != nil {
return err
}
// Run loop 2 times
for i := 0; i < 2; i++ {
// Gets information from IP table
Addresses, err = p2p.ReadIpTable()
if err != nil {
return err
}
//DoNotRead.IpAddress = append(DoNotRead.IpAddress, PublicIP)
//DoNotRead.IpAddress = append(DoNotRead.IpAddress, PublicIP)
// Updates IP table based on server IP table
for j := range Addresses.IpAddress {
// Updates IP table based on server IP table
for j := range Addresses.IpAddress {
Exists := false
// If the address is local then add to the local list
if currentIPV4 == Addresses.IpAddress[j].Ipv4 && Addresses.IpAddress[j].ServerPort == Config.ServerPort {
Exists = true
}
Exists := false
// If the address is local then add to the local list
if currentIPV4 == Addresses.IpAddress[j].Ipv4 && Addresses.IpAddress[j].ServerPort == Config.ServerPort {
Exists = true
}
// Check if IP addresses is there in the struct DoNotRead
for k := range DoNotRead.IpAddress {
if (DoNotRead.IpAddress[k].Ipv4 == Addresses.IpAddress[j].Ipv4 && DoNotRead.IpAddress[k].ServerPort == Addresses.IpAddress[j].ServerPort) || (DoNotRead.IpAddress[k].Ipv6 != "" && Addresses.IpAddress[j].Ipv6 == DoNotRead.IpAddress[k].Ipv6) {
Exists = true
break
}
}
// Check if IP addresses is there in the struct DoNotRead
for k := range DoNotRead.IpAddress {
if (DoNotRead.IpAddress[k].Ipv4 == Addresses.IpAddress[j].Ipv4 && DoNotRead.IpAddress[k].ServerPort == Addresses.IpAddress[j].ServerPort) || (DoNotRead.IpAddress[k].Ipv6 != "" && Addresses.IpAddress[j].Ipv6 == DoNotRead.IpAddress[k].Ipv6) {
Exists = true
break
}
}
// If the struct exists then continues
if Exists {
continue
}
// If the struct exists then continues
if Exists {
continue
}
w.Add(1)
if Addresses.IpAddress[j].Ipv6 != "" {
go UpdateIpTable(Addresses.IpAddress[j].Ipv6, Addresses.IpAddress[j].ServerPort, &w)
} else if Addresses.IpAddress[j].Ipv4 != currentIPV4 {
go UpdateIpTable(Addresses.IpAddress[j].Ipv4, Addresses.IpAddress[j].ServerPort, &w)
}
w.Wait()
w.Add(1)
if Addresses.IpAddress[j].Ipv6 != "" {
go UpdateIpTable(Addresses.IpAddress[j].Ipv6, Addresses.IpAddress[j].ServerPort, &w)
} else if Addresses.IpAddress[j].Ipv4 != currentIPV4 {
go UpdateIpTable(Addresses.IpAddress[j].Ipv4, Addresses.IpAddress[j].ServerPort, &w)
}
w.Wait()
//Appends server1 IP address to variable DoNotRead
DoNotRead.IpAddress = append(DoNotRead.IpAddress, Addresses.IpAddress[j])
}
}
//Appends server1 IP address to variable DoNotRead
DoNotRead.IpAddress = append(DoNotRead.IpAddress, Addresses.IpAddress[j])
}
}
return nil
return nil
}
func RemoveOfflineNodes() error {
// Ensure that the IP Table has Node pingable
err := p2p.LocalSpeedTestIpTable()
if err != nil {
return err
}
return nil
}
// SendPostRequest Sends a file as a
@@ -197,58 +206,58 @@ func UpdateIpTableListClient() error {
//}
func UploadMultipartFile(client http.Client, uri, key, path string) ([]byte, error) {
body, writer := io.Pipe()
body, writer := io.Pipe()
req, err := http.NewRequest(http.MethodPost, uri, body)
if err != nil {
return nil, err
}
req, err := http.NewRequest(http.MethodPost, uri, body)
if err != nil {
return nil, err
}
mwriter := multipart.NewWriter(writer)
req.Header.Add("Content-Type", mwriter.FormDataContentType())
mwriter := multipart.NewWriter(writer)
req.Header.Add("Content-Type", mwriter.FormDataContentType())
errchan := make(chan error)
errchan := make(chan error)
go func() {
defer close(errchan)
defer writer.Close()
defer mwriter.Close()
go func() {
defer close(errchan)
defer writer.Close()
defer mwriter.Close()
w, err := mwriter.CreateFormFile(key, path)
if err != nil {
errchan <- err
return
}
w, err := mwriter.CreateFormFile(key, path)
if err != nil {
errchan <- err
return
}
in, err := os.Open(path)
if err != nil {
errchan <- err
return
}
defer in.Close()
in, err := os.Open(path)
if err != nil {
errchan <- err
return
}
defer in.Close()
if written, err := io.Copy(w, in); err != nil {
errchan <- fmt.Errorf("error copying %s (%d bytes written): %v", path, written, err)
return
}
if written, err := io.Copy(w, in); err != nil {
errchan <- fmt.Errorf("error copying %s (%d bytes written): %v", path, written, err)
return
}
if err := mwriter.Close(); err != nil {
errchan <- err
return
}
}()
if err := mwriter.Close(); err != nil {
errchan <- err
return
}
}()
resp, err := client.Do(req)
if err != nil {
return nil, err
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
content, err := ioutil.ReadAll(resp.Body)
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
return content, nil
return content, nil
}

View File

@@ -1,8 +1,10 @@
package client
import (
b64 "encoding/base64"
"encoding/json"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"io/ioutil"
@@ -19,7 +21,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,9 +35,22 @@ 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
//}
// Get config information
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
// Get public key
PublicKey, err := Config.GetPublicKey()
if err != nil {
return nil, err
}
// Used in URL to pass public key -> b64.StdEncoding.EncodeToString([]byte(PublicKey))
URL = `http://` + IP + `/startcontainer?ports=` + fmt.Sprint(NumPorts) + `&GPU=` + strconv.FormatBool(GPU) + `&ContainerName=` + ContainerName + `&BaseImage=` + baseImage + `&PublicKey=` + b64.StdEncoding.EncodeToString([]byte(PublicKey))
// Encode URL due to public key passed.
resp, err := http.Get(URL)
if err != nil {
return nil, err

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
{}

View File

@@ -4,8 +4,7 @@ import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/generate"
"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"
@@ -14,11 +13,14 @@ import (
var CliAction = func(ctx *cli.Context) error {
if Server {
err := server.Server()
_, err := server.Server()
if err != nil {
fmt.Print(err)
}
//server.Rpc()
for {
}
}
//Listing servers and also updates IP tables (Default 3 hops)
@@ -93,10 +95,14 @@ var CliAction = func(ctx *cli.Context) error {
}
// Function called to stop and remove server from Docker
if RemoveVM != "" && ID != "" {
err := client.RemoveContianer(RemoveVM, ID)
if err != nil {
fmt.Print(err)
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)
}
}
}
@@ -111,7 +117,7 @@ var CliAction = func(ctx *cli.Context) error {
}
// 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 {
fmt.Print(err)
@@ -132,7 +138,7 @@ var CliAction = func(ctx *cli.Context) error {
//Sets default paths to the config file
if SetDefaultConfig {
err := config.SetDefaults()
_, err := generate.SetDefaults("P2PRC", false, nil, false)
if err != nil {
fmt.Print(err)
}
@@ -179,7 +185,7 @@ var CliAction = func(ctx *cli.Context) error {
fmt.Println("Success")
}
} else {
fmt.Println("provide container ID")
fmt.Println("provide container ID via --ID or --id")
}
}
@@ -247,39 +253,6 @@ var CliAction = func(ctx *cli.Context) error {
}
}
// Starts server as a reverse proxy so that
// nodes can connect to each other behind NAT
//if FRPProxy {
// err := frp.StartFRPProxyFromRandom()
// if err != nil {
// fmt.Println(err)
// }
//}
// -- REMOVE ON REGULAR RELEASE --
// when flag --gen is called an extension
// of the project is created to repurpose
// the project for custom purpose
if Generate != "" {
var err error
// If the module name is provided
if Modulename != "" {
err = generate.GenerateNewProject(Generate, Modulename)
} else {
err = generate.GenerateNewProject(Generate, Generate)
}
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Created new folder: " + Generate)
fmt.Println("1. Enter inside " + Generate + " directory")
fmt.Println("2. git remote add " + Generate + " <PATH to the github repo>")
fmt.Println("3. git push " + Generate + " <PATH to the github repo>")
fmt.Println("4. go mod tidy")
fmt.Println("5. sh install.sh " + Generate)
fmt.Println("6. ./" + Generate + " -h (This is to test if the binary is working)")
}
}
//--------------------------------
if PullPlugin != "" {
@@ -300,5 +273,26 @@ var CliAction = func(ctx *cli.Context) error {
}
}
if AddMetaData != "" {
err := clientIPTable.AddCustomInformationToIPTable(AddMetaData)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Success")
}
}
if MAPPort != "" {
address, err := client.MAPPort(MAPPort)
if err != nil {
return err
}
if err != nil {
fmt.Println(err)
} else {
fmt.Println(address)
}
}
return nil
}

View File

@@ -10,6 +10,7 @@ var (
ViewImages string
CreateVM string
ContainerName string
BaseImage string
Ports string
Server bool
RemoveVM string
@@ -28,6 +29,7 @@ var (
Groups bool
RemoveContainerGroup bool
RemoveGroup string
MAPPort string
//FRPProxy bool
// Generate only allowed in dev release
// -- REMOVE ON REGULAR RELEASE --
@@ -36,6 +38,7 @@ var (
//--------------------------------
PullPlugin string
RemovePlugin string
AddMetaData string
)
var AppConfigFlags = []cli.Flag{
@@ -89,10 +92,17 @@ 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"},
Usage: "Stop and Remove Docker container",
Usage: "Stop and Remove Docker container (IP:port) accompanied by container ID via --ID or --id",
EnvVars: []string{"REMOVE_VM"},
Destination: &RemoveVM,
},
@@ -148,7 +158,7 @@ var AppConfigFlags = []cli.Flag{
&cli.BoolFlag{
Name: "TrackedContainers",
Aliases: []string{"tc"},
Usage: "View containers which have " +
Usage: "View (currently running) containers which have " +
"been created from the client side ",
EnvVars: []string{"TRACKED_CONTAINERS"},
Destination: &TrackedContainers,
@@ -195,6 +205,13 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"REMOVE_GROUP"},
Destination: &RemoveGroup,
},
&cli.StringFlag{
Name: "MAPPort",
Aliases: []string{"mp"},
Usage: "Maps port for a specific port provided as the parameter",
EnvVars: []string{"MAPPORT"},
Destination: &MAPPort,
},
// Generate only allowed in dev release
// -- REMOVE ON REGULAR RELEASE --
&cli.StringFlag{
@@ -233,4 +250,11 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"REMOVEPLUGIN"},
Destination: &RemovePlugin,
},
&cli.StringFlag{
Name: "AddMetaData",
Aliases: []string{"amd"},
Usage: "Adds metadata about the current node in the p2p network which is then propagated through the network",
EnvVars: []string{"ADDMETADATA"},
Destination: &AddMetaData,
},
}

View File

@@ -1,13 +1,13 @@
package config
import (
"github.com/spf13/viper"
"io"
"encoding/json"
"io/ioutil"
"os"
)
var (
defaultPath string
//defaultPath string
defaults = map[string]interface{}{}
configName = "config"
configType = "json"
@@ -21,6 +21,7 @@ type Config struct {
IPTable string
DockerContainers string
DefaultDockerFile string
DockerRunLogs string
SpeedTestFile string
IPV6Address string
PluginPath string
@@ -29,46 +30,36 @@ type Config struct {
GroupTrackContainersPath string
FRPServerPort string
BehindNAT string
IPTableKey string
PublicKeyFile string
PrivateKeyFile string
BareMetal string
CustomConfig interface{}
//NetworkInterface string
//NetworkInterfaceIPV6Index int
}
// Exists reports whether the named file or directory exists.
func fileExists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// Copy the src file to dst. Any existing file will be overwritten and will not
// copy file attributes.
// Source: https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file
func Copy(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
return out.Close()
// GetCurrentPath Getting P2PRC Directory from environment variable
func GetCurrentPath() (string, error) {
curDir := os.Getenv("PWD")
return curDir + "/", nil
}
// GetPathP2PRC Getting P2PRC Directory from environment variable
func GetPathP2PRC() (string, error) {
func GetPathP2PRC(Envname string) (string, error) {
if Envname != "" {
err := SetEnvName(Envname)
if err != nil {
return "", err
}
}
curDir := os.Getenv(defaultEnvName)
if curDir == "" {
// if the OS env path is not found then you use
// the current directory path.
currentPath, _ := GetCurrentPath()
return currentPath, nil
}
return curDir + "/", nil
}
@@ -82,115 +73,109 @@ func SetEnvName(EnvName string) error {
return nil
}
// GetCurrentPath Getting P2PRC Directory from environment variable
func GetCurrentPath() (string, error) {
curDir := os.Getenv("PWD")
return curDir + "/", nil
func GetEnvName() string {
return defaultEnvName
}
// SetDefaults This function to be called only during a
// make install
func SetDefaults() error {
//Setting current directory to default path
defaultPath, err := GetPathP2PRC()
if err != nil {
return err
// 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
//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
}
//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"] = "0"
defaults["BehindNAT"] = "True"
// Random name generator
hostname, err := os.Hostname()
if err != nil {
return err
}
defaults["MachineName"] = hostname
//defaults["NetworkInterface"] = "wlp0s20f3"
//defaults["NetworkInterfaceIPV6Index"] = "2"
//Paths to search for config file
configPaths = append(configPaths, defaultPath)
if fileExists(defaultPath + "config.json") {
err := os.Remove(defaultPath + "config.json")
if err != nil {
return err
}
}
//Calling configuration file
_, err = ConfigInit()
if err != nil {
return err
}
return nil
}
func ConfigInit() (*Config, error) {
//Setting current directory to default path
defaultPath, err := GetPathP2PRC()
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)
// 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
}
//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)
// defer the closing of our jsonFile so that we can parse it later on
defer jsonFile.Close()
if err = viper.WriteConfig(); err != nil {
byteValue, _ := ioutil.ReadAll(jsonFile)
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
}
}
// Adds configuration to the struct
var config Config
if err := viper.Unmarshal(&config); err != nil {
return nil, err
// Again map the byte to the CustomConfig interface
json.Unmarshal(customConfigByte, &CustomConfig)
}
return &config, nil
}
func (c *Config) WriteConfig() error {
//Getting Current Directory from environment variable
//curDir := os.Getenv("REMOTEGAMING")
defaultPath, err := GetPathP2PRC(defaultEnvName)
if err != nil {
return err
}
file, _ := json.MarshalIndent(c, "", " ")
_ = ioutil.WriteFile(defaultPath+"config.json", file, 0644)
return nil
}
// GetPublicKey Gets public key of the current machine
// based on the path provided on the
// config file
func (c *Config) GetPublicKey() (string, error) {
publicKey, err := ioutil.ReadFile(c.PublicKeyFile) // just pass the file name
if err != nil {
return "", err
}
return string(publicKey), nil
}

View File

@@ -1,63 +0,0 @@
package config
import (
"fmt"
"os"
"testing"
)
func TestConfigInit(t *testing.T) {
_,err := ConfigInit()
if err != nil {
t.Error(err)
}
}
func TestSetDefaults(t *testing.T) {
err := SetDefaults()
if err != nil {
t.Error(err)
}
}
func TestGetCurrentPath(t *testing.T) {
path, err := GetCurrentPath()
if err != nil {
fmt.Println(err)
t.Error(err)
}
fmt.Println(path)
}
func TestGetPathP2PRC(t *testing.T) {
path, err := GetPathP2PRC()
if err != nil {
fmt.Println(err)
t.Error(err)
}
fmt.Println(path)
}
func TestSetEnvName(t *testing.T) {
// Create an Env variable TEST with the value "lol"
err := os.Setenv("TEST", "lol")
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Sets the environment variable as the default to read
// for P2PRC
err = SetEnvName("TEST")
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Checks if the output for the default read is "lol"
path, err := GetPathP2PRC()
if err != nil {
fmt.Println(err)
t.Error(err)
}
fmt.Println(path)
}

View File

@@ -0,0 +1,64 @@
package generate
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"os"
"testing"
)
// func TestConfigInit(t *testing.T) {
// _, err := config.ConfigInit(nil)
// if err != nil {
// t.Error(err)
// }
// }
// func TestSetDefaults(t *testing.T) {
// _, err := SetDefaults("", false)
// if err != nil {
// t.Error(err)
// }
// }
func TestGetCurrentPath(t *testing.T) {
path, err := GetCurrentPath()
if err != nil {
fmt.Println(err)
t.Error(err)
}
fmt.Println(path)
}
func TestGetPathP2PRC(t *testing.T) {
path, err := config.GetPathP2PRC("")
if err != nil {
fmt.Println(err)
t.Error(err)
}
fmt.Println(path)
}
func TestSetEnvName(t *testing.T) {
// Create an Env variable TEST with the value "lol"
err := os.Setenv("TEST", "lol")
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Sets the environment variable as the default to read
// for P2PRC
err = config.SetEnvName("TEST")
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Checks if the output for the default read is "lol"
path, err := config.GetPathP2PRC("")
if err != nil {
fmt.Println(err)
t.Error(err)
}
fmt.Println(path)
}

167
config/generate/generate.go Normal file
View File

@@ -0,0 +1,167 @@
package generate
import (
"github.com/Akilan1999/p2p-rendering-computation/config"
"math/rand"
"os"
"time"
)
var (
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
}
// SetEnvName Sets the environment name
// This is to ensure that the Path of your project is detected from
// 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
}
// 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 := config.GetCurrentPath()
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
//}
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"
Defaults.DockerRunLogs = "/tmp/"
// Generate a random key to be added to IPTable
Defaults.IPTableKey = String(12)
// Random name generator
hostname, err := os.Hostname()
if err != nil {
return nil, err
}
// Generate Public and private keys and set path
Defaults.PublicKeyFile = defaultPath + "p2prc.PublicKeyBareMetal"
Defaults.PrivateKeyFile = defaultPath + "p2prc.privateKey"
Defaults.BareMetal = "False"
PrivateKeyExists, err := FileExists(Defaults.PrivateKeyFile)
if err != nil {
return nil, err
}
if !PrivateKeyExists {
// Generate SSH keys
err = MakeSSHKeyPair(Defaults.PublicKeyFile, Defaults.PrivateKeyFile)
if err != nil {
return nil, err
}
}
Defaults.MachineName = hostname + "-" + String(7)
} else {
Defaults = *ConfigUpdate[0]
}
//defaults["NetworkInterface"] = "wlp0s20f3"
//defaults["NetworkInterfaceIPV6Index"] = "2"
//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
}
}
// 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
}
if !NoBoilerPlate {
err = GenerateFiles()
if err != nil {
return nil, err
}
}
return Config, nil
}
// Generating a random string
const charset = "abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var seededRand *rand.Rand = rand.New(
rand.NewSource(time.Now().UnixNano()))
func StringWithCharset(length int, charset string) string {
b := make([]byte, length)
for i := range b {
b[i] = charset[seededRand.Intn(len(charset))]
}
return string(b)
}
func String(length int) string {
return StringWithCharset(length, charset)
}

View File

@@ -0,0 +1,290 @@
package generate
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/go-git/go-git/v5"
"golang.org/x/crypto/ssh"
"io/ioutil"
"os"
)
// GenerateFiles Generates all the files needed to setup P2PRC
func GenerateFiles(rootNodes ...p2p.IpAddress) (err error) {
err = GenerateIPTableFile(rootNodes)
if err != nil {
return err
}
err = GenerateDockerFiles()
if err != nil {
return err
}
err = GeneratePluginDirectory()
if err != nil {
return err
}
err = GenerateClientTrackContainers()
return
}
// GenerateIPTableFile Generates the IPTable file with the appropirate root node
func GenerateIPTableFile(rootNodes []p2p.IpAddress) (err error) {
var rootnodes p2p.IpAddresses
var rootnode p2p.IpAddress
err = CreateIPTableFolderStructure()
if err != nil {
return err
}
// If root node addresses are not provided as optional parameters
if len(rootNodes) <= 0 {
rootnode.Name = "Node1"
rootnode.ServerPort = "8078"
rootnode.NAT = "False"
rootnode.Ipv4 = "217.76.63.222"
rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode)
} else {
// if root nodes are provided then override them as the optional parameter
for i := range rootNodes {
rootnodes.IpAddress = append(rootnodes.IpAddress, rootNodes[i])
}
}
err = rootnodes.WriteIpTable()
return
}
// CreateIPTableFolderStructure Create folder structure for IPTable
func CreateIPTableFolderStructure() (err error) {
path, err := config.GetCurrentPath()
if err != nil {
return err
}
if _, err = os.Stat(path + "p2p"); os.IsNotExist(err) {
if err = os.Mkdir(path+"p2p", os.ModePerm); err != nil {
return err
}
}
if _, err = os.Stat(path + "p2p/iptable"); os.IsNotExist(err) {
if err = os.Mkdir(path+"p2p/iptable", os.ModePerm); err != nil {
return err
}
}
if _, err = os.Stat(path + "p2p/iptable/ip_table.json"); os.IsNotExist(err) {
_, err = os.Create(path + "p2p/iptable/ip_table.json")
if err != nil {
return err
}
}
return
}
// GenerateDockerFiles Generate default docker files
func GenerateDockerFiles() (err error) {
path, err := config.GetCurrentPath()
if err != nil {
return err
}
if _, err = os.Stat(path + "server"); os.IsNotExist(err) {
if err = os.Mkdir(path+"server", os.ModePerm); err != nil {
return err
}
if _, err = os.Stat(path + "server/docker"); os.IsNotExist(err) {
if err = os.Mkdir(path+"server/docker", os.ModePerm); err != nil {
return err
}
}
if _, err = os.Stat(path + "server/docker/containers"); os.IsNotExist(err) {
if err = os.Mkdir(path+"server/docker/containers", os.ModePerm); err != nil {
return err
}
}
if _, err = os.Stat(path + "server/docker/containers"); os.IsNotExist(err) {
if err = os.Mkdir(path+"server/docker/containers", os.ModePerm); err != nil {
return err
}
}
if _, err = os.Stat(path + "server/docker/containers/docker-ubuntu-sshd"); os.IsNotExist(err) {
if err = os.Mkdir(path+"server/docker/containers/docker-ubuntu-sshd", os.ModePerm); err != nil {
return err
}
}
}
// Clone base docker image
_, err = git.PlainClone(path+"server/docker/containers/docker-ubuntu-sshd", false, &git.CloneOptions{
URL: "https://github.com/Akilan1999/docker-ubuntu-sshd",
Progress: os.Stdout,
})
if err != nil {
return err
}
return
}
// GeneratePluginDirectory Generates plugin directory structure
func GeneratePluginDirectory() (err error) {
path, err := config.GetCurrentPath()
if err != nil {
return err
}
if _, err = os.Stat(path + "plugin"); os.IsNotExist(err) {
if err = os.Mkdir(path+"plugin", os.ModePerm); err != nil {
return err
}
if _, err = os.Stat(path + "plugin/deploy"); os.IsNotExist(err) {
if err = os.Mkdir(path+"plugin/deploy", os.ModePerm); err != nil {
return err
}
}
}
return
}
func GenerateClientTrackContainers() (err error) {
path, err := config.GetCurrentPath()
if err != nil {
return err
}
if _, err = os.Stat(path + "client"); os.IsNotExist(err) {
if err = os.Mkdir(path+"client", os.ModePerm); err != nil {
return err
}
if err = os.Mkdir(path+"client/trackcontainers", os.ModePerm); err != nil {
return err
}
if _, err = os.Stat(path + "client/trackcontainers/trackcontainers.json"); os.IsNotExist(err) {
_, err = os.Create(path + "client/trackcontainers/trackcontainers.json")
if err != nil {
return err
}
_, err = os.Create(path + "client/trackcontainers/grouptrackcontainers.json")
if err != nil {
return err
}
}
}
return
}
// MakeSSHKeyPair make a pair of public and private keys for SSH access.
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
// Private Key generated is PEM encoded
// source: https://gist.github.com/goliatone/e9c13e5f046e34cef6e150d06f20a34c
func MakeSSHKeyPair(pubKeyPath, privateKeyPath string) error {
privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
return err
}
// generate and write private key as PEM
privateKeyFile, err := os.Create(privateKeyPath)
defer privateKeyFile.Close()
if err != nil {
return err
}
// Set permission to private key to SSH into docker machine
err = os.Chmod(privateKeyPath, 600)
if err != nil {
return err
}
privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil {
return err
}
// generate and write public key
pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
if err != nil {
return err
}
return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655)
}
// FileExists exists returns whether the given file or directory exists
// source: https://stackoverflow.com/questions/10510691/how-to-check-whether-a-file-or-directory-exists
func FileExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// AuthorizedKey struct represents the structure of an authorized key
type AuthorizedKey struct {
Username string
Key string
}
// AddPublicKeyBareMetal Adds the parameter public key to the auth list
// Generated by ChatGPT
// Prompts:
// - Generate a go program to read authorised key and map it to a struct and write it back to the same location.
// - Can you follow the original format
// (TURNED OUT TO BE PRETTY SHITTY GENERATED CODE)
//func AddPublicKeyBareMetal(PublicKey string) error {
// // Specify the path to the authorized_keys file
// dirname, err := os.UserHomeDir()
// if err != nil {
// return err
// }
//
// authorizedKeysPath := dirname + "/.ssh/" + "authorized_keys"
//
// // Read the contents of the authorized_keys file
// file, err := os.Open(authorizedKeysPath)
// if err != nil {
// return err
// }
// defer file.Close()
//
// // Create a slice to store AuthorizedKey structs
// var authorizedKeys []AuthorizedKey
//
// // Read each line of the file and parse the data
// scanner := bufio.NewScanner(file)
// for scanner.Scan() {
// line := scanner.Text()
// parts := strings.Fields(line)
// if len(parts) >= 2 {
// authorizedKey := AuthorizedKey{
// Username: parts[0],
// Key: parts[1],
// }
// authorizedKeys = append(authorizedKeys, authorizedKey)
// }
// }
//
// if err := scanner.Err(); err != nil {
// return err
// }
//
// // Modify the slice of structs if needed
// // authorizedKeys[0].Username = "newUsername"
// // authorizedKeys[0].Key = "newKey"
// authorizedKeys = append(authorizedKeys, AuthorizedKey{Username: "", Key: PublicKey})
//
// // Write the modified data back to the authorized_keys file
// newFile, err := os.Create(authorizedKeysPath)
// if err != nil {
// return err
// }
// defer newFile.Close()
//
// return nil
//}

View File

@@ -0,0 +1,40 @@
package generate
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"testing"
)
type CustomConfig struct {
Test string
}
// Test case to generate defaults with custom data-structure
func TestSetDefaults(t *testing.T) {
setDefaults, err := SetDefaults("", true, &CustomConfig{Test: "lol"}, true)
if err != nil {
fmt.Println(err)
t.Fail()
return
}
fmt.Println(setDefaults)
var c CustomConfig
_, err = config.ConfigInit(nil, &c)
if err != nil {
fmt.Println(err)
t.Fail()
return
}
fmt.Println(c)
}
// Test case to generate public and private keys
func TestGeneratePublicAndPrivateKeys(t *testing.T) {
MakeSSHKeyPair("test.pub", "test.prv")
}

View File

@@ -0,0 +1,39 @@
package generate
import (
"io"
"os"
)
// Exists reports whether the named file or directory exists.
func fileExists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// Copy the src file to dst. Any existing file will be overwritten and will not
// copy file attributes.
// Source: https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file
func Copy(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
return out.Close()
}

22
default.nix Normal file
View File

@@ -0,0 +1,22 @@
{ nixpkgs ? import <nixpkgs> { } }:
let
pkgs = [
nixpkgs.go
nixpkgs.tmux
nixpkgs.docker
nixpkgs.vim
];
in
nixpkgs.stdenv.mkDerivation {
name = "env";
buildInputs = pkgs;
pure-eval = true;
shellHook =
''
make
export P2PRC=$PWD
export PATH=$PWD:$PATH
'';
}

View File

@@ -1,386 +0,0 @@
// Package generate The purpose of this package is to ensure that we can extend the use-case of P2PRC.
// We will create a project directory with the template to extend the use-case of P2PRC
package generate
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/otiai10/copy"
"go/ast"
"go/token"
modfile "golang.org/x/mod/modfile"
"io/ioutil"
"os"
"os/exec"
"strings"
)
// NewProject Struct information required when creating a new project
type NewProject struct {
Name string
Module string
NewDir string
P2PRCPath string
CurrentModule string
Option *copy.Options
Token *token.FileSet
AST *ast.File
FileNameAST string
}
// GenerateNewProject creates a new copy of the P2PRC
// project for custom modification
func GenerateNewProject(name string, module string) error {
// Create new variable of type NewProject
var newProject NewProject
//Setting module name to the new project
newProject.Module = module
// Get path of the current directory
curDir, err := config.GetCurrentPath()
if err != nil {
return err
}
// Folder name of the new generated project
newProject.NewDir = curDir + name + "/"
// Create a new folder based on name entered
err = CreateFolder(name, curDir)
if err != nil {
return err
}
// get path of P2PRC
P2PRCPATH, err := config.GetPathP2PRC()
if err != nil {
return err
}
// Assign P2PRC path to the newly generated project
newProject.P2PRCPath = P2PRCPATH
// Steps:
// - copy all files from P2PRC
// - remove go.mod and go.sum and create new ones
// Files we require to skip
var Options copy.Options
// IF YOU ARE RELEASING AN EXTENSION OF P2PRC
// MODIFY HERE (AN EXTENSION FROM YOUR EXTENSION :P)
// Skip or have the appropriate files and directories not needed
//----------------------------------------------------------------
// Action performed:
// - Ensuring main.go file exists
// - Ensuring generate.go file exists
// - Ensuring modifyGenerate.go file exists
// - Ensuring generate_test.go file exists
// - Ensuring server/server.go file exists
// - Ensuring server/gopsutil.go file exists
// - Ensuring server/gpu.go file exists
// - Ensuring cmd/action.go file exists
// - Ensuring cmd/flags.go file exists
// - Skipping all .go files apart from the ones listed above
// - Skipping go.mod file
// - Skipping go.sum file
// - Skipping .idea/ directory
// - Skipping Makefile file
// - Skipping <Project Name>/ directory
//----------------------------------------------------------------
Options.Skip = func(src string) (bool, error) {
switch {
case strings.HasSuffix(src, "main.go"):
return false, nil
case strings.HasSuffix(src, "generate.go"):
return false, nil
case strings.HasSuffix(src, "modifyGenerate.go"):
return false, nil
case strings.HasSuffix(src, "generate_test.go"):
return false, nil
case strings.HasSuffix(src, "server/server.go"):
return false, nil
case strings.HasSuffix(src, "server/gopsutil.go"):
return false, nil
case strings.HasSuffix(src, "server/gpu.go"):
return false, nil
case strings.HasSuffix(src, "cmd/action.go"):
return false, nil
case strings.HasSuffix(src, "cmd/flags.go"):
return false, nil
case strings.HasSuffix(src, "config/config.go"):
return false, nil
case strings.HasSuffix(src, "config/config_test.go"):
return false, nil
case strings.HasSuffix(src, ".go"):
return true, nil
case strings.HasSuffix(src, "go.mod"):
return true, nil
case strings.HasSuffix(src, "go.sum"):
return true, nil
case strings.HasSuffix(src, ".idea"):
return true, nil
case strings.HasSuffix(src, "Makefile"):
return true, nil
case strings.HasSuffix(src, name):
return true, nil
default:
return false, nil
}
}
// Storing type option in the struct new project
newProject.Option = &Options
// Copies all files from P2PRC to the new project created
err = copy.Copy(newProject.P2PRCPath, newProject.NewDir, *newProject.Option)
if err != nil {
return err
}
// Creating a new go.mod file in the appropriate directory
err = newProject.CreateGoMod()
if err != nil {
return err
}
// Get current project mod name
err = newProject.GetCurrentGoModule()
if err != nil {
return err
}
// Change the appropriate imports
err = newProject.ChangeImportFiles()
if err != nil {
return err
}
// Add changes inside the new project
err = newProject.GitAdd()
if err != nil {
return err
}
// commit changes inside the new project
err = newProject.GitCommit()
if err != nil {
return err
}
// Creates go.sum file
//err = newProject.CreateGoModTidy()
//if err != nil {
// return err
//}
return nil
}
// CreateFolder Creates a new folder based on the name and path provided
func CreateFolder(name string, path string) error {
//Create a folder/directory at a full qualified path
err := os.Mkdir(path+name, 0755)
if err != nil {
return err
}
return nil
}
// CreateGoMod Creates a new go module for the new project created
func (a *NewProject) CreateGoMod() error {
// Create new go.mod in the appropriate directory
cmd := exec.Command("go", "mod", "init", a.Module)
cmd.Dir = a.NewDir
if err := cmd.Run(); err != nil {
return err
}
return nil
}
func (a *NewProject) CreateGoModTidy() error {
// Installs all the appropriate dependencies and creates go.sum
cmd := exec.Command("go", "mod", "tidy")
cmd.Dir = a.NewDir
if err := cmd.Run(); err != nil {
return err
}
return nil
}
// ChangeImportFiles Changes Appropriate imports in the appropriate file
func (a *NewProject) ChangeImportFiles() error {
// IF YOU ARE RELEASING AN EXTENSION OF P2PRC
// MODIFY HERE (AN EXTENSION FROM YOUR EXTENSION :P)
//----------------------------------------------------------------
// Action performed:
// Files we would need to modify the imports in
// - generate/generate.go -> config module
// - generate/generate_test.go -> config module
// - cmd/action.go -> config module, server module, generate module
// - cmd/flags.go -> config module, server module, generate module
// - server/server.go -> config module
// - main.go -> cmd module
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// 1.0 - generate/generate.go -> config module
a.FileNameAST = a.NewDir + "generate/generate.go"
// Get AST information of the file
err := a.GetASTGoFile()
if err != nil {
return err
}
// Change the appropriate Go file
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
if err != nil {
return err
}
// Writes the change to the appropriate file
err = a.WriteGoAst()
if err != nil {
return err
}
//-----------------------------------------------------------------
// 1.1 - generate/generate_test.go -> config module
a.FileNameAST = a.NewDir + "generate/generate_test.go"
// Get AST information of the file
err = a.GetASTGoFile()
if err != nil {
return err
}
// Change the appropriate Go file
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
if err != nil {
return err
}
// Writes the change to the appropriate file
err = a.WriteGoAst()
if err != nil {
return err
}
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// 2.0 - cmd/action.go -> config module, server module, generate module
a.FileNameAST = a.NewDir + "cmd/action.go"
// Get AST information of the file
err = a.GetASTGoFile()
if err != nil {
return err
}
// Change the appropriate Go file
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
if err != nil {
return err
}
err = a.ChangeImports(a.CurrentModule+"/server", a.Module+"/server")
if err != nil {
return err
}
err = a.ChangeImports(a.CurrentModule+"/generate", a.Module+"/generate")
if err != nil {
return err
}
// Writes the change to the appropriate file
err = a.WriteGoAst()
if err != nil {
return err
}
//-----------------------------------------------------------------
// 2.1 - cmd/flags.go -> config module, server module, generate module
a.FileNameAST = a.NewDir + "cmd/flags.go"
// Get AST information of the file
err = a.GetASTGoFile()
if err != nil {
return err
}
// Change the appropriate Go file
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
if err != nil {
return err
}
err = a.ChangeImports(a.CurrentModule+"/server", a.Module+"/server")
if err != nil {
return err
}
err = a.ChangeImports(a.CurrentModule+"/generate", a.Module+"/generate")
if err != nil {
return err
}
// Writes the change to the appropriate file
err = a.WriteGoAst()
if err != nil {
return err
}
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// 3.0 - server/server.go -> config module
a.FileNameAST = a.NewDir + "server/server.go"
// Get AST information of the file
err = a.GetASTGoFile()
if err != nil {
return err
}
// Change the appropriate Go file
err = a.ChangeImports(a.CurrentModule+"/config", a.Module+"/config")
if err != nil {
return err
}
// Writes the change to the appropriate file
err = a.WriteGoAst()
if err != nil {
return err
}
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// 4.0 - server/server.go -> config module
a.FileNameAST = a.NewDir + "main.go"
// Get AST information of the file
err = a.GetASTGoFile()
if err != nil {
return err
}
// Change the appropriate Go file
err = a.ChangeImports(a.CurrentModule+"/cmd", a.Module+"/cmd")
if err != nil {
return err
}
// Writes the change to the appropriate file
err = a.WriteGoAst()
if err != nil {
return err
}
//-----------------------------------------------------------------
return nil
}
// GetCurrentGoModule Gets the current go module name
func (a *NewProject) GetCurrentGoModule() error {
goModBytes, err := ioutil.ReadFile(a.P2PRCPath + "go.mod")
if err != nil {
return err
}
modName := modfile.ModulePath(goModBytes)
fmt.Fprintf(os.Stdout, "modName=%+v\n", modName)
// Set current module to struct of file NewProject
a.CurrentModule = modName
return nil
}
func (a *NewProject) GitAdd() error {
// Installs all the appropriate dependencies and creates go.sum
cmd := exec.Command("git", "add", ".")
cmd.Dir = a.NewDir
if err := cmd.Run(); err != nil {
return err
}
return nil
}
func (a *NewProject) GitCommit() error {
// Installs all the appropriate dependencies and creates go.sum
cmd := exec.Command("git", "commit", "-m=removed appropriate go files")
cmd.Dir = a.NewDir
if err := cmd.Run(); err != nil {
return err
}
return nil
}

View File

@@ -1,112 +0,0 @@
package generate
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"testing"
)
// Tests the create folder function creates a folder
// This test will create a folder in the temporary
// directory
func TestCreateFolder(t *testing.T) {
err := CreateFolder("test", "/tmp/")
if err != nil {
t.Error(err)
}
}
// Testing if a new project is created successfully
func TestGenerateNewProject(t *testing.T) {
// Checking if a new project is created successfully
err := GenerateNewProject("p2prctest", "p2prctest")
if err != nil {
fmt.Println(err)
t.Error(err)
}
}
// Testing AST function to ensure imports are
// working as intended
func TestChangingImportAST(t *testing.T) {
// Create a new variable of type NewProject
var np NewProject
// Get current directory
path, err := config.GetCurrentPath()
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Create testcase scenario
err = config.Copy(path+"testcaseAST.go", path+"/Test/testcaseAST.go")
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Sets new directory to the folder test
np.NewDir = path + "Test/"
// Sets file name to be opened and modified in the AST
np.FileNameAST = path + "Test/" + "testcaseAST.go"
// Call the Read AST function
err = np.GetASTGoFile()
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Change an import
err = np.ChangeImports("fmt", "lolol")
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Write those saved changes
err = np.WriteGoAst()
if err != nil {
fmt.Println(err)
t.Error(err)
}
}
// Testing the if Go Mod is created
func TestNewProject_CreateGoMod(t *testing.T) {
// Create a new variable of type NewProject
var np NewProject
path, err := config.GetCurrentPath()
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Set new project name as Test
np.Name = "Test"
// Set new project module as github.com/Test
np.Module = "github.com/Test"
// Set Path of the new project
np.NewDir = path + "Test/"
// Creating a go.mod file
err = np.CreateGoMod()
if err != nil {
fmt.Println(err)
t.Error(err)
}
}
// Testing if the current go module is returned
func TestNewProject_GetCurrentGoModule(t *testing.T) {
// Create a new variable of type NewProject
var np NewProject
path, err := config.GetPathP2PRC()
if err != nil {
fmt.Println(err)
t.Error(err)
}
// Set Current project path
np.P2PRCPath = path
// Get module name
err = np.GetCurrentGoModule()
if err != nil {
fmt.Println(err)
t.Error(err)
}
fmt.Println(np.CurrentModule)
}

View File

@@ -1,49 +0,0 @@
package generate
import (
"go/parser"
"go/printer"
"go/token"
"os"
)
// GetASTGoFile Gets AST of the Go file provided
func (np *NewProject)GetASTGoFile() error{
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, np.FileNameAST, nil, parser.ParseComments)
if err != nil {
return err
}
//Write Token information to the struct
np.Token = fset
// Write AST information the struct
np.AST = node
return nil
}
// ChangeImports Changes import of the AST
func (np *NewProject)ChangeImports(CurrentImport string,ChangedImport string) error {
// Iterating through the loop and changing the appropriate import
for i, spec := range np.AST.Imports {
// If the current import is found then change it
if spec.Path.Value == "\"" + CurrentImport + "\"" {
np.AST.Imports[i].Path.Value = "\"" + ChangedImport + "\""
}
}
return nil
}
// WriteGoAst Write changed imports back to the AST
func (np *NewProject)WriteGoAst() error {
// write new AST to file
f, err := os.Create(np.FileNameAST)
if err != nil {
return nil
}
defer f.Close()
if err := printer.Fprint(f, np.Token, np.AST); err != nil {
return err
}
return nil
}

View File

@@ -1,9 +0,0 @@
package generate
import (
"fmt"
)
func TestCaseAST() {
fmt.Println("lol")
}

11
go.mod
View File

@@ -3,28 +3,25 @@ module github.com/Akilan1999/p2p-rendering-computation
go 1.15
require (
github.com/Microsoft/hcsshim v0.8.15 // indirect
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 // indirect
github.com/apenella/go-ansible v1.1.0
github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5 // indirect
github.com/containerd/containerd v1.5.0-beta.1 // indirect
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible
github.com/docker/go-connections v0.4.0
github.com/docker/go-connections v0.4.0 // indirect
github.com/fatedier/frp v0.45.0
github.com/gin-gonic/gin v1.6.3
github.com/go-git/go-git/v5 v5.4.2
github.com/google/uuid v1.3.0
github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e
github.com/lithammer/shortuuid v3.0.0+incompatible
github.com/moby/sys/mount v0.2.0 // indirect
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/otiai10/copy v1.6.0
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/shirou/gopsutil/v3 v3.22.10
github.com/spf13/viper v1.7.0
github.com/urfave/cli/v2 v2.3.0
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
golang.org/x/crypto v0.16.0
gopkg.in/yaml.v2 v2.4.0
gotest.tools/v3 v3.0.3 // indirect
)

52
go.sum
View File

@@ -65,7 +65,6 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
@@ -80,8 +79,6 @@ github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3h
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
github.com/Microsoft/hcsshim v0.8.15 h1:Aof83YILRs2Vx3GhHqlvvfyx1asRJKMFIMeVlHsZKtI=
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@@ -156,7 +153,6 @@ github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLE
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102 h1:Qf4HiqfvmB7zS6scsmNgTLmByHbq8n9RTF39v+TzP7A=
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
@@ -175,8 +171,6 @@ github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5 h1:k6Dn7shF+i1q4utvCyW4+o9REsCMAeRyORM5IhXMCnw=
github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
@@ -285,7 +279,6 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
@@ -369,7 +362,6 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -451,8 +443,6 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e h1:XmA6L9IPRdUr28a+SK/oMchGgQy159wvzXA5tJ7l+40=
github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e/go.mod h1:AFIo+02s+12CEg8Gzz9kzhCbmbq6JcKNrhHffCGA9z4=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@@ -486,7 +476,6 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
@@ -558,7 +547,6 @@ github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHT
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -589,13 +577,9 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
github.com/moby/sys/mountinfo v0.4.0 h1:1KInV3Huv18akCu58V7lzNlt+jFmqlu1EaErnEHE/VM=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
@@ -655,7 +639,6 @@ github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5X
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -674,7 +657,6 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9
github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E=
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
@@ -770,24 +752,19 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -807,7 +784,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -878,7 +854,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -903,8 +878,9 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -941,8 +917,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1001,8 +977,10 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1033,8 +1011,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1130,11 +1108,17 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1143,8 +1127,11 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1215,6 +1202,7 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

4
install-binary.bat Normal file
View File

@@ -0,0 +1,4 @@
setx PATH "%PATH%;%cd%"
setx P2PRC "%cd%"
p2p-rendering-computation.exe --dc

8
install-binary.sh Normal file
View File

@@ -0,0 +1,8 @@
# This script setups up the project P2PRC
echo '# Add the following paths to .bashrc or .zshrc based on the configuration you have set'
echo export P2PRC=$PWD
echo export PATH=$PWD:\${PATH}
export P2PRC=${PWD}
export PATH=${PWD}:${PATH}
./p2p-rendering-computation --dc

31
main.go
View File

@@ -1,14 +1,15 @@
package main
import (
"github.com/Akilan1999/p2p-rendering-computation/cmd"
"github.com/urfave/cli/v2"
"log"
"os"
"log"
"os"
"github.com/Akilan1999/p2p-rendering-computation/cmd"
"github.com/urfave/cli/v2"
)
// VERSION specifies the version of the platform
var VERSION = "1.5.0"
var VERSION = "2.0.0"
var mode string
// Varaibles if mode is client
@@ -16,15 +17,15 @@ var OS, Pull_location, Run_script string
var List_servers, Ip_table bool
func main() {
app := cli.NewApp()
app.Name = "p2p-rendering-computation"
app.Usage = "p2p cli application to create and access VMs in other servers"
app.Version = VERSION
app.Flags = cmd.AppConfigFlags
app.Action = cmd.CliAction
app := cli.NewApp()
app.Name = "p2p-rendering-computation"
app.Usage = "p2p cli application to create and access VMs in other servers"
app.Version = VERSION
app.Flags = cmd.AppConfigFlags
app.Action = cmd.CliAction
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}

View File

@@ -1,165 +1,178 @@
package frp
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/pkg/config"
"github.com/phayes/freeport"
"math/rand"
"strconv"
"time"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/pkg/config"
"math/rand"
"strconv"
"time"
"github.com/phayes/freeport"
)
// Client This struct stores
// client information with server
// proxy connected
type Client struct {
Name string
Server *Server
ClientMappings []ClientMapping
Name string
Server *Server
ClientMappings []ClientMapping
}
// ClientMapping Stores client mapping ports
// to proxy server
type ClientMapping struct {
LocalIP string
LocalPort int
RemotePort int
LocalIP string
LocalPort int
RemotePort int
}
// StartFRPClientForServer Starts Server using FRP server
// returns back a port
func StartFRPClientForServer(ipaddress string, port string, localport string) (string, error) {
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return "", err
}
s.port = portInt
// remote port is a custom external port a user would want
// to open. This under the assumption the user knows the
// exact port available in server doing the TURN connection.
func StartFRPClientForServer(ipaddress string, port string, localport string, remoteport string) (string, error) {
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return "", err
}
s.port = portInt
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// converts localport to int
portInt, err = strconv.Atoi(localport)
if err != nil {
return "", err
}
// converts localport to int
portInt, err = strconv.Atoi(localport)
if err != nil {
return "", err
}
//random port
//randPort := rangeIn(10000, 99999)
OpenPorts, err := freeport.GetFreePorts(1)
if err != nil {
return "", err
}
c.ClientMappings = []ClientMapping{
{
LocalIP: "localhost",
LocalPort: portInt,
RemotePort: OpenPorts[0],
},
}
var OpenPorts []int
// if the remote port is
// not empty then set the remote port to that.
if remoteport != "" {
// converts localport to int
portIntRemote, err := strconv.Atoi(remoteport)
if err != nil {
return "", err
}
OpenPorts = append(OpenPorts, portIntRemote)
} else {
//random port
//randPort := rangeIn(10000, 99999)
OpenPorts, err = freeport.GetFreePorts(1)
if err != nil {
return "", err
}
}
c.ClientMappings = []ClientMapping{
{
LocalIP: "localhost",
LocalPort: portInt,
RemotePort: OpenPorts[0],
},
}
// Start client server
go c.StartFRPClient()
// Start client server
go c.StartFRPClient()
return strconv.Itoa(OpenPorts[0]), nil
return strconv.Itoa(OpenPorts[0]), nil
}
func StartFRPCDockerContainer(ipaddress string, port string, Docker *docker.DockerVM) (*docker.DockerVM, error) {
// setting new docker variable
// setting new docker variable
//var DockerFRP docker.DockerVM
//var DockerFRP docker.DockerVM
//DockerFRP = *Docker
//DockerFRP.Ports.PortSet = []docker.Port{}
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return nil, err
}
s.port = portInt
//DockerFRP = *Docker
//DockerFRP.Ports.PortSet = []docker.Port{}
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return nil, err
}
s.port = portInt
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// set client mapping
//var clientMappings []ClientMapping
fmt.Println(len(Docker.Ports.PortSet))
for i, _ := range Docker.Ports.PortSet {
portMap := Docker.Ports.PortSet[i].ExternalPort
// set client mapping
//var clientMappings []ClientMapping
for i, _ := range Docker.Ports.PortSet {
portMap := Docker.Ports.PortSet[i].ExternalPort
serverPort, err := GetFRPServerPort("http://" + ipaddress + ":" + port)
if err != nil {
return nil, err
}
serverPort, err := GetFRPServerPort("http://" + ipaddress + ":" + port)
if err != nil {
return nil, err
}
//delay to allow the FRP server to start
time.Sleep(1 * time.Second)
//delay to allow the FRP server to start
time.Sleep(1 * time.Second)
proxyPort, err := StartFRPClientForServer(ipaddress, serverPort, strconv.Itoa(portMap))
if err != nil {
return nil, err
}
proxyPort, err := StartFRPClientForServer(ipaddress, serverPort, strconv.Itoa(portMap), "")
if err != nil {
return nil, err
}
portInt, err = strconv.Atoi(proxyPort)
if err != nil {
return nil, err
}
portInt, err = strconv.Atoi(proxyPort)
if err != nil {
return nil, err
}
Docker.Ports.PortSet[i].ExternalPort = portInt
}
Docker.Ports.PortSet[i].ExternalPort = portInt
}
return Docker, nil
return Docker, nil
}
// StartFRPClient Starts FRP client
func (c *Client) StartFRPClient() error {
cfg := config.GetDefaultClientConf()
cfg := config.GetDefaultClientConf()
var proxyConfs map[string]config.ProxyConf
var visitorCfgs map[string]config.VisitorConf
var proxyConfs map[string]config.ProxyConf
var visitorCfgs map[string]config.VisitorConf
proxyConfs = make(map[string]config.ProxyConf)
proxyConfs = make(map[string]config.ProxyConf)
cfg.ServerAddr = c.Server.address
cfg.ServerPort = c.Server.port
cfg.ServerAddr = c.Server.address
cfg.ServerPort = c.Server.port
for i, _ := range c.ClientMappings {
var tcpcnf config.TCPProxyConf
tcpcnf.LocalIP = c.ClientMappings[i].LocalIP
tcpcnf.LocalPort = c.ClientMappings[i].LocalPort
tcpcnf.RemotePort = c.ClientMappings[i].RemotePort
for i, _ := range c.ClientMappings {
var tcpcnf config.TCPProxyConf
tcpcnf.LocalIP = c.ClientMappings[i].LocalIP
tcpcnf.LocalPort = c.ClientMappings[i].LocalPort
tcpcnf.RemotePort = c.ClientMappings[i].RemotePort
proxyConfs[tcpcnf.ProxyName] = &tcpcnf
}
proxyConfs[tcpcnf.ProxyName] = &tcpcnf
}
cli, err := client.NewService(cfg, proxyConfs, visitorCfgs, "")
if err != nil {
return err
}
cli, err := client.NewService(cfg, proxyConfs, visitorCfgs, "")
if err != nil {
return err
}
cli.Run()
cli.Run()
return nil
return nil
}
// helper function to generate random
// number in a certain range
func rangeIn(low, hi int) int {
return low + rand.Intn(hi-low)
return low + rand.Intn(hi-low)
}

View File

@@ -1,13 +1,16 @@
{
"ip_address": [
{
"Name": "Node1",
"IPV4": "64.227.168.102",
"IPV6": "",
"Latency": 0,
"ServerPort": "8088",
"NAT": "False",
"EscapeImplementation": "None"
}
]
}
"ip_address": [
{
"Name": "Node1",
"IPV4": "139.59.162.154",
"IPV6": "",
"Latency": 0,
"Download": 0,
"Upload": 0,
"ServerPort": "8078",
"NAT": "False",
"EscapeImplementation": "",
"CustomInformation": null
}
]
}

View File

@@ -1,6 +1,8 @@
package p2p
import (
"bytes"
"crypto/sha256"
"encoding/json"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
@@ -25,8 +27,11 @@ type IpAddress struct {
Download float64 `json:"Download"`
Upload float64 `json:"Upload"`
ServerPort string `json:"ServerPort"`
BareMetalSSHPort string `json:"BareMetalSSHPort"`
NAT string `json:"NAT"`
EscapeImplementation string `json:"EscapeImplementation"`
CustomInformation string `json:"CustomInformation"`
//CustomInformationKey []byte `json:"CustomInformationKey"`
}
type IP struct {
@@ -36,7 +41,7 @@ type IP struct {
// ReadIpTable Read data from Ip tables from json file
func ReadIpTable() (*IpAddresses, error) {
// Get Path from config
config, err := config.ConfigInit()
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
@@ -101,7 +106,7 @@ func (i *IpAddresses) WriteIpTable() error {
}
// Get Path from config
config, err := config.ConfigInit()
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
@@ -117,17 +122,17 @@ func (i *IpAddresses) WriteIpTable() error {
// PrintIpTable Print Ip table data for Cli
func PrintIpTable() error {
table, err := ReadIpTable()
//
if err != nil {
return err
}
for i := 0; i < len(table.IpAddress); i++ {
fmt.Printf("\nMachine Name: %s\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\nbehindNAT: %s\nEscapeImplementation: %s\n-----------"+
"-----------------\n", table.IpAddress[i].Name, table.IpAddress[i].Ipv4, table.IpAddress[i].Ipv6,
table.IpAddress[i].Latency, table.IpAddress[i].ServerPort, table.IpAddress[i].NAT, table.IpAddress[i].EscapeImplementation)
}
//PrettyPrint(table)
//
//for i := 0; i < len(table.IpAddress); i++ {
// fmt.Printf("\nMachine Name: %s\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\nbehindNAT: %s\nEscapeImplementation: %s\n-----------"+
// "-----------------\n", table.IpAddress[i].Name, table.IpAddress[i].Ipv4, table.IpAddress[i].Ipv6,
// table.IpAddress[i].Latency, table.IpAddress[i].ServerPort, table.IpAddress[i].NAT, table.IpAddress[i].EscapeImplementation)
//}
PrettyPrint(table)
return nil
}
@@ -189,7 +194,7 @@ func CurrentPublicIP() (string, error) {
// GetCurrentIPV6 gets the current IPV6 address based on the interface
// specified in the config file
func GetCurrentIPV6() (string, error) {
Config, err := config.ConfigInit()
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return "", err
}
@@ -254,13 +259,36 @@ func Ip4or6(s string) string {
}
//func PrettyPrint(data interface{}) {
// var p []byte
// // var err := error
// p, err := json.MarshalIndent(data, "", "\t")
// if err != nil {
// fmt.Println(err)
// return
// }
// fmt.Printf("%s \n", p)
//}
func PrettyPrint(data interface{}) {
var p []byte
// var err := error
p, err := json.MarshalIndent(data, "", "\t")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s \n", p)
}
func GenerateHashSHA256(text string) []byte {
h := sha256.New()
h.Write([]byte(text))
return h.Sum(nil)
}
// ValidateHashSHA256 CustomInformationKey the text and check if the text and
// the hash are the same, if they are
// then return true
// SHA256 is the current hashing algorthm
// used.
func ValidateHashSHA256(text string, Hash []byte) bool {
h := sha256.New()
h.Write([]byte(text))
textHash := h.Sum(nil)
if bytes.Equal(textHash, Hash) {
return true
}
return false
}

View File

@@ -1,16 +1,16 @@
package p2p
import (
"bytes"
"errors"
"github.com/Akilan1999/p2p-rendering-computation/config"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"os"
"time"
"bytes"
"errors"
"github.com/Akilan1999/p2p-rendering-computation/config"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"os"
"time"
)
// var dlSizes = [...]int{350, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000}
@@ -80,100 +80,100 @@ var httpclient = http.Client{}
// Download Speed
func (s *IpAddress) DownloadSpeed() error {
start := time.Now()
resp, err := httpclient.Get("http://" + s.Ipv4 + ":8088/50")
if err != nil {
return err
}
defer resp.Body.Close()
ioutil.ReadAll(resp.Body)
t := time.Since(start)
//fmt.Println(s.Seconds())
// size * time (seconds)
s.Download = (50 / t.Seconds()) * 8
return nil
start := time.Now()
resp, err := httpclient.Get("http://" + s.Ipv4 + ":8088/50")
if err != nil {
return err
}
defer resp.Body.Close()
ioutil.ReadAll(resp.Body)
t := time.Since(start)
//fmt.Println(s.Seconds())
// size * time (seconds)
s.Download = (50 / t.Seconds()) * 8
return nil
}
func (s *IpAddress) UploadSpeed() error {
start := time.Now()
start := time.Now()
// Get upload file path from config file
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
return err
}
// Get upload file path from config file
// Get Path from config
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
b, w := createMultipartFormData("file", config.SpeedTestFile)
b, w := createMultipartFormData("file", config.SpeedTestFile)
req, err := http.NewRequest("GET", "http://"+s.Ipv4+":"+s.ServerPort+"/upload", &b)
if err != nil {
return err
}
// Don't forget to set the content type, this will contain the boundary.
req.Header.Set("Content-Type", w.FormDataContentType())
defer req.Body.Close()
ioutil.ReadAll(req.Body)
t := time.Since(start)
//fmt.Println(s.Seconds())
// size * time (seconds)
s.Upload = (50 / t.Seconds()) * 8
return nil
req, err := http.NewRequest("GET", "http://"+s.Ipv4+":"+s.ServerPort+"/upload", &b)
if err != nil {
return err
}
// Don't forget to set the content type, this will contain the boundary.
req.Header.Set("Content-Type", w.FormDataContentType())
defer req.Body.Close()
ioutil.ReadAll(req.Body)
t := time.Since(start)
//fmt.Println(s.Seconds())
// size * time (seconds)
s.Upload = (50 / t.Seconds()) * 8
return nil
}
// Upload helper function for uploading
// (https://stackoverflow.com/questions/20205796/post-data-using-the-content-type-multipart-form-data
func createMultipartFormData(fieldName, fileName string) (bytes.Buffer, *multipart.Writer) {
var b bytes.Buffer
var err error
w := multipart.NewWriter(&b)
var fw io.Writer
file := mustOpen(fileName)
if fw, err = w.CreateFormFile(fieldName, file.Name()); err != nil {
log.Fatalf("Error creating writer: %v", err)
}
if _, err = io.Copy(fw, file); err != nil {
log.Fatalf("Error with io.Copy: %v", err)
//t.Errorf("Error with io.Copy: %v", err)
}
w.Close()
return b, w
var b bytes.Buffer
var err error
w := multipart.NewWriter(&b)
var fw io.Writer
file := mustOpen(fileName)
if fw, err = w.CreateFormFile(fieldName, file.Name()); err != nil {
log.Fatalf("Error creating writer: %v", err)
}
if _, err = io.Copy(fw, file); err != nil {
log.Fatalf("Error with io.Copy: %v", err)
//t.Errorf("Error with io.Copy: %v", err)
}
w.Close()
return b, w
}
func mustOpen(f string) *os.File {
r, err := os.Open(f)
if err != nil {
log.Fatalf("Error with mustOpen: %v", err)
}
return r
r, err := os.Open(f)
if err != nil {
log.Fatalf("Error with mustOpen: %v", err)
}
return r
}
// PingTest executes test to measure latency
func (s *IpAddress) PingTest() error {
//pingURL := strings.Split(s.URL, "/upload")[0] + "/latency.txt"
var pingURL string
if s.Ipv6 != "" {
pingURL = "http://[" + s.Ipv6 + "]:" + s.ServerPort + "/server_info"
s.Ipv4 = ""
} else {
pingURL = "http://" + s.Ipv4 + ":" + s.ServerPort + "/server_info"
}
//pingURL := strings.Split(s.URL, "/upload")[0] + "/latency.txt"
var pingURL string
if s.Ipv6 != "" {
pingURL = "http://[" + s.Ipv6 + "]:" + s.ServerPort + "/server_info"
s.Ipv4 = ""
} else {
pingURL = "http://" + s.Ipv4 + ":" + s.ServerPort + "/server_info"
}
l := time.Duration(100000000000) // 10sec
for i := 0; i < 3; i++ {
sTime := time.Now()
resp, err := http.Get(pingURL)
fTime := time.Now()
if err != nil || resp.StatusCode != 200 {
return errors.New("Node not found")
}
if fTime.Sub(sTime) < l {
l = fTime.Sub(sTime)
}
resp.Body.Close()
}
l := time.Duration(100000000000) // 10sec
for i := 0; i < 3; i++ {
sTime := time.Now()
resp, err := http.Get(pingURL)
fTime := time.Now()
if err != nil || resp.StatusCode != 200 {
return errors.New("Node not found")
}
if fTime.Sub(sTime) < l {
l = fTime.Sub(sTime)
}
resp.Body.Close()
}
s.Latency = time.Duration(int64(l.Nanoseconds() / 2))
s.Latency = time.Duration(int64(l.Nanoseconds() / 2))
return nil
return nil
}

View File

@@ -1,64 +1,64 @@
package plugin
import (
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/go-git/go-git/v5"
"net/url"
"os"
"strings"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/go-git/go-git/v5"
"net/url"
"os"
"strings"
)
// DownloadPlugin This functions downloads package from
// a git repo.
func DownloadPlugin(pluginurl string) error {
// paring plugin url
u, err := url.Parse(pluginurl)
if err != nil {
return err
}
path := u.Path
// Trim first character of the string
path = path[1:]
// trim last element of the string
path = path[:len(path)-1]
// Replaces / with _
folder := strings.Replace(path, "/", "_", -1)
// Reads plugin path from the config path
config, err := config.ConfigInit()
if err != nil {
return err
}
// clones a repo and stores it at the plugin directory
_, err = git.PlainClone(config.PluginPath+"/"+folder, false, &git.CloneOptions{
URL: pluginurl,
Progress: os.Stdout,
})
// returns error if raised
if err != nil {
return err
}
// paring plugin url
u, err := url.Parse(pluginurl)
if err != nil {
return err
}
path := u.Path
// Trim first character of the string
path = path[1:]
// trim last element of the string
path = path[:len(path)-1]
// Replaces / with _
folder := strings.Replace(path, "/", "_", -1)
// Reads plugin path from the config path
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
// clones a repo and stores it at the plugin directory
_, err = git.PlainClone(config.PluginPath+"/"+folder, false, &git.CloneOptions{
URL: pluginurl,
Progress: os.Stdout,
})
// returns error if raised
if err != nil {
return err
}
return nil
return nil
}
// DeletePlugin The following function deletes a plugin based on
// the plugin name provided.
func DeletePlugin(pluginname string) error {
config, err := config.ConfigInit()
if err != nil {
return err
}
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
}
plugin, err := SearchPlugin(pluginname)
if err != nil {
return err
}
plugin, err := SearchPlugin(pluginname)
if err != nil {
return err
}
// Delete the directory holding the plugin
err = os.RemoveAll(config.PluginPath + "/" + plugin.FolderName)
if err != nil {
return err
}
// Delete the directory holding the plugin
err = os.RemoveAll(config.PluginPath + "/" + plugin.FolderName)
if err != nil {
return err
}
return nil
return nil
}

View File

@@ -1,362 +1,362 @@
package plugin
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/google/uuid"
"gopkg.in/yaml.v2"
"io/ioutil"
"net"
"os"
"strconv"
"text/template"
"context"
"encoding/json"
"errors"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/google/uuid"
"gopkg.in/yaml.v2"
"io/ioutil"
"net"
"os"
"strconv"
"text/template"
"github.com/apenella/go-ansible/pkg/execute"
"github.com/apenella/go-ansible/pkg/options"
"github.com/apenella/go-ansible/pkg/playbook"
"github.com/apenella/go-ansible/pkg/stdoutcallback/results"
"github.com/otiai10/copy"
"github.com/apenella/go-ansible/pkg/execute"
"github.com/apenella/go-ansible/pkg/options"
"github.com/apenella/go-ansible/pkg/playbook"
"github.com/apenella/go-ansible/pkg/stdoutcallback/results"
"github.com/otiai10/copy"
)
// Plugins Array of all plugins detected
type Plugins struct {
PluginsDetected []*Plugin
PluginsDetected []*Plugin
}
// Plugin Information about the plugins available
type Plugin struct {
FolderName string
PluginDescription string
path string
Execute []*ExecuteIP
NumOfPorts int
FolderName string
PluginDescription string
path string
Execute []*ExecuteIP
NumOfPorts int
}
// ExecuteIP IP Address to execute Ansible instruction
type ExecuteIP struct {
ContainerID string
IPAddress string
SSHPortNo string
Success bool
ContainerID string
IPAddress string
SSHPortNo string
Success bool
}
// Host Struct for ansible host
// Generated from https://zhwt.github.io/yaml-to-go/
type Host struct {
All struct {
Vars struct {
AnsiblePythonInterpreter string `yaml:"ansible_python_interpreter"`
} `yaml:"vars"`
} `yaml:"all"`
Main struct {
Hosts struct {
Host1 struct {
AnsibleHost string `yaml:"ansible_host"`
AnsiblePort int `yaml:"ansible_port"`
AnsibleUser string `yaml:"ansible_user"`
AnsibleSSHPass string `yaml:"ansible_ssh_pass"`
AnsibleSudoPass string `yaml:"ansible_sudo_pass"`
} `yaml:"host1"`
} `yaml:"hosts"`
} `yaml:"main"`
All struct {
Vars struct {
AnsiblePythonInterpreter string `yaml:"ansible_python_interpreter"`
} `yaml:"vars"`
} `yaml:"all"`
Main struct {
Hosts struct {
Host1 struct {
AnsibleHost string `yaml:"ansible_host"`
AnsiblePort int `yaml:"ansible_port"`
AnsibleUser string `yaml:"ansible_user"`
AnsibleSSHPass string `yaml:"ansible_ssh_pass"`
AnsibleSudoPass string `yaml:"ansible_sudo_pass"`
} `yaml:"host1"`
} `yaml:"hosts"`
} `yaml:"main"`
}
// DetectPlugins Detects all the plugins available
func DetectPlugins() (*Plugins, error) {
config, err := config.ConfigInit()
if err != nil {
return nil, err
}
folders, err := ioutil.ReadDir(config.PluginPath)
if err != nil {
return nil, err
}
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
folders, err := ioutil.ReadDir(config.PluginPath)
if err != nil {
return nil, err
}
var plugins *Plugins = new(Plugins)
var plugins *Plugins = new(Plugins)
for _, f := range folders {
if f.IsDir() {
//Declare variable plugin of type Plugin
var plugin Plugin
for _, f := range folders {
if f.IsDir() {
//Declare variable plugin of type Plugin
var plugin Plugin
// Setting name of folder to plugin
plugin.FolderName = f.Name()
// Getting Description from file description.txt
Description, err := ioutil.ReadFile(config.PluginPath + "/" + plugin.FolderName + "/description.txt")
// if we os.Open returns an error then handle it
if err != nil {
return nil, err
}
// Setting name of folder to plugin
plugin.FolderName = f.Name()
// Getting Description from file description.txt
Description, err := ioutil.ReadFile(config.PluginPath + "/" + plugin.FolderName + "/description.txt")
// if we os.Open returns an error then handle it
if err != nil {
return nil, err
}
// Get Description from description.txt
plugin.PluginDescription = string(Description)
// Set plugin path
plugin.path = config.PluginPath + "/" + plugin.FolderName
// Get Description from description.txt
plugin.PluginDescription = string(Description)
// Set plugin path
plugin.path = config.PluginPath + "/" + plugin.FolderName
plugins.PluginsDetected = append(plugins.PluginsDetected, &plugin)
// Get the number of ports the plugin needs
err = plugin.NumPorts()
if err != nil {
return nil, err
}
}
}
plugins.PluginsDetected = append(plugins.PluginsDetected, &plugin)
// Get the number of ports the plugin needs
err = plugin.NumPorts()
if err != nil {
return nil, err
}
}
}
return plugins, nil
return plugins, nil
}
// SearchPlugin Detects plugin information based on the
// name provided on the parameter
func SearchPlugin(pluginname string) (*Plugin, error) {
plugins, err := DetectPlugins()
if err != nil {
return nil, err
}
plugins, err := DetectPlugins()
if err != nil {
return nil, err
}
// loop ot find the plugin name that matches
for _, plugin := range plugins.PluginsDetected {
if pluginname == plugin.FolderName {
return plugin, nil
}
}
// loop ot find the plugin name that matches
for _, plugin := range plugins.PluginsDetected {
if pluginname == plugin.FolderName {
return plugin, nil
}
}
return nil, errors.New("plugin not detected")
return nil, errors.New("plugin not detected")
}
// RunPlugin Executes plugins based on the plugin name provided
func RunPlugin(pluginName string, IPAddresses []*ExecuteIP) (*Plugin, error) {
plugins, err := DetectPlugins()
if err != nil {
return nil, err
}
plugins, err := DetectPlugins()
if err != nil {
return nil, err
}
// Variable to store struct information about the plugin
var plugindetected *Plugin
for _, plugin := range plugins.PluginsDetected {
if plugin.FolderName == pluginName {
plugindetected = plugin
plugindetected.Execute = IPAddresses
// Get Execute plugin path from config file
config, err := config.ConfigInit()
if err != nil {
return nil, err
}
plugindetected.path = config.PluginPath
break
}
}
// Variable to store struct information about the plugin
var plugindetected *Plugin
for _, plugin := range plugins.PluginsDetected {
if plugin.FolderName == pluginName {
plugindetected = plugin
plugindetected.Execute = IPAddresses
// Get Execute plugin path from config file
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
plugindetected.path = config.PluginPath
break
}
}
if plugindetected == nil {
return nil, errors.New("Plugin not detected")
}
if plugindetected == nil {
return nil, errors.New("Plugin not detected")
}
// Create copy of the plugin the tmp directory
// To ensure we execute the plugin from there
err = plugindetected.CopyToTmpPlugin()
if err != nil {
return nil, err
}
// Create copy of the plugin the tmp directory
// To ensure we execute the plugin from there
err = plugindetected.CopyToTmpPlugin()
if err != nil {
return nil, err
}
// Executing the plugin
err = plugindetected.ExecutePlugin()
if err != nil {
return nil, err
}
// Executing the plugin
err = plugindetected.ExecutePlugin()
if err != nil {
return nil, err
}
return plugindetected, nil
return plugindetected, nil
}
// ExecutePlugin Function to execute plugins that are called
func (p *Plugin) ExecutePlugin() error {
// Run ip address to execute ansible inside
for _, execute := range p.Execute {
// Modify ansible hosts before executing
err := execute.ModifyHost(p)
if err != nil {
return err
}
// sets the ports to the plugin folder
err = p.AutoSetPorts(execute.ContainerID)
if err != nil {
return err
}
err = execute.RunAnsible(p)
if err != nil {
return err
}
// If ran successfully then change success flag to true
execute.Success = true
}
return nil
// Run ip address to execute ansible inside
for _, execute := range p.Execute {
// Modify ansible hosts before executing
err := execute.ModifyHost(p)
if err != nil {
return err
}
// sets the ports to the plugin folder
err = p.AutoSetPorts(execute.ContainerID)
if err != nil {
return err
}
err = execute.RunAnsible(p)
if err != nil {
return err
}
// If ran successfully then change success flag to true
execute.Success = true
}
return nil
}
// RunAnsible Executes based on credentials on the struct
func (e *ExecuteIP) RunAnsible(p *Plugin) error {
ansiblePlaybookConnectionOptions := &options.AnsibleConnectionOptions{
User: "master",
}
ansiblePlaybookConnectionOptions := &options.AnsibleConnectionOptions{
User: "master",
}
ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{
Inventory: p.path + "/" + p.FolderName + "/hosts",
ExtraVars: map[string]interface{}{"ansible_ssh_common_args": "-o StrictHostKeyChecking=no"},
}
ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{
Inventory: p.path + "/" + p.FolderName + "/hosts",
ExtraVars: map[string]interface{}{"ansible_ssh_common_args": "-o StrictHostKeyChecking=no"},
}
ansiblePlaybookPrivilegeEscalationOptions := &options.AnsiblePrivilegeEscalationOptions{
Become: true,
}
ansiblePlaybookPrivilegeEscalationOptions := &options.AnsiblePrivilegeEscalationOptions{
Become: true,
}
playbook := &playbook.AnsiblePlaybookCmd{
Playbooks: []string{p.path + "/" + p.FolderName + "/site.yml"},
ConnectionOptions: ansiblePlaybookConnectionOptions,
PrivilegeEscalationOptions: ansiblePlaybookPrivilegeEscalationOptions,
Options: ansiblePlaybookOptions,
Exec: execute.NewDefaultExecute(
execute.WithTransformers(
results.Prepend("success"),
),
),
}
playbook := &playbook.AnsiblePlaybookCmd{
Playbooks: []string{p.path + "/" + p.FolderName + "/site.yml"},
ConnectionOptions: ansiblePlaybookConnectionOptions,
PrivilegeEscalationOptions: ansiblePlaybookPrivilegeEscalationOptions,
Options: ansiblePlaybookOptions,
Exec: execute.NewDefaultExecute(
execute.WithTransformers(
results.Prepend("success"),
),
),
}
err := playbook.Run(context.TODO())
if err != nil {
return err
}
err := playbook.Run(context.TODO())
if err != nil {
return err
}
return nil
return nil
}
// ModifyHost adds IP address , port no to the config file
func (e *ExecuteIP) ModifyHost(p *Plugin) error {
host, err := ReadHost(p.path + "/" + p.FolderName + "/hosts")
if err != nil {
return err
}
// Setting ansible host
host.Main.Hosts.Host1.AnsibleHost = e.IPAddress
// Setting SSH port no
host.Main.Hosts.Host1.AnsiblePort, err = strconv.Atoi(e.SSHPortNo)
if err != nil {
return err
}
// Setting SSH user name
host.Main.Hosts.Host1.AnsibleUser = "master"
// Setting SSH password
host.Main.Hosts.Host1.AnsibleSSHPass = "password"
// Setting SSH sudo password
host.Main.Hosts.Host1.AnsibleSudoPass = "password"
host, err := ReadHost(p.path + "/" + p.FolderName + "/hosts")
if err != nil {
return err
}
// Setting ansible host
host.Main.Hosts.Host1.AnsibleHost = e.IPAddress
// Setting SSH port no
host.Main.Hosts.Host1.AnsiblePort, err = strconv.Atoi(e.SSHPortNo)
if err != nil {
return err
}
// Setting SSH user name
host.Main.Hosts.Host1.AnsibleUser = "master"
// Setting SSH password
host.Main.Hosts.Host1.AnsibleSSHPass = "password"
// Setting SSH sudo password
host.Main.Hosts.Host1.AnsibleSudoPass = "password"
// write modified information to the hosts yaml file
data, err := yaml.Marshal(host)
if err != nil {
return err
}
err = ioutil.WriteFile(p.path+"/"+p.FolderName+"/hosts", data, 0777)
if err != nil {
return err
}
return nil
// write modified information to the hosts yaml file
data, err := yaml.Marshal(host)
if err != nil {
return err
}
err = ioutil.WriteFile(p.path+"/"+p.FolderName+"/hosts", data, 0777)
if err != nil {
return err
}
return nil
}
// ReadHost Reads host file and adds
func ReadHost(filename string) (*Host, error) {
buf, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
buf, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
c := &Host{}
err = yaml.Unmarshal(buf, c)
if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err)
}
c := &Host{}
err = yaml.Unmarshal(buf, c)
if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err)
}
return c, nil
return c, nil
}
// RunPluginContainer Runs ansible plugin based on plugin name and container name which
// is derived from the tracked containers file
// We pass in the group ID as a parameter because when we modify the ports taken
func RunPluginContainer(PluginName string, ContainerID string) error {
// Gets container information based on container ID
ContainerInformation, err := client.GetContainerInformation(ContainerID)
if err != nil {
return err
}
// Gets container information based on container ID
ContainerInformation, err := client.GetContainerInformation(ContainerID)
if err != nil {
return err
}
// Setting Up IP's for which the plugins will be executed
var ExecuteIPs []*ExecuteIP
var ExecuteIP ExecuteIP
// Getting port no of SSH port
for _, port := range ContainerInformation.Container.Ports.PortSet {
if port.PortName == "SSH" {
ExecuteIP.SSHPortNo = fmt.Sprint(port.ExternalPort)
break
}
}
// Handle error if SSH port is not provided
if ExecuteIP.SSHPortNo == "" {
return errors.New("SSH port not found")
}
// Split the port no from ip address since current the IP address
// field is populated as
// <ip address>:<port no>
// Setting Up IP's for which the plugins will be executed
var ExecuteIPs []*ExecuteIP
var ExecuteIP ExecuteIP
// Getting port no of SSH port
for _, port := range ContainerInformation.Container.Ports.PortSet {
if port.PortName == "SSH" {
ExecuteIP.SSHPortNo = fmt.Sprint(port.ExternalPort)
break
}
}
// Handle error if SSH port is not provided
if ExecuteIP.SSHPortNo == "" {
return errors.New("SSH port not found")
}
// Split the port no from ip address since current the IP address
// field is populated as
// <ip address>:<port no>
host, _, err := net.SplitHostPort(ContainerInformation.IpAddress)
if err != nil {
return err
}
// IP address of the container
ExecuteIP.IPAddress = host
// Set container ID to ExecutorIP
ExecuteIP.ContainerID = ContainerInformation.Id
// Append IP to list of executor IP
ExecuteIPs = append(ExecuteIPs, &ExecuteIP)
// Run plugin to execute plugin
_, err = RunPlugin(PluginName, ExecuteIPs)
if err != nil {
return err
}
host, _, err := net.SplitHostPort(ContainerInformation.IpAddress)
if err != nil {
return err
}
// IP address of the container
ExecuteIP.IPAddress = host
// Set container ID to ExecutorIP
ExecuteIP.ContainerID = ContainerInformation.Id
// Append IP to list of executor IP
ExecuteIPs = append(ExecuteIPs, &ExecuteIP)
// Run plugin to execute plugin
_, err = RunPlugin(PluginName, ExecuteIPs)
if err != nil {
return err
}
return nil
return nil
}
// CheckRunPlugin Checks if the ID belongs to the group or container
// calls the plugin function the appropriate amount of times
func CheckRunPlugin(PluginName string, ID string) error {
// Check if the ID belongs to the group or container ID
id, err := client.CheckID(ID)
if err != nil {
return err
}
// When the ID belongs to a group
if id == "group" {
// gets the group information
group, err := client.GetGroup(ID)
if err != nil {
return err
}
// Iterate through each container information in the group
// and run the plugin in each of them
for _, container := range group.TrackContainerList {
// runs plugin for each container
err := RunPluginContainer(PluginName, container.Id)
if err != nil {
return err
}
}
} else { // This means the following ID is a container ID
err := RunPluginContainer(PluginName, ID)
if err != nil {
return err
}
}
// Check if the ID belongs to the group or container ID
id, err := client.CheckID(ID)
if err != nil {
return err
}
// When the ID belongs to a group
if id == "group" {
// gets the group information
group, err := client.GetGroup(ID)
if err != nil {
return err
}
// Iterate through each container information in the group
// and run the plugin in each of them
for _, container := range group.TrackContainerList {
// runs plugin for each container
err := RunPluginContainer(PluginName, container.Id)
if err != nil {
return err
}
}
} else { // This means the following ID is a container ID
err := RunPluginContainer(PluginName, ID)
if err != nil {
return err
}
}
return nil
return nil
}
// CopyToTmpPlugin This function would ensure that we create a copy of the
@@ -364,101 +364,101 @@ func CheckRunPlugin(PluginName string, ID string) error {
// from there. This due to the reason of automating port allocation
// when running plugins
func (p *Plugin) CopyToTmpPlugin() 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(p.path+"/"+p.FolderName, "/tmp/"+id.String()+"_"+p.FolderName)
if err != nil {
return err
}
// 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(p.path+"/"+p.FolderName, "/tmp/"+id.String()+"_"+p.FolderName)
if err != nil {
return err
}
// Set the plugin execution to the tmp location
p.path = "/tmp"
p.FolderName = id.String() + "_" + p.FolderName
// Set the plugin execution to the tmp location
p.path = "/tmp"
p.FolderName = id.String() + "_" + p.FolderName
return nil
return nil
}
// AutoSetPorts Automatically maps free ports to site.yml file
func (p *Plugin) AutoSetPorts(containerID string) error {
container, err := client.GetContainerInformation(containerID)
if err != nil {
return err
}
// variable that would have a list of ports
// to be allocated to the plugin system
var ports []int
// Counted that increments when a port is taken
PortTaken := 0
// setting all external ports available in an array
for i, port := range container.Container.Ports.PortSet {
if port.IsUsed == false {
// Ensuring we break outside the loop once the ports
// are set.
if PortTaken >= p.NumOfPorts {
break
}
// Setting the following port flag to true
container.Container.Ports.PortSet[i].IsUsed = true
// Incrementing the variable PortTaken
PortTaken++
// Maps to internal since
// Inside the machine
// internal port -> (maps) same internal port
// TURN (i.e FRP) based approach (internal port -> maps to different external port)
ports = append(ports, port.InternalPort)
}
}
container, err := client.GetContainerInformation(containerID)
if err != nil {
return err
}
// variable that would have a list of ports
// to be allocated to the plugin system
var ports []int
// Counted that increments when a port is taken
PortTaken := 0
// setting all external ports available in an array
for i, port := range container.Container.Ports.PortSet {
if port.IsUsed == false {
// Ensuring we break outside the loop once the ports
// are set.
if PortTaken >= p.NumOfPorts {
break
}
// Setting the following port flag to true
container.Container.Ports.PortSet[i].IsUsed = true
// Incrementing the variable PortTaken
PortTaken++
// Maps to internal since
// Inside the machine
// internal port -> (maps) same internal port
// TURN (i.e FRP) based approach (internal port -> maps to different external port)
ports = append(ports, port.InternalPort)
}
}
// parses the site.yml file in the tmp directory
t, err := template.ParseFiles(p.path + "/" + p.FolderName + "/site.yml")
if err != nil {
return err
}
// opens the output file
f, err := os.Create(p.path + "/" + p.FolderName + "/site.yml")
if err != nil {
return err
}
// sends the ports to the site.yml file to populate them
err = t.Execute(f, ports)
if err != nil {
return err
}
// Once the following is done set port to taken
// n tracked container list
err = container.ModifyContainerInformation()
if err != nil {
return err
}
// Once the following is done set port to taken
// I(Groups)
err = container.ModifyContainerGroups()
if err != nil {
return err
}
// parses the site.yml file in the tmp directory
t, err := template.ParseFiles(p.path + "/" + p.FolderName + "/site.yml")
if err != nil {
return err
}
// opens the output file
f, err := os.Create(p.path + "/" + p.FolderName + "/site.yml")
if err != nil {
return err
}
// sends the ports to the site.yml file to populate them
err = t.Execute(f, ports)
if err != nil {
return err
}
// Once the following is done set port to taken
// n tracked container list
err = container.ModifyContainerInformation()
if err != nil {
return err
}
// Once the following is done set port to taken
// I(Groups)
err = container.ModifyContainerGroups()
if err != nil {
return err
}
return nil
return nil
}
// NumPorts Gets the Number the ports the
// plugin requires
func (p *Plugin) NumPorts() error {
jsonFile, err := os.Open(p.path + "/ports.json")
// if we os.Open returns an error then handle it
if err != nil {
return err
}
jsonFile, err := os.Open(p.path + "/ports.json")
// if we os.Open returns an error then handle it
if err != nil {
return 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()
// read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile)
// read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile)
// we unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &p)
// we unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &p)
return nil
return nil
}

View File

@@ -1,257 +1,257 @@
package plugin
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"net"
"strconv"
"testing"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"net"
"strconv"
"testing"
)
// Test if the dummy plugin added is detected
func TestDetectPlugins(t *testing.T) {
_, err := DetectPlugins()
if err != nil {
t.Fail()
}
_, err := DetectPlugins()
if err != nil {
t.Fail()
}
}
// Test ensures that the ansible are executed inside local containers
func TestRunPlugin(t *testing.T) {
var testips []*ExecuteIP
var testip1, testip2 ExecuteIP
var testips []*ExecuteIP
var testip1, testip2 ExecuteIP
// Create docker container and get SSH port
container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Create docker container and get SSH port
container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
//Test IP 1 configuration
testip1.IPAddress = "0.0.0.0"
testip1.SSHPortNo = strconv.Itoa(container1.Ports.PortSet[0].ExternalPort)
//Test IP 1 configuration
testip1.IPAddress = "0.0.0.0"
testip1.SSHPortNo = strconv.Itoa(container1.Ports.PortSet[0].ExternalPort)
// Create docker container and get SSH port
container2, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
//Test IP 2 configuration
testip2.IPAddress = "0.0.0.0"
testip2.SSHPortNo = strconv.Itoa(container2.Ports.PortSet[0].ExternalPort)
// Create docker container and get SSH port
container2, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
//Test IP 2 configuration
testip2.IPAddress = "0.0.0.0"
testip2.SSHPortNo = strconv.Itoa(container2.Ports.PortSet[0].ExternalPort)
testips = append(testips, &testip1)
testips = append(testips, &testip2)
testips = append(testips, &testip1)
testips = append(testips, &testip2)
_, err = RunPlugin("TestAnsible", testips)
if err != nil {
fmt.Println(err)
t.Fail()
}
_, err = RunPlugin("TestAnsible", testips)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
err = docker.StopAndRemoveContainer(container2.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
err = docker.StopAndRemoveContainer(container2.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
}
// Test to ensure that the ansible host file is modified to
// the appropriate IP
func TestExecuteIP_ModifyHost(t *testing.T) {
var plugin Plugin
var testip ExecuteIP
var plugin Plugin
var testip ExecuteIP
// Get plugin path from config file
Config, err := config.ConfigInit()
if err != nil {
fmt.Println(err)
t.Fail()
}
//Set plugin name
plugin.FolderName = "TestAnsible"
plugin.path = Config.PluginPath
// Get plugin path from config file
Config, err := config.ConfigInit(nil, nil)
if err != nil {
fmt.Println(err)
t.Fail()
}
//Set plugin name
plugin.FolderName = "TestAnsible"
plugin.path = Config.PluginPath
//Test IP 1 configuration
testip.IPAddress = "0.0.0.0"
testip.SSHPortNo = "41289"
//Test IP 1 configuration
testip.IPAddress = "0.0.0.0"
testip.SSHPortNo = "41289"
err = testip.ModifyHost(&plugin)
if err != nil {
fmt.Println(err)
t.Fail()
}
err = testip.ModifyHost(&plugin)
if err != nil {
fmt.Println(err)
t.Fail()
}
}
// Test to ensure the cli function runs as intended and executes
// the test ansible script
func TestRunPluginContainer(t *testing.T) {
// Create docker container and get SSH port
container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Create docker container and get SSH port
container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Ensuring created container is the added to the tracked list
err = client.AddTrackContainer(container1, "0.0.0.0")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Ensuring created container is the added to the tracked list
err = client.AddTrackContainer(container1, "0.0.0.0")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Running test Ansible script
err = RunPluginContainer("TestAnsible", container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Running test Ansible script
err = RunPluginContainer("TestAnsible", container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removes container information from the tracker IP addresses
err = client.RemoveTrackedContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removes container information from the tracker IP addresses
err = client.RemoveTrackedContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
}
// Testing the function can plugin can run with
// group ID and container ID
func TestCheckRunPlugin(t *testing.T) {
// Create docker container and get SSH port
container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Create docker container and get SSH port
container2, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Create docker container and get SSH port
container1, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Create docker container and get SSH port
container2, err := docker.BuildRunContainer(0, "false", "")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Ensuring created container1 is the added to the tracked list
err = client.AddTrackContainer(container1, "0.0.0.0")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Ensuring created container2 is the added to the tracked list
err = client.AddTrackContainer(container2, "0.0.0.0")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Ensuring created container1 is the added to the tracked list
err = client.AddTrackContainer(container1, "0.0.0.0")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Ensuring created container2 is the added to the tracked list
err = client.AddTrackContainer(container2, "0.0.0.0")
if err != nil {
fmt.Println(err)
t.Fail()
}
// Create group to add created containers
group, err := client.CreateGroup()
if err != nil {
fmt.Println(err)
t.Fail()
}
// Create group to add created containers
group, err := client.CreateGroup()
if err != nil {
fmt.Println(err)
t.Fail()
}
// Add container 1 to the group
_, err = client.AddContainerToGroup(container1.ID, group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Add container 1 to the group
_, err = client.AddContainerToGroup(container1.ID, group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Add container 2 to the group
_, err = client.AddContainerToGroup(container2.ID, group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Add container 2 to the group
_, err = client.AddContainerToGroup(container2.ID, group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// -------------------------- Main test cases -------------------------------
// -------------------------- Main test cases -------------------------------
// Checking function against container ID
err = CheckRunPlugin("TestAnsible", container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Checking function against container ID
err = CheckRunPlugin("TestAnsible", container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Checking function against group ID
err = CheckRunPlugin("TestAnsible", group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Checking function against group ID
err = CheckRunPlugin("TestAnsible", group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Remove created group
err = client.RemoveGroup(group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Remove created group
err = client.RemoveGroup(group.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removes container1 information from the tracker IP addresses
err = client.RemoveTrackedContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removes container1 information from the tracker IP addresses
err = client.RemoveTrackedContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container1 after Ansible is executed
err = docker.StopAndRemoveContainer(container1.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removes container2 information from the tracker IP addresses
err = client.RemoveTrackedContainer(container2.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removes container2 information from the tracker IP addresses
err = client.RemoveTrackedContainer(container2.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container2 after Ansible is executed
err = docker.StopAndRemoveContainer(container2.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
// Removing container2 after Ansible is executed
err = docker.StopAndRemoveContainer(container2.ID)
if err != nil {
fmt.Println(err)
t.Fail()
}
}
func TestDownloadPlugin(t *testing.T) {
err := DownloadPlugin("https://github.com/Akilan1999/laplace/")
if err != nil {
err := DownloadPlugin("https://github.com/Akilan1999/laplace/")
if err != nil {
}
}
}
// Simple test case implemented to the test if
// the port no can be extracted from the IP address.
func TestParseIP(t *testing.T) {
host, port, err := net.SplitHostPort("12.34.23.13:5432")
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Printf("Host: %s\nPort: %s\n", host, port)
}
host, port, err := net.SplitHostPort("12.34.23.13:5432")
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Printf("Host: %s\nPort: %s\n", host, port)
}
}

BIN
server/.DS_Store vendored Normal file

Binary file not shown.

BIN
server/docker/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,7 +0,0 @@
Containers
===========
Structure
|_ Containers
|_ <name> (To ensure the name is the same as the tag name)
|_ DockerFile

View File

@@ -1,43 +0,0 @@
from horovod/horovod-cpu
# Switch to root user to install additional software
USER 0
# Make sure we don't get notifications we can't answer during building.
env DEBIAN_FRONTEND noninteractive
run apt-get -q -y update; apt-get -q -y upgrade
run apt install net-tools
# Prepare scripts and configs
add ./scripts/start /start
# Set root password
run echo 'root:password' >> /root/passwdfile
# Create user and it's password
run useradd -m -G sudo master && \
echo 'master:password' >> /root/passwdfile
# Apply root password
run chpasswd -c SHA512 < /root/passwdfile && \
rm /root/passwdfile
# Port 22 is used for ssh
expose 22
# Assign /data as static volume.
volume ["/data"]
# Fix all permissions
run chmod +x /start
# Starting sshd
cmd ["/start"]

View File

@@ -1 +0,0 @@
Running official horovod dockerfile cpu version

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# -----------------------------------------------------------------------------
# docker-ubuntu-sshd /start script
#
# Authors: Art567
# Updated: Sep 20th, 2015
# -----------------------------------------------------------------------------
# Run OpenSSH server in daemon mode
/usr/sbin/sshd -D

View File

@@ -1,61 +0,0 @@
# -----------------------------------------------------------------------------
# This is base image of Ubuntu LTS with SSHD service.
#
# Authors: Art567
# Updated: Sep 20th, 2015
# Require: Docker (http://www.docker.io/)
# -----------------------------------------------------------------------------
# Base system is the latest LTS version of Ubuntu.
# from consol/ubuntu-xfce-vnc
# due to dependency issues vnc is still work in progress
from ubuntu:20.04
# Switch to root user to install additional software
USER 0
# Make sure we don't get notifications we can't answer during building.
env DEBIAN_FRONTEND noninteractive
# Prepare scripts and configs
add ./scripts/start /start
# Download and install everything from the repos.
run apt-get -q -y update; apt-get -q -y upgrade && \
apt-get -q -y install sudo openssh-server && \
mkdir /var/run/sshd
# Set root password
run echo 'root:password' >> /root/passwdfile
# Create user and it's password
run useradd -m -G sudo master && \
echo 'master:password' >> /root/passwdfile
# Apply root password
run chpasswd -c SHA512 < /root/passwdfile && \
rm /root/passwdfile
# Port 22 is used for ssh
expose 22
# Assign /data as static volume.
volume ["/data"]
# Fix all permissions
run chmod +x /start
# Starting sshd
cmd ["/start"]

View File

@@ -1,72 +0,0 @@
Ubuntu LTS with SSH (Docker)
=========
A Docker file to build a [docker.io] base container with Ubuntu LTS and a sshd service
[docker.io]: http://docker.io
Nice and easy way to get any server up and running using docker
Instructions
-----------
- Install Docker first.
Read [installation instructions] (http://docs.docker.io/en/latest/installation/).
- Clone this repository:
`$ git clone https://github.com/art567/docker-ubuntu-sshd.git`
- Enter local directory:
`$ cd docker-ubuntu-sshd`
- Change passwords in Dockerfile:
`$ vi Dockerfile`
- Build the container:
`$ sudo docker build -t art567/ubuntu .`
- Run the container:
`$ sudo docker run -d=true --name=ubuntu --restart=always -p=2222:22 -v=/opt/data:/data art567/ubuntu /start`
- Your container will start and bind ssh to 2222 port.
- Find your local IP Address:
`$ ifconfig`
- Connect to the SSH server:
`$ ssh root@<ip-address> -p 2222`
- If you don't want to deal with root:
`$ ssh master@<ip-address> -p 2222`
**VERY IMPORTANT!!!**
-----------
**Don't forget to change passwords in Dockerfile before building image!**
Versions
-----------
Some branches represents Ubuntu versions.
Branch `master` is always represented by latest Ubuntu LTS
For example:
- 12.04 - Ubuntu 12.04 LTS
- 14.04 - Ubuntu 14.04 LTS
- 16.04 - Ubuntu 16.04 LTS

View File

@@ -1 +0,0 @@
Simple Ubuntu 20.04 image

View File

@@ -1,16 +0,0 @@
{
"Port": [
{
"PortName": "SSH",
"InternalPort": 22,
"Type": "tcp",
"Description": "SSH Port"
},
{
"PortName": "VNC",
"InternalPort": 5900,
"Type": "tcp",
"Description": "VNC port"
}
]
}

View File

@@ -1,14 +0,0 @@
#!/bin/bash
# -----------------------------------------------------------------------------
# docker-ubuntu-sshd /start script
#
# Authors: Art567
# Updated: Sep 20th, 2015
# -----------------------------------------------------------------------------
# Run OpenSSH server in daemon mode
/usr/sbin/sshd -D
# Running x11 server with password

View File

@@ -1,61 +0,0 @@
# -----------------------------------------------------------------------------
# This is base image of Ubuntu LTS with SSHD service.
#
# Authors: Art567
# Updated: Sep 20th, 2015
# Require: Docker (http://www.docker.io/)
# -----------------------------------------------------------------------------
# Base system is the latest LTS version of Ubuntu.
# from consol/ubuntu-xfce-vnc
# due to dependency issues vnc is still work in progress
from ubuntu:20.04
# Switch to root user to install additional software
USER 0
# Make sure we don't get notifications we can't answer during building.
env DEBIAN_FRONTEND noninteractive
# Prepare scripts and configs
add ./scripts/start /start
# Download and install everything from the repos.
run apt-get -q -y update; apt-get -q -y upgrade && \
apt-get -q -y install sudo openssh-server && \
mkdir /var/run/sshd
# Set root password
run echo 'root:password' >> /root/passwdfile
# Create user and it's password
run useradd -m -G sudo master && \
echo 'master:password' >> /root/passwdfile
# Apply root password
run chpasswd -c SHA512 < /root/passwdfile && \
rm /root/passwdfile
# Port 22 is used for ssh
expose 22
# Assign /data as static volume.
volume ["/data"]
# Fix all permissions
run chmod +x /start
# Starting sshd
cmd ["/start"]

View File

@@ -1,72 +0,0 @@
Ubuntu LTS with SSH (Docker)
=========
A Docker file to build a [docker.io] base container with Ubuntu LTS and a sshd service
[docker.io]: http://docker.io
Nice and easy way to get any server up and running using docker
Instructions
-----------
- Install Docker first.
Read [installation instructions] (http://docs.docker.io/en/latest/installation/).
- Clone this repository:
`$ git clone https://github.com/art567/docker-ubuntu-sshd.git`
- Enter local directory:
`$ cd docker-ubuntu-sshd`
- Change passwords in Dockerfile:
`$ vi Dockerfile`
- Build the container:
`$ sudo docker build -t art567/ubuntu .`
- Run the container:
`$ sudo docker run -d=true --name=ubuntu --restart=always -p=2222:22 -v=/opt/data:/data art567/ubuntu /start`
- Your container will start and bind ssh to 2222 port.
- Find your local IP Address:
`$ ifconfig`
- Connect to the SSH server:
`$ ssh root@<ip-address> -p 2222`
- If you don't want to deal with root:
`$ ssh master@<ip-address> -p 2222`
**VERY IMPORTANT!!!**
-----------
**Don't forget to change passwords in Dockerfile before building image!**
Versions
-----------
Some branches represents Ubuntu versions.
Branch `master` is always represented by latest Ubuntu LTS
For example:
- 12.04 - Ubuntu 12.04 LTS
- 14.04 - Ubuntu 14.04 LTS
- 16.04 - Ubuntu 16.04 LTS

View File

@@ -1 +0,0 @@
Simple Ubuntu 20.04 image

View File

@@ -1,22 +0,0 @@
{
"Port": [
{
"PortName": "SSH",
"InternalPort": 22,
"Type": "tcp",
"Description": "SSH Port"
},
{
"PortName": "NoVNC",
"InternalPort": 5901,
"Type": "tcp",
"Description": "NoVNC port"
},
{
"PortName": "NoVNC",
"InternalPort": 6081,
"Type": "tcp",
"Description": "NoVNC port"
}
]
}

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# -----------------------------------------------------------------------------
# docker-ubuntu-sshd /start script
#
# Authors: Art567
# Updated: Sep 20th, 2015
# -----------------------------------------------------------------------------
# Run OpenSSH server in daemon mode
/usr/sbin/sshd -D

View File

@@ -1,41 +0,0 @@
from horovod/horovod
# Switch to root user to install additional software
USER 0
# Make sure we don't get notifications we can't answer during building.
env DEBIAN_FRONTEND noninteractive
# Prepare scripts and configs
add ./scripts/start /start
# Set root password
run echo 'root:password' >> /root/passwdfile
# Create user and it's password
run useradd -m -G sudo master && \
echo 'master:password' >> /root/passwdfile
# Apply root password
run chpasswd -c SHA512 < /root/passwdfile && \
rm /root/passwdfile
# Port 22 is used for ssh
expose 22
# Assign /data as static volume.
volume ["/data"]
# Fix all permissions
run chmod +x /start
# Starting sshd
cmd ["/start"]

View File

@@ -1 +0,0 @@
Running official horovod dockerfile cpu version

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# -----------------------------------------------------------------------------
# docker-ubuntu-sshd /start script
#
# Authors: Art567
# Updated: Sep 20th, 2015
# -----------------------------------------------------------------------------
# Run OpenSSH server in daemon mode
/usr/sbin/sshd -D

View File

@@ -1,61 +0,0 @@
# -----------------------------------------------------------------------------
# This is base image of Ubuntu LTS with SSHD service.
#
# Authors: Art567
# Updated: Sep 20th, 2015
# Require: Docker (http://www.docker.io/)
# -----------------------------------------------------------------------------
# Base system is the latest LTS version of Ubuntu.
# from consol/ubuntu-xfce-vnc
# due to dependency issues vnc is still work in progress
from dorowu/ubuntu-desktop-lxde-vnc
# Switch to root user to install additional software
USER 0
# Make sure we don't get notifications we can't answer during building.
env DEBIAN_FRONTEND noninteractive
# Prepare scripts and configs
add ./scripts/start /start
# Download and install everything from the repos.
run apt-get -q -y update; apt-get -q -y upgrade && \
apt-get -q -y install sudo openssh-server && \
mkdir /var/run/sshd
# Set root password
run echo 'root:password' >> /root/passwdfile
# Create user and it's password
run useradd -m -G sudo master && \
echo 'master:password' >> /root/passwdfile
# Apply root password
run chpasswd -c SHA512 < /root/passwdfile && \
rm /root/passwdfile
# Port 22 is used for ssh
expose 22
# Assign /data as static volume.
volume ["/data"]
# Fix all permissions
run chmod +x /start
# Starting sshd
cmd ["/start"]

View File

@@ -1,72 +0,0 @@
Ubuntu LTS with SSH (Docker)
=========
A Docker file to build a [docker.io] base container with Ubuntu LTS and a sshd service
[docker.io]: http://docker.io
Nice and easy way to get any server up and running using docker
Instructions
-----------
- Install Docker first.
Read [installation instructions] (http://docs.docker.io/en/latest/installation/).
- Clone this repository:
`$ git clone https://github.com/art567/docker-ubuntu-sshd.git`
- Enter local directory:
`$ cd docker-ubuntu-sshd`
- Change passwords in Dockerfile:
`$ vi Dockerfile`
- Build the container:
`$ sudo docker build -t art567/ubuntu .`
- Run the container:
`$ sudo docker run -d=true --name=ubuntu --restart=always -p=2222:22 -v=/opt/data:/data art567/ubuntu /start`
- Your container will start and bind ssh to 2222 port.
- Find your local IP Address:
`$ ifconfig`
- Connect to the SSH server:
`$ ssh root@<ip-address> -p 2222`
- If you don't want to deal with root:
`$ ssh master@<ip-address> -p 2222`
**VERY IMPORTANT!!!**
-----------
**Don't forget to change passwords in Dockerfile before building image!**
Versions
-----------
Some branches represents Ubuntu versions.
Branch `master` is always represented by latest Ubuntu LTS
For example:
- 12.04 - Ubuntu 12.04 LTS
- 14.04 - Ubuntu 14.04 LTS
- 16.04 - Ubuntu 16.04 LTS

View File

@@ -1 +0,0 @@
Simple Ubuntu 20.04 image

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# -----------------------------------------------------------------------------
# docker-ubuntu-sshd /start script
#
# Authors: Art567
# Updated: Sep 20th, 2015
# -----------------------------------------------------------------------------
# Run OpenSSH server in daemon mode
/usr/sbin/sshd -D

View File

@@ -3,32 +3,34 @@ 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/google/uuid"
"github.com/lithammer/shortuuid"
"github.com/otiai10/copy"
"github.com/phayes/freeport"
"io"
"io/ioutil"
"os"
"os/exec"
"time"
"text/template"
)
type DockerVM struct {
SSHUsername string `json:"SSHUsername"`
SSHPassword string `json:"SSHPassword"`
SSHPublcKey string `json:"SSHPublicKey"`
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
SSHCommand string `json:"SSHCommand"`
}
type DockerContainers struct {
@@ -65,30 +67,34 @@ 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) {
func BuildRunContainer(NumPorts int, GPU string, ContainerName string, baseImage string, publicKey string) (*DockerVM, error) {
//Docker Struct Variable
var RespDocker *DockerVM = new(DockerVM)
// Sets if GPU is selected or not
RespDocker.GPU = GPU
// Get config informatopn
// 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.SSHUsername = "root"
//RespDocker.BaseImage = "ubuntu:20.04"
//RespDocker.VNCPassword = "vncpassword"
//Default parameters
RespDocker.TagName = "p2p-ubuntu"
// Get Path from config
config, err := config.ConfigInit()
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
RespDocker.ImagePath = config.DefaultDockerFile
RespDocker.LogsPath = config.DockerRunLogs
RespDocker.SSHPublcKey = publicKey
// We are checking if the container name is not nil and not equal to the default one used
// which is docker-ubuntu-sshd
@@ -110,7 +116,22 @@ func BuildRunContainer(NumPorts int, GPU string, ContainerName string) (*DockerV
}
}
PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/ports.json")
// Checking if the base image is provided
if baseImage != "" {
RespDocker.BaseImage = baseImage
} else {
RespDocker.BaseImage = "ubuntu:20.04"
}
// Template docker with the base image provided
err = RespDocker.TemplateDockerContainer()
if err != nil {
return nil, err
}
// Template the DockerFile and point to the temp location
PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/" + RespDocker.TagName + "/ports.json")
if err != nil {
return nil, err
}
@@ -171,30 +192,40 @@ func BuildRunContainer(NumPorts int, GPU string, ContainerName string) (*DockerV
// 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)
//ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
//defer cancel()
tar, err := archive.TarWithOptions(d.ImagePath, &archive.TarOptions{})
var cmd bytes.Buffer
cmd.WriteString("docker build -t " + d.TagName + " " + d.ImagePath + "/" + d.TagName + ` --build-arg SSH_KEY="` + d.SSHPublcKey + `"`)
//"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
cmdStr := cmd.String()
output, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
fmt.Printf("%s", output)
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
}
//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
//}
return nil
}
@@ -205,97 +236,101 @@ 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
//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{}{},
}
// 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
}
var cmd bytes.Buffer
cmd.WriteString("docker run -d=true --name=" + id + " --restart=always ")
if d.GPU == "true" {
cmd.WriteString("--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=/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
}
@@ -303,24 +338,45 @@ func (d *DockerVM) runContainer(dockerClient *client.Client) error {
// 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())
// stop docker container
var stop bytes.Buffer
stop.WriteString("docker stop " + containername)
cmdStr := stop.String()
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
return err
}
if err = client.ContainerStop(ctx, containername, nil); err != nil {
return err
}
// remove docker container
var remove bytes.Buffer
remove.WriteString("docker remove " + containername)
removeOptions := types.ContainerRemoveOptions{
RemoveVolumes: true,
Force: true,
}
cmdStr = remove.String()
if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil {
_, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
return err
}
@@ -330,7 +386,7 @@ func StopAndRemoveContainer(containername string) error {
// 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()
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
@@ -402,3 +458,51 @@ func OpenPortsFile(filename string) (*Ports, error) {
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
}

View File

@@ -99,7 +99,8 @@ The Docker Containers Dashboard shows key metrics for monitoring running contain
* Container network inbound usage graph
* Container network outbound usage graph
Note that this dashboard doesn't show the containers that are part of the monitoring stack.
> [!NOTE]
> This dashboard doesn't show the containers that are part of the monitoring stack.
***Monitor Services Dashboard***

View File

@@ -14,9 +14,9 @@ To get started on AWS ECS and EC2:
- Copy prometheus.yml configuration present here to base prometheus configuration to enable EC2 service discovery
- `docker compose up -d`
**Note**:
Set query.staleness-delta to 1m make metrics more realtime
> [!NOTE]
> Set query.staleness-delta to 1m make metrics more realtime
### TODO
- Add alerting rules based on ECS
- [ ] Add alerting rules based on ECS

View File

@@ -1,50 +1,50 @@
package server
import (
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
)
// SysInfo saves the basic system information
type SysInfo struct {
Hostname string `bson:hostname`
Platform string `bson:platform`
CPU string `bson:cpu`
RAM uint64 `bson:ram`
Disk uint64 `bson:disk`
GPU *Query `xml: GpuInfo`
Hostname string `bson:hostname`
Platform string `bson:platform`
CPU string `bson:cpu`
RAM uint64 `bson:ram`
Disk uint64 `bson:disk`
GPU *Query `xml: GpuInfo`
}
func ServerInfo() interface{} {
hostStat, _ := host.Info()
cpuStat, _ := cpu.Info()
vmStat, _ := mem.VirtualMemory()
func ServerInfo() *SysInfo {
hostStat, _ := host.Info()
cpuStat, _ := cpu.Info()
vmStat, _ := mem.VirtualMemory()
info := new(SysInfo)
info := new(SysInfo)
filesystem := "/"
filesystem := "/"
// If the server is running windows
if info.Hostname == "windows" {
filesystem = "\\"
}
// If the server is running windows
if info.Hostname == "windows" {
filesystem = "\\"
}
diskStat, _ := disk.Usage(filesystem) // If you're in Unix change this "\\" for "/"
diskStat, _ := disk.Usage(filesystem) // If you're in Unix change this "\\" for "/"
info.Hostname = hostStat.Hostname
info.Platform = hostStat.Platform
info.CPU = cpuStat[0].ModelName
info.RAM = vmStat.Total / 1024 / 1024
info.Disk = diskStat.Total / 1024 / 1024
info.Hostname = hostStat.Hostname
info.Platform = hostStat.Platform
info.CPU = cpuStat[0].ModelName
info.RAM = vmStat.Total / 1024 / 1024
info.Disk = diskStat.Total / 1024 / 1024
gpu, err := GPUInfo()
gpu, err := GPUInfo()
if err == nil {
info.GPU = gpu
}
if err == nil {
info.GPU = gpu
}
return info
return info
}

View File

@@ -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)
}

View File

@@ -1,6 +1,7 @@
package server
import (
b64 "encoding/base64"
"encoding/json"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
@@ -15,13 +16,13 @@ import (
"time"
)
func Server() error {
func Server() (*gin.Engine, error) {
r := gin.Default()
//Get Server port based on the config file
config, err := config.ConfigInit()
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
return nil, err
}
// update IPTable with new port and ip address and update ip table
@@ -107,14 +108,27 @@ func Server() error {
Ports := c.DefaultQuery("ports", "0")
GPU := c.DefaultQuery("GPU", "false")
ContainerName := c.DefaultQuery("ContainerName", "")
BaseImage := c.DefaultQuery("BaseImage", "")
PublicKey := c.DefaultQuery("PublicKey", "")
var PortsInt int
if PublicKey == "" {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", "Publickey not passed"))
}
PublicKeyDecoded, err := b64.StdEncoding.DecodeString(PublicKey)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
// Convert Get Request value to int
fmt.Sscanf(Ports, "%d", &PortsInt)
fmt.Println(string(PublicKeyDecoded[:]))
// Creates container and returns-back result to
// access container
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName)
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName, BaseImage, string(PublicKeyDecoded[:]))
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
@@ -126,7 +140,6 @@ func Server() error {
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
fmt.Println(resp)
}
c.JSON(http.StatusOK, resp)
@@ -160,6 +173,16 @@ func Server() error {
c.String(http.StatusOK, strconv.Itoa(port))
})
r.GET("/MAPPort", func(c *gin.Context) {
Ports := c.DefaultQuery("port", "0")
url, _, err := MapPort(Ports)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.String(http.StatusOK, url)
})
// If there is a proxy port specified
// then starts the FRP server
//if config.FRPServerPort != "0" {
@@ -170,9 +193,12 @@ func Server() error {
// 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 err
return nil, err
}
var lowestLatency int64
@@ -182,7 +208,7 @@ func Server() error {
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 {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i]
}
@@ -192,14 +218,14 @@ func Server() error {
if lowestLatency != 10000000 {
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return err
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)
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, config.ServerPort, "")
if err != nil {
return err
return nil, err
}
// updating with the current proxy address
@@ -209,21 +235,99 @@ func Server() error {
ProxyIpAddr.NAT = "False"
ProxyIpAddr.EscapeImplementation = "FRP"
// Sorry Jan it's a string
// Yes I could convert it
// to a boolean operator
// But I am way too tired
if config.BareMetal == "True" {
_, SSHPort, err := MapPort("22")
if err != nil {
return nil, err
}
ProxyIpAddr.BareMetalSSHPort = SSHPort
}
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
// append the following to the ip table
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
// write information back to the IP Table
table.WriteIpTable()
err = table.WriteIpTable()
if err != nil {
return nil, err
}
// update ip table
go clientIPTable.UpdateIpTableListClient()
go func() error {
err := clientIPTable.UpdateIpTableListClient()
if err != nil {
fmt.Println(err)
return err
}
return nil
}()
}
}
// Run gin server on the specified port
err = r.Run(":" + config.ServerPort)
go r.Run(":" + config.ServerPort)
return r, nil
}
func MapPort(port string) (string, string, error) {
//Get Server port based on the config file
config, err := config.ConfigInit(nil, nil)
if err != nil {
return err
return "", "", err
}
return nil
// update IPTable with new port and ip address and update ip table
var ProxyIpAddr p2p.IpAddress
var lowestLatencyIpAddress p2p.IpAddress
clientIPTable.RemoveOfflineNodes()
table, err := p2p.ReadIpTable()
if err != nil {
return "", "", err
}
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]
}
}
// If there is an identified node
if lowestLatency != 10000000 {
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return "", "", 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, port, "")
if err != nil {
return "", "", err
}
// updating with the current proxy address
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = "False"
ProxyIpAddr.EscapeImplementation = "FRP"
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
}
return ProxyIpAddr.Ipv4 + ":" + ProxyIpAddr.ServerPort, ProxyIpAddr.ServerPort, nil
}