├── .dockerignore ├── .gitattributes ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .golangci.yaml ├── Dockerfile ├── LICENSE ├── Makefile ├── api ├── control_plane_api_server.go ├── data_plane_api_server.go ├── proto │ ├── common.pb.go │ ├── common.proto │ ├── control_plane_interface.pb.go │ ├── control_plane_interface.proto │ ├── control_plane_interface_grpc.pb.go │ ├── data_plane_interface.pb.go │ ├── data_plane_interface.proto │ ├── data_plane_interface_grpc.pb.go │ ├── raft.pb.go │ ├── raft.proto │ ├── worker_node_interface.pb.go │ ├── worker_node_interface.proto │ └── worker_node_interface_grpc.pb.go └── worker_node_api_server.go ├── artifact_evaluation ├── .gitignore ├── README.md ├── azure_500 │ ├── dirigent │ │ ├── .gitignore │ │ ├── INSTRUCTIONS.md │ │ └── azure_500 │ │ │ ├── dirigent.csv │ │ │ ├── durations.csv │ │ │ ├── invocations.csv │ │ │ └── memory.csv │ └── knative │ │ ├── .gitignore │ │ ├── INSTRUCTIONS.md │ │ └── azure_500 │ │ ├── dirigent.csv │ │ ├── durations.csv │ │ ├── invocations.csv │ │ └── memory.csv ├── cold_start_sweep │ ├── dirigent │ │ ├── .gitignore │ │ └── INSTRUCTIONS.md │ └── knative │ │ ├── .gitignore │ │ └── INSTRUCTIONS.md ├── plot_azure_500.py ├── plot_cold_start_sweep.py ├── run_plotting_scripts.sh └── sample_results │ ├── azure_500_per_function_slowdown.png │ ├── azure_500_scheduling_latency.png │ └── cold_start_sweep.png ├── async └── fire.go ├── cmd ├── data_plane │ ├── config.yaml │ ├── config_1.yaml │ ├── config_2.yaml │ ├── config_async.yaml │ ├── config_cluster.yaml │ ├── config_cluster_async.yaml │ ├── config_cluster_raft.yaml │ ├── config_raft.yaml │ └── main.go ├── flush │ └── main.go ├── master_node │ ├── config.yaml │ ├── config_cluster.yaml │ ├── config_cluster_raft_1.yaml │ ├── config_cluster_raft_2.yaml │ ├── config_cluster_raft_3.yaml │ ├── config_raft_1.yaml │ ├── config_raft_2.yaml │ ├── config_raft_3.yaml │ ├── main.go │ └── state_management │ │ └── election_management.go ├── monitoring │ └── monitoring.py ├── simulator_workers │ └── main.go └── worker_node │ ├── config.yaml │ ├── config_cluster.yaml │ ├── config_cluster_containerd.yaml │ ├── config_cluster_fake_worker.yaml │ ├── config_cluster_fake_worker_raft.yaml │ ├── config_cluster_raft.yaml │ ├── config_raft.yaml │ └── main.go ├── configs ├── check_apiserver.sh ├── cni.conf ├── fcnet.conflist ├── firecracker │ ├── image.sh │ ├── openrc-service.sh │ ├── rootfs.ext4 │ ├── setup-alpine.sh │ ├── vmlinux-4.14.bin │ ├── vmlinux-5.10.bin │ └── vmlinux-6.1.bin ├── haproxy.cfg ├── keepalived.conf └── substitute_interface.sh ├── docker-compose.yml ├── docs ├── architecture.png └── firecracker.md ├── go.mod ├── go.sum ├── internal ├── control_plane │ ├── autoscaling │ │ ├── autoscaling.go │ │ ├── controller.go │ │ └── controller_test.go │ ├── control_plane.go │ ├── control_plane_test.go │ ├── core │ │ ├── interface.go │ │ └── types.go │ ├── data_plane │ │ ├── data_plane.go │ │ ├── data_plane_test.go │ │ └── empty_dataplane │ │ │ └── empty_dataplane.go │ ├── eviction_policy │ │ ├── eviction_policy.go │ │ └── eviction_policy_test.go │ ├── failure.go │ ├── helpers.go │ ├── leader_election │ │ ├── consensus_module.go │ │ ├── consensus_module_test.go │ │ ├── server.go │ │ └── state.go │ ├── persistence │ │ ├── empty_persistence.go │ │ ├── interface.go │ │ └── redis_persistence.go │ ├── placement_policy │ │ ├── k8s_placement.go │ │ ├── k8s_placement_test.go │ │ ├── placement_policy.go │ │ ├── placement_policy_test.go │ │ ├── random.go │ │ ├── resource_map.go │ │ ├── resource_map_test.go │ │ └── round_robin.go │ ├── reconstruction.go │ ├── registration_server │ │ └── registration_server.go │ ├── scaling_loop.go │ └── workers │ │ ├── empty_worker │ │ ├── empty_interface_client.go │ │ └── empty_worker.go │ │ ├── worker_node.go │ │ └── worker_node_test.go ├── data_plane │ ├── data_plane.go │ ├── data_plane_test.go │ ├── function_metadata │ │ ├── deployment.go │ │ ├── function_metadata.go │ │ ├── function_metadata_test.go │ │ └── statistics.go │ ├── haproxy │ │ ├── connection.go │ │ ├── manager.go │ │ └── manager_test.go │ └── proxy │ │ ├── async_proxy_handler.go │ │ ├── load_balancing │ │ ├── load_balancing.go │ │ └── load_balancing_test.go │ │ ├── metrics.go │ │ ├── net │ │ ├── buffer_pool.go │ │ └── factory.go │ │ ├── persistence │ │ ├── empty_persistence.go │ │ ├── redis_persistence.go │ │ └── request_persistence.go │ │ ├── proxy.go │ │ ├── requests │ │ └── requests.go │ │ ├── sync_proxy_handler.go │ │ └── utils.go └── worker_node │ ├── managers │ ├── exponential_backoff.go │ ├── exponential_backoff_test.go │ ├── ip_manager.go │ ├── ip_manager_test.go │ ├── iptables_manager.go │ ├── process_monitor.go │ ├── readiness_probes.go │ ├── rootfs_manager.go │ ├── sandbox_manager.go │ ├── sandbox_manager_test.go │ ├── thread_safe_random.go │ └── veth_name_generator.go │ ├── sandbox │ ├── containerd │ │ ├── config_builder.go │ │ ├── iface.go │ │ ├── iface_test.go │ │ ├── image_manager.go │ │ ├── image_manager_test.go │ │ └── runtime.go │ ├── fake_snapshot │ │ └── runtime.go │ ├── firecracker │ │ ├── iface.go │ │ ├── networking.go │ │ ├── runtime.go │ │ ├── snapshot_manager.go │ │ └── vm.go │ └── runtime_interface.go │ ├── worker_node.go │ └── worker_node_test.go ├── mock ├── mock_core │ └── mock_core.go ├── mock_cp_api │ └── mock_cp_api.go └── mock_persistence │ └── mock_persistence.go ├── pkg ├── atomic_map │ ├── atomic_map.go │ ├── atomic_map_counter.go │ ├── atomic_map_counter_test.go │ └── atomic_map_test.go ├── config │ ├── config.go │ └── config_test.go ├── grpc_helpers │ └── grpc_helpers.go ├── hardware │ ├── hardware.go │ └── hardware_test.go ├── logger │ └── logging.go ├── map │ ├── maps.go │ └── maps_test.go ├── network │ └── ip.go ├── profiler │ └── profiler.go ├── redis_helpers │ └── redis_helpers.go ├── synchronization │ └── control_plane_sync.go ├── tracing │ └── tracing.go └── utils │ ├── constants.go │ └── utils.go ├── readme.md ├── scripts ├── .gitignore ├── add_auth_token.sh ├── add_ssh_key.sh ├── azure.sh ├── collect_resource_monitoring.sh ├── common.sh ├── invitro_traces │ ├── generate_traces.py │ └── samples │ │ ├── 100 │ │ ├── config.json │ │ ├── dirigent.csv │ │ ├── durations.csv │ │ ├── invocations.csv │ │ └── memory.csv │ │ ├── 250 │ │ ├── config.json │ │ ├── dirigent.csv │ │ ├── durations.csv │ │ ├── invocations.csv │ │ └── memory.csv │ │ ├── 500 │ │ ├── config.json │ │ ├── dirigent.csv │ │ ├── durations.csv │ │ ├── invocations.csv │ │ └── memory.csv │ │ └── 4000 │ │ ├── config.json │ │ ├── dirigent.csv │ │ ├── durations.csv │ │ ├── invocations.csv │ │ └── memory.csv ├── measure_async.sh ├── plotting │ ├── breakdown_comparison.py │ ├── cdf.py │ ├── common.py │ ├── compare.py │ ├── get_percentile.py │ ├── latency_breakdown_burst.py │ ├── latency_breakdown_sweep.py │ ├── plot.py │ ├── plot_utilization.py │ └── proxy_analysis.py ├── remote_install.sh ├── remote_start_cluster.sh ├── restart_workers.sh ├── restart_workers_containerd.sh ├── rps_containerd.sh ├── rps_firecracker.sh ├── scalability_copy_results.sh ├── setup.cfg ├── setup_node.sh ├── start_async_data_plane.sh ├── start_control_plane.sh ├── start_data_plane.sh ├── start_redis.sh ├── start_resource_monitoring.sh ├── string.py └── systemd │ ├── control_plane.service │ ├── data_plane.service │ └── worker_node.service └── workload ├── go.mod ├── go.sum ├── http_workload.go └── workload.go /.dockerignore: -------------------------------------------------------------------------------- 1 | **/api 2 | **/architecture 3 | **/cmd 4 | **/configs 5 | **/data 6 | **/docs 7 | **/internal 8 | **/mock 9 | **/pkg 10 | **/scripts 11 | **/tests 12 | **/.git 13 | **/.github 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bin filter=lfs diff=lfs merge=lfs -text 2 | *.ext4 filter=lfs diff=lfs merge=lfs -text 3 | *.csv filter=lfs diff=lfs merge=lfs -text 4 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: Go 5 | 6 | on: 7 | push: 8 | branches: [ "*" ] 9 | pull_request: 10 | branches: [ "*" ] 11 | 12 | jobs: 13 | test: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - name: Set up Go 19 | uses: actions/setup-go@v4 20 | with: 21 | go-version: '1.20' 22 | 23 | - name: Configure HAProxy 24 | run: sudo apt-get update && sudo apt-get install haproxy && sudo cp ./configs/haproxy.cfg /etc/haproxy/haproxy.cfg 25 | 26 | - name: Build 27 | run: go build ./... 28 | 29 | - name: Test 30 | run: | 31 | curl -L -o cni-plugins.tgz https://github.com/containernetworking/plugins/releases/download/v0.8.1/cni-plugins-linux-amd64-v0.8.1.tgz 32 | sudo mkdir -p /opt/cni/bin 33 | sudo tar -C /opt/cni/bin -xzf cni-plugins.tgz 34 | sudo go test -v ./... -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .github 2 | .idea 3 | cpp_legacy/.idea 4 | cpp_legacy/cmake-build-debug 5 | 6 | data 7 | data/* 8 | scripts/__pycache__/ 9 | scripts/plotting/__pycache__/ 10 | 11 | cmd/test 12 | 13 | # This is not to allow non-explicit updates to Linux kernel image and Rootfs image 14 | configs/firecracker/app 15 | configs/firecracker/rootfs.ext4 16 | configs/firecracker/vmlinux* 17 | 18 | notes.txt 19 | *.pdf 20 | 21 | scripts/invitro_traces/rps/* -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | nlreturn: 3 | block-size: 2 4 | godot: 5 | scope: toplevel 6 | exclude: 7 | - "^fixme:" 8 | - "^todo:" 9 | - "^ -" 10 | wsl: 11 | enforce-err-cuddling: true 12 | tagliatelle: 13 | case: 14 | rules: 15 | json: snake 16 | 17 | linters: 18 | enable-all: true 19 | disable: 20 | - ifshort # deprecated 21 | - nosnakecase # deprecated 22 | - interfacer # deprecated 23 | - deadcode # deprecated 24 | - exhaustivestruct # deprecated 25 | - varcheck # deprecated 26 | - structcheck # deprecated 27 | - maligned # deprecated 28 | - scopelint # deprecated 29 | - golint # deprecated 30 | - rowserrcheck # https://github.com/golangci/golangci-lint/issues/2649 31 | - sqlclosecheck # https://github.com/golangci/golangci-lint/issues/2649 32 | - wastedassign # https://github.com/golangci/golangci-lint/issues/2649 33 | - gomnd # we use status code numbers and for our use case it's not practical 34 | - godox # we have TODOs at this stage of the project, enable in future 35 | - forbidigo # we use things like fmt.Printf for debugging, enable in future 36 | - gci # conflicts with goimports 37 | - gofumpt # conflicts with goimports 38 | - depguard 39 | - testpackage 40 | - funlen 41 | - lll 42 | fast: true 43 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:latest 2 | 3 | # Stage 0: Build # 4 | # Use the official Golang image to create a build artifact. 5 | # This is based on Debian and sets the GOPATH to /go. 6 | FROM golang:1.21 as BUILDER 7 | 8 | # Create and change to the app directory. 9 | WORKDIR /app 10 | 11 | # Retrieve application dependencies using go modules. 12 | # Allows container builds to reuse downloaded dependencies. 13 | COPY go.* ./ 14 | RUN go mod download 15 | 16 | # Copy local code to the container image. 17 | COPY . ./ 18 | 19 | # Build the binary. 20 | WORKDIR /app/workload 21 | 22 | # -mod=readonly: ensures immutable go.mod and go.sum in container builds. 23 | # CGO_ENABLED=1: uses common libraries found on most major OS distributions. 24 | # GOARCH=amd64 GOGCCFLAGS=-m64: specifies x86, 64-bit GCC. 25 | RUN CGO_ENABLED=1 GOARCH=amd64 GOGCCFLAGS=-m64 GOOS=linux go build -mod=readonly -v -o server 26 | 27 | # Stage 1: Run # 28 | FROM debian:stable-slim 29 | 30 | # Copy the binary to the production image from the BUILDER stage. 31 | COPY --from=BUILDER /app/workload/server /server 32 | 33 | # Run the web service on container startup. 34 | CMD /server -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 EASL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROTOC_ARGS_API=--go_out=api/proto --go_opt=paths=source_relative --go-grpc_out=api/proto --go-grpc_opt=paths=source_relative 2 | PROTOC_ARGS_TESTS=--go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative 3 | 4 | # Absolute path to directory of this Makefile 5 | ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) 6 | 7 | install_golang_proto_compiler: 8 | go get google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 9 | go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 10 | 11 | proto: 12 | protoc $(PROTOC_ARGS_API) --proto_path=api/proto api/proto/*.proto 13 | 14 | install_mockgen: 15 | go install go.uber.org/mock/mockgen@latest 16 | 17 | generate_mock_files: 18 | mockgen -source internal/control_plane/persistence/interface.go > mock/mock_persistence/mock_persistence.go 19 | mockgen -source internal/control_plane/core/interface.go > mock/mock_core/mock_core.go 20 | mockgen -source api/proto/control_plane_interface_grpc.pb.go -package mock_cp_api > mock/mock_cp_api/mock_cp_api.go 21 | 22 | build_rootfs: 23 | sudo rm -rf $(ROOT_DIR)/configs/firecracker/app $(ROOT_DIR)/configs/firecracker/rootfs.ext4 24 | sudo $(ROOT_DIR)/configs/firecracker/image.sh \ 25 | -d $(ROOT_DIR)/configs/firecracker/ \ 26 | -s $(ROOT_DIR)/workload \ 27 | -r $(ROOT_DIR)/configs/firecracker/rootfs.ext4 28 | 29 | empty_container: 30 | docker build \ 31 | -f Dockerfile \ 32 | -t cvetkovic/dirigent_empty_function . 33 | docker push cvetkovic/dirigent_empty_function:latest 34 | 35 | trace_container: 36 | docker build \ 37 | -f Dockerfile \ 38 | -t cvetkovic/dirigent_trace_function . 39 | docker push cvetkovic/dirigent_trace_function:latest 40 | -------------------------------------------------------------------------------- /api/data_plane_api_server.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package api 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "cluster_manager/internal/data_plane" 30 | "cluster_manager/internal/data_plane/proxy" 31 | "context" 32 | "github.com/sirupsen/logrus" 33 | "google.golang.org/protobuf/types/known/emptypb" 34 | ) 35 | 36 | type DpApiServer struct { 37 | proto.UnimplementedDpiInterfaceServer 38 | 39 | dataplane *data_plane.Dataplane 40 | Proxy *proxy.ProxyingService 41 | } 42 | 43 | func NewDpApiServer(dataPlane *data_plane.Dataplane) *DpApiServer { 44 | return &DpApiServer{ 45 | dataplane: dataPlane, 46 | } 47 | } 48 | 49 | func (api *DpApiServer) AddDeployment(_ context.Context, in *proto.ServiceInfo) (*proto.DeploymentUpdateSuccess, error) { 50 | return api.dataplane.AddDeployment(in) 51 | } 52 | 53 | func (api *DpApiServer) UpdateEndpointList(_ context.Context, patch *proto.DeploymentEndpointPatch) (*proto.DeploymentUpdateSuccess, error) { 54 | return api.dataplane.UpdateEndpointList(patch) 55 | } 56 | 57 | func (api *DpApiServer) DeleteDeployment(_ context.Context, name *proto.ServiceInfo) (*proto.DeploymentUpdateSuccess, error) { 58 | return api.dataplane.DeleteDeployment(name) 59 | } 60 | 61 | func (api *DpApiServer) DrainSandbox(_ context.Context, endpoint *proto.DeploymentEndpointPatch) (*proto.DeploymentUpdateSuccess, error) { 62 | return api.dataplane.DrainSandbox(endpoint) 63 | } 64 | 65 | // TODO: Remove this function 66 | func (api *DpApiServer) ResetMeasurements(_ context.Context, in *emptypb.Empty) (*proto.ActionStatus, error) { 67 | logrus.Warn("This function does nothing") 68 | return &proto.ActionStatus{Success: true}, nil 69 | } 70 | -------------------------------------------------------------------------------- /api/proto/common.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package data_plane; 3 | 4 | option go_package = "github.com/eth-easl/cluster_manager/api/proto"; 5 | 6 | enum L4Protocol { 7 | TCP = 0; 8 | UDP = 1; 9 | } 10 | 11 | message PortMapping { 12 | int32 HostPort = 1; 13 | int32 GuestPort = 2; 14 | L4Protocol Protocol = 3; 15 | } 16 | 17 | message AutoscalingConfiguration { 18 | int32 ScalingUpperBound = 1; 19 | int32 ScalingLowerBound = 2; 20 | float PanicThresholdPercentage = 3; 21 | float MaxScaleUpRate = 4; 22 | float MaxScaleDownRate = 5; 23 | int32 ContainerConcurrency = 6; 24 | int32 ContainerConcurrencyTargetPercentage = 7; 25 | int32 StableWindowWidthSeconds = 8; 26 | int32 PanicWindowWidthSeconds = 9; 27 | int32 ScalingPeriodSeconds = 10; 28 | int32 ScalingMethod = 11; 29 | } 30 | 31 | message ServiceInfo { 32 | string Name = 1; 33 | string Image = 2; 34 | uint64 RequestedCpu = 3; 35 | uint64 RequestedMemory = 4; 36 | PortMapping PortForwarding = 5; 37 | AutoscalingConfiguration AutoscalingConfig = 6; 38 | } 39 | 40 | message ServiceList { 41 | repeated string Service = 1; 42 | } 43 | 44 | message ActionStatus { 45 | bool Success = 1; 46 | string Message = 2; 47 | } 48 | 49 | message DataplaneInformation { 50 | string Address = 1; 51 | string ApiPort = 2; 52 | string ProxyPort = 3; 53 | } 54 | 55 | message WorkerNodeInformation { 56 | string Name = 1; 57 | string Ip = 2; 58 | string Port = 3; 59 | uint64 CpuCores = 4; 60 | uint64 Memory = 5; 61 | } 62 | 63 | message Endpoint { 64 | string SandboxID = 1; 65 | string URL = 2; 66 | string NodeName = 3; 67 | string ServiceName = 4; 68 | int32 HostPort = 5; 69 | } -------------------------------------------------------------------------------- /api/proto/control_plane_interface.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package data_plane; 3 | 4 | option go_package = "github.com/eth-easl/cluster_manager/api/proto"; 5 | 6 | import "common.proto"; 7 | import "raft.proto"; 8 | 9 | import "google/protobuf/empty.proto"; 10 | 11 | message NodeInfo { 12 | string NodeID = 1; 13 | string IP = 2; 14 | int32 Port = 3; 15 | uint64 CpuCores = 4; 16 | uint64 MemorySize = 5; 17 | } 18 | 19 | message NodeHeartbeatMessage { 20 | string NodeID = 1; 21 | uint64 CpuUsage = 2; 22 | uint64 MemoryUsage = 3; 23 | } 24 | 25 | message AutoscalingMetric { 26 | string ServiceName = 1; 27 | string DataplaneName = 2; 28 | int32 InflightRequests = 3; 29 | } 30 | 31 | message DataplaneInfo { 32 | string IP = 1; 33 | int32 APIPort = 2; 34 | int32 ProxyPort = 3; 35 | } 36 | 37 | enum FailureType { 38 | SANDBOX_FAILURE = 0; 39 | SANDBOX_DAEMON_FAILURE = 1; 40 | WORKER_NODE_FAILURE = 2; 41 | } 42 | 43 | message Failure { 44 | FailureType Type = 1; 45 | string ServiceName = 2; 46 | repeated string SandboxIDs = 3; 47 | } 48 | 49 | message HAProxyConfig { 50 | repeated string Dataplanes = 1; 51 | repeated string RegistrationServers = 2; 52 | } 53 | 54 | service CpiInterface { 55 | rpc OnMetricsReceive(AutoscalingMetric) returns (ActionStatus); 56 | rpc ListServices(google.protobuf.Empty) returns (ServiceList); 57 | 58 | rpc RegisterDataplane(DataplaneInfo) returns (ActionStatus); 59 | rpc RegisterService(ServiceInfo) returns (ActionStatus); 60 | rpc RegisterNode(NodeInfo) returns (ActionStatus); 61 | rpc NodeHeartbeat(NodeHeartbeatMessage) returns (ActionStatus); 62 | 63 | rpc ReportFailure(Failure) returns (ActionStatus); 64 | 65 | rpc DeregisterDataplane(DataplaneInfo) returns (ActionStatus); 66 | rpc DeregisterNode(NodeInfo) returns (ActionStatus); 67 | rpc DeregisterService(ServiceInfo) returns (ActionStatus); 68 | 69 | rpc ResetMeasurements(google.protobuf.Empty) returns (ActionStatus); 70 | 71 | // RAFT leader election 72 | rpc RequestVote(RequestVoteArgs) returns (RequestVoteReply); 73 | rpc AppendEntries(AppendEntriesArgs) returns (AppendEntriesReply); 74 | 75 | // HAProxy 76 | rpc ReviseHAProxyConfiguration(HAProxyConfig) returns (ActionStatus); 77 | } -------------------------------------------------------------------------------- /api/proto/data_plane_interface.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package data_plane; 3 | 4 | option go_package = "github.com/eth-easl/cluster_manager/api/proto"; 5 | 6 | import "common.proto"; 7 | import "google/protobuf/empty.proto"; 8 | 9 | message EndpointInfo { 10 | string ID = 1; 11 | string URL = 2; 12 | } 13 | 14 | message DeploymentEndpointPatch { 15 | ServiceInfo Service = 1; 16 | repeated EndpointInfo Endpoints = 2; 17 | } 18 | 19 | message DeploymentUpdateSuccess { 20 | bool Success = 1; 21 | string Message = 2; 22 | } 23 | 24 | service DpiInterface { 25 | rpc AddDeployment(ServiceInfo) returns (DeploymentUpdateSuccess); 26 | rpc DeleteDeployment(ServiceInfo) returns (DeploymentUpdateSuccess); 27 | 28 | rpc UpdateEndpointList(DeploymentEndpointPatch) returns (DeploymentUpdateSuccess); 29 | rpc DrainSandbox(DeploymentEndpointPatch) returns (DeploymentUpdateSuccess); 30 | 31 | rpc ResetMeasurements(google.protobuf.Empty) returns (ActionStatus); 32 | } -------------------------------------------------------------------------------- /api/proto/raft.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/eth-easl/cluster_manager/api/proto"; 4 | 5 | message RequestVoteArgs { 6 | int32 Term = 1; 7 | int32 CandidateID = 2; 8 | int32 LastLogIndex = 3; 9 | int32 LastLogTerm = 4; 10 | } 11 | 12 | message RequestVoteReply { 13 | int32 Term = 1; 14 | bool VoteGranted = 2; 15 | } 16 | 17 | message AppendEntriesArgs { 18 | int32 Term = 1; 19 | int32 LeaderID = 2; 20 | } 21 | 22 | message AppendEntriesReply { 23 | int32 Term = 1; 24 | bool Success = 2; 25 | } 26 | -------------------------------------------------------------------------------- /api/proto/worker_node_interface.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package data_plane; 3 | 4 | option go_package = "github.com/eth-easl/cluster_manager/api/proto"; 5 | 6 | import "common.proto"; 7 | import "google/protobuf/empty.proto"; 8 | import "google/protobuf/duration.proto"; 9 | 10 | message SandboxID { 11 | string ID = 1; 12 | int32 HostPort = 2; 13 | } 14 | 15 | message SandboxCreationStatus { 16 | bool Success = 1; 17 | string ID = 2; 18 | PortMapping PortMappings = 3; 19 | SandboxCreationBreakdown LatencyBreakdown = 5; 20 | } 21 | 22 | message SandboxCreationBreakdown { 23 | google.protobuf.Duration Total = 1; 24 | google.protobuf.Duration ImageFetch = 2; 25 | google.protobuf.Duration SandboxCreate = 3; 26 | google.protobuf.Duration NetworkSetup = 4; 27 | google.protobuf.Duration SandboxStart = 5; 28 | google.protobuf.Duration Iptables = 6; 29 | google.protobuf.Duration ReadinessProbing = 7; 30 | google.protobuf.Duration DataplanePropagation = 8; 31 | google.protobuf.Duration SnapshotCreation = 9; 32 | google.protobuf.Duration ConfigureMonitoring = 10; 33 | google.protobuf.Duration FindSnapshot = 11; 34 | } 35 | 36 | message EndpointsList { 37 | repeated Endpoint endpoint = 1; 38 | } 39 | 40 | service WorkerNodeInterface { 41 | rpc CreateSandbox(ServiceInfo) returns (SandboxCreationStatus); 42 | rpc DeleteSandbox(SandboxID) returns (ActionStatus); 43 | 44 | rpc ListEndpoints(google.protobuf.Empty) returns (EndpointsList); 45 | } -------------------------------------------------------------------------------- /api/worker_node_api_server.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package api 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "cluster_manager/internal/worker_node" 30 | "context" 31 | "google.golang.org/protobuf/types/known/emptypb" 32 | ) 33 | 34 | type WnApiServer struct { 35 | proto.UnimplementedWorkerNodeInterfaceServer 36 | 37 | workerNode *worker_node.WorkerNode 38 | } 39 | 40 | func NewWorkerNodeApi(workerNode *worker_node.WorkerNode) *WnApiServer { 41 | return &WnApiServer{ 42 | workerNode: workerNode, 43 | } 44 | } 45 | 46 | func (w *WnApiServer) CreateSandbox(grpcCtx context.Context, in *proto.ServiceInfo) (*proto.SandboxCreationStatus, error) { 47 | return w.workerNode.SandboxRuntime.CreateSandbox(grpcCtx, in) 48 | } 49 | 50 | func (w *WnApiServer) DeleteSandbox(grpcCtx context.Context, in *proto.SandboxID) (*proto.ActionStatus, error) { 51 | return w.workerNode.SandboxRuntime.DeleteSandbox(grpcCtx, in) 52 | } 53 | 54 | func (w *WnApiServer) ListEndpoints(grpcCtx context.Context, in *emptypb.Empty) (*proto.EndpointsList, error) { 55 | return w.workerNode.SandboxRuntime.ListEndpoints(grpcCtx, in) 56 | } 57 | -------------------------------------------------------------------------------- /artifact_evaluation/.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | !sample_results/*.png -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/dirigent/.gitignore: -------------------------------------------------------------------------------- 1 | results_azure_500* 2 | results_azure_500_firecracker* -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/dirigent/INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | ## Azure 500 on Dirigent 2 | 3 | Time required: 10 min to set up environment and 30 min per experiment 4 | 5 | Description: This experiment runs the downsampled Azure trace with 500 functions. We recommend you follow the order of experiments as given in the `README.md`. 6 | 7 | Instructions: 8 | - Start Dirigent cluster as per instructions located in the root folder of artifact evaluation instructions. 9 | - On the `node0` execute `mkdir -p ~/invitro/data/traces/azure_500`. 10 | - Copy traces from this folder to `node0` using `scp azure_500/* user@node0:~/invitro/data/traces/azure_500/`. 11 | - Make sure on `node0` `~/invitro` branch is `rps_mode`. With text editor open `~/invitro/cmd/config_dirigent_trace.json` and change TracePath to match `data/traces/azure_500`. 12 | - On your local machine run `./scripts/start_resource_monitoring.sh user@node0 user@node1 user@node2`. 13 | - Run the load generator in screen/tmux on `node0` with `cd ~/invitro; go run cmd/loader.go --config cmd/config_dirigent_trace.json`. Wait until the experiment completed (~30 minutes). There should be ~170K invocations, with a negligible failure rate. 14 | - Gather experiment results. Make sure you do not overwrite data from the other experiment, and you place results in correct folders. 15 | - Create folders for storing results with `mkdir -p ./artifact_evaluation/azure_500/dirigent/results_azure_500`. 16 | - Copy load generator output with `scp user@node0:~/invitro/data/out/experiment_duration_30.csv results_azure_500/` 17 | - Copy resource utilization data with `mkdir -p ./artifact_evaluation/azure_500/dirigent/results_azure_500/cpu_mem_usage && ./scripts/collect_resource_monitoring.sh ./artifact_evaluation/azure_500/dirigent/results_azure_500/cpu_mem_usage user@node0 user@node1 user@node2`. 18 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/dirigent/azure_500/dirigent.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:72b0ae99689826ff136e2876dfa84b31c58054b066d02c7bf432395381081c9e 3 | size 67589 4 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/dirigent/azure_500/durations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bc2e52d33f1ec0d4032dc7cbdacadb7622413c9264f5478bf8da2c3aacd92b55 3 | size 122145 4 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/dirigent/azure_500/invocations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a0ca953d1b50cc1f0e813c656e0c3d65b7369757804b571e2767e1ab76b05536 3 | size 598449 4 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/dirigent/azure_500/memory.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ea3ac4b65629cb33e567ac0a517d6ae68747a5dd143ff394b86f78f685b65305 3 | size 139891 4 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/knative/.gitignore: -------------------------------------------------------------------------------- 1 | results_azure_500 -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/knative/INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | ## Azure 500 on Knative/K8s 2 | 3 | Time required: 10 min to set up environment and 30-60 min for the experiment 4 | 5 | Description: This experiment runs the downsampled Azure trace with 500 functions. Do not reuse Knative/K8s cluster if you configured the cluster for cold start sweep experiment. 6 | 7 | Important: Do not reuse Knative/K8s cluster if you previously ran cold start sweep experiments, as the autoscaling configuration was changed and could affect the results severely. 8 | 9 | Instructions: 10 | - SSH into `node0` and on that node clone the load generator repo. Then checkout to `rps_mode` branch. The command is `git clone --branch=rps_mode https://github.com/vhive-serverless/invitro`. 11 | - On `node0` create a directory where trace will be stored `cd invitro; mkdir data/traces/azure_500`. 12 | - Copy the trace from folder where this instruction file is located to the folder you previously created on `node0` using the following command `scp azure_500/*.csv user@node0:~/invitro/data/traces/azure_500`. 13 | - On your local machine run `./scripts/start_resource_monitoring.sh user@node0 user@node1 user@node2`. 14 | - On `node0` inside screen/tmux run `cd ~/invitro; go run cmd/loader.go --config cmd/config_knative.json`. Function deployment will take 10-20 minutes, and then experiment will run for additional 30 minutes. 15 | - Gather experiment results. Make sure you do not overwrite data from the other experiment, and you place results in correct folders. 16 | - Create a folder for storing results with `mkdir -p ./artifact_evaluation/azure_500/knative/results_azure_500` 17 | - Copy load generator output with `scp user@node0:~/invitro/data/out/experiment_duration_30.csv results_azure_500/` 18 | - Copy resource utilization data with `mkdir -p ./artifact_evaluation/azure_500/knative/results_azure_500/cpu_mem_usage && ./scripts/collect_resource_monitoring.sh ./artifact_evaluation/azure_500/knative/results_azure_500/cpu_mem_usage user@node0 user@node1 user@node2`. -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/knative/azure_500/dirigent.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:72b0ae99689826ff136e2876dfa84b31c58054b066d02c7bf432395381081c9e 3 | size 67589 4 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/knative/azure_500/durations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bc2e52d33f1ec0d4032dc7cbdacadb7622413c9264f5478bf8da2c3aacd92b55 3 | size 122145 4 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/knative/azure_500/invocations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a0ca953d1b50cc1f0e813c656e0c3d65b7369757804b571e2767e1ab76b05536 3 | size 598449 4 | -------------------------------------------------------------------------------- /artifact_evaluation/azure_500/knative/azure_500/memory.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ea3ac4b65629cb33e567ac0a517d6ae68747a5dd143ff394b86f78f685b65305 3 | size 139891 4 | -------------------------------------------------------------------------------- /artifact_evaluation/cold_start_sweep/dirigent/.gitignore: -------------------------------------------------------------------------------- 1 | results_containerd* 2 | results_firecracker* -------------------------------------------------------------------------------- /artifact_evaluation/cold_start_sweep/dirigent/INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | ## Cold start sweep on Dirigent 2 | 3 | Time required: 10 min to set up environment and 2-3 min per data point 4 | 5 | Description: This experiment triggers cold start in Maestro cluster. You should sweep the load until the cluster saturates, which will be visible on the latency plot. We suggest running experiments with 1, 10, 100, 200, 300, ... RPS and observing the latency after conducting experiment for each data point. Low RPS (<10 RPS) rates should be run for 3-5 minutes, because of warmup, while any higher load can be run for just a minute. Always discard the results of the first experiment when starting a new cluster, as these measurements include image pull latency, which pollutes the measurements (can be seen as high p99 at low RPS). 6 | 7 | Instructions: 8 | - Start Dirigent cluster according to instructions located in the root folder of artifact evaluation instructions (`README.md`). You can reuse the existing cluster running Dirigent containerd. 9 | - On remote machine `node0` open `~/invitro/cmd/config_dirigent_rps.json`. Set `RpsColdStartRatioPercentage` to `100`, and sweep the load with `RpsTarget` while configuring `ExperimentDuration` according to instructions above. For higher RPS (>1000), it might be necessary to increase `RpsCooldownSeconds`, which controls the number of functions that are deployed in the cluster to achieve the requested RPS. Set `GRPCFunctionTimeoutSeconds` to `15`. For containerd experiments make sure `RpsImage` is set to `docker.io/cvetkovic/dirigent_empty_function:latest`. 10 | - Start RPS experiment by running `cd ~/invitro; go run cmd/loader.go --config cmd/config_dirigent_rps.json`. 11 | - Create folder storing results with `mkdir -p ./artifact_evaluation/cold_start_sweep/dirigent/results_containerd`. 12 | - Gather results located in `data/out/experiment_duration_X.csv` and copy them to your local machine in format `rps_X.csv` to the folder you created in the previous step. 13 | - Repeat for different RPS values until the cluster saturates, which you can see by plotting the data with the provided script. 14 | 15 | Notes: 16 | - It is tottaly fine to see error rates of <1 percent. 17 | - If you start seeing a high percentage of errors, it means the cluster has saturated and you need to reload the cluster using the `remote_start_cluster.sh` script. 18 | -------------------------------------------------------------------------------- /artifact_evaluation/cold_start_sweep/knative/.gitignore: -------------------------------------------------------------------------------- 1 | results -------------------------------------------------------------------------------- /artifact_evaluation/cold_start_sweep/knative/INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | ## Cold start sweep on Knative/K8s 2 | 3 | Time required: 10 min to set up environment and 2-3 min per data point 4 | 5 | Description: This experiment triggers cold start in Maestro cluster. You should sweep the load until the cluster saturates, which will be visible on the latency plot and should happen around 3 RPS. We suggest running experiments with 1, 2, 3 RPS and observing the latency after conducting experiment for each data point. Always discard the results of the first experiment when starting a new cluster, as these measurements include image pull latency, which pollutes the results. 6 | 7 | Instructions: 8 | - Start Knative/K8s cluster according to instructions located in the root folder of artifact evaluation instructions (`README.md`). You can reuse the existing cluster running Knative/K8s, but after executing the instructions below do not use such cluster for running Azure 500 trace again. 9 | - On `node0` execute the following commands: 10 | - Open `~/invitro/workloads/container/trace_func_go.yaml`, set `autoscaling.knative.dev/max-scale` to `1`, and then set image to `docker.io/cvetkovic/dirigent_empty_function:latest`. 11 | - Run `kubectl patch configmap config-autoscaler -n knative-serving -p '{"data":{"scale-to-zero-grace-period":"1s","scale-to-zero-pod-retention-period":"1s","stable-window":"6s"}}'` 12 | - In `~/invitro/cmd/config_knative_rps.json` set `ExperimentDuration` to 2 and `RpsColdStartRatioPercentage` to `100` 13 | - The command for running experiment for each data point is `cd ~/invitro; go run cmd/loader.go --config cmd/config_knative_rps.json`. Use the following data point settings in `cmd/config_knative_rps.json` for experiments. 14 | - `RpsTarget=1` with `RpsCooldownSeconds=10` 15 | - `RpsTarget=2` with `RpsCooldownSeconds=15` 16 | - `RpsTarget=3` with `RpsCooldownSeconds=20` 17 | - After each experiment copy results from `data/out/experiment_duration_2.csv` and save it to your local machine at `artifact_evaluation/cold_start_sweep/knative/results/rps_X.csv` -------------------------------------------------------------------------------- /artifact_evaluation/run_plotting_scripts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | python3 plot_azure_500.py 28 | python3 plot_cold_start_sweep.py -------------------------------------------------------------------------------- /artifact_evaluation/sample_results/azure_500_per_function_slowdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-easl/dirigent/9715b857aa096cb65f904aacaa5b74ba130519d2/artifact_evaluation/sample_results/azure_500_per_function_slowdown.png -------------------------------------------------------------------------------- /artifact_evaluation/sample_results/azure_500_scheduling_latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-easl/dirigent/9715b857aa096cb65f904aacaa5b74ba130519d2/artifact_evaluation/sample_results/azure_500_scheduling_latency.png -------------------------------------------------------------------------------- /artifact_evaluation/sample_results/cold_start_sweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-easl/dirigent/9715b857aa096cb65f904aacaa5b74ba130519d2/artifact_evaluation/sample_results/cold_start_sweep.png -------------------------------------------------------------------------------- /cmd/data_plane/config.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "127.0.0.1" 2 | controlPlaneAddress: "127.0.0.1:9090" 3 | portProxy: "8080" 4 | portGRPC: "8081" 5 | portProxyRead: "8082" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "random" 9 | async: false 10 | persistRequests: false 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "127.0.0.1:6379" 15 | replicas: "" 16 | password: "" 17 | db: 0 18 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/config_1.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "127.0.0.1" 2 | controlPlaneAddress: "127.0.0.1:9090,127.0.0.1:10000,127.0.0.1:10001" 3 | portProxy: "8080" 4 | portGRPC: "8081" 5 | portProxyRead: "8082" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "random" 9 | async: false 10 | persistRequests: false 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "127.0.0.1:6379" 15 | replicas: "" 16 | password: "" 17 | db: 0 18 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/config_2.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "127.0.0.1" 2 | controlPlaneAddress: "127.0.0.1:9090,127.0.0.1:10000,127.0.0.1:10001" 3 | portProxy: "11080" 4 | portGRPC: "11081" 5 | portProxyRead: "11082" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "random" 9 | async: false 10 | persistRequests: false 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "127.0.0.1:6379" 15 | replicas: "" 16 | password: "" 17 | db: 0 18 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/config_async.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "127.0.0.1" 2 | controlPlaneAddress: "localhost:9090" 3 | portProxy: "8080" 4 | portGRPC: "8081" 5 | portProxyRead: "8082" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "random" 9 | async: true 10 | persistRequests: true 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "127.0.0.1:6379" 15 | replicas: "" 16 | password: "" 17 | db: 0 18 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/config_cluster.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090" 3 | portProxy: "8080" 4 | portProxyRead: "8082" 5 | portGRPC: "8081" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "knative" 9 | async: false 10 | persistRequests: false 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "10.0.1.1:6379" 15 | replicas: "" 16 | password: "" 17 | db: 0 18 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/config_cluster_async.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090" 3 | portProxy: "8080" 4 | portProxyRead: "8082" 5 | portGRPC: "8081" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "knative" 9 | async: true 10 | persistRequests: true 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "10.0.1.1:6379" 15 | password: "" 16 | db: 0 17 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/config_cluster_raft.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090,10.0.1.3:10000,10.0.1.4:10001" 3 | portProxy: "8080" 4 | portProxyRead: "8082" 5 | portGRPC: "8081" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "knative" 9 | async: false 10 | persistRequests: false 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "10.0.1.1:6379" 15 | replicas: "" 16 | password: "" 17 | db: 0 18 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/config_raft.yaml: -------------------------------------------------------------------------------- 1 | dataPlaneIp: "127.0.0.1" 2 | controlPlaneAddress: "127.0.0.1:9090,127.0.0.1:10000,127.0.0.1:10001" 3 | portProxy: "8080" 4 | portGRPC: "8081" 5 | portProxyRead: "8082" 6 | verbosity: "trace" 7 | traceOutputFolder: "data" 8 | loadBalancingPolicy: "random" 9 | async: false 10 | persistRequests: false 11 | numberRetries: 3 12 | 13 | redis: 14 | address: "127.0.0.1:6379" 15 | replicas: "" 16 | password: "" 17 | db: 0 18 | fullPersistence: false -------------------------------------------------------------------------------- /cmd/data_plane/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package main 26 | 27 | import ( 28 | "cluster_manager/api" 29 | "cluster_manager/api/proto" 30 | "cluster_manager/internal/data_plane" 31 | "cluster_manager/pkg/config" 32 | "cluster_manager/pkg/grpc_helpers" 33 | "cluster_manager/pkg/logger" 34 | "cluster_manager/pkg/utils" 35 | "flag" 36 | "github.com/sirupsen/logrus" 37 | "google.golang.org/grpc" 38 | ) 39 | 40 | var ( 41 | configPath = flag.String("config", "cmd/data_plane/config.yaml", "Path to the configuration file") 42 | ) 43 | 44 | func main() { 45 | flag.Parse() 46 | 47 | logrus.Debugf("Configuration path is : %s", *configPath) 48 | 49 | cfg, err := config.ReadDataPlaneConfiguration(*configPath) 50 | if err != nil { 51 | logrus.Fatalf("Failed to read configuration file (error : %s)", err.Error()) 52 | } 53 | 54 | logger.SetupLogger(cfg.Verbosity) 55 | 56 | dataPlane := data_plane.NewDataplane(cfg) 57 | 58 | apiServer := api.NewDpApiServer(dataPlane) 59 | 60 | go grpc_helpers.CreateGRPCServer(cfg.PortGRPC, func(sr grpc.ServiceRegistrar) { 61 | proto.RegisterDpiInterfaceServer(sr, apiServer) 62 | }) 63 | 64 | proxyServer, err := dataPlane.GetProxyServer(cfg.Async) 65 | if err != nil { 66 | logrus.Fatalf("Failed to start proxy server (error : %s)", err.Error()) 67 | } 68 | 69 | go proxyServer.StartTracingService() 70 | go proxyServer.StartProxyServer() 71 | 72 | go dataPlane.SetupHeartbeatLoop(proxyServer) 73 | 74 | utils.WaitTerminationSignal(func() { 75 | dataPlane.DeregisterControlPlaneConnection() 76 | }) 77 | } 78 | -------------------------------------------------------------------------------- /cmd/flush/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package main 26 | 27 | import ( 28 | "cluster_manager/internal/control_plane/persistence" 29 | "cluster_manager/pkg/config" 30 | "context" 31 | ) 32 | 33 | func main() { 34 | client, err := persistence.CreateRedisClient(context.Background(), config.RedisConf{ 35 | Address: "localhost:6379", 36 | Password: "", 37 | Db: 0, 38 | }) 39 | 40 | err = client.RedisClient.FlushAll(context.Background()).Err() 41 | if err != nil { 42 | panic(err) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cmd/master_node/config.yaml: -------------------------------------------------------------------------------- 1 | port: "9090" 2 | replicas: "" 3 | registrationServer: "127.0.0.1:9091" 4 | registrationServerReplicas: "" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: false 9 | reconstruct: false 10 | 11 | # to use HAProxy load balancer put 127.0.0.1:8079, otherwise leave blank 12 | loadBalancerAddress: "127.0.0.1:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "127.0.0.1:6379" 25 | dockerAddress: "127.0.0.1:6379" 26 | password: "" 27 | db: 0 28 | fullPersistence: true 29 | 30 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/master_node/config_cluster.yaml: -------------------------------------------------------------------------------- 1 | port: "9090" 2 | replicas: "" 3 | registrationServer: "10.0.1.2:9091" 4 | registrationServerReplicas: "" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: true 9 | reconstruct: true 10 | 11 | # to use HAProxy load balancer put 10.0.1.254:8079, otherwise leave blank 12 | loadBalancerAddress: "10.0.1.254:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "10.0.1.2:6379" 25 | dockerAddress: "10.0.1.2:6379" 26 | replicas: "" 27 | password: "" 28 | db: 0 29 | fullPersistence: true 30 | 31 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/master_node/config_cluster_raft_1.yaml: -------------------------------------------------------------------------------- 1 | port: "9090" 2 | replicas: "10.0.1.3:10000,10.0.1.4:10001" 3 | registrationServer: "10.0.1.2:9091" 4 | registrationServerReplicas: "10.0.1.3:9091,10.0.1.4:9091" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: true 9 | reconstruct: true 10 | 11 | # to use HAProxy load balancer put 10.0.1.254:8079, otherwise leave blank 12 | loadBalancerAddress: "10.0.1.254:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "10.0.1.2:6379" 25 | dockerAddress: "10.0.1.2:6379" 26 | replicas: "10.0.1.3:6379,10.0.1.4:6379" 27 | password: "" 28 | db: 0 29 | fullPersistence: true 30 | 31 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/master_node/config_cluster_raft_2.yaml: -------------------------------------------------------------------------------- 1 | port: "10000" 2 | replicas: "10.0.1.2:9090,10.0.1.4:10001" 3 | registrationServer: "10.0.1.3:9091" 4 | registrationServerReplicas: "10.0.1.2:9091,10.0.1.4:9091" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: true 9 | reconstruct: true 10 | 11 | # to use HAProxy load balancer put 10.0.1.254:8079, otherwise leave blank 12 | loadBalancerAddress: "10.0.1.254:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "10.0.1.3:6379" 25 | dockerAddress: "10.0.1.3:6379" 26 | replicas: "10.0.1.2:6379,10.0.1.4:6379" 27 | password: "" 28 | db: 0 29 | fullPersistence: true 30 | 31 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/master_node/config_cluster_raft_3.yaml: -------------------------------------------------------------------------------- 1 | port: "10001" 2 | replicas: "10.0.1.2:9090,10.0.1.3:10000" 3 | registrationServer: "10.0.1.4:9091" 4 | registrationServerReplicas: "10.0.1.2:9091,10.0.1.3:9091" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: true 9 | reconstruct: true 10 | 11 | # to use HAProxy load balancer put 10.0.1.254:8079, otherwise leave blank 12 | loadBalancerAddress: "10.0.1.254:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "10.0.1.4:6379" 25 | dockerAddress: "10.0.1.4:6379" 26 | replicas: "10.0.1.2:6379,10.0.1.3:6379" 27 | password: "" 28 | db: 0 29 | fullPersistence: true 30 | 31 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/master_node/config_raft_1.yaml: -------------------------------------------------------------------------------- 1 | port: "9090" 2 | replicas: "127.0.0.1:10000,127.0.0.1:10001" 3 | registrationServer: "127.0.0.1:13091" 4 | registrationServerReplicas: "127.0.0.1:14091,127.0.0.1:15091" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: true 9 | reconstruct: true 10 | 11 | # to use HAProxy load balancer put 127.0.0.1:8079, otherwise leave blank 12 | loadBalancerAddress: "127.0.0.1:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "127.0.0.1:6380" 25 | dockerAddress: "redis_1:6379" 26 | replicas: "127.0.0.1:6381,127.0.0.1:6382" 27 | password: "" 28 | db: 0 29 | fullPersistence: true 30 | 31 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/master_node/config_raft_2.yaml: -------------------------------------------------------------------------------- 1 | port: "10000" 2 | replicas: "127.0.0.1:9090,127.0.0.1:10001" 3 | registrationServer: "127.0.0.1:14091" 4 | registrationServerReplicas: "127.0.0.1:13091,127.0.0.1:15091" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: true 9 | reconstruct: true 10 | 11 | # to use HAProxy load balancer put 127.0.0.1:8079, otherwise leave blank 12 | loadBalancerAddress: "127.0.0.1:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "127.0.0.1:6381" 25 | dockerAddress: "redis_2:6379" 26 | replicas: "127.0.0.1:6380,127.0.0.1:6382" 27 | password: "" 28 | db: 0 29 | fullPersistence: true 30 | 31 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/master_node/config_raft_3.yaml: -------------------------------------------------------------------------------- 1 | port: "10001" 2 | replicas: "127.0.0.1:9090,127.0.0.1:10000" 3 | registrationServer: "127.0.0.1:15091" 4 | registrationServerReplicas: "127.0.0.1:13091,127.0.0.1:14091" 5 | verbosity: "trace" 6 | traceOutputFolder: "data" 7 | placementPolicy: "random" 8 | persistence: true 9 | reconstruct: true 10 | 11 | # to use HAProxy load balancer put 127.0.0.1:8079, otherwise leave blank 12 | loadBalancerAddress: "127.0.0.1:8079" 13 | 14 | removeWorkerNode: false 15 | removeDataplane: false 16 | 17 | precreateSnapshots: false 18 | 19 | profiler: 20 | enable: false 21 | mutex: false 22 | 23 | redis: 24 | address: "127.0.0.1:6382" 25 | dockerAddress: "redis_3:6379" 26 | replicas: "127.0.0.1:6380,127.0.0.1:6381" 27 | password: "" 28 | db: 0 29 | fullPersistence: true 30 | 31 | endpointPersistence: false -------------------------------------------------------------------------------- /cmd/monitoring/monitoring.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import psutil 24 | import time 25 | 26 | # Function to write utilization data to a CSV file 27 | def write_utilization_to_csv(): 28 | with open("utilization.csv", "w") as file: 29 | # Write the CSV header 30 | file.write("Timestamp, CPUUtilization, memoryUtilization \n") 31 | 32 | while True: 33 | # Get the current Unix timestamp 34 | timestamp = int(time.time()) 35 | 36 | # Get the CPU utilization 37 | cpu_percent = psutil.cpu_percent(interval=1) 38 | 39 | # Get the memory utilization 40 | memory_percent = psutil.virtual_memory().percent 41 | 42 | # Append the utilization data to the CSV file 43 | with open("utilization.csv", "a") as file: 44 | file.write(f"{timestamp}, {cpu_percent}, {memory_percent}\n") 45 | 46 | time.sleep(1) # Sleep for 1 second 47 | 48 | if __name__ == "__main__": 49 | write_utilization_to_csv() 50 | -------------------------------------------------------------------------------- /cmd/worker_node/config.yaml: -------------------------------------------------------------------------------- 1 | workerNodeIp: "127.0.0.1" 2 | controlPlaneAddress: "127.0.0.1:9090" 3 | port: "10010" 4 | verbosity: "trace" 5 | criType: "containerd" 6 | criPath: "/run/containerd/containerd.sock" 7 | cniConfigPath: "configs/cni.conf" 8 | prefetchImage: false 9 | 10 | firecrackerKernel: "configs/firecracker/vmlinux-4.14.bin" 11 | firecrackerFileSystem: "configs/firecracker/rootfs.ext4" 12 | firecrackerInternalIPPrefix: "100" 13 | firecrackerExposedIPPrefix: "192.254" 14 | firecrackerVMDebugMode: false 15 | firecrackerUseSnapshots: true 16 | firecrackerNetworkPoolSize: 128 -------------------------------------------------------------------------------- /cmd/worker_node/config_cluster.yaml: -------------------------------------------------------------------------------- 1 | workerNodeIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090" 3 | port: "10010" 4 | verbosity: "trace" 5 | criType: "containerd" 6 | criPath: "/run/containerd/containerd.sock" 7 | cniConfigPath: "/cluster_manager/configs/cni.conf" 8 | prefetchImage: false 9 | 10 | firecrackerKernel: "/cluster_manager/configs/firecracker/vmlinux-4.14.bin" 11 | firecrackerFileSystem: "/cluster_manager/configs/firecracker/rootfs.ext4" 12 | firecrackerInternalIPPrefix: "100" 13 | firecrackerExposedIPPrefix: "192.254" 14 | firecrackerVMDebugMode: false 15 | firecrackerUseSnapshots: true 16 | firecrackerNetworkPoolSize: 256 -------------------------------------------------------------------------------- /cmd/worker_node/config_cluster_containerd.yaml: -------------------------------------------------------------------------------- 1 | workerNodeIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090" 3 | port: "10010" 4 | verbosity: "trace" 5 | criType: "containerd" 6 | criPath: "/run/containerd/containerd.sock" 7 | cniConfigPath: "configs/cni.conf" 8 | prefetchImage: false 9 | 10 | firecrackerKernel: "/cluster_manager/configs/firecracker/vmlinux-4.14.bin" 11 | firecrackerFileSystem: "/cluster_manager/configs/firecracker/rootfs.ext4" 12 | firecrackerInternalIPPrefix: "100" 13 | firecrackerExposedIPPrefix: "192.254" 14 | firecrackerVMDebugMode: false 15 | firecrackerUseSnapshots: true 16 | firecrackerNetworkPoolSize: 128 -------------------------------------------------------------------------------- /cmd/worker_node/config_cluster_fake_worker.yaml: -------------------------------------------------------------------------------- 1 | workerNodeIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090" 3 | port: "$DAEMON_PORT" 4 | verbosity: "trace" 5 | criType: "scalability_test" 6 | criPath: "/run/containerd/containerd.sock" 7 | cniConfigPath: "configs/cni.conf" 8 | prefetchImage: false 9 | 10 | firecrackerKernel: "/cluster_manager/configs/firecracker/vmlinux-4.14.bin" 11 | firecrackerFileSystem: "/cluster_manager/configs/firecracker/rootfs.ext4" 12 | firecrackerInternalIPPrefix: "100" 13 | firecrackerExposedIPPrefix: "192.254" 14 | firecrackerVMDebugMode: false 15 | firecrackerUseSnapshots: true 16 | firecrackerNetworkPoolSize: 128 -------------------------------------------------------------------------------- /cmd/worker_node/config_cluster_fake_worker_raft.yaml: -------------------------------------------------------------------------------- 1 | workerNodeIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090,10.0.1.3:10000,10.0.1.4:10001" 3 | port: "$DAEMON_PORT" 4 | verbosity: "trace" 5 | criType: "scalability_test" 6 | criPath: "/run/containerd/containerd.sock" 7 | cniConfigPath: "configs/cni.conf" 8 | prefetchImage: false 9 | 10 | firecrackerKernel: "/cluster_manager/configs/firecracker/vmlinux-4.14.bin" 11 | firecrackerFileSystem: "/cluster_manager/configs/firecracker/rootfs.ext4" 12 | firecrackerInternalIPPrefix: "100" 13 | firecrackerExposedIPPrefix: "192.254" 14 | firecrackerVMDebugMode: false 15 | firecrackerUseSnapshots: true 16 | firecrackerNetworkPoolSize: 128 -------------------------------------------------------------------------------- /cmd/worker_node/config_cluster_raft.yaml: -------------------------------------------------------------------------------- 1 | workerNodeIp: "dynamic" 2 | controlPlaneAddress: "10.0.1.2:9090,10.0.1.3:10000,10.0.1.4:10001" 3 | port: "10010" 4 | verbosity: "trace" 5 | criType: "containerd" 6 | criPath: "/run/containerd/containerd.sock" 7 | cniConfigPath: "/cluster_manager/configs/cni.conf" 8 | prefetchImage: false 9 | 10 | firecrackerKernel: "/cluster_manager/configs/firecracker/vmlinux-4.14.bin" 11 | firecrackerFileSystem: "/cluster_manager/configs/firecracker/rootfs.ext4" 12 | firecrackerInternalIPPrefix: "100" 13 | firecrackerExposedIPPrefix: "192.254" 14 | firecrackerVMDebugMode: false 15 | firecrackerUseSnapshots: true 16 | firecrackerNetworkPoolSize: 256 -------------------------------------------------------------------------------- /cmd/worker_node/config_raft.yaml: -------------------------------------------------------------------------------- 1 | workerNodeIp: "127.0.0.1" 2 | controlPlaneAddress: "127.0.0.1:9090,127.0.0.1:10000,127.0.0.1:10001" 3 | port: "10010" 4 | verbosity: "trace" 5 | criType: "containerd" 6 | criPath: "/run/containerd/containerd.sock" 7 | cniConfigPath: "configs/cni.conf" 8 | prefetchImage: false 9 | 10 | firecrackerKernel: "configs/firecracker/vmlinux-4.14.bin" 11 | firecrackerFileSystem: "configs/firecracker/rootfs.ext4" 12 | firecrackerInternalIPPrefix: "100" 13 | firecrackerExposedIPPrefix: "192.254" 14 | firecrackerVMDebugMode: false 15 | firecrackerUseSnapshots: true 16 | firecrackerNetworkPoolSize: 128 -------------------------------------------------------------------------------- /configs/check_apiserver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | errorExit() { 28 | echo "*** $*" 1>&2 29 | exit 1 30 | } 31 | 32 | curl --silent --max-time 2 --insecure http://localhost:8079/health -o /dev/null || errorExit "Error GET http://localhost:8079/health" 33 | if ip addr | grep -q 10.0.1.254; then 34 | curl --silent --max-time 2 --insecure http://10.0.1.254:8079/health -o /dev/null || errorExit "Error GET http://10.0.1.254:8079/health" 35 | fi -------------------------------------------------------------------------------- /configs/cni.conf: -------------------------------------------------------------------------------- 1 | { 2 | "cniVersion": "0.3.1", 3 | "name": "mynet", 4 | "type": "bridge", 5 | "bridge": "cni0", 6 | "isGateway": true, 7 | "ipMasq": true, 8 | "ipam": { 9 | "type": "host-local", 10 | "subnet": "100.22.0.0/16", 11 | "routes": [ 12 | { "dst": "0.0.0.0/0" } 13 | ] 14 | } 15 | } -------------------------------------------------------------------------------- /configs/fcnet.conflist: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fcnet", 3 | "cniVersion": "0.4.0", 4 | "plugins": [ 5 | { 6 | "type": "ptp", 7 | "ipMasq": true, 8 | "ipam": { 9 | "type": "host-local", 10 | "subnet": "192.168.127.0/24", 11 | "resolvConf": "/etc/resolv.conf" 12 | } 13 | }, 14 | { 15 | "type": "tc-redirect-tap" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /configs/firecracker/openrc-service.sh: -------------------------------------------------------------------------------- 1 | #!/sbin/openrc-run 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | name=$RC_SVCNAME 28 | description="Function agent" 29 | supervisor="supervise-daemon" 30 | command="/usr/local/bin/agent" 31 | pidfile="/run/agent.pid" 32 | command_user="root:root" 33 | output_log="/tmp/agent.log" 34 | error_log="/tmp/agent.err" 35 | depend() { 36 | after net 37 | } -------------------------------------------------------------------------------- /configs/firecracker/rootfs.ext4: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8bd5b62c13df8431088b624b7315b8b473c7c2840a087c08016fe2db688586aa 3 | size 67108864 4 | -------------------------------------------------------------------------------- /configs/firecracker/setup-alpine.sh: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2024 EASL 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | apk add --no-cache openrc 26 | apk add --no-cache util-linux 27 | apk add --no-cache openssh 28 | 29 | # might remove for benchmark 30 | ln -s agetty /etc/init.d/agetty.ttyS0 31 | echo ttyS0 > /etc/securetty 32 | rc-update add agetty.ttyS0 default 33 | 34 | # might remove for benchmark 35 | echo "root:root" | chpasswd 36 | 37 | # might remove for benchmark? 38 | echo "nameserver 1.1.1.1" >>/etc/resolv.conf 39 | 40 | addgroup -g 1000 -S agentUser && adduser -u 1000 -S agentUser -G agentUser 41 | 42 | chown agentUser:agentUser /etc/init.d/agent 43 | chmod u+x /etc/init.d/agent 44 | chown agentUser:agentUser /usr/local/bin/agent 45 | chmod u+x /usr/local/bin/agent 46 | 47 | rc-update add devfs boot 48 | rc-update add procfs boot 49 | rc-update add sysfs boot 50 | 51 | rc-update add agent boot 52 | 53 | # for extracting logs with scp 54 | # rc-update add sshd 55 | # echo "PermitRootLogin yes" >> /etc/ssh/sshd_config 56 | 57 | 58 | # Copy the configured system to the rootfs image 59 | for d in bin etc lib root sbin usr; do tar c "/$d" | tar x -C /rootfs; done 60 | for dir in dev proc run sys var tmp; do mkdir /rootfs/${dir}; done 61 | 62 | chmod 1777 /rootfs/tmp 63 | mkdir -p /rootfs/home/agentUser/ 64 | chown 1000:1000 /rootfs/home/agentUser/ 65 | -------------------------------------------------------------------------------- /configs/firecracker/vmlinux-4.14.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:882fa465c43ab7d92e31bd4167da3ad6a82cb9230f9b0016176df597c6014cef 3 | size 21266136 4 | -------------------------------------------------------------------------------- /configs/firecracker/vmlinux-5.10.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d63474d9d2be88c901e0c3a60e81667e743f0d2370b4ae83e038f23299d2df40 3 | size 45608448 4 | -------------------------------------------------------------------------------- /configs/firecracker/vmlinux-6.1.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2b0a77f65666d15e36cfd31d67d086d284abef5e67fbaf37bcae8f77a9f2c71b 3 | size 47958448 4 | -------------------------------------------------------------------------------- /configs/haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | log /dev/log local0 3 | log /dev/log local1 notice 4 | daemon 5 | stats socket /run/haproxy/admin.sock mode 660 level admin 6 | maxconn 60000 7 | 8 | defaults 9 | mode http 10 | log global 11 | option httplog 12 | option dontlognull 13 | option http-server-close 14 | option forwardfor except 127.0.0.0/8 15 | option redispatch 16 | 17 | retries 3 18 | timeout connect 10s 19 | 20 | timeout http-request 900s 21 | timeout queue 60s 22 | timeout client 900s 23 | timeout server 900s 24 | timeout http-keep-alive 60s 25 | timeout check 5s 26 | 27 | frontend dirigent_data_planes 28 | bind *:8079 29 | mode http 30 | option tcplog 31 | default_backend dirigent_data_planes 32 | 33 | frontend dirigent_registration_server 34 | bind *:9092 35 | mode http 36 | option tcplog 37 | default_backend dirigent_registration_server 38 | 39 | backend dirigent_data_planes 40 | option httpchk GET /health 41 | http-check expect status 200 42 | mode http 43 | balance hdr(host) 44 | http-reuse always 45 | 46 | backend dirigent_registration_server 47 | option httpchk GET /health 48 | http-check expect status 200 49 | mode http 50 | balance hdr(host) 51 | http-reuse always 52 | -------------------------------------------------------------------------------- /configs/keepalived.conf: -------------------------------------------------------------------------------- 1 | ! /etc/keepalived/keepalived.conf 2 | ! Configuration File for keepalived 3 | global_defs { 4 | router_id LVS_DEVEL 5 | } 6 | 7 | vrrp_script check_apiserver { 8 | script "/etc/keepalived/check_apiserver.sh" 9 | interval 5 10 | weight -2 11 | fall 3 12 | rise 1 13 | } 14 | 15 | vrrp_instance VI_1 { 16 | state MASTER 17 | interface $INTERFACE_NAME 18 | virtual_router_id 51 19 | priority 101 20 | authentication { 21 | auth_type PASS 22 | auth_pass 42 23 | } 24 | virtual_ipaddress { 25 | 10.0.1.253 26 | 10.0.1.254 27 | } 28 | track_script { 29 | check_apiserver 30 | } 31 | } -------------------------------------------------------------------------------- /configs/substitute_interface.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | readonly DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | 29 | export INTERFACE_NAME=$(ifconfig | grep -B1 "10.0.1" | head -n1 | sed 's/:.*//') 30 | 31 | cat $DIR/keepalived.conf | envsubst > $DIR/keepalived.conff 32 | 33 | echo "Successfully created HA load balancer configuration!" -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | redis: 3 | image: redis 4 | ports: 5 | - "6379:6379" 6 | 7 | redis_1: 8 | image: redis:latest 9 | hostname: redis_1 10 | volumes: 11 | - redis_1:/data 12 | ports: 13 | - '6380:6379' 14 | 15 | redis_2: 16 | image: redis:latest 17 | hostname: redis_2 18 | volumes: 19 | - redis_2:/data 20 | ports: 21 | - '6381:6379' 22 | 23 | redis_3: 24 | image: redis:latest 25 | hostname: redis_3 26 | volumes: 27 | - redis_3:/data 28 | ports: 29 | - '6382:6379' 30 | 31 | volumes: 32 | redis_1: 33 | redis_2: 34 | redis_3: 35 | -------------------------------------------------------------------------------- /docs/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-easl/dirigent/9715b857aa096cb65f904aacaa5b74ba130519d2/docs/architecture.png -------------------------------------------------------------------------------- /docs/firecracker.md: -------------------------------------------------------------------------------- 1 | Kernel compilation and image building: 2 | - https://gruchalski.com/posts/2021-02-06-taking-firecracker-for-a-spin/ 3 | - https://github.com/firecracker-microvm/firecracker/blob/main/docs/rootfs-and-kernel-setup.md -------------------------------------------------------------------------------- /internal/control_plane/autoscaling/controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package autoscaling 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "github.com/stretchr/testify/assert" 30 | "testing" 31 | "time" 32 | ) 33 | 34 | func getScalingChannel() chan int { 35 | return make(chan int) 36 | } 37 | 38 | func getServiceInfo() *proto.ServiceInfo { 39 | return &proto.ServiceInfo{ 40 | Name: "mockService", 41 | Image: "", 42 | PortForwarding: nil, 43 | AutoscalingConfig: &proto.AutoscalingConfiguration{ 44 | ScalingUpperBound: 1, 45 | ScalingLowerBound: 0, 46 | PanicThresholdPercentage: 0, 47 | MaxScaleUpRate: 0, 48 | MaxScaleDownRate: 0, 49 | ContainerConcurrency: 0, 50 | ContainerConcurrencyTargetPercentage: 0, 51 | StableWindowWidthSeconds: 0, 52 | PanicWindowWidthSeconds: 0, 53 | ScalingPeriodSeconds: 0, 54 | }, 55 | } 56 | } 57 | 58 | func TestSimpleController(t *testing.T) { 59 | scalingChannel := getScalingChannel() 60 | serviceInfo := getServiceInfo() 61 | 62 | pfStateController := NewPerFunctionStateController(scalingChannel, serviceInfo, time.Millisecond*100) 63 | 64 | assert.True(t, pfStateController.Start(), "Start should return true") 65 | } 66 | 67 | func TestMultipleStarts(t *testing.T) { 68 | scalingChannel := getScalingChannel() 69 | serviceInfo := getServiceInfo() 70 | 71 | pfStateController := NewPerFunctionStateController(scalingChannel, serviceInfo, time.Millisecond*100) 72 | assert.True(t, pfStateController.Start(), "Start should return true") 73 | for i := 0; i < 10000; i++ { 74 | assert.False(t, pfStateController.Start(), "Start should return false") 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /internal/control_plane/core/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package core 26 | 27 | import "cluster_manager/pkg/tracing" 28 | 29 | type DataplaneFactory func(string, string, string) DataPlaneInterface 30 | 31 | type WorkerNodeConfiguration struct { 32 | Name string 33 | IP string 34 | Port string 35 | CpuCores uint64 36 | Memory uint64 37 | } 38 | 39 | type WorkerNodeFactory func(configuration WorkerNodeConfiguration) WorkerNodeInterface 40 | 41 | type Endpoint struct { 42 | SandboxID string 43 | URL string 44 | Node WorkerNodeInterface 45 | HostPort int32 46 | CreationHistory tracing.ColdStartLogEntry 47 | } 48 | -------------------------------------------------------------------------------- /internal/control_plane/data_plane/data_plane_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package data_plane 26 | 27 | import ( 28 | "cluster_manager/internal/control_plane/core" 29 | "cluster_manager/internal/control_plane/workers" 30 | "github.com/stretchr/testify/assert" 31 | "testing" 32 | "time" 33 | ) 34 | 35 | func TestDataPlaneCreation(t *testing.T) { 36 | conf := core.WorkerNodeConfiguration{ 37 | Name: "mockName", 38 | IP: "mockIp", 39 | Port: "100", 40 | CpuCores: 10, 41 | Memory: 10, 42 | } 43 | 44 | wn := workers.NewWorkerNode(conf) 45 | 46 | assert.Equal(t, wn.GetName(), conf.Name) 47 | assert.Equal(t, wn.GetIP(), conf.IP) 48 | assert.Equal(t, wn.GetPort(), conf.Port) 49 | assert.Equal(t, wn.GetCpuCores(), conf.CpuCores) 50 | assert.Equal(t, wn.GetMemory(), conf.Memory) 51 | 52 | wn.UpdateLastHearBeat() 53 | 54 | assert.True(t, time.Since(wn.GetLastHeartBeat()) < time.Second) 55 | } 56 | -------------------------------------------------------------------------------- /internal/control_plane/eviction_policy/eviction_policy.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package eviction_policy 26 | 27 | import ( 28 | "cluster_manager/internal/control_plane/core" 29 | "math/rand" 30 | ) 31 | 32 | func EvictionPolicy(endpoint []*core.Endpoint) (*core.Endpoint, []*core.Endpoint) { 33 | if len(endpoint) == 0 { 34 | return nil, []*core.Endpoint{} 35 | } 36 | 37 | index := rand.Intn(len(endpoint)) 38 | 39 | var newEndpointList []*core.Endpoint 40 | 41 | for i := 0; i < len(endpoint); i++ { 42 | if i != index { 43 | newEndpointList = append(newEndpointList, endpoint[i]) 44 | } 45 | } 46 | 47 | return endpoint[index], newEndpointList 48 | } 49 | -------------------------------------------------------------------------------- /internal/control_plane/eviction_policy/eviction_policy_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package eviction_policy 26 | 27 | import ( 28 | "cluster_manager/internal/control_plane/core" 29 | "cluster_manager/pkg/tracing" 30 | "github.com/stretchr/testify/assert" 31 | "testing" 32 | ) 33 | 34 | func TestEvictionPolicyEmpty(t *testing.T) { 35 | emptyList := make([]*core.Endpoint, 0) 36 | 37 | toEvict, currentState := EvictionPolicy(emptyList) 38 | 39 | assert.Nil(t, toEvict, "Evicted point should be nil") 40 | assert.Len(t, currentState, 0, "No object should ne present in the list") 41 | } 42 | 43 | func TestEvictionPolicy(t *testing.T) { 44 | list := make([]*core.Endpoint, 0) 45 | 46 | list = append(list, &core.Endpoint{ 47 | SandboxID: "", 48 | URL: "", 49 | Node: nil, 50 | HostPort: 0, 51 | CreationHistory: tracing.ColdStartLogEntry{}, 52 | }) 53 | 54 | list = append(list, &core.Endpoint{ 55 | SandboxID: "", 56 | URL: "", 57 | Node: nil, 58 | HostPort: 0, 59 | CreationHistory: tracing.ColdStartLogEntry{}, 60 | }) 61 | 62 | list = append(list, &core.Endpoint{ 63 | SandboxID: "", 64 | URL: "", 65 | Node: nil, 66 | HostPort: 0, 67 | CreationHistory: tracing.ColdStartLogEntry{}, 68 | }) 69 | 70 | toEvict, currentState := EvictionPolicy(list) 71 | 72 | assert.NotNil(t, toEvict, "Evicted point should not be nil") 73 | assert.Len(t, currentState, 2, "Two objects should be present in the list") 74 | } 75 | -------------------------------------------------------------------------------- /internal/control_plane/leader_election/state.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package leader_election 26 | 27 | import "github.com/sirupsen/logrus" 28 | 29 | type CMState int 30 | 31 | const ( 32 | Follower CMState = iota 33 | Candidate 34 | Leader 35 | Dead 36 | ) 37 | 38 | func (s CMState) String() string { 39 | switch s { 40 | case Follower: 41 | return "Follower" 42 | case Candidate: 43 | return "Candidate" 44 | case Leader: 45 | return "Leader" 46 | case Dead: 47 | return "Dead" 48 | default: 49 | logrus.Fatal("Invalid leader election state machine state") 50 | } 51 | 52 | return "" 53 | } 54 | -------------------------------------------------------------------------------- /internal/control_plane/persistence/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package persistence 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "cluster_manager/internal/control_plane/core" 30 | "context" 31 | ) 32 | 33 | type PersistenceLayer interface { 34 | StoreDataPlaneInformation(ctx context.Context, dataplaneInfo *proto.DataplaneInformation) error 35 | DeleteDataPlaneInformation(ctx context.Context, dataplaneInfo *proto.DataplaneInformation) error 36 | GetDataPlaneInformation(ctx context.Context) ([]*proto.DataplaneInformation, error) 37 | StoreWorkerNodeInformation(ctx context.Context, workerNodeInfo *proto.WorkerNodeInformation) error 38 | DeleteWorkerNodeInformation(ctx context.Context, name string) error 39 | GetWorkerNodeInformation(ctx context.Context) ([]*proto.WorkerNodeInformation, error) 40 | StoreServiceInformation(ctx context.Context, serviceInfo *proto.ServiceInfo) error 41 | DeleteServiceInformation(ctx context.Context, serviceInfo *proto.ServiceInfo) error 42 | GetServiceInformation(ctx context.Context) ([]*proto.ServiceInfo, error) 43 | SetLeader(ctx context.Context) error 44 | StoreEndpoint(ctx context.Context, endpoint core.Endpoint) error 45 | } 46 | -------------------------------------------------------------------------------- /internal/control_plane/placement_policy/k8s_placement_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package placement_policy 26 | 27 | import ( 28 | "testing" 29 | 30 | "github.com/stretchr/testify/assert" 31 | ) 32 | 33 | func TestLeastAllocated(t *testing.T) { 34 | // values taken from k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources:690 35 | request := ExtendCPU(CreateResourceMap(1000, 2000)) 36 | n1_occupied := ExtendCPU(CreateResourceMap(2000, 4000)) 37 | n2_occupied := ExtendCPU(CreateResourceMap(1000, 2000)) 38 | n1_capacity := ExtendCPU(CreateResourceMap(4000, 10000)) 39 | n2_capacity := ExtendCPU(CreateResourceMap(6000, 10000)) 40 | 41 | n1_score := ScoreFitLeastAllocated(*n1_capacity, *SumResources(request, n1_occupied)) 42 | n2_score := ScoreFitLeastAllocated(*n2_capacity, *SumResources(request, n2_occupied)) 43 | 44 | assert.True(t, n1_score == 32 && n2_score == 63, "Least allocated scoring test failed.") 45 | } 46 | 47 | func TestBalancedAllocation(t *testing.T) { 48 | request := ExtendCPU(CreateResourceMap(3000, 5000)) 49 | n1_occupied := ExtendCPU(CreateResourceMap(3000, 0)) 50 | n2_occupied := ExtendCPU(CreateResourceMap(3000, 5000)) 51 | n1_capacity := ExtendCPU(CreateResourceMap(10000, 20000)) 52 | n2_capacity := ExtendCPU(CreateResourceMap(10000, 50000)) 53 | 54 | n1_score := ScoreBalancedAllocation(*n1_capacity, *SumResources(request, n1_occupied)) 55 | n2_score := ScoreBalancedAllocation(*n2_capacity, *SumResources(request, n2_occupied)) 56 | 57 | assert.True(t, n1_score == 82 && n2_score == 80, "Least allocated scoring test failed.") 58 | } 59 | -------------------------------------------------------------------------------- /internal/control_plane/placement_policy/random.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package placement_policy 26 | 27 | import ( 28 | "cluster_manager/internal/control_plane/core" 29 | "cluster_manager/pkg/synchronization" 30 | "math/rand" 31 | ) 32 | 33 | type Random struct{} 34 | 35 | func NewRandomPlacement() *Random { 36 | return &Random{} 37 | } 38 | 39 | func (p *Random) Place(storage synchronization.SyncStructure[string, core.WorkerNodeInterface], _ *ResourceMap) core.WorkerNodeInterface { 40 | schedulable := getSchedulableNodes(storage.GetValues()) 41 | 42 | if len(schedulable) != 0 { 43 | return schedulable[rand.Intn(len(schedulable))] 44 | } else { 45 | return nil 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /internal/control_plane/placement_policy/resource_map_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package placement_policy 26 | 27 | import ( 28 | "testing" 29 | 30 | "github.com/stretchr/testify/assert" 31 | ) 32 | 33 | const ( 34 | mockCpus uint64 = 4 35 | mockCpus2 uint64 = 8 36 | mockMemory uint64 = 10 37 | mockMemory2 uint64 = 20 38 | mockSumCpu uint64 = 12 39 | mockSumMemory uint64 = 30 40 | ) 41 | 42 | func TestResourceMap(t *testing.T) { 43 | resourceMap := CreateResourceMap(mockCpus, mockMemory) 44 | 45 | assert.Equal(t, resourceMap.GetCPUCores(), mockCpus, "Cpu cores should be the same") 46 | assert.Equal(t, resourceMap.GetMemory(), mockMemory, "Memory should be the same") 47 | 48 | resourceMap.SetCPUCores(mockCpus2) 49 | resourceMap.SetMemory(mockMemory2) 50 | 51 | assert.Equal(t, resourceMap.GetCPUCores(), mockCpus2, "Cpu cores should be the same") 52 | assert.Equal(t, resourceMap.GetMemory(), mockMemory2, "Memory should be the same") 53 | 54 | assert.Equal(t, resourceMap.SumAllResourceTypes(), mockCpus2+mockMemory2) 55 | } 56 | 57 | func TestSumResources(t *testing.T) { 58 | resourceMap1 := CreateResourceMap(mockCpus, mockMemory) 59 | resourceMap2 := CreateResourceMap(mockCpus2, mockMemory2) 60 | sumResourceMap := SumResources(resourceMap1, resourceMap2) 61 | assert.Equal(t, sumResourceMap, CreateResourceMap(mockSumCpu, mockSumMemory)) 62 | } 63 | 64 | func TestSubtractResource(t *testing.T) { 65 | resourceMap1 := CreateResourceMap(mockCpus2, mockMemory2) 66 | resourceMap2 := CreateResourceMap(mockCpus, mockMemory) 67 | sumResourceMap := SubtractResources(resourceMap1, resourceMap2) 68 | assert.Equal(t, sumResourceMap, resourceMap2) 69 | } 70 | -------------------------------------------------------------------------------- /internal/control_plane/placement_policy/round_robin.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package placement_policy 26 | 27 | import ( 28 | "cluster_manager/internal/control_plane/core" 29 | "cluster_manager/pkg/synchronization" 30 | "sync/atomic" 31 | ) 32 | 33 | type RoundRobinPlacement struct { 34 | schedulingCounterRoundRobin int32 35 | } 36 | 37 | func NewRoundRobinPlacement() *RoundRobinPlacement { 38 | return &RoundRobinPlacement{ 39 | schedulingCounterRoundRobin: 0, 40 | } 41 | } 42 | 43 | func (policy *RoundRobinPlacement) Place(storage synchronization.SyncStructure[string, core.WorkerNodeInterface], _ *ResourceMap) core.WorkerNodeInterface { 44 | schedulable := getSchedulableNodes(storage.GetValues()) 45 | if len(schedulable) == 0 { 46 | return nil 47 | } 48 | 49 | var index int32 50 | swapped := false 51 | for !swapped { 52 | index = atomic.LoadInt32(&policy.schedulingCounterRoundRobin) % int32(len(schedulable)) 53 | newIndex := (index + 1) % int32(len(schedulable)) 54 | 55 | swapped = atomic.CompareAndSwapInt32(&policy.schedulingCounterRoundRobin, index, newIndex) 56 | } 57 | 58 | return schedulable[index] 59 | } 60 | -------------------------------------------------------------------------------- /internal/control_plane/workers/empty_worker/empty_interface_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package empty_worker 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "context" 30 | "google.golang.org/grpc" 31 | "google.golang.org/protobuf/types/known/emptypb" 32 | ) 33 | 34 | type emptyInterfaceClient struct { 35 | } 36 | 37 | func NewEmptyInterfaceClient() proto.WorkerNodeInterfaceClient { 38 | return &emptyInterfaceClient{} 39 | } 40 | 41 | func (e emptyInterfaceClient) CreateSandbox(ctx context.Context, in *proto.ServiceInfo, opts ...grpc.CallOption) (*proto.SandboxCreationStatus, error) { 42 | return &proto.SandboxCreationStatus{ 43 | Success: true, 44 | }, nil 45 | } 46 | 47 | func (e emptyInterfaceClient) DeleteSandbox(ctx context.Context, in *proto.SandboxID, opts ...grpc.CallOption) (*proto.ActionStatus, error) { 48 | return &proto.ActionStatus{ 49 | Success: true, 50 | }, nil 51 | } 52 | 53 | func (e emptyInterfaceClient) ListEndpoints(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*proto.EndpointsList, error) { 54 | return &proto.EndpointsList{}, nil 55 | } 56 | -------------------------------------------------------------------------------- /internal/control_plane/workers/worker_node_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package workers 26 | 27 | import ( 28 | "cluster_manager/internal/control_plane/data_plane" 29 | "github.com/stretchr/testify/assert" 30 | "testing" 31 | ) 32 | 33 | func TestWorkerNodeCreation(t *testing.T) { 34 | mockIp := "mockIp" 35 | mockAPI := "mockAPI" 36 | mockProxy := "mockProxy" 37 | 38 | dataPlane := data_plane.NewDataplaneConnection(mockIp, mockAPI, mockProxy) 39 | 40 | assert.Equal(t, mockIp, dataPlane.GetIP()) 41 | assert.Equal(t, mockAPI, dataPlane.GetApiPort()) 42 | assert.Equal(t, mockProxy, dataPlane.GetProxyPort()) 43 | } 44 | -------------------------------------------------------------------------------- /internal/data_plane/data_plane_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package data_plane 26 | 27 | import ( 28 | "cluster_manager/pkg/config" 29 | "github.com/stretchr/testify/assert" 30 | "go.uber.org/mock/gomock" 31 | "testing" 32 | ) 33 | 34 | func TestCreationWorkerNode(t *testing.T) { 35 | ctrl := gomock.NewController(t) 36 | defer ctrl.Finish() 37 | 38 | mockConfig := config.DataPlaneConfig{ 39 | ControlPlaneAddress: []string{""}, 40 | PortProxy: "", 41 | PortGRPC: "", 42 | Verbosity: "", 43 | TraceOutputFolder: "", 44 | LoadBalancingPolicy: "", 45 | } 46 | 47 | assert.NotNil(t, NewDataplane(mockConfig), "Generated dataplane should not be nil") 48 | } 49 | -------------------------------------------------------------------------------- /internal/data_plane/proxy/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package proxy 26 | 27 | import ( 28 | "cluster_manager/internal/data_plane/function_metadata" 29 | "encoding/json" 30 | "net/http" 31 | ) 32 | 33 | func CreateMetricsHandler(deployments *function_metadata.Deployments) func(writer http.ResponseWriter, r *http.Request) { 34 | return func(writer http.ResponseWriter, r *http.Request) { 35 | var statistics *function_metadata.FunctionStatistics 36 | 37 | service := r.URL.Query().Get("service") 38 | if service == "" { 39 | statistics = function_metadata.AggregateStatistics(deployments.ListDeployments()) 40 | } else { 41 | metadata, _ := deployments.GetDeployment(service) 42 | if metadata == nil { 43 | writer.WriteHeader(http.StatusBadRequest) 44 | return 45 | } 46 | 47 | statistics = metadata.GetStatistics() 48 | } 49 | 50 | data, err := json.Marshal(*statistics) 51 | if err != nil { 52 | writer.WriteHeader(http.StatusInternalServerError) 53 | return 54 | } 55 | 56 | _, _ = writer.Write(data) 57 | writer.WriteHeader(http.StatusOK) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /internal/data_plane/proxy/net/buffer_pool.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package net 26 | 27 | import ( 28 | "net/http/httputil" 29 | "sync" 30 | ) 31 | 32 | type bufferPool struct { 33 | pool *sync.Pool 34 | } 35 | 36 | // NewBufferPool creates a new BufferPool. This is only safe to use in the context 37 | // of a httputil.ReverseProxy, as the buffers returned via Put are not cleaned 38 | // explicitly. 39 | func NewBufferPool() httputil.BufferPool { 40 | return &bufferPool{ 41 | // We don't use the New function of sync.Pool here to avoid an unnecessary 42 | // allocation when creating the slices. They are implicitly created in the 43 | // Get function below. 44 | pool: &sync.Pool{}, 45 | } 46 | } 47 | 48 | func (b *bufferPool) Get() []byte { 49 | buf := b.pool.Get() 50 | if buf == nil { 51 | // Use the default buffer size as defined in the ReverseProxy itself. 52 | return make([]byte, 32*1024) 53 | } 54 | 55 | buffer, ok := buf.(*[]byte) 56 | if !ok { 57 | panic("Failed to get buffer") // TODO: François Costa, is it the best way of doing? 58 | } 59 | 60 | return *buffer 61 | } 62 | 63 | // Put returns the given Buffer to the bufferPool. 64 | func (b *bufferPool) Put(buffer []byte) { 65 | b.pool.Put(&buffer) 66 | } 67 | -------------------------------------------------------------------------------- /internal/data_plane/proxy/persistence/empty_persistence.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package request_persistence 26 | 27 | import ( 28 | "cluster_manager/internal/data_plane/proxy/requests" 29 | "context" 30 | "time" 31 | ) 32 | 33 | type emptyRequestPersistence struct { 34 | } 35 | 36 | func CreateEmptyRequestPersistence() RequestPersistence { 37 | return &emptyRequestPersistence{} 38 | } 39 | 40 | func (empty *emptyRequestPersistence) PersistBufferedRequest(ctx context.Context, request *requests.BufferedRequest) (error, time.Duration, time.Duration) { 41 | return nil, 0, 0 42 | } 43 | 44 | func (empty *emptyRequestPersistence) PersistBufferedResponse(ctx context.Context, response *requests.BufferedResponse) error { 45 | return nil 46 | } 47 | 48 | func (empty *emptyRequestPersistence) ScanBufferedRequests(ctx context.Context) ([]*requests.BufferedRequest, error) { 49 | return make([]*requests.BufferedRequest, 0), nil 50 | } 51 | 52 | func (empty *emptyRequestPersistence) ScanBufferedResponses(ctx context.Context) ([]*requests.BufferedResponse, error) { 53 | return make([]*requests.BufferedResponse, 0), nil 54 | } 55 | 56 | func (empty *emptyRequestPersistence) DeleteBufferedRequest(ctx context.Context, code string) error { 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /internal/data_plane/proxy/persistence/request_persistence.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package request_persistence 26 | 27 | import ( 28 | "cluster_manager/internal/data_plane/proxy/requests" 29 | "context" 30 | "time" 31 | ) 32 | 33 | type RequestPersistence interface { 34 | PersistBufferedRequest(ctx context.Context, request *requests.BufferedRequest) (error, time.Duration, time.Duration) 35 | PersistBufferedResponse(ctx context.Context, response *requests.BufferedResponse) error 36 | ScanBufferedRequests(ctx context.Context) ([]*requests.BufferedRequest, error) 37 | ScanBufferedResponses(ctx context.Context) ([]*requests.BufferedResponse, error) 38 | DeleteBufferedRequest(ctx context.Context, code string) error 39 | } 40 | -------------------------------------------------------------------------------- /internal/data_plane/proxy/proxy.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package proxy 26 | 27 | import "cluster_manager/api/proto" 28 | 29 | type Proxy interface { 30 | StartProxyServer() 31 | StartTracingService() 32 | 33 | GetCpApiServer() proto.CpiInterfaceClient 34 | SetCpApiServer(client proto.CpiInterfaceClient) 35 | } 36 | -------------------------------------------------------------------------------- /internal/data_plane/proxy/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package proxy 26 | 27 | import ( 28 | common "cluster_manager/internal/data_plane/function_metadata" 29 | "net/http" 30 | "sync/atomic" 31 | ) 32 | 33 | func GetServiceName(r *http.Request) string { 34 | // provided by the gRPC client through WithAuthority(...) call 35 | return r.Host 36 | } 37 | 38 | func giveBackCCCapacity(endpoint *common.UpstreamEndpoint) { 39 | endpointInflight := atomic.AddInt32(&endpoint.InFlight, -1) 40 | if atomic.LoadInt32(&endpoint.Drained) != 0 && endpointInflight == 0 { 41 | endpoint.DrainingCallback <- struct{}{} 42 | } 43 | 44 | if endpoint.Capacity != nil { 45 | endpoint.Capacity <- struct{}{} 46 | } 47 | } 48 | 49 | func contextTerminationHandler(r *http.Request, coldStartChannel chan common.ColdStartChannelStruct) { 50 | select { 51 | case <-r.Context().Done(): 52 | if coldStartChannel != nil { 53 | coldStartChannel <- common.ColdStartChannelStruct{ 54 | Outcome: common.CanceledColdStart, 55 | AddEndpointDuration: 0, 56 | } 57 | } 58 | } 59 | } 60 | 61 | func HealthHandler(writer http.ResponseWriter, _ *http.Request) { 62 | writer.WriteHeader(http.StatusOK) 63 | } 64 | -------------------------------------------------------------------------------- /internal/worker_node/managers/exponential_backoff.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import "math" 28 | 29 | type ExponentialBackoff struct { 30 | // interval * exponential_rate ^ retry_number 31 | Interval float64 32 | ExponentialRate float64 33 | RetryNumber float64 34 | 35 | MaxDifference float64 36 | } 37 | 38 | func (eb *ExponentialBackoff) calculate(retry float64) float64 { 39 | return eb.Interval * math.Pow(eb.ExponentialRate, retry) 40 | } 41 | 42 | func (eb *ExponentialBackoff) Next() float64 { 43 | if eb.RetryNumber == 0 { 44 | eb.RetryNumber += 1 45 | 46 | return eb.calculate(0) 47 | } else { 48 | oldValue := eb.calculate(eb.RetryNumber) 49 | newValue := eb.calculate(eb.RetryNumber + 1) 50 | eb.RetryNumber += 1 51 | 52 | if math.Abs(newValue-oldValue) > eb.MaxDifference { 53 | return -1 54 | } else { 55 | return newValue 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /internal/worker_node/managers/exponential_backoff_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import ( 28 | "fmt" 29 | "math" 30 | "testing" 31 | ) 32 | 33 | func TestExponentialBackoff(t *testing.T) { 34 | eb := &ExponentialBackoff{ 35 | Interval: 0.01, 36 | ExponentialRate: 1.35, 37 | RetryNumber: 0, 38 | MaxDifference: 2, 39 | } 40 | 41 | dataPoints := 20 42 | 43 | var res []float64 44 | for i := 0; i < dataPoints; i++ { 45 | res = append(res, eb.Next()) 46 | fmt.Println(i+1, ": ", res[i]) 47 | } 48 | 49 | for i := 0; i < dataPoints-1; i++ { 50 | if math.Abs(res[i]-res[i+1]) > eb.MaxDifference { 51 | t.Error("Unexpected value.") 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /internal/worker_node/managers/ip_manager_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import ( 28 | "math/rand" 29 | "sync" 30 | "sync/atomic" 31 | "testing" 32 | "time" 33 | ) 34 | 35 | func TestGetUniqueValue(t *testing.T) { 36 | ipm := &IPManager{} 37 | wg := &sync.WaitGroup{} 38 | 39 | tries := 1000 40 | var sum uint32 = 0 41 | 42 | wg.Add(tries) 43 | for i := 0; i < tries; i++ { 44 | go func() { 45 | atomic.AddUint32(&sum, ipm.getUniqueCounterValue()) 46 | wg.Done() 47 | }() 48 | } 49 | 50 | wg.Wait() 51 | 52 | computedSum := atomic.LoadUint32(&sum) 53 | expectedSum := uint32(tries * (tries - 1) / 2) 54 | if computedSum != expectedSum { 55 | t.Error("Bad IP manager. Concurrency error.") 56 | } 57 | } 58 | 59 | func TestIPAddressGeneration(t *testing.T) { 60 | rand.Seed(time.Now().UnixNano()) 61 | 62 | ipm := &IPManager{} 63 | barrier := &sync.WaitGroup{} 64 | 65 | tries := 256 + rand.Intn(32)*256 66 | 67 | barrier.Add(tries) 68 | for i := 0; i < tries; i++ { 69 | go func() { 70 | c, d := ipm.generateRawGatewayIP() 71 | 72 | if c > 255 || d > 255 { 73 | t.Errorf("Invalid IP address received - x.x.%d.%d", c, d) 74 | } 75 | 76 | barrier.Done() 77 | }() 78 | } 79 | 80 | barrier.Wait() 81 | } 82 | -------------------------------------------------------------------------------- /internal/worker_node/managers/rootfs_manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import ( 28 | "cluster_manager/pkg/atomic_map" 29 | ) 30 | 31 | type RootFsManager[K interface{}] struct { 32 | atomic_map.AtomicMap[string, K] 33 | } 34 | -------------------------------------------------------------------------------- /internal/worker_node/managers/sandbox_manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "cluster_manager/pkg/atomic_map" 30 | ) 31 | 32 | type SandboxManager struct { 33 | Metadata atomic_map.AtomicMap[string, *Metadata] 34 | 35 | nodeName string 36 | } 37 | 38 | type RuntimeMetadata interface{} 39 | 40 | type Metadata struct { 41 | ServiceName string 42 | 43 | RuntimeMetadata RuntimeMetadata 44 | 45 | HostPort int 46 | IP string 47 | GuestPort int 48 | NetNs string 49 | 50 | ExitStatusChannel chan uint32 51 | } 52 | 53 | func NewSandboxManager(nodeName string) *SandboxManager { 54 | return &SandboxManager{ 55 | Metadata: *atomic_map.NewAtomicMap[string, *Metadata](), 56 | nodeName: nodeName, 57 | } 58 | } 59 | 60 | func (m *SandboxManager) AddSandbox(key string, metadata *Metadata) { 61 | m.Metadata.Set(key, metadata) 62 | } 63 | 64 | func (m *SandboxManager) DeleteSandbox(key string) *Metadata { 65 | res, ok := m.Metadata.Get(key) 66 | if !ok { 67 | return nil 68 | } 69 | 70 | m.Metadata.Delete(key) 71 | 72 | return res 73 | } 74 | 75 | func (m *SandboxManager) ListEndpoints() (*proto.EndpointsList, error) { 76 | list := &proto.EndpointsList{} 77 | 78 | // TODO: check for consistency with containerd client list 79 | keys, values := m.Metadata.KeyValues() 80 | for i := 0; i < len(keys); i++ { 81 | list.Endpoint = append(list.Endpoint, &proto.Endpoint{ 82 | SandboxID: keys[i], 83 | URL: values[i].IP, 84 | NodeName: m.nodeName, 85 | ServiceName: values[i].ServiceName, 86 | HostPort: int32(values[i].HostPort), 87 | }) 88 | } 89 | 90 | return list, nil 91 | } 92 | -------------------------------------------------------------------------------- /internal/worker_node/managers/sandbox_manager_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import ( 28 | "github.com/stretchr/testify/assert" 29 | "strconv" 30 | "testing" 31 | ) 32 | 33 | const ( 34 | mockHost string = "mockHost" 35 | mockkey string = "mockKey" 36 | ) 37 | 38 | func TestSimpleAddDelete(t *testing.T) { 39 | manager := NewSandboxManager(mockHost) 40 | 41 | manager.AddSandbox(mockkey, &Metadata{}) 42 | manager.DeleteSandbox(mockkey) 43 | } 44 | 45 | func TestSandboxManager(t *testing.T) { 46 | i := 0 47 | manager := NewSandboxManager(mockHost) 48 | 49 | for ; i <= 1000; i++ { 50 | manager.AddSandbox(strconv.Itoa(i), &Metadata{}) 51 | assert.Equal(t, manager.Metadata.Len(), i+1) 52 | } 53 | 54 | i-- 55 | 56 | for ; i >= 0; i-- { 57 | manager.DeleteSandbox(strconv.Itoa(i)) 58 | assert.Equal(t, manager.Metadata.Len(), i) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /internal/worker_node/managers/thread_safe_random.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import ( 28 | "math/rand" 29 | "sync" 30 | "time" 31 | ) 32 | 33 | type ThreadSafeRandomGenerator struct { 34 | s *rand.Rand 35 | m sync.Mutex 36 | } 37 | 38 | func NewThreadSafeRandomGenerator() *ThreadSafeRandomGenerator { 39 | return &ThreadSafeRandomGenerator{ 40 | s: rand.New(rand.NewSource(time.Now().UnixNano())), 41 | m: sync.Mutex{}, 42 | } 43 | } 44 | 45 | func (rg *ThreadSafeRandomGenerator) Int() int { 46 | rg.m.Lock() 47 | defer rg.m.Unlock() 48 | 49 | return rg.s.Int() 50 | } 51 | -------------------------------------------------------------------------------- /internal/worker_node/managers/veth_name_generator.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package managers 26 | 27 | import "sync/atomic" 28 | 29 | type VETHNameGenerator struct { 30 | counter int32 31 | } 32 | 33 | func NewVETHNameGenerator() *VETHNameGenerator { 34 | return &VETHNameGenerator{} 35 | } 36 | 37 | func (gen *VETHNameGenerator) Generate() int32 { 38 | swapped := false 39 | var oldValue int32 = -1 40 | for !swapped { 41 | oldValue = atomic.LoadInt32(&gen.counter) 42 | newValue := oldValue + 2 43 | 44 | swapped = atomic.CompareAndSwapInt32(&gen.counter, oldValue, newValue) 45 | } 46 | 47 | return oldValue 48 | } 49 | -------------------------------------------------------------------------------- /internal/worker_node/sandbox/containerd/config_builder.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package containerd 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "math/rand" 30 | "sync" 31 | ) 32 | 33 | var portsInUse = make(map[int]struct{}) 34 | var portsInUseMutex = sync.Mutex{} 35 | 36 | func l4ProtocolToString(protocol proto.L4Protocol) string { 37 | switch protocol.Number() { 38 | case 1: 39 | return "udp" 40 | default: 41 | return "tcp" 42 | } 43 | } 44 | 45 | func validatePort(port int32) bool { 46 | if port <= 0 || port >= 65536 { 47 | return false 48 | } 49 | 50 | return true 51 | } 52 | 53 | func AssignRandomPort() int { 54 | portsInUseMutex.Lock() 55 | defer portsInUseMutex.Unlock() 56 | 57 | var port int 58 | 59 | for { 60 | port = 1024 + rand.Intn(64000) 61 | 62 | _, ok := portsInUse[port] 63 | if !ok { 64 | portsInUse[port] = struct{}{} 65 | 66 | break 67 | } 68 | } 69 | 70 | return port 71 | } 72 | 73 | func UnassignPort(port int) { 74 | portsInUseMutex.Lock() 75 | defer portsInUseMutex.Unlock() 76 | 77 | delete(portsInUse, port) 78 | } 79 | -------------------------------------------------------------------------------- /internal/worker_node/sandbox/containerd/image_manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package containerd 26 | 27 | import ( 28 | "cluster_manager/internal/worker_node/managers" 29 | "context" 30 | "time" 31 | 32 | "github.com/containerd/containerd" 33 | ) 34 | 35 | type ImageManager struct { 36 | managers.RootFsManager[containerd.Image] 37 | } 38 | 39 | func NewContainerdImageManager() *ImageManager { 40 | return &ImageManager{} 41 | } 42 | 43 | func (m *ImageManager) GetImage(ctx context.Context, containerdClient *containerd.Client, url string) (containerd.Image, error, time.Duration) { 44 | start := time.Now() 45 | 46 | image, ok := m.Get(url) 47 | if !ok { 48 | var err error 49 | 50 | image, err = FetchImage(ctx, containerdClient, url) 51 | if err != nil { 52 | return image, err, time.Since(start) 53 | } 54 | 55 | m.Set(url, image) 56 | 57 | return image, nil, time.Since(start) 58 | } 59 | 60 | return image, nil, time.Since(start) 61 | } 62 | -------------------------------------------------------------------------------- /internal/worker_node/sandbox/containerd/image_manager_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package containerd 26 | 27 | import ( 28 | "cluster_manager/pkg/utils" 29 | "context" 30 | "github.com/containerd/containerd/namespaces" 31 | "github.com/stretchr/testify/assert" 32 | "testing" 33 | ) 34 | 35 | func TestImageManager(t *testing.T) { 36 | t.Skip() 37 | 38 | imageManager := NewContainerdImageManager() 39 | 40 | containerdClient := GetContainerdClient("/run/containerd/containerd.sock") 41 | defer containerdClient.Close() 42 | 43 | _, err, _ := imageManager.GetImage(namespaces.WithNamespace(context.Background(), "default"), containerdClient, utils.TestDockerImageName) 44 | assert.NoError(t, err, "Image fetching should return no error") 45 | } 46 | -------------------------------------------------------------------------------- /internal/worker_node/sandbox/firecracker/snapshot_manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package firecracker 26 | 27 | import ( 28 | "cluster_manager/internal/worker_node/managers" 29 | ) 30 | 31 | type SnapshotManager struct { 32 | managers.RootFsManager[*SnapshotMetadata] 33 | } 34 | 35 | type SnapshotMetadata struct { 36 | MemoryPath string 37 | SnapshotPath string 38 | } 39 | 40 | func NewFirecrackerSnapshotManager() *SnapshotManager { 41 | return &SnapshotManager{} 42 | } 43 | 44 | func (sm *SnapshotManager) Exists(serviceName string) bool { 45 | _, ok := sm.Get(serviceName) 46 | 47 | return ok 48 | } 49 | 50 | func (sm *SnapshotManager) AddSnapshot(serviceID string, metadata *SnapshotMetadata) { 51 | sm.LoadOrStore(serviceID, metadata) 52 | } 53 | 54 | func (sm *SnapshotManager) FindSnapshot(serviceName string) (*SnapshotMetadata, bool) { 55 | return sm.Get(serviceName) 56 | } 57 | -------------------------------------------------------------------------------- /internal/worker_node/sandbox/runtime_interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package sandbox 26 | 27 | import ( 28 | "cluster_manager/api/proto" 29 | "context" 30 | "google.golang.org/protobuf/types/known/emptypb" 31 | ) 32 | 33 | type RuntimeInterface interface { 34 | CreateSandbox(ctx context.Context, serviceInfo *proto.ServiceInfo) (*proto.SandboxCreationStatus, error) 35 | DeleteSandbox(ctx context.Context, in *proto.SandboxID) (*proto.ActionStatus, error) 36 | ListEndpoints(ctx context.Context, _ *emptypb.Empty) (*proto.EndpointsList, error) 37 | ValidateHostConfig() bool 38 | } 39 | -------------------------------------------------------------------------------- /internal/worker_node/worker_node_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package worker_node 26 | 27 | import ( 28 | "cluster_manager/internal/worker_node/sandbox/containerd" 29 | "cluster_manager/pkg/config" 30 | "github.com/stretchr/testify/assert" 31 | "go.uber.org/mock/gomock" 32 | "testing" 33 | ) 34 | 35 | func TestCreationWorkerNode(t *testing.T) { 36 | ctrl := gomock.NewController(t) 37 | defer ctrl.Finish() 38 | 39 | mockConfig := config.WorkerNodeConfig{ 40 | ControlPlaneAddress: []string{}, 41 | Port: 0, 42 | Verbosity: "", 43 | CRIType: "containerd", 44 | CRIPath: "/run/containerd/containerd.sock", 45 | CNIConfigPath: "../../configs/cni.conf", 46 | PrefetchImage: false, 47 | } 48 | 49 | containerdClient := containerd.GetContainerdClient(mockConfig.CRIPath) 50 | defer containerdClient.Close() 51 | 52 | assert.NotNil(t, NewWorkerNode(nil, mockConfig), "Created worker not should not be nil") 53 | } 54 | -------------------------------------------------------------------------------- /pkg/atomic_map/atomic_map_counter.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package atomic_map 26 | 27 | import ( 28 | "github.com/sirupsen/logrus" 29 | "sync" 30 | "sync/atomic" 31 | ) 32 | 33 | type AtomicMapCounter[K any] struct { 34 | m sync.Map 35 | } 36 | 37 | func NewAtomicMapCounter[K any]() *AtomicMapCounter[K] { 38 | return &AtomicMapCounter[K]{} 39 | } 40 | 41 | func (c *AtomicMapCounter[K]) Get(key K) int64 { 42 | count, ok := c.m.Load(key) 43 | if ok { 44 | val, ok := count.(*int64) 45 | if !ok { 46 | logrus.Fatal("Type assertion failed") 47 | } 48 | 49 | return atomic.LoadInt64(val) 50 | } 51 | 52 | return 0 53 | } 54 | 55 | func (c *AtomicMapCounter[K]) AtomicAdd(key K, value int64) int64 { 56 | count, loaded := c.m.LoadOrStore(key, &value) 57 | if loaded { 58 | val, ok := count.(*int64) 59 | if !ok { 60 | logrus.Fatal("Type assertion failed") 61 | } 62 | 63 | return atomic.AddInt64(val, value) 64 | } 65 | 66 | val, ok := count.(*int64) 67 | if !ok { 68 | logrus.Fatal("Type assertion failed") 69 | } 70 | 71 | return *val 72 | } 73 | 74 | func (c *AtomicMapCounter[K]) AtomicIncrement(key K) { 75 | c.AtomicAdd(key, 1) 76 | } 77 | 78 | func (c *AtomicMapCounter[K]) AtomicDecrement(key K) { 79 | c.AtomicAdd(key, -1) 80 | } 81 | 82 | func (c *AtomicMapCounter[K]) Delete(key K) { 83 | c.m.Delete(key) 84 | } 85 | -------------------------------------------------------------------------------- /pkg/hardware/hardware.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package hardware 26 | 27 | import ( 28 | "log" 29 | "math" 30 | "runtime" 31 | 32 | "github.com/pbnjay/memory" 33 | "github.com/shirou/gopsutil/cpu" 34 | ) 35 | 36 | type HardwareUsage struct { 37 | CpuUsage uint64 38 | MemoryUsage uint64 39 | } 40 | 41 | func GetNumberCpus() uint64 { 42 | return uint64(runtime.NumCPU()) 43 | } 44 | 45 | func GetMemory() uint64 { 46 | return memory.TotalMemory() 47 | } 48 | 49 | func getCpuUsage() uint64 { 50 | percent, err := cpu.Percent(0, false) 51 | if err != nil { 52 | log.Fatal(err) 53 | } 54 | 55 | return uint64(math.Ceil(percent[0])) 56 | } 57 | 58 | func getMemoryUsage() uint64 { 59 | memory := float64(memory.TotalMemory()-memory.FreeMemory()) / float64(memory.TotalMemory()) 60 | return uint64(memory * 100) 61 | } 62 | 63 | func GetHardwareUsage() HardwareUsage { 64 | return HardwareUsage{ 65 | CpuUsage: getCpuUsage(), 66 | MemoryUsage: getMemoryUsage(), 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /pkg/hardware/hardware_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package hardware 26 | 27 | import ( 28 | "testing" 29 | 30 | "github.com/stretchr/testify/assert" 31 | ) 32 | 33 | func TestGetCpu(t *testing.T) { 34 | assert.Positive(t, GetNumberCpus()) 35 | } 36 | 37 | func TestGetMemory(t *testing.T) { 38 | assert.Positive(t, GetMemory()) 39 | } 40 | 41 | func TestCpuPercentage(t *testing.T) { 42 | assert.True(t, 0 <= getCpuUsage() && getCpuUsage() <= 100) 43 | } 44 | 45 | func TestMemoryUsage(t *testing.T) { 46 | assert.True(t, 0 <= getMemoryUsage() && getMemoryUsage() <= 100) 47 | } 48 | -------------------------------------------------------------------------------- /pkg/logger/logging.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package logger 26 | 27 | import ( 28 | "math/rand" 29 | "time" 30 | 31 | "github.com/sirupsen/logrus" 32 | ) 33 | 34 | func SetupLogger(verbosity string) { 35 | rand.Seed(time.Now().UnixNano()) 36 | 37 | logrus.SetFormatter(&logrus.TextFormatter{TimestampFormat: time.StampMilli, FullTimestamp: true}) 38 | 39 | switch verbosity { 40 | case "debug": 41 | logrus.SetLevel(logrus.DebugLevel) 42 | case "trace": 43 | logrus.SetLevel(logrus.TraceLevel) 44 | default: 45 | logrus.SetLevel(logrus.InfoLevel) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pkg/map/maps.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package _map 26 | 27 | func Keys[M ~map[K]V, K comparable, V any](m M) []K { 28 | r := make([]K, 0, len(m)) 29 | 30 | for k := range m { 31 | r = append(r, k) 32 | } 33 | 34 | return r 35 | } 36 | 37 | func Values[M ~map[K]V, K comparable, V any](m M) []V { 38 | r := make([]V, 0, len(m)) 39 | 40 | for _, v := range m { 41 | r = append(r, v) 42 | } 43 | 44 | return r 45 | } 46 | 47 | func Difference[T comparable](a, b []T) []T { 48 | mb := make(map[T]struct{}, len(b)) 49 | for _, x := range b { 50 | mb[x] = struct{}{} 51 | } 52 | 53 | var diff []T 54 | 55 | for _, x := range a { 56 | if _, found := mb[x]; !found { 57 | diff = append(diff, x) 58 | } 59 | } 60 | 61 | return diff 62 | } 63 | 64 | func ExtractField[T any](m []T, extractor func(T) string) ([]string, map[string]T) { 65 | var res []string 66 | 67 | mm := make(map[string]T) 68 | 69 | for i := 0; i < len(m); i++ { 70 | val := extractor(m[i]) 71 | 72 | res = append(res, val) 73 | mm[val] = m[i] 74 | } 75 | 76 | return res, mm 77 | } 78 | -------------------------------------------------------------------------------- /pkg/map/maps_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package _map 26 | 27 | import ( 28 | "testing" 29 | 30 | "github.com/stretchr/testify/assert" 31 | ) 32 | 33 | func TestKeysValues(t *testing.T) { 34 | mp := make(map[string]string) 35 | mp["paris"] = "france" 36 | mp["london"] = "uk" 37 | 38 | assert.Len(t, Keys(mp), 2) 39 | assert.Len(t, Values(mp), 2) 40 | 41 | mp["roma"] = "italy" 42 | mp["bern"] = "switzerland" 43 | 44 | assert.Len(t, Keys(mp), 4) 45 | assert.Len(t, Values(mp), 4) 46 | } 47 | 48 | func TestDifference(t *testing.T) { 49 | slice1 := []int{1, 2, 3, 4} 50 | slice2 := []int{4, 2} 51 | 52 | output := Difference(slice1, slice2) 53 | assert.Len(t, output, 2) 54 | assert.Equal(t, output[0], slice1[0]) 55 | assert.Equal(t, output[1], slice1[2]) 56 | } 57 | 58 | func TestDifferenceSecond(t *testing.T) { 59 | s1 := []string{"a", "b", "c"} 60 | s2 := []string{"b", "c", "d"} 61 | 62 | lr := Difference(s1, s2) 63 | assert.NotNil(t, lr, "s1 \\ s2 yielded a wrong result.") 64 | assert.Equal(t, len(lr), 1, "s1 \\ s2 yielded a wrong result.") 65 | assert.Equal(t, lr[0], "a", "s1 \\ s2 yielded a wrong result.") 66 | 67 | rr := Difference(s2, s1) 68 | assert.NotNil(t, rr, "s2 \\ s1 yielded a wrong result.") 69 | assert.Len(t, rr, 1, "s2 \\ s1 yielded a wrong result.") 70 | assert.Equal(t, rr[0], "d", "s2 \\ s1 yielded a wrong result.") 71 | } 72 | -------------------------------------------------------------------------------- /pkg/network/ip.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package network 26 | 27 | import ( 28 | "github.com/sirupsen/logrus" 29 | "os/exec" 30 | ) 31 | 32 | func GetLocalIP() string { 33 | cmd := exec.Command("bash", "-c", "/usr/bin/netstat -ie | grep -B1 '10.0.1' | sed -n 2p | tr -s ' ' | cut -d ' ' -f 3") 34 | stdout, err := cmd.Output() 35 | 36 | if err != nil { 37 | logrus.Fatal(err) 38 | } 39 | 40 | ip := string(stdout) 41 | ip = ip[0 : len(ip)-1] 42 | 43 | return ip 44 | } 45 | -------------------------------------------------------------------------------- /pkg/profiler/profiler.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package profiler 26 | 27 | import ( 28 | "cluster_manager/pkg/config" 29 | "log" 30 | "net/http" 31 | "runtime" 32 | ) 33 | 34 | func SetupProfilerServer(config config.ProfilerConfig) { 35 | if config.Mutex { 36 | runtime.SetMutexProfileFraction(1) 37 | } 38 | 39 | if config.Enable { 40 | log.Println(http.ListenAndServe("localhost:6060", nil)) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pkg/utils/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package utils 26 | 27 | import "time" 28 | 29 | const ( 30 | Localhost string = "0.0.0.0" 31 | 32 | DefaultDataPlaneProxyPort string = "8080" 33 | DefaultDataPlaneApiPort string = "8081" 34 | 35 | DefaultControlPlanePort string = "9090" 36 | DefaultControlPlanePortServiceRegistration string = "9091" 37 | 38 | DefaultWorkerNodePort int = 10010 39 | 40 | DefaultTraceOutputFolder string = "data" 41 | 42 | TCP string = "tcp" 43 | 44 | TestDockerImageName string = "docker.io/cvetkovic/dirigent_empty_function:latest" 45 | 46 | TolerateHeartbeatMisses = 3 47 | HeartbeatInterval = 5 * time.Second 48 | 49 | WorkerNodeTrafficTimeout = 60 * time.Second 50 | 51 | GRPCConnectionTimeout = 5 * time.Second 52 | GRPCFunctionTimeout = 15 * time.Minute // AWS Lambda 53 | ) 54 | -------------------------------------------------------------------------------- /pkg/utils/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package utils 26 | 27 | import ( 28 | "context" 29 | "github.com/sirupsen/logrus" 30 | "log" 31 | "os/signal" 32 | "os/user" 33 | "syscall" 34 | ) 35 | 36 | func WaitTerminationSignal(cleanFunction func()) { 37 | ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) 38 | defer stop() 39 | 40 | select { 41 | case <-ctx.Done(): 42 | logrus.Info("Received interruption signal, try to gracefully stop") 43 | 44 | cleanFunction() 45 | } 46 | } 47 | 48 | func IsRoot() bool { 49 | currentUser, err := user.Current() 50 | if err != nil { 51 | log.Fatalf("[isRoot] Unable to get current user: %s", err) 52 | } 53 | return currentUser.Username == "root" 54 | } 55 | -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | *.csv 2 | *.png 3 | -------------------------------------------------------------------------------- /scripts/add_auth_token.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | server_exec() { 28 | ssh -oStrictHostKeyChecking=no -p 22 "$1" "$2"; 29 | } 30 | 31 | ACCESS_TOKEN="$(cat ~/.git_token_loader)" 32 | 33 | server_exec $1 'echo -en "\n\n" | ssh-keygen -t rsa' 34 | server_exec $1 'ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts' 35 | server_exec $1 'curl -H "Authorization: token '"$ACCESS_TOKEN"'" --data "{\"title\":\"'"key:\$(hostname)"'\",\"key\":\"'"\$(cat ~/.ssh/id_rsa.pub)"'\"}" https://api.github.com/user/keys' 36 | -------------------------------------------------------------------------------- /scripts/add_ssh_key.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | readonly KEY="cvetkovi@node-99.boze-pomozi.faas-sched-pg0.utah.cloudlab.us" 28 | 29 | function internal() { 30 | # Connect to the remote machine and start a tmux session 31 | ssh $1 "echo $KEY >> ~/.ssh/authorized_keys" 32 | } 33 | 34 | for ip in "$@" 35 | do 36 | internal $ip & 37 | done 38 | 39 | wait -------------------------------------------------------------------------------- /scripts/azure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | function Run() { 31 | RemoteExec $INVITRO "cd ~/invitro;git checkout rps_mode; sudo /usr/local/go/bin/go run cmd/loader.go --config ~/invitro/samples/$1/config.json --verbosity trace" 32 | 33 | scp $INVITRO:~/invitro/data/out/experiment_duration_5.csv plotting/azure_$1.csv 34 | scp $INVITRO:~/invitro/data/out/experiment_duration_30.csv plotting/azure_$1.csv 35 | StoreResults $1 36 | } 37 | 38 | for VALUE in "$@" 39 | do 40 | Run $VALUE 41 | done 42 | -------------------------------------------------------------------------------- /scripts/collect_resource_monitoring.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | function internal() { 28 | file_name="$2/utilization_$1.csv" 29 | scp $1:~/utilization.csv $file_name 30 | ssh $1 "tmux kill-session -t resource_monitoring" 31 | } 32 | 33 | PREFIX=$1 34 | shift 35 | 36 | for ip in "$@" 37 | do 38 | internal $ip $PREFIX & 39 | done 40 | 41 | wait -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/100/config.json: -------------------------------------------------------------------------------- 1 | {"Seed": 42, "Platform": "Dirigent", "DirigentControlPlaneIP": "10.0.1.253:9092", "TracePath": "./samples/100", "Granularity": "minute", "OutputPathPrefix": "data/out/experiment", "IATDistribution": "equidistant", "ExperimentDuration": 5, "WarmupDuration": 0, "IsPartiallyPanic": false, "EnableZipkinTracing": false, "EnableMetricsScrapping": false, "MetricScrapingPeriodSeconds": 15, "AutoscalingMetric": "concurrency", "GRPCConnectionTimeoutSeconds": 120, "GRPCFunctionTimeoutSeconds": 120} -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/100/dirigent.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4629435f3ac36653eddb6c97b9b579defe269fd475b7242cf0d4048e60b5dd3d 3 | size 13389 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/100/durations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f25b3424cc6030143c92f595bbeef97707f22cfcaf306792b6b840a2875e2e16 3 | size 24554 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/100/invocations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:002e124025d2f7cc81867cf5e48809bec4c853f1728d7874db46433e5d289305 3 | size 120123 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/100/memory.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:999563b3a707cfd0f3b998e8109016b7bf4225158816ffd21f1e7cf2463ab0df 3 | size 28555 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/250/config.json: -------------------------------------------------------------------------------- 1 | {"Seed": 42, "Platform": "Dirigent", "DirigentControlPlaneIP": "10.0.1.253:9092", "TracePath": "./samples/250", "Granularity": "minute", "OutputPathPrefix": "data/out/experiment", "IATDistribution": "equidistant", "ExperimentDuration": 5, "WarmupDuration": 0, "IsPartiallyPanic": false, "EnableZipkinTracing": false, "EnableMetricsScrapping": false, "MetricScrapingPeriodSeconds": 15, "AutoscalingMetric": "concurrency", "GRPCConnectionTimeoutSeconds": 120, "GRPCFunctionTimeoutSeconds": 120} -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/250/dirigent.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:36be8d1900d276cbff9ad03c2455322398250e729122d6eee3343177cdd3e315 3 | size 33339 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/250/durations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eb111cf27ea1ae725cffe20c68a762619315d3d5f321807ede629cf53da3e3dd 3 | size 61200 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/250/invocations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c55b87e0fa7f7e43dfd71d351544641264da7b4929afd68b20163e4490c9bd0c 3 | size 298630 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/250/memory.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:557fd5832e7e6173c868377da7ee0a48cd019cdd15a096619edabe363b0442e4 3 | size 69770 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/4000/config.json: -------------------------------------------------------------------------------- 1 | {"Seed": 42, "Platform": "Dirigent", "DirigentControlPlaneIP": "10.0.1.253:9092", "TracePath": "./samples/4000", "Granularity": "minute", "OutputPathPrefix": "data/out/experiment", "IATDistribution": "equidistant", "ExperimentDuration": 30, "WarmupDuration": 0, "IsPartiallyPanic": false, "EnableZipkinTracing": false, "EnableMetricsScrapping": false, "MetricScrapingPeriodSeconds": 15, "AutoscalingMetric": "concurrency", "GRPCConnectionTimeoutSeconds": 120, "GRPCFunctionTimeoutSeconds": 120} 2 | 3 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/4000/dirigent.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cd7e34c6e30fc78d0d28dfbb518ef279d72b5abfba1dbba7c362faded28bb3dc 3 | size 540089 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/4000/durations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b3b7b9cdc437a15da6715aec209a6e08f1d85ef5d1ae8c14a153472106641d45 3 | size 979175 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/4000/invocations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f6283e30cbf39f03e8dca020731b0075494b91e4c8ed16b5caaaf382ff56cd57 3 | size 4771521 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/4000/memory.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d096740622d94e8fa465d502975a1715df2c75909da1fce179df7bdd7123a614 3 | size 1124367 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/500/config.json: -------------------------------------------------------------------------------- 1 | {"Seed": 42, "Platform": "Dirigent", "DirigentControlPlaneIP": "10.0.1.253:9092", "TracePath": "./samples/500", "Granularity": "minute", "OutputPathPrefix": "data/out/experiment", "IATDistribution": "equidistant", "ExperimentDuration": 30, "WarmupDuration": 0, "IsPartiallyPanic": false, "EnableZipkinTracing": false, "EnableMetricsScrapping": false, "MetricScrapingPeriodSeconds": 15, "AutoscalingMetric": "concurrency", "GRPCConnectionTimeoutSeconds": 120, "GRPCFunctionTimeoutSeconds": 120} 2 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/500/dirigent.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5406f5e8e616768c781242dd99218d6659fdb3a776f14dbe5f66bd10b10c45d5 3 | size 66589 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/500/durations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bc2e52d33f1ec0d4032dc7cbdacadb7622413c9264f5478bf8da2c3aacd92b55 3 | size 122145 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/500/invocations.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a0ca953d1b50cc1f0e813c656e0c3d65b7369757804b571e2767e1ab76b05536 3 | size 598449 4 | -------------------------------------------------------------------------------- /scripts/invitro_traces/samples/500/memory.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ea3ac4b65629cb33e567ac0a517d6ae68747a5dd143ff394b86f78f685b65305 3 | size 139891 4 | -------------------------------------------------------------------------------- /scripts/measure_async.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | 31 | function RunMeasure() { 32 | RemoteExec $DATAPLANE "cd ~/cluster_manager/async;git pull; git reset --hard origin/current; /usr/local/go/bin/go run fire.go" 33 | 34 | scp $DATAPLANE:~/cluster_manager/cmd/data_plane/data/proxy_trace.csv proxy_trace_$1.csv 35 | scp $CONTROLPLANE:~/cluster_manager/cmd/master_node/data/cold_start_trace.csv cold_start_trace_$1.csv 36 | } 37 | 38 | 39 | RunMeasure 40 | 41 | # ./run.sh 1 2 4 8 16 32 50 100 200 400 800 -------------------------------------------------------------------------------- /scripts/plotting/cdf.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import pandas as pd 24 | import numpy as np 25 | import matplotlib.pyplot as plt 26 | 27 | rootPath = './francois' 28 | load = [100,150,200,250,300,350,400,450] 29 | 30 | 31 | percent = np.arange(1, 101, 1) 32 | 33 | result = [] 34 | for l in load: 35 | cpTrace = pd.read_csv(f'{rootPath}/cold_start_trace_{l}.csv') 36 | proxyTrace = pd.read_csv(f'{rootPath}/proxy_trace_{l}.csv') 37 | 38 | data = pd.merge(proxyTrace, cpTrace, on=['container_id', 'service_name'], how='inner') 39 | data = data[data['success'] == True] # keep only successful invocations 40 | data = data[data['cold_start'] > 0] # keep only cold starts 41 | 42 | data = data.drop(columns=['time_x', 'time_y', 'success', 'service_name', 'container_id']) 43 | 44 | data['control_plane'] = data['cold_start'] - \ 45 | (data['image_fetch'] + data['sandbox_create'] + data['sandbox_start'] + 46 | data['network_setup'] + data['iptables'] + data['db'] + data['other_worker_node']) 47 | data = data.drop(columns=['cold_start']) 48 | 49 | hist = [] 50 | for per in percent: 51 | hist.append(np.sum(data.quantile(per / 100))) 52 | plt.plot(hist, percent, label="{} colds starts per second".format(l)) 53 | 54 | 55 | plt.title(f'CDF - Sweep test') 56 | plt.ylabel('Percentile') 57 | plt.xlabel('Latency [ms]') 58 | plt.legend() 59 | plt.savefig(f"{rootPath}/cdf_sweep.png",dpi=160) -------------------------------------------------------------------------------- /scripts/plotting/compare.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import pandas as pd 24 | import numpy as np 25 | import matplotlib.pyplot as plt 26 | 27 | load = ['./output/osdi', './output/main'] 28 | 29 | 30 | percent = np.arange(1, 101, 1) 31 | 32 | result = [] 33 | for rootPath in load: 34 | cpTrace = pd.read_csv(f'{rootPath}/cold_start_trace_500.csv') 35 | proxyTrace = pd.read_csv(f'{rootPath}/proxy_trace_500.csv') 36 | 37 | data = pd.merge(proxyTrace, cpTrace, on=['container_id', 'service_name'], how='inner') 38 | data = data[data['success'] == True] # keep only successful invocations 39 | data = data[data['cold_start'] > 0] # keep only cold starts 40 | 41 | data = data.drop(columns=['time_x', 'time_y', 'success', 'service_name', 'container_id']) 42 | 43 | data['control_plane'] = data['cold_start'] - \ 44 | (data['image_fetch'] + data['sandbox_create'] + data['sandbox_start'] + 45 | data['network_setup'] + data['iptables'] + data['other_worker_node']) 46 | data = data.drop(columns=['cold_start']) 47 | 48 | hist = [] 49 | for per in percent: 50 | hist.append(np.sum(data.quantile(per / 100))) 51 | plt.plot(hist, percent, label="{} colds starts per second".format(l)) 52 | 53 | 54 | 55 | 56 | plt.title(f'CDF - Sweep test') 57 | plt.ylabel('Percentile') 58 | plt.xlabel('Latency [ms]') 59 | plt.legend() 60 | plt.savefig(f"{rootPath}/cdf_sweep.png",dpi=160) -------------------------------------------------------------------------------- /scripts/plotting/get_percentile.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import pandas as pd 24 | 25 | data = pd.read_csv("/home/lcvetkovic/Desktop/cluster_manager/cold_start_steady_load/experiment_50rps.csv") 26 | 27 | data = data[data['responseTime'] > 50_000] 28 | p50 = data[['responseTime']].quantile(0.5) 29 | p95 = data[['responseTime']].quantile(0.95) 30 | 31 | print(p50) 32 | print(p95) -------------------------------------------------------------------------------- /scripts/plotting/latency_breakdown_burst.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from common import * 24 | 25 | rootPath = '/home/lcvetkovic/Desktop/data_analysis' 26 | load = [500] 27 | 28 | plotClusteredStackedBarchart(getResult(load, rootPath), 29 | title='', 30 | clusterLabels=[ 31 | 'Azure 500 functions', 32 | ], 33 | clusterLabelPosition=(-0.20, 1.1), 34 | categoryLabelPosition=(-0.25, 0.65)) 35 | 36 | plt.title(f'Cold start latency breakdown burst') 37 | plt.xlabel('Percentile') 38 | plt.xticks(rotation=0) 39 | plt.ylabel('Latency [ms]') 40 | plt.grid() 41 | plt.tight_layout() 42 | 43 | plt.savefig(f"{rootPath}/breakdown_burst.png", dpi=160) 44 | plt.savefig(f"{rootPath}/breakdown_burst.pdf", dpi=160) 45 | -------------------------------------------------------------------------------- /scripts/plotting/latency_breakdown_sweep.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from common import * 24 | 25 | rootPath = '/home/lcvetkovic/Desktop/replay/sosp/dirigent_1cp_1dp/rps_sweep_containerd/containerd' 26 | load = [250, 1000, 1250] 27 | 28 | #load = [500, 2000, 2500] 29 | 30 | labels = [] 31 | [labels.append(f'{x} CS/s') for x in load] 32 | 33 | rawData = getResult(load, rootPath)[0] 34 | for idx in range(0, len(labels)): 35 | rawData[idx].to_csv(f'{rootPath}/statistics_load_{load[idx]}.csv') 36 | 37 | plt.figure(figsize=(3, 6)) 38 | plotClusteredStackedBarchart(rawData, 39 | title='', 40 | clusterLabels=labels, 41 | clusterLabelPosition=(0.15, 0.1), 42 | categoryLabelPosition=(0.35, 0.65)) 43 | 44 | plt.title(f'Cold start latency\nbreakdown sweep') 45 | plt.xlabel('Percentile') 46 | plt.xticks(rotation=0) 47 | plt.ylabel('Latency [ms]') 48 | plt.grid() 49 | plt.tight_layout() 50 | 51 | plt.savefig(f"{rootPath}/breakdown_sweep.png", dpi=160) 52 | -------------------------------------------------------------------------------- /scripts/plotting/plot.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from common import * 24 | 25 | rootPath = '/home/lcvetkovic/Desktop/azure_500/containerd' 26 | load = [500] 27 | 28 | # Dirigent 29 | results_to_plot, dirigent_grouped_results = getResult(load, rootPath) 30 | 31 | # Knative 32 | knative_results = pd.DataFrame([ 33 | [5], # [0, 0], 34 | [1417.12] # [492.69, 383.7] 35 | ], columns=['Cluster manager']) # ['Container creation', 'Readiness probes']) 36 | knative_results.index = ['p50', 'p99'] 37 | 38 | dirigent_grouped_results.append(knative_results) 39 | 40 | plt.figure(figsize=(6, 3)) 41 | 42 | plotClusteredStackedBarchart(dirigent_grouped_results, 43 | title='', 44 | clusterLabels=[ 45 | 'Dirigent', 46 | 'Knative-on-K8s', 47 | ], 48 | clusterLabelPosition=(-1, -0.5), # bars 49 | categoryLabelPosition=(0.65, 0.75)) # categories 50 | 51 | plt.xlabel('Percentile') 52 | plt.xticks(rotation=0) 53 | 54 | plt.ylabel('Function scheduling latency [ms]') 55 | plt.yscale('log') 56 | 57 | plt.grid() 58 | plt.tight_layout() 59 | 60 | plt.savefig(f"{rootPath}/breakdown.png", dpi=160) 61 | plt.savefig(f"{rootPath}/breakdown.pdf", format='pdf', bbox_inches='tight') 62 | -------------------------------------------------------------------------------- /scripts/plotting/proxy_analysis.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import pandas as pd 24 | import matplotlib.pyplot as plt 25 | import numpy as np 26 | 27 | def parse_df(path): 28 | df = pd.read_csv(path) 29 | df = df[df['cold_start'] == 0] 30 | df = df.drop(['time', 'service_name', 'container_id'], axis=1) 31 | 32 | df['proxying'] = df['proxying'] - 1460 33 | 34 | return df 35 | 36 | async_df = parse_df("proxy_async.csv").mean(axis=0) 37 | sync_df = parse_df("proxy.csv").mean(axis=0) 38 | 39 | labels = parse_df("proxy_async.csv").columns.values.tolist() 40 | fig, (ax1,ax2) = plt.subplots(1,2) 41 | 42 | 43 | ax1.title.set_text("Sync data plane | Total (microseconds) : " + str(int(np.array(sync_df).sum()))) 44 | ax1.pie(sync_df, labels=labels,autopct='%1.1f%%') 45 | 46 | ax2.title.set_text("Async data plane | Total (microseconds) : " + str(int(np.array(async_df).sum()))) 47 | ax2.pie(async_df, labels=labels,autopct='%1.1f%%') 48 | 49 | 50 | plt.show() -------------------------------------------------------------------------------- /scripts/remote_start_cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | readonly DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | 29 | source $DIR/common.sh 30 | source $DIR/setup.cfg 31 | 32 | # Skip the loader node 33 | shift 34 | 35 | # Kill all Dirigent processes 36 | KillSystemdServices $@ 37 | 38 | # Starting control plane(s) 39 | for (( c=1; c<=$CONTROL_PLANE_REPLICAS; c++ )) 40 | do 41 | if [ "$CONTROL_PLANE_REPLICAS" -eq 1 ]; then 42 | SetupControlPlane $1 43 | else 44 | SetupControlPlane $1 "_raft_${c}" 45 | fi 46 | 47 | shift 48 | done 49 | 50 | # Starting data plane(s) 51 | for (( c=1; c<=$DATA_PLANE_REPLICAS; c++ )) 52 | do 53 | CP_PREFIX="" 54 | if [ "$CONTROL_PLANE_REPLICAS" -ne 1 ]; then 55 | CP_PREFIX="_raft" 56 | fi 57 | 58 | SetupDataPlane $1 $CP_PREFIX 59 | 60 | shift 61 | done 62 | 63 | 64 | if [ "$FAKE_WORKER_MODE" -eq 1 ]; then 65 | KillFakeWorkerNodes $@ 66 | SetupFakeWorkerNodes $CONTROL_PLANE_REPLICAS $@ 67 | else 68 | SetupWorkerNodes $CONTROL_PLANE_REPLICAS $@ 69 | fi 70 | -------------------------------------------------------------------------------- /scripts/restart_workers_containerd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | 31 | function RestartWorkers() { 32 | function internal_setup() { 33 | RemoteExec $1 "tmux kill-session -t worker" 34 | RemoteExec $1 "tmux new -s worker -d" 35 | 36 | RemoteExec $1 "sudo sysctl -w net.ipv4.conf.all.route_localnet=1" 37 | RemoteExec $1 "sudo iptables -t nat -F" 38 | 39 | CMD=$"cd ~/cluster_manager; git fetch origin;git reset --hard origin/current; sudo /usr/local/go/bin/go run cmd/worker_node/main.go --config cmd/worker_node/config_cluster_containerd.yaml" 40 | 41 | RemoteExec $1 "tmux send -t worker \"$CMD\" ENTER" 42 | } 43 | 44 | for NODE in "$@" 45 | do 46 | internal_setup $NODE & 47 | done 48 | 49 | 50 | wait 51 | } 52 | 53 | function StopWorkers() { 54 | function internal_setup() { 55 | RemoteExec $1 "tmux kill-session -t worker" 56 | #RemoteExec $1 "sudo kill -9 $(sudo lsof -t -i:10010)" 57 | } 58 | 59 | for NODE in "$@" 60 | do 61 | internal_setup $NODE & 62 | done 63 | 64 | wait 65 | } 66 | 67 | 68 | # StopWorkers $@ 69 | RestartWorkers $(python3 string.py --type worker-ha) 70 | 71 | # sudo env 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin:/usr/local/bin/firecracker:/usr/local/bin/firecracker' /usr/local/go/bin/go run main.go --config config_cluster.yaml 72 | # rsync -av samples Francois@pc704.emulab.net:invitro/ -------------------------------------------------------------------------------- /scripts/rps_containerd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | function Run() { 31 | RemoteExec $INVITRO "cd ~/invitro;git checkout rps_mode; sudo /usr/local/go/bin/go run cmd/loader.go --config ~/invitro/rps/$1/config_containerd.json --verbosity trace" 32 | StoreResults $1 33 | } 34 | 35 | for VALUE in "$@" 36 | do 37 | Run $VALUE 38 | done -------------------------------------------------------------------------------- /scripts/rps_firecracker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | function Run() { 31 | RemoteExec $INVITRO "cd ~/invitro;git checkout rps_mode; sudo /usr/local/go/bin/go run cmd/loader.go --config ~/invitro/rps/$1/config_firecracker.json --verbosity trace" 32 | StoreResults $1 33 | } 34 | 35 | for VALUE in "$@" 36 | do 37 | Run $VALUE 38 | done -------------------------------------------------------------------------------- /scripts/scalability_copy_results.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | SUFFIX=500 31 | DESTINATION_DIR=/home/lcvetkovic/Desktop/dirigent_rps_sweep/d430_100_percent_cold_start 32 | 33 | LOADER_NODE=cvetkovi@pc848.emulab.net 34 | CONTROL_PLANE_NODE=cvetkovi@pc784.emulab.net 35 | DATA_PLANE_NODE=cvetkovi@pc735.emulab.net 36 | 37 | scp $LOADER_NODE:/users/cvetkovi/invitro/data/out/experiment_duration_5.csv ${DESTINATION_DIR}/rps_${SUFFIX}.csv 38 | 39 | RemoteExec $CONTROL_PLANE_NODE "sudo cp /data/cold_start_trace.csv ~/cold_start_trace.csv" 40 | scp $CONTROL_PLANE_NODE:~/cold_start_trace.csv ${DESTINATION_DIR}/cold_start_trace_${SUFFIX}.csv 41 | 42 | RemoteExec $DATA_PLANE_NODE "sudo cp /data/proxy_trace.csv ~/proxy_trace.csv" 43 | scp $DATA_PLANE_NODE:~/proxy_trace.csv ${DESTINATION_DIR}/proxy_trace_${SUFFIX}.csv -------------------------------------------------------------------------------- /scripts/setup.cfg: -------------------------------------------------------------------------------- 1 | # Core component replicas (default: 1, for high-availability use 3) 2 | CONTROL_PLANE_REPLICAS=1 3 | # Do not change for now - FEATURE TO BE IMPLEMENTED 4 | DATA_PLANE_REPLICAS=1 5 | 6 | # Fake worker node experiment - enable = 1; disable = 0 7 | FAKE_WORKER_MODE=0 8 | DAEMONS_PER_NODE=1 9 | 10 | # Choose from [containerd, firecracker] 11 | WORKER_RUNTIME="containerd" -------------------------------------------------------------------------------- /scripts/start_async_data_plane.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | RemoteExec $DATAPLANE "cd ~/cluster_manager/cmd/data_plane; git pull; git reset --hard origin/current;/usr/local/go/bin/go run main.go --config config_cluster_async.yaml" -------------------------------------------------------------------------------- /scripts/start_control_plane.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | function StartControlplane() { 31 | 32 | #RemoteExec $1 "sudo apt update && sudo apt install -y haproxy" 33 | #RemoteExec $1 "sudo cp ~/cluster_manager/configs/haproxy.cfg /etc/haproxy/haproxy.cfg" 34 | 35 | # Kill old process 36 | RemoteExec $1 "sudo kill -9 \$(sudo lsof -t -i:9091)" 37 | 38 | # Start new data plane 39 | #RemoteExec $1 "cd ~/cluster_manager; sudo docker-compose up -d" 40 | RemoteExec $1 "cd ~/cluster_manager/cmd/master_node; git pull; git reset --hard origin/current; sudo /usr/local/go/bin/go run main.go --config $2" 41 | } 42 | 43 | if [ "$HA" = true ] ; 44 | then 45 | StartControlplane $CONTROLPLANE_1 config_cluster_raft_1.yaml & 46 | StartControlplane $CONTROLPLANE_2 config_cluster_raft_2.yaml & 47 | StartControlplane $CONTROLPLANE_3 config_cluster_raft_3.yaml 48 | else 49 | StartControlplane $CONTROLPLANE config_cluster.yaml 50 | fi -------------------------------------------------------------------------------- /scripts/start_data_plane.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | function StartDataplane() { 31 | # Kill old process 32 | RemoteExec $1 "sudo kill -9 \$(sudo lsof -t -i:8081)" 33 | 34 | # Start new dataplane 35 | RemoteExec $1 "cd ~/cluster_manager/cmd/data_plane; git pull; git reset --hard origin/current;sudo /usr/local/go/bin/go run main.go --config config_cluster.yaml" 36 | } 37 | 38 | if $HA; 39 | then 40 | StartDataplane $DATAPLANE_1 & 41 | StartDataplane $DATAPLANE_2 & 42 | StartDataplane $DATAPLANE_3 43 | else 44 | StartDataplane $DATAPLANE 45 | fi 46 | -------------------------------------------------------------------------------- /scripts/start_redis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | source $DIR/common.sh 29 | 30 | RemoteExec $INVITRO "cd ~/cluster_manager/; sudo docker-compose up" -------------------------------------------------------------------------------- /scripts/start_resource_monitoring.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MIT License 5 | # 6 | # Copyright (c) 2024 EASL 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | readonly DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" 28 | 29 | function internal() { 30 | # Connect to the remote machine and start a tmux session 31 | scp $DIR/../cmd/monitoring/monitoring.py $1:~/monitoring.py 32 | 33 | ssh $1 "tmux kill-session -t resource_monitoring" 34 | ssh $1 "tmux new-session -d -s resource_monitoring" 35 | ssh $1 "tmux send-keys -t resource_monitoring 'python3 ~/monitoring.py' ENTER" 36 | } 37 | 38 | for ip in "$@" 39 | do 40 | internal $ip & 41 | done 42 | 43 | wait -------------------------------------------------------------------------------- /scripts/string.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 EASL 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import argparse 24 | parser=argparse.ArgumentParser(description="Custom address generator with arugments") 25 | parser.add_argument('--type', required=False, default = "basic", type=str) 26 | args=parser.parse_args() 27 | 28 | start_addr = 0 29 | if args.type == "worker": 30 | start_addr = 3 31 | elif args.type == "worker-ha": 32 | start_addr = 7 33 | 34 | # Change this line with the automatic script 35 | list = ["Francois@pc841.emulab.net","Francois@pc790.emulab.net","Francois@pc738.emulab.net","Francois@pc734.emulab.net","Francois@pc848.emulab.net","Francois@pc737.emulab.net","Francois@pc795.emulab.net"] 36 | ans = "" 37 | 38 | for i in range (start_addr,len(list)): 39 | ans = ans + " " + str(list[i]) 40 | 41 | print(ans) -------------------------------------------------------------------------------- /scripts/systemd/control_plane.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Control plane service 3 | After=multi-user.target 4 | [Service] 5 | Type=simple 6 | Restart=always 7 | ExecStart=/cluster_manager/cmd/master_node/main --config /cluster_manager/cmd/master_node/config_cluster.yaml 8 | KillSignal=SIGKILL 9 | [Install] 10 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /scripts/systemd/data_plane.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Data plane service 3 | After=multi-user.target 4 | [Service] 5 | Type=simple 6 | Restart=always 7 | ExecStart=/cluster_manager/cmd/data_plane/main --config /cluster_manager/cmd/data_plane/config_cluster.yaml 8 | KillSignal=SIGKILL 9 | [Install] 10 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /scripts/systemd/worker_node.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Worker node service 3 | After=multi-user.target 4 | [Service] 5 | Type=simple 6 | Restart=always 7 | Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin:/usr/local/bin/firecracker" 8 | ExecStart=/cluster_manager/cmd/worker_node/main --config /cluster_manager/cmd/worker_node/config_cluster.yaml 9 | KillSignal=SIGKILL 10 | [Install] 11 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /workload/go.mod: -------------------------------------------------------------------------------- 1 | module workload 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.3 7 | github.com/sirupsen/logrus v1.9.3 8 | github.com/vhive-serverless/loader v0.0.0-20230918110343-89f72449fcbb 9 | google.golang.org/grpc v1.58.1 10 | ) 11 | 12 | require ( 13 | golang.org/x/net v0.12.0 // indirect 14 | golang.org/x/sys v0.10.0 // indirect 15 | golang.org/x/text v0.11.0 // indirect 16 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect 17 | google.golang.org/protobuf v1.31.0 // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /workload/workload.go: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2024 EASL 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package main 26 | 27 | func main() { 28 | StartHTTPServer() 29 | } 30 | --------------------------------------------------------------------------------