From 32208449b2cf4de7b9c6b05b1bf58538f7f8640a Mon Sep 17 00:00:00 2001 From: liuxu Date: Thu, 21 Nov 2024 11:58:36 +0800 Subject: [PATCH 153/156] sandbox: sandbox api adapt rust interface Signed-off-by: liuxu --- cmake/options.cmake | 10 +- cmake/protoc.cmake | 10 - src/CMakeLists.txt | 4 + .../sandbox/google/protobuf/any.proto | 155 ------ .../sandbox/google/protobuf/empty.proto | 52 -- .../sandbox/google/protobuf/timestamp.proto | 138 ------ src/api/services/sandbox/sandbox.proto | 204 -------- .../sandbox/sandbox/types/metrics.proto | 30 -- .../sandbox/sandbox/types/mount.proto | 43 -- .../sandbox/sandbox/types/platform.proto | 30 -- .../sandbox/sandbox/types/sandbox.proto | 54 -- src/daemon/common/cri/v1/v1_cri_helpers.cc | 3 +- src/daemon/sandbox/CMakeLists.txt | 27 +- .../sandbox/{controller => }/controller.h | 34 +- src/daemon/sandbox/controller/CMakeLists.txt | 32 -- .../sandboxer/client/CMakeLists.txt | 20 - .../sandboxer/client/grpc_async_wait_call.cc | 142 ------ .../sandboxer/client/grpc_async_wait_call.h | 94 ---- .../sandboxer/client/grpc_client_utils.cc | 36 -- .../sandboxer/client/grpc_client_utils.h | 23 - .../sandboxer/client/grpc_sandboxer_client.cc | 337 ------------- .../client/grpc_sandboxer_monitor.cc | 314 ------------ .../sandboxer/client/grpc_sandboxer_monitor.h | 85 ---- .../{controller => }/controller_manager.cc | 3 - .../{controller => }/controller_manager.h | 0 src/daemon/sandbox/sandbox.cc | 215 -------- src/daemon/sandbox/sandbox.h | 26 +- src/daemon/sandbox/sandbox_manager.cc | 44 +- src/daemon/sandbox/sandbox_ops.cc | 250 +++++++--- src/daemon/sandbox/sandbox_task.cc | 7 +- src/daemon/sandbox/sandboxer/CMakeLists.txt | 15 + .../controller}/CMakeLists.txt | 0 .../controller/client/CMakeLists.txt | 12 + .../client/grpc_sandboxer_client.cc | 463 ++++++++++++++++++ .../client/grpc_sandboxer_client.h | 46 +- .../controller}/sandboxer_controller.cc | 27 +- .../controller}/sandboxer_controller.h | 9 +- .../sandbox/sandboxer/sandboxer_sandbox.cc | 254 ++++++++++ .../sandbox/sandboxer/sandboxer_sandbox.h | 63 +++ src/daemon/sandbox/shim/CMakeLists.txt | 15 + .../shim => shim/controller}/CMakeLists.txt | 0 .../controller}/shim_controller.cc | 19 +- .../controller}/shim_controller.h | 12 +- src/daemon/sandbox/shim/shim_sandbox.cc | 65 +++ src/daemon/sandbox/shim/shim_sandbox.h | 49 ++ 45 files changed, 1225 insertions(+), 2246 deletions(-) delete mode 100644 src/api/services/sandbox/google/protobuf/any.proto delete mode 100644 src/api/services/sandbox/google/protobuf/empty.proto delete mode 100644 src/api/services/sandbox/google/protobuf/timestamp.proto delete mode 100644 src/api/services/sandbox/sandbox.proto delete mode 100644 src/api/services/sandbox/sandbox/types/metrics.proto delete mode 100644 src/api/services/sandbox/sandbox/types/mount.proto delete mode 100644 src/api/services/sandbox/sandbox/types/platform.proto delete mode 100644 src/api/services/sandbox/sandbox/types/sandbox.proto rename src/daemon/sandbox/{controller => }/controller.h (79%) delete mode 100644 src/daemon/sandbox/controller/CMakeLists.txt delete mode 100755 src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h rename src/daemon/sandbox/{controller => }/controller_manager.cc (98%) rename src/daemon/sandbox/{controller => }/controller_manager.h (100%) create mode 100755 src/daemon/sandbox/sandboxer/CMakeLists.txt rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/CMakeLists.txt (100%) create mode 100755 src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt create mode 100644 src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/client/grpc_sandboxer_client.h (54%) rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/sandboxer_controller.cc (78%) rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/sandboxer_controller.h (82%) create mode 100644 src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc create mode 100644 src/daemon/sandbox/sandboxer/sandboxer_sandbox.h create mode 100755 src/daemon/sandbox/shim/CMakeLists.txt rename src/daemon/sandbox/{controller/shim => shim/controller}/CMakeLists.txt (100%) rename src/daemon/sandbox/{controller/shim => shim/controller}/shim_controller.cc (97%) rename src/daemon/sandbox/{controller/shim => shim/controller}/shim_controller.h (89%) create mode 100644 src/daemon/sandbox/shim/shim_sandbox.cc create mode 100644 src/daemon/sandbox/shim/shim_sandbox.h diff --git a/cmake/options.cmake b/cmake/options.cmake index 41177fe0..cee83ef2 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -53,9 +53,13 @@ endif() option(ENABLE_SANDBOXER "Enable sandbox API" OFF) if (ENABLE_SANDBOXER STREQUAL "ON") - add_definitions(-DENABLE_SANDBOXER) - set(ENABLE_SANDBOXER 1) - message("${Green}-- Enable sandbox API${ColourReset}") + if (ENABLE_CRI_API_V1) + add_definitions(-DENABLE_SANDBOXER) + set(ENABLE_SANDBOXER 1) + message("${Green}-- Enable sandbox API${ColourReset}") + else() + message("${Yellow}-- Can not enable sandboxer, sandboxer need enable CRI API V1 first ${ColourReset}") + endif() endif() option(ENABLE_OOM_MONITOR "Enable oom monitor" ON) diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake index 6343fe3e..de337f25 100644 --- a/cmake/protoc.cmake +++ b/cmake/protoc.cmake @@ -66,13 +66,3 @@ if (GRPC_CONNECTOR) PROTOC_GRPC_GEN(network ${NETWORK_PROTOS_OUT_PATH} ${PROTOS_PATH}/network/network.proto) endif() endif() - -if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) - execute_process(COMMAND mkdir -p ${SANDBOX_PROTOS_OUT_PATH}) - PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/sandbox.proto) - PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/mount.proto) - PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/platform.proto) - PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/metrics.proto) - PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox.proto) - PROTOC_GRPC_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox.proto) -endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 70a8ac91..6aab3f69 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -200,6 +200,10 @@ else() set_target_properties(isulad PROPERTIES LINKER_LANGUAGE "C") endif() +if (ENABLE_SANDBOXER) + target_link_libraries(isulad isula_sandbox) +endif() + target_link_libraries(isulad libisulad_tools libhttpclient -ldl) if (ANDROID OR MUSL) target_link_libraries(isulad ${LIBSSL_LIBRARY} ${LIBYAJL_LIBRARY}) diff --git a/src/api/services/sandbox/google/protobuf/any.proto b/src/api/services/sandbox/google/protobuf/any.proto deleted file mode 100644 index c9be8541..00000000 --- a/src/api/services/sandbox/google/protobuf/any.proto +++ /dev/null @@ -1,155 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/any"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "AnyProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// `Any` contains an arbitrary serialized protocol buffer message along with a -// URL that describes the type of the serialized message. -// -// Protobuf library provides support to pack/unpack Any values in the form -// of utility functions or additional generated methods of the Any type. -// -// Example 1: Pack and unpack a message in C++. -// -// Foo foo = ...; -// Any any; -// any.PackFrom(foo); -// ... -// if (any.UnpackTo(&foo)) { -// ... -// } -// -// Example 2: Pack and unpack a message in Java. -// -// Foo foo = ...; -// Any any = Any.pack(foo); -// ... -// if (any.is(Foo.class)) { -// foo = any.unpack(Foo.class); -// } -// -// Example 3: Pack and unpack a message in Python. -// -// foo = Foo(...) -// any = Any() -// any.Pack(foo) -// ... -// if any.Is(Foo.DESCRIPTOR): -// any.Unpack(foo) -// ... -// -// Example 4: Pack and unpack a message in Go -// -// foo := &pb.Foo{...} -// any, err := ptypes.MarshalAny(foo) -// ... -// foo := &pb.Foo{} -// if err := ptypes.UnmarshalAny(any, foo); err != nil { -// ... -// } -// -// The pack methods provided by protobuf library will by default use -// 'type.googleapis.com/full.type.name' as the type URL and the unpack -// methods only use the fully qualified type name after the last '/' -// in the type URL, for example "foo.bar.com/x/y.z" will yield type -// name "y.z". -// -// -// JSON -// ==== -// The JSON representation of an `Any` value uses the regular -// representation of the deserialized, embedded message, with an -// additional field `@type` which contains the type URL. Example: -// -// package google.profile; -// message Person { -// string first_name = 1; -// string last_name = 2; -// } -// -// { -// "@type": "type.googleapis.com/google.profile.Person", -// "firstName": , -// "lastName": -// } -// -// If the embedded message type is well-known and has a custom JSON -// representation, that representation will be embedded adding a field -// `value` which holds the custom JSON in addition to the `@type` -// field. Example (for message [google.protobuf.Duration][]): -// -// { -// "@type": "type.googleapis.com/google.protobuf.Duration", -// "value": "1.212s" -// } -// -message Any { - // A URL/resource name that uniquely identifies the type of the serialized - // protocol buffer message. This string must contain at least - // one "/" character. The last segment of the URL's path must represent - // the fully qualified name of the type (as in - // `path/google.protobuf.Duration`). The name should be in a canonical form - // (e.g., leading "." is not accepted). - // - // In practice, teams usually precompile into the binary all types that they - // expect it to use in the context of Any. However, for URLs which use the - // scheme `http`, `https`, or no scheme, one can optionally set up a type - // server that maps type URLs to message definitions as follows: - // - // * If no scheme is provided, `https` is assumed. - // * An HTTP GET on the URL must yield a [google.protobuf.Type][] - // value in binary format, or produce an error. - // * Applications are allowed to cache lookup results based on the - // URL, or have them precompiled into a binary to avoid any - // lookup. Therefore, binary compatibility needs to be preserved - // on changes to types. (Use versioned type names to manage - // breaking changes.) - // - // Note: this functionality is not currently available in the official - // protobuf release, and it is not used for type URLs beginning with - // type.googleapis.com. - // - // Schemes other than `http`, `https` (or the empty scheme) might be - // used with implementation specific semantics. - // - string type_url = 1; - - // Must be a valid serialized protocol buffer of the above specified type. - bytes value = 2; -} diff --git a/src/api/services/sandbox/google/protobuf/empty.proto b/src/api/services/sandbox/google/protobuf/empty.proto deleted file mode 100644 index 03cacd23..00000000 --- a/src/api/services/sandbox/google/protobuf/empty.proto +++ /dev/null @@ -1,52 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/empty"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "EmptyProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; -option cc_enable_arenas = true; - -// A generic empty message that you can re-use to avoid defining duplicated -// empty messages in your APIs. A typical example is to use it as the request -// or the response type of an API method. For instance: -// -// service Foo { -// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); -// } -// -// The JSON representation for `Empty` is empty JSON object `{}`. -message Empty {} diff --git a/src/api/services/sandbox/google/protobuf/timestamp.proto b/src/api/services/sandbox/google/protobuf/timestamp.proto deleted file mode 100644 index cd357864..00000000 --- a/src/api/services/sandbox/google/protobuf/timestamp.proto +++ /dev/null @@ -1,138 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/timestamp"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "TimestampProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// A Timestamp represents a point in time independent of any time zone or local -// calendar, encoded as a count of seconds and fractions of seconds at -// nanosecond resolution. The count is relative to an epoch at UTC midnight on -// January 1, 1970, in the proleptic Gregorian calendar which extends the -// Gregorian calendar backwards to year one. -// -// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap -// second table is needed for interpretation, using a [24-hour linear -// smear](https://developers.google.com/time/smear). -// -// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By -// restricting to that range, we ensure that we can convert to and from [RFC -// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. -// -// # Examples -// -// Example 1: Compute Timestamp from POSIX `time()`. -// -// Timestamp timestamp; -// timestamp.set_seconds(time(NULL)); -// timestamp.set_nanos(0); -// -// Example 2: Compute Timestamp from POSIX `gettimeofday()`. -// -// struct timeval tv; -// gettimeofday(&tv, NULL); -// -// Timestamp timestamp; -// timestamp.set_seconds(tv.tv_sec); -// timestamp.set_nanos(tv.tv_usec * 1000); -// -// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. -// -// FILETIME ft; -// GetSystemTimeAsFileTime(&ft); -// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; -// -// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z -// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. -// Timestamp timestamp; -// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); -// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); -// -// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. -// -// long millis = System.currentTimeMillis(); -// -// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) -// .setNanos((int) ((millis % 1000) * 1000000)).build(); -// -// -// Example 5: Compute Timestamp from current time in Python. -// -// timestamp = Timestamp() -// timestamp.GetCurrentTime() -// -// # JSON Mapping -// -// In JSON format, the Timestamp type is encoded as a string in the -// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the -// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" -// where {year} is always expressed using four digits while {month}, {day}, -// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional -// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), -// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone -// is required. A proto3 JSON serializer should always use UTC (as indicated by -// "Z") when printing the Timestamp type and a proto3 JSON parser should be -// able to accept both UTC and other timezones (as indicated by an offset). -// -// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past -// 01:30 UTC on January 15, 2017. -// -// In JavaScript, one can convert a Date object to this format using the -// standard -// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) -// method. In Python, a standard `datetime.datetime` object can be converted -// to this format using -// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with -// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use -// the Joda Time's [`ISODateTimeFormat.dateTime()`]( -// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D -// ) to obtain a formatter capable of generating timestamps in this format. -// -// -message Timestamp { - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. - int32 nanos = 2; -} diff --git a/src/api/services/sandbox/sandbox.proto b/src/api/services/sandbox/sandbox.proto deleted file mode 100644 index dcc78444..00000000 --- a/src/api/services/sandbox/sandbox.proto +++ /dev/null @@ -1,204 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -syntax = "proto3"; - -// Sandbox is a v2 runtime extension that allows more complex execution environments for containers. -// This adds a notion of groups of containers that share same lifecycle and/or resources. -// A few good fits for sandbox can be: -// - A "pause" container in k8s, that acts as a parent process for child containers to hold network namespace. -// - (micro)VMs that launch a VM process and executes containers inside guest OS. -// containerd in this case remains implementation agnostic and delegates sandbox handling to runtimes. -// See proposal and discussion here: https://github.com/containerd/containerd/issues/4131 -package containerd.services.sandbox.v1; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; - -import "sandbox/types/sandbox.proto"; -import "sandbox/types/mount.proto"; -import "sandbox/types/platform.proto"; -import "sandbox/types/metrics.proto"; - -option go_package = "github.com/containerd/containerd/api/services/sandbox/v1;sandbox"; - -// Store provides a metadata storage interface for sandboxes. Similarly to `Containers`, -// sandbox object includes info required to start a new instance, but no runtime state. -// When running a new sandbox instance, store objects are used as base type to create from. -service Store { - rpc Create(StoreCreateRequest) returns (StoreCreateResponse); - rpc Update(StoreUpdateRequest) returns (StoreUpdateResponse); - rpc Delete(StoreDeleteRequest) returns (StoreDeleteResponse); - rpc List(StoreListRequest) returns (StoreListResponse); - rpc Get(StoreGetRequest) returns (StoreGetResponse); -} - -message StoreCreateRequest { - containerd.types.Sandbox sandbox = 1; -} - -message StoreCreateResponse { - containerd.types.Sandbox sandbox = 1; -} - -message StoreUpdateRequest { - containerd.types.Sandbox sandbox = 1; - repeated string fields = 2; -} - -message StoreUpdateResponse { - containerd.types.Sandbox sandbox = 1; -} - -message StoreDeleteRequest { - string sandbox_id = 1; -} - -message StoreDeleteResponse {} - -message StoreListRequest { - repeated string filters = 1; -} - -message StoreListResponse { - repeated containerd.types.Sandbox list = 1; -} - -message StoreGetRequest { - string sandbox_id = 1; -} - -message StoreGetResponse { - containerd.types.Sandbox sandbox = 1; -} - -// Controller is an interface to manage runtime sandbox instances. -service Controller { - rpc Create(ControllerCreateRequest) returns (ControllerCreateResponse); - rpc Start(ControllerStartRequest) returns (ControllerStartResponse); - rpc Platform(ControllerPlatformRequest) returns (ControllerPlatformResponse); - rpc Stop(ControllerStopRequest) returns (ControllerStopResponse); - rpc Wait(ControllerWaitRequest) returns (ControllerWaitResponse); - rpc Status(ControllerStatusRequest) returns (ControllerStatusResponse); - rpc Shutdown(ControllerShutdownRequest) returns (ControllerShutdownResponse); - rpc Metrics(ControllerMetricsRequest) returns (ControllerMetricsResponse); - rpc Update(ControllerUpdateRequest) returns (ControllerUpdateResponse); -} - -message ControllerCreateRequest { - string sandbox_id = 1; - repeated containerd.types.Mount rootfs = 2; - google.protobuf.Any options = 3; - string netns_path = 4; - map annotations = 5; - containerd.types.Sandbox sandbox = 6; - string sandboxer = 10; -} - -message ControllerCreateResponse { - string sandbox_id = 1; -} - -message ControllerStartRequest { - string sandbox_id = 1; - string sandboxer = 10; -} - -message ControllerStartResponse { - string sandbox_id = 1; - uint32 pid = 2; - google.protobuf.Timestamp created_at = 3; - map labels = 4; - // Address of the sandbox for containerd to connect, - // for calling Task or other APIs serving in the sandbox. - // it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://:. - string address = 5; - uint32 version = 6; -} - -message ControllerPlatformRequest { - string sandbox_id = 1; - string sandboxer = 10; -} - -message ControllerPlatformResponse { - containerd.types.Platform platform = 1; -} - -message ControllerStopRequest { - string sandbox_id = 1; - uint32 timeout_secs = 2; - string sandboxer = 10; -} - -message ControllerStopResponse {} - -message ControllerWaitRequest { - string sandbox_id = 1; - string sandboxer = 10; -} - -message ControllerWaitResponse { - uint32 exit_status = 1; - google.protobuf.Timestamp exited_at = 2; -} - -message ControllerStatusRequest { - string sandbox_id = 1; - bool verbose = 2; - string sandboxer = 10; -} - -message ControllerStatusResponse { - string sandbox_id = 1; - uint32 pid = 2; - string state = 3; - map info = 4; - google.protobuf.Timestamp created_at = 5; - google.protobuf.Timestamp exited_at = 6; - google.protobuf.Any extra = 7; - // Address of the sandbox for containerd to connect, - // for calling Task or other APIs serving in the sandbox. - // it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://:. - string address = 8; - uint32 version = 9; -} - -message ControllerShutdownRequest { - string sandbox_id = 1; - string sandboxer = 10; -} - -message ControllerShutdownResponse {} - -message ControllerMetricsRequest { - string sandbox_id = 1; - string sandboxer = 10; -} - -message ControllerMetricsResponse { - types.Metric metrics = 1; -} - -message ControllerUpdateRequest { - string sandbox_id = 1; - string sandboxer = 2; - containerd.types.Sandbox sandbox = 3; - repeated string fields = 4; -} - -message ControllerUpdateResponse { -} \ No newline at end of file diff --git a/src/api/services/sandbox/sandbox/types/metrics.proto b/src/api/services/sandbox/sandbox/types/metrics.proto deleted file mode 100644 index 61185939..00000000 --- a/src/api/services/sandbox/sandbox/types/metrics.proto +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -syntax = "proto3"; - -package containerd.types; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "github.com/containerd/containerd/api/types;types"; - -message Metric { - google.protobuf.Timestamp timestamp = 1; - string id = 2; - google.protobuf.Any data = 3; -} \ No newline at end of file diff --git a/src/api/services/sandbox/sandbox/types/mount.proto b/src/api/services/sandbox/sandbox/types/mount.proto deleted file mode 100644 index 54e0a0cd..00000000 --- a/src/api/services/sandbox/sandbox/types/mount.proto +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -syntax = "proto3"; - -package containerd.types; - -option go_package = "github.com/containerd/containerd/api/types;types"; - -// Mount describes mounts for a container. -// -// This type is the lingua franca of ContainerD. All services provide mounts -// to be used with the container at creation time. -// -// The Mount type follows the structure of the mount syscall, including a type, -// source, target and options. -message Mount { - // Type defines the nature of the mount. - string type = 1; - - // Source specifies the name of the mount. Depending on mount type, this - // may be a volume name or a host path, or even ignored. - string source = 2; - - // Target path in container - string target = 3; - - // Options specifies zero or more fstab style mount options. - repeated string options = 4; -} diff --git a/src/api/services/sandbox/sandbox/types/platform.proto b/src/api/services/sandbox/sandbox/types/platform.proto deleted file mode 100644 index 102e6e2b..00000000 --- a/src/api/services/sandbox/sandbox/types/platform.proto +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -syntax = "proto3"; - -package containerd.types; - -option go_package = "github.com/containerd/containerd/api/types;types"; - -// Platform follows the structure of the OCI platform specification, from -// descriptors. -message Platform { - string os = 1; - string architecture = 2; - string variant = 3; - string os_version = 4; -} \ No newline at end of file diff --git a/src/api/services/sandbox/sandbox/types/sandbox.proto b/src/api/services/sandbox/sandbox/types/sandbox.proto deleted file mode 100644 index 6fe08d40..00000000 --- a/src/api/services/sandbox/sandbox/types/sandbox.proto +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -syntax = "proto3"; - -package containerd.types; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "github.com/containerd/containerd/api/types;types"; - -// Sandbox represents a sandbox metadata object that keeps all info required by controller to -// work with a particular instance. -message Sandbox { - // SandboxID is a unique instance identifier within namespace - string sandbox_id = 1; - message Runtime { - // Name is the name of the runtime. - string name = 1; - // Options specify additional runtime initialization options for the shim (this data will be available in StartShim). - // Typically this data expected to be runtime shim implementation specific. - google.protobuf.Any options = 2; - } - // Runtime specifies which runtime to use for executing this container. - Runtime runtime = 2; - // Spec is sandbox configuration (kin of OCI runtime spec), spec's data will be written to a config.json file in the - // bundle directory (similary to OCI spec). - google.protobuf.Any spec = 3; - // Labels provides an area to include arbitrary data on containers. - map labels = 4; - // CreatedAt is the time the container was first created. - google.protobuf.Timestamp created_at = 5; - // UpdatedAt is the last time the container was mutated. - google.protobuf.Timestamp updated_at = 6; - // Extensions allow clients to provide optional blobs that can be handled by runtime. - map extensions = 7; - // Sandboxer is the name of the sandbox controller who manages the sandbox. - string sandboxer = 10; - -} \ No newline at end of file diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.cc b/src/daemon/common/cri/v1/v1_cri_helpers.cc index 31b6b137..dfe14ade 100644 --- a/src/daemon/common/cri/v1/v1_cri_helpers.cc +++ b/src/daemon/common/cri/v1/v1_cri_helpers.cc @@ -397,7 +397,7 @@ std::string CRISandboxerConvert(const std::string &runtime) std::string sandboxer; defs_map_string_object_sandboxer *criSandboxerList = nullptr; - if (runtime.empty() || runtime == DEFAULT_SANDBOXER_NAME) { + if (runtime.empty()) { return DEFAULT_SANDBOXER_NAME; } @@ -412,6 +412,7 @@ std::string CRISandboxerConvert(const std::string &runtime) goto out; } + sandboxer = DEFAULT_SANDBOXER_NAME; criSandboxerList = args->json_confs->cri_sandboxers; for (size_t i = 0; i < criSandboxerList->len; i++) { if (criSandboxerList->keys[i] == nullptr || criSandboxerList->values[i] == nullptr || diff --git a/src/daemon/sandbox/CMakeLists.txt b/src/daemon/sandbox/CMakeLists.txt index 7679ea68..2c31f243 100644 --- a/src/daemon/sandbox/CMakeLists.txt +++ b/src/daemon/sandbox/CMakeLists.txt @@ -1,15 +1,32 @@ # get current directory sources files aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_top_srcs) -add_subdirectory(controller) -set(SANDBOX_SRCS +set(local_sandbox_top_srcs ${sandbox_top_srcs} - ${SANDBOX_CONTROLLER_SRCS} + ) +set(local_sandbox_top_incs + ${CMAKE_CURRENT_SOURCE_DIR} + ) + +if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) + add_subdirectory(sandboxer) + list (APPEND local_sandbox_top_srcs + ${SANDBOXER_SANDBOX_SRCS} + ) + list (APPEND local_sandbox_top_incs + ${SANDBOXER_SANDBOX_INCS} + ) +endif() + +add_subdirectory(shim) +set(SANDBOX_SRCS + ${local_sandbox_top_srcs} + ${SHIM_SANDBOX_SRCS} PARENT_SCOPE ) set(SANDBOX_INCS - ${CMAKE_CURRENT_SOURCE_DIR} - ${SANDBOX_CONTROLLER_INCS} + ${local_sandbox_top_incs} + ${SHIM_SANDBOX_INCS} PARENT_SCOPE ) \ No newline at end of file diff --git a/src/daemon/sandbox/controller/controller.h b/src/daemon/sandbox/controller.h similarity index 79% rename from src/daemon/sandbox/controller/controller.h rename to src/daemon/sandbox/controller.h index 60d2dee5..0975015a 100644 --- a/src/daemon/sandbox/controller/controller.h +++ b/src/daemon/sandbox/controller.h @@ -22,15 +22,19 @@ #include #include +#include + #include "errors.h" #include "api_v1.pb.h" -#include "sandbox.pb.h" +#include "utils_array.h" namespace sandbox { #define SANDBOX_READY_STATE_STR "SANDBOX_READY" #define SANDBOX_NOTREADY_STATE_STR "SANDBOX_NOTREADY" +const std::string SHIM_CONTROLLER_NAME = "shim"; + struct ControllerMountInfo { std::string source; std::string destination; @@ -66,7 +70,7 @@ struct ControllerSandboxInfo { uint32_t pid; uint64_t createdAt; std::string taskAddress; - std::string version; + uint32_t version; google::protobuf::Map labels; }; @@ -80,7 +84,7 @@ struct ControllerSandboxStatus { uint32_t pid; std::string state; std::string taskAddress; - std::string version; + uint32_t version; google::protobuf::Map info; uint64_t createdAt; uint64_t exitedAt; @@ -95,20 +99,6 @@ struct ControllerStreamInfo { bool terminal; }; -struct ControllerPrepareParams { - std::string containerId; - std::string execId; - std::unique_ptr spec; - std::vector> rootfs; - std::unique_ptr streamInfo; -}; - -struct ControllerUpdateResourcesParams { - std::string containerId; - std::unique_ptr resources; - google::protobuf::Map &annotations; -}; - class SandboxStatusCallback { public: virtual void OnSandboxReady() = 0; @@ -120,19 +110,13 @@ class Controller { public: virtual ~Controller() {}; virtual bool Init(Errors &error) = 0; - virtual void Destroy() = 0; virtual bool Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) = 0; virtual std::unique_ptr Start(const std::string &sandboxId, Errors &error) = 0 ; virtual std::unique_ptr Platform(const std::string &sandboxId, Errors &error) = 0; - virtual bool Prepare(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) = 0; - virtual bool Purge(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) = 0; - virtual bool UpdateResources(const std::string &sandboxId, - const ControllerUpdateResourcesParams ¶ms, - Errors &error) = 0; + virtual bool Update(sandbox_sandbox *apiSandbox, + string_array *fields, Errors &error) = 0; virtual bool Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) = 0; virtual bool Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) = 0; virtual std::unique_ptr Status(const std::string &sandboxId, bool verbose, Errors &error) = 0; diff --git a/src/daemon/sandbox/controller/CMakeLists.txt b/src/daemon/sandbox/controller/CMakeLists.txt deleted file mode 100644 index 8764c05b..00000000 --- a/src/daemon/sandbox/controller/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# get current directory sources files - -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_controller_top_srcs) - -set(local_sandbox_controller_top_srcs - ${sandbox_controller_top_srcs} - ) -set(local_sandbox_controller_top_incs - ${CMAKE_CURRENT_SOURCE_DIR} - ) - -if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) - add_subdirectory(sandboxer) - list (APPEND local_sandbox_controller_top_srcs - ${CONTROLLER_SANDBOXER_SRCS} - ) - list (APPEND local_sandbox_controller_top_incs - ${CONTROLLER_SANDBOXER_INCS} - ) -endif() - -add_subdirectory(shim) -set(SANDBOX_CONTROLLER_SRCS - ${local_sandbox_controller_top_srcs} - ${CONTROLLER_SHIM_SRCS} - PARENT_SCOPE - ) -set(SANDBOX_CONTROLLER_INCS - ${local_sandbox_controller_top_incs} - ${CONTROLLER_SHIM_INCS} - PARENT_SCOPE - ) \ No newline at end of file diff --git a/src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt b/src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt deleted file mode 100755 index 958ebaa5..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# get current directory sources files -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_controller_sandboxer_client_srcs) -aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox grpc_sandbox_api_srcs) -aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/google/protobuf grpc_sandbox_google_protobuf_api_srcs) -aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/types sandbox_type_srcs) - - -set(CONTROLLER_SANDBOXER_CLIENT_SRCS - ${sandbox_controller_sandboxer_client_srcs} - ${grpc_sandbox_api_srcs} - ${grpc_sandbox_google_protobuf_api_srcs} - ${sandbox_type_srcs} - PARENT_SCOPE - ) - -set(CONTROLLER_SANDBOXER_CLIENT_INCS - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox - PARENT_SCOPE - ) diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc deleted file mode 100644 index c6f97da1..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc +++ /dev/null @@ -1,142 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: xuxuepeng - * Create: 2023-07-28 - * Description: gRPC Async wait call object - ******************************************************************************/ - -#include "grpc_async_wait_call.h" - -#include -#include - -#include "grpc_client_utils.h" - -namespace sandbox { - -// Max retry counter. In monitor thread, we will check deferred calls every 200ms -// so if a call has retry counter for 1500, it means the call will be retried after 300 seconds -const int64_t MAX_RETRY_COUNTER = 1500; // 1500 * 200ms = 300s - -SandboxerAsyncWaitCall::SandboxerAsyncWaitCall(std::shared_ptr cb, - const std::string &sandboxId, const std::string &sandboxer) - : m_cb(cb), m_sandboxId(sandboxId), m_sandboxer(sandboxer) -{ - m_status = grpc::Status::OK; - m_retryTimes = 0; - m_retryCounter = 0; - m_remove = false; -} - -auto SandboxerAsyncWaitCall::Call(containerd::services::sandbox::v1::Controller::StubInterface &stub, - grpc::CompletionQueue &cq) -> bool -{ - containerd::services::sandbox::v1::ControllerWaitRequest request; - m_context = std::unique_ptr(new grpc::ClientContext()); - request.set_sandboxer(m_sandboxer); - request.set_sandbox_id(m_sandboxId); - m_responseReader = stub.PrepareAsyncWait(m_context.get(), request, &cq); - if (m_responseReader == nullptr) { - // Most likely the completion queue is shutdown - ERROR("Failed to prepare async wait request for sandboxer wait request, sandbox id: %s", m_sandboxId.c_str()); - SandboxExitCallback(false, ControllerExitInfo()); - return false; - } - m_responseReader->StartCall(); - m_responseReader->Finish(&m_response, &m_status, (void *)this); - return true; -} - -auto SandboxerAsyncWaitCall::SandboxExitCallback(bool statusOK, const ControllerExitInfo &exitInfo) -> void -{ - // If statusOK is false, it means something unexpected happened during async wait, - // the exitInfo is not valid, but we assume that the sandbox has exited. - if (!statusOK) { - ControllerExitInfo info; - auto currentTime = std::chrono::high_resolution_clock::now(); - auto duration = currentTime.time_since_epoch(); - info.exitedAt = std::chrono::duration_cast(duration).count(); - info.exitStatus = -1; - m_cb->OnSandboxExit(info); - return; - } - m_cb->OnSandboxExit(exitInfo); -} - -auto SandboxerAsyncWaitCall::SandboxPendingCallback() -> void -{ - m_cb->OnSandboxPending(); -} - -auto SandboxerAsyncWaitCall::SandboxReadyCallback() -> void -{ - m_cb->OnSandboxReady(); -} - -auto SandboxerAsyncWaitCall::Timeout() -> bool -{ - m_retryCounter--; - return m_retryCounter == 0; -} - -auto SandboxerAsyncWaitCall::GetSandboxId() -> const std::string & -{ - return m_sandboxId; -} - -SandboxerAsyncWaitStatus SandboxerAsyncWaitCall::HandleResponse() -{ - ControllerExitInfo exitInfo; - SandboxerAsyncWaitStatus waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_ERROR; - - switch (m_status.error_code()) { - case grpc::StatusCode::UNAVAILABLE: - // If the status is unavailable, connection failed, we should retry - WARN("Sandboxer controller wait rpc server unavailable, error_code: %d: %s", m_status.error_code(), - m_status.error_message().c_str()); - waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_RETRY; - m_retryTimes++; - // If retried times is more than 10, we should retry every 300 seconds - if (m_retryTimes > 10) { - m_retryCounter = MAX_RETRY_COUNTER; - } else { - // Retry interval is 2 ^ retry times - m_retryCounter = 1 << m_retryTimes; - } - m_cb->OnSandboxPending(); - break; - case grpc::StatusCode::OK: - exitInfo.exitedAt = TimestampToNanos(m_response.exited_at()); - exitInfo.exitStatus = m_response.exit_status(); - DEBUG("Sandboxer controller wait request success, sandbox id: %s, exit status: %d, exited at: %lu", - m_sandboxId.c_str(), exitInfo.exitStatus, exitInfo.exitedAt); - SandboxExitCallback(true, exitInfo); - waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_OK; - break; - case grpc::StatusCode::NOT_FOUND: - // If the sandbox is not found, it has been deleted, we should return not found - WARN("The sandbox wait doesn't exist, sandbox id: %s, error_code: %d: %s", - m_sandboxId.c_str(), m_status.error_code(), m_status.error_message().c_str()); - waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_NOT_FOUND; - SandboxExitCallback(false, exitInfo); - break; - default: - // TODO: More error code should be handled - ERROR("Sandboxer controller wait request failed, error_code: %d: %s", m_status.error_code(), - m_status.error_message().c_str()); - SandboxExitCallback(false, exitInfo); - break; - } - - return waitStatus; -} - -}; // namespace sandbox \ No newline at end of file diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h deleted file mode 100644 index 6e5a6756..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: xuxuepeng - * Create: 2023-07-28 - * Description: gRPC Async wait call object - ******************************************************************************/ - -#ifndef DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_ASYNC_WAIT_CALL_H -#define DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_ASYNC_WAIT_CALL_H - -#include - -#include "sandbox.pb.h" -#include "sandbox.grpc.pb.h" - -#include "controller.h" - -namespace sandbox { - -enum SandboxerAsyncWaitStatus { - SANDBOXER_ASYNC_WAIT_STATUS_OK = 0, - SANDBOXER_ASYNC_WAIT_STATUS_RETRY, - SANDBOXER_ASYNC_WAIT_STATUS_NOT_FOUND, - SANDBOXER_ASYNC_WAIT_STATUS_ERROR, -}; - -/** - * SandboxerAsyncWaitCall is used to call the async wait method. - * It will be passed to completion queue to wait for the response. - * When the response is received, HandleResponse will be called. - */ -class SandboxerAsyncWaitCall { -public: - SandboxerAsyncWaitCall(std::shared_ptr cb, - const std::string &sandboxId, const std::string &sandboxer); - virtual ~SandboxerAsyncWaitCall() = default; - auto Call(containerd::services::sandbox::v1::Controller::StubInterface &stub, grpc::CompletionQueue &cq) -> bool; - auto HandleResponse() -> SandboxerAsyncWaitStatus; - auto Timeout() -> bool; - void SandboxExitCallback(bool statusOK, const ControllerExitInfo &exitInfo); - void SandboxPendingCallback(); - void SandboxReadyCallback(); - auto GetSandboxId() -> const std::string &; - auto MarkRemove() -> void - { - m_remove = true; - } - auto ToRemove() -> bool - { - return m_remove; - } - auto ResetRetryTimes() -> void - { - m_retryTimes = 0; - } - -protected: - std::shared_ptr m_stub; - std::shared_ptr m_cb; - std::string m_sandboxId; - std::string m_sandboxer; - std::unique_ptr> - m_responseReader; - std::unique_ptr m_context; - containerd::services::sandbox::v1::ControllerWaitResponse m_response; - grpc::Status m_status; - uint32_t m_retryTimes; - uint64_t m_retryCounter; - // The Call object will be deleted when it is unable to be enqueued to completion queue. - // However, since gRPC call happens in async function in Future object, there is potential race condition - // when deleting the call object: - // 1. Monitor thread cleanup future object first, which holding the reference to call object, and - // then AysncCompletionRpcThread received response for the call later, and delete the call object. - // It is OK in this case, since future release the call ownership, and the call object deleted later. - // 2. AsyncCompletionRpcThread received response for the call first, and delete the call object, and - // then Monitor thread cleanup future object later, which could cause use-after-free, since monitor - // thread will use the call to call the callback when cleaning the future object. - // So we need to mark the call object as removed, cleanup them together in Monitor thread after checking - // the future objects. - bool m_remove; -}; - - -}; // namespace sandbox - -#endif // DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_ASYNC_WAIT_CALL_H \ No newline at end of file diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc deleted file mode 100644 index 2cc5a11e..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: xuxuepeng - * Create: 2023-07-28 - * Description: grpc client utils functions - ******************************************************************************/ - -#include "grpc_client_utils.h" - -const uint64_t SECOND_TO_NANOS = 1000000000; -const int64_t MAX_SECONDS_FOR_TIMESTAMP = 253402300799; // 9999-12-31T23:59:59Z -const int32_t MAX_NANOS_FOR_TIMESTAMP = 999999999; - -auto TimestampToNanos(const google::protobuf::Timestamp ×tamp) -> uint64_t -{ - int64_t seconds = 0; - int32_t nanos = 0; - - seconds = timestamp.seconds(); - seconds = seconds < 0 ? 0 : seconds; - seconds = seconds > MAX_SECONDS_FOR_TIMESTAMP ? MAX_SECONDS_FOR_TIMESTAMP : seconds; - - nanos = timestamp.nanos(); - nanos = nanos < 0 ? 0 : nanos; - nanos = nanos > MAX_NANOS_FOR_TIMESTAMP ? MAX_NANOS_FOR_TIMESTAMP : nanos; - - return seconds * SECOND_TO_NANOS + nanos; -} diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h deleted file mode 100644 index 105d33fc..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h +++ /dev/null @@ -1,23 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: xuxuepeng - * Create: 2023-07-28 - * Description: grpc client utils functions - ******************************************************************************/ - -#ifndef DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_CLIENT_UTILS_H -#define DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_CLIENT_UTILS_H - -#include - -uint64_t TimestampToNanos(const google::protobuf::Timestamp ×tamp); - -#endif // DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_CLIENT_UTILS_H \ No newline at end of file diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc deleted file mode 100644 index e042ad45..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc +++ /dev/null @@ -1,337 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: xuxuepeng - * Create: 2023-07-10 - * Description: Sandboxer grpc client - ******************************************************************************/ - -#include "grpc_sandboxer_client.h" - -#include -#include -#include -#include -#include - -#include "sandbox/types/platform.pb.h" -#include "sandbox.pb.h" -#include "sandbox.grpc.pb.h" -#include "utils.h" -#include "isula_libutils/log.h" - -#include "grpc_client_utils.h" - -namespace sandbox { - -SandboxerClient::SandboxerClient(const std::string &sandboxer, const std::string &address): - m_sandboxer(sandboxer), m_address(address) -{ - std::string unixPrefix(UNIX_SOCKET_PREFIX); - - // Only support unix domain socket - if (m_address.compare(0, unixPrefix.length(), unixPrefix) != 0) { - m_address = unixPrefix + m_address; - } - m_channel = grpc::CreateChannel(m_address, grpc::InsecureChannelCredentials()); - m_stub = containerd::services::sandbox::v1::Controller::NewStub(m_channel); - // Monitor shares the same channel with client and has its own stub - m_monitor = std::unique_ptr(new SandboxerClientMonitor(m_channel, m_sandboxer)); -} - -void SandboxerClient::InitMountInfo(Mount &mount, const ControllerMountInfo &mountInfo) -{ - mount.set_type(mountInfo.type); - mount.set_source(mountInfo.source); - mount.set_target(mountInfo.destination); - for (const auto &option : mountInfo.options) { - mount.add_options(option); - } -} - -auto SandboxerClient::InitCreateRequest(containerd::services::sandbox::v1::ControllerCreateRequest &request, - const std::string &sandboxId, - const ControllerCreateParams ¶ms) -> bool -{ - if (params.config == nullptr) { - ERROR("Sandboxer controller create request failed, config is null"); - return false; - } - request.mutable_options()->PackFrom(*params.config); - request.set_sandboxer(m_sandboxer); - request.set_sandbox_id(sandboxId); - for (const auto &entry : params.mounts) { - if (entry != nullptr) { - Mount* mount = request.add_rootfs(); - InitMountInfo(*mount, *entry); - } - } - request.set_netns_path(params.netNSPath); - // The arg sandbox is useless for now - return true; -} - -void SandboxerClient::Init(Errors &error) -{ - m_monitor->Start(); -} - -void SandboxerClient::Destroy() -{ - m_monitor->Stop(); -} - -auto SandboxerClient::Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerCreateRequest request; - containerd::services::sandbox::v1::ControllerCreateResponse response; - grpc::Status status; - - if (!InitCreateRequest(request, sandboxId, params)) { - error.SetError("Failed to init create request for sandboxer create request, sandbox id: " + sandboxId); - return false; - } - - status = m_stub->Create(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller create request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - return true; -} - -void SandboxerClient::StartResponseToSandboxInfo(const containerd::services::sandbox::v1::ControllerStartResponse - &response, - ControllerSandboxInfo &sandboxInfo) -{ - sandboxInfo.id = response.sandbox_id(); - sandboxInfo.pid = response.pid(); - sandboxInfo.createdAt = TimestampToNanos(response.created_at()); - sandboxInfo.taskAddress = response.address(); - sandboxInfo.version = response.version(); - sandboxInfo.labels = response.labels(); -} - -auto SandboxerClient::Start(const std::string &sandboxId, ControllerSandboxInfo &sandboxInfo, Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerStartRequest request; - containerd::services::sandbox::v1::ControllerStartResponse response; - grpc::Status status; - - request.set_sandboxer(m_sandboxer); - request.set_sandbox_id(sandboxId); - - status = m_stub->Start(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller start request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - StartResponseToSandboxInfo(response, sandboxInfo); - - return true; -} - -void SandboxerClient::InitUpdateRequest(containerd::services::sandbox::v1::ControllerUpdateRequest &request, - containerd::types::Sandbox &apiSandbox, - std::vector &fields) -{ - request.set_sandbox_id(apiSandbox.sandbox_id()); - request.set_sandboxer(apiSandbox.sandboxer()); - *(request.mutable_sandbox()) = apiSandbox; - *(request.mutable_fields()) = {fields.begin(), fields.end()}; -} - -auto SandboxerClient::Prepare(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerUpdateRequest request; - containerd::services::sandbox::v1::ControllerUpdateResponse response; - grpc::Status status; - - InitUpdateRequest(request, apiSandbox, fields); - - status = m_stub->Update(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller prepare request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - return true; -} - -auto SandboxerClient::Purge(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerUpdateRequest request; - containerd::services::sandbox::v1::ControllerUpdateResponse response; - grpc::Status status; - - InitUpdateRequest(request, apiSandbox, fields); - - status = m_stub->Update(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller purge request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - return true; -} - -auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, - Errors &error) -> bool -{ - return true; -} - -void SandboxerClient::PlatformResponseToPlatformInfo(const containerd::services::sandbox::v1::ControllerPlatformResponse - &response, - ControllerPlatformInfo &platformInfo) -{ - auto &platform = response.platform(); - platformInfo.os = platform.os(); - platformInfo.arch = platform.architecture(); - platformInfo.variant = platform.variant(); -} - -auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, - Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerPlatformRequest request; - containerd::services::sandbox::v1::ControllerPlatformResponse response; - grpc::Status status; - - request.set_sandboxer(m_sandboxer); - request.set_sandbox_id(sandboxId); - - status = m_stub->Platform(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller platform request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - PlatformResponseToPlatformInfo(response, platformInfo); - - return true; -} - -auto SandboxerClient::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerStopRequest request; - containerd::services::sandbox::v1::ControllerStopResponse response; - grpc::Status status; - - request.set_sandboxer(m_sandboxer); - request.set_sandbox_id(sandboxId); - request.set_timeout_secs(timeoutSecs); - - status = m_stub->Stop(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller stop request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - return true; -} - -void SandboxerClient::StatusResponseToSandboxStatus(const containerd::services::sandbox::v1::ControllerStatusResponse - &response, - ControllerSandboxStatus &sandboxStatus) -{ - sandboxStatus.id = response.sandbox_id(); - sandboxStatus.pid = response.pid(); - sandboxStatus.state = response.state(); - sandboxStatus.taskAddress = response.address(); - sandboxStatus.version = response.version(); - sandboxStatus.info.insert(response.info().begin(), response.info().end()); - sandboxStatus.createdAt = TimestampToNanos(response.created_at()); - sandboxStatus.exitedAt = TimestampToNanos(response.exited_at()); - sandboxStatus.extra = response.extra().value(); -} - -auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, - Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerStatusRequest request; - containerd::services::sandbox::v1::ControllerStatusResponse response; - grpc::Status status; - - request.set_sandboxer(m_sandboxer); - request.set_sandbox_id(sandboxId); - request.set_verbose(verbose); - - status = m_stub->Status(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller status request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - StatusResponseToSandboxStatus(response, sandboxStatus); - - return true; -} - -auto SandboxerClient::Shutdown(const std::string &sandboxId, Errors &error) -> bool -{ - grpc::ClientContext context; - containerd::services::sandbox::v1::ControllerShutdownRequest request; - containerd::services::sandbox::v1::ControllerShutdownResponse response; - grpc::Status status; - - request.set_sandboxer(m_sandboxer); - request.set_sandbox_id(sandboxId); - - status = m_stub->Shutdown(&context, request, &response); - if (!status.ok()) { - error.SetError(status.error_message()); - ERROR("Sandboxer controller shutdown request failed, error_code: %d: %s", status.error_code(), - status.error_message().c_str()); - return false; - } - - return true; -} - -auto SandboxerClient::Wait(std::shared_ptr cb, const std::string &sandboxId, - Errors &error) -> bool -{ - if (m_monitor == nullptr) { - error.SetError("Cannot wait for sandbox, sandboxer client monitor is not initialized, " - "sandboxer: " + m_sandboxer); - return false; - } - SandboxerAsyncWaitCall *call = new SandboxerAsyncWaitCall(cb, sandboxId, m_sandboxer); - // Transfer ownership of call to monitor - return m_monitor->Monitor(call); -} - -} // namespace diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc deleted file mode 100644 index 485a0b23..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc +++ /dev/null @@ -1,314 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: xuxuepeng - * Create: 2023-07-28 - * Description: Sandboxer grpc client monitor - ******************************************************************************/ - -#include "grpc_sandboxer_monitor.h" - -#include - -#include "isula_libutils/log.h" - -namespace sandbox { - -const int64_t DEFERRED_QUEUE_CHECK_INTERVAL = 200; // milliseconds - -SandboxerClientMonitor::SandboxerClientMonitor(std::shared_ptr channel, const std::string &sandboxer): - m_channel(channel), m_sandboxer(sandboxer), m_teardown(false) -{ - m_stub = containerd::services::sandbox::v1::Controller::NewStub(m_channel); -} - -// Monitor will gain the ownership of the call object, and is responsible -// for deleting it -auto SandboxerClientMonitor::Monitor(SandboxerAsyncWaitCall *call) -> bool -{ - if (call == nullptr) { - ERROR("Async wait call is null, failed to monitor."); - return false; - } - - if (m_teardown) { - ERROR("Monitor is already shutdown, failed to monitor sandbox, id: %s", - call->GetSandboxId().c_str()); - delete call; - return false; - } - - // Try to monitor the call, if failed, we should delete it right way - if (!call->Call(*m_stub, m_cq)) { - // The failure is most likely due to the fact that the completion queue is shutdown - delete call; - return false; - } - // The call will be enqueued into completion queue, and the callback - // will be invoked when the response is ready - std::unique_lock lock(m_callsMutex); - m_calls.push_back(call); - INFO("Start to monitor sandboxer wait call, sandbox id: %s", - call->GetSandboxId().c_str()); - return true; -} - -void SandboxerClientMonitor::Start() -{ - m_cqThread = std::thread(&SandboxerClientMonitor::AsyncCompleteRpcThread, this); - m_deferredThread = std::thread(&SandboxerClientMonitor::MonitorThread, this); -} - -void SandboxerClientMonitor::Stop() -{ - // At the time of shutdown, the calls objects are in three states: - // 1. In the completion queue, waiting for the response - // 2. In the deferred queue, waiting for the dispatch - // 3. In the future queue, are about to get into completion queue - // We should cleanup all those objects - m_cq.Shutdown(); - m_teardown = true; - // In case the deferred queue is empty, we should notify the condition variable - m_deferredCallsCond.notify_one(); - INFO("Stopping sandboxer wait call monitor, sandboxer: %s", m_sandboxer.c_str()); - // Wait until all the threads exit - m_cqThread.join(); - m_deferredThread.join(); -} - -auto SandboxerClientMonitor::IsAlive() -> bool -{ - // GetState will retry the channel connection if channel is not active when the parameter is true. - // Monitor will keep retrying with wait call, so we dont have to let channel reconnect here, use false instead. - return m_channel->GetState(false) == GRPC_CHANNEL_READY; -} - -// When the call needs to be retried, we should put it into the deferred queue -void SandboxerClientMonitor::AddDeferredCall(SandboxerAsyncWaitCall *call) -{ - std::unique_lock lock(m_deferredCallsMutex); - m_deferredCalls.push_back(call); - m_deferredCallsCond.notify_one(); -} - -// When the deferred queue and future queue are empty, we should wait for the condition signal -void SandboxerClientMonitor::WaitForDeferredCall() -{ - std::unique_lock lock(m_deferredCallsMutex); - // Check m_futures queue here as well just in case m_futures queue is - if (m_deferredCalls.empty() && m_futures.empty() && !m_teardown) { - m_deferredCallsCond.wait(lock); - } -} - -// Retry the call after a random sleep time -// There are two return values for the future: -// 1. bool: Indicate the call has been successfully retried and enqueued into completion queue -// 2. SandboxerAsyncWaitCall *: The call handled by the future -void SandboxerClientMonitor::InvokeDeferredCall(SandboxerAsyncWaitCall *call) -{ - m_futures.push_back(std::async([this, call]() { - // Random sleep for 50 ~ 200 milliseconds to avoid thundering herd - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(DEFERRED_QUEUE_CHECK_INTERVAL / 4, DEFERRED_QUEUE_CHECK_INTERVAL); - int sleepTime = dis(gen); - std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); - - if (this->m_teardown) { - // If the monitor is already shutdown, the call will be cleaned up - // by the cleanup function - return std::pair(false, nullptr); - } - if (!call->Call(*m_stub, m_cq)) { - return std::pair(false, call); - } - return std::pair(true, call); - })); -} - -// Iterate the calls that are timeout and retry them -void SandboxerClientMonitor::DispatchDeferredCalls() -{ - std::unique_lock lock(m_deferredCallsMutex); - if (m_teardown) { - // Stop dispatching deferred calls - return; - } - for (auto it = m_deferredCalls.begin(); it != m_deferredCalls.end();) { - auto &call = (*it); - if (call->Timeout()) { - // If the call is timeout, we should retry - InvokeDeferredCall(call); - it = m_deferredCalls.erase(it); - } else { - it++; - } - } -} - -// We use future to invoke the deferred call, when the future is ready, we should check the result -void SandboxerClientMonitor::CheckCompletedFutures() -{ - for (auto it = m_futures.begin(); it != m_futures.end();) { - auto &future = (*it); - if (future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { - auto result = future.get(); - auto enqueued = result.first; - auto call = result.second; - if (!enqueued) { - if (call != nullptr) { - // Sandbox has been notified due to call failure in call->Call, - // so no need to notify again - call->MarkRemove(); - } - } else { - // When the async wait is enqueued into completion queue, - // and wait does not return error, we have no feadback - // from the sandboxer, since async wait only return when - // sandbox exited or some errors happened. - // Therefore, one way to assume that the wait call suceeded - // is that check the client status. If the client goes alive, - // we assume the wait call succeeded. - if (IsAlive()) { - // The future is responsible to enqueue the call - // into completion queue. So there is still a chance - // that before we check future status here, - // the call in completion queue has already finished, - // and the callback has been invoked with OnSandboxPending - // or OnSandboxExit in the HandleResponse function. - // In this case, the OnSandboxReady will overwrite the - // status, but it is ok, because: - // 1. If OnSandboxPending has been invoked, - // retry will happen pretty soon, and the - // callback will be invoked again. - // 2. If OnSandboxExit has been invoked, the caller - // should check the sandbox status in the OnSandboxReady - // callback, and it will find out the sandbox has exited, - // and not set sandbox to ready status. - call->SandboxReadyCallback(); - call->ResetRetryTimes(); - } - } - it = m_futures.erase(it); - } else { - it++; - } - } -} - -void SandboxerClientMonitor::ClearDeferredCalls() -{ - std::unique_lock lock(m_deferredCallsMutex); - m_deferredCalls.clear(); -} - -void SandboxerClientMonitor::ClearAllCalls() -{ - std::unique_lock lock(m_callsMutex); - for (auto &call : m_calls) { - delete call; - } - m_calls.clear(); -} - -void SandboxerClientMonitor::Cleanup() -{ - for (auto &future : m_futures) { - future.wait(); - } - m_futures.clear(); - ClearDeferredCalls(); - ClearAllCalls(); -} - -/** - * Thread for handling completion queue. - */ -void SandboxerClientMonitor::AsyncCompleteRpcThread() -{ - void *got_tag; - bool ok = false; - SandboxerAsyncWaitStatus waitStatus; - INFO("Start thread to monitor wait call completion queue for sandboxer, sandboxer: %s", - m_sandboxer.c_str()); - - pthread_setname_np(pthread_self(), "SandboxerAsyncWaitThread"); - - // Next only return false when the completion queue is shutdown and - // the queue is fully drained - while (m_cq.Next(&got_tag, &ok)) { - if (got_tag == nullptr || m_teardown) { - // The completion queue is shutdown - // The calls will be cleaned up by the cleanup function - break; - } - auto call = static_cast(got_tag); - waitStatus = call->HandleResponse(); - if (waitStatus == SANDBOXER_ASYNC_WAIT_STATUS_RETRY) { - AddDeferredCall(call); - continue; - } - // The reason for not deleting the call here is that - // while the call is being handled in this thread, - // the call object could still possibly be referenced in the future - // that has not been checked yet by the monitor thread. This could happen - // especially when the completion queue is shutdown. - call->MarkRemove(); - // Should notify deferred thread to clean up the call - m_deferredCallsCond.notify_one(); - } - INFO("Completion queue is shutdown, wait call monitor thread exit for sandboxer: %s", - m_sandboxer.c_str()); -} - -/** - * Delete the calls that are marked to be removed. - */ -void SandboxerClientMonitor::DeleteRemovedCalls() -{ - std::unique_lock lock(m_callsMutex); - for (auto it = m_calls.begin(); it != m_calls.end();) { - auto &call = (*it); - if (call->ToRemove()) { - delete call; - it = m_calls.erase(it); - } else { - it++; - } - } -} - -/** - * Thread for handling deferred retry calls and cleanup. - */ -void SandboxerClientMonitor::MonitorThread() -{ - INFO("Start wait call monitoring thread, sandboxer: %s", - m_sandboxer.c_str()); - pthread_setname_np(pthread_self(), "SandboxerMonitorThread"); - while (!m_teardown) { - // 1. Clean up futures that are ready - CheckCompletedFutures(); - // 2. Delete the calls that are marked to be removed - DeleteRemovedCalls(); - // 3. If deferred queue is empty, wait for the condition signal - WaitForDeferredCall(); - // 4. We have deferred calls in the queue, deferred for 200 ms - std::this_thread::sleep_for(std::chrono::milliseconds(DEFERRED_QUEUE_CHECK_INTERVAL)); - // 5. Dispatch the deferred calls - DispatchDeferredCalls(); - } - // Cleanup the queue - Cleanup(); - INFO("Start wait call monitoring thread, sandboxer: %s", m_sandboxer.c_str()); -} - -} // namespace sandbox \ No newline at end of file diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h deleted file mode 100644 index b5740b44..00000000 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. - * iSulad licensed under the Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - * PURPOSE. - * See the Mulan PSL v2 for more details. - * Author: xuxuepeng - * Create: 2023-07-28 - * Description: Sandboxer grpc client monitor - ******************************************************************************/ - -#ifndef DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_SANDBOXER_MONITOR_H -#define DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_SANDBOXER_MONITOR_H - -#include -#include -#include -#include - -#include "grpc_async_wait_call.h" - -namespace sandbox { - -/** - * SandboxerClientMonitor is used to monitor the async wait call. - * It will start two threads, one for monitoring the completion queue, - * the other for retrying the async wait call. - * The lifecycle of SandboxerAsyncWaitCall object is managed in the following way: - * 1. When the async call first called, it will be directly passed into completion queue. - * 2. If the call status received from completion queue is SANDBOXER_ASYNC_WAIT_STATUS_RETRY, - * the call will be enqueued to m_deferredCalls, otherwise it will be deleted. - * 3. When the deferred duration is reached for the call, it will be retried, and passed to - * completion queue again. - */ -class SandboxerClientMonitor { -public: - SandboxerClientMonitor(std::shared_ptr channel, const std::string &sandboxer); - ~SandboxerClientMonitor() = default; - - auto Monitor(SandboxerAsyncWaitCall *call) -> bool; - void Start(); - void Stop(); -private: - auto IsAlive() -> bool; - void AddDeferredCall(SandboxerAsyncWaitCall *call); - void WaitForDeferredCall(); - void InvokeDeferredCall(SandboxerAsyncWaitCall *call); - void DispatchDeferredCalls(); - void AsyncCompleteRpcThread(); - void MonitorThread(); - void CheckCompletedFutures(); - void DeleteRemovedCalls(); - void ClearDeferredCalls(); - void ClearAllCalls(); - void Cleanup(); - - std::thread m_cqThread; - std::thread m_deferredThread; - std::unique_ptr m_stub; - std::shared_ptr m_channel; - std::string m_sandboxer; - // Completion queue is thread safe, no mutex needed - grpc::CompletionQueue m_cq; - // Vector for holding all the calls for monitoring - std::vector m_calls; - std::mutex m_callsMutex; - // Use to indicate whether - bool m_teardown; - // Vector for holding all the retry calls - std::vector m_deferredCalls; - std::mutex m_deferredCallsMutex; - std::condition_variable m_deferredCallsCond; - - // Vector for holding all the futures in flight - // No need to lock, only used in m_deferredThread thread - std::vector>> m_futures; -}; - -} // namespace sandbox - -#endif // DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_SANDBOXER_MONITOR_H \ No newline at end of file diff --git a/src/daemon/sandbox/controller/controller_manager.cc b/src/daemon/sandbox/controller_manager.cc similarity index 98% rename from src/daemon/sandbox/controller/controller_manager.cc rename to src/daemon/sandbox/controller_manager.cc index 91c98d26..947f2d19 100644 --- a/src/daemon/sandbox/controller/controller_manager.cc +++ b/src/daemon/sandbox/controller_manager.cc @@ -57,9 +57,6 @@ bool ControllerManager::Init(Errors &error) bool ControllerManager::Cleanup(Errors &error) { - for (auto &it : m_controllers) { - it.second->Destroy(); - } return true; } diff --git a/src/daemon/sandbox/controller/controller_manager.h b/src/daemon/sandbox/controller_manager.h similarity index 100% rename from src/daemon/sandbox/controller/controller_manager.h rename to src/daemon/sandbox/controller_manager.h diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc index 97b77f22..3715e5e0 100644 --- a/src/daemon/sandbox/sandbox.cc +++ b/src/daemon/sandbox/sandbox.cc @@ -1098,11 +1098,6 @@ auto Sandbox::GetNetworkSettingsPath() -> std::string return m_rootdir + std::string("/") + NETWORK_SETTINGS_JSON; } -auto Sandbox::GetTasksJsonPath() -> std::string -{ - return m_rootdir + std::string("/") + SANDBOX_TASKS_JSON; -} - void Sandbox::FillSandboxMetadata(sandbox_metadata* metadata, Errors &error) { std::string jsonStr; @@ -1123,214 +1118,4 @@ void Sandbox::FillSandboxMetadata(sandbox_metadata* metadata, Errors &error) metadata->sandbox_config_json = util_strdup_s(jsonStr.c_str()); } - -auto Sandbox::AddTaskById(const char *task_id, sandbox_task *task) -> bool -{ - - std::string taskId = std::string(task_id); - auto iter = m_tasks.find(taskId); - - if (iter != m_tasks.end()) { - ERROR("Failed to add exits sandbox task %s for sandbox: %s", - task_id, m_id.c_str()); - return false; - } - m_tasks[taskId] = std::make_shared(task); - return true; -} - -auto Sandbox::ReadSandboxTasksJson() -> sandbox_tasks * -{ - const std::string path = GetTasksJsonPath(); - __isula_auto_free parser_error err = nullptr; - sandbox_tasks *tasksArray = nullptr; - - ReadGuard lock(m_tasksMutex); - tasksArray = sandbox_tasks_parse_file(path.c_str(), nullptr, &err); - if (tasksArray == nullptr) { - WARN("Failed to read %s tasks json: %s", path.c_str(), err); - } - return tasksArray; -} - -auto Sandbox::WriteSandboxTasksJson(std::string &tasks_json) -> bool -{ - int nret = 0; - const std::string path = GetTasksJsonPath(); - - WriteGuard lock(m_tasksMutex); - nret = util_atomic_write_file(path.c_str(), tasks_json.c_str(), tasks_json.size(), CONFIG_FILE_MODE, false); - if (nret != 0) { - SYSERROR("Failed to write file %s", path.c_str()); - } - return nret == 0; -} - -auto Sandbox::DeleteSandboxTasksJson() -> bool -{ - int get_err = 0; - const std::string path = GetTasksJsonPath(); - - WriteGuard lock(m_tasksMutex); - if (util_fileself_exists(path.c_str()) && - !util_force_remove_file(path.c_str(), &get_err)) { - errno = get_err; - SYSERROR("Failed to remove file %s", path.c_str()); - return false; - } - - return true; -} - -void Sandbox::AddSandboxTasksByArray(sandbox_tasks *tasksArray) -{ - size_t i; - - WriteGuard lock(m_tasksMutex); - for (i = 0; i < tasksArray->tasks_len; i++) { - if (!AddTaskById(tasksArray->tasks[i]->task_id, tasksArray->tasks[i])) { - return; - } - tasksArray->tasks[i] = nullptr; - } - tasksArray->tasks_len = 0; -} - -void Sandbox::LoadSandboxTasks() -{ - sandbox_tasks *tasksArray = nullptr; - - tasksArray = ReadSandboxTasksJson(); - if (tasksArray == nullptr) { - return; - } - - AddSandboxTasksByArray(tasksArray); - - free_sandbox_tasks(tasksArray); -} - -auto Sandbox::SaveSandboxTasks() -> bool -{ - std::string tasks_json; - - if (m_tasks.empty()) { - return DeleteSandboxTasksJson(); - } - - tasks_json = GetAnySandboxTasks(); - if (tasks_json.empty()) { - ERROR("Failed to get sandbox tasks json for sandbox: '%s'", m_id.c_str()); - return false; - } - - return WriteSandboxTasksJson(tasks_json); -} - -auto Sandbox::AddSandboxTasks(sandbox_task *task) -> bool -{ - if (task == nullptr) { - return true; - } - if (task->task_id == nullptr) { - return false; - } - - WriteGuard lock(m_tasksMutex); - - return AddTaskById(task->task_id, task); -} - -auto Sandbox::GetAnySandboxTasks() -> std::string -{ - __isula_auto_free parser_error err = nullptr; - sandbox_tasks tasksArray = { 0 }; - size_t i = 0; - __isula_auto_free char *tasks_json = nullptr; - - tasksArray.tasks = (sandbox_task **)util_smart_calloc_s(sizeof(sandbox_task *), m_tasks.size()); - if (tasksArray.tasks == nullptr) { - SYSERROR("Out of memory."); - return std::string(""); - } - - ReadGuard lock(m_tasksMutex); - for (auto const& [_, val] : m_tasks) { - /* - * We ignore that the processes are modified - * when we generate tasks json string. - * Because no matter whether a process is deleted or added, - * the Update of sandbox api will be called eventually. - * - * And we ignore that the task is freed after we do GetTask(). - * Because the only way to free task is DeleteSandboxTasks() - * which needs write lock of m_tasksMutex. - */ - tasksArray.tasks[i] = val->GetTask(); - i++; - } - tasksArray.tasks_len = m_tasks.size(); - - tasks_json = sandbox_tasks_generate_json(&tasksArray, nullptr, &(err)); - if (tasks_json == nullptr || strlen(tasks_json) == 0) { - ERROR("Failed to get sandbox tasks json for sandbox: '%s'", m_id.c_str()); - free(tasksArray.tasks); - return std::string(""); - } - - free(tasksArray.tasks); - return std::string(tasks_json); -} - -void Sandbox::DeleteSandboxTasks(const char *containerId) -{ - if (containerId == nullptr) { - return; - } - - std::string taskId = std::string(containerId); - - WriteGuard lock(m_tasksMutex); - auto iter = m_tasks.find(taskId); - if (iter == m_tasks.end()) { - return; - } - m_tasks.erase(iter); -} - -auto Sandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool -{ - if (containerId == nullptr || processes == nullptr) { - ERROR("Empty args."); - return false; - } - - std::string taskId = std::string(containerId); - - ReadGuard lock(m_tasksMutex); - auto iter = m_tasks.find(taskId); - if (iter == m_tasks.end()) { - SYSERROR("Failed to find container %s", containerId); - return false; - } - - return iter->second->AddSandboxTasksProcess(processes); -} - -void Sandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) -{ - if (containerId == nullptr || execId == nullptr) { - return; - } - - std::string taskId = std::string(containerId); - - ReadGuard lock(m_tasksMutex); - auto iter = m_tasks.find(taskId); - if (iter == m_tasks.end()) { - return; - } - iter->second->DeleteSandboxTasksProcess(execId); -} - } \ No newline at end of file diff --git a/src/daemon/sandbox/sandbox.h b/src/daemon/sandbox/sandbox.h index 437b6113..415406ff 100644 --- a/src/daemon/sandbox/sandbox.h +++ b/src/daemon/sandbox/sandbox.h @@ -141,13 +141,13 @@ public: void Status(runtime::v1::PodSandboxStatus &status); // for sandbox api update - void LoadSandboxTasks(); - auto SaveSandboxTasks() -> bool; - auto AddSandboxTasks(sandbox_task *task) -> bool; - auto GetAnySandboxTasks() -> std::string; - void DeleteSandboxTasks(const char *containerId); - auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool; - void DeleteSandboxTasksProcess(const char *containerId, const char *execId); + virtual void LoadSandboxTasks() = 0; + virtual auto SaveSandboxTasks() -> bool = 0; + virtual auto AddSandboxTasks(sandbox_task *task) -> bool = 0; + virtual auto GetAnySandboxTasks() -> std::string = 0; + virtual void DeleteSandboxTasks(const char *containerId) = 0; + virtual auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool = 0; + virtual void DeleteSandboxTasksProcess(const char *containerId, const char *execId) = 0; private: auto SaveState(Errors &error) -> bool; @@ -172,7 +172,6 @@ private: auto GetMetadataJsonPath() -> std::string; auto GetStatePath() -> std::string; auto GetNetworkSettingsPath() -> std::string; - auto GetTasksJsonPath() -> std::string; void FillSandboxState(sandbox_state *state); void FillSandboxMetadata(sandbox_metadata* metadata, Errors &error); @@ -189,12 +188,6 @@ private: void updateSelinuxLabels(std::string &selinuxLabels); - auto AddTaskById(const char *task_id, sandbox_task *task) -> bool; - auto ReadSandboxTasksJson() -> sandbox_tasks *; - auto WriteSandboxTasksJson(std::string &tasks_json) -> bool; - auto DeleteSandboxTasksJson() -> bool; - void AddSandboxTasksByArray(sandbox_tasks *tasksArray); - private: // Since the cri module will operate concurrently on the sandbox instance, // use m_mutex to ensure the correctness of the sandbox instance @@ -230,11 +223,6 @@ private: // vsock ports std::mutex m_vsockPortsMutex; std::set m_vsockPorts; - - // use m_tasksMutex to ensure the correctness of the tasks - RWMutex m_tasksMutex; - // for sandbox api update, containerId --> tasks - std::map> m_tasks; }; } // namespace sandbox diff --git a/src/daemon/sandbox/sandbox_manager.cc b/src/daemon/sandbox/sandbox_manager.cc index 4159993f..ba003d56 100644 --- a/src/daemon/sandbox/sandbox_manager.cc +++ b/src/daemon/sandbox/sandbox_manager.cc @@ -21,8 +21,13 @@ #include #include +#include #include "sandbox.h" +#ifdef ENABLE_SANDBOXER +#include "sandboxer_sandbox.h" +#endif +#include "shim_sandbox.h" #include "isulad_config.h" #include "utils_verify.h" #include "utils_file.h" @@ -109,7 +114,15 @@ auto SandboxManager::CreateSandbox(const std::string &name, RuntimeInfo &info, s return nullptr; } - sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); +#ifdef ENABLE_SANDBOXER + if (info.sandboxer == SHIM_CONTROLLER_NAME) { + sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); + } else { + sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); + } +#else + sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); +#endif if (sandbox == nullptr) { ERROR("Failed to malloc for sandbox: %s", name.c_str()); error.Errorf("Failed to malloc for sandbox: %s", name.c_str()); @@ -442,6 +455,25 @@ bool SandboxManager::ListAllSandboxdir(std::vector &allSubdir) return true; } +#ifdef ENABLE_SANDBOXER +static auto IsShimSandbox(const std::string &id, const std::string &rootdir) -> bool +{ + __isula_auto_free parser_error err = NULL; + const std::string path = rootdir + "/" + id + "/" + SANDBOX_METADATA_JSON; + sandbox_metadata *metadata = NULL; + + metadata = sandbox_metadata_parse_file(path.c_str(), NULL, &err); + if (metadata == NULL) { + return false; + } + + bool ret = (strcmp(metadata->runtime_info->sandboxer, SHIM_CONTROLLER_NAME.c_str()) == 0); + + free_sandbox_metadata(metadata); + return ret; +} +#endif + auto SandboxManager::LoadSandbox(std::string &id) -> std::shared_ptr { std::shared_ptr sandbox = nullptr; @@ -451,7 +483,15 @@ auto SandboxManager::LoadSandbox(std::string &id) -> std::shared_ptr return nullptr; } - sandbox = std::make_shared(id, m_rootdir, m_statedir); +#ifdef ENABLE_SANDBOXER + if (IsShimSandbox(id, m_rootdir)) { + sandbox = std::make_shared(id, m_rootdir, m_statedir); + } else { + sandbox = std::make_shared(id, m_rootdir, m_statedir); + } +#else + sandbox = std::make_shared(id, m_rootdir, m_statedir); +#endif if (sandbox == nullptr) { ERROR("Failed to malloc for sandboxes: %s", id.c_str()); return nullptr; diff --git a/src/daemon/sandbox/sandbox_ops.cc b/src/daemon/sandbox/sandbox_ops.cc index 96e541a4..f50a1033 100644 --- a/src/daemon/sandbox/sandbox_ops.cc +++ b/src/daemon/sandbox/sandbox_ops.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include "controller_manager.h" @@ -24,6 +25,7 @@ #include "namespace.h" #include "utils.h" #include "utils_timestamp.h" +#include "utils_array.h" const std::string SANDBOX_EXTENSIONS_TASKS = "extensions.tasks"; const std::string SANDBOX_TASKS_KEY = "tasks"; @@ -62,42 +64,30 @@ static int generate_ctrl_rootfs(sandbox_task *task, return 0; } -static int do_sandbox_prepare(std::shared_ptr &sandbox, containerd::types::Sandbox &apiSandbox) +static int do_sandbox_update(std::shared_ptr &sandbox, sandbox_sandbox *apiSandbox) { Errors err; - std::vector fields; - - fields.push_back(SANDBOX_EXTENSIONS_TASKS); + size_t fields_len = 1; + __isula_auto_string_array_t string_array *fields = nullptr; - auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox->GetSandboxer()); - if (nullptr == controller) { - ERROR("Invalid sandboxer name: %s", sandbox->GetSandboxer().c_str()); + fields = util_string_array_new(fields_len); + if (fields == nullptr) { + ERROR("Out of memory."); return -1; } - - if (!controller->Prepare(apiSandbox, fields, err)) { - ERROR("Failed to prepare in container controller prepare: %s", err.GetCMessage()); + if (util_append_string_array(fields, SANDBOX_EXTENSIONS_TASKS.c_str())) { + ERROR("Out of memory."); return -1; } - return 0; -} - -static int do_sandbox_purge(std::shared_ptr &sandbox, containerd::types::Sandbox &apiSandbox) -{ - Errors err; - std::vector fields; - - fields.push_back(SANDBOX_EXTENSIONS_TASKS); - auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox->GetSandboxer()); if (nullptr == controller) { ERROR("Invalid sandboxer name: %s", sandbox->GetSandboxer().c_str()); return -1; } - if (!controller->Purge(apiSandbox, fields, err)) { - ERROR("Failed to purge: %s", err.GetCMessage()); + if (!controller->Update(apiSandbox, fields, err)) { + ERROR("Failed to update in container controller update: %s", err.GetCMessage()); return -1; } @@ -161,40 +151,112 @@ static std::shared_ptr get_prepare_sandbox(const container_con return sandbox; } -static int init_prepare_api_sandbox(std::shared_ptr sandbox, const char *containerId, - containerd::types::Sandbox &apiSandbox) +static sandbox_sandbox_runtime *init_sandbox_runtime(std::shared_ptr sandbox) +{ + sandbox_sandbox_runtime *runtime = nullptr; + + auto runtime_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox_runtime); + if (runtime_wrapper == nullptr) { + ERROR("Out of memory"); + return nullptr; + } + runtime = runtime_wrapper->get(); + runtime->name = util_strdup_s(sandbox->GetRuntime().c_str()); + // Just ignore options for now + + return runtime_wrapper->move(); +} + +static json_map_string_string *init_sandbox_labels(std::shared_ptr sandbox) { - google::protobuf::Map *labels = apiSandbox.mutable_labels(); - google::protobuf::Map *extensions = apiSandbox.mutable_extensions(); - google::protobuf::Any any; - auto created_at = new (std::nothrow) google::protobuf::Timestamp; - auto updated_at = new (std::nothrow) google::protobuf::Timestamp; + json_map_string_string *labels = nullptr; + + auto labels_wrapper = makeUniquePtrCStructWrapper(free_json_map_string_string); + if (labels_wrapper == nullptr) { + ERROR("Out of memory"); + return nullptr; + } + labels = labels_wrapper->get(); + if (append_json_map_string_string(labels, "name", sandbox->GetName().c_str()) != 0) { + ERROR("Out of memory"); + return nullptr; + } - apiSandbox.set_sandbox_id(sandbox->GetId()); - apiSandbox.mutable_runtime()->set_name(sandbox->GetRuntime()); - // TODO how get options - // apiSandbox.mutable_runtime()->set_options(sandbox->GetRuntime()); - // Just ignore spec - (*labels)[std::string("name")] = sandbox->GetName(); - - *created_at = google::protobuf::util::TimeUtil::NanosecondsToTimestamp( - sandbox->GetCreatedAt()); - apiSandbox.set_allocated_created_at(created_at); - *updated_at = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(util_get_now_time_nanos()); - apiSandbox.set_allocated_updated_at(updated_at); - - auto any_type_url = any.mutable_type_url(); - *any_type_url = SANDBOX_TASKS_TYPEURL; - auto any_value = any.mutable_value(); - *any_value = sandbox->GetAnySandboxTasks(); - if ((*any_value).empty()) { + return labels_wrapper->move(); +} + +static defs_map_string_object_any *init_sandbox_extensions(std::shared_ptr sandbox) +{ + defs_map_string_object_any *extensions = nullptr; + size_t len = 1; + std::string task_json; + + auto extensions_wrapper = makeUniquePtrCStructWrapper(free_defs_map_string_object_any); + if (extensions_wrapper == nullptr) { + ERROR("Out of memory"); + return nullptr; + } + extensions = extensions_wrapper->get(); + extensions->keys = (char **)util_smart_calloc_s(sizeof(char *), len); + if (extensions->keys == nullptr) { + ERROR("Out of memory."); + return nullptr; + } + extensions->len = len; + extensions->values = (defs_map_string_object_any_element **) + util_smart_calloc_s(sizeof(defs_map_string_object_any_element *), len); + if (extensions->values == nullptr) { + ERROR("Out of memory."); + return nullptr; + } + extensions->values[0] = (defs_map_string_object_any_element *) + util_common_calloc_s(sizeof(defs_map_string_object_any_element)); + if (extensions->values[0] == nullptr) { + ERROR("Out of memory."); + return nullptr; + } + extensions->values[0]->element = (defs_any *)util_common_calloc_s(sizeof(defs_any)); + if (extensions->values[0]->element == nullptr) { + ERROR("Out of memory."); + return nullptr; + } + + extensions->keys[0] = util_strdup_s(SANDBOX_TASKS_KEY.c_str()); + task_json = sandbox->GetAnySandboxTasks(); + if (task_json.empty()) { ERROR("Failed to get any sandbox tasks"); - return -1; + return nullptr; } - DEBUG("Get any sandbox tasks %s", (*any_value).c_str()); - (*extensions)[SANDBOX_TASKS_KEY] = any; + DEBUG("Get any sandbox tasks %s", task_json.c_str()); + extensions->values[0]->element->type_url = util_strdup_s(SANDBOX_TASKS_TYPEURL.c_str()); + extensions->values[0]->element->value = reinterpret_cast(util_strdup_s(task_json.c_str())); + extensions->values[0]->element->value_len = strlen(task_json.c_str()); + + return extensions_wrapper->move(); +} - apiSandbox.set_sandboxer(sandbox->GetSandboxer()); +static int init_api_sandbox(std::shared_ptr sandbox, sandbox_sandbox *apiSandbox) +{ + apiSandbox->sandbox_id = util_strdup_s(sandbox->GetId().c_str()); + apiSandbox->runtime = init_sandbox_runtime(sandbox); + if (apiSandbox->runtime == nullptr) { + ERROR("Failed to init sandbox runtime"); + return -1; + } + // Just ignore spec + apiSandbox->labels = init_sandbox_labels(sandbox); + if (apiSandbox->labels == nullptr) { + ERROR("Failed to init sandbox runtime"); + return -1; + } + apiSandbox->created_at = sandbox->GetCreatedAt(); + apiSandbox->updated_at = util_get_now_time_nanos(); + apiSandbox->extensions = init_sandbox_extensions(sandbox); + if (apiSandbox->extensions == nullptr) { + ERROR("Failed to init sandbox runtime"); + return -1; + } + apiSandbox->sandboxer = util_strdup_s(sandbox->GetSandboxer().c_str()); return 0; } @@ -204,7 +266,7 @@ int sandbox_prepare_container(const container_config_v2_common_config *config, const char * console_fifos[], bool tty) { sandbox_task *task = nullptr; - containerd::types::Sandbox apiSandbox; + sandbox_sandbox *apiSandbox = nullptr; int ret = -1; INFO("Prepare container for sandbox"); @@ -220,20 +282,28 @@ int sandbox_prepare_container(const container_config_v2_common_config *config, return -1; } - task = (sandbox_task *)util_common_calloc_s(sizeof(sandbox_task)); - if (task == nullptr) { - ERROR("Out of memory."); + auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); + if (apiSandbox_wrapper == nullptr) { + ERROR("Out of memory"); return -1; } + apiSandbox = apiSandbox_wrapper->get(); + auto task_wrapper = makeUniquePtrCStructWrapper(free_sandbox_task); + if (task_wrapper == nullptr) { + ERROR("Out of memory"); + return -1; + } + task = task_wrapper->get(); + task->task_id = util_strdup_s(config->id); task->spec = clone_oci_runtime_spec(oci_spec); if (task->spec == nullptr) { ERROR("Out of memory."); - goto free_out; + return -1; } if (generate_ctrl_rootfs(task, config) != 0) { ERROR("Invalid rootfs"); - goto free_out; + return -1; } task->stdin = util_strdup_s((nullptr == console_fifos[0]) ? "" : console_fifos[0]); task->stdout = util_strdup_s((nullptr == console_fifos[1]) ? "" : console_fifos[1]); @@ -241,15 +311,15 @@ int sandbox_prepare_container(const container_config_v2_common_config *config, if (!sandbox->AddSandboxTasks(task)) { ERROR("Failed to add sandbox %s task.", config->id); - goto free_out; + return -1; } - task = nullptr; - ret = init_prepare_api_sandbox(sandbox, config->id, apiSandbox); + task = task_wrapper->move(); + ret = init_api_sandbox(sandbox, apiSandbox); if (ret != 0) { ERROR("Failed to init %s api sandbox.", config->id); goto del_out; } - ret = do_sandbox_prepare(sandbox, apiSandbox); + ret = do_sandbox_update(sandbox, apiSandbox); del_out: if (ret != 0) { @@ -259,8 +329,7 @@ del_out: ERROR("Failed to Save %s sandbox tasks.", config->id); ret = -1; } -free_out: - free_sandbox_task(task); + return ret; } @@ -269,7 +338,7 @@ int sandbox_prepare_exec(const container_config_v2_common_config *config, const char * console_fifos[], bool tty) { sandbox_process *process = nullptr; - containerd::types::Sandbox apiSandbox; + sandbox_sandbox *apiSandbox = nullptr; int ret = -1; INFO("Prepare exec for container in sandbox"); @@ -285,16 +354,24 @@ int sandbox_prepare_exec(const container_config_v2_common_config *config, return -1; } - process = (sandbox_process *)util_common_calloc_s(sizeof(sandbox_process)); - if (process == nullptr) { - ERROR("Out of memory."); + auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); + if (apiSandbox_wrapper == nullptr) { + ERROR("Out of memory"); + return -1; + } + apiSandbox = apiSandbox_wrapper->get(); + auto process_wrapper = makeUniquePtrCStructWrapper(free_sandbox_process); + if (process_wrapper == nullptr) { + ERROR("Out of memory"); return -1; } + process = process_wrapper->get(); + process->exec_id = util_strdup_s(exec_id); process->spec = clone_defs_process(process_spec); if (process->spec == nullptr) { ERROR("Out of memory."); - goto free_out; + return -1; } process->stdin = util_strdup_s((nullptr == console_fifos[0]) ? "" : console_fifos[0]); process->stdout = util_strdup_s((nullptr == console_fifos[1]) ? "" : console_fifos[1]); @@ -302,15 +379,15 @@ int sandbox_prepare_exec(const container_config_v2_common_config *config, if (!sandbox->AddSandboxTasksProcess(config->id, process)) { ERROR("Failed to add sandbox %s process.", config->id); - goto free_out; + return -1; } - process = nullptr; - ret = init_prepare_api_sandbox(sandbox, config->id, apiSandbox); + process = process_wrapper->move(); + ret = init_api_sandbox(sandbox, apiSandbox); if (ret != 0) { ERROR("Failed to init %s api sandbox.", config->id); goto del_out; } - ret = do_sandbox_prepare(sandbox, apiSandbox); + ret = do_sandbox_update(sandbox, apiSandbox); del_out: if (ret != 0) { @@ -320,14 +397,13 @@ del_out: ERROR("Failed to Save %s sandbox tasks.", config->id); ret = -1; } -free_out: - free_sandbox_process(process); + return ret; } int sandbox_purge_container(const container_config_v2_common_config *config) { - containerd::types::Sandbox apiSandbox; + sandbox_sandbox *apiSandbox = nullptr; INFO("Purge container for sandbox"); @@ -337,22 +413,29 @@ int sandbox_purge_container(const container_config_v2_common_config *config) return -1; } + auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); + if (apiSandbox_wrapper == nullptr) { + ERROR("Out of memory"); + return -1; + } + apiSandbox = apiSandbox_wrapper->get(); + sandbox->DeleteSandboxTasks(config->id); if (!sandbox->SaveSandboxTasks()) { ERROR("Failed to Save %s sandbox tasks.", config->id); return -1; } - if (init_prepare_api_sandbox(sandbox, config->id, apiSandbox) != 0) { + if (init_api_sandbox(sandbox, apiSandbox) != 0) { ERROR("Failed to init %s api sandbox.", config->id); return -1; } - return do_sandbox_purge(sandbox, apiSandbox); + return do_sandbox_update(sandbox, apiSandbox); } int sandbox_purge_exec(const container_config_v2_common_config *config, const char *exec_id) { - containerd::types::Sandbox apiSandbox; + sandbox_sandbox *apiSandbox = nullptr; INFO("Purge exec for container in sandbox"); @@ -362,18 +445,25 @@ int sandbox_purge_exec(const container_config_v2_common_config *config, const ch return -1; } + auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); + if (apiSandbox_wrapper == nullptr) { + ERROR("Out of memory"); + return -1; + } + apiSandbox = apiSandbox_wrapper->get(); + sandbox->DeleteSandboxTasksProcess(config->id, exec_id); if (!sandbox->SaveSandboxTasks()) { ERROR("Failed to Save %s sandbox tasks.", config->id); return -1; } - if (init_prepare_api_sandbox(sandbox, config->id, apiSandbox) != 0) { + if (init_api_sandbox(sandbox, apiSandbox) != 0) { ERROR("Failed to init %s api sandbox.", exec_id); return -1; } - return do_sandbox_purge(sandbox, apiSandbox); + return do_sandbox_update(sandbox, apiSandbox); } int sandbox_on_sandbox_exit(const char *sandbox_id, int exit_code) diff --git a/src/daemon/sandbox/sandbox_task.cc b/src/daemon/sandbox/sandbox_task.cc index b1efc340..4533f381 100644 --- a/src/daemon/sandbox/sandbox_task.cc +++ b/src/daemon/sandbox/sandbox_task.cc @@ -91,8 +91,11 @@ void SandboxTask::DeleteSandboxTasksProcess(const char *execId) return; } free_sandbox_process(m_task->processes[idx]); - (void)memcpy((void **)&m_task->processes[idx], (void **)&m_task->processes[idx + 1], - (m_task->processes_len - idx - 1) * sizeof(void *)); + m_task->processes[idx] = nullptr; + if (idx != (int)m_task->processes_len - 1) { + (void)memcpy((void **)&m_task->processes[idx], (void **)&m_task->processes[idx + 1], + (m_task->processes_len - idx - 1) * sizeof(void *)); + } m_task->processes_len--; } diff --git a/src/daemon/sandbox/sandboxer/CMakeLists.txt b/src/daemon/sandbox/sandboxer/CMakeLists.txt new file mode 100755 index 00000000..2b0607e0 --- /dev/null +++ b/src/daemon/sandbox/sandboxer/CMakeLists.txt @@ -0,0 +1,15 @@ +# get current directory sources files +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandboxer_sandbox_srcs) + +add_subdirectory(controller) + +set(SANDBOXER_SANDBOX_SRCS + ${sandboxer_sandbox_srcs} + ${CONTROLLER_SANDBOXER_SRCS} + PARENT_SCOPE + ) +set(SANDBOXER_SANDBOX_INCS + ${CMAKE_CURRENT_SOURCE_DIR} + ${CONTROLLER_SANDBOXER_INCS} + PARENT_SCOPE + ) diff --git a/src/daemon/sandbox/controller/sandboxer/CMakeLists.txt b/src/daemon/sandbox/sandboxer/controller/CMakeLists.txt similarity index 100% rename from src/daemon/sandbox/controller/sandboxer/CMakeLists.txt rename to src/daemon/sandbox/sandboxer/controller/CMakeLists.txt diff --git a/src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt b/src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt new file mode 100755 index 00000000..6ecd350b --- /dev/null +++ b/src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt @@ -0,0 +1,12 @@ +# get current directory sources files +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_controller_sandboxer_client_srcs) + +set(CONTROLLER_SANDBOXER_CLIENT_SRCS + ${sandbox_controller_sandboxer_client_srcs} + PARENT_SCOPE + ) + +set(CONTROLLER_SANDBOXER_CLIENT_INCS + ${CMAKE_CURRENT_SOURCE_DIR} + PARENT_SCOPE + ) diff --git a/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc new file mode 100644 index 00000000..d7ff76d7 --- /dev/null +++ b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc @@ -0,0 +1,463 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: xuxuepeng + * Create: 2023-07-10 + * Description: Sandboxer grpc client + ******************************************************************************/ + +#include "grpc_sandboxer_client.h" + +#include +#include +#include +#include +#include + +#include + +#include "utils.h" +#include "cstruct_wrapper.h" +#include "transform.h" +#include "sandbox_manager.h" + +namespace sandbox { + +SandboxerClient::SandboxerClient(const std::string &sandboxer, const std::string &address): + m_sandboxer(sandboxer), m_address(address) +{ + std::string unixPrefix(UNIX_SOCKET_PREFIX); + + // Only support unix domain socket + if (m_address.compare(0, unixPrefix.length(), unixPrefix) == 0) { + m_address = m_address.substr(unixPrefix.length()); + } + m_controller_handle = sandbox_api_build_controller(m_sandboxer.c_str(), m_address.c_str()); + if (m_controller_handle == nullptr) { + ERROR("Failed to create sandboxer client, sandboxer: %s, address: %s", m_sandboxer.c_str(), m_address.c_str()); + } +} + +auto SandboxerClient::InitMountInfo(sandbox_mount &m, const ControllerMountInfo &mountInfo) -> int +{ + m.type = util_strdup_s(mountInfo.type.c_str()); + m.source = util_strdup_s(mountInfo.source.c_str()); + m.target = util_strdup_s(mountInfo.destination.c_str()); + + size_t mount_options_len = mountInfo.options.size(); + int ret = 0; + for (size_t j = 0; j < mount_options_len; j++) { + ret = util_array_append(&(m.options), mountInfo.options[j].c_str()); + if (ret != 0) { + ERROR("append mount options to array failed"); + return -1; + } + m.options_len++; + } + return 0; +} + +auto SandboxerClient::InitCreateRequest(sandbox_create_request &request, + const std::string &sandboxId, + const ControllerCreateParams ¶ms) -> bool +{ + if (params.config == nullptr) { + ERROR("Sandboxer controller create request failed, config is null"); + return false; + } + request.sandboxer = util_strdup_s(m_sandboxer.c_str()); + request.sandbox_id = util_strdup_s(sandboxId.c_str()); + std::string encoded; + if (!params.config->SerializeToString(&encoded)) { + ERROR("Failed to serialize config"); + return false; + } + request.options = (defs_any *)util_common_calloc_s(sizeof(defs_any)); + if (request.options == nullptr) { + ERROR("Out of memory"); + return false; + } + request.options->value = (uint8_t *)util_common_calloc_s(encoded.size()); + if (request.options == nullptr) { + ERROR("Out of memory"); + return false; + } + (void)memcpy(request.options->value, encoded.c_str(), encoded.size()); + request.options->value_len = encoded.size(); + request.netns_path = util_strdup_s(params.netNSPath.c_str()); + sandbox_mount **mounts = NULL; + size_t mounts_len = params.mounts.size(); + if (mounts_len > 0) { + request.rootfs = (sandbox_mount**)util_common_calloc_s(mounts_len * sizeof(sandbox_mount *)); + if (request.rootfs == nullptr) { + ERROR("Out of memory"); + return false; + } + for (const auto &entry : params.mounts) { + if (entry != nullptr) { + sandbox_mount *m = (sandbox_mount *)util_common_calloc_s(sizeof(sandbox_mount)); + if (m == NULL) { + ERROR("Out of memory"); + return false; + } + if (InitMountInfo(*m, *entry) != 0) { + ERROR("Failed to init mount info"); + free(m); + return false; + } + mounts[request.rootfs_len++] = m; + m = NULL; + } + } + } + return true; +} + +auto SandboxerClient::Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) -> bool +{ + sandbox_create_request *request { nullptr }; + sandbox_create_response *response { nullptr }; + + auto create_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_create_request); + if (create_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = create_request_wrapper->get(); + + auto create_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_create_response); + if (create_response_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + response = create_response_wrapper->get(); + + if (!InitCreateRequest(*request, sandboxId, params)) { + ERROR("Failed to init create request for sandboxer create request"); + error.SetError("Failed to init create request for sandboxer create request"); + return false; + } + int ret = sandbox_api_create(m_controller_handle, request, response); + if (ret != 0) { + ERROR("Failed to create sandbox"); + error.SetError("Failed to create sandbox"); + return false; + } + + return true; +} + +void SandboxerClient::StartResponseToSandboxInfo(sandbox_start_response &response, + ControllerSandboxInfo &sandboxInfo) +{ + sandboxInfo.id = std::string(response.sandbox_id); + sandboxInfo.pid = response.pid; + sandboxInfo.createdAt = response.created_at; + sandboxInfo.taskAddress = std::string(response.address); + sandboxInfo.version = response.version; + Transform::JsonMapToProtobufMapForString(response.labels, sandboxInfo.labels); +} + +auto SandboxerClient::Start(const std::string &sandboxId, ControllerSandboxInfo &sandboxInfo, Errors &error) -> bool +{ + sandbox_start_request *request { nullptr }; + sandbox_start_response *response { nullptr }; + + auto start_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_start_request); + if (start_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = start_request_wrapper->get(); + + auto start_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_start_response); + if (start_response_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + response = start_response_wrapper->get(); + + request->sandboxer = util_strdup_s(m_sandboxer.c_str()); + request->sandbox_id = util_strdup_s(sandboxId.c_str()); + + int ret = sandbox_api_start(m_controller_handle, request, response); + if (ret != 0) { + ERROR("Failed to start sandbox"); + error.SetError("Failed to start sandbox"); + return false; + } + + StartResponseToSandboxInfo(*response, sandboxInfo); + + return true; +} + +void SandboxerClient::InitUpdateRequest(sandbox_update_request &request, + sandbox_sandbox *apiSandbox, string_array *fields) +{ + request.sandbox_id = util_strdup_s(apiSandbox->sandbox_id); + request.sandboxer = util_strdup_s(apiSandbox->sandboxer); + request.sandbox = apiSandbox; + request.fields = fields->items; + request.fields_len = fields->len; +} + +auto SandboxerClient::Update(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error) -> bool +{ + sandbox_update_request *request { nullptr }; + + auto update_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_update_request); + if (update_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = update_request_wrapper->get(); + + InitUpdateRequest(*request, apiSandbox, fields); + int ret = sandbox_api_update(m_controller_handle, request); + request->sandbox = nullptr; + request->fields = nullptr; + request->fields_len = 0; + if (ret != 0) { + ERROR("Failed to update sandbox"); + error.SetError("Failed to update sandbox"); + return false; + } + + return true; +} + +void SandboxerClient::PlatformResponseToPlatformInfo(sandbox_platform_response &response, + ControllerPlatformInfo &platformInfo) +{ + platformInfo.os = std::string(response.os); + platformInfo.arch = std::string(response.architecture); + platformInfo.variant = std::string(response.variant); +} + +auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, + Errors &error) -> bool +{ + sandbox_platform_request *request { nullptr }; + sandbox_platform_response *response { nullptr }; + + auto platform_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_platform_request); + if (platform_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = platform_request_wrapper->get(); + + auto platform_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_platform_response); + if (platform_response_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + response = platform_response_wrapper->get(); + + request->sandboxer = util_strdup_s(m_sandboxer.c_str()); + request->sandbox_id = util_strdup_s(sandboxId.c_str()); + int ret = sandbox_api_platform(m_controller_handle, request, response); + if (ret != 0) { + ERROR("Failed to platform sandbox"); + error.SetError("Failed to platform sandbox"); + return false; + } + + PlatformResponseToPlatformInfo(*response, platformInfo); + + return true; +} + +auto SandboxerClient::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool +{ + sandbox_stop_request *request { nullptr }; + + auto stop_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_stop_request); + if (stop_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = stop_request_wrapper->get(); + + request->sandboxer = util_strdup_s(m_sandboxer.c_str()); + request->sandbox_id = util_strdup_s(sandboxId.c_str()); + request->timeout_secs = timeoutSecs; + int ret = sandbox_api_stop(m_controller_handle, request); + if (ret != 0) { + ERROR("Failed to stop sandbox"); + error.SetError("Failed to stop sandbox"); + return false; + } + + return true; +} + +void SandboxerClient::StatusResponseToSandboxStatus(sandbox_status_response + &response, + ControllerSandboxStatus &sandboxStatus) +{ + sandboxStatus.id = std::string(response.sandbox_id); + sandboxStatus.pid = response.pid; + sandboxStatus.state = std::string(response.state); + Transform::JsonMapToProtobufMapForString(response.info, sandboxStatus.info); + sandboxStatus.createdAt = response.created_at; + sandboxStatus.exitedAt = response.exited_at; + if (response.extra != nullptr && response.extra->value != nullptr) { + sandboxStatus.extra = std::string(response.extra->value, + response.extra->value + response.extra->value_len); + } else { + sandboxStatus.extra = std::string(""); + } + sandboxStatus.taskAddress = std::string(response.address); + sandboxStatus.version = response.version; +} + +auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, + Errors &error) -> bool +{ + sandbox_status_request *request { nullptr }; + sandbox_status_response *response { nullptr }; + + auto status_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_status_request); + if (status_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = status_request_wrapper->get(); + + auto status_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_status_response); + if (status_response_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + response = status_response_wrapper->get(); + + request->sandboxer = util_strdup_s(m_sandboxer.c_str()); + request->sandbox_id = util_strdup_s(sandboxId.c_str()); + request->verbose = verbose; + int ret = sandbox_api_status(m_controller_handle, request, response); + if (ret != 0) { + ERROR("Failed to status sandbox"); + error.SetError("Failed to status sandbox"); + return false; + } + + StatusResponseToSandboxStatus(*response, sandboxStatus); + + return true; +} + +auto SandboxerClient::Shutdown(const std::string &sandboxId, Errors &error) -> bool +{ + sandbox_shutdown_request *request { nullptr }; + + auto shutdown_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_shutdown_request); + if (shutdown_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = shutdown_request_wrapper->get(); + + request->sandboxer = util_strdup_s(m_sandboxer.c_str()); + request->sandbox_id = util_strdup_s(sandboxId.c_str()); + int ret = sandbox_api_shutdown(m_controller_handle, request); + if (ret != 0) { + ERROR("Failed to shutdown sandbox"); + error.SetError("Failed to shutdown sandbox"); + return false; + } + + return true; +} + +static int sandbox_api_ready(const char *sandbox_id) +{ + std::string sandboxId = std::string(sandbox_id); + auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(sandboxId); + if (nullptr == sandbox) { + ERROR("Sandbox not found"); + return -1; + } + + sandbox->OnSandboxReady(); + return 0; +} + +static int sandbox_api_pending(const char *sandbox_id) +{ + std::string sandboxId = std::string(sandbox_id); + auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(sandboxId); + if (nullptr == sandbox) { + ERROR("Sandbox not found"); + return -1; + } + + sandbox->OnSandboxPending(); + return 0; +} + +static int sandbox_api_exit(const char *sandbox_id, const sandbox_wait_response *response) +{ + ControllerExitInfo exitInfo; + std::string sandboxId = std::string(sandbox_id); + auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(sandboxId); + if (nullptr == sandbox) { + ERROR("Sandbox not found"); + return -1; + } + + exitInfo.exitStatus = response->exit_status; + exitInfo.exitedAt = response->exited_at; + sandbox->OnSandboxExit(exitInfo); + return 0; +} + +auto SandboxerClient::Wait(std::shared_ptr cb, const std::string &sandboxId, + Errors &error) -> bool +{ + sandbox_wait_request *request { nullptr }; + sandbox_api_wait_callback callback; + + auto wait_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_wait_request); + if (wait_request_wrapper == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return false; + } + request = wait_request_wrapper->get(); + + request->sandboxer = util_strdup_s(m_sandboxer.c_str()); + request->sandbox_id = util_strdup_s(sandboxId.c_str()); + callback.ready = sandbox_api_ready; + callback.pending = sandbox_api_pending; + callback.exit = sandbox_api_exit; + int ret = sandbox_api_wait(m_controller_handle, request, callback); + if (ret != 0) { + ERROR("Failed to wait sandbox"); + error.SetError("Failed to wait sandbox"); + return false; + } + + return true; +} + +} // namespace diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.h similarity index 54% rename from src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h rename to src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.h index eeb5d7f2..d712be04 100644 --- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h +++ b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.h @@ -20,15 +20,10 @@ #include #include -#include "sandbox/types/mount.pb.h" -#include "sandbox.pb.h" -#include "sandbox.grpc.pb.h" -#include "controller.h" -#include "grpc_async_wait_call.h" -#include "grpc_sandboxer_monitor.h" +#include -using containerd::types::Mount; -using google::protobuf::Timestamp; +#include "controller.h" +#include "utils_array.h" namespace sandbox { @@ -38,24 +33,13 @@ public: ~SandboxerClient() = default; - void Init(Errors &error); - - void Destroy(); - auto Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) -> bool; auto Start(const std::string &sandboxId, ControllerSandboxInfo &sandboxInfo, Errors &error) -> bool; auto Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, Errors &error) -> bool; - auto Prepare(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) -> bool; - - auto Purge(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) -> bool; - - auto UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, - Errors &error) -> bool; + auto Update(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error) -> bool; auto Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool; @@ -66,27 +50,23 @@ public: auto Shutdown(const std::string &sandboxId, Errors &error) -> bool; private: - void InitMountInfo(Mount &mount, const ControllerMountInfo &mountInfo); - auto InitCreateRequest(containerd::services::sandbox::v1::ControllerCreateRequest &request, + auto InitMountInfo(sandbox_mount &m, const ControllerMountInfo &mountInfo) -> int; + auto InitCreateRequest(sandbox_create_request &request, const std::string &sandboxId, const ControllerCreateParams ¶ms) -> bool; - void StartResponseToSandboxInfo(const containerd::services::sandbox::v1::ControllerStartResponse &response, + void StartResponseToSandboxInfo(sandbox_start_response &response, ControllerSandboxInfo &sandboxInfo); - void InitUpdateRequest(containerd::services::sandbox::v1::ControllerUpdateRequest &request, - containerd::types::Sandbox &apiSandbox, std::vector &fields); - // auto InitUpdateResourcesRequest(containerd::services::sandbox::v1::UpdateResourcesRequest &request, - // const std::string &sandboxId, - // const ControllerUpdateResourcesParams ¶ms) -> bool; - void PlatformResponseToPlatformInfo(const containerd::services::sandbox::v1::ControllerPlatformResponse &response, + void InitUpdateRequest(sandbox_update_request &request, + sandbox_sandbox *apiSandbox, string_array *fields); + + void PlatformResponseToPlatformInfo(sandbox_platform_response &response, ControllerPlatformInfo &platformInfo); - void StatusResponseToSandboxStatus(const containerd::services::sandbox::v1::ControllerStatusResponse &response, + void StatusResponseToSandboxStatus(sandbox_status_response &response, ControllerSandboxStatus &sandboxStatus); protected: std::string m_sandboxer; std::string m_address; - std::shared_ptr m_channel; - std::unique_ptr m_stub; - std::unique_ptr m_monitor; + ControllerHandle_t m_controller_handle; }; } // namespace diff --git a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc similarity index 78% rename from src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc rename to src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc index 70cab015..bbe52c85 100644 --- a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc +++ b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc @@ -27,15 +27,9 @@ SandboxerController::~SandboxerController() {} bool SandboxerController::Init(Errors &error) { - m_client->Init(error); return true; } -void SandboxerController::Destroy() -{ - m_client->Destroy(); -} - bool SandboxerController::Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) @@ -61,25 +55,10 @@ std::unique_ptr SandboxerController::Platform(const std: return platformInfo; } -bool SandboxerController::Prepare(containerd::types::Sandbox &apiSandbox, - std::vector &fields, - Errors &error) -{ - return m_client->Prepare(apiSandbox, fields, error); -} - -bool SandboxerController::Purge(containerd::types::Sandbox &apiSandbox, - std::vector &fields, - Errors &error) -{ - return m_client->Purge(apiSandbox, fields, error); -} - -bool SandboxerController::UpdateResources(const std::string &sandboxId, - const ControllerUpdateResourcesParams ¶ms, - Errors &error) +bool SandboxerController::Update(sandbox_sandbox *apiSandbox, + string_array *fields, Errors &error) { - return m_client->UpdateResources(sandboxId, params, error); + return m_client->Update(apiSandbox, fields, error); } bool SandboxerController::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) diff --git a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.h similarity index 82% rename from src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h rename to src/daemon/sandbox/sandboxer/controller/sandboxer_controller.h index 8cb7fe7c..13ab86ab 100644 --- a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h +++ b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.h @@ -31,19 +31,12 @@ public: SandboxerController(const std::string &sandboxer, const std::string &address); virtual ~SandboxerController(); bool Init(Errors &error) override; - void Destroy() override; bool Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) override; std::unique_ptr Start(const std::string &sandboxId, Errors &error) override; std::unique_ptr Platform(const std::string &sandboxId, Errors &error) override; - bool Prepare(containerd::types::Sandbox &apiSandbox, std::vector &fields, - Errors &error) override; - bool Purge(containerd::types::Sandbox &apiSandbox, std::vector &fields, - Errors &error) override; - bool UpdateResources(const std::string &sandboxId, - const ControllerUpdateResourcesParams ¶ms, - Errors &error) override; + bool Update(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error) override; bool Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) override; bool Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) override; std::unique_ptr Status(const std::string &sandboxId, bool verbose, Errors &error) override; diff --git a/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc new file mode 100644 index 00000000..726b7b3a --- /dev/null +++ b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc @@ -0,0 +1,254 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: liuxu + * Create: 2024-11-20 + * Description: provide sandboxer sandbox class definition + *********************************************************************************/ +#include "sandboxer_sandbox.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "utils_file.h" +#include "utils.h" +#include "cxxutils.h" + +namespace sandbox { + +SandboxerSandbox::SandboxerSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name, + const RuntimeInfo info, std::string netMode, std::string netNsPath, const runtime::v1::PodSandboxConfig sandboxConfig, + const std::string image):Sandbox(id, rootdir, statedir, name, info, netMode, + netNsPath, sandboxConfig, image) +{ +} + +auto SandboxerSandbox::GetTasksJsonPath() -> std::string +{ + return GetStateDir() + std::string("/") + SANDBOX_TASKS_JSON; +} + +auto SandboxerSandbox::AddTaskById(const char *task_id, sandbox_task *task) -> bool +{ + + std::string taskId = std::string(task_id); + auto iter = m_tasks.find(taskId); + + if (iter != m_tasks.end()) { + ERROR("Failed to add existing sandbox task %s for sandbox: %s", + task_id, GetId().c_str()); + return false; + } + m_tasks[taskId] = std::make_shared(task); + return true; +} + +auto SandboxerSandbox::ReadSandboxTasksJson() -> sandbox_tasks * +{ + const std::string path = GetTasksJsonPath(); + __isula_auto_free parser_error err = nullptr; + sandbox_tasks *tasksArray = nullptr; + + ReadGuard lock(m_tasksMutex); + tasksArray = sandbox_tasks_parse_file(path.c_str(), nullptr, &err); + if (tasksArray == nullptr) { + WARN("Failed to read %s tasks json: %s", path.c_str(), err); + } + return tasksArray; +} + +auto SandboxerSandbox::WriteSandboxTasksJson(std::string &tasks_json) -> bool +{ + int nret = 0; + const std::string path = GetTasksJsonPath(); + + WriteGuard lock(m_tasksMutex); + nret = util_atomic_write_file(path.c_str(), tasks_json.c_str(), tasks_json.size(), CONFIG_FILE_MODE, false); + if (nret != 0) { + SYSERROR("Failed to write file %s", path.c_str()); + } + return nret == 0; +} + +auto SandboxerSandbox::DeleteSandboxTasksJson() -> bool +{ + int get_err = 0; + const std::string path = GetTasksJsonPath(); + + WriteGuard lock(m_tasksMutex); + if (util_fileself_exists(path.c_str()) && + !util_force_remove_file(path.c_str(), &get_err)) { + errno = get_err; + SYSERROR("Failed to remove file %s", path.c_str()); + return false; + } + + return true; +} + +void SandboxerSandbox::AddSandboxTasksByArray(sandbox_tasks *tasksArray) +{ + size_t i; + + WriteGuard lock(m_tasksMutex); + for (i = 0; i < tasksArray->tasks_len; i++) { + if (!AddTaskById(tasksArray->tasks[i]->task_id, tasksArray->tasks[i])) { + return; + } + tasksArray->tasks[i] = nullptr; + } + tasksArray->tasks_len = 0; +} + +void SandboxerSandbox::LoadSandboxTasks() +{ + sandbox_tasks *tasksArray = nullptr; + + tasksArray = ReadSandboxTasksJson(); + if (tasksArray == nullptr) { + return; + } + + AddSandboxTasksByArray(tasksArray); + + free_sandbox_tasks(tasksArray); +} + +auto SandboxerSandbox::SaveSandboxTasks() -> bool +{ + std::string tasks_json; + + if (m_tasks.empty()) { + return DeleteSandboxTasksJson(); + } + + tasks_json = GetAnySandboxTasks(); + if (tasks_json.empty()) { + ERROR("Failed to get sandbox tasks json for sandbox: '%s'", GetId().c_str()); + return false; + } + + return WriteSandboxTasksJson(tasks_json); +} + +auto SandboxerSandbox::AddSandboxTasks(sandbox_task *task) -> bool +{ + if (task == nullptr) { + return true; + } + if (task->task_id == nullptr) { + return false; + } + + WriteGuard lock(m_tasksMutex); + + return AddTaskById(task->task_id, task); +} + +auto SandboxerSandbox::GetAnySandboxTasks() -> std::string +{ + __isula_auto_free parser_error err = nullptr; + sandbox_tasks tasksArray = { 0 }; + size_t i = 0; + __isula_auto_free char *tasks_json = nullptr; + + tasksArray.tasks = (sandbox_task **)util_smart_calloc_s(sizeof(sandbox_task *), m_tasks.size()); + if (tasksArray.tasks == nullptr) { + SYSERROR("Out of memory."); + return std::string(""); + } + + ReadGuard lock(m_tasksMutex); + for (auto const& [_, val] : m_tasks) { + /* + * We ignore that the processes are modified + * when we generate tasks json string. + * Because no matter whether a process is deleted or added, + * the Update of sandbox api will be called eventually. + * + * And we ignore that the task is freed after we do GetTask(). + * Because the only way to free task is DeleteSandboxTasks() + * which needs write lock of m_tasksMutex. + */ + tasksArray.tasks[i] = val->GetTask(); + i++; + } + tasksArray.tasks_len = m_tasks.size(); + + tasks_json = sandbox_tasks_generate_json(&tasksArray, nullptr, &(err)); + if (tasks_json == nullptr || strlen(tasks_json) == 0) { + ERROR("Failed to get sandbox tasks json for sandbox: '%s'", GetId().c_str()); + free(tasksArray.tasks); + return std::string(""); + } + + free(tasksArray.tasks); + return std::string(tasks_json); +} + +void SandboxerSandbox::DeleteSandboxTasks(const char *containerId) +{ + if (containerId == nullptr) { + return; + } + + std::string taskId = std::string(containerId); + + WriteGuard lock(m_tasksMutex); + auto iter = m_tasks.find(taskId); + if (iter == m_tasks.end()) { + return; + } + m_tasks.erase(iter); +} + +auto SandboxerSandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool +{ + if (containerId == nullptr || processes == nullptr) { + ERROR("Empty args."); + return false; + } + + std::string taskId = std::string(containerId); + + ReadGuard lock(m_tasksMutex); + auto iter = m_tasks.find(taskId); + if (iter == m_tasks.end()) { + SYSERROR("Failed to find container %s", containerId); + return false; + } + + return iter->second->AddSandboxTasksProcess(processes); +} + +void SandboxerSandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) +{ + if (containerId == nullptr || execId == nullptr) { + return; + } + + std::string taskId = std::string(containerId); + + ReadGuard lock(m_tasksMutex); + auto iter = m_tasks.find(taskId); + if (iter == m_tasks.end()) { + return; + } + iter->second->DeleteSandboxTasksProcess(execId); +} + +} \ No newline at end of file diff --git a/src/daemon/sandbox/sandboxer/sandboxer_sandbox.h b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.h new file mode 100644 index 00000000..552eb328 --- /dev/null +++ b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: liuxu + * Create: 2024-11-20 + * Description: provide sandboxer sandbox class definition + *********************************************************************************/ + +#ifndef DAEMON_SANDBOX_SANDBOXER_SANDBOX_H +#define DAEMON_SANDBOX_SANDBOXER_SANDBOX_H + +#include +#include +#include + +#include "read_write_lock.h" +#include "sandbox_task.h" +#include "sandbox.h" + +namespace sandbox { + +class SandboxerSandbox : public Sandbox { +public: + SandboxerSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name = "", + const RuntimeInfo info = {"", "", ""}, std::string netMode = DEFAULT_NETMODE, std::string netNsPath = "", + const runtime::v1::PodSandboxConfig sandboxConfig = runtime::v1::PodSandboxConfig::default_instance(), + const std::string image = ""); + virtual ~SandboxerSandbox() = default; + + // for sandbox api update + auto GetTasksJsonPath() -> std::string; + void LoadSandboxTasks() override; + auto SaveSandboxTasks() -> bool override; + auto AddSandboxTasks(sandbox_task *task) -> bool override; + auto GetAnySandboxTasks() -> std::string override; + void DeleteSandboxTasks(const char *containerId) override; + auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool override; + void DeleteSandboxTasksProcess(const char *containerId, const char *execId) override; + +private: + auto AddTaskById(const char *task_id, sandbox_task *task) -> bool; + auto ReadSandboxTasksJson() -> sandbox_tasks *; + auto WriteSandboxTasksJson(std::string &tasks_json) -> bool; + auto DeleteSandboxTasksJson() -> bool; + void AddSandboxTasksByArray(sandbox_tasks *tasksArray); + +private: + // use m_tasksMutex to ensure the correctness of the tasks + RWMutex m_tasksMutex; + // for sandbox api update, containerId --> tasks + std::map> m_tasks; +}; + +} // namespace sandbox + +#endif // DAEMON_SANDBOX_SANDBOXER_SANDBOX_H \ No newline at end of file diff --git a/src/daemon/sandbox/shim/CMakeLists.txt b/src/daemon/sandbox/shim/CMakeLists.txt new file mode 100755 index 00000000..66fff738 --- /dev/null +++ b/src/daemon/sandbox/shim/CMakeLists.txt @@ -0,0 +1,15 @@ +# get current directory sources files +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} shim_sandbox_srcs) + +add_subdirectory(controller) + +set(SHIM_SANDBOX_SRCS + ${shim_sandbox_srcs} + ${CONTROLLER_SHIM_SRCS} + PARENT_SCOPE + ) +set(SHIM_SANDBOX_INCS + ${CMAKE_CURRENT_SOURCE_DIR} + ${CONTROLLER_SHIM_INCS} + PARENT_SCOPE + ) diff --git a/src/daemon/sandbox/controller/shim/CMakeLists.txt b/src/daemon/sandbox/shim/controller/CMakeLists.txt similarity index 100% rename from src/daemon/sandbox/controller/shim/CMakeLists.txt rename to src/daemon/sandbox/shim/controller/CMakeLists.txt diff --git a/src/daemon/sandbox/controller/shim/shim_controller.cc b/src/daemon/sandbox/shim/controller/shim_controller.cc similarity index 97% rename from src/daemon/sandbox/controller/shim/shim_controller.cc rename to src/daemon/sandbox/shim/controller/shim_controller.cc index 14c99168..7e4338f6 100644 --- a/src/daemon/sandbox/controller/shim/shim_controller.cc +++ b/src/daemon/sandbox/shim/controller/shim_controller.cc @@ -45,8 +45,6 @@ bool ShimController::Init(Errors &error) return true; } -void ShimController::Destroy() {} - void ShimController::ApplySandboxLinuxOptions(const runtime::v1::LinuxPodSandboxConfig &lc, host_config *hc, container_config *custom_config, Errors &error) { @@ -340,21 +338,8 @@ std::unique_ptr ShimController::Platform(const std::stri return nullptr; } -bool ShimController::Prepare(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) -{ - return true; -} - -bool ShimController::Purge(containerd::types::Sandbox &apiSandbox, - std::vector &fields, Errors &error) -{ - return true; -} - -bool ShimController::UpdateResources(const std::string &sandboxId, - const ControllerUpdateResourcesParams ¶ms, - Errors &error) +bool ShimController::Update(sandbox_sandbox *apiSandbox, + string_array *fields, Errors &error) { return true; } diff --git a/src/daemon/sandbox/controller/shim/shim_controller.h b/src/daemon/sandbox/shim/controller/shim_controller.h similarity index 89% rename from src/daemon/sandbox/controller/shim/shim_controller.h rename to src/daemon/sandbox/shim/controller/shim_controller.h index 1985ddc0..fc86be98 100644 --- a/src/daemon/sandbox/controller/shim/shim_controller.h +++ b/src/daemon/sandbox/shim/controller/shim_controller.h @@ -32,26 +32,18 @@ namespace sandbox { -const std::string SHIM_CONTROLLER_NAME = "shim"; - class ShimController : public Controller { public: ShimController(const std::string &sandboxer); virtual ~ShimController(); bool Init(Errors &error) override; - void Destroy() override; bool Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) override; std::unique_ptr Start(const std::string &sandboxId, Errors &error) override; std::unique_ptr Platform(const std::string &sandboxId, Errors &error) override; - bool Prepare(containerd::types::Sandbox &apiSandbox, std::vector &fields, - Errors &error) override; - bool Purge(containerd::types::Sandbox &apiSandbox, std::vector &fields, - Errors &error) override; - bool UpdateResources(const std::string &sandboxId, - const ControllerUpdateResourcesParams ¶ms, - Errors &error) override; + bool Update(sandbox_sandbox *apiSandbox, + string_array *fields, Errors &error) override; bool Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) override; bool Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) override; std::unique_ptr Status(const std::string &sandboxId, bool verbose, Errors &error) override; diff --git a/src/daemon/sandbox/shim/shim_sandbox.cc b/src/daemon/sandbox/shim/shim_sandbox.cc new file mode 100644 index 00000000..2efb8d7c --- /dev/null +++ b/src/daemon/sandbox/shim/shim_sandbox.cc @@ -0,0 +1,65 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: liuxu + * Create: 2024-11-20 + * Description: provide sandboxer sandbox class definition + *********************************************************************************/ +#include "shim_sandbox.h" + +#include +#include + +#include +#include + + +namespace sandbox { + +ShimSandbox::ShimSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name, + const RuntimeInfo info, std::string netMode, std::string netNsPath, const runtime::v1::PodSandboxConfig sandboxConfig, + const std::string image):Sandbox(id, rootdir, statedir, name, info, netMode, + netNsPath, sandboxConfig, image) +{ +} + +void ShimSandbox::LoadSandboxTasks() +{ +} + +auto ShimSandbox::SaveSandboxTasks() -> bool +{ + return true; +} + +auto ShimSandbox::AddSandboxTasks(sandbox_task *task) -> bool +{ + return true; +} + +auto ShimSandbox::GetAnySandboxTasks() -> std::string +{ + return std::string("Nothing for shim."); +} + +void ShimSandbox::DeleteSandboxTasks(const char *containerId) +{ +} + +auto ShimSandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool +{ + return true; +} + +void ShimSandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) +{ +} + +} \ No newline at end of file diff --git a/src/daemon/sandbox/shim/shim_sandbox.h b/src/daemon/sandbox/shim/shim_sandbox.h new file mode 100644 index 00000000..82da0573 --- /dev/null +++ b/src/daemon/sandbox/shim/shim_sandbox.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: liuxu + * Create: 2024-11-20 + * Description: provide shim sandbox class definition + *********************************************************************************/ + +#ifndef DAEMON_SANDBOX_SHIM_SANDBOX_H +#define DAEMON_SANDBOX_SHIM_SANDBOX_H + +#include +#include +#include + +#include "read_write_lock.h" +#include "sandbox_task.h" +#include "sandbox.h" + +namespace sandbox { + +class ShimSandbox : public Sandbox { +public: + ShimSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name = "", + const RuntimeInfo info = {"", "", ""}, std::string netMode = DEFAULT_NETMODE, std::string netNsPath = "", + const runtime::v1::PodSandboxConfig sandboxConfig = runtime::v1::PodSandboxConfig::default_instance(), + const std::string image = ""); + virtual ~ShimSandbox() = default; + + // for sandbox api update + void LoadSandboxTasks() override; + auto SaveSandboxTasks() -> bool override; + auto AddSandboxTasks(sandbox_task *task) -> bool override; + auto GetAnySandboxTasks() -> std::string override; + void DeleteSandboxTasks(const char *containerId) override; + auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool override; + void DeleteSandboxTasksProcess(const char *containerId, const char *execId) override; +}; + +} // namespace sandbox + +#endif // DAEMON_SANDBOX_SHIM_SANDBOX_H \ No newline at end of file -- 2.34.1