diff --git a/clusternet/apis/worker/controllers/__init__.py b/clusternet/apis/worker/controllers/__init__.py index 3771b41..2f5f085 100644 --- a/clusternet/apis/worker/controllers/__init__.py +++ b/clusternet/apis/worker/controllers/__init__.py @@ -9,9 +9,11 @@ from clusternet.apis.worker.controllers.remove_link import RemoveLinkController from clusternet.apis.worker.controllers.run_command import RunCommandOnHostController from clusternet.apis.worker.controllers.run_pingall import RunPingallController +from clusternet.apis.worker.controllers.run_service import RunServiceController from clusternet.apis.worker.controllers.start_docker import StartDockerController from clusternet.apis.worker.controllers.start_worker import StartWorkerController from clusternet.apis.worker.controllers.stop_docker import StopDockerController from clusternet.apis.worker.controllers.stop_worker import StopWorkerController from clusternet.apis.worker.controllers.update_cpu import UpdateCPUController from clusternet.apis.worker.controllers.update_memory import UpdateMemoryController + diff --git a/clusternet/apis/worker/controllers/run_service.py b/clusternet/apis/worker/controllers/run_service.py new file mode 100644 index 0000000..8229bcf --- /dev/null +++ b/clusternet/apis/worker/controllers/run_service.py @@ -0,0 +1,27 @@ +from clusternet.apis.presentation.exceptions import BadRequestException +from clusternet.apis.presentation.helpers import ( + bad_request, created, error, internal_server_error, validate_required_params +) +from clusternet.apis.presentation.protocols import Controller, HttpRequest, HttpResponse +from clusternet.apis.worker.helpers import get_hostname, run_container + + +class RunServiceController(Controller): + def __init__(self) -> None: + pass + + def handle(self, request: HttpRequest) -> HttpResponse: + required_params = ['name', 'image'] + try: + hostname = get_hostname() + validate_required_params(request, required_params) + + name = str(request.body.pop('name')) + image = str(request.body.pop('image')) + run_container(name, image, **request.body) + + return created({'content': f'[{hostname}]: service {name} created'}) + except BadRequestException as ex: + return bad_request(error(f'{ex}')) + except Exception as ex: + return internal_server_error(error(f'{ex}')) diff --git a/clusternet/apis/worker/helpers.py b/clusternet/apis/worker/helpers.py index 5975e02..260e2ef 100644 --- a/clusternet/apis/worker/helpers.py +++ b/clusternet/apis/worker/helpers.py @@ -1,10 +1,11 @@ -from typing import List +from typing import Any, List import docker import socket from mininet.log import info from clusternet.apis.worker.data import WorkerInstance +client = docker.from_env() def get_hostname() -> str: return socket.gethostname() @@ -21,4 +22,7 @@ def clean_containers_with_prefix(prefix: str) -> List[str]: container.remove(force=True) # type: ignore removed_containers.append(name) - return removed_containers \ No newline at end of file + return removed_containers + +def run_container(name: str, image: str, **params: Any): + client.containers.run(image, name=name, remove=True, detach=True, **params) diff --git a/clusternet/client/worker.py b/clusternet/client/worker.py index 5680163..7401aa3 100644 --- a/clusternet/client/worker.py +++ b/clusternet/client/worker.py @@ -1,3 +1,4 @@ +from typing import Any import httpx from clusternet.client.container import RemoteContainer @@ -17,7 +18,7 @@ def add_controller(self, name: str, ip: str, port: int): print(f'{response.json()["content"]}') - def add_docker(self, name: str, **params) -> RemoteContainer: + def add_docker(self, name: str, **params: Any) -> RemoteContainer: data = {'name': name, **params} response = httpx.post(url=f'{self.url}/containers', json=data, timeout=None) @@ -28,7 +29,7 @@ def add_docker(self, name: str, **params) -> RemoteContainer: return RemoteContainer(name, self.url) - def add_link(self, node1: str, node2: str, **params): + def add_link(self, node1: str, node2: str, **params: Any): data = {'node1': node1, 'node2': node2, **params} response = httpx.post(url=f'{self.url}/links', json=data, timeout=None) @@ -97,6 +98,15 @@ def run_pingall(self): print(f'{response.json()["content"]}') + def run_service(self, name: str, image: str, **params: Any): + data = {'name': name, 'image': image, **params} + response = httpx.post(url=f'{self.url}/services', json=data, timeout=None) + + if(response.is_error): + raise Exception(response.json()['error']) + print(f'{response.json()["content"]}') + + def start(self): response = httpx.get(url=f'{self.url}/start', timeout=None) diff --git a/clusternet/server/worker_app.py b/clusternet/server/worker_app.py index 70de606..be3e10d 100644 --- a/clusternet/server/worker_app.py +++ b/clusternet/server/worker_app.py @@ -7,8 +7,9 @@ from clusternet.apis.worker.controllers import ( AddController, AddDockerController, AddLinkController, AddSwitchController, CleanContainersController, ConfigDefaultController, GetDockerIPController, - RemoveDockerController, RemoveLinkController, RunCommandOnHostController, RunPingallController, - StartDockerController, StopDockerController, StartWorkerController, StopWorkerController, + RemoveDockerController, RemoveLinkController, RunCommandOnHostController, + RunServiceController, RunPingallController, StartDockerController, + StopDockerController, StartWorkerController, StopWorkerController, UpdateCPUController, UpdateMemoryController ) from clusternet.apis.presentation.helpers import parse_request @@ -112,6 +113,12 @@ def run_pingall(): return make_response(controller, request) +@server.route('/services', methods=['POST']) +def run_service(): + controller = RunServiceController() + return make_response(controller, request) + + @server.route('/start', methods=['GET']) def start(): controller = StartWorkerController() diff --git a/setup.py b/setup.py index e3195a5..a180d15 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='clusternet', - version='0.6.2', + version='0.7.2', description='Distributed Software Defined Network Emulation', long_description='Distributed Software Defined Network Emulation', keywords=['networking', 'emulator', 'containernet', 'mininet', 'OpenFlow', 'SDN', 'fog'],