Skip to content

Commit

Permalink
Add initial implementation of Mesh Agent and Multipoint Groups (#295)
Browse files Browse the repository at this point in the history
* Add initial implementation of Mesh Agent and Multipoint Groups

* Implement Mesh Agent to manage media proxies, connections,
bridges, and multipoint groups.
* Integrate ST2110-xx and RDMA bridges to multipoint groups.
* Implement configuration reconciliation logic in media proxy.

Signed-off-by: Konstantin Ilichev <[email protected]>

* Update setup_build_env.sh

* Update Dockerfile

* Fix go version

Signed-off-by: Konstantin Ilichev <[email protected]>

* Minor fixes

Signed-off-by: Konstantin Ilichev <[email protected]>

* Replace 65536 with 65535 in Agent for better code style

Signed-off-by: Konstantin Ilichev <[email protected]>

* Install golang from source not pkg manager

Install golang from source not pkg manager

Signed-off-by: Milosz Linkiewicz <[email protected]>

* Update media-proxy Dockerfile with golang install

Update media-proxy Dockerfile with golang install

Signed-off-by: Milosz Linkiewicz <[email protected]>

* [FIX] Dockerfiles versions.env fixes, usage and adjustments

[FIX] Dockerfiles versions.env usage and fixed
[FIX] Added missing package `curl`
[FIX] Install golang v1.23 from source (pkg manager ver. <1.23)
[UPDATE] Update golang dependencies to non-vulnerable ones
[UPDATE] Minor Dockerfiles fixes

Signed-off-by: Milosz Linkiewicz <[email protected]>

* Moved GoLang bin versions to verions.env file

Moved GoLang bin versions to verions.env file.
This is to unify versioning in pre-required components.

Signed-off-by: Milosz Linkiewicz <[email protected]>

---------

Signed-off-by: Konstantin Ilichev <[email protected]>
Signed-off-by: Milosz Linkiewicz <[email protected]>
Co-authored-by: Miłosz Linkiewicz <[email protected]>
  • Loading branch information
ko80 and Mionsz authored Dec 31, 2024
1 parent 0d55e62 commit bf65034
Show file tree
Hide file tree
Showing 85 changed files with 5,957 additions and 230 deletions.
7 changes: 3 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ dump_*
irdma/

# for gRPC protos
media-proxy/protos/controller.grpc.pb.cc
media-proxy/protos/controller.grpc.pb.h
media-proxy/protos/controller.pb.cc
media-proxy/protos/controller.pb.h
*.pb.cc
*.pb.h
*.pb.go

# for VS Code settings
.vscode/*
Expand Down
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ set(MP_TESTS_DIR ${MP_DIR}/tests)
set(SDK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk)
set(SDK_TESTS_DIR ${SDK_DIR}/tests)
set(SDK_INCLUDE_DIR ${SDK_DIR}/include)
set(AGENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/control-plane-agent)
set(TESTS_VAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests/validation)

# Setup output folder
Expand All @@ -34,7 +35,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

add_subdirectory(${SDK_DIR})
add_subdirectory(${MP_DIR})

add_subdirectory(${AGENT_DIR})

# Fetch google test dependencies
include(FetchContent)
Expand All @@ -54,4 +55,4 @@ if (BUILD_UNIT_TESTS)
target_link_libraries(media_proxy_lib PUBLIC mcm_dp gtest gmock gtest_main)
else()
target_link_libraries(media_proxy_lib PUBLIC mcm_dp)
endif()
endif()
8 changes: 5 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ as_root ldconfig

# Run unit tests
export LD_LIBRARY_PATH="${PREFIX_DIR}/usr/local/lib:/usr/local/lib64"
ctest --output-on-failure --test-dir "${MCM_BUILD_DIR}" -V

"${MCM_BUILD_DIR}/bin/sdk_unit_tests"
"${MCM_BUILD_DIR}/bin/media_proxy_unit_tests"
ln -sf "${MCM_BUILD_DIR}" "${SCRIPT_DIR}/build"

log_info "Build Succeeded"
function print_success() { echo -e "\e[48;2;0;255;0;30m $* \e[0m"; }

print_success "Build Succeeded"
75 changes: 75 additions & 0 deletions control-plane-agent/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause

cmake_minimum_required(VERSION 3.10)

# Project name
project(ControlPlaneAgent)

# Set the Go compiler
find_program(GO_EXECUTABLE NAMES go)

if(NOT GO_EXECUTABLE)
message(FATAL_ERROR "Go compiler not found. Please install Go.")
endif()

# Find the protoc compiler
find_program(PROTOC_EXECUTABLE NAMES protoc)

if(NOT PROTOC_EXECUTABLE)
message(FATAL_ERROR "protoc compiler not found. Please install Protocol Buffers.")
endif()

# Define the paths to the protoc-gen-go and protoc-gen-go-grpc plugins
set(PROTOC_GEN_GO_EXECUTABLE "$ENV{HOME}/go/bin/protoc-gen-go")
set(PROTOC_GEN_GO_GRPC_EXECUTABLE "$ENV{HOME}/go/bin/protoc-gen-go-grpc")

if(NOT EXISTS ${PROTOC_GEN_GO_EXECUTABLE})
message(FATAL_ERROR "protoc-gen-go plugin not found. Please install the Go Protocol Buffers plugin.")
endif()

if(NOT EXISTS ${PROTOC_GEN_GO_GRPC_EXECUTABLE})
message(FATAL_ERROR "protoc-gen-go-grpc plugin not found. Please install the Go gRPC plugin.")
endif()

# Define the source directory and the main Go file
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmd/mesh-agent")
set(MAIN_GO_FILE "${SOURCE_DIR}/mesh-agent.go")
set(CMAKE_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/bin)

# Define the proto file and the output directory for generated code
set(PROTO_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../protos/mediaproxy.proto")
set(GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/api/proxy/proto/mediaproxy")

# Define the output directory for the executable
set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../_build/mcm/bin")

# Create the output directories if they don't exist
file(MAKE_DIRECTORY ${OUTPUT_DIR})
file(MAKE_DIRECTORY ${GENERATED_DIR})

# Define the output executable name
set(EXECUTABLE_NAME "mesh-agent")

# Add a custom target to generate gRPC code from the proto file
add_custom_target(generate_grpc
COMMAND ${PROTOC_EXECUTABLE}
--proto_path=${CMAKE_CURRENT_SOURCE_DIR}/../protos
--go_out=paths=source_relative:${GENERATED_DIR}
--go-grpc_out=paths=source_relative:${GENERATED_DIR}
--plugin=protoc-gen-go=${PROTOC_GEN_GO_EXECUTABLE}
--plugin=protoc-gen-go-grpc=${PROTOC_GEN_GO_GRPC_EXECUTABLE}
${PROTO_FILE}
COMMENT "Generating gRPC code from proto file..."
)

# Add a custom target to build the Go project
add_custom_target(build ALL
COMMAND ${GO_EXECUTABLE} build -o ${OUTPUT_DIR}/${EXECUTABLE_NAME} ${MAIN_GO_FILE}
WORKING_DIRECTORY ${SOURCE_DIR}
COMMENT "Building Go project..."
DEPENDS generate_grpc
)

install(PROGRAMS ${OUTPUT_DIR}/${EXECUTABLE_NAME} DESTINATION ${CMAKE_INSTALL_PATH})
97 changes: 97 additions & 0 deletions control-plane-agent/api/control-plane/bridge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: BSD-3-Clause
*/

package controlplane

import (
"encoding/json"
"errors"
"net/http"

"github.com/gorilla/mux"

"control-plane-agent/internal/model"
"control-plane-agent/internal/registry"
)

func (a *API) ListBridges(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
addStatus := query.Has("status")
addConfig := query.Has("config")

items, err := registry.BridgeRegistry.List(r.Context(), nil, addStatus, addConfig)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

resp := struct {
Bridge []model.Bridge `json:"bridge"`
}{
Bridge: items,
}
applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(resp)
}

func (a *API) GetBridge(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
addConfig := r.URL.Query().Has("config")

item, err := registry.BridgeRegistry.Get(r.Context(), id, addConfig)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

item.Id = "" // hide the id in JSON (omitempty)

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(item)
}

func (a *API) AddBridge(w http.ResponseWriter, r *http.Request) {
// DEBUG
proxyId := r.URL.Query().Get("proxy")
groupId := r.URL.Query().Get("group")
// DEBUG

bridge := model.Bridge{
ProxyId: proxyId,
GroupId: groupId,
Config: &model.BridgeConfig{},
Status: &model.ConnectionStatus{},
}

id, err := registry.BridgeRegistry.Add(r.Context(), bridge)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

bridge = model.Bridge{Id: id}

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(bridge)
}

func (a *API) DeleteBridge(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

err := registry.BridgeRegistry.Delete(r.Context(), id)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
94 changes: 94 additions & 0 deletions control-plane-agent/api/control-plane/conn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: BSD-3-Clause
*/

package controlplane

import (
"encoding/json"
"errors"
"net/http"

"github.com/gorilla/mux"

"control-plane-agent/internal/model"
"control-plane-agent/internal/registry"
)

func (a *API) ListConnections(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
addStatus := query.Has("status")
addConfig := query.Has("config")

items, err := registry.ConnRegistry.List(r.Context(), nil, addStatus, addConfig)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

resp := struct {
Conn []model.Connection `json:"connection"`
}{
Conn: items,
}
applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(resp)
}

func (a *API) GetConnection(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
addConfig := r.URL.Query().Has("config")

item, err := registry.ConnRegistry.Get(r.Context(), id, addConfig)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

item.Id = "" // hide the id in JSON (omitempty)

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(item)
}

func (a *API) AddConnection(w http.ResponseWriter, r *http.Request) {

conn := model.Connection{
Status: &model.ConnectionStatus{},
Config: &model.ConnectionConfig{
Conn: model.ConnectionST2110{},
// Payload: model.PayloadVideo{},
},
}

id, err := registry.ConnRegistry.Add(r.Context(), conn)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

conn = model.Connection{Id: id}

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(conn)
}

func (a *API) DeleteConnection(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

err := registry.ConnRegistry.Delete(r.Context(), id)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
Loading

0 comments on commit bf65034

Please sign in to comment.