279 lines
10 KiB
Org Mode
279 lines
10 KiB
Org Mode
* Server Module Implementation
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: server-module-implementation
|
|
:END:
|
|
This section focuses on an in-depth understanding of the server module
|
|
implementation. To understand the architecture of the server module
|
|
refer. The server module can be split into various sections. Each
|
|
section will provide information on how a certain feature works.
|
|
|
|
The server module takes care of setting and removing the virtualization
|
|
environment (i.e containers) for accessing and doing the appropriate
|
|
computation. It also interacts with the peer to peer module to update
|
|
the IP table on the server side. The server module accesses information
|
|
regarding CPU and GPU specifications of the machine running the server
|
|
module. To do Speed tests the server has routes which allows it to
|
|
upload and download a 50mb.
|
|
|
|
#+caption: UML diagram of server module
|
|
[[file:images/servermoduleArch.png]]
|
|
|
|
** Web framework
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: web-framework
|
|
:END:
|
|
The web framework used for the server module is called Gin. The reason
|
|
Gin was chosen is due to its wide use and strong documentation available
|
|
on the official github repository. The default port used is 8088. For
|
|
version 1.0 of the project ,the server needs to keep port 8088 open to
|
|
ensure that other clients and servers can detect it. The possible
|
|
requests available are GET and POST for this implementation. The
|
|
possible responses are either a string or json response or a file. In
|
|
the majority of routes a string response refers to an error when calling
|
|
the following routes. The following sub topics below will talk about the
|
|
route implemented:
|
|
|
|
*** /server_info
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: server_info
|
|
:END:
|
|
This route is responsible to get information about the specifications of
|
|
the server. The response of this route is in json if the call was
|
|
successful.
|
|
|
|
*** /50
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: section
|
|
:END:
|
|
This route is responsible for returning a randomly generated 50mb file.
|
|
This is used to calculate the download speed from the p2p module.
|
|
|
|
*** /IpTable
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: iptable
|
|
:END:
|
|
This route is a POST request that is responsible to update the server IP
|
|
table based on the IP table the client provides. Once the server gets
|
|
the IP table it checks if the client is also a server. This is done by
|
|
calling the url http://:8088/server_info. If the server_info route from
|
|
the client responds back with computer specifications of the client.
|
|
Then the server initially appends the clients IP to the struct. After
|
|
that the IP table received from the client is uploaded to the struct.
|
|
Once this is done the server passes the struct to the peer to peer
|
|
module function. The peer to peer module function will return the back
|
|
with the new struct with the valid server nodes. The server responds
|
|
back to the new struct as a json format. If a string is present in the
|
|
response then there is probably an error on the server side.
|
|
|
|
*** /startcontainer
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: startcontainer
|
|
:END:
|
|
This route takes in a GET request with the number of TCP ports to open
|
|
and checks whether the docker container should be hooked to the GPU or
|
|
not. This route talks to the docker module implemented as a sub module
|
|
in the server module. More information on the docker module in section
|
|
5.4.3. This route calls docker the module to start the container for the
|
|
client. The docker module returns back a struct. This struct is returned
|
|
back to the client as the json response. This struct consists of
|
|
information such as docker id, ports numbers open , information
|
|
regarding SSH and VNC connections to the docker container created when
|
|
the client created this request.
|
|
|
|
*** /RemoveContainer
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: removecontainer
|
|
:END:
|
|
This route takes in a GET request as the container ID. Based on the
|
|
container ID provided ,it calls the docker module which deletes the
|
|
container. If the deletion is successful it returns back a string which
|
|
says success.
|
|
|
|
** Server information/ Specification
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: server-information-specification
|
|
:END:
|
|
This section provides information on how the server specifications are
|
|
read. There are 2 major implementations. The first implementation
|
|
mentions how basic information such as RAM usage, CPU specification are
|
|
detected and the second implementation mentions how the GPU drivers are
|
|
detected and information is extracted. The client has to assume that the
|
|
server is using default docker settings in terms of CPU cycles and other
|
|
parameters.
|
|
|
|
*** Basic Information
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: basic-information
|
|
:END:
|
|
The file name for these functions is called gopsutil.go. This codebase
|
|
uses the library gopsutil. Gopsutil has various packages or modules
|
|
within the library which have functions implemented to get system
|
|
information. The following information is stored in a struct and the
|
|
function returns that struct.
|
|
|
|
#+begin_src go
|
|
type SysInfo struct {
|
|
Hostname string `bson:hostname`
|
|
Platform string `bson:platform`
|
|
CPU string `bson:cpu`
|
|
RAM uint64 `bson:ram`
|
|
Disk uint64 `bson:disk`
|
|
GPU *Query `xml: GpuInfo`
|
|
}
|
|
#+end_src
|
|
|
|
*** GPU Information
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: gpu-information
|
|
:END:
|
|
The file name for these functions is called GPU.go. This codebase checks
|
|
if the Nvidia driver exists and returns the driver information. To do
|
|
this a shell command called nvidia-smi is executed. This shell command
|
|
is executed with a --xml as flag to ensure that the output is in the XML
|
|
format. If there is an output as a xml format, that means there is an
|
|
nvidia driver installed, and the function just reads the output and
|
|
stores it to the struct and returns the GPU information.
|
|
|
|
#+begin_src go
|
|
|
|
type Query struct {
|
|
DriveVersion string `xml:"driver_version"`
|
|
Gpu Gpu `xml:"gpu"`
|
|
}
|
|
|
|
type Gpu struct{
|
|
GpuName string `xml:"product_name"`
|
|
BiosVersion string `xml:"vbios_version"`
|
|
FanSpeed string `xml:"fan_speed"`
|
|
Utilization GpuUtilization `xml:"utilization"`
|
|
Temperature GpuTemperature `xml:"temperature"`
|
|
Clock GpuClock `xml:"clocks"`
|
|
}
|
|
|
|
type GpuUtilization struct {
|
|
GpuUsage string `xml:"gpu_util"`
|
|
MemoryUsage string `xml:"memory_util"`
|
|
}
|
|
|
|
type GpuTemperature struct {
|
|
GpuTemp string `xml:"gpu_temp"`
|
|
}
|
|
|
|
type GpuClock struct {
|
|
GpuClock string `xml:"graphics_clock"`
|
|
GpuMemClock string `xml:"mem_clock"`
|
|
}
|
|
#+end_src
|
|
|
|
** Docker Module
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: docker-module
|
|
:END:
|
|
This section provides information on how the server module interacts
|
|
with the docker containers. The server calls 2 routes which either
|
|
creates or removes the docker container. Docker has a huge advantage
|
|
because it takes less than 20 seconds to spin up a new container once
|
|
it's built and executed at least once. For docker operations a separate
|
|
module/package has been created. The following subtopics will provide
|
|
more information on how this package works.
|
|
|
|
*** Docker Api
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: docker-api
|
|
:END:
|
|
For this the api has been taken from the official docker repository. To
|
|
be more specific it is the client module in the official docker
|
|
repository. Docker was built using Go. During this project Docker
|
|
functions could be directly called from the docker repository. The
|
|
Docker api initially ensures that it can detect the docker environment
|
|
variables. Once detected, it can execute various functions from the
|
|
docker client module. The reason the docker api was selected was to
|
|
detect and handle errors better.
|
|
|
|
*** Docker Image
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: docker-image
|
|
:END:
|
|
The docker image used to spin up the containers is called
|
|
ConSol/docker-headless-vnc-container. The following container was
|
|
modified to open SSH ports for an SSH connection. The following docker
|
|
image runs ubuntu 16. The reason this image was chosen as a default is
|
|
because if the client wants to access the container in the form of a
|
|
desktop environment. This image would allow the client to do so from
|
|
just a browser.
|
|
|
|
*** Build container
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: build-container
|
|
:END:
|
|
This function pulls the docker image locally and builds the image.
|
|
Initially there is a timeout function to ensure that building the image
|
|
does not take too long to build. The next phase would be based on the
|
|
path to get the DockerFile. The tag name of the container is set as
|
|
p2p-ubuntu as default. Once the following is set then the docker build
|
|
command is executed.
|
|
|
|
*** Run container
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: run-container
|
|
:END:
|
|
After building the container it needs to be executed for the user to
|
|
access the container and do certain operations. The docker
|
|
package/module has a function to do this. The function takes in the
|
|
docker environment as a parameter and also the docker struct. The docker
|
|
struct has information such as the TCP ports which are supposed to be
|
|
open and whether the docker container should have the GPU hooked to it
|
|
or not. Based on the appropriate information provided ,the docker image
|
|
gets started. The Image gets started by interacting with the docker
|
|
client modules. When hooking the GPU the docker run command is called
|
|
from the shell. This is because the docker Api does not support the GPU
|
|
module yet. When the container is executed for the first time it takes
|
|
more than 10 minutes to build. From the second time onwards it takes
|
|
only 10 seconds to run.
|
|
|
|
*** Stop and remove container
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: stop-and-remove-container
|
|
:END:
|
|
This implementation here ensures that the docker is stopped, and the
|
|
container is removed. This is to ensure it does not utilize server
|
|
resources when it is not being used, or the task that is intended to be
|
|
executed is complete. To run this function all that is needed is the
|
|
docker container ID. If the function is successful it returns a string
|
|
that says success.
|
|
|
|
*** Ports json file
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: ports-json-file
|
|
:END:
|
|
This file will help map internal ports inside a container to external
|
|
ports inside a container. A common example would be the SSH port which
|
|
is port 22 inside the docker container and is mapped to random TCP port
|
|
outside container so that any external machines can directly connect
|
|
into the container. The below representation mentions of where the
|
|
ports.json file is located and also the format of that file.
|
|
|
|
#+begin_example
|
|
|_ <Container name>
|
|
|_ Dockerfile
|
|
|_ description.txt
|
|
|_ ports.json // The ports file
|
|
#+end_example
|
|
|
|
Format of the ports.json file
|
|
|
|
#+begin_example
|
|
{
|
|
"Port": [
|
|
{
|
|
"PortName": "<Port name>",
|
|
"InternalPort": <internal port>,
|
|
"Type": "<tcp/udp>",
|
|
"ExternalPort": <external port>,
|
|
"IsUsed": "<boolean value (i.e true or false)>",
|
|
"Description": "<description about the port>"
|
|
}, ... n
|
|
]
|
|
}
|
|
#+end_example
|