78 Commits

Author SHA1 Message Date
ac2c5f8a83 test changes 2025-06-02 18:25:05 +01:00
22c5d61082 finished mvp for nix templating 2025-06-02 00:43:50 +01:00
a1bf13cac3 finishing automated setup 2025-06-02 00:37:28 +01:00
616bf76bda finishing automated setup 2025-06-02 00:31:29 +01:00
539bceee7d finishing automated setup 2025-06-02 00:31:04 +01:00
69b9ea3527 finishing automated setup 2025-06-02 00:11:59 +01:00
27f4615cd1 finishing automated setup 2025-06-02 00:07:53 +01:00
01e19d9a8c adding git actions 2025-06-02 00:03:24 +01:00
aafc0ebdd7 adding git actions 2025-06-01 23:54:25 +01:00
9de0b1b985 adding git actions 2025-06-01 23:52:00 +01:00
4c12d74789 adding git actions 2025-06-01 23:50:41 +01:00
f06df58a8a adding git actions 2025-06-01 23:47:11 +01:00
30004d59c6 adding git actions 2025-06-01 23:44:57 +01:00
4c8cde8857 adding git actions 2025-06-01 23:34:01 +01:00
994c52faf0 adding git actions 2025-06-01 23:25:41 +01:00
5e65381377 adding git actions 2025-06-01 20:57:38 +01:00
ff66d55153 adding git actions 2025-06-01 20:54:38 +01:00
50983dbb19 adding git actions 2025-06-01 20:50:49 +01:00
189edd73b1 adding git actions 2025-06-01 20:48:59 +01:00
27670f2408 adding git actions 2025-06-01 19:55:00 +01:00
b301a54fba adding git actions 2025-06-01 19:53:33 +01:00
05e29aab0d adding git actions 2025-06-01 19:47:17 +01:00
b883feb825 adding git actions 2025-06-01 19:44:43 +01:00
5059444d26 adding git actions 2025-06-01 19:42:23 +01:00
be3be96987 adding git actions 2025-06-01 19:39:32 +01:00
682424074f adding git actions 2025-06-01 19:36:41 +01:00
9d0ec3eba4 adding git actions 2025-06-01 19:34:32 +01:00
bf87217b9a adding git actions 2025-06-01 19:27:52 +01:00
e4638232d3 adding git actions 2025-06-01 19:24:56 +01:00
fb6c3ab091 adding new version for p2prc-hs bootstrapping 2025-06-01 15:12:16 +01:00
a59657a93b removing wasm file 2025-05-31 15:18:27 +01:00
30ea1f810a Merge remote-tracking branch 'refs/remotes/principal/master' 2025-05-31 11:11:00 +01:00
fe72625266 removed erroneous commands 2025-05-31 10:44:10 +01:00
d2030b7d74 updating lock versions 2025-05-31 00:17:59 +01:00
73a283a545 another attempt to test bootstrapping 2025-05-31 00:07:50 +01:00
623cfffb6a another attempt to test bootstrapping 2025-05-31 00:05:04 +01:00
3669fdfad2 adding initHaskellProject to bootstrap project 2025-05-30 23:56:03 +01:00
f39fab04ce adding initHaskellProject to bootstrap project 2025-05-30 23:41:34 +01:00
12ff0ceb37 adding initHaskellProject to bootstrap project 2025-05-30 23:36:27 +01:00
99c62a8dca adding initHaskellProject to bootstrap project 2025-05-30 23:32:49 +01:00
ce5c80a10e adding initHaskellProject to bootstrap project 2025-05-30 23:31:40 +01:00
46ef4e1db9 adding initHaskellProject to bootstrap project 2025-05-30 23:29:28 +01:00
14743f7f9b adding initHaskellProject to bootstrap project 2025-05-30 23:27:10 +01:00
a461c2da64 adding initHaskellProject to bootstrap project 2025-05-30 23:02:06 +01:00
99c9c41528 Documentation for Simulation added 2025-05-30 18:06:32 +01:00
0e260cf8e4 Made simulation simple 2025-05-30 17:10:54 +01:00
02e58493f5 added working version of simulator 2025-05-30 17:09:36 +01:00
a46ec3575c Simulation base code 2025-05-30 16:23:39 +01:00
2d55643dd9 removed heavy WASM binary 2025-05-30 11:59:32 +01:00
1ac0647d46 refactoring nix flake template 2025-05-30 00:04:43 +01:00
a07a412c72 temporary fix to test remote flake init 2025-05-29 23:52:14 +01:00
e04e918328 fixed haskell template 2025-05-29 23:36:11 +01:00
0bb949a1e2 fixed overlay and templates 2025-05-29 23:34:08 +01:00
cf6611087a adding haskell template providing dev/prod environments 2025-05-29 23:29:55 +01:00
b1a69189d3 adding haskell template providing dev/prod environments 2025-05-29 23:20:21 +01:00
ad76773111 adding haskell template providing dev/prod environments 2025-05-29 23:13:11 +01:00
ec46f74c4e adding haskell template providing dev/prod environments 2025-05-29 23:10:12 +01:00
3fb225676f fixed devshell environment 2025-05-29 00:23:42 +01:00
0e86459122 fixed p2prc-hs issue 2025-05-28 22:25:09 +01:00
77ebb76838 updating flake 2025-05-28 00:04:49 +01:00
85806ab035 refactoring flake code 2025-05-27 23:49:08 +01:00
9d92ecb202 working on template for haskell 2025-05-27 23:22:47 +01:00
5fa625160e improving overlays 2025-05-26 21:26:40 +01:00
403ad72ddb fixing environment 2025-05-26 21:08:11 +01:00
6446681719 renaming overlay file 2025-05-26 01:16:03 +01:00
d50534e270 improving executable exposure 2025-05-26 01:06:42 +01:00
8a2dfb7b5b fixed haskell development environment 2025-05-26 00:15:36 +01:00
0f4f52cb8b working on haskell development shell 2025-05-26 00:06:11 +01:00
cd8bb2df8c removed redundant code from flake 2025-05-25 23:45:44 +01:00
fa5b7a27d5 fixed overlays typo 2025-05-25 23:17:03 +01:00
21f0fc79c1 removed executable from haskell project 2025-05-25 22:07:26 +01:00
bebe2a02a0 improving nix flake for haskell library bootstrapping 2025-05-25 19:09:41 +01:00
7b0b2404b2 improving overlay 2025-05-24 17:59:16 +01:00
724daf5eda preparing overlays for build system 2025-05-24 16:58:08 +01:00
c262e612e1 preparing overlays for build system 2025-05-24 16:53:01 +01:00
257d91a432 fixing nix development and build environments 2025-05-21 23:11:56 +01:00
42cf9bd028 fixing nix env 2025-05-20 23:51:33 +01:00
7c34c5385a fix abstraction 2025-05-17 23:30:58 +01:00
85 changed files with 11465 additions and 2024 deletions

BIN
.DS_Store vendored

Binary file not shown.

3
.gitignore vendored
View File

@@ -49,6 +49,3 @@ venv
# Nix and Nix flake files
result
result-*
# Ignore WASM generated files
*.wasm

View File

@@ -1,5 +1,3 @@
//go:build cgo
package main
import "C"
@@ -18,23 +16,23 @@ import (
// --------------------------------- Container Control ----------------------------------------
////export StartContainer
//func StartContainer(IP string) (output *C.char) {
// container, err := abstractions.StartContainer(IP)
// if err != nil {
// return C.CString(err.Error())
// }
// return ConvertStructToJSONString(container)
//}
//
////export RemoveContainer
//func RemoveContainer(IP string, ID string) (output *C.char) {
// err := abstractions.RemoveContainer(IP, ID)
// if err != nil {
// return C.CString(err.Error())
// }
// return C.CString("Success")
//}
//export StartContainer
func StartContainer(IP string) (output *C.char) {
container, err := abstractions.StartContainer(IP)
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
//export RemoveContainer
func RemoveContainer(IP string, ID string) (output *C.char) {
err := abstractions.RemoveContainer(IP, ID)
if err != nil {
return C.CString(err.Error())
}
return C.CString("Success")
}
// --------------------------------- Plugin Control ----------------------------------------

View File

@@ -18,23 +18,41 @@
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"flake-utils": [
"p2prc",
"p2prc-main",
"flake-utils"
],
"nixpkgs": [
"p2prc",
"p2prc-main",
"nixpkgs"
]
},
"locked": {
"lastModified": 1733668782,
"narHash": "sha256-tPsqU00FhgdFr0JiQUiBMgPVbl1jbPCY5gbFiJycL3I=",
"lastModified": 1745875161,
"narHash": "sha256-0YkWCS13jpoo3+sX/3kcgdxBNt1VZTmvF+FhZb4rFKI=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "514283ec89c39ad0079ff2f3b1437404e4cba608",
"rev": "2cbd7fdd6eeab65c494cc426e18f4e4d2a5e35c0",
"type": "github"
},
"original": {
@@ -57,11 +75,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1735834308,
"narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=",
"lastModified": 1748026106,
"narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6df24922a1400241dae323af55f30e4318a6ca65",
"rev": "063f43f2dbdef86376cc29ad646c45c46e93234c",
"type": "github"
},
"original": {
@@ -71,28 +89,28 @@
"type": "github"
}
},
"p2prc": {
"p2prc-main": {
"inputs": {
"flake-utils": "flake-utils",
"flake-utils": "flake-utils_2",
"gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 0,
"narHash": "sha256-f4e4JcQzBS+R+8HqJbQVeecInm2ggInJuSSymj6gtQo=",
"path": "/nix/store/hmk8v0lxifsscll054qsdnzxqfql1998-source",
"narHash": "sha256-5qbaxawuLsg8iu9076zlAbLtTFSNJaTz7WERS5rWRxU=",
"path": "/nix/store/lg694r23fzc6v5ai3qqcszq1fp44djg2-source",
"type": "path"
},
"original": {
"path": "/nix/store/hmk8v0lxifsscll054qsdnzxqfql1998-source",
"path": "/nix/store/lg694r23fzc6v5ai3qqcszq1fp44djg2-source",
"type": "path"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"p2prc": "p2prc",
"utils": "utils"
"p2prc-main": "p2prc-main"
}
},
"systems": {
@@ -124,24 +142,6 @@
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",

View File

@@ -1,24 +1,28 @@
{
description = "Nix flake for P2PRC Haskell library";
inputs = {
p2prc.url = "../../";
utils.url = "github:numtide/flake-utils";
flake-utils.url = "github:numtide/flake-utils";
p2prc-main.url = "../../";
};
outputs = { self, nixpkgs, utils, p2prc }: utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
cabal-install
haskell.compiler.ghc96
zlib.dev
p2prc.outputs.packages.${system}.default
];
};
}
);
outputs = { nixpkgs, flake-utils, p2prc-main, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
packages.default = pkgs.haskellPackages.callPackage ./project.nix {};
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
cabal2nix
cabal-install
ghc
zlib.dev
p2prc-main.packages.${system}.default
];
};
}
);
}

View File

@@ -116,5 +116,5 @@ eitherErrorDecode esa =
-- assumes the program is ran inside the haskell module in p2prc's repo
-- assumes that last path segment is "haskell" and that p2prc binary's name is "p2p-rendering-computation"
p2prcCmdName :: String
p2prcCmdName = "p2prc"
p2prcCmdName = "p2p-rendering-computation"

View File

@@ -0,0 +1,13 @@
{ mkDerivation, aeson, base, bytestring, directory, lib, process
, text
}:
mkDerivation {
pname = "p2prc";
version = "0.1.0.0";
src = ./.;
libraryHaskellDepends = [
aeson base bytestring directory process text
];
description = "P2PRC haskell library";
license = "unknown";
}

View File

@@ -64,9 +64,6 @@ def StartServer():
# Starting P2PRC as a server mode
p2prc.Server()
def Init():
p2prc.Init("")
# Class to create string to pass as string function
# parameter to shared object file
class go_string(Structure):

View File

@@ -1,14 +0,0 @@
This is a temporary android setup instruction:
1. Instruction to run from ADB with termux
'''
run-as com.termux files/usr/bin/bash -lic 'export PATH=/data/data/com.termux/files/usr/bin:$PATH; export LD_PRELOAD=/data/data/com.termux/files/usr/lib/libtermux-exec.so; bash -i'
'''
2. Install golang
'''
pkg install golang
'''

View File

@@ -3,7 +3,7 @@
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2025-04-28 Mon 23:14 -->
<!-- 2025-05-30 Fri 18:05 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>&lrm;</title>
@@ -26,12 +26,12 @@
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org3cfeea9">1. Guide through video</a>
<li><a href="#orga8d6384">1. Guide through video</a>
<ul>
<li>
<ul>
<li><a href="#org4256417">1.0.1. The video below shows the setup and usage of P2PRC.</a></li>
<li><a href="#orgecee0c3">1.0.2. Source code: https://github.com/Akilan1999/p2p-rendering-computation</a></li>
<li><a href="#org1df53fe">1.0.1. The video below shows the setup and usage of P2PRC.</a></li>
<li><a href="#orgd08f572">1.0.2. Source code: https://github.com/Akilan1999/p2p-rendering-computation</a></li>
</ul>
</li>
</ul>
@@ -78,8 +78,8 @@
<li><a href="#pulling-plugin-from-a-remote-repo">4.0.17. Pulling plugin from a remote repo</a></li>
<li><a href="#deleting-plugin-from-the-plugin-directory">4.0.18. Deleting plugin from the plugin directory</a></li>
<li><a href="#added-custom-metadata-about-the-current-node">4.0.19. Added custom metadata about the current node</a></li>
<li><a href="#org899f210">4.0.20. MapPort and link to domain name</a></li>
<li><a href="#orge681470">4.0.21. Add root node</a></li>
<li><a href="#org966244c">4.0.20. MapPort and link to domain name</a></li>
<li><a href="#org2f19c06">4.0.21. Add root node</a></li>
</ul>
</li>
</ul>
@@ -109,8 +109,8 @@
</li>
<li><a href="#current-languages-supported">6.3. Current languages supported</a>
<ul>
<li><a href="#org92a1e8c">6.3.1. Python</a></li>
<li><a href="#org780e43b">6.3.2. Haskell</a></li>
<li><a href="#orgf65d6f6">6.3.1. Python</a></li>
<li><a href="#org40fe543">6.3.2. Haskell</a></li>
</ul>
</li>
</ul>
@@ -127,22 +127,28 @@
</ul>
</li>
<li><a href="#client-mode">10. Client mode</a></li>
<li><a href="#org1b92827">11. Blog posts</a>
<li><a href="#orgfe7fc3c">11. Simulation</a>
<ul>
<li><a href="#orgec8979c">11.1. Self host within 5 minutes any program</a>
<li><a href="#org22226ea">11.1. Command</a></li>
<li><a href="#orga514f52">11.2. Sample bash instructions</a></li>
</ul>
</li>
<li><a href="#orga046d58">12. Blog posts</a>
<ul>
<li><a href="#orgd03815a">11.1.1. 1. Find a program you want to run</a></li>
<li><a href="#orgec88f20">12.1. Self host within 5 minutes any program</a>
<ul>
<li><a href="#org07ee6bd">12.1.1. 1. Find a program you want to run</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#orgb32e475">12. Ideas for future potencial features</a>
<li><a href="#orgf31160d">13. Ideas for future potencial features</a>
<ul>
<li><a href="#org2666d00">12.1. To support hetrogenous set of Nodes that cannot run P2PRC</a>
<li><a href="#org1a8a88e">13.1. To support hetrogenous set of Nodes that cannot run P2PRC</a>
<ul>
<li><a href="#org332fcc8">12.1.1. Assumptions:</a></li>
<li><a href="#org21a29ac">12.1.2. Set of interesting possible:</a></li>
<li><a href="#org4947494">12.1.3. Implementation</a></li>
<li><a href="#org5d2c045">13.1.1. Assumptions:</a></li>
<li><a href="#orgb55e814">13.1.2. Set of interesting possible:</a></li>
<li><a href="#org7855189">13.1.3. Implementation</a></li>
</ul>
</li>
</ul>
@@ -151,26 +157,26 @@
</div>
</div>
<div id="orgefb6d6c" class="figure">
<div id="org628b85a" class="figure">
<p><img src="./Colored-On-Light-Image.png" alt="Colored-On-Light-Image.png" width="300px" />
</p>
</div>
<div id="outline-container-org3cfeea9" class="outline-2">
<h2 id="org3cfeea9"><span class="section-number-2">1.</span> Guide through video</h2>
<div id="outline-container-orga8d6384" class="outline-2">
<h2 id="orga8d6384"><span class="section-number-2">1.</span> Guide through video</h2>
<div class="outline-text-2" id="text-1">
</div>
<div id="outline-container-org4256417" class="outline-4">
<h4 id="org4256417"><span class="section-number-4">1.0.1.</span> The video below shows the setup and usage of P2PRC.</h4>
<div id="outline-container-org1df53fe" class="outline-4">
<h4 id="org1df53fe"><span class="section-number-4">1.0.1.</span> The video below shows the setup and usage of P2PRC.</h4>
<div class="outline-text-4" id="text-1-0-1">
<div id="org863dfc7" class="figure">
<div id="orgaf620b9" class="figure">
<p><a href="https://www.youtube.com/watch?v=OMwCpedu5cs" class="video"><img src="https://i3.ytimg.com/vi/OMwCpedu5cs/maxresdefault.jpg" alt="maxresdefault.jpg" class="video" /></a>
</p>
</div>
</div>
</div>
<div id="outline-container-orgecee0c3" class="outline-4">
<h4 id="orgecee0c3"><span class="section-number-4">1.0.2.</span> Source code: <a href="https://github.com/Akilan1999/p2p-rendering-computation">https://github.com/Akilan1999/p2p-rendering-computation</a></h4>
<div id="outline-container-orgd08f572" class="outline-4">
<h4 id="orgd08f572"><span class="section-number-4">1.0.2.</span> Source code: <a href="https://github.com/Akilan1999/p2p-rendering-computation">https://github.com/Akilan1999/p2p-rendering-computation</a></h4>
</div>
</div>
<div id="outline-container-chapter1-introduction" class="outline-2">
@@ -259,7 +265,7 @@ Go API to create and interact with the containers.
to install docker GPU</a>
</p>
<pre class="example" id="orgfc326ea">
<pre class="example" id="orge229820">
// Do ensure that the docker command does not need sudo to run
sudo chmod 666 /var/run/docker.sock
</pre>
@@ -273,7 +279,7 @@ To set up the internal dependencies and build the entire go code into a
single binary
</p>
<pre class="example" id="org9abf859">
<pre class="example" id="orge6efab3">
make
</pre>
</div>
@@ -285,7 +291,7 @@ To set up P2PRC on Windows, simply run this batch file. <b>Make sure you
are not in admin mode when running this.</b>
</p>
<pre class="example" id="org754bc46">
<pre class="example" id="org503a4ba">
.\install.bat
</pre>
</div>
@@ -295,7 +301,7 @@ are not in admin mode when running this.</b>
<div id="outline-container-add-appropriate-paths-to-.bashrc" class="outline-4">
<h4 id="add-appropriate-paths-to-.bashrc"><span class="section-number-4">3.2.4.</span> Add appropriate paths to <code>.bashrc</code></h4>
<div class="outline-text-4" id="text-add-appropriate-paths-to-.bashrc">
<pre class="example" id="org06344db">
<pre class="example" id="org3da98df">
export P2PRC=/&lt;PATH&gt;/p2p-rendering-computation
export PATH=/&lt;PATH&gt;/p2p-rendering-computation:${PATH}
</pre>
@@ -304,14 +310,14 @@ export PATH=/&lt;PATH&gt;/p2p-rendering-computation:${PATH}
<div id="outline-container-test-if-binary-works" class="outline-4">
<h4 id="test-if-binary-works"><span class="section-number-4">3.2.5.</span> Test if binary works</h4>
<div class="outline-text-4" id="text-test-if-binary-works">
<pre class="example" id="org189a0e9">
<pre class="example" id="org842f745">
p2prc --help
</pre>
</div>
<ol class="org-ol">
<li><a id="output"></a>Output:<br />
<div class="outline-text-5" id="text-output">
<pre class="example" id="org705fb25">
<pre class="example" id="org2d62e91">
NAME:
p2p-rendering-computation - p2p cli application to create and access VMs in other servers
@@ -373,7 +379,7 @@ GLOBAL OPTIONS:
<div id="outline-container-start-as-a-server" class="outline-4">
<h4 id="start-as-a-server"><span class="section-number-4">4.0.1.</span> Start as a server</h4>
<div class="outline-text-4" id="text-start-as-a-server">
<pre class="example" id="org1be9ce7">
<pre class="example" id="org41f3e1c">
p2prc -s
</pre>
</div>
@@ -381,7 +387,7 @@ p2prc -s
<div id="outline-container-view-server-specification" class="outline-4">
<h4 id="view-server-specification"><span class="section-number-4">4.0.2.</span> View server Specification</h4>
<div class="outline-text-4" id="text-view-server-specification">
<pre class="example" id="org7c6080c">
<pre class="example" id="orgc305043">
p2prc --specs=&lt;ip address&gt;
</pre>
</div>
@@ -393,7 +399,7 @@ p2prc --specs=&lt;ip address&gt;
use the <code>--gpu</code> if you know the other machine has a gpu.
</p>
<pre class="example" id="org96ebc97">
<pre class="example" id="orgc7648f7">
p2prc --touch=&lt;server ip address&gt; -p &lt;number of ports&gt; --gpu
</pre>
</div>
@@ -405,7 +411,7 @@ p2prc --touch=&lt;server ip address&gt; -p &lt;number of ports&gt; --gpu
The docker id is present in the output where you create a container
</p>
<pre class="example" id="org3a50a5b">
<pre class="example" id="org9aca1f2">
p2prc --rm=&lt;server ip address&gt; --id=&lt;docker container id&gt;
</pre>
</div>
@@ -413,7 +419,7 @@ p2prc --rm=&lt;server ip address&gt; --id=&lt;docker container id&gt;
<div id="outline-container-adding-servers-to-ip-table" class="outline-4">
<h4 id="adding-servers-to-ip-table"><span class="section-number-4">4.0.5.</span> Adding servers to ip table</h4>
<div class="outline-text-4" id="text-adding-servers-to-ip-table">
<pre class="example" id="orgd0b12dc">
<pre class="example" id="orgb518ed0">
p2prc --as=&lt;server ip address you want to add&gt;
</pre>
</div>
@@ -421,7 +427,7 @@ p2prc --as=&lt;server ip address you want to add&gt;
<div id="outline-container-update-ip-table" class="outline-4">
<h4 id="update-ip-table"><span class="section-number-4">4.0.6.</span> Update ip table</h4>
<div class="outline-text-4" id="text-update-ip-table">
<pre class="example" id="org2b52762">
<pre class="example" id="org26ead4a">
p2prc --us
</pre>
</div>
@@ -429,7 +435,7 @@ p2prc --us
<div id="outline-container-list-servers" class="outline-4">
<h4 id="list-servers"><span class="section-number-4">4.0.7.</span> List Servers</h4>
<div class="outline-text-4" id="text-list-servers">
<pre class="example" id="org9a40c4a">
<pre class="example" id="orgc098d33">
p2prc --ls
</pre>
</div>
@@ -437,7 +443,7 @@ p2prc --ls
<div id="outline-container-view-network-interfaces" class="outline-4">
<h4 id="view-network-interfaces"><span class="section-number-4">4.0.8.</span> View Network interfaces</h4>
<div class="outline-text-4" id="text-view-network-interfaces">
<pre class="example" id="orge766dd3">
<pre class="example" id="org68a2716">
p2prc --ni
</pre>
</div>
@@ -445,7 +451,7 @@ p2prc --ni
<div id="outline-container-viewing-containers-created-client-side" class="outline-4">
<h4 id="viewing-containers-created-client-side"><span class="section-number-4">4.0.9.</span> Viewing Containers created Client side</h4>
<div class="outline-text-4" id="text-viewing-containers-created-client-side">
<pre class="example" id="org9787c64">
<pre class="example" id="orgc3b9a5e">
p2prc --tc
</pre>
</div>
@@ -453,7 +459,7 @@ p2prc --tc
<div id="outline-container-running-plugin" class="outline-4">
<h4 id="running-plugin"><span class="section-number-4">4.0.10.</span> Running plugin</h4>
<div class="outline-text-4" id="text-running-plugin">
<pre class="example" id="org94b7a90">
<pre class="example" id="org0f205e5">
p2prc --plugin &lt;plugin name&gt; --id &lt;container id or group id&gt;
</pre>
</div>
@@ -461,7 +467,7 @@ p2prc --plugin &lt;plugin name&gt; --id &lt;container id or group id&gt;
<div id="outline-container-create-group" class="outline-4">
<h4 id="create-group"><span class="section-number-4">4.0.11.</span> Create group</h4>
<div class="outline-text-4" id="text-create-group">
<pre class="example" id="orge008a6c">
<pre class="example" id="org3dc07ae">
p2prc --cgroup
</pre>
</div>
@@ -469,7 +475,7 @@ p2prc --cgroup
<div id="outline-container-add-container-to-group" class="outline-4">
<h4 id="add-container-to-group"><span class="section-number-4">4.0.12.</span> Add container to group</h4>
<div class="outline-text-4" id="text-add-container-to-group">
<pre class="example" id="org8598b18">
<pre class="example" id="orgc7ac7ea">
p2prc --group &lt;group id&gt; --id &lt;container id&gt;
</pre>
</div>
@@ -477,7 +483,7 @@ p2prc --group &lt;group id&gt; --id &lt;container id&gt;
<div id="outline-container-view-groups" class="outline-4">
<h4 id="view-groups"><span class="section-number-4">4.0.13.</span> View groups</h4>
<div class="outline-text-4" id="text-view-groups">
<pre class="example" id="org5425a07">
<pre class="example" id="org147a736">
p2prc --groups
</pre>
</div>
@@ -485,7 +491,7 @@ p2prc --groups
<div id="outline-container-view-specific-group" class="outline-4">
<h4 id="view-specific-group"><span class="section-number-4">4.0.14.</span> View specific group</h4>
<div class="outline-text-4" id="text-view-specific-group">
<pre class="example" id="org187af36">
<pre class="example" id="orgd045744">
p2prc --group &lt;group id&gt;
</pre>
</div>
@@ -493,7 +499,7 @@ p2prc --group &lt;group id&gt;
<div id="outline-container-delete-container-from-group" class="outline-4">
<h4 id="delete-container-from-group"><span class="section-number-4">4.0.15.</span> Delete container from group</h4>
<div class="outline-text-4" id="text-delete-container-from-group">
<pre class="example" id="orga4687ab">
<pre class="example" id="org9fc6938">
p2prc --rmcgroup --group &lt;group id&gt; --id &lt;container id&gt;
</pre>
</div>
@@ -501,7 +507,7 @@ p2prc --rmcgroup --group &lt;group id&gt; --id &lt;container id&gt;
<div id="outline-container-delete-entire-group" class="outline-4">
<h4 id="delete-entire-group"><span class="section-number-4">4.0.16.</span> Delete entire group</h4>
<div class="outline-text-4" id="text-delete-entire-group">
<pre class="example" id="orgf60b3a8">
<pre class="example" id="org752e829">
p2prc --rmgroup &lt;group id&gt;
</pre>
</div>
@@ -509,7 +515,7 @@ p2prc --rmgroup &lt;group id&gt;
<div id="outline-container-pulling-plugin-from-a-remote-repo" class="outline-4">
<h4 id="pulling-plugin-from-a-remote-repo"><span class="section-number-4">4.0.17.</span> Pulling plugin from a remote repo</h4>
<div class="outline-text-4" id="text-pulling-plugin-from-a-remote-repo">
<pre class="example" id="orgb9bee77">
<pre class="example" id="orga6511bc">
p2prc --pp &lt;repo link&gt;
</pre>
</div>
@@ -517,7 +523,7 @@ p2prc --pp &lt;repo link&gt;
<div id="outline-container-deleting-plugin-from-the-plugin-directory" class="outline-4">
<h4 id="deleting-plugin-from-the-plugin-directory"><span class="section-number-4">4.0.18.</span> Deleting plugin from the plugin directory</h4>
<div class="outline-text-4" id="text-deleting-plugin-from-the-plugin-directory">
<pre class="example" id="org2979ba1">
<pre class="example" id="orgbff120f">
p2prc --rp &lt;plugin name&gt;
</pre>
</div>
@@ -525,28 +531,28 @@ p2prc --rp &lt;plugin name&gt;
<div id="outline-container-added-custom-metadata-about-the-current-node" class="outline-4">
<h4 id="added-custom-metadata-about-the-current-node"><span class="section-number-4">4.0.19.</span> Added custom metadata about the current node</h4>
<div class="outline-text-4" id="text-added-custom-metadata-about-the-current-node">
<pre class="example" id="org3c1dba9">
<pre class="example" id="org93cf0f5">
p2prc --amd "custom metadata"
</pre>
</div>
</div>
<div id="outline-container-org899f210" class="outline-4">
<h4 id="org899f210"><span class="section-number-4">4.0.20.</span> MapPort and link to domain name</h4>
<div id="outline-container-org966244c" class="outline-4">
<h4 id="org966244c"><span class="section-number-4">4.0.20.</span> MapPort and link to domain name</h4>
<div class="outline-text-4" id="text-4-0-20">
<p>
Allows to expose remote ports from a machine in the P2P network.
</p>
<pre class="example" id="org9d628c6">
<pre class="example" id="org583d4c1">
p2prc --mp &lt;port no to map&gt; --dn &lt;domain name to link Mapped port against&gt;
</pre>
</div>
<ol class="org-ol">
<li><a id="org29021b1"></a>MapPort in remote machine<br />
<li><a id="orgf707bff"></a>MapPort in remote machine<br />
<div class="outline-text-5" id="text-4-0-20-1">
<p>
This is to ensure ports on remote machines on the P2PRC can be easily opened.
</p>
<pre class="example" id="orga1ff65e">
<pre class="example" id="org72eef4d">
p2prc --mp &lt;port no to map&gt; --dn &lt;domain name to link Mapped port against&gt; --ra &lt;remote server address&gt;
</pre>
@@ -555,15 +561,15 @@ p2prc --mp &lt;port no to map&gt; --dn &lt;domain name to link Mapped port again
</li>
</ol>
</div>
<div id="outline-container-orge681470" class="outline-4">
<h4 id="orge681470"><span class="section-number-4">4.0.21.</span> Add root node</h4>
<div id="outline-container-org2f19c06" class="outline-4">
<h4 id="org2f19c06"><span class="section-number-4">4.0.21.</span> Add root node</h4>
<div class="outline-text-4" id="text-4-0-21">
<p>
Adds a root node to P2RRC and overwrites all other nodes in the ip table.
To be only added before the network is started and with
the intention of a fresh instance.
</p>
<pre class="example" id="org79b869e">
<pre class="example" id="org202dc68">
p2prc --arn --ip &lt;root node ip address&gt; -p &lt;root node port no&gt;
</pre>
</div>
@@ -674,7 +680,7 @@ from the TURN server. The flow below describes the workflow.
<li>Call <code>/FRPPort</code></li>
</ul>
<pre class="example" id="org90a2001">
<pre class="example" id="org2bea991">
http://&lt;turn server ip&gt;:&lt;server port no&gt;/FRPport
</pre>
@@ -763,7 +769,7 @@ p2prc.h p2prc.so
Below are a sample set of commands to open the bindings implementation.
</p>
<pre class="example" id="orgb8690e2">
<pre class="example" id="orgdd81071">
# run
cd Bindings/
# list files
@@ -851,7 +857,7 @@ that convert a go object to JSON string initially and converts it to
</li>
<li><a id="a-pseudo-code-to-refer-to-the-common-function-implementation-shape-could-be-represented-as"></a>A Pseudo code to refer to the common function implementation shape could be represented as:<br />
<div class="outline-text-5" id="text-a-pseudo-code-to-refer-to-the-common-function-implementation-shape-could-be-represented-as">
<pre class="example" id="orgd0da451">
<pre class="example" id="orge44168c">
func &lt;Function name&gt; (output *C.char) {
&lt;response&gt;,&lt;error&gt; := &lt;P2PRC function name&gt;(&lt;parameters if needed&gt;)
if &lt;error&gt; != nil {
@@ -869,8 +875,8 @@ func &lt;Function name&gt; (output *C.char) {
<h3 id="current-languages-supported"><span class="section-number-3">6.3.</span> Current languages supported</h3>
<div class="outline-text-3" id="text-current-languages-supported">
</div>
<div id="outline-container-org92a1e8c" class="outline-4">
<h4 id="org92a1e8c"><span class="section-number-4">6.3.1.</span> Python</h4>
<div id="outline-container-orgf65d6f6" class="outline-4">
<h4 id="orgf65d6f6"><span class="section-number-4">6.3.1.</span> Python</h4>
<div class="outline-text-4" id="text-6-3-1">
</div>
<ol class="org-ol">
@@ -907,8 +913,8 @@ called from other programming languages.
</li>
</ol>
</div>
<div id="outline-container-org780e43b" class="outline-4">
<h4 id="org780e43b"><span class="section-number-4">6.3.2.</span> Haskell</h4>
<div id="outline-container-org40fe543" class="outline-4">
<h4 id="org40fe543"><span class="section-number-4">6.3.2.</span> Haskell</h4>
<div class="outline-text-4" id="text-6-3-2">
<p>
P2PRC officially supports Haskell bindings and will further support
@@ -943,18 +949,28 @@ configuration file was generated using JSON format.
<div class="org-src-container">
<pre class="src src-json">{
"MachineName": "pc-74-120.customer.ask4.lan",
"MachineName": "Akilans-MacBook-Pro.local-975261X",
"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/",
"DockerRunLogs": "/tmp/",
"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",
"ProxyPort": "",
"GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json",
"FRPServerPort": "True",
"BehindNAT": "True",
"FRPServerPort": true,
"BehindNAT": true,
"IPTableKey": "QH3yQrGRe2X4",
"PublicKeyFile": "/Users/akilan/Documents/p2p-rendering-computation/p2prc.publicKey",
"PrivateKeyFile": "/Users/akilan/Documents/p2p-rendering-computation/p2prc.privateKey",
"PemFile": "/Users/akilan/Documents/p2p-rendering-computation/cert.pem",
"KeyFile": "/Users/akilan/Documents/p2p-rendering-computation/key.pem",
"BareMetal": false,
"UnsafeMode": false,
"Test": false,
"CustomConfig": null
}
</pre>
@@ -1020,7 +1036,7 @@ from the TURN server. The flow below describes the workflow.
<li>Call <code>/FRPPort</code></li>
</ul>
<pre class="example" id="org910dfb2">
<pre class="example" id="org60a83ac">
http://&lt;turn server ip&gt;:&lt;server port no&gt;/FRPport
</pre>
@@ -1051,14 +1067,73 @@ func main() {
</div>
</div>
</div>
<div id="outline-container-org1b92827" class="outline-2">
<h2 id="org1b92827"><span class="section-number-2">11.</span> Blog posts</h2>
<div id="outline-container-orgfe7fc3c" class="outline-2">
<h2 id="orgfe7fc3c"><span class="section-number-2">11.</span> Simulation</h2>
<div class="outline-text-2" id="text-11">
<p>
The simulation library is a really simple library to locally
run serveral instances of P2PRC to test the functionality
of sending information through the network and particularly
the Node discovery mechanism. There are current 5 commands
which can be used as shown below:
</p>
</div>
<div id="outline-container-orgec8979c" class="outline-3">
<h3 id="orgec8979c"><span class="section-number-3">11.1.</span> Self host within 5 minutes any program</h3>
<div id="outline-container-org22226ea" class="outline-3">
<h3 id="org22226ea"><span class="section-number-3">11.1.</span> Command</h3>
<div class="outline-text-3" id="text-11-1">
<ul class="org-ul">
<li><b><b><b>P2PRC instances "number of instances"</b></b></b> : Starts p2prc processes
based on the number of number instances provided. This includes
creating temporary folders with independent IPTables.</li>
<li><b><b><b>Start all instances "number of instances"</b></b></b>: Starts the P2PRC instances
created. This function enters into the instance directory and runs
```p2prc -s &amp;``` with a delay for approximately 3 seconds. This allows
each independent created node to learn about each other.</li>
<li><b><b><b>IP Tables after Started number of instances"</b></b></b>: Prints the IPTable of
each independant node.</li>
<li><b><b><b>Remove all test files</b></b></b>: Removes all test files created which needed for
testing the generated P2PRC instances.</li>
<li><b><b><b>Kill all instances</b></b></b>: Kills all the background P2PRC instances created.</li>
</ul>
</div>
</div>
<div id="outline-container-orga514f52" class="outline-3">
<h3 id="orga514f52"><span class="section-number-3">11.2.</span> Sample bash instructions</h3>
<div class="outline-text-3" id="text-11-2">
<div class="org-src-container">
<pre class="src src-bash"># Unset default P2PRC env path
unset P2PRC
# Run with 2 nodes
P2PRC_instances 3
# Start instances
Start_all_instances 3
# List ip tables of nodes started
IP_Tables_after_Started 3
# Remove test files created
Remove_all_test_files
# Kill all instances
Kill_all_instances
</pre>
</div>
<p>
Source code: <a href="https://github.com/Akilan1999/p2p-rendering-computation/blob/master/Simulation/simulation.sh">https://github.com/Akilan1999/p2p-rendering-computation/blob/master/Simulation/simulation.sh</a>
</p>
</div>
</div>
</div>
<div id="outline-container-orga046d58" class="outline-2">
<h2 id="orga046d58"><span class="section-number-2">12.</span> Blog posts</h2>
<div class="outline-text-2" id="text-12">
</div>
<div id="outline-container-orgec88f20" class="outline-3">
<h3 id="orgec88f20"><span class="section-number-3">12.1.</span> Self host within 5 minutes any program</h3>
<div class="outline-text-3" id="text-12-1">
<ul class="org-ul">
<li>Author: <a href="http://akilan.io/">Akilan Selvacoumar</a></li>
<li>Date: 28-01-2025</li>
</ul>
@@ -1068,7 +1143,7 @@ func main() {
<li>Video tutorial:</li>
</ul>
<div id="org756aa28" class="figure">
<div id="org01fbebe" class="figure">
<p><a href="https://youtu.be/rN4SiVowg5E" class="video"><img src="https://i3.ytimg.com/vi/rN4SiVowg5E/maxresdefault.jpg" alt="maxresdefault.jpg" class="video" /></a>
</p>
</div>
@@ -1078,9 +1153,9 @@ This is a fun expirement for anyone to try to quickly run a server and
quickly do a map port and domain name mapping in a single command.
</p>
</div>
<div id="outline-container-orgd03815a" class="outline-4">
<h4 id="orgd03815a"><span class="section-number-4">11.1.1.</span> 1. Find a program you want to run</h4>
<div class="outline-text-4" id="text-11-1-1">
<div id="outline-container-org07ee6bd" class="outline-4">
<h4 id="org07ee6bd"><span class="section-number-4">12.1.1.</span> 1. Find a program you want to run</h4>
<div class="outline-text-4" id="text-12-1-1">
<p>
Let's try to setup a really easy program (Let's do with Linkwarden
with docker compose :) ). This is under the assumption you have docker
@@ -1088,8 +1163,8 @@ compose installed on your local machine.
</p>
</div>
<ol class="org-ol">
<li><a id="orgc05f730"></a>Let's run Linkwarden using docker compose and P2PRC<br />
<div class="outline-text-5" id="text-11-1-1-1">
<li><a id="org2b6a10c"></a>Let's run Linkwarden using docker compose and P2PRC<br />
<div class="outline-text-5" id="text-12-1-1-1">
<p>
<a href="https://docs.linkwarden.app/self-hosting/installation">Installation instructions</a>:
</p>
@@ -1177,17 +1252,17 @@ ex: <a href="https://linkwarden.akilan.io">https://linkwarden.akilan.io</a>
</div>
</div>
</div>
<div id="outline-container-orgb32e475" class="outline-2">
<h2 id="orgb32e475"><span class="section-number-2">12.</span> Ideas for future potencial features</h2>
<div class="outline-text-2" id="text-12">
<div id="outline-container-orgf31160d" class="outline-2">
<h2 id="orgf31160d"><span class="section-number-2">13.</span> Ideas for future potencial features</h2>
<div class="outline-text-2" id="text-13">
<p>
Consists of personal loideas for the future of P2PRC.
At moment only has main contributors writiing to this.
</p>
</div>
<div id="outline-container-org2666d00" class="outline-3">
<h3 id="org2666d00"><span class="section-number-3">12.1.</span> To support hetrogenous set of Nodes that cannot run P2PRC</h3>
<div class="outline-text-3" id="text-12-1">
<div id="outline-container-org1a8a88e" class="outline-3">
<h3 id="org1a8a88e"><span class="section-number-3">13.1.</span> To support hetrogenous set of Nodes that cannot run P2PRC</h3>
<div class="outline-text-3" id="text-13-1">
<p>
This stems from a personal issue I have when doing research
on <a href="https://github.com/CTSRD-CHERI/cheribsd">CheriBSD</a> kernel. For my research I am using the ARM morello
@@ -1202,9 +1277,9 @@ and would introduce a new layer fault tolerance within a local
network nodes.
</p>
</div>
<div id="outline-container-org332fcc8" class="outline-4">
<h4 id="org332fcc8"><span class="section-number-4">12.1.1.</span> Assumptions:</h4>
<div class="outline-text-4" id="text-12-1-1">
<div id="outline-container-org5d2c045" class="outline-4">
<h4 id="org5d2c045"><span class="section-number-4">13.1.1.</span> Assumptions:</h4>
<div class="outline-text-4" id="text-13-1-1">
<ul class="org-ul">
<li>I have a Morello board that cannot run P2PRC</li>
<li>The Morello has a local IP address (ex: 192.168.0.10)</li>
@@ -1216,9 +1291,9 @@ as well look into custom tasks into the hetrogenous hardware.</li>
</ul>
</div>
</div>
<div id="outline-container-org21a29ac" class="outline-4">
<h4 id="org21a29ac"><span class="section-number-4">12.1.2.</span> Set of interesting possible:</h4>
<div class="outline-text-4" id="text-12-1-2">
<div id="outline-container-orgb55e814" class="outline-4">
<h4 id="orgb55e814"><span class="section-number-4">13.1.2.</span> Set of interesting possible:</h4>
<div class="outline-text-4" id="text-13-1-2">
<p>
We build a cool set possibilities before and use this to build up the implementation
plan.
@@ -1234,9 +1309,9 @@ weight hypervisors.</li>
</ul>
</div>
</div>
<div id="outline-container-org4947494" class="outline-4">
<h4 id="org4947494"><span class="section-number-4">12.1.3.</span> Implementation</h4>
<div class="outline-text-4" id="text-12-1-3">
<div id="outline-container-org7855189" class="outline-4">
<h4 id="org7855189"><span class="section-number-4">13.1.3.</span> Implementation</h4>
<div class="outline-text-4" id="text-13-1-3">
<ul class="org-ul">
<li>To use implementations similar to <a href="https://linux.die.net/man/1/socat">socat</a> to ensure we can bind address of local
nodes to a node running P2PRC and the node running P2PRC can do a local map port.</li>
@@ -1249,7 +1324,7 @@ other nodes can access the Morello board who have permission access.</li>
</ul>
<div id="orgf818690" class="figure">
<div id="orgd955246" class="figure">
<p><img src="./images/P2PRCRemoteNodes.png" alt="P2PRCRemoteNodes.png" />
</p>
<p><span class="figure-number">Figure 1: </span>Implementation idea (To be improved upon)</p>
@@ -1261,7 +1336,7 @@ other nodes can access the Morello board who have permission access.</li>
</div>
<div id="postamble" class="status">
<p class="author">Author: Akilan</p>
<p class="date">Created: 2025-04-28 Mon 23:14</p>
<p class="date">Created: 2025-05-30 Fri 18:05</p>
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>

View File

@@ -690,18 +690,28 @@ configuration file was generated using JSON format.
#+begin_src json
{
"MachineName": "pc-74-120.customer.ask4.lan",
"MachineName": "Akilans-MacBook-Pro.local-975261X",
"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/",
"DockerRunLogs": "/tmp/",
"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",
"ProxyPort": "",
"GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json",
"FRPServerPort": "True",
"BehindNAT": "True",
"FRPServerPort": true,
"BehindNAT": true,
"IPTableKey": "QH3yQrGRe2X4",
"PublicKeyFile": "/Users/akilan/Documents/p2p-rendering-computation/p2prc.publicKey",
"PrivateKeyFile": "/Users/akilan/Documents/p2p-rendering-computation/p2prc.privateKey",
"PemFile": "/Users/akilan/Documents/p2p-rendering-computation/cert.pem",
"KeyFile": "/Users/akilan/Documents/p2p-rendering-computation/key.pem",
"BareMetal": false,
"UnsafeMode": false,
"Test": false,
"CustomConfig": null
}
#+end_src
@@ -783,10 +793,48 @@ func main() {
}
}
#+end_src
* Simulation
The simulation library is a really simple library to locally
run serveral instances of P2PRC to test the functionality
of sending information through the network and particularly
the Node discovery mechanism. There are current 5 commands
which can be used as shown below:
** Command
- ***P2PRC instances "number of instances"*** : Starts p2prc processes
based on the number of number instances provided. This includes
creating temporary folders with independent IPTables.
- ***Start all instances "number of instances"***: Starts the P2PRC instances
created. This function enters into the instance directory and runs
```p2prc -s &``` with a delay for approximately 3 seconds. This allows
each independent created node to learn about each other.
- ***IP Tables after Started number of instances"***: Prints the IPTable of
each independant node.
- ***Remove all test files***: Removes all test files created which needed for
testing the generated P2PRC instances.
- ***Kill all instances***: Kills all the background P2PRC instances created.
** Sample bash instructions
#+begin_src bash
# Unset default P2PRC env path
unset P2PRC
# Run with 2 nodes
P2PRC_instances 3
# Start instances
Start_all_instances 3
# List ip tables of nodes started
IP_Tables_after_Started 3
# Remove test files created
Remove_all_test_files
# Kill all instances
Kill_all_instances
#+end_src
Source code: https://github.com/Akilan1999/p2p-rendering-computation/blob/master/Simulation/simulation.sh
* Blog posts
** Self host within 5 minutes any program

View File

@@ -1,143 +0,0 @@
import ctypes
from ctypes import Structure, c_char_p, c_int, cdll
from dataclasses import dataclass, astuple
import time
import json
from urllib.parse import urlparse
from typing import List
import subprocess
import uuid
import dacite
import os
import sqlalchemy
import dataclasses
from typing import Union
import schedule
import threading
import requests
import subprocess
# p2prc.Init("")
# Start running schedule
schedule.run_pending()
# # Create Sqlite database to track processes
# engine=sqlalchemy.create_engine(f'sqlite:///homeserver.db')
# Global variable
# A global variable will be populated on runtime.
# It is read from P2PRC directly or from a local
# database.
# Node information
# Generated using: https://jsonformatter.org/json-to-python
@dataclass
class Node:
Name: str
MachineUsername: str
IPV4: str
IPV6: str
Latency: int
Download: int
Upload: int
ServerPort: str
BareMetalSSHPort: str
NAT: bool
EscapeImplementation: str
ProxyServer: bool
UnSafeMode: bool
PublicKey: str
CustomInformation: str
@dataclass
class IPAddress:
ip_address: List[Node]
# ----------------------------------------------------------------------------
# ----------------------------- Helper functions -----------------------------
# ----------------------------------------------------------------------------
p2prc = None
def LoadDLL(envPath=""):
global p2prc
# os.environ["P2PRC"] = envPath
print(envPath)
# env = "P2PRC=" + envPath
os.system("sh setEnv.sh " + envPath)
# subprocess.call("sh setEnv.sh " + envPath)
p2prc = ctypes.CDLL("SharedObjects/p2prc.so")
def StartServer():
# Starting P2PRC as a server mode
p2prc.Server()
def Init():
p2prc.Init("")
# Class to create string to pass as string function
# parameter to shared object file
class go_string(Structure):
_fields_ = [
("p", c_char_p),
("n", c_int)]
# Ensuring local port can escape NAT and responds
# with the public ip and port no.
# If the domain name is specified then the public IP
# can be used as an A name entry.
def P2PRCMapPort(port="",domainname="",serveraddress=""):
port = go_string(c_char_p(port.encode('utf-8')), len(port))
domainname = go_string(c_char_p(domainname.encode('utf-8')), len(domainname))
serveraddress = go_string(c_char_p(serveraddress.encode('utf-8')), len(serveraddress))
# Defining the response type of the GoLang function
# function
p2prc.MapPort.restype = c_char_p
# Calling the Go function
address = p2prc.MapPort(port,domainname,serveraddress)
res = str(address).strip("b'")
return res
# Lists all avaliable nodes in the network
def ListNodes():
# View IP Table information
p2prc.ViewIPTable.restype = c_char_p
ipTable = p2prc.ViewIPTable()
# View IP Table as
ipTableObject = json.loads((str(ipTable).strip("b'")))
dat: IPAddress = dacite.from_dict(IPAddress,ipTableObject)
return dat
# Add a root node to P2RRC and overwrites all other nodes.
# To be only added before the network started and with
# the intention of a fresh protocol.
def AddRootNode(ip="", port="") -> bool:
ip = go_string(c_char_p(ip.encode('utf-8')), len(ip))
port = go_string(c_char_p(port.encode('utf-8')), len(port))
p2prc.AddRootNode.restype = c_char_p
res = p2prc.AddRootNode(ip, port)
if str(res).strip("b'") == "Success":
return True
return False
# python function to pass-through custom
# information to interpret which can be
# interpreted as a DSL.
def AddCustomInformation(message="") -> bool:
message = go_string(c_char_p(message.encode('utf-8')), len(message))
p2prc.CustomInformation.restype = c_char_p
status = p2prc.CustomInformation(message)
if str(status).strip("b'") == "Success":
return True
return False

View File

@@ -1,6 +0,0 @@
dacite
schedule
sqlalchemy
dacite
schedule
sqlalchemy

View File

@@ -1,4 +0,0 @@
dacite
schedule
sqlalchemy
requests

View File

@@ -1 +0,0 @@
export P2PRC=$1

View File

@@ -1,145 +0,0 @@
# This repo consists of the P2PRC simulation to ensure
# that we can test various nodes locally with just processes.
# Note: This implementation is for local nodes only.
from library import *
import os
import socket
from contextlib import closing
# Stores the base information
# required to know about a P2PRC node
@dataclass
class P2PRCNode:
Name: str
ConfigLocation: str
ServerPort: str
RunningState: bool
RootNodePort: str
@dataclass
class P2PRCNodes:
P2PRCNodes: List[P2PRCNode]
# Tracker for P2PRC nodes
PublicP2PRCNodes: Union[P2PRCNodes, None] = None
# Tracker of root Node
RootNode: P2PRCNode
# Sets up P2PRC with default configuration
def SetupP2PRCNode(name=""):
# Unset environment variables
os.environ.pop('P2PRC', None)
# Create Test folder
Dirname = "P2PRC-Test-" + name
try:
os.mkdir(Dirname)
print(f"Directory '{Dirname}' created successfully.")
except FileExistsError:
print(f"Directory '{Dirname}' already exists.")
KillProcedure()
# Set env variable for session
envPath = os.path.abspath(os.getcwd()) + "/" + Dirname
LoadDLL(envPath)
# Generate random 4
ServerPortNo = str(find_free_port())
# Initialise data class
p2prcNode = P2PRCNode(
Name = name,
ConfigLocation = envPath,
ServerPort = ServerPortNo,
RunningState = True,
RootNodePort = "",
)
# Adds P2PRC node to memory
AddP2PRCNodeToMemory(p2prcNode)
# Initialise P2PRC instance
Init()
# Add root node to ip table
AddRootNode("0.0.0.0",ServerPortNo)
# Change server port no on Config
ChangeFileValue(envPath + "/config.json", "ServerPort", ServerPortNo)
thread = threading.Thread(target = StartServer)
thread.start()
# Find free TCP port avaliable
# Source: https://stackoverflow.com/questions/1365265/on-localhost-how-do-i-pick-a-free-port-number
def find_free_port():
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
s.bind(('', 0))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
return s.getsockname()[1]
# Standard function called after
# a simulation is terminated or
# when error exception is called
def KillProcedure():
RemoveAllP2PRCNodesFromMemoryAndConfigFile()
# -------------------------- helper functions -----------------------
def ChangeFileValue(file_path, key, new_value):
"""
Reads a JSON file, updates a key with a new value, and writes it back.
:param file_path: Path to the JSON file
:param key: Key in the JSON to update
:param new_value: New value to assign to the key
"""
# Read from the JSON file
with open(file_path, 'r') as file:
data = json.load(file)
# Update the key with the new value
data[key] = new_value
# Write the updated data back to the JSON file
with open(file_path, 'w') as file:
json.dump(data, file, indent=4)
# Adds the process dataclass the to
# the global variable PublicProcess.
def AddP2PRCNodeToMemory(p2prcNode: P2PRCNode):
global PublicP2PRCNodes
global RootNode
if PublicP2PRCNodes == None:
PublicP2PRCNodes = P2PRCNodes(P2PRCNodes=[p2prcNode])
p2prcNode.RootNodePort = p2prcNode.ServerPort
RootNode = p2prcNode
else:
p2prcNode.RootNodePort = RootNode.ServerPort
PublicP2PRCNodes.P2PRCNodes.append(p2prcNode)
# Remove all nodes test nodes generated
def RemoveAllP2PRCNodesFromMemoryAndConfigFile():
global PublicP2PRCNodes
if PublicP2PRCNodes is not None:
for node in PublicP2PRCNodes.P2PRCNodes:
config_path = node.ConfigLocation
# Safely remove the folder if it exists
if os.path.exists(config_path) and os.path.isdir(config_path):
try:
shutil.rmtree(config_path)
print(f"Deleted folder: {config_path}")
except Exception as e:
print(f"Failed to delete {config_path}: {e}")
# Clear the node list
PublicP2PRCNodes = None
print("All P2PRC nodes removed from memory.")
else:
print("No P2PRC nodes to remove.")
if __name__ == "__main__":
# Setting up 2 P2PRC nodes
SetupP2PRCNode(name="Test")
SetupP2PRCNode(name="Test1")

114
Simulation/simulation.sh Normal file
View File

@@ -0,0 +1,114 @@
# Unset P2PRC
unset P2PRC
# Create P2PRC instances
# Parameters:
# 1. Number of nodes
P2PRC_instances() {
local rootPort=""
for (( counter=0; counter<$1; counter++ )); do
mkdir test-$counter/
cd test-$counter/
# Generate a new random port
NEW_PORT=$(shuf -i 2000-65000 -n 1)
# Initialize node
p2prc --dc
# Save rootPort from the first node
if [[ $counter -eq 0 ]]; then
rootPort=$NEW_PORT
fi
echo "Root port: $rootPort"
echo "This node's port: $NEW_PORT"
# Set root port
p2prc --arn --ip 0.0.0.0 -p "$rootPort"
# add current node
p2prc --as 0.0.0.0 -p "$NEW_PORT"
# Replace the ServerPort in config
sed -i.bak "s/\"ServerPort\": \"[0-9]*\"/\"ServerPort\": \"$NEW_PORT\"/" "./config.json"
sed -i.bak "s/\"Test\": false/\"Test\": true/" "./config.json"
sed -i.bak "s/\"BehindNAT\": true/\"BehindNAT\": false/" "./config.json"
cat config.json
# List services
p2prc --ls
cd ..
done
# remove all instances after testing (optional — might want to comment this during testing)
# rm -rf test-*
}
# Arrays of process IDs
pids=()
# Calls all the P2PRC instances created for testing
Start_all_instances() {
for (( counter=0; counter<$1; counter++ )); do
cd test-$counter/
# Start P2PRC as background process
p2prc -s &
pids+=($!)
sleep 3
cd ..
done
}
# Kills all P2PRC instances
Kill_all_instances() {
for pid in "${pids[@]}"; do
kill "$pid"
echo "Killed process $pid"
done
}
# Removes all test files created
Remove_all_test_files() {
rm -rf test-*
}
# List ip tables of all nodes started
IP_Tables_after_Started() {
for (( counter=0; counter<$1; counter++ )); do
cd test-$counter/
p2prc --ls
cd ..
done
}
Update_All_IP_Tables() {
for (( counter=0; counter<$1; counter++ )); do
cd test-$counter/
p2prc --us
cd ..
done
}
# ---------------- Work flow test ---------------
# Unset default P2PRC env path
unset P2PRC
# Run with 2 nodes
P2PRC_instances 3
## Start instances
Start_all_instances 3
## List ip tables of nodes started
IP_Tables_after_Started 3
#
## Remove test files created
Remove_all_test_files
## Kill all instances
Kill_all_instances

View File

@@ -1,14 +0,0 @@
from library import *
if __name__ == "__main__":
P2PRCNodes = ListNodes()
# Print nodes in the network
print(P2PRCNodes)
# Add custom information to the network
if AddCustomInformation("Test"):
print("It worked")
if AddRootNode("0.0.0.0", "8081"):
print("It worked for adding root node")

View File

@@ -1,107 +1,108 @@
package abstractions
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/gin-gonic/gin"
"os"
"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
}
}
// 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
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
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, domainName string, serverAddress string) (response *client.ResponseMAPPort, err error) {
response, err = client.MAPPort(port, domainName, serverAddress)
return
response, err = client.MAPPort(port, domainName, serverAddress)
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)
//}
// 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
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
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()
return clientIPTable.UpdateIpTableListClient()
}
// AddCustomInformation allows to pass custom information
// through the network to which can be listened on
// all peers in the network to execute a task.
func AddCustomInformation(information string) error {
return clientIPTable.AddCustomInformationToIPTable(information)
return clientIPTable.AddCustomInformationToIPTable(information)
}
// AddRootNode Adds root node to the network by using defaults except for
// ip address and port no. Supports only IPV4 as of now.
func AddRootNode(rootIP string, portNo string) error {
var rootNode []p2p.IpAddress
var rootNode []p2p.IpAddress
rootNode = append(rootNode, p2p.IpAddress{
Name: "",
Ipv4: rootIP,
ServerPort: portNo,
NAT: false,
})
return generate.GenerateIPTableFile(rootNode)
rootNode = append(rootNode, p2p.IpAddress{
Name: "",
Ipv4: rootIP,
ServerPort: portNo,
NAT: false,
})
return generate.GenerateIPTableFile(rootNode)
}

View File

@@ -1,301 +1,310 @@
package client
import (
"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"`
//}
//
//// 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
//}
//
//// 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
// }
//
// 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:]...)
//
// // Write new groups to the grouptrackcontainer json file
// err = groups.WriteGroup()
// if err != nil {
// return err
// }
//
// 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)
//
// // 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
//}
//
//// 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
// }
//
// 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
// }
//
// 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
// }
// }
//
// 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
// }
//
// return nil
//}
type Groups struct {
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
}
// 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
}
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:]...)
// Write new groups to the grouptrackcontainer json file
err = groups.WriteGroup()
if err != nil {
return err
}
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)
// 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
}
// 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
}
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
}
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
}
}
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
}
return nil
}
// ReadGroup Function reads grouptrackcontainers.json and converts
// result to Groups
//func ReadGroup() (*Groups, error) {
// // 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(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
//}
//
//// 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
//}
//
//// 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
//}
//
//// 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
// }
// }
// }
//
// // Write modified result to the Groups track container JSON file
// err = group.WriteGroup()
// if err != nil {
// return err
// }
//
// return nil
//}
func ReadGroup() (*Groups, error) {
// 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(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
}
// 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
}
// 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
}
// 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
}
}
}
// Write modified result to the Groups track container JSON file
err = group.WriteGroup()
if err != nil {
return err
}
return nil
}

View File

@@ -1,210 +1,220 @@
package client
//// TrackContainers This struct stores arrays of current containers running
//type TrackContainers struct {
// 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"`
//}
//
//// 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(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
// }
//
// // 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)
//
// // 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
//}
//
//// 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(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
// }
//
// return nil
//}
//
//// ViewTrackedContainers View Containers currently tracked
//func ViewTrackedContainers() (error, *TrackContainers) {
// 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
//}
//
//// ReadTrackContainers Reads containers which are currently tracked
//func ReadTrackContainers(filename string) (*TrackContainers, error) {
// 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)
// }
//
// return c, nil
//}
//
////func ModifyTrackContainers()
//
//// 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. ")
//}
//
//// 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
// }
//
// return nil
//}
//
//// WriteContainers Write information back to the config file
//func (TC *TrackContainers) WriteContainers() error {
// // 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
//}
//
//// 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
//}
import (
"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"`
}
// TrackContainer Stores information of current containers
type TrackContainer struct {
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(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
}
// 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)
// 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
}
// 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(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
}
return nil
}
// ViewTrackedContainers View Containers currently tracked
func ViewTrackedContainers() (error, *TrackContainers) {
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
}
// ReadTrackContainers Reads containers which are currently tracked
func ReadTrackContainers(filename string) (*TrackContainers, error) {
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)
}
return c, nil
}
//func ModifyTrackContainers()
// 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. ")
}
// 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
}
return nil
}
// WriteContainers Write information back to the config file
func (TC *TrackContainers) WriteContainers() error {
// 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
}
// 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
}

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,146 +18,147 @@ 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(nil, nil)
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
}
}
// Not required to update IP table as speed test updates the IP Table
//err = ipStruct.WriteIpTable()
//if err != nil {
// return err
//}
// Not required to update IP table as speed test updates the IP Table
//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(nil, nil)
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 && !Config.Test) && 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)
//}
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
// Ensure that the IP Table has Node pingable
err := p2p.LocalSpeedTestIpTable()
if err != nil {
return err
}
return nil
}
// SendPostRequest Sends a file as a
@@ -207,58 +208,58 @@ func RemoveOfflineNodes() 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,180 +1,192 @@
package client
//var (
// serverPort = "8088"
// client = http.Client{}
//)
//
//// StartContainer Start container using REST api Implementation
//// 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, 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)
// //
// ////Get port number of the server
// //serverPort, err := GetServerPort(IP)
// //if err != nil {
// // return nil, err
// //}
//
// //if version == "version 6" {
// // URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
// //} else {
// // 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
// }
//
// // Convert response to byte value
// byteValue, err := ioutil.ReadAll(resp.Body)
// if err != nil {
// return nil, err
// }
//
// // Create variable for result response type
// var dockerResult docker.DockerVM
//
// // Adds byte value to docker.DockerVM struct
// json.Unmarshal(byteValue, &dockerResult)
// if err != nil {
// return nil, err
// }
//
// // Adds the container to the tracked list
// err = AddTrackContainer(&dockerResult, IP)
// if err != nil {
// return nil, err
// }
//
// return &dockerResult, nil
//}
//
//// RemoveContianer Stops and removes container from the server
//func RemoveContianer(IP string, ID string) error {
// var URL string
// //version := p2p.Ip4or6(IP)
// //
// ////Get port number of the server
// //serverPort, err := GetServerPort(IP)
// //if err != nil {
// // return err
// //}
//
// //if version == "version 6" {
// // URL = "http://[" + IP + "]:" + serverPort + "/RemoveContainer?id=" + ID
// //} else {
// URL = "http://" + IP + "/RemoveContainer?id=" + ID
// //}
// 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
// }
//
// // Checks if success is returned in the body
// if string(byteValue[:]) == "success" {
// fmt.Println("success")
// }
//
// // Remove container from groups it exists in
// err = RemoveContainerGroups(ID)
// if err != nil {
// return err
// }
// // Remove container created from the tracked list
// err = RemoveTrackedContainer(ID)
// if err != nil {
// return err
// }
//
// return nil
//}
//
//// ViewContainers This function displays all containers available on server side
//func ViewContainers(IP string) (*docker.DockerContainers, error) {
// // Passes URL with route /ShowImages
// var URL string
// //version := p2p.Ip4or6(IP)
// //
// ////Get port number of the server
// //serverPort, err := GetServerPort(IP)
// //if err != nil {
// // return nil, err
// //}
//
// //if version == "version 6" {
// // URL = "http://[" + IP + "]:" + serverPort + "/ShowImages"
// //} else {
// URL = "http://" + IP + "/ShowImages"
// //}
// resp, err := http.Get(URL)
// if err != nil {
// return nil, err
// }
//
// // Convert response to byte value
// byteValue, err := ioutil.ReadAll(resp.Body)
// if err != nil {
// return nil, err
// }
//
// // Create variable for result response type
// var Result docker.DockerContainers
//
// // Adds byte value to docker.DockerContainers struct
// json.Unmarshal(byteValue, &Result)
// if err != nil {
// return nil, err
// }
//
// return &Result, nil
//}
//
//// GetServerPort Helper function to do find out server port information
//func GetServerPort(IpAddress string) (string, error) {
// // Getting information from the clients ip table
// ipTable, err := p2p.ReadIpTable()
// if err != nil {
// return "", err
// }
//
// // Iterate thorough ip table struct and find
// // out which port is for the ip address provided
// // in the parameter of the function
// for _, address := range ipTable.IpAddress {
// // If we found a match then return a port
// if address.Ipv4 == IpAddress || address.Ipv6 == IpAddress {
// return address.ServerPort, nil
// }
// }
//
// // We return default port
// return "8088", nil
//}
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"
"net/http"
"strconv"
)
var (
serverPort = "8088"
client = http.Client{}
)
// StartContainer Start container using REST api Implementation
// 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, 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)
//
////Get port number of the server
//serverPort, err := GetServerPort(IP)
//if err != nil {
// return nil, err
//}
//if version == "version 6" {
// URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
//} else {
// 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
}
// Convert response to byte value
byteValue, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// Create variable for result response type
var dockerResult docker.DockerVM
// Adds byte value to docker.DockerVM struct
json.Unmarshal(byteValue, &dockerResult)
if err != nil {
return nil, err
}
// Adds the container to the tracked list
err = AddTrackContainer(&dockerResult, IP)
if err != nil {
return nil, err
}
return &dockerResult, nil
}
// RemoveContianer Stops and removes container from the server
func RemoveContianer(IP string, ID string) error {
var URL string
//version := p2p.Ip4or6(IP)
//
////Get port number of the server
//serverPort, err := GetServerPort(IP)
//if err != nil {
// return err
//}
//if version == "version 6" {
// URL = "http://[" + IP + "]:" + serverPort + "/RemoveContainer?id=" + ID
//} else {
URL = "http://" + IP + "/RemoveContainer?id=" + ID
//}
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
}
// Checks if success is returned in the body
if string(byteValue[:]) == "success" {
fmt.Println("success")
}
// Remove container from groups it exists in
err = RemoveContainerGroups(ID)
if err != nil {
return err
}
// Remove container created from the tracked list
err = RemoveTrackedContainer(ID)
if err != nil {
return err
}
return nil
}
// ViewContainers This function displays all containers available on server side
func ViewContainers(IP string) (*docker.DockerContainers, error) {
// Passes URL with route /ShowImages
var URL string
//version := p2p.Ip4or6(IP)
//
////Get port number of the server
//serverPort, err := GetServerPort(IP)
//if err != nil {
// return nil, err
//}
//if version == "version 6" {
// URL = "http://[" + IP + "]:" + serverPort + "/ShowImages"
//} else {
URL = "http://" + IP + "/ShowImages"
//}
resp, err := http.Get(URL)
if err != nil {
return nil, err
}
// Convert response to byte value
byteValue, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// Create variable for result response type
var Result docker.DockerContainers
// Adds byte value to docker.DockerContainers struct
json.Unmarshal(byteValue, &Result)
if err != nil {
return nil, err
}
return &Result, nil
}
// GetServerPort Helper function to do find out server port information
func GetServerPort(IpAddress string) (string, error) {
// Getting information from the clients ip table
ipTable, err := p2p.ReadIpTable()
if err != nil {
return "", err
}
// Iterate thorough ip table struct and find
// out which port is for the ip address provided
// in the parameter of the function
for _, address := range ipTable.IpAddress {
// If we found a match then return a port
if address.Ipv4 == IpAddress || address.Ipv6 == IpAddress {
return address.ServerPort, nil
}
}
// We return default port
return "8088", nil
}
// PrintStartContainer Prints results Generated container
//func PrintStartContainer(d *docker.DockerVM){

View File

@@ -7,6 +7,7 @@ import (
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/plugin"
"github.com/Akilan1999/p2p-rendering-computation/server"
"github.com/urfave/cli/v2"
)
@@ -85,36 +86,36 @@ var CliAction = func(ctx *cli.Context) error {
}
// Displays all images available on the server side
//if ViewImages != "" {
// imageRes, err := client.ViewContainers(ViewImages)
// standardOutput(err, imageRes)
//}
//
//// Function called to stop and remove server from Docker
//if RemoveVM != "" {
// if ID == "" {
// fmt.Println("provide container ID via --ID or --id")
// } else {
// err := client.RemoveContianer(RemoveVM, ID)
// standardOutput(err, nil)
// }
//}
if ViewImages != "" {
imageRes, err := client.ViewContainers(ViewImages)
standardOutput(err, imageRes)
}
// Function called to stop and remove server from Docker
if RemoveVM != "" {
if ID == "" {
fmt.Println("provide container ID via --ID or --id")
} else {
err := client.RemoveContianer(RemoveVM, ID)
standardOutput(err, nil)
}
}
//Call function to create Docker container
//if CreateVM != "" {
//
// var PortsInt int
//
// if Ports != "" {
// // Convert Get Request value to int
// fmt.Sscanf(Ports, "%d", &PortsInt)
// }
//
// // Calls function to do Api call to start the container on the server side
// imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
//
// standardOutput(err, imageRes)
//}
if CreateVM != "" {
var PortsInt int
if Ports != "" {
// Convert Get Request value to int
fmt.Sscanf(Ports, "%d", &PortsInt)
}
// Calls function to do Api call to start the container on the server side
imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
standardOutput(err, imageRes)
}
//Call if specs flag is called
if Specs != "" {
@@ -137,83 +138,83 @@ var CliAction = func(ctx *cli.Context) error {
// If the view plugin flag is called then display all
// plugins available
//if ViewPlugin {
// plugins, err := plugin.DetectPlugins()
// standardOutput(err, plugins)
//}
if ViewPlugin {
plugins, err := plugin.DetectPlugins()
standardOutput(err, plugins)
}
// If the flag Tracked Container is called or the flag
// --tc
//if TrackedContainers {
// err, trackedContainers := client.ViewTrackedContainers()
// standardOutput(err, trackedContainers)
//}
if TrackedContainers {
err, trackedContainers := client.ViewTrackedContainers()
standardOutput(err, trackedContainers)
}
//Executing plugin when the plugin flag is called
// --plugin
//if ExecutePlugin != "" {
// // To execute plugin requires the container ID or group ID provided when being executed
// if ID != "" {
// err := plugin.CheckRunPlugin(ExecutePlugin, ID)
// standardOutput(err, nil)
// }
// //else {
// // fmt.Println("provide container ID via --ID or --id")
// //}
//
//}
if ExecutePlugin != "" {
// To execute plugin requires the container ID or group ID provided when being executed
if ID != "" {
err := plugin.CheckRunPlugin(ExecutePlugin, ID)
standardOutput(err, nil)
}
//else {
// fmt.Println("provide container ID via --ID or --id")
//}
}
// Executing function to create new group
// Creates new group and outputs JSON file
//if CreateGroup {
// group, err := client.CreateGroup()
// standardOutput(err, group)
//}
if CreateGroup {
group, err := client.CreateGroup()
standardOutput(err, group)
}
// Actions to be performed when the
// group flag is called
// --group <Group ID>
//if Group != "" {
// // Remove container from group based on group ID provided
// // --rmcgroup --id <contianer id>
// if RemoveContainerGroup && ID != "" {
// group, err := client.RemoveContainerGroup(ID, Group)
// standardOutput(err, group)
// } else if ID != "" { // Add container to group based on group ID provided
// // --id <Container ID>
// group, err := client.AddContainerToGroup(ID, Group)
// standardOutput(err, group)
// } else { // View all information about current group
// group, err := client.GetGroup(Group)
// standardOutput(err, group)
// }
//}
if Group != "" {
// Remove container from group based on group ID provided
// --rmcgroup --id <contianer id>
if RemoveContainerGroup && ID != "" {
group, err := client.RemoveContainerGroup(ID, Group)
standardOutput(err, group)
} else if ID != "" { // Add container to group based on group ID provided
// --id <Container ID>
group, err := client.AddContainerToGroup(ID, Group)
standardOutput(err, group)
} else { // View all information about current group
group, err := client.GetGroup(Group)
standardOutput(err, group)
}
}
// Execute function to remove entire group
// when remove group flag is called
// --rmgroup
//if RemoveGroup != "" {
// err := client.RemoveGroup(RemoveGroup)
// standardOutput(err, nil)
//}
if RemoveGroup != "" {
err := client.RemoveGroup(RemoveGroup)
standardOutput(err, nil)
}
// Execute Function to view all groups
//if Groups {
// groups, err := client.ReadGroup()
// standardOutput(err, groups)
//}
if Groups {
groups, err := client.ReadGroup()
standardOutput(err, groups)
}
//--------------------------------
//if PullPlugin != "" {
// err := plugin.DownloadPlugin(PullPlugin)
// standardOutput(err, nil)
//}
//
//if RemovePlugin != "" {
// err := plugin.DeletePlugin(RemovePlugin)
// standardOutput(err, nil)
//}
if PullPlugin != "" {
err := plugin.DownloadPlugin(PullPlugin)
standardOutput(err, nil)
}
if RemovePlugin != "" {
err := plugin.DeletePlugin(RemovePlugin)
standardOutput(err, nil)
}
if AddMetaData != "" {
err := clientIPTable.AddCustomInformationToIPTable(AddMetaData)

View File

@@ -74,48 +74,48 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"ADD_SERVER"},
Destination: &AddServer,
},
//&cli.StringFlag{
// Name: "ViewImages",
// Aliases: []string{"vi"},
// Usage: "View images available on the server IP address",
// EnvVars: []string{"VIEW_IMAGES"},
// Destination: &ViewImages,
//},
//&cli.StringFlag{
// Name: "CreateVM",
// Aliases: []string{"touch"},
// Usage: "Creates Docker container on the selected server",
// EnvVars: []string{"CREATE_VM"},
// Destination: &CreateVM,
//},
//&cli.StringFlag{
// Name: "ContainerName",
// Aliases: []string{"cn"},
// Usage: "Specifying the container run on the server side",
// 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 (IP:port) accompanied by container ID via --ID or --id",
// EnvVars: []string{"REMOVE_VM"},
// Destination: &RemoveVM,
//},
//&cli.StringFlag{
// Name: "ID",
// Aliases: []string{"id"},
// Usage: "Docker Container ID",
// EnvVars: []string{"ID"},
// Destination: &ID,
//},
&cli.StringFlag{
Name: "ViewImages",
Aliases: []string{"vi"},
Usage: "View images available on the server IP address",
EnvVars: []string{"VIEW_IMAGES"},
Destination: &ViewImages,
},
&cli.StringFlag{
Name: "CreateVM",
Aliases: []string{"touch"},
Usage: "Creates Docker container on the selected server",
EnvVars: []string{"CREATE_VM"},
Destination: &CreateVM,
},
&cli.StringFlag{
Name: "ContainerName",
Aliases: []string{"cn"},
Usage: "Specifying the container run on the server side",
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 (IP:port) accompanied by container ID via --ID or --id",
EnvVars: []string{"REMOVE_VM"},
Destination: &RemoveVM,
},
&cli.StringFlag{
Name: "ID",
Aliases: []string{"id"},
Usage: "Docker Container ID",
EnvVars: []string{"ID"},
Destination: &ID,
},
&cli.StringFlag{
Name: "Ports",
Aliases: []string{"p"},
@@ -123,13 +123,13 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"NUM_PORTS"},
Destination: &Ports,
},
//&cli.BoolFlag{
// Name: "GPU",
// Aliases: []string{"gpu"},
// Usage: "Create Docker Containers to access GPU",
// EnvVars: []string{"USE_GPU"},
// Destination: &GPU,
//},
&cli.BoolFlag{
Name: "GPU",
Aliases: []string{"gpu"},
Usage: "Create Docker Containers to access GPU",
EnvVars: []string{"USE_GPU"},
Destination: &GPU,
},
&cli.StringFlag{
Name: "Specification",
Aliases: []string{"specs"},
@@ -151,63 +151,63 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"NETWORK_INTERFACE"},
Destination: &NetworkInterface,
},
//&cli.BoolFlag{
// Name: "ViewPlugins",
// Aliases: []string{"vp"},
// Usage: "Shows plugins available to be executed",
// EnvVars: []string{"VIEW_PLUGIN"},
// Destination: &ViewPlugin,
//},
//&cli.BoolFlag{
// Name: "TrackedContainers",
// Aliases: []string{"tc"},
// Usage: "View (currently running) containers which have " +
// "been created from the client side ",
// EnvVars: []string{"TRACKED_CONTAINERS"},
// Destination: &TrackedContainers,
//},
//&cli.StringFlag{
// Name: "ExecutePlugin",
// Aliases: []string{"plugin"},
// Usage: "Plugin which needs to be executed",
// EnvVars: []string{"EXECUTE_PLUGIN"},
// Destination: &ExecutePlugin,
//},
//&cli.BoolFlag{
// Name: "CreateGroup",
// Aliases: []string{"cgroup"},
// Usage: "Creates a new group",
// EnvVars: []string{"CREATE_GROUP"},
// Destination: &CreateGroup,
//},
//&cli.StringFlag{
// Name: "Group",
// Aliases: []string{"group"},
// Usage: "group flag with argument group ID",
// EnvVars: []string{"GROUP"},
// Destination: &Group,
//},
//&cli.BoolFlag{
// Name: "Groups",
// Aliases: []string{"groups"},
// Usage: "View all groups",
// EnvVars: []string{"GROUPS"},
// Destination: &Groups,
//},
//&cli.BoolFlag{
// Name: "RemoveContainerGroup",
// Aliases: []string{"rmcgroup"},
// Usage: "Remove specific container in the group",
// EnvVars: []string{"REMOVE_CONTAINER_GROUP"},
// Destination: &RemoveContainerGroup,
//},
//&cli.StringFlag{
// Name: "RemoveGroup",
// Aliases: []string{"rmgroup"},
// Usage: "Removes the entire group",
// EnvVars: []string{"REMOVE_GROUP"},
// Destination: &RemoveGroup,
//},
&cli.BoolFlag{
Name: "ViewPlugins",
Aliases: []string{"vp"},
Usage: "Shows plugins available to be executed",
EnvVars: []string{"VIEW_PLUGIN"},
Destination: &ViewPlugin,
},
&cli.BoolFlag{
Name: "TrackedContainers",
Aliases: []string{"tc"},
Usage: "View (currently running) containers which have " +
"been created from the client side ",
EnvVars: []string{"TRACKED_CONTAINERS"},
Destination: &TrackedContainers,
},
&cli.StringFlag{
Name: "ExecutePlugin",
Aliases: []string{"plugin"},
Usage: "Plugin which needs to be executed",
EnvVars: []string{"EXECUTE_PLUGIN"},
Destination: &ExecutePlugin,
},
&cli.BoolFlag{
Name: "CreateGroup",
Aliases: []string{"cgroup"},
Usage: "Creates a new group",
EnvVars: []string{"CREATE_GROUP"},
Destination: &CreateGroup,
},
&cli.StringFlag{
Name: "Group",
Aliases: []string{"group"},
Usage: "group flag with argument group ID",
EnvVars: []string{"GROUP"},
Destination: &Group,
},
&cli.BoolFlag{
Name: "Groups",
Aliases: []string{"groups"},
Usage: "View all groups",
EnvVars: []string{"GROUPS"},
Destination: &Groups,
},
&cli.BoolFlag{
Name: "RemoveContainerGroup",
Aliases: []string{"rmcgroup"},
Usage: "Remove specific container in the group",
EnvVars: []string{"REMOVE_CONTAINER_GROUP"},
Destination: &RemoveContainerGroup,
},
&cli.StringFlag{
Name: "RemoveGroup",
Aliases: []string{"rmgroup"},
Usage: "Removes the entire group",
EnvVars: []string{"REMOVE_GROUP"},
Destination: &RemoveGroup,
},
&cli.StringFlag{
Name: "MAPPort",
Aliases: []string{"mp"},
@@ -231,20 +231,20 @@ var AppConfigFlags = []cli.Flag{
},
// Generate only allowed in dev release
// -- REMOVE ON REGULAR RELEASE --
//&cli.StringFlag{
// Name: "Generate",
// Aliases: []string{"gen"},
// Usage: "Generates a new copy of P2PRC which can be modified based on your needs",
// EnvVars: []string{"GENERATE"},
// Destination: &Generate,
//},
//&cli.StringFlag{
// Name: "ModuleName",
// Aliases: []string{"mod"},
// Usage: "New go project module name",
// EnvVars: []string{"MODULENAME"},
// Destination: &Modulename,
//},
&cli.StringFlag{
Name: "Generate",
Aliases: []string{"gen"},
Usage: "Generates a new copy of P2PRC which can be modified based on your needs",
EnvVars: []string{"GENERATE"},
Destination: &Generate,
},
&cli.StringFlag{
Name: "ModuleName",
Aliases: []string{"mod"},
Usage: "New go project module name",
EnvVars: []string{"MODULENAME"},
Destination: &Modulename,
},
//&cli.BoolFlag{
// Name: "FRPServerProxy",
// Aliases: []string{"proxy"},
@@ -253,20 +253,20 @@ var AppConfigFlags = []cli.Flag{
// Destination: &FRPProxy,
//},
//--------------------------------
//&cli.StringFlag{
// Name: "PullPlugin",
// Aliases: []string{"pp"},
// Usage: "Pulls plugin from git repos",
// EnvVars: []string{"PULLPLUGIN"},
// Destination: &PullPlugin,
//},
//&cli.StringFlag{
// Name: "RemovePlugin",
// Aliases: []string{"rp"},
// Usage: "Removes plugin",
// EnvVars: []string{"REMOVEPLUGIN"},
// Destination: &RemovePlugin,
//},
&cli.StringFlag{
Name: "PullPlugin",
Aliases: []string{"pp"},
Usage: "Pulls plugin from git repos",
EnvVars: []string{"PULLPLUGIN"},
Destination: &PullPlugin,
},
&cli.StringFlag{
Name: "RemovePlugin",
Aliases: []string{"rp"},
Usage: "Removes plugin",
EnvVars: []string{"REMOVEPLUGIN"},
Destination: &RemovePlugin,
},
&cli.StringFlag{
Name: "AddMetaData",
Aliases: []string{"amd"},

View File

@@ -38,6 +38,7 @@ type Config struct {
KeyFile string
BareMetal bool
UnsafeMode bool
Test bool
CustomConfig interface{}
//NetworkInterface string
//NetworkInterfaceIPV6Index int

View File

@@ -95,6 +95,7 @@ func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, No
Defaults.PrivateKeyFile = defaultPath + "p2prc.privateKey"
Defaults.BareMetal = false
Defaults.UnsafeMode = false
Defaults.Test = false
// Generate certificate files for SSL
err = GenerateCertificate()

View File

@@ -16,7 +16,6 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"log"
"math/big"
"net"
@@ -54,7 +53,8 @@ func GenerateCertificate() error {
//flag.Parse()
host, err = p2p.CurrentPublicIP()
//host, err = p2p.CurrentPublicIP()
host = "0.0.0.0"
if err != nil {
return err

12
flake.lock generated
View File

@@ -28,11 +28,11 @@
]
},
"locked": {
"lastModified": 1733668782,
"narHash": "sha256-tPsqU00FhgdFr0JiQUiBMgPVbl1jbPCY5gbFiJycL3I=",
"lastModified": 1745875161,
"narHash": "sha256-0YkWCS13jpoo3+sX/3kcgdxBNt1VZTmvF+FhZb4rFKI=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "514283ec89c39ad0079ff2f3b1437404e4cba608",
"rev": "2cbd7fdd6eeab65c494cc426e18f4e4d2a5e35c0",
"type": "github"
},
"original": {
@@ -43,11 +43,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1735834308,
"narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=",
"lastModified": 1748460289,
"narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6df24922a1400241dae323af55f30e4318a6ca65",
"rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102",
"type": "github"
},
"original": {

170
flake.nix
View File

@@ -1,41 +1,147 @@
{
description = "P2PRC nix flake";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.gomod2nix.url = "github:nix-community/gomod2nix";
inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils";
inputs = {
outputs = { self, nixpkgs, flake-utils, gomod2nix }:
(flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ gomod2nix.overlays.default ];
};
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# pkgs = nixpkgs.legacyPackages.${system};
flake-utils = {
url = "github:numtide/flake-utils";
};
# The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
# This has no effect on other platforms.
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;
in
{
gomod2nix = {
url = "github:nix-community/gomod2nix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
};
packages.default = callPackage ./. { };
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
go
gopls
gotools
go-tools
gomod2nix.packages.${system}.default
sqlite-interactive
];
};
})
);
outputs =
{
nixpkgs,
flake-utils,
gomod2nix,
...
}:
let
bindingsOverlay = import ./nix/overlays/bindings.nix;
coreOverlay = (final: prev: {
p2prc = final.callPackage ./. { };
});
in
(flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
gomod2nix.overlays.default
coreOverlay
bindingsOverlay
];
};
# The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
# This has no effect on other platforms.
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;
p2prcDefault = callPackage ./. { };
in
{
packages.default = p2prcDefault;
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
go
gopls
gotools
go-tools
gomod2nix.packages.${system}.default
sqlite-interactive
];
};
packages.initHaskellProject = pkgs.writeShellApplication {
name = "initHaskellProject";
runtimeInputs = with pkgs; [
ghc
cabal2nix
cabal-install
git
p2prcDefault
];
text =
let
# TODO: add the content for the main file
# p2prcMainContent = availablePort: availableUrl:
# ''
# module Main where
#
# import P2PRC
# ( runP2PRC
# , MapPortRequest(MkMapPortRequest)
# )
#
# main :: IO ()
# main =
# runP2PRC
# ( MkMapPortRequest ${availablePort} "${availableUrl}.akilan.io"
# )
# '';
#
# mainFileContent = p2prcMainContent (builtins.toString 8080) "haskell";
in
''
clear
if [ "$#" -eq 0 ]; then
echo "No arguments provided."
echo "Please provide the name of your project"
echo "nix run github:akilan1999/p2p-rendering-computation#initHaskellProject -- <NAME-PROJECT>"
exit 1;
fi
PROJECT_DIR="$1"
mkdir "$PROJECT_DIR"
cd "$PROJECT_DIR"
git init .
clear
cabal init --exe --simple
sed -i 's/base.*$/base, p2prc/' "$PROJECT_DIR".cabal
cabal2nix . > ./cabal.nix;
cabal2nix . --shell > shell.nix
git add .
clear
echo -e "run the following commands to finish nix development and production environment:\n\n"
echo -e "cd $PROJECT_DIR"
echo -e "nix flake init -t github:akilan1999/p2p-rendering-computation#haskell"
echo -e "nix develop"
echo -e "nix run"
'';
};
}
)) //
{
overlays = {
default = coreOverlay;
bindings = bindingsOverlay;
};
templates.haskell = {
path = ./nix/templates/haskell;
description = "Haskell Bindings to p2prc protocol";
};
};
}

5
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/Akilan1999/p2p-rendering-computation
go 1.18
require (
github.com/apenella/go-ansible v1.1.0
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible
github.com/fatedier/frp v0.45.0
github.com/gin-gonic/gin v1.6.3
@@ -15,6 +16,7 @@ require (
github.com/urfave/cli/v2 v2.3.0
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
golang.org/x/crypto v0.16.0
gopkg.in/yaml.v2 v2.4.0
)
require (
@@ -22,6 +24,8 @@ require (
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/apenella/go-common-utils v0.1.1 // indirect
github.com/apenella/go-common-utils/error v0.0.0-20200917063805-34b0ed3c4ce1 // indirect
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
@@ -96,6 +100,5 @@ require (
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools/v3 v3.0.3 // indirect
)

36
go.sum
View File

@@ -63,6 +63,7 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
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=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@@ -78,6 +79,13 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/apenella/go-ansible v1.1.0 h1:wWqaZBvoDxPjvtwXc2fXbDj546uBj/Kv2PL7PW82EfY=
github.com/apenella/go-ansible v1.1.0/go.mod h1:tHqFBSwWXF9k2hkLQWfq6oxMQZHslySQqttkA2siyqE=
github.com/apenella/go-common-utils v0.1.1 h1:dJA2tY22z6mYB5a+EogfiS7NxZsR/Ld3TWnZcS3JPa0=
github.com/apenella/go-common-utils v0.1.1/go.mod h1:E7RUbl9B1vdLkTIapoTE2W6pIgW7dTSJOxL3pf4gV6g=
github.com/apenella/go-common-utils/error v0.0.0-20200917063805-34b0ed3c4ce1 h1:lw/fwF65AaJVxyUTJShtBiZfaiafKde3QkR4im1glzQ=
github.com/apenella/go-common-utils/error v0.0.0-20200917063805-34b0ed3c4ce1/go.mod h1:Hj3S/BcSHKfv9VDMcrY7lsm9hGnb7cd70alSkl/Sv+4=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
@@ -98,6 +106,7 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -158,6 +167,8 @@ github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
@@ -189,6 +200,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@@ -228,6 +240,7 @@ github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac/go.mod h1:fLV0TLw
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74=
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
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=
@@ -301,6 +314,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
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=
@@ -371,10 +385,13 @@ github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -382,6 +399,7 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
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/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -444,6 +462,7 @@ github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5n
github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w=
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/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
@@ -451,6 +470,7 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
@@ -486,6 +506,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -526,6 +547,7 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
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/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-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
@@ -546,6 +568,7 @@ github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAm
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
@@ -560,6 +583,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
@@ -569,6 +594,7 @@ github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
@@ -580,6 +606,7 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
@@ -608,14 +635,20 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
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/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
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/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/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -648,6 +681,7 @@ github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
@@ -669,6 +703,7 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -683,6 +718,7 @@ gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 h1:dizWJqTWj
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40/go.mod h1:rOnSnoRyxMI3fe/7KIbVcsHRGxe30OONv8dEgo+vCfA=
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3 h1:qXqiXDgeQxspR3reot1pWme00CX1pXbxesdzND+EjbU=
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3/go.mod h1:sleOmkovWsDEQVYXmOJhx69qheoMTmCuPYyiCFCihlg=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=

35
main.go
View File

@@ -1,10 +1,13 @@
package main
import (
"github.com/Akilan1999/p2p-rendering-computation/cmd"
"github.com/urfave/cli/v2"
"log"
"os"
"os/signal"
"syscall"
"github.com/Akilan1999/p2p-rendering-computation/cmd"
"github.com/urfave/cli/v2"
)
// VERSION specifies the version of the platform
@@ -16,20 +19,20 @@ var OS, Pull_location, Run_script string
var List_servers, Ip_table bool
// To be implemented later on
//func getFireSignalsChannel() chan os.Signal {
//
// c := make(chan os.Signal, 1)
// signal.Notify(c,
// // https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
// syscall.SIGTERM, // "the normal way to politely ask a program to terminate"
// syscall.SIGINT, // Ctrl+C
// syscall.SIGQUIT, // Ctrl-\
// syscall.SIGKILL, // "always fatal", "SIGKILL and SIGSTOP may not be caught by a program"
// syscall.SIGHUP, // "terminal is disconnected"
// )
// return c
//
//}
func getFireSignalsChannel() chan os.Signal {
c := make(chan os.Signal, 1)
signal.Notify(c,
// https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
syscall.SIGTERM, // "the normal way to politely ask a program to terminate"
syscall.SIGINT, // Ctrl+C
syscall.SIGQUIT, // Ctrl-\
syscall.SIGKILL, // "always fatal", "SIGKILL and SIGSTOP may not be caught by a program"
syscall.SIGHUP, // "terminal is disconnected"
)
return c
}
func main() {
app := cli.NewApp()

View File

@@ -0,0 +1,7 @@
final: prev: {
haskellPackages = prev.haskellPackages.override {
overrides = hfinal: hprev: {
p2prc = hfinal.callPackage ../../Bindings/Haskell/project.nix { };
};
};
}

190
nix/templates/haskell/flake.lock generated Normal file
View File

@@ -0,0 +1,190 @@
{
"nodes": {
"flake-util": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"flake-utils": [
"p2prc-flake",
"flake-utils"
],
"nixpkgs": [
"p2prc-flake",
"nixpkgs"
]
},
"locked": {
"lastModified": 1745875161,
"narHash": "sha256-0YkWCS13jpoo3+sX/3kcgdxBNt1VZTmvF+FhZb4rFKI=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "2cbd7fdd6eeab65c494cc426e18f4e4d2a5e35c0",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "gomod2nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1748460289,
"narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1748370509,
"narHash": "sha256-QlL8slIgc16W5UaI3w7xHQEP+Qmv/6vSNTpoZrrSlbk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4faa5f5321320e49a78ae7848582f684d64783e9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"p2prc-flake": {
"inputs": {
"flake-utils": "flake-utils_2",
"gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1748646470,
"narHash": "sha256-7aZQQ+jHdlxUzFPXzEEYfH1oU3isSZlZnMC7HWUDHCk=",
"owner": "xecarlox94",
"repo": "p2p-rendering-computation",
"rev": "73a283a545d61754a0fe821287541c2cd412bc0e",
"type": "github"
},
"original": {
"owner": "xecarlox94",
"ref": "nix",
"repo": "p2p-rendering-computation",
"type": "github"
}
},
"root": {
"inputs": {
"flake-util": "flake-util",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"p2prc-flake": "p2prc-flake"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@@ -0,0 +1,49 @@
{
description = "Start of Haskell P2PRC flake";
inputs =
{
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-util.url = "github:numtide/flake-utils";
p2prc-flake.url = "github:xecarlox94/p2p-rendering-computation?ref=nix";
};
outputs = { nixpkgs, p2prc-flake, flake-utils, ... }:
(flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
p2prc-flake.overlays.default
p2prc-flake.overlays.bindings
];
};
in {
packages.default = pkgs.haskellPackages.callPackage ./cabal.nix { };
devShells.default = pkgs.haskellPackages.shellFor {
packages = p: [
(p.callPackage ./cabal.nix { })
];
buildInputs = with pkgs; [
p2prc-flake.packages.${system}.default
ghc
cabal2nix
cabal-install
];
# TODO: add cabal2nix shell command
# cabal2nix . --shell > ./shell.nix
shellHook = ''
cabal2nix . > ./cabal.nix
'';
};
}
));
}

View File

@@ -1,28 +1,30 @@
package frp
import (
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/pkg/config"
"github.com/phayes/freeport"
"math/rand"
"strconv"
"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"
)
// 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
@@ -31,154 +33,154 @@ type ClientMapping struct {
// 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 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
}
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],
},
}
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
//
// //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
//
// // Setup client information
// var c Client
// c.Name = "ServerPort"
// c.Server = &s
//
// // 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
// }
//
// //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
// }
//
// portInt, err = strconv.Atoi(proxyPort)
// if err != nil {
// return nil, err
// }
//
// Docker.Ports.PortSet[i].ExternalPort = portInt
// }
//
// return Docker, nil
//
//}
func StartFRPCDockerContainer(ipaddress string, port string, Docker *docker.DockerVM) (*docker.DockerVM, error) {
// setting new docker variable
//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
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// 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
}
//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
}
portInt, err = strconv.Atoi(proxyPort)
if err != nil {
return nil, err
}
Docker.Ports.PortSet[i].ExternalPort = portInt
}
return Docker, nil
}
// StartFRPClient Starts FRP client
func (c *Client) StartFRPClient() error {
cfg := config.GetDefaultClientConf()
cfg := config.GetDefaultClientConf()
//Config, err := defaultConfig.ConfigInit(nil, nil)
//if err != nil {
// return err
//}
//Config, err := defaultConfig.ConfigInit(nil, nil)
//if err != nil {
// return err
//}
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.TLSEnable = true
//cfg.TLSKeyFile = Config.KeyFile
//cfg.TLSCertFile = Config.PemFile
cfg.ServerAddr = c.Server.address
cfg.ServerPort = c.Server.port
//cfg.TLSEnable = true
//cfg.TLSKeyFile = Config.KeyFile
//cfg.TLSCertFile = Config.PemFile
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

@@ -42,6 +42,8 @@ type IP struct {
Query string
}
var Test = false
// ReadIpTable Read data from Ip tables from json file
func ReadIpTable() (*IpAddresses, error) {
// Get Path from config
@@ -178,6 +180,16 @@ func (table *IpAddresses) RemoveDuplicates() error {
// CurrentPublicIP Get Current Public IP address
func CurrentPublicIP() (string, error) {
// Get configs
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return "", err
}
// If test mode is on then return local address
if Config.Test {
return "0.0.0.0", nil
}
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return "", err

3
plugin/.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
.idea
.DS_Store
Dockerfile

2
plugin/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.idea
.DS_Store

1
plugin/README.md Normal file
View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@
Test if it's detected

12
plugin/TestAnsible/hosts Normal file
View File

@@ -0,0 +1,12 @@
---
all:
vars:
ansible_python_interpreter: /usr/bin/python3
main:
hosts:
host1:
ansible_host: 0.0.0.0 # Replace with your remote IP
ansible_port: 44003 # Replace with your remote SSH port
ansible_user: master # Replace wtih your username
ansible_ssh_pass: password
ansible_sudo_pass: password

View File

@@ -0,0 +1,8 @@
---
- hosts: all
tasks:
- name: simple-ansibleplaybook
debug:
msg: Your are running 'simple-ansibleplaybook' example

224
plugin/docs.md Normal file
View File

@@ -0,0 +1,224 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# plugin
```go
import "github.com/Akilan1999/p2p-rendering-computation/plugin"
```
## Index
- [func CheckRunPlugin\(PluginName string, ID string\) error](<#CheckRunPlugin>)
- [func DeletePlugin\(pluginname string\) error](<#DeletePlugin>)
- [func DownloadPlugin\(pluginurl string\) error](<#DownloadPlugin>)
- [func RunPluginContainer\(PluginName string, ContainerID string\) error](<#RunPluginContainer>)
- [type ExecuteIP](<#ExecuteIP>)
- [func \(e \*ExecuteIP\) ModifyHost\(p \*Plugin\) error](<#ExecuteIP.ModifyHost>)
- [func \(e \*ExecuteIP\) RunAnsible\(p \*Plugin\) error](<#ExecuteIP.RunAnsible>)
- [type Host](<#Host>)
- [func ReadHost\(filename string\) \(\*Host, error\)](<#ReadHost>)
- [type Plugin](<#Plugin>)
- [func RunPlugin\(pluginName string, IPAddresses \[\]\*ExecuteIP\) \(\*Plugin, error\)](<#RunPlugin>)
- [func SearchPlugin\(pluginname string\) \(\*Plugin, error\)](<#SearchPlugin>)
- [func \(p \*Plugin\) AutoSetPorts\(containerID string\) error](<#Plugin.AutoSetPorts>)
- [func \(p \*Plugin\) CopyToTmpPlugin\(\) error](<#Plugin.CopyToTmpPlugin>)
- [func \(p \*Plugin\) ExecutePlugin\(\) error](<#Plugin.ExecutePlugin>)
- [func \(p \*Plugin\) NumPorts\(\) error](<#Plugin.NumPorts>)
- [type Plugins](<#Plugins>)
- [func DetectPlugins\(\) \(\*Plugins, error\)](<#DetectPlugins>)
<a name="CheckRunPlugin"></a>
## func [CheckRunPlugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L330>)
```go
func CheckRunPlugin(PluginName string, ID string) error
```
CheckRunPlugin Checks if the ID belongs to the group or container calls the plugin function the appropriate amount of times
<a name="DeletePlugin"></a>
## func [DeletePlugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/packageManager.go#L46>)
```go
func DeletePlugin(pluginname string) error
```
DeletePlugin The following function deletes a plugin based on the plugin name provided.
<a name="DownloadPlugin"></a>
## func [DownloadPlugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/packageManager.go#L13>)
```go
func DownloadPlugin(pluginurl string) error
```
DownloadPlugin This functions downloads package from a git repo.
<a name="RunPluginContainer"></a>
## func [RunPluginContainer](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L284>)
```go
func RunPluginContainer(PluginName string, ContainerID string) error
```
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
<a name="ExecuteIP"></a>
## type [ExecuteIP](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L40-L45>)
ExecuteIP IP Address to execute Ansible instruction
```go
type ExecuteIP struct {
ContainerID string
IPAddress string
SSHPortNo string
Success bool
}
```
<a name="ExecuteIP.ModifyHost"></a>
### func \(\*ExecuteIP\) [ModifyHost](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L234>)
```go
func (e *ExecuteIP) ModifyHost(p *Plugin) error
```
ModifyHost adds IP address , port no to the config file
<a name="ExecuteIP.RunAnsible"></a>
### func \(\*ExecuteIP\) [RunAnsible](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L199>)
```go
func (e *ExecuteIP) RunAnsible(p *Plugin) error
```
RunAnsible Executes based on credentials on the struct
<a name="Host"></a>
## type [Host](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L49-L66>)
Host Struct for ansible host Generated from https://zhwt.github.io/yaml-to-go/
```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"`
}
```
<a name="ReadHost"></a>
### func [ReadHost](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L266>)
```go
func ReadHost(filename string) (*Host, error)
```
ReadHost Reads host file and adds
<a name="Plugin"></a>
## type [Plugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L31-L37>)
Plugin Information about the plugins available
```go
type Plugin struct {
FolderName string
PluginDescription string
Execute []*ExecuteIP
NumOfPorts int
// contains filtered or unexported fields
}
```
<a name="RunPlugin"></a>
### func [RunPlugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L131>)
```go
func RunPlugin(pluginName string, IPAddresses []*ExecuteIP) (*Plugin, error)
```
RunPlugin Executes plugins based on the plugin name provided
<a name="SearchPlugin"></a>
### func [SearchPlugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L114>)
```go
func SearchPlugin(pluginname string) (*Plugin, error)
```
SearchPlugin Detects plugin information based on the name provided on the parameter
<a name="Plugin.AutoSetPorts"></a>
### func \(\*Plugin\) [AutoSetPorts](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L383>)
```go
func (p *Plugin) AutoSetPorts(containerID string) error
```
AutoSetPorts Automatically maps free ports to site.yml file
<a name="Plugin.CopyToTmpPlugin"></a>
### func \(\*Plugin\) [CopyToTmpPlugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L366>)
```go
func (p *Plugin) CopyToTmpPlugin() error
```
CopyToTmpPlugin This function would ensure that we create a copy of the plugin in the tmp directory, and it would be executed from there. This due to the reason of automating port allocation when running plugins
<a name="Plugin.ExecutePlugin"></a>
### func \(\*Plugin\) [ExecutePlugin](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L174>)
```go
func (p *Plugin) ExecutePlugin() error
```
ExecutePlugin Function to execute plugins that are called
<a name="Plugin.NumPorts"></a>
### func \(\*Plugin\) [NumPorts](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L446>)
```go
func (p *Plugin) NumPorts() error
```
NumPorts Gets the Number the ports the plugin requires
<a name="Plugins"></a>
## type [Plugins](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L26-L28>)
Plugins Array of all plugins detected
```go
type Plugins struct {
PluginsDetected []*Plugin
}
```
<a name="DetectPlugins"></a>
### func [DetectPlugins](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/plugin/plugin.go#L69>)
```go
func DetectPlugins() (*Plugins, error)
```
DetectPlugins Detects all the plugins available
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

View File

@@ -0,0 +1 @@
cp -r plugin/TestAnsible/ plugin/deploy/

64
plugin/packageManager.go Normal file
View File

@@ -0,0 +1,64 @@
package plugin
import (
"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(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
}
// DeletePlugin The following function deletes a plugin based on
// the plugin name provided.
func DeletePlugin(pluginname string) error {
config, err := config.ConfigInit(nil, nil)
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
}
return nil
}

464
plugin/plugin.go Normal file
View File

@@ -0,0 +1,464 @@
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"
"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
}
// Plugin Information about the plugins available
type Plugin struct {
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
}
// 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"`
}
// DetectPlugins Detects all the plugins available
func DetectPlugins() (*Plugins, error) {
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)
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
}
// 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
}
}
}
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
}
// 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")
}
// 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
}
// 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")
}
// 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
}
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
}
// RunAnsible Executes based on credentials on the struct
func (e *ExecuteIP) RunAnsible(p *Plugin) error {
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"},
}
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"),
),
),
}
err := playbook.Run(context.TODO())
if err != nil {
return err
}
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"
// 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
}
c := &Host{}
err = yaml.Unmarshal(buf, c)
if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err)
}
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
}
// 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
}
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
}
}
return nil
}
// CopyToTmpPlugin This function would ensure that we create a copy of the
// plugin in the tmp directory, and it would be executed
// 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
}
// Set the plugin execution to the tmp location
p.path = "/tmp"
p.FolderName = id.String() + "_" + p.FolderName
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)
}
}
// 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
}
// 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
}
// 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 unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &p)
return nil
}

257
plugin/plugin_test.go Normal file
View File

@@ -0,0 +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"
// )
//
// // Test if the dummy plugin added is detected
// func TestDetectPlugins(t *testing.T) {
// _, 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
//
// // 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)
//
// // 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)
//
// _, 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()
// }
//
// 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
//
// // 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"
//
// 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()
// }
//
// // 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()
// }
//
// // 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()
// }
// }
//
// // 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()
// }
//
// // 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()
// }
//
// // 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()
// }
//
// // -------------------------- Main test cases -------------------------------
//
// // 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()
// }
//
// // ----------------------------------------------------------------------------
//
// // 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()
// }
//
// // 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()
// }
//
// // 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 {
//
// }
// }
//
// // 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)
// }
// }

BIN
server/docker/.DS_Store vendored Normal file

Binary file not shown.

12
server/docker/Makefile Normal file
View File

@@ -0,0 +1,12 @@
SHELL := /bin/bash
.PHONY: set_virtualenv,install_docker_requirements,dockerproc
set_virtualenv:
virtualenv env
install_docker_requirements:
source env/bin/activate && pip install -r requirements.txt
dockerproc:
ADMIN_USER=admin ADMIN_PASSWORD=admin docker-compose -f dockprom/docker-compose.yml up -d

6
server/docker/README Normal file
View File

@@ -0,0 +1,6 @@
Docker Module P2P-rendering-computation
========================================
This module is incharge to spin up docker contaianers , create
SSH server and VNC server. This module is implemented using
python.

508
server/docker/docker.go Normal file
View File

@@ -0,0 +1,508 @@
package docker
import (
"bufio"
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/docker/docker/client"
"github.com/google/uuid"
"github.com/lithammer/shortuuid"
"github.com/otiai10/copy"
"github.com/phayes/freeport"
"io"
"io/ioutil"
"os"
"os/exec"
"text/template"
)
type DockerVM struct {
SSHUsername string `json:"SSHUsername"`
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 {
DockerContainer []DockerContainer `json:"DockerContainer"`
}
type DockerContainer struct {
ContainerName string `json:"DockerContainerName"`
ContainerDescription string `json:"ContainerDescription"`
}
type Ports struct {
PortSet []Port `json:"Port"`
}
type Port struct {
PortName string `json:"PortName"`
InternalPort int `json:"InternalPort"`
Type string `json:"Type"`
ExternalPort int `json:"ExternalPort"`
IsUsed bool `json:"IsUsed"`
Description string `json:"Description"`
}
type ErrorLine struct {
Error string `json:"error"`
ErrorDetail ErrorDetail `json:"errorDetail"`
}
type ErrorDetail struct {
Message string `json:"message"`
}
var dockerRegistryUserID = ""
// BuildRunContainer Function is incharge to invoke building and running contianer and also allocating external
// ports
func BuildRunContainer(NumPorts int, GPU string, ContainerName string, 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 = "root"
//RespDocker.BaseImage = "ubuntu:20.04"
//RespDocker.VNCPassword = "vncpassword"
//Default parameters
RespDocker.TagName = "p2p-ubuntu"
// Get Path from config
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
RespDocker.ImagePath = config.DefaultDockerFile
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
if ContainerName != "" && ContainerName != "docker-ubuntu-sshd" {
Containers, err := ViewAllContainers()
if err != nil {
return nil, err
}
for _, dockerContainer := range Containers.DockerContainer {
if dockerContainer.ContainerName == ContainerName {
RespDocker.ImagePath = config.DockerContainers + ContainerName + "/"
RespDocker.TagName = ContainerName
break
}
}
if RespDocker.ImagePath == config.DefaultDockerFile {
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
}
}
// 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
}
// Number of perts we want to open + number of ports required inside the
// docker container
count := NumPorts + len(PortsInformation.PortSet)
// Creates number of ports
OpenPorts, err := freeport.GetFreePorts(count)
if err != nil {
return nil, err
}
// Allocate external ports to ports available in the ports.json file
for i := range PortsInformation.PortSet {
// Setting external ports
PortsInformation.PortSet[i].ExternalPort = OpenPorts[i]
PortsInformation.PortSet[i].IsUsed = true
}
//Length of Ports allocated from thr port file
portFileLength := len(PortsInformation.PortSet)
// Allocate New ports the user wants to generate
for i := 0; i < NumPorts; i++ {
var TempPort Port
TempPort.PortName = "AutoGen Port"
TempPort.Type = "tcp"
TempPort.InternalPort = OpenPorts[portFileLength+i]
TempPort.ExternalPort = OpenPorts[portFileLength+i]
TempPort.Description = "Auto generated TCP port"
TempPort.IsUsed = false
//Append temp port to port information
PortsInformation.PortSet = append(PortsInformation.PortSet, TempPort)
}
// Setting ports to the docker VM struct
RespDocker.Ports = *PortsInformation
// Gets docker information from env variables
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil, err
}
// Builds docker image
err = RespDocker.imageBuild(cli)
if err != nil {
return nil, err
}
// Runs docker contianer
err = RespDocker.runContainer(cli)
if err != nil {
return nil, err
}
return RespDocker, nil
}
// Builds docker image (TODO: relative path for Dockerfile deploy)
func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
//ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
//defer cancel()
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
}
//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
}
// Starts container and assigns port numbers
// Sample Docker run Command
// docker run -d=true --name=Test123 --restart=always --gpus all
// -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)
// The first mode runs using the Docker Api. As the API supports using
// CPU and uses a shell script for GPU call because till this point of
// implementation docker api does not support the flag "--gpu all"
//if d.GPU != "true" {
// //Exposed ports for docker config file
// var ExposedPort nat.PortSet
//
// ExposedPort = nat.PortSet{
// "22/tcp": struct{}{},
// //"6901/tcp": struct{}{},
// }
//
// // Port forwarding for VNC and SSH ports
// PortForwarding := nat.PortMap{
// //"22/tcp": []nat.PortBinding{
// // {
// // HostIP: "0.0.0.0",
// // HostPort: fmt.Sprint(d.SSHPort),
// // },
// //},
// //"6901/tcp": []nat.PortBinding{
// // {
// // HostIP: "0.0.0.0",
// // HostPort: fmt.Sprint(d.VNCPort),
// // },
// //},
// }
//
// for i := range d.Ports.PortSet {
// // Parameters "tcp or udp", external port
// Port, err := nat.NewPort(d.Ports.PortSet[i].Type, fmt.Sprint(d.Ports.PortSet[i].InternalPort))
// if err != nil {
// return err
// }
//
// // Exposed Ports
// ExposedPort[Port] = struct{}{}
//
// PortForwarding[Port] = []nat.PortBinding{
// {
// HostIP: "0.0.0.0",
// HostPort: fmt.Sprint(d.Ports.PortSet[i].ExternalPort),
// },
// }
// }
//
// config := &container.Config{
// Image: d.TagName,
// Entrypoint: []string{"/start"},
// Volumes: map[string]struct{}{"/opt/data:/data": {}},
// ExposedPorts: ExposedPort,
// }
// hostConfig := &container.HostConfig{
// PortBindings: PortForwarding,
// }
//
// res, err := dockerClient.ContainerCreate(ctx, config, hostConfig,
// nil, nil, "")
//
// // Set response ID
// d.ID = res.ID
//
// if err != nil {
// return err
// }
//
// err = dockerClient.ContainerStart(ctx, res.ID, types.ContainerStartOptions{})
//
// if err != nil {
// return err
// }
//} else {
// Generate Random ID
id := shortuuid.New()
d.ID = id
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
}
// StopAndRemoveContainer
// Stop and remove a container
// Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6)
func StopAndRemoveContainer(containername string) error {
//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
//}
// 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
}
// remove docker container
var remove bytes.Buffer
remove.WriteString("docker remove " + containername)
cmdStr = remove.String()
_, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
return err
}
return nil
}
// ViewAllContainers returns all containers runnable and which can be built
func ViewAllContainers() (*DockerContainers, error) {
// Traverse the deploy path as per given in the config file
config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
folders, err := ioutil.ReadDir(config.DockerContainers)
if err != nil {
return nil, err
}
//Declare variable DockerContainers of type struct
var Containers *DockerContainers = new(DockerContainers)
for _, f := range folders {
if f.IsDir() {
//Declare variable DockerContainer of type struct
var Container DockerContainer
// Setting container name to deploy name
Container.ContainerName = f.Name()
// Getting Description from file description.txt
Description, err := ioutil.ReadFile(config.DockerContainers + "/" + Container.ContainerName + "/description.txt")
// if we os.Open returns an error then handle it
if err != nil {
return nil, err
}
// Get Description from description.txt
Container.ContainerDescription = string(Description)
Containers.DockerContainer = append(Containers.DockerContainer, Container)
}
}
return Containers, nil
}
func print(rd io.Reader) error {
var lastLine string
scanner := bufio.NewScanner(rd)
for scanner.Scan() {
lastLine = scanner.Text()
}
errLine := &ErrorLine{}
json.Unmarshal([]byte(lastLine), errLine)
if errLine.Error != "" {
return errors.New(errLine.Error)
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func OpenPortsFile(filename string) (*Ports, error) {
buf, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
c := &Ports{}
err = json.Unmarshal(buf, c)
if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err)
}
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

@@ -0,0 +1,42 @@
package docker
// import (
// "testing"
// )
//
// func TestDockerUbuntuSSHDProvided(t *testing.T) {
// // Testing by providing default container name
// _,err := BuildRunContainer(2,"false","docker-ubuntu-sshd")
//
// if err != nil {
// t.Error(err)
// }
//
// }
//
// func TestDockerDefaultContainer(t *testing.T) {
// // Testing by providing without providing default container name
// _,err := BuildRunContainer(2,"false","")
//
// if err != nil {
// t.Error(err)
// }
// }
//
// func TestContainerHorovod(t *testing.T) {
// // Testing by providing the horovod cpu image
// _,err := BuildRunContainer(2,"false","cpuhorovod")
//
// if err != nil {
// t.Error(err)
// }
// }
//
// func TestViewAllContainers(t *testing.T) {
// _,err := ViewAllContainers()
//
// if err != nil {
// t.Error(err)
// }
//
// }

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Stefan Prodan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,353 @@
dockprom
========
A monitoring solution for Docker hosts and containers with [Prometheus](https://prometheus.io/), [Grafana](http://grafana.org/), [cAdvisor](https://github.com/google/cadvisor),
[NodeExporter](https://github.com/prometheus/node_exporter) and alerting with [AlertManager](https://github.com/prometheus/alertmanager).
***If you're looking for the Docker Swarm version please go to [stefanprodan/swarmprom](https://github.com/stefanprodan/swarmprom)***
## Install
Clone this repository on your Docker host, cd into dockprom directory and run compose up:
```bash
git clone https://github.com/stefanprodan/dockprom
cd dockprom
ADMIN_USER=admin ADMIN_PASSWORD=admin docker-compose up -d
```
Prerequisites:
* Docker Engine >= 1.13
* Docker Compose >= 1.11
Containers:
* Prometheus (metrics database) `http://<host-ip>:9090`
* Prometheus-Pushgateway (push acceptor for ephemeral and batch jobs) `http://<host-ip>:9091`
* AlertManager (alerts management) `http://<host-ip>:9093`
* Grafana (visualize metrics) `http://<host-ip>:3000`
* NodeExporter (host metrics collector)
* cAdvisor (containers metrics collector)
* Caddy (reverse proxy and basic auth provider for prometheus and alertmanager)
## Setup Grafana
Navigate to `http://<host-ip>:3000` and login with user ***admin*** password ***admin***. You can change the credentials in the compose file or by supplying the `ADMIN_USER` and `ADMIN_PASSWORD` environment variables on compose up. The config file can be added directly in grafana part like this
```
grafana:
image: grafana/grafana:7.2.0
env_file:
- config
```
and the config file format should have this content
```
GF_SECURITY_ADMIN_USER=admin
GF_SECURITY_ADMIN_PASSWORD=changeme
GF_USERS_ALLOW_SIGN_UP=false
```
If you want to change the password, you have to remove this entry, otherwise the change will not take effect
```
- grafana_data:/var/lib/grafana
```
Grafana is preconfigured with dashboards and Prometheus as the default data source:
* Name: Prometheus
* Type: Prometheus
* Url: http://prometheus:9090
* Access: proxy
***Docker Host Dashboard***
![Host](https://raw.githubusercontent.com/stefanprodan/dockprom/master/screens/Grafana_Docker_Host.png)
The Docker Host Dashboard shows key metrics for monitoring the resource usage of your server:
* Server uptime, CPU idle percent, number of CPU cores, available memory, swap and storage
* System load average graph, running and blocked by IO processes graph, interrupts graph
* CPU usage graph by mode (guest, idle, iowait, irq, nice, softirq, steal, system, user)
* Memory usage graph by distribution (used, free, buffers, cached)
* IO usage graph (read Bps, read Bps and IO time)
* Network usage graph by device (inbound Bps, Outbound Bps)
* Swap usage and activity graphs
For storage and particularly Free Storage graph, you have to specify the fstype in grafana graph request.
You can find it in `grafana/dashboards/docker_host.json`, at line 480 :
"expr": "sum(node_filesystem_free_bytes{fstype=\"btrfs\"})",
I work on BTRFS, so i need to change `aufs` to `btrfs`.
You can find right value for your system in Prometheus `http://<host-ip>:9090` launching this request :
node_filesystem_free_bytes
***Docker Containers Dashboard***
![Containers](https://raw.githubusercontent.com/stefanprodan/dockprom/master/screens/Grafana_Docker_Containers.png)
The Docker Containers Dashboard shows key metrics for monitoring running containers:
* Total containers CPU load, memory and storage usage
* Running containers graph, system load graph, IO usage graph
* Container CPU usage graph
* Container memory usage graph
* Container cached memory usage graph
* Container network inbound usage graph
* Container network outbound usage graph
> [!NOTE]
> This dashboard doesn't show the containers that are part of the monitoring stack.
***Monitor Services Dashboard***
![Monitor Services](https://raw.githubusercontent.com/stefanprodan/dockprom/master/screens/Grafana_Prometheus.png)
The Monitor Services Dashboard shows key metrics for monitoring the containers that make up the monitoring stack:
* Prometheus container uptime, monitoring stack total memory usage, Prometheus local storage memory chunks and series
* Container CPU usage graph
* Container memory usage graph
* Prometheus chunks to persist and persistence urgency graphs
* Prometheus chunks ops and checkpoint duration graphs
* Prometheus samples ingested rate, target scrapes and scrape duration graphs
* Prometheus HTTP requests graph
* Prometheus alerts graph
## Define alerts
Three alert groups have been setup within the [alert.rules](https://github.com/stefanprodan/dockprom/blob/master/prometheus/alert.rules) configuration file:
* Monitoring services alerts [targets](https://github.com/stefanprodan/dockprom/blob/master/prometheus/alert.rules#L2-L11)
* Docker Host alerts [host](https://github.com/stefanprodan/dockprom/blob/master/prometheus/alert.rules#L13-L40)
* Docker Containers alerts [containers](https://github.com/stefanprodan/dockprom/blob/master/prometheus/alert.rules#L42-L69)
You can modify the alert rules and reload them by making a HTTP POST call to Prometheus:
```
curl -X POST http://admin:admin@<host-ip>:9090/-/reload
```
***Monitoring services alerts***
Trigger an alert if any of the monitoring targets (node-exporter and cAdvisor) are down for more than 30 seconds:
```yaml
- alert: monitor_service_down
expr: up == 0
for: 30s
labels:
severity: critical
annotations:
summary: "Monitor service non-operational"
description: "Service {{ $labels.instance }} is down."
```
***Docker Host alerts***
Trigger an alert if the Docker host CPU is under high load for more than 30 seconds:
```yaml
- alert: high_cpu_load
expr: node_load1 > 1.5
for: 30s
labels:
severity: warning
annotations:
summary: "Server under high load"
description: "Docker host is under high load, the avg load 1m is at {{ $value}}. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}."
```
Modify the load threshold based on your CPU cores.
Trigger an alert if the Docker host memory is almost full:
```yaml
- alert: high_memory_load
expr: (sum(node_memory_MemTotal_bytes) - sum(node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes) ) / sum(node_memory_MemTotal_bytes) * 100 > 85
for: 30s
labels:
severity: warning
annotations:
summary: "Server memory is almost full"
description: "Docker host memory usage is {{ humanize $value}}%. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}."
```
Trigger an alert if the Docker host storage is almost full:
```yaml
- alert: high_storage_load
expr: (node_filesystem_size_bytes{fstype="aufs"} - node_filesystem_free_bytes{fstype="aufs"}) / node_filesystem_size_bytes{fstype="aufs"} * 100 > 85
for: 30s
labels:
severity: warning
annotations:
summary: "Server storage is almost full"
description: "Docker host storage usage is {{ humanize $value}}%. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}."
```
***Docker Containers alerts***
Trigger an alert if a container is down for more than 30 seconds:
```yaml
- alert: jenkins_down
expr: absent(container_memory_usage_bytes{name="jenkins"})
for: 30s
labels:
severity: critical
annotations:
summary: "Jenkins down"
description: "Jenkins container is down for more than 30 seconds."
```
Trigger an alert if a container is using more than 10% of total CPU cores for more than 30 seconds:
```yaml
- alert: jenkins_high_cpu
expr: sum(rate(container_cpu_usage_seconds_total{name="jenkins"}[1m])) / count(node_cpu_seconds_total{mode="system"}) * 100 > 10
for: 30s
labels:
severity: warning
annotations:
summary: "Jenkins high CPU usage"
description: "Jenkins CPU usage is {{ humanize $value}}%."
```
Trigger an alert if a container is using more than 1.2GB of RAM for more than 30 seconds:
```yaml
- alert: jenkins_high_memory
expr: sum(container_memory_usage_bytes{name="jenkins"}) > 1200000000
for: 30s
labels:
severity: warning
annotations:
summary: "Jenkins high memory usage"
description: "Jenkins memory consumption is at {{ humanize $value}}."
```
## Setup alerting
The AlertManager service is responsible for handling alerts sent by Prometheus server.
AlertManager can send notifications via email, Pushover, Slack, HipChat or any other system that exposes a webhook interface.
A complete list of integrations can be found [here](https://prometheus.io/docs/alerting/configuration).
You can view and silence notifications by accessing `http://<host-ip>:9093`.
The notification receivers can be configured in [alertmanager/config.yml](https://github.com/stefanprodan/dockprom/blob/master/alertmanager/config.yml) file.
To receive alerts via Slack you need to make a custom integration by choose ***incoming web hooks*** in your Slack team app page.
You can find more details on setting up Slack integration [here](http://www.robustperception.io/using-slack-with-the-alertmanager/).
Copy the Slack Webhook URL into the ***api_url*** field and specify a Slack ***channel***.
```yaml
route:
receiver: 'slack'
receivers:
- name: 'slack'
slack_configs:
- send_resolved: true
text: "{{ .CommonAnnotations.description }}"
username: 'Prometheus'
channel: '#<channel>'
api_url: 'https://hooks.slack.com/services/<webhook-id>'
```
![Slack Notifications](https://raw.githubusercontent.com/stefanprodan/dockprom/master/screens/Slack_Notifications.png)
## Sending metrics to the Pushgateway
The [pushgateway](https://github.com/prometheus/pushgateway) is used to collect data from batch jobs or from services.
To push data, simply execute:
echo "some_metric 3.14" | curl --data-binary @- http://user:password@localhost:9091/metrics/job/some_job
Please replace the `user:password` part with your user and password set in the initial configuration (default: `admin:admin`).
## Updating Grafana to v5.2.2
[In Grafana versions >= 5.1 the id of the grafana user has been changed](http://docs.grafana.org/installation/docker/#migration-from-a-previous-version-of-the-docker-container-to-5-1-or-later). Unfortunately this means that files created prior to 5.1 wont have the correct permissions for later versions.
| Version | User | User ID |
|:-------:|:-------:|:-------:|
| < 5.1 | grafana | 104 |
| \>= 5.1 | grafana | 472 |
There are two possible solutions to this problem.
- Change ownership from 104 to 472
- Start the upgraded container as user 104
##### Specifying a user in docker-compose.yml
To change ownership of the files run your grafana container as root and modify the permissions.
First perform a `docker-compose down` then modify your docker-compose.yml to include the `user: root` option:
```
grafana:
image: grafana/grafana:5.2.2
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/datasources:/etc/grafana/datasources
- ./grafana/dashboards:/etc/grafana/dashboards
- ./grafana/setup.sh:/setup.sh
entrypoint: /setup.sh
user: root
environment:
- GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin}
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
- GF_USERS_ALLOW_SIGN_UP=false
restart: unless-stopped
expose:
- 3000
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
```
Perform a `docker-compose up -d` and then issue the following commands:
```
docker exec -it --user root grafana bash
# in the container you just started:
chown -R root:root /etc/grafana && \
chmod -R a+r /etc/grafana && \
chown -R grafana:grafana /var/lib/grafana && \
chown -R grafana:grafana /usr/share/grafana
```
To run the grafana container as `user: 104` change your `docker-compose.yml` like such:
```
grafana:
image: grafana/grafana:5.2.2
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/datasources:/etc/grafana/datasources
- ./grafana/dashboards:/etc/grafana/dashboards
- ./grafana/setup.sh:/setup.sh
entrypoint: /setup.sh
user: "104"
environment:
- GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin}
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
- GF_USERS_ALLOW_SIGN_UP=false
restart: unless-stopped
expose:
- 3000
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
```

View File

@@ -0,0 +1,11 @@
route:
receiver: 'slack'
receivers:
- name: 'slack'
slack_configs:
- send_resolved: true
text: "{{ .CommonAnnotations.description }}"
username: 'Prometheus'
channel: '#<channel-name>'
api_url: 'https://hooks.slack.com/services/<webhook-id>'

View File

@@ -0,0 +1,36 @@
:9090 {
proxy / prometheus:9090 {
transparent
}
errors stderr
tls off
}
:9093 {
proxy / alertmanager:9093 {
transparent
}
errors stderr
tls off
}
:9091 {
proxy / pushgateway:9091 {
transparent
}
errors stderr
tls off
}
:3000 {
proxy / grafana:3000 {
transparent
websocket
}
errors stderr
tls off
}

View File

@@ -0,0 +1,3 @@
GF_SECURITY_ADMIN_USER=admin
GF_SECURITY_ADMIN_PASSWORD=changeme
GF_USERS_ALLOW_SIGN_UP=false

View File

@@ -0,0 +1,36 @@
version: '2.1'
services:
nodeexporter:
image: prom/node-exporter:v1.0.1
container_name: nodeexporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
restart: unless-stopped
network_mode: host
labels:
org.label-schema.group: "monitoring"
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.38.7
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /cgroup:/cgroup:ro
restart: unless-stopped
network_mode: host
labels:
org.label-schema.group: "monitoring"

View File

@@ -0,0 +1,146 @@
version: '2.1'
networks:
monitor-net:
driver: bridge
volumes:
prometheus_data: {}
grafana_data: {}
services:
prometheus:
image: prom/prometheus:v2.24.1
container_name: prometheus
volumes:
- ./prometheus:/etc/prometheus
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
restart: unless-stopped
expose:
- 9090
ports:
- "9090:9090"
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
alertmanager:
image: prom/alertmanager:v0.21.0
container_name: alertmanager
volumes:
- ./alertmanager:/etc/alertmanager
command:
- '--config.file=/etc/alertmanager/config.yml'
- '--storage.path=/alertmanager'
restart: unless-stopped
expose:
- 9093
ports:
- "9093:9093"
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
nodeexporter:
image: prom/node-exporter:v1.0.1
container_name: nodeexporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
restart: unless-stopped
expose:
- 9100
ports:
- "9100:9100"
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.38.7
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
#- /cgroup:/cgroup:ro #doesn't work on MacOS only for Linux
restart: unless-stopped
expose:
- 8080
ports:
- "8080:8080"
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
grafana:
image: grafana/grafana:7.3.7
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
environment:
- GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin}
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
- GF_USERS_ALLOW_SIGN_UP=false
restart: unless-stopped
expose:
- 3000
ports:
- "3000:3000"
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
pushgateway:
image: prom/pushgateway:v1.4.0
container_name: pushgateway
restart: unless-stopped
expose:
- 9091
ports:
- "9091:9091"
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"
caddy:
image: caddy:2.3.0-alpine
container_name: caddy
ports:
- "3000:3000"
- "9090:9090"
- "9093:9093"
- "9091:9091"
volumes:
- ./caddy:/etc/caddy
environment:
- ADMIN_USER=${ADMIN_USER:-admin}
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
restart: unless-stopped
networks:
- monitor-net
labels:
org.label-schema.group: "monitoring"

View File

@@ -0,0 +1,12 @@
apiVersion: 1
providers:
- name: 'Prometheus'
orgId: 1
folder: ''
type: file
disableDeletion: false
editable: true
allowUiUpdates: true
options:
path: /etc/grafana/provisioning/dashboards

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,398 @@
{
"id": null,
"title": "Nginx",
"description": "Nginx exporter metrics",
"tags": [
"nginx"
],
"style": "dark",
"timezone": "browser",
"editable": true,
"hideControls": false,
"sharedCrosshair": true,
"rows": [
{
"collapse": false,
"editable": true,
"height": "250px",
"panels": [
{
"aliasColors": {},
"bars": false,
"datasource": "Prometheus",
"decimals": 2,
"editable": true,
"error": false,
"fill": 1,
"grid": {
"threshold1": null,
"threshold1Color": "rgba(216, 200, 27, 0.27)",
"threshold2": null,
"threshold2Color": "rgba(234, 112, 112, 0.22)"
},
"id": 3,
"isNew": true,
"legend": {
"alignAsTable": true,
"avg": true,
"current": true,
"max": true,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"span": 12,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(irate(nginx_connections_processed_total{stage=\"any\"}[5m])) by (stage)",
"hide": false,
"interval": "",
"intervalFactor": 10,
"legendFormat": "requests",
"metric": "",
"refId": "B",
"step": 10
}
],
"timeFrom": null,
"timeShift": null,
"title": "Requests/sec",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"show": true
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": 0,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
},
{
"aliasColors": {},
"bars": false,
"datasource": "Prometheus",
"decimals": 2,
"editable": true,
"error": false,
"fill": 1,
"grid": {
"threshold1": null,
"threshold1Color": "rgba(216, 200, 27, 0.27)",
"threshold2": null,
"threshold2Color": "rgba(234, 112, 112, 0.22)"
},
"id": 2,
"isNew": true,
"legend": {
"alignAsTable": true,
"avg": true,
"current": true,
"max": true,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"span": 12,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(nginx_connections_current) by (state)",
"interval": "",
"intervalFactor": 2,
"legendFormat": "{{state}}",
"metric": "",
"refId": "A",
"step": 2
}
],
"timeFrom": null,
"timeShift": null,
"title": "Connections",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"show": true
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": 0,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
},
{
"aliasColors": {},
"bars": false,
"datasource": "Prometheus",
"decimals": 2,
"editable": true,
"error": false,
"fill": 1,
"grid": {
"threshold1": null,
"threshold1Color": "rgba(216, 200, 27, 0.27)",
"threshold2": null,
"threshold2Color": "rgba(234, 112, 112, 0.22)"
},
"id": 1,
"isNew": true,
"legend": {
"alignAsTable": true,
"avg": true,
"current": true,
"max": true,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"span": 12,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(irate(nginx_connections_processed_total{stage!=\"any\"}[5m])) by (stage)",
"hide": false,
"interval": "",
"intervalFactor": 10,
"legendFormat": "{{stage}}",
"metric": "",
"refId": "B",
"step": 10
}
],
"timeFrom": null,
"timeShift": null,
"title": "Connections rate",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"show": true
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": 0,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
}
],
"title": "Nginx exporter metrics"
},
{
"collapse": false,
"editable": true,
"height": "250px",
"panels": [
{
"aliasColors": {},
"bars": false,
"datasource": null,
"editable": true,
"error": false,
"fill": 1,
"grid": {
"threshold1": null,
"threshold1Color": "rgba(216, 200, 27, 0.27)",
"threshold2": null,
"threshold2Color": "rgba(234, 112, 112, 0.22)"
},
"id": 4,
"isNew": true,
"legend": {
"alignAsTable": true,
"avg": true,
"current": true,
"max": true,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"span": 12,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(container_cpu_usage_seconds_total{name=~\"nginx\"}[5m])) / count(node_cpu_seconds_total{mode=\"system\"}) * 100",
"intervalFactor": 2,
"legendFormat": "nginx",
"refId": "A",
"step": 2
}
],
"timeFrom": null,
"timeShift": null,
"title": "CPU usage",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"show": true
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
}
],
"title": "Nginx container metrics"
}
],
"time": {
"from": "now-15m",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"templating": {
"list": []
},
"annotations": {
"list": []
},
"refresh": "10s",
"schemaVersion": 12,
"version": 9,
"links": [],
"gnetId": null
}

View File

@@ -0,0 +1,11 @@
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
basicAuth: false
isDefault: true
editable: true

View File

@@ -0,0 +1,22 @@
# Prometheus on EC2 & ECS:
Some helpers for anyone configuring Prometheus on ECS and AWS EC2.
To get started on AWS ECS and EC2:
*For EC2/ECS nodes*:
- Import the ecs task definition and add cadvisor and node-exporter service/task definition and run them on each host you want to be monitored
- Any hosts which have "Monitoring: On" tag will be automatically added in the targets
- Expose ports 9100 and 9191 to your Prometheus host
*For Prometheus host*:
- 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
### TODO
- [ ] Add alerting rules based on ECS

View File

@@ -0,0 +1,78 @@
{
"family": "cadvisor",
"containerDefinitions": [
{
"name": "cadvisor",
"image": "google/cadvisor",
"cpu": 10,
"memory": 300,
"portMappings": [
{
"containerPort": 9191,
"hostPort": 9191
}
],
"essential": true,
"privileged": true,
"mountPoints": [
{
"sourceVolume": "root",
"containerPath": "/rootfs",
"readOnly": true
},
{
"sourceVolume": "var_run",
"containerPath": "/var/run",
"readOnly": false
},
{
"sourceVolume": "sys",
"containerPath": "/sys",
"readOnly": true
},
{
"sourceVolume": "var_lib_docker",
"containerPath": "/var/lib/docker",
"readOnly": true
},
{
"sourceVolume": "cgroup",
"containerPath": "/cgroup",
"readOnly": true
}
]
}
],
"volumes": [
{
"name": "root",
"host": {
"sourcePath": "/"
}
},
{
"name": "var_run",
"host": {
"sourcePath": "/var/run"
}
},
{
"name": "sys",
"host": {
"sourcePath": "/sys"
}
},
{
"name": "var_lib_docker",
"host": {
"sourcePath": "/var/lib/docker/"
}
},
{
"name": "cgroup",
"host": {
"sourcePath": "/cgroup"
}
}
]
}

View File

@@ -0,0 +1,22 @@
{
"family": "prometheus",
"containerDefinitions": [
{
"portMappings": [
{
"hostPort": 9100,
"containerPort": 9100,
"protocol": "tcp"
}
],
"essential": true,
"name": "node_exporter",
"image": "prom/node-exporter",
"cpu": 0,
"privileged": null,
"memoryReservation": 150
}
],
"volumes": [],
"networkMode": "host"
}

View File

@@ -0,0 +1,53 @@
global:
scrape_interval: 15s
evaluation_interval: 15s
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'docker-host-alpha'
# Load and evaluate rules in this file every 'evaluation_interval' seconds.
rule_files:
- "targets.rules"
- "hosts.rules"
- "containers.rules"
# A scrape configuration containing exactly one endpoint to scrape.
scrape_configs:
- job_name: 'nodeexporter'
scrape_interval: 5s
static_configs:
- targets: ['nodeexporter:9100']
- job_name: 'cadvisor'
scrape_interval: 5s
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'prometheus'
scrape_interval: 10s
static_configs:
- targets: ['localhost:9090']
# sample scrape configuration for AWS EC2
- job_name: 'nodeexporter'
ec2_sd_configs:
- region: us-east-1
port: 9100
relabel_configs:
# Only monitor instances which have a tag called Monitoring "Monitoring"
- source_labels: [__meta_ec2_tag_Monitoring]
regex: On
action: keep
- job_name: 'cadvisor'
ec2_sd_configs:
- region: us-east-1
port: 9010
relabel_configs:
# Only monitor instances which have a tag called Monitoring "Monitoring"
- source_labels: [__meta_ec2_tag_Monitoring]
regex: On
action: keep

View File

@@ -0,0 +1,70 @@
groups:
- name: targets
rules:
- alert: monitor_service_down
expr: up == 0
for: 30s
labels:
severity: critical
annotations:
summary: "Monitor service non-operational"
description: "Service {{ $labels.instance }} is down."
- name: host
rules:
- alert: high_cpu_load
expr: node_load1 > 1.5
for: 30s
labels:
severity: warning
annotations:
summary: "Server under high load"
description: "Docker host is under high load, the avg load 1m is at {{ $value}}. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}."
- alert: high_memory_load
expr: (sum(node_memory_MemTotal_bytes) - sum(node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes) ) / sum(node_memory_MemTotal_bytes) * 100 > 85
for: 30s
labels:
severity: warning
annotations:
summary: "Server memory is almost full"
description: "Docker host memory usage is {{ humanize $value}}%. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}."
- alert: high_storage_load
expr: (node_filesystem_size_bytes{fstype="aufs"} - node_filesystem_free_bytes{fstype="aufs"}) / node_filesystem_size_bytes{fstype="aufs"} * 100 > 85
for: 30s
labels:
severity: warning
annotations:
summary: "Server storage is almost full"
description: "Docker host storage usage is {{ humanize $value}}%. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}."
- name: containers
rules:
- alert: jenkins_down
expr: absent(container_memory_usage_bytes{name="jenkins"})
for: 30s
labels:
severity: critical
annotations:
summary: "Jenkins down"
description: "Jenkins container is down for more than 30 seconds."
- alert: jenkins_high_cpu
expr: sum(rate(container_cpu_usage_seconds_total{name="jenkins"}[1m])) / count(node_cpu_seconds_total{mode="system"}) * 100 > 10
for: 30s
labels:
severity: warning
annotations:
summary: "Jenkins high CPU usage"
description: "Jenkins CPU usage is {{ humanize $value}}%."
- alert: jenkins_high_memory
expr: sum(container_memory_usage_bytes{name="jenkins"}) > 1200000000
for: 30s
labels:
severity: warning
annotations:
summary: "Jenkins high memory usage"
description: "Jenkins memory consumption is at {{ humanize $value}}."

View File

@@ -0,0 +1,53 @@
global:
scrape_interval: 15s
evaluation_interval: 15s
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'docker-host-alpha'
# Load and evaluate rules in this file every 'evaluation_interval' seconds.
rule_files:
- "alert.rules"
# A scrape configuration containing exactly one endpoint to scrape.
scrape_configs:
- job_name: 'nodeexporter'
scrape_interval: 5s
static_configs:
- targets: ['nodeexporter:9100']
- job_name: 'cadvisor'
scrape_interval: 5s
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'prometheus'
scrape_interval: 10s
static_configs:
- targets: ['localhost:9090']
- job_name: 'pushgateway'
scrape_interval: 10s
honor_labels: true
static_configs:
- targets: ['pushgateway:9091']
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets:
- 'alertmanager:9093'
# - job_name: 'nginx'
# scrape_interval: 10s
# static_configs:
# - targets: ['nginxexporter:9113']
# - job_name: 'aspnetcore'
# scrape_interval: 10s
# static_configs:
# - targets: ['eventlog-proxy:5000', 'eventlog:5000']

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

174
server/docker/docs.md Normal file
View File

@@ -0,0 +1,174 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# docker
```go
import "github.com/Akilan1999/p2p-rendering-computation/server/docker"
```
## Index
- [func StopAndRemoveContainer\(containername string\) error](<#StopAndRemoveContainer>)
- [type DockerContainer](<#DockerContainer>)
- [type DockerContainers](<#DockerContainers>)
- [func ViewAllContainers\(\) \(\*DockerContainers, error\)](<#ViewAllContainers>)
- [type DockerVM](<#DockerVM>)
- [func BuildRunContainer\(NumPorts int, GPU string, ContainerName string, baseImage string, publicKey string\) \(\*DockerVM, error\)](<#BuildRunContainer>)
- [func \(d \*DockerVM\) CopyToTmpContainer\(\) error](<#DockerVM.CopyToTmpContainer>)
- [func \(d \*DockerVM\) TemplateDockerContainer\(\) error](<#DockerVM.TemplateDockerContainer>)
- [type ErrorDetail](<#ErrorDetail>)
- [type ErrorLine](<#ErrorLine>)
- [type Port](<#Port>)
- [type Ports](<#Ports>)
- [func OpenPortsFile\(filename string\) \(\*Ports, error\)](<#OpenPortsFile>)
<a name="StopAndRemoveContainer"></a>
## func [StopAndRemoveContainer](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L340>)
```go
func StopAndRemoveContainer(containername string) error
```
StopAndRemoveContainer Stop and remove a container Reference \(https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6\)
<a name="DockerContainer"></a>
## type [DockerContainer](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L40-L43>)
```go
type DockerContainer struct {
ContainerName string `json:"DockerContainerName"`
ContainerDescription string `json:"ContainerDescription"`
}
```
<a name="DockerContainers"></a>
## type [DockerContainers](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L36-L38>)
```go
type DockerContainers struct {
DockerContainer []DockerContainer `json:"DockerContainer"`
}
```
<a name="ViewAllContainers"></a>
### func [ViewAllContainers](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L387>)
```go
func ViewAllContainers() (*DockerContainers, error)
```
ViewAllContainers returns all containers runnable and which can be built
<a name="DockerVM"></a>
## type [DockerVM](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L22-L34>)
```go
type DockerVM struct {
SSHUsername string `json:"SSHUsername"`
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"`
}
```
<a name="BuildRunContainer"></a>
### func [BuildRunContainer](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L70>)
```go
func BuildRunContainer(NumPorts int, GPU string, ContainerName string, baseImage string, publicKey string) (*DockerVM, error)
```
BuildRunContainer Function is incharge to invoke building and running contianer and also allocating external ports
<a name="DockerVM.CopyToTmpContainer"></a>
### func \(\*DockerVM\) [CopyToTmpContainer](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L493>)
```go
func (d *DockerVM) CopyToTmpContainer() error
```
CopyToTmpContainer Creates a copy of the docker folder
<a name="DockerVM.TemplateDockerContainer"></a>
### func \(\*DockerVM\) [TemplateDockerContainer](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L464>)
```go
func (d *DockerVM) TemplateDockerContainer() error
```
TemplateDockerContainer This function templates the docker container with the base docker image to use
<a name="ErrorDetail"></a>
## type [ErrorDetail](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L62-L64>)
```go
type ErrorDetail struct {
Message string `json:"message"`
}
```
<a name="ErrorLine"></a>
## type [ErrorLine](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L57-L60>)
```go
type ErrorLine struct {
Error string `json:"error"`
ErrorDetail ErrorDetail `json:"errorDetail"`
}
```
<a name="Port"></a>
## type [Port](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L48-L55>)
```go
type Port struct {
PortName string `json:"PortName"`
InternalPort int `json:"InternalPort"`
Type string `json:"Type"`
ExternalPort int `json:"ExternalPort"`
IsUsed bool `json:"IsUsed"`
Description string `json:"Description"`
}
```
<a name="Ports"></a>
## type [Ports](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L45-L47>)
```go
type Ports struct {
PortSet []Port `json:"Port"`
}
```
<a name="OpenPortsFile"></a>
### func [OpenPortsFile](<https://github.com/Akilan1999/p2p-rendering-computation/blob/master/server/docker/docker.go#L447>)
```go
func OpenPortsFile(filename string) (*Ports, error)
```
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

View File

@@ -0,0 +1,4 @@
docker kill $(docker ps -q)\
docker rm $(docker ps -a -q)
docker rmi $(docker images -q) --force
docker system prune --all

View File

@@ -1,6 +1,7 @@
package server
import (
b64 "encoding/base64"
"encoding/json"
"errors"
"fmt"
@@ -8,6 +9,7 @@ import (
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
@@ -118,65 +120,65 @@ func Server() (*gin.Engine, error) {
})
// Starts docker container in server
//r.GET("/startcontainer", func(c *gin.Context) {
// // Get Number of ports to open and whether to use GPU or not
// Ports := c.DefaultQuery("ports", "0")
// GPU := c.DefaultQuery("GPU", "false")
// ContainerName := c.DefaultQuery("ContainerName", "")
// BaseImage := c.DefaultQuery("BaseImage", "")
// 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, BaseImage, string(PublicKeyDecoded[:]))
//
// if err != nil {
// c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
// }
//
// // Ensures that FRP is triggered only if a proxy address is provided
// if ProxyIpAddr.Ipv4 != "" && c.Request.Host != "localhost:"+config.ServerPort && c.Request.Host != "0.0.0.0:"+config.ServerPort {
// resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
// if err != nil {
// c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
// }
// }
//
// c.JSON(http.StatusOK, resp)
//})
r.GET("/startcontainer", func(c *gin.Context) {
// Get Number of ports to open and whether to use GPU or not
Ports := c.DefaultQuery("ports", "0")
GPU := c.DefaultQuery("GPU", "false")
ContainerName := c.DefaultQuery("ContainerName", "")
BaseImage := c.DefaultQuery("BaseImage", "")
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, BaseImage, string(PublicKeyDecoded[:]))
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
// Ensures that FRP is triggered only if a proxy address is provided
if ProxyIpAddr.Ipv4 != "" && c.Request.Host != "localhost:"+config.ServerPort && c.Request.Host != "0.0.0.0:"+config.ServerPort {
resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
}
c.JSON(http.StatusOK, resp)
})
//Remove container
//r.GET("/RemoveContainer", func(c *gin.Context) {
// ID := c.DefaultQuery("id", "0")
// if err := docker.StopAndRemoveContainer(ID); err != nil {
// c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
// }
// c.String(http.StatusOK, "success")
//})
//
////Show images available
//r.GET("/ShowImages", func(c *gin.Context) {
// resp, err := docker.ViewAllContainers()
// if err != nil {
// c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
// }
// c.JSON(http.StatusOK, resp)
//})
r.GET("/RemoveContainer", func(c *gin.Context) {
ID := c.DefaultQuery("id", "0")
if err := docker.StopAndRemoveContainer(ID); err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.String(http.StatusOK, "success")
})
//Show images available
r.GET("/ShowImages", func(c *gin.Context) {
resp, err := docker.ViewAllContainers()
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.JSON(http.StatusOK, resp)
})
// Request for port no from Server with address
r.GET("/FRPPort", func(c *gin.Context) {
@@ -310,6 +312,7 @@ func Server() (*gin.Engine, error) {
if err != nil {
fmt.Println(err)
}
ProxyIpAddr.ServerPort = config.ServerPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = false

BIN
wasm/p2prc.wasm Executable file

Binary file not shown.

View File

@@ -1,156 +0,0 @@
package main
import (
"encoding/json"
"errors"
"time"
"syscall/js"
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
func main() {
// Register functions
js.Global().Set("getSpecs", js.FuncOf(getSpecs))
js.Global().Set("initConfig", js.FuncOf(initConfig))
js.Global().Set("viewIPTable", js.FuncOf(viewIPTable))
js.Global().Set("updateIPTable", js.FuncOf(updateIPTable))
js.Global().Set("escapeFirewall", js.FuncOf(escapeFirewall))
js.Global().Set("mapPort", js.FuncOf(mapPort))
js.Global().Set("customInformation", js.FuncOf(customInformation))
js.Global().Set("addRootNode", js.FuncOf(addRootNode))
js.Global().Set("startServer", js.FuncOf(startServer))
// Prevent Go program from exiting
select {}
}
// ------------------------------------- Helpers ----------------------------------------
func convertToJSValue(value interface{}) js.Value {
jsonBytes, err := json.Marshal(value)
if err != nil {
return js.ValueOf(map[string]interface{}{"error": err.Error()})
}
return js.ValueOf(string(jsonBytes))
}
func returnError(err error) js.Value {
return js.ValueOf(map[string]interface{}{"error": err.Error()})
}
// ------------------------------------- WASM Functions ----------------------------------------
func getSpecs(this js.Value, args []js.Value) any {
if len(args) < 1 {
return returnError(jsError("Missing IP argument"))
}
specs, err := abstractions.GetSpecs(args[0].String())
if err != nil {
return returnError(err)
}
return convertToJSValue(specs)
}
func initConfig(this js.Value, args []js.Value) any {
if len(args) < 1 {
return returnError(jsError("Missing config argument"))
}
initData, err := abstractions.Init(args[0].String())
if err != nil {
return returnError(err)
}
return convertToJSValue(initData)
}
func viewIPTable(this js.Value, args []js.Value) any {
table, err := abstractions.ViewIPTable()
if err != nil {
return returnError(err)
}
return convertToJSValue(table)
}
func updateIPTable(this js.Value, args []js.Value) any {
err := abstractions.UpdateIPTable()
if err != nil {
return returnError(err)
}
return js.ValueOf("Success")
}
func escapeFirewall(this js.Value, args []js.Value) any {
if len(args) < 3 {
return returnError(jsError("Expected 3 arguments"))
}
host := args[0].String()
port := args[1].String()
internalPort := args[2].String()
serverPort, err := frp.GetFRPServerPort("http://" + host + ":" + port)
if err != nil {
return returnError(err)
}
time.Sleep(5 * time.Second)
exposedPort, err := frp.StartFRPClientForServer(host+":"+port, serverPort, internalPort, "")
if err != nil {
return returnError(err)
}
return js.ValueOf(exposedPort)
}
func mapPort(this js.Value, args []js.Value) any {
if len(args) < 3 {
return returnError(jsError("Expected 3 arguments"))
}
port := args[0].String()
domain := args[1].String()
server := args[2].String()
addr, err := abstractions.MapPort(port, domain, server)
if err != nil {
return returnError(err)
}
return js.ValueOf(addr.EntireAddress)
}
func customInformation(this js.Value, args []js.Value) any {
if len(args) < 1 {
return returnError(jsError("Missing custom information"))
}
err := abstractions.AddCustomInformation(args[0].String())
if err != nil {
return returnError(err)
}
return js.ValueOf("Success")
}
func addRootNode(this js.Value, args []js.Value) any {
if len(args) < 2 {
return returnError(jsError("Expected 2 arguments"))
}
err := abstractions.AddRootNode(args[0].String(), args[1].String())
if err != nil {
return returnError(err)
}
return js.ValueOf("Success")
}
func startServer(this js.Value, args []js.Value) any {
_, err := abstractions.Start()
if err != nil {
return returnError(err)
}
return js.ValueOf("Server started")
}
// ------------------------------------- Utility ----------------------------------------
func jsError(msg string) error {
return errors.New("WASM error: " + msg)
}