diff --git a/.gitignore b/.gitignore index 6f97ca1afcc063e5102e7192528d2c2521213aaa..ccbcf73e56362a12b6ae4da21de33976ec0fdaed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ build *.pyc +.deps +.dirstamp +GPATH +GRTAGS +GTAGS diff --git a/iSulad.spec b/iSulad.spec index 699bad3ffe3682b35d89e697eb63f76a06abf398..ed5dcf2e26455216d44187b7850495a148da066b 100644 --- a/iSulad.spec +++ b/iSulad.spec @@ -1,5 +1,5 @@ %global _version 1.1.11 -%global _release 20200204.221506.git50cfadfa +%global _release 20200213.091554.git2cbd4087 %global is_systemd 1 %global debug_package %{nil} @@ -32,7 +32,7 @@ Requires(preun): initscripts BuildRequires: cmake gcc-c++ lxc lxc-devel lcr yajl yajl-devel clibcni-devel BuildRequires: grpc grpc-devel protobuf-devel BuildRequires: libcurl libcurl-devel sqlite-devel -BuildRequires: http-parser-devel libevhtp-devel libevent-devel +BuildRequires: http-parser-devel BuildRequires: libseccomp-devel libcap-devel libwebsockets libwebsockets-devel BuildRequires: systemd-devel git @@ -41,7 +41,7 @@ Requires: grpc protobuf yajl Requires: libcurl Requires: sqlite http-parser libseccomp Requires: libcap libwebsockets -Requires: libevhtp libevent systemd +Requires: systemd %description This is a umbrella project for gRPC-services based Lightweight Container @@ -68,6 +68,7 @@ install -m 0640 ./conf/isulad.pc %{buildroot}/%{_libdir}/pkgconfig/ install -d $RPM_BUILD_ROOT/%{_bindir} install -m 0755 ./src/isula %{buildroot}/%{_bindir}/isula +install -m 0755 ./src/isulad-shim %{buildroot}/%{_bindir}/isulad-shim install -m 0755 ./src/isulad %{buildroot}/%{_bindir}/isulad install -d $RPM_BUILD_ROOT/%{_includedir}/isulad diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0222d59982d55db3cdf3883cd2a530bd65b5422..8c0b2d9d72607264b5b40e0515fd344c879c59a0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -143,6 +143,18 @@ target_include_directories(isula PUBLIC ${ISULA_INCS} ${SHARED_INCS}) target_link_libraries(isula libisula -lpthread) # ------ build isula finish ------- +# ------ build isulad-shim ------- +add_executable(isulad-shim + ${ISULAD_SHIM_SRCS} + ${CMAKE_BINARY_DIR}/json/shim_client_process_state.c + ${CMAKE_BINARY_DIR}/json/json_common.c + ${commonjsonsrcs} + ) +target_include_directories(isulad-shim PUBLIC ${ISULAD_SHIM_INCS} ${SHARED_INCS}) +target_link_libraries(isulad-shim ${LIBYAJL_LIBRARY} -lpthread) + +# ------ build isula-shim finish ------- + # ------ build isulad ------- add_subdirectory(services) add_subdirectory(image) @@ -237,5 +249,7 @@ install(TARGETS libisula LIBRARY DESTINATION ${LIB_INSTALL_DIR_DEFAULT} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) install(TARGETS isula RUNTIME DESTINATION bin PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) +install(TARGETS isulad-shim + RUNTIME DESTINATION bin PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) install(TARGETS isulad RUNTIME DESTINATION bin PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt index 8c18272df51ef93c1f042f74129f43ca96fb4115..845cb0fb227a312b2d8c311ee6517a3d53ca5df3 100644 --- a/src/cmd/CMakeLists.txt +++ b/src/cmd/CMakeLists.txt @@ -8,3 +8,7 @@ set(ISULA_INCS ${CMAKE_CURRENT_SOURCE_DIR} ${CMD_ISULA_INCS} PARENT_SCOPE) add_subdirectory(isulad) set(ISULAD_SRCS ${comm_srcs} ${CMD_ISULAD_SRCS} PARENT_SCOPE) set(ISULAD_INCS ${CMAKE_CURRENT_SOURCE_DIR} ${CMD_ISULAD_INCS} PARENT_SCOPE) + +add_subdirectory(isulad-shim) +set(ISULAD_SHIM_SRCS ${CMD_ISULAD_SHIM_SRCS} PARENT_SCOPE) +set(ISULAD_SHIM_INCS ${CMAKE_CURRENT_SOURCE_DIR} ${CMD_ISULAD_SHIM_INCS} PARENT_SCOPE) diff --git a/src/cmd/commander.h b/src/cmd/commander.h index 775456e91b67861ceca8370987c7132107489863..d1feb5c71c49e60c7a668786c3bad2e6b93dc8c0 100644 --- a/src/cmd/commander.h +++ b/src/cmd/commander.h @@ -21,6 +21,10 @@ #include "host_config.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifndef COMMANDER_MAX_OPTIONS #define COMMANDER_MAX_OPTIONS 64 #endif @@ -112,5 +116,9 @@ int check_default_ulimit_type(const char *type); void free_default_ulimit(host_config_ulimits_element **default_ulimit); +#ifdef __cplusplus +} +#endif + #endif /* COMMANDER_H */ diff --git a/src/cmd/isula/arguments.h b/src/cmd/isula/arguments.h index 4ecc5b6b840aeb6ee99f0f8c8401dbc171fa439e..1a1ab04755033edd54d9437c2da262aed5618244 100644 --- a/src/cmd/isula/arguments.h +++ b/src/cmd/isula/arguments.h @@ -26,6 +26,10 @@ #include "json_common.h" #include "isula_connect.h" +#ifdef __cplusplus +extern "C" { +#endif + /* max arguments can be specify in client */ #define MAX_CLIENT_ARGS 1000 @@ -322,15 +326,15 @@ struct client_arguments { { CMD_OPT_TYPE_STRING_DUP, false, "host", 'H', &(cmdargs).socket, \ "Daemon socket(s) to connect to", command_valid_socket }, \ { CMD_OPT_TYPE_BOOL, false, "tls", 0, &(cmdargs).tls, \ - "Use TLS; implied by --tlsverify", NULL}, \ + "Use TLS; implied by --tlsverify", NULL}, \ { CMD_OPT_TYPE_BOOL, false, "tlsverify", 0, &(cmdargs).tls_verify, \ - "Use TLS and verify the remote", NULL}, \ + "Use TLS and verify the remote", NULL}, \ { CMD_OPT_TYPE_STRING_DUP, false, "tlscacert", 0, &(cmdargs).ca_file, \ - "Trust certs signed only by this CA (default \"/root/.iSulad/ca.pem\")", NULL }, \ + "Trust certs signed only by this CA (default \"/root/.iSulad/ca.pem\")", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "tlscert", 0, &(cmdargs).cert_file, \ - "Path to TLS certificate file (default \"/root/.iSulad/cert.pem\")", NULL }, \ + "Path to TLS certificate file (default \"/root/.iSulad/cert.pem\")", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "tlskey", 0, &(cmdargs).key_file, \ - "Path to TLS key file (default \"/root/.iSulad/key.pem\")", NULL }, \ + "Path to TLS key file (default \"/root/.iSulad/key.pem\")", NULL }, \ { CMD_OPT_TYPE_STRING, false, "help", 0, NULL, "Print usage", NULL } #define VERSION_OPTIONS(cmdargs) \ @@ -350,5 +354,9 @@ extern void client_print_error(uint32_t cc, uint32_t server_errono, const char * extern client_connect_config_t get_connect_config(const struct client_arguments *args); +#ifdef __cplusplus +} +#endif + #endif /* __ISULA_ARGUMENTS_H */ diff --git a/src/cmd/isula/base/create.c b/src/cmd/isula/base/create.c index 7cc41dfb3479cf980e0677c2914e34717b1466b9..d9621f593554ac77e41716d645afcc12ba794828 100644 --- a/src/cmd/isula/base/create.c +++ b/src/cmd/isula/base/create.c @@ -37,7 +37,7 @@ const char g_cmd_create_desc[] = "Create a new container"; const char g_cmd_create_usage[] = "create [OPTIONS] --external-rootfs=PATH|IMAGE [COMMAND] [ARG...]"; struct client_arguments g_cmd_create_args = { - .runtime = "lcr", + .runtime = "", .restart = "no", .log_file_size = "1MB", .log_file_rotate = 7, diff --git a/src/cmd/isula/base/create.h b/src/cmd/isula/base/create.h index 87ad1c1cea2ff03343e5ad85372890e879d8f0a7..b586831ec12fcb66ff1917d1a789c981b1581584 100644 --- a/src/cmd/isula/base/create.h +++ b/src/cmd/isula/base/create.h @@ -17,137 +17,141 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define CREATE_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_CALLBACK, false, "accel", 0, &(cmdargs).custom_conf.accel, \ "Accelerator bindings (format: [=][@[,]])", \ command_append_array }, \ { CMD_OPT_TYPE_BOOL, false, "read-only", 0, &(cmdargs).custom_conf.readonly, \ - "Make container rootfs readonly", NULL }, \ + "Make container rootfs readonly", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "cap-add", 0, &(cmdargs).custom_conf.cap_adds, \ - "Add Linux capabilities ('ALL' to add all capabilities)", command_append_array }, \ + "Add Linux capabilities ('ALL' to add all capabilities)", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "cap-drop", 0, &(cmdargs).custom_conf.cap_drops, \ - "Drop Linux capabilities ('ALL' to drop all capabilities)", command_append_array }, \ + "Drop Linux capabilities ('ALL' to drop all capabilities)", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "cpu-shares", 0, &(cmdargs).cr.cpu_shares, \ - "CPU shares (relative weight)", command_convert_llong }, \ + "CPU shares (relative weight)", command_convert_llong }, \ { CMD_OPT_TYPE_CALLBACK, false, "cpu-period", 0, &(cmdargs).cr.cpu_period, \ - "Limit CPU CFS (Completely Fair Scheduler) period", command_convert_llong }, \ + "Limit CPU CFS (Completely Fair Scheduler) period", command_convert_llong }, \ { CMD_OPT_TYPE_CALLBACK, false, "cpu-quota", 0, &(cmdargs).cr.cpu_quota, \ - "Limit CPU CFS (Completely Fair Scheduler) quota", command_convert_llong }, \ + "Limit CPU CFS (Completely Fair Scheduler) quota", command_convert_llong }, \ { CMD_OPT_TYPE_STRING, false, "cpuset-cpus", 0, &(cmdargs).cr.cpuset_cpus, \ - "CPUs in which to allow execution (e.g. 0-3, 0,1)", NULL }, \ + "CPUs in which to allow execution (e.g. 0-3, 0,1)", NULL }, \ { CMD_OPT_TYPE_STRING, false, "cpuset-mems", 0, &(cmdargs).cr.cpuset_mems, \ - "MEMs in which to allow execution (0-3, 0,1)", NULL }, \ + "MEMs in which to allow execution (0-3, 0,1)", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "device-read-bps", 0, &(cmdargs).custom_conf.blkio_throttle_read_bps_device, \ - "Limit read rate (bytes per second) from a device (default [])", command_append_array }, \ + "Limit read rate (bytes per second) from a device (default [])", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "device-write-bps", 0, &(cmdargs).custom_conf.blkio_throttle_write_bps_device, \ - "Limit write rate (bytes per second) to a device (default [])", command_append_array }, \ + "Limit write rate (bytes per second) to a device (default [])", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "oom-score-adj", 0, &(cmdargs).cr.oom_score_adj, \ - "Tune host's OOM preferences (-1000 to 1000)", command_convert_llong }, \ + "Tune host's OOM preferences (-1000 to 1000)", command_convert_llong }, \ { CMD_OPT_TYPE_CALLBACK, false, "device", 0, &(cmdargs).custom_conf.devices, \ - "Add a host device to the container", command_append_array }, \ + "Add a host device to the container", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "env", 'e', &(cmdargs).custom_conf.env, \ - "Set environment variables", command_append_array }, \ + "Set environment variables", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "env-file", 0, &(cmdargs).custom_conf.env_file, \ - "Read in a file of environment variables", command_append_array }, \ + "Read in a file of environment variables", command_append_array }, \ { CMD_OPT_TYPE_STRING_DUP, false, "entrypoint", 0, &(cmdargs).custom_conf.entrypoint, \ - "Entrypoint to run when starting the container", NULL }, \ + "Entrypoint to run when starting the container", NULL }, \ { CMD_OPT_TYPE_STRING, false, "external-rootfs", 0, &(cmdargs).external_rootfs, \ - "Specify the custom rootfs that is not managed by isulad for the container, directory or block device", NULL }, \ + "Specify the custom rootfs that is not managed by isulad for the container, directory or block device", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "files-limit", 0, &(cmdargs).custom_conf.files_limit, \ - "Tune container files limit (set -1 for unlimited)", command_convert_llong }, \ + "Tune container files limit (set -1 for unlimited)", command_convert_llong }, \ { CMD_OPT_TYPE_STRING_DUP, false, "hook-spec", 0, &(cmdargs).custom_conf.hook_spec, \ - "File containing hook definition(prestart, poststart, poststop)", NULL }, \ + "File containing hook definition(prestart, poststart, poststop)", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "hostname", 'h', &(cmdargs).custom_conf.hostname, \ - "Container host name", NULL }, \ + "Container host name", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "add-host", 0, &(cmdargs).custom_conf.extra_hosts, \ - "Add a custom host-to-IP mapping (host:ip)", command_append_array }, \ + "Add a custom host-to-IP mapping (host:ip)", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "dns", 0, &(cmdargs).custom_conf.dns, \ - "Set custom DNS servers", command_append_array }, \ + "Set custom DNS servers", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "dns-opt", 0, &(cmdargs).custom_conf.dns_options, \ - "Set DNS options", command_append_array }, \ + "Set DNS options", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "dns-search", 0, &(cmdargs).custom_conf.dns_search, \ - "Set custom DNS search domains", command_append_array }, \ + "Set custom DNS search domains", command_append_array }, \ { CMD_OPT_TYPE_STRING, false, "user-remap", 0, &(cmdargs).custom_conf.user_remap, \ - "Set user remap for container", NULL }, \ + "Set user remap for container", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "ipc", 0, &(cmdargs).custom_conf.share_ns[NAMESPACE_IPC], \ - "IPC namespace to use", NULL }, \ + "IPC namespace to use", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "shm-size", 0, &(cmdargs).custom_conf.shm_size, \ - "Size of /dev/shm, default value is 64MB", command_convert_membytes }, \ + "Size of /dev/shm, default value is 64MB", command_convert_membytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "kernel-memory", 0, &(cmdargs).cr.kernel_memory_limit, \ - "Kernel memory limit", command_convert_membytes }, \ + "Kernel memory limit", command_convert_membytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "hugetlb-limit", 0, &(cmdargs).custom_conf.hugepage_limits, \ - "Huge page limit (format: [size:], e.g. --hugetlb-limit 2MB:32MB)", command_append_array }, \ + "Huge page limit (format: [size:], e.g. --hugetlb-limit 2MB:32MB)", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "log-opt", 0, &(cmdargs), \ - "Container log options, value formate: key=value", callback_log_opt }, \ + "Container log options, value formate: key=value", callback_log_opt }, \ { CMD_OPT_TYPE_CALLBACK, false, "memory", 'm', &(cmdargs).cr.memory_limit, \ - "Memory limit", command_convert_membytes }, \ + "Memory limit", command_convert_membytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "memory-reservation", 0, &(cmdargs).cr.memory_reservation, \ - "Memory soft limit", command_convert_membytes }, \ + "Memory soft limit", command_convert_membytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "memory-swap", 0, &(cmdargs).cr.memory_swap, \ - "Swap limit equal to memory plus swap: '-1' to enable unlimited swap", command_convert_memswapbytes }, \ + "Swap limit equal to memory plus swap: '-1' to enable unlimited swap", command_convert_memswapbytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "mount", 0, &(cmdargs).custom_conf.mounts, \ - "Attach a filesystem mount to the service", command_append_array }, \ + "Attach a filesystem mount to the service", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "group-add", 0, &(cmdargs).custom_conf.group_add, \ - "Add additional groups to join", command_append_array }, \ + "Add additional groups to join", command_append_array }, \ { CMD_OPT_TYPE_STRING_DUP, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "net", 0, &(cmdargs).custom_conf.share_ns[NAMESPACE_NET], \ - "Connect a container to a network", NULL }, \ + "Connect a container to a network", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "pid", 0, &(cmdargs).custom_conf.share_ns[NAMESPACE_PID], \ - "PID namespace to use", NULL }, \ + "PID namespace to use", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "pids-limit", 0, &(cmdargs).custom_conf.pids_limit, \ - "Tune container pids limit (set -1 for unlimited)", command_convert_llong }, \ + "Tune container pids limit (set -1 for unlimited)", command_convert_llong }, \ { CMD_OPT_TYPE_BOOL, false, "privileged", 0, &(cmdargs).custom_conf.privileged, \ - "Give extended privileges to this container", NULL }, \ + "Give extended privileges to this container", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "tty", 't', &(cmdargs).custom_conf.tty, "Allocate a pseudo-TTY", NULL }, \ { CMD_OPT_TYPE_STRING, false, "restart", 0, &(cmdargs).restart, \ - "Restart policy to apply when a container exits(no, always, on-reboot, on-failure[:max-retries])", NULL }, \ + "Restart policy to apply when a container exits(no, always, on-reboot, on-failure[:max-retries])", NULL }, \ { CMD_OPT_TYPE_STRING, false, "host-channel", 0, &(cmdargs).host_channel, \ - "Create share memory between host and container", NULL }, \ + "Create share memory between host and container", NULL }, \ { CMD_OPT_TYPE_STRING, false, "runtime", 'R', &(cmdargs).runtime, \ - "Runtime to use for containers(default: lcr)", NULL }, \ + "Runtime to use for containers(default: lcr)", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "user", 'u', &(cmdargs).custom_conf.user, \ - "Username or UID (format: [:])", NULL }, \ + "Username or UID (format: [:])", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "uts", 0, &(cmdargs).custom_conf.share_ns[NAMESPACE_UTS], \ - "UTS namespace to use", NULL }, \ + "UTS namespace to use", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "volume", 'v', &(cmdargs).custom_conf.volumes, \ - "Bind mount a volume", command_append_array }, \ + "Bind mount a volume", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "annotation", 0, &(cmdargs), \ - "Set annotations on a container", callback_annotation }, \ + "Set annotations on a container", callback_annotation }, \ { CMD_OPT_TYPE_STRING_DUP, false, "workdir", 0, &(cmdargs).custom_conf.workdir, \ - "Working directory inside the container", NULL }, \ + "Working directory inside the container", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "system-container", 0, &(cmdargs).custom_conf.system_container, \ - "Extend some features only needed by running system container", NULL }, \ + "Extend some features only needed by running system container", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "oom-kill-disable", 0, &(cmdargs).custom_conf.oom_kill_disable, \ - "Disable OOM Killer", NULL }, \ + "Disable OOM Killer", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "security-opt", 0, &(cmdargs).custom_conf.security, \ - "Security Options (default [])", command_append_array }, \ + "Security Options (default [])", command_append_array }, \ { CMD_OPT_TYPE_CALLBACK, false, "storage-opt", 0, &(cmdargs).custom_conf.storage_opts, \ - "Storage driver options for the container", command_append_array }, \ + "Storage driver options for the container", command_append_array }, \ { CMD_OPT_TYPE_STRING_DUP, false, "health-cmd", 0, &(cmdargs).custom_conf.health_cmd, \ - "Command to run to check health", NULL }, \ + "Command to run to check health", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "sysctl", 0, &(cmdargs).custom_conf.sysctls, \ - "Sysctl options", command_append_array }, \ + "Sysctl options", command_append_array }, \ { CMD_OPT_TYPE_STRING_DUP, false, "env-target-file", 0, &(cmdargs).custom_conf.env_target_file, \ - "Export env to target file path in rootfs", NULL }, \ + "Export env to target file path in rootfs", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, false, "cgroup-parent", 0, &(cmdargs).custom_conf.cgroup_parent, \ - "Optional parent cgroup for the container", NULL }, \ + "Optional parent cgroup for the container", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "health-interval", 0, &(cmdargs).custom_conf.health_interval, \ - "Time between running the check (ms|s|m|h) (default 30s)", command_convert_nanoseconds }, \ + "Time between running the check (ms|s|m|h) (default 30s)", command_convert_nanoseconds }, \ { CMD_OPT_TYPE_CALLBACK, false, "health-retries", 0, &(cmdargs).custom_conf.health_retries, \ - "Consecutive failures needed to report unhealthy (default 3)", command_convert_int }, \ + "Consecutive failures needed to report unhealthy (default 3)", command_convert_int }, \ { CMD_OPT_TYPE_CALLBACK, false, "health-timeout", 0, &(cmdargs).custom_conf.health_timeout, \ - "Maximum time to allow one check to run (ms|s|m|h) (default 30s)", command_convert_nanoseconds }, \ + "Maximum time to allow one check to run (ms|s|m|h) (default 30s)", command_convert_nanoseconds }, \ { CMD_OPT_TYPE_CALLBACK, false, "health-start-period", 0, &(cmdargs).custom_conf.health_start_period, \ - "Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) " \ - "(default 0s)", command_convert_nanoseconds }, \ + "Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) " \ + "(default 0s)", command_convert_nanoseconds }, \ { CMD_OPT_TYPE_BOOL, false, "no-healthcheck", 0, &(cmdargs).custom_conf.no_healthcheck, \ - "Disable any container-specified HEALTHCHECK", NULL }, \ + "Disable any container-specified HEALTHCHECK", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "health-exit-on-unhealthy", 0, &(cmdargs).custom_conf.exit_on_unhealthy, \ - "Kill the container when it is detected to be unhealthy", NULL }, \ + "Kill the container when it is detected to be unhealthy", NULL }, \ { CMD_OPT_TYPE_STRING, false, "ns-change-opt", 0, &(cmdargs).custom_conf.ns_change_opt, \ - "Namespaced kernel param options for system container (default [])", NULL }, \ + "Namespaced kernel param options for system container (default [])", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "ulimit", 0, &(cmdargs).custom_conf.ulimits, \ - "Ulimit options (default [])", command_append_array } + "Ulimit options (default [])", command_append_array } #define CREATE_EXTEND_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "interactive", 'i', &(cmdargs).custom_conf.open_stdin, \ @@ -169,5 +173,9 @@ int callback_annotation(command_option_t *option, const char *value); int cmd_create_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_CREATE_H */ diff --git a/src/cmd/isula/base/kill.h b/src/cmd/isula/base/kill.h index 605b225058551447678ec2d949d6bcf99986cc9b..8b087869fddc942d0754d6576211e4b5917eebd3 100644 --- a/src/cmd/isula/base/kill.h +++ b/src/cmd/isula/base/kill.h @@ -18,6 +18,10 @@ #include "arguments.h" #include "wait.h" +#ifdef __cplusplus +extern "C" { +#endif + #define KILL_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "signal", 's', &(cmdargs).signal, \ "Signal to send to the container (default \"SIGKILL\")", NULL } @@ -26,5 +30,10 @@ extern const char g_cmd_kill_desc[]; extern const char g_cmd_kill_usage[]; extern struct client_arguments g_cmd_kill_args; int cmd_kill_main(int argc, const char **argv); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/cmd/isula/base/rename.h b/src/cmd/isula/base/rename.h index 9f921f7bdbb72df289c0b4365780cee226389d01..2f9c211c5015a370a2201cc3ae2cad1e0f0e527b 100644 --- a/src/cmd/isula/base/rename.h +++ b/src/cmd/isula/base/rename.h @@ -17,10 +17,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_rename_desc[]; extern const char g_cmd_rename_usage[]; extern struct client_arguments g_cmd_rename_args; int cmd_rename_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/cmd/isula/base/restart.h b/src/cmd/isula/base/restart.h index 1af6a224af110c9d197d6093e353bfe579ea7c68..0f1e00c5e233826c286fbec7e4c904559df538e0 100644 --- a/src/cmd/isula/base/restart.h +++ b/src/cmd/isula/base/restart.h @@ -15,6 +15,10 @@ #ifndef __CMD_RESTART_H #define __CMD_RESTART_H +#ifdef __cplusplus +extern "C" { +#endif + #define RESTART_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_CALLBACK, false, "time", 't', &(cmdargs).time, \ "Seconds to wait for stop before killing it (default 10)", command_convert_int } @@ -24,5 +28,9 @@ extern const char g_cmd_restart_usage[]; extern struct client_arguments g_cmd_restart_args; int cmd_restart_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_RESTART_H */ diff --git a/src/cmd/isula/base/rm.h b/src/cmd/isula/base/rm.h index 5f6ee084d8b4417d797b07fdbfcfb616f8f2b3c3..c89d7cfcd881742394c30a2e08d78a2e0f591019 100644 --- a/src/cmd/isula/base/rm.h +++ b/src/cmd/isula/base/rm.h @@ -17,16 +17,24 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define DELETE_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "force", 'f', &(cmdargs).force, \ "Force the removal of a running container (uses SIGKILL)", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "volumes", 'v', &(cmdargs).volume, \ - "Remove the volumes associated with the container", NULL } + "Remove the volumes associated with the container", NULL } extern const char g_cmd_delete_desc[]; extern const char g_cmd_delete_usage[]; extern struct client_arguments g_cmd_delete_args; int cmd_delete_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_DELETE_H */ diff --git a/src/cmd/isula/base/run.c b/src/cmd/isula/base/run.c index a059cdeb9a6af79cc90f517c48bb004c12411253..7e846ba1772c993ae0ef6a0b83c05b78614a2b8b 100644 --- a/src/cmd/isula/base/run.c +++ b/src/cmd/isula/base/run.c @@ -29,7 +29,7 @@ const char g_cmd_run_desc[] = "Run a command in a new container"; const char g_cmd_run_usage[] = "run [OPTIONS] ROOTFS|IMAGE [COMMAND] [ARG...]"; static int run_checker(struct client_arguments *args); struct client_arguments g_cmd_run_args = { - .runtime = "lcr", + .runtime = "", .restart = "no", .log_file = NULL, .log_file_size = "1MB", diff --git a/src/cmd/isula/base/run.h b/src/cmd/isula/base/run.h index e080fe3f047115f175cf3924a532afc859f5aac9..1589a2b0f958f8fd46ee0694ae52ab676c8ac01a 100644 --- a/src/cmd/isula/base/run.h +++ b/src/cmd/isula/base/run.h @@ -19,16 +19,24 @@ #include "start.h" #include "wait.h" +#ifdef __cplusplus +extern "C" { +#endif + #define RUN_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "detach", 'd', &(cmdargs).detach, \ "Run container in background and print container ID", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "rm", 0, &(cmdargs).custom_conf.auto_remove, \ - "Automatically remove the container when it exits", NULL } + "Automatically remove the container when it exits", NULL } extern const char g_cmd_run_desc[]; extern const char g_cmd_run_usage[]; extern struct client_arguments g_cmd_run_args; int cmd_run_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_RUN_H */ diff --git a/src/cmd/isula/base/start.h b/src/cmd/isula/base/start.h index b5840000a2c53d67d923f80fea8751ddc7f742f4..69945ccb553b390fa11ff5722175efe2f1ebf4cb 100644 --- a/src/cmd/isula/base/start.h +++ b/src/cmd/isula/base/start.h @@ -19,6 +19,10 @@ #include "commands.h" #include +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_start_desc[]; extern struct client_arguments g_cmd_start_args; @@ -28,5 +32,10 @@ void client_restore_console(bool reset_tty, const struct termios *oldtios, struc int client_start(const struct client_arguments *args, bool *reset_tty, struct termios *oldtios, struct command_fifo_config **console_fifos); int cmd_start_main(int argc, const char **argv); + +#ifdef __cplusplus +} +#endif + #endif /* __CMD_START_H */ diff --git a/src/cmd/isula/base/stop.h b/src/cmd/isula/base/stop.h index f2f1dbc61ab6288e28f8b0d906fc18cc6c2e01f9..9b6fdcbd0fee42f85538c46415882670924b77a3 100644 --- a/src/cmd/isula/base/stop.h +++ b/src/cmd/isula/base/stop.h @@ -17,10 +17,14 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define STOP_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "force", 'f', &(cmdargs).force, "Stop by force killing", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "time", 't', &(cmdargs).time, \ - "Seconds to wait for stop before killing it (default 10)", command_convert_int } + "Seconds to wait for stop before killing it (default 10)", command_convert_int } extern const char g_cmd_stop_desc[]; extern const char g_cmd_stop_usage[]; @@ -28,5 +32,9 @@ extern struct client_arguments g_cmd_stop_args; int cmd_stop_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_STOP_H */ diff --git a/src/cmd/isula/commands.h b/src/cmd/isula/commands.h index 7ed3b979d8d6b81a0800f4c1b0f650e610ee4904..06f6cf3293c3bc2ca1dbdc4b253671d4c7243786 100644 --- a/src/cmd/isula/commands.h +++ b/src/cmd/isula/commands.h @@ -18,6 +18,10 @@ #include "arguments.h" #include +#ifdef __cplusplus +extern "C" { +#endif + #define CLIENT_RUNDIR "/var/run/isula" // A command is described by: @@ -69,5 +73,10 @@ int commmand_default_help(const char * const program_name, const char **argv); int run_command(struct command *commands, int argc, const char **argv); + +#ifdef __cplusplus +} +#endif + #endif /* __COMMAND_H */ diff --git a/src/cmd/isula/extend/events.h b/src/cmd/isula/extend/events.h index 76f498217c2e2a90bda0a4f9d8070b99d3de25a8..09435265ef94465a9c2821ec6251b1b24ec052d7 100644 --- a/src/cmd/isula/extend/events.h +++ b/src/cmd/isula/extend/events.h @@ -17,18 +17,26 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define EVENTS_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, \ "Name of the container", NULL }, \ { CMD_OPT_TYPE_STRING, false, "since", 'S', &(cmdargs).since, \ - "Show all events created since this timestamp", NULL }, \ + "Show all events created since this timestamp", NULL }, \ { CMD_OPT_TYPE_STRING, false, "until", 'U', &(cmdargs).until, \ - "Show all events created until this timestamp", NULL } + "Show all events created until this timestamp", NULL } extern const char g_cmd_events_desc[]; extern const char g_cmd_events_usage[]; extern struct client_arguments g_cmd_events_args; int cmd_events_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_EVENT_H */ diff --git a/src/cmd/isula/extend/export.h b/src/cmd/isula/extend/export.h index 5209504a7019b5a5bc80cfc2e4896782b09f3b4a..dada33f4e7c7613447a231b4b76525e7d059b51e 100644 --- a/src/cmd/isula/extend/export.h +++ b/src/cmd/isula/extend/export.h @@ -17,6 +17,10 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define EXPORT_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "output", 'o', &(cmdargs).file, "Write to a file", NULL } @@ -25,5 +29,9 @@ extern const char g_cmd_export_usage[]; extern struct client_arguments g_cmd_export_args; int cmd_export_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/cmd/isula/extend/pause.h b/src/cmd/isula/extend/pause.h index 8b758072bcc8708a1adff7d4184319ea653eca2e..1facb0ee8459ab2feb8b4e2cea491d4b251f8873 100644 --- a/src/cmd/isula/extend/pause.h +++ b/src/cmd/isula/extend/pause.h @@ -17,10 +17,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_pause_desc[]; extern const char g_cmd_pause_usage[]; extern struct client_arguments g_cmd_pause_args; int cmd_pause_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/cmd/isula/extend/resume.h b/src/cmd/isula/extend/resume.h index 655b3fea9506f4f40b6f1ed0e672a9d9d842e420..1aff63483605ba6389c6fffb74cf1337f2fa9d57 100644 --- a/src/cmd/isula/extend/resume.h +++ b/src/cmd/isula/extend/resume.h @@ -17,10 +17,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_resume_desc[]; extern const char g_cmd_resume_usage[]; extern struct client_arguments g_cmd_resume_args; int cmd_resume_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/cmd/isula/extend/stats.h b/src/cmd/isula/extend/stats.h index 253511698aa0521fe4f78d051b81d408ffce87b0..5634d3b73f43544f07894842406267fbd190d994 100644 --- a/src/cmd/isula/extend/stats.h +++ b/src/cmd/isula/extend/stats.h @@ -17,16 +17,24 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define STATUS_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "all", 'a', &(cmdargs).showall, \ "Show all containers (default shows just running)", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "no-stream", 0, &(cmdargs).nostream, \ - "Disable streaming stats and only pull the first result", NULL } + "Disable streaming stats and only pull the first result", NULL } extern const char g_cmd_stats_desc[]; extern const char g_cmd_stats_usage[]; extern struct client_arguments g_cmd_stats_args; int cmd_stats_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_STATS_H */ diff --git a/src/cmd/isula/extend/update.h b/src/cmd/isula/extend/update.h index 9628f04a3cacda5e3b4283f4c732e3eba177cec8..b026800aa62b134d13028e132083350b5ad21a9a 100644 --- a/src/cmd/isula/extend/update.h +++ b/src/cmd/isula/extend/update.h @@ -17,27 +17,31 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define UPDATE_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_CALLBACK, false, "cpu-shares", 0, &(cmdargs).cr.cpu_shares, \ "CPU shares (relative weight)", command_convert_llong }, \ { CMD_OPT_TYPE_CALLBACK, false, "cpu-period", 0, &(cmdargs).cr.cpu_period, \ - "Limit CPU CFS (Completely Fair Scheduler) period", command_convert_llong }, \ + "Limit CPU CFS (Completely Fair Scheduler) period", command_convert_llong }, \ { CMD_OPT_TYPE_CALLBACK, false, "cpu-quota", 0, &(cmdargs).cr.cpu_quota, \ - "Limit CPU CFS (Completely Fair Scheduler) quota", command_convert_llong }, \ + "Limit CPU CFS (Completely Fair Scheduler) quota", command_convert_llong }, \ { CMD_OPT_TYPE_STRING, false, "cpuset-cpus", 0, &(cmdargs).cr.cpuset_cpus, \ - "CPUs in which to allow execution (0-3, 0,1)", NULL }, \ + "CPUs in which to allow execution (0-3, 0,1)", NULL }, \ { CMD_OPT_TYPE_STRING, false, "cpuset-mems", 0, &(cmdargs).cr.cpuset_mems, \ - "MEMs in which to allow execution (0-3, 0,1)", NULL }, \ + "MEMs in which to allow execution (0-3, 0,1)", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "kernel-memory", 0, &(cmdargs).cr.kernel_memory_limit, \ - "Kernel memory limit", command_convert_membytes }, \ + "Kernel memory limit", command_convert_membytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "memory", 'm', &(cmdargs).cr.memory_limit, \ - "Memory limit", command_convert_membytes }, \ + "Memory limit", command_convert_membytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "memory-reservation", 0, &(cmdargs).cr.memory_reservation, \ - "Memory soft limit", command_convert_membytes }, \ + "Memory soft limit", command_convert_membytes }, \ { CMD_OPT_TYPE_CALLBACK, false, "memory-swap", 0, &(cmdargs).cr.memory_swap, \ - "Swap limit equal to memory plus swap: '-1' to enable unlimited swap", command_convert_memswapbytes }, \ + "Swap limit equal to memory plus swap: '-1' to enable unlimited swap", command_convert_memswapbytes }, \ { CMD_OPT_TYPE_STRING, false, "restart", 0, &(cmdargs).restart, \ - "Restart policy to apply when a container exits", NULL } + "Restart policy to apply when a container exits", NULL } extern const char g_cmd_update_desc[]; extern const char g_cmd_update_usage[]; @@ -45,5 +49,9 @@ extern struct client_arguments g_cmd_update_args; int cmd_update_main(int argc, const char **argv); int update_checker(const struct client_arguments *args); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_UPDATE_H */ diff --git a/src/cmd/isula/images/images.h b/src/cmd/isula/images/images.h index 5fd55ddd80f634fade2f1b04ae7469f576bd03fd..9e46bbedd6d75c044321a4dfe35b9d54b57959d1 100644 --- a/src/cmd/isula/images/images.h +++ b/src/cmd/isula/images/images.h @@ -17,10 +17,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_images_desc[]; extern const char g_cmd_images_usage[]; extern struct client_arguments g_cmd_images_args; int cmd_images_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_IMAGES_LIST_H */ diff --git a/src/cmd/isula/images/load.h b/src/cmd/isula/images/load.h index e6f5555d8356e45cca8cf245d7ce1bd1a9781480..372716b4b6e8ea4b0aecb3ba7e6e73c322014032 100644 --- a/src/cmd/isula/images/load.h +++ b/src/cmd/isula/images/load.h @@ -17,10 +17,14 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LOAD_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "input", 'i', &(cmdargs).file, "Read from a manifest or an archive", NULL }, \ { CMD_OPT_TYPE_STRING, false, "tag", 0, &(cmdargs).tag, \ - "Name and optionally a tag in the 'name:tag' format, valid if type is docker", NULL } + "Name and optionally a tag in the 'name:tag' format, valid if type is docker", NULL } #define EMBEDDED_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "type", 't', &(cmdargs).type, "Image type, embedded or docker(default)", NULL } @@ -29,5 +33,9 @@ extern const char g_cmd_load_desc[]; extern struct client_arguments g_cmd_load_args; int cmd_load_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_LOAD_H */ diff --git a/src/cmd/isula/images/login.h b/src/cmd/isula/images/login.h index e50c28ebad1ff5a548dabea667780c72afbab0f3..d2503341ebf8d2b102219f334b157c11247c32e7 100644 --- a/src/cmd/isula/images/login.h +++ b/src/cmd/isula/images/login.h @@ -16,11 +16,15 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LOGIN_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "username", 'u', &(cmdargs).username, "Username", NULL }, \ { CMD_OPT_TYPE_STRING, false, "password", 'p', &(cmdargs).password, "Password", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "password-stdin", 0, &(cmdargs).password_stdin, \ - "Take the password from stdin", NULL }, \ + "Take the password from stdin", NULL }, \ extern const char g_cmd_login_desc[]; @@ -28,5 +32,9 @@ extern const char g_cmd_login_usage[]; extern struct client_arguments g_cmd_login_args; int cmd_login_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_LOGIN_H */ diff --git a/src/cmd/isula/images/logout.h b/src/cmd/isula/images/logout.h index 7100f837cf2d93fca4a639579e08aec49f8ea135..d3ee77bae78c541af8bb6fe322f928327d4319fc 100644 --- a/src/cmd/isula/images/logout.h +++ b/src/cmd/isula/images/logout.h @@ -16,10 +16,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_logout_desc[]; extern const char g_cmd_logout_usage[]; extern struct client_arguments g_cmd_logout_args; int cmd_logout_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_LOGOUT_H */ diff --git a/src/cmd/isula/images/pull.h b/src/cmd/isula/images/pull.h index 728ec4ea9b9e69e216984af3fb6d7e1d24a8ff6c..3cab4e4b6ecb8a74d716fba51251960c6f8ea14f 100644 --- a/src/cmd/isula/images/pull.h +++ b/src/cmd/isula/images/pull.h @@ -18,6 +18,10 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_pull_desc[]; extern const char g_cmd_pull_usage[]; extern struct client_arguments g_cmd_pull_args; @@ -25,5 +29,9 @@ int client_pull(const struct client_arguments *args); int cmd_pull_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_PULL_IMAGE_H */ diff --git a/src/cmd/isula/images/rmi.h b/src/cmd/isula/images/rmi.h index bc8ec8018432e1a94452b53c179babba2fbd6a7b..d2962e7ab72f3331f9b5d15eb4c4199f58df235c 100644 --- a/src/cmd/isula/images/rmi.h +++ b/src/cmd/isula/images/rmi.h @@ -17,6 +17,10 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define RMI_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "force", 'f', &(cmdargs).force, "Force removal of the image", NULL } @@ -25,5 +29,9 @@ extern const char g_cmd_rmi_usage[]; extern struct client_arguments g_cmd_rmi_args; int cmd_rmi_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_REMOVE_IMAGE_H */ diff --git a/src/cmd/isula/information/health.h b/src/cmd/isula/information/health.h index e9d490881e0ecf588105375b5fa0abf1de688bbe..bc6919ae70a4f69b27dcc69c745d1adba47309eb 100644 --- a/src/cmd/isula/information/health.h +++ b/src/cmd/isula/information/health.h @@ -17,6 +17,10 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define HEALTH_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "service", 'S', &(cmdargs).service, "GRPC service name", NULL } @@ -25,5 +29,9 @@ extern const char g_cmd_health_check_usage[]; extern struct client_arguments g_cmd_health_check_args; int cmd_health_check_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/cmd/isula/information/info.h b/src/cmd/isula/information/info.h index f358f9ddca9457be52c57107384fdbdf7b766ae1..19eb05583c22f4acead586e23b663960aada4a65 100644 --- a/src/cmd/isula/information/info.h +++ b/src/cmd/isula/information/info.h @@ -17,10 +17,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_info_desc[]; extern const char g_cmd_info_usage[]; extern struct client_arguments g_cmd_info_args; int cmd_info_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_INFO_H */ diff --git a/src/cmd/isula/information/inspect.h b/src/cmd/isula/information/inspect.h index c83d3ec1fbea5ee78c94bb062ba79b5b303faee2..dfe4252765fa0f2d1f91ced7383dffc53ed6a599 100644 --- a/src/cmd/isula/information/inspect.h +++ b/src/cmd/isula/information/inspect.h @@ -17,16 +17,24 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define INSPECT_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_STRING, false, "format", 'f', &(cmdargs).format, \ "Format the output using the given go template", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "time", 't', &(cmdargs).time, \ - "Seconds to wait for inspect timeout (default 120)", command_convert_int } + "Seconds to wait for inspect timeout (default 120)", command_convert_int } extern const char g_cmd_inspect_desc[]; extern const char g_cmd_inspect_usage[]; extern struct client_arguments g_cmd_inspect_args; int cmd_inspect_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_INSPECT_H */ diff --git a/src/cmd/isula/information/logs.h b/src/cmd/isula/information/logs.h index c92314bf10253fdd42c8839663145b21e25a0e26..dfcfb112ca8d59a969fac29b584340fe83295984 100644 --- a/src/cmd/isula/information/logs.h +++ b/src/cmd/isula/information/logs.h @@ -17,10 +17,14 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LOGS_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "follow", 'f', &(cmdargs).follow, "Follow log output", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "tail", 0, &(cmdargs).tail, \ - "Number of lines to show from the end of the logs", callback_tail } + "Number of lines to show from the end of the logs", callback_tail } extern const char g_cmd_logs_desc[]; extern const char g_cmd_logs_usage[]; @@ -28,5 +32,10 @@ extern struct client_arguments g_cmd_logs_args; int callback_tail(command_option_t *option, const char *arg); int cmd_logs_main(int argc, const char **argv); + +#ifdef __cplusplus +} +#endif + #endif /* __CMD_LOGS_H */ diff --git a/src/cmd/isula/information/ps.h b/src/cmd/isula/information/ps.h index 65b77d00cef69c61940467dd5f834ed6c2e8ddff..1e76c6b97b0ee48bfc1bcd61d08fe8be05e0a5f3 100644 --- a/src/cmd/isula/information/ps.h +++ b/src/cmd/isula/information/ps.h @@ -17,21 +17,29 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LIST_OPTIONS(cmdargs) \ { CMD_OPT_TYPE_BOOL, false, "all", 'a', &(cmdargs).list_all, \ "Display all containers (default shows just running)", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "quiet", 'q', &(cmdargs).dispname, "Only display numeric IDs", NULL }, \ { CMD_OPT_TYPE_CALLBACK, false, "filter", 'f', &(cmdargs).filters, \ - "Filter output based on conditions provided", command_append_array }, \ + "Filter output based on conditions provided", command_append_array }, \ { CMD_OPT_TYPE_BOOL, false, "no-trunc", 0, &(cmdargs).no_trunc, \ - "Don't truncate output", NULL }, \ + "Don't truncate output", NULL }, \ { CMD_OPT_TYPE_STRING, false, "format", 0, &(cmdargs).format, \ - "Format the output using the given go template", NULL } + "Format the output using the given go template", NULL } extern const char g_cmd_list_desc[]; extern const char g_cmd_list_usage[]; extern struct client_arguments g_cmd_list_args; int cmd_list_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_LIST_H */ diff --git a/src/cmd/isula/information/top.h b/src/cmd/isula/information/top.h index f96d780e4ea3a0841c808b89686e7c6e13f2db35..6078195f815b1c1fc45539a42c70d5ff9653a32e 100644 --- a/src/cmd/isula/information/top.h +++ b/src/cmd/isula/information/top.h @@ -17,10 +17,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_top_desc[]; extern const char g_cmd_top_usage[]; extern struct client_arguments g_cmd_top_args; int cmd_top_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_TOP_H */ diff --git a/src/cmd/isula/information/version.h b/src/cmd/isula/information/version.h index e8bab52b471182c35d86692d9cbdaa6330d08c8e..be23446b8707094bc701dfe04a3da8cd15f5f980 100644 --- a/src/cmd/isula/information/version.h +++ b/src/cmd/isula/information/version.h @@ -17,10 +17,18 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_version_desc[]; extern const char g_cmd_version_usage[]; extern struct client_arguments g_cmd_version_args; int cmd_version_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_VERSION_H */ diff --git a/src/cmd/isula/information/wait.h b/src/cmd/isula/information/wait.h index b9f89c277ba3bc25e71a0397c62416ee4b8ed4f2..594d5381044308d6672ced795fe0205856bad3e1 100644 --- a/src/cmd/isula/information/wait.h +++ b/src/cmd/isula/information/wait.h @@ -17,11 +17,19 @@ #include "arguments.h" +#ifdef __cplusplus +extern "C" { +#endif + extern const char g_cmd_wait_desc[]; extern const char g_cmd_wait_usage[]; extern struct client_arguments g_cmd_wait_args; int cmd_wait_main(int argc, const char **argv); int client_wait(const struct client_arguments *args, unsigned int *exit_code); +#ifdef __cplusplus +} +#endif + #endif /* __CMD_WAIT_H */ diff --git a/src/cmd/isulad-shim/CMakeLists.txt b/src/cmd/isulad-shim/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..846994eb4c1127aeb6f7881e57e20a95d86dac16 --- /dev/null +++ b/src/cmd/isulad-shim/CMakeLists.txt @@ -0,0 +1,12 @@ +# get current directory sources files +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} isulad_shim_srcs) + +set(CMD_ISULAD_SHIM_SRCS + ${isulad_shim_srcs} + PARENT_SCOPE + ) + +set(CMD_ISULAD_SHIM_INCS + ${CMAKE_CURRENT_SOURCE_DIR} + PARENT_SCOPE + ) diff --git a/src/cmd/isulad-shim/common.c b/src/cmd/isulad-shim/common.c new file mode 100644 index 0000000000000000000000000000000000000000..2a1b9c532e53546996c7e4487ef1dfd64cfd92e2 --- /dev/null +++ b/src/cmd/isulad-shim/common.c @@ -0,0 +1,301 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: leizhongkai + * Create: 2020-1-21 + * Description: common functions of isulad-shim + ******************************************************************************/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +extern int g_log_fd; + +int set_fd_no_inherited(int fd) +{ + int ret = SHIM_ERR; + int flag = -1; + + flag = fcntl(fd, F_GETFD, 0); + if (flag < 0) { + return SHIM_ERR; + } + + ret = fcntl(fd, F_SETFD, flag | FD_CLOEXEC); + if (ret != 0) { + return SHIM_ERR; + } + + return SHIM_OK; +} + +ssize_t read_nointr(int fd, void *buf, size_t count) +{ + ssize_t nret; + + if (buf == NULL) { + return -1; + } + + for (;;) { + nret = read(fd, buf, count); + if (nret < 0 && (errno == EINTR || errno == EAGAIN)) { + continue; + } else { + break; + } + } + + return nret; +} + +ssize_t write_nointr(int fd, const void *buf, size_t count) +{ + ssize_t nret; + + if (buf == NULL) { + return -1; + } + + for (;;) { + nret = write(fd, buf, count); + if (nret < 0 && (errno == EINTR || errno == EAGAIN)) { + continue; + } else { + break; + } + } + return nret; +} + +bool file_exists(const char *f) +{ + struct stat buf; + int nret; + + if (f == NULL) { + return false; + } + + nret = stat(f, &buf); + if (nret < 0) { + return false; + } + return true; +} + +int cmd_combined_output(const char *binary, const char *params[], void *output, int *output_len) +{ + int ret = SHIM_ERR; + int exec_fd[2] = { -1, -1 }; + int stdio[2] = { -1, -1 }; + pid_t pid = 0; + char exec_buff[BUFSIZ + 1] = { 0 }; + ssize_t nread; + + if (pipe2(exec_fd, O_CLOEXEC) != 0) { + return SHIM_ERR; + } + + if (pipe2(stdio, O_CLOEXEC) != 0) { + return SHIM_ERR; + } + + pid = fork(); + if (pid == (pid_t) - 1) { + return SHIM_ERR; + } + + // child + if (pid == (pid_t)0) { + close(exec_fd[0]); + close(stdio[0]); + dup2(stdio[1], 1); + dup2(stdio[1], 2); + execvp(binary, (char * const *)params); + (void)dprintf(exec_fd[1], "fork/exec error: %s", strerror(errno)); + } + + // parent + close(exec_fd[1]); + close(stdio[1]); + nread = read_nointr(exec_fd[0], exec_buff, sizeof(exec_buff)); + if (nread > 0) { + ret = SHIM_ERR; + goto out; + } + *output_len = read_nointr(stdio[0], output, 8191); + + close(stdio[0]); + close(exec_fd[0]); + int status = 0; + wait(&status); + ret = SHIM_OK; +out: + if (ret != SHIM_OK && pid != 0) { + kill(pid, 9); + } + + return ret; +} + +int generate_random_str(char *id, size_t len) +{ + int fd = -1; + int num = 0; + size_t i; + const int m = 256; + + len = len / 2; + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) { + return SHIM_ERR; + } + for (i = 0; i < len; i++) { + int nret; + if (read(fd, &num, sizeof(int)) < 0) { + close(fd); + return SHIM_ERR; + } + unsigned char rs = (unsigned char)(num % m); + nret = snprintf((id + i * 2), ((len - i) * 2 + 1), "%02x", (unsigned int)rs); + if (nret < 0) { + close(fd); + return SHIM_ERR; + } + } + close(fd); + id[i * 2] = '\0'; + + return SHIM_OK; +} + +void write_message(int fd, const char *level, const char *fmt, ...) +{ +#define MAX_MSG_JSON_TEMPLATE 32 +#define MAX_MESSAGE_CONTENT_LEN 128 +#define MAX_MESSAGE_LEN (MAX_MSG_JSON_TEMPLATE + MAX_MESSAGE_CONTENT_LEN) + if (fd < 0) { + return; + } + + char buf[MAX_MESSAGE_CONTENT_LEN] = { 0 }; + char msg[MAX_MESSAGE_LEN] = { 0 }; + int nwrite = -1; + + va_list arg_list; + va_start(arg_list, fmt); + vsnprintf(buf, MAX_MESSAGE_CONTENT_LEN, fmt, arg_list); + va_end(arg_list); + + snprintf(msg, MAX_MESSAGE_LEN - 1, "{\"level\": \"%s\", \"msg\": \"%s\"}\n", level, buf); + nwrite = write(fd, msg, strlen(msg)); + if (nwrite != strlen(msg)) { + return; + } + + return; +} + +/* note: This function can only read small text file. */ +char *read_text_file(const char *path) +{ + char *buf = NULL; + long len = 0; + size_t readlen = 0; + FILE *filp = NULL; + const long max_size = 10 * 1024 * 1024; /* 10M */ + + if (path == NULL) { + return NULL; + } + + filp = fopen(path, "r"); + if (filp == NULL) { + goto err_out; + } + if (fseek(filp, 0, SEEK_END)) { + goto err_out; + } + + len = ftell(filp); + if (len > max_size) { + goto err_out; + } + if (fseek(filp, 0, SEEK_SET)) { + goto err_out; + } + + buf = (char *)calloc(1, (size_t)(len + 1)); + if (buf == NULL) { + goto err_out; + } + + readlen = fread(buf, 1, (size_t)len, filp); + if (((readlen < (size_t)len) && (!feof(filp))) || (readlen > (size_t)len)) { + if (buf != NULL) { + free(buf); + buf = NULL; + } + goto err_out; + } + + buf[(size_t)len] = 0; + +err_out: + + if (filp != NULL) { + fclose(filp); + } + + return buf; +} + +void close_fd(int *pfd) +{ + if (pfd != NULL && *pfd != -1) { + close(*pfd); + *pfd = -1; + } +} + +int open_no_inherit(const char *path, int flag, mode_t mode) +{ + int fd = -1; + int ret = SHIM_ERR; + + fd = open(path, flag, mode); + if (fd < 0) { + return -1; + } + + ret = set_fd_no_inherited(fd); + if (ret != SHIM_OK) { + close(fd); + return -1; + } + + return fd; +} + diff --git a/src/cmd/isulad-shim/common.h b/src/cmd/isulad-shim/common.h new file mode 100644 index 0000000000000000000000000000000000000000..a1ee0dbc51ed2a075a8949711ed47d0241bedb9a --- /dev/null +++ b/src/cmd/isulad-shim/common.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: leizhongkai + * Create: 2020-1-20 + * Description: common definition of isulad-shim + ******************************************************************************/ + +#ifndef __COMMON_H_ +#define __COMMON_H_ + +#include + +// error code +#define SHIM_ERR_BASE (-10000) +#define SHIM_SYS_ERR(err) (SHIM_ERR_BASE-err) +#define SHIM_OK 0 +#define SHIM_ERR -1 +#define SHIM_ERR_WAIT -2 +#define SHIM_ERR_NOT_REQUIRED -3 + +#define INFO_MSG "info" +#define WARN_MSG "warn" +#define ERR_MSG "error" + +#define DEFAULT_TIMEOUT 120 // sec +#define CONTAINER_ID_LEN 64 +#define MAX_RT_NAME_LEN 64 +#define MAX_CONSOLE_SOCK_LEN 32 + +#define MAX_RUNTIME_ARGS 20 + +#define SHIM_BINARY "isulad-shim" +#define SHIM_LOG_NAME "shim-log.json" + +#define CONTAINER_ACTION_REBOOT 129 +#define CONTAINER_ACTION_SHUTDOWN 130 + +ssize_t read_nointr(int fd, void *buf, size_t count); +ssize_t write_nointr(int fd, const void *buf, size_t count); + +char *read_text_file(const char *path); + +bool file_exists(const char *f); + +int cmd_combined_output(const char *binary, const char *params[], void *output, int *output_len); + +void write_message(int fd, const char *level, const char *fmt, ...); + +int generate_random_str(char *id, size_t len); + +void close_fd(int *pfd); + +int open_no_inherit(const char *path, int flag, mode_t mode); + +#endif + diff --git a/src/cmd/isulad-shim/main.c b/src/cmd/isulad-shim/main.c new file mode 100644 index 0000000000000000000000000000000000000000..7b0b0521b6467ee28051aff21b0e863ceffde2be --- /dev/null +++ b/src/cmd/isulad-shim/main.c @@ -0,0 +1,162 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: leizhongkai + * Create: 2020-1-20 + * Description: main process of isulad-shim + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "process.h" + +int g_log_fd = -1; + +void signal_routine(int sig) +{ + switch (sig) { + case SIGALRM: + write_message(g_log_fd, ERR_MSG, "runtime timeout"); + exit(1); + default: + break; + } +} + +static void set_timeout_exit(unsigned int timeout) +{ + signal(SIGALRM, signal_routine); + (void)alarm(timeout); +} + +static void released_timeout_exit() +{ + (void)alarm(0); + signal(SIGALRM, SIG_IGN); +} + +static int set_subreaper() +{ + int ret = SHIM_ERR; + ret = prctl(PR_SET_CHILD_SUBREAPER, 1); + if (ret != SHIM_OK) { + return SHIM_SYS_ERR(errno); + } + + return SHIM_OK; +} + +static int parse_args(int argc, char **argv, char **cid, char **bundle, char **rt_name, char **log_level) +{ + if (argc < 4) { + return SHIM_ERR; + } + + *cid = strdup(argv[1]); + *bundle = strdup(argv[2]); + *rt_name = strdup(argv[3]); + if (*cid == NULL || *bundle == NULL || rt_name == NULL) { + return SHIM_ERR; + } + + if (argc > 4) { + *log_level = strdup(argv[4]); + if (*log_level == NULL) { + return SHIM_ERR; + } + } + + return SHIM_OK; +} + + +int main(int argc, char **argv) +{ + char *container_id = NULL; + char *bundle = NULL; + char *rt_name = NULL; + char *log_level = NULL; + int ret = SHIM_ERR; + int efd = -1; + process_t *p = NULL; + + g_log_fd = open_no_inherit(SHIM_LOG_NAME, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, 0640); + if (g_log_fd < 0) { + _exit(EXIT_FAILURE); + } + + set_timeout_exit(DEFAULT_TIMEOUT); + + ret = set_subreaper(); + if (ret != SHIM_OK) { + write_message(g_log_fd, ERR_MSG, "set subreaper failed:%d", ret); + exit(EXIT_FAILURE); + } + + ret = parse_args(argc, argv, &container_id, &bundle, &rt_name, &log_level); + if (ret != SHIM_OK) { + write_message(g_log_fd, ERR_MSG, "parse args failed:%d", ret); + exit(EXIT_FAILURE); + } + + p = new_process(container_id, bundle, rt_name); + if (p == NULL) { + write_message(g_log_fd, ERR_MSG, "new process failed"); + exit(EXIT_FAILURE); + } + + // open exit pipe + if (!p->state->exec) { + if (p->state->exit_fifo != NULL) { + efd = open_no_inherit("exit_fifo", O_WRONLY, -1); + if (efd < 0) { + write_message(g_log_fd, ERR_MSG, "open exit pipe failed:%d", SHIM_SYS_ERR(errno)); + exit(EXIT_FAILURE); + } + p->exit_fd = efd; + } + } + + // create main loop and start epoll + ret = process_io_init(p); + if (ret != SHIM_OK) { + write_message(g_log_fd, ERR_MSG, "process io init failed:%d", ret); + exit(EXIT_FAILURE); + } + + ret = open_io(p); + if (ret != SHIM_OK) { + exit(EXIT_FAILURE); + } + + ret = create_process(p); + if (ret != SHIM_OK) { + exit(EXIT_FAILURE); + } + + released_timeout_exit(); + + ret = process_signal_handle_routine(p); + if (ret != SHIM_OK) { + exit(EXIT_FAILURE); + } + + exit(EXIT_SUCCESS); +} diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c new file mode 100644 index 0000000000000000000000000000000000000000..e2289755be92f794d49013d5a6332db758b23975 --- /dev/null +++ b/src/cmd/isulad-shim/process.c @@ -0,0 +1,1013 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: leizhongkai + * Create: 2020-1-20 + * Description: process operation encapsulation + ******************************************************************************/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "process.h" + +#define MAX_EVENTS 100 +#define DEFAULT_IO_COPY_BUF (16*1024) + +extern int g_log_fd; + +typedef int (*epoll_loop_callback_t)(int fd, uint32_t event, void *data); + +struct epoll_loop_handler { + epoll_loop_callback_t cb; + int epfd; + int cbfd; + void *cbdata; +}; + + +static shim_client_process_state* load_process() +{ + parser_error err = NULL; + shim_client_process_state *p_state = NULL; + p_state = shim_client_process_state_parse_file("process.json", NULL, &err); + if (p_state == NULL) { + write_message(g_log_fd, ERR_MSG, "parse process state failed"); + goto out; + } +out: + if (err != NULL) { + free(err); + } + + return p_state; +} + +static int open_fifo_noblock(const char *path, mode_t mode) +{ + int fd = -1; + + // By default, We consider that the file has been created by isulad + fd = open_no_inherit(path, mode | O_NONBLOCK, -1); + if (fd < 0) { + write_message(g_log_fd, ERR_MSG, "open fifo file failed:%d", SHIM_SYS_ERR(errno)); + return -1; + } + + return fd; +} + +static int receive_fd(int sock) +{ + u_char *pfd = NULL; + int fd = -1; + int cmsgsize = CMSG_LEN(sizeof(int)); + struct cmsghdr* cmptr = (struct cmsghdr*)calloc(1, cmsgsize); + if (cmptr == NULL) { + return -1; + } + + char buf[32] = { 0 }; + struct iovec iov[1]; + iov[0].iov_base = buf; + iov[0].iov_len = sizeof(buf); + + struct msghdr msg; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmptr; + msg.msg_controllen = cmsgsize; + + int ret = recvmsg(sock, &msg, 0); + if (ret == -1) { + free(cmptr); + write_message(g_log_fd, ERR_MSG, "get console fd failed:%d", SHIM_SYS_ERR(errno)); + return -1; + } + + pfd = CMSG_DATA(cmptr); + fd = *(int *)pfd; + free(cmptr); + + return fd; +} + +static bool check_fd(int fd) +{ + struct termios term; + int ret = ioctl(fd, TCGETS, &term); + if (ret != 0) { + return false; + } + + return true; +} + +static int add_io_dispatch(int epfd, io_thread_t *io_thd, int from, int to) +{ + int ret = SHIM_ERR; + + if (io_thd == NULL || io_thd->ioc == NULL) { + return SHIM_ERR; + } + + io_copy_t *ioc = io_thd->ioc; + fd_node_t *fn = (fd_node_t *)calloc(1, sizeof(fd_node_t)); + if (fn == NULL) { + return SHIM_ERR; + } + fn->fd = to; + fn->next = NULL; + + pthread_mutex_lock(&(ioc->mutex)); + // add src fd + if (from != -1 && ioc->fd_from == -1) { + ioc->fd_from = from; + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.ptr = io_thd; + + ret = epoll_ctl(epfd, EPOLL_CTL_ADD, from, &ev); + if (ret != SHIM_OK) { + write_message(g_log_fd, ERR_MSG, "add fd %d to epoll loop failed:%d", from, SHIM_SYS_ERR(errno)); + pthread_mutex_unlock(&(ioc->mutex)); + return SHIM_ERR; + } + } + + // add dest fd + if (to != -1) { + if (ioc->fd_to == NULL) { + ioc->fd_to = fn; + } else { + fd_node_t *tmp = ioc->fd_to; + while (tmp->next != NULL) { + tmp = tmp->next; + } + tmp->next = fn; + } + } + pthread_mutex_unlock(&(ioc->mutex)); + + return SHIM_OK; +} + +static void remove_io_dispatch(io_thread_t *io_thd, int from, int to) +{ + if (io_thd == NULL || io_thd->ioc == NULL) { + return; + } + io_copy_t *ioc = io_thd->ioc; + + pthread_mutex_lock(&(ioc->mutex)); + fd_node_t *tmp = NULL; + do { + // remove src fd + if (from != -1 && from == ioc->fd_from) { + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.fd = ioc->fd_from; + (void)epoll_ctl(io_thd->epfd, EPOLL_CTL_DEL, ioc->fd_from, &ev); + } + + // remove dest fd + if (ioc->fd_to == NULL) { + break; + } + if (ioc->fd_to->fd == to) { + tmp = ioc->fd_to; + ioc->fd_to = ioc->fd_to->next; + break; + } + fd_node_t *pre = NULL; + tmp = ioc->fd_to->next; + while (tmp != NULL && tmp->fd != to) { + pre = tmp; + tmp = tmp->next; + } + if (tmp != NULL) { + pre->next = tmp->next; + } + } while (0); + if (tmp != NULL) { + free(tmp); + } + pthread_mutex_unlock(&(ioc->mutex)); +} + +static void* task_io_copy(void *data) +{ + io_thread_t *io_thd = (io_thread_t*)data; + if (io_thd == NULL || io_thd->ioc == NULL) { + return NULL; + } + io_copy_t *ioc = io_thd->ioc; + char *buf = calloc(1, DEFAULT_IO_COPY_BUF + 1); + if (buf == NULL) { + _exit(EXIT_FAILURE); + } + + for (;;) { + memset(buf, 0, DEFAULT_IO_COPY_BUF); + sem_wait(&(io_thd->sem_thd)); + if (io_thd->shutdown) { + break; + } + + int r_count = read(ioc->fd_from, buf, DEFAULT_IO_COPY_BUF); + if (r_count == -1) { + // If errno == EAGAIN, that means we have read all data + if (errno == EAGAIN || errno == EINTR) { + continue; + } + break; + } else if (r_count == 0) { + // End of file. The remote has closed the connection. + break; + } else { + fd_node_t *fn = ioc->fd_to; + for (; fn != NULL; fn = fn->next) { + int w_count; + w_count = write_nointr(fn->fd, buf, r_count); + if (w_count < 0) { + // remove the write fd + remove_io_dispatch(io_thd, -1, fn->fd); + } + } + } + } + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.fd = ioc->fd_from; + (void)epoll_ctl(io_thd->epfd, EPOLL_CTL_DEL, ioc->fd_from, &ev); + + free(buf); + + return NULL; +} + +static void do_io_copy(int fd, uint32_t event, void *data) +{ + io_thread_t *thd = (io_thread_t*)data; + if (thd->ioc == NULL || fd != thd->ioc->fd_from) { + return; + } + + if (event & EPOLLIN) { + sem_post(&thd->sem_thd); + } else if (event & EPOLLHUP) { + thd->shutdown = true; + sem_post(&thd->sem_thd); + } + + return; +} + +static int process_io_start(process_t *p, int std_id) +{ + int ret = SHIM_ERR; + io_thread_t *io_thd = NULL; + io_copy_t *ioc = NULL; + + ioc = (io_copy_t *)calloc(1, sizeof(io_copy_t)); + if (ioc == NULL) { + goto failure; + } + ioc->id = std_id; + ioc->fd_from = -1; + ioc->fd_to = NULL; + if (pthread_mutex_init(&(ioc->mutex), NULL) != 0) { + goto failure; + } + + io_thd = (io_thread_t *)calloc(1, sizeof(io_thread_t)); + if (io_thd == NULL) { + goto failure; + } + if (sem_init(&io_thd->sem_thd, 0, 0) == -1) { + write_message(g_log_fd, ERR_MSG, "sem init failed:%d", SHIM_SYS_ERR(errno)); + goto failure; + } + io_thd->epfd = p->io_loop_fd; + io_thd->ioc = ioc; + io_thd->shutdown = false; + p->io_threads[std_id] = io_thd; + + ret = pthread_create(&(io_thd->tid), NULL, task_io_copy, io_thd); + if (ret != SHIM_OK) { + write_message(g_log_fd, ERR_MSG, "thread io copy create failed:%d", SHIM_SYS_ERR(errno)); + goto failure; + } + + ret = SHIM_OK; + + return ret; + +failure: + if (ioc != NULL) { + pthread_mutex_destroy(&(ioc->mutex)); + free(ioc); + } + if (io_thd != NULL) { + free(io_thd); + } + + return SHIM_ERR; +} + +static int start_io_copy_threads(process_t *p) +{ + int ret = SHIM_ERR; + int i; + + for (i = 0; i < 3; i++) { + ret = process_io_start(p, i); + if (ret != SHIM_OK) { + return SHIM_ERR; + } + } + return SHIM_OK; +} + +static void destory_io_thread(process_t *p, int std_id) +{ + io_thread_t *io_thd = p->io_threads[std_id]; + if (io_thd == NULL) { + return; + } + + io_thd->shutdown = true; + sem_post(&io_thd->sem_thd); + pthread_join(io_thd->tid, NULL); + if (io_thd->ioc != NULL) { + free(io_thd->ioc); + } + free(io_thd); + p->io_threads[std_id] = NULL; +} + +static int connect_to_isulad(process_t *p, int std_id, const char *isulad_stdio, int fd) +{ + mode_t mode; + int fd_isulad = -1; + int *fd_from = NULL; + int *fd_to = NULL; + + if (std_id == stdid_in) { + mode = O_RDONLY; + fd_from = &fd_isulad; + fd_to = &fd; + } else { + mode = O_WRONLY; + fd_from = &fd; + fd_to = &fd_isulad; + } + + if (isulad_stdio != NULL && file_exists(isulad_stdio)) { + fd_isulad = open_fifo_noblock(isulad_stdio, mode); + if (fd_isulad < 0) { + return SHIM_ERR; + } + } + + if (*fd_from != -1) { + return add_io_dispatch(p->io_loop_fd, p->io_threads[std_id], *fd_from, *fd_to); + } + + // if no I/O source is available, the I/O thread nead to be destroyed + destory_io_thread(p, std_id); + + return SHIM_OK; +} + +static void* task_console_accept(void *data) +{ + int conn_fd = -1; + int recv_fd = -1; + int ret = SHIM_ERR; + console_accept_t *ac = (console_accept_t*)data; + + conn_fd = accept(ac->listen_fd, NULL, NULL); + if (conn_fd < 0) { + write_message(g_log_fd, ERR_MSG, "accept from fd %d failed:%d", ac->listen_fd, SHIM_SYS_ERR(errno)); + exit(EXIT_FAILURE); + } + + recv_fd = receive_fd(conn_fd); + if (check_fd(recv_fd) != true) { + write_message(g_log_fd, ERR_MSG, "check console fd failed"); + exit(EXIT_FAILURE); + } + + // do console io copy + // + // p.state.stdin---->runtime.console + ret = connect_to_isulad(ac->p, stdid_in, ac->p->state->isulad_stdin, recv_fd); + if (ret != SHIM_OK) { + exit(EXIT_FAILURE); + } + + // p.state.stdout<------runtime.console + ret = connect_to_isulad(ac->p, stdid_out, ac->p->state->isulad_stdout, recv_fd); + if (ret != SHIM_OK) { + exit(EXIT_FAILURE); + } + + // if the terminal is used, we do not need to active the io copy of stderr pipe + destory_io_thread(ac->p, stdid_err); + + // release listen socket + close_fd(&ac->listen_fd); + if (ac->p->console_sock_path != NULL) { + unlink(ac->p->console_sock_path); + free(ac->p->console_sock_path); + ac->p->console_sock_path = NULL; + } + free(ac); + + return NULL; +} + +static void* task_io_loop(void *data) +{ + process_t *p = (process_t*)data; + int wait_fds = 0; + struct epoll_event evs[MAX_EVENTS]; + int i; + + p->io_loop_fd = epoll_create1(EPOLL_CLOEXEC); + if (p->io_loop_fd < 0) { + write_message(g_log_fd, ERR_MSG, "epoll create failed:%d", SHIM_SYS_ERR(errno)); + exit(EXIT_FAILURE); + } + + // begin wait + while (1) { + wait_fds = epoll_wait(p->io_loop_fd, evs, MAX_EVENTS, -1); + if (wait_fds < 0) { + if (errno == EINTR) { + continue; + } + _exit(EXIT_FAILURE); + } + + for (i = 0; i < wait_fds; i++) { + io_thread_t *thd_io = (io_thread_t*)evs[i].data.ptr; + do_io_copy(thd_io->ioc->fd_from, evs[i].events, thd_io); + } + } +} + +static int new_temp_console_path(process_t *p) +{ +#define RAND_NUM_LEN 9 + int ret = SHIM_ERR; + char str_rand[RAND_NUM_LEN + 1] = { 0 }; + + ret = generate_random_str(str_rand, RAND_NUM_LEN); + if (ret != SHIM_OK) { + return SHIM_ERR; + } + p->console_sock_path = (char *)calloc(1, MAX_CONSOLE_SOCK_LEN + 1); + if (p->console_sock_path == NULL) { + return SHIM_ERR; + } + snprintf(p->console_sock_path, MAX_CONSOLE_SOCK_LEN, "/tmp/isulad%s-pty.sock", str_rand); + + return SHIM_OK; +} + +static int console_init(process_t *p) +{ + int ret = SHIM_ERR; + int fd = -1; + struct sockaddr_un addr; + console_accept_t* ac = NULL; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + return SHIM_SYS_ERR(errno); + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, p->console_sock_path, strlen(p->console_sock_path)); + + // bind + ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); + if (ret < 0) { + write_message(g_log_fd, ERR_MSG, "bind console fd failed:%d", SHIM_SYS_ERR(errno)); + goto failure; + } + + // listen + ret = listen(fd, 2); + if (ret < 0) { + write_message(g_log_fd, ERR_MSG, "listen console fd failed:%d", SHIM_SYS_ERR(errno)); + goto failure; + } + + ac = (console_accept_t*)calloc(1, sizeof(console_accept_t)); + if (ac == NULL) { + goto failure; + } + ac->p = p; + ac->listen_fd = fd; + + pthread_t tid_accept; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&tid_accept, &attr, task_console_accept, ac); + if (ret != SHIM_OK) { + goto failure; + } + + return SHIM_OK; +failure: + close_fd(&fd); + if (ac != NULL) { + free(ac); + } + + return SHIM_ERR; +} + +static stdio_t* initialize_io(process_t *p) +{ + int ret = SHIM_ERR; + int stdio_fd[3][2] = { {-1, -1}, {-1, -1}, {-1, -1} }; + int i, j; + + stdio_t *stdio = (stdio_t *)calloc(1, sizeof(stdio_t)); + p->stdio = (stdio_t *)calloc(1, sizeof(stdio_t)); + if (p->stdio == NULL || stdio == NULL) { + goto failure; + } + + if ((pipe2(stdio_fd[0], O_CLOEXEC | O_NONBLOCK) != 0) || + (pipe2(stdio_fd[1], O_CLOEXEC | O_NONBLOCK) != 0) || + (pipe2(stdio_fd[2], O_CLOEXEC | O_NONBLOCK) != 0)) { + write_message(g_log_fd, ERR_MSG, "open pipe failed when init io:%d", SHIM_SYS_ERR(errno)); + goto failure; + } + + p->stdio->in = stdio_fd[0][0];// r + stdio->in = stdio_fd[0][1]; // w + p->stdio->out = stdio_fd[1][1];// w + stdio->out = stdio_fd[1][0];// r + p->stdio->err = stdio_fd[2][1];// w + stdio->err = stdio_fd[2][0];// r + + for (i = 0; i < 3; i++) { + for (j = 0; j < 2; j++) { + ret = fchown(stdio_fd[i][j], p->state->root_uid, p->state->root_gid); + if (ret != SHIM_OK) { + goto failure; + } + } + } + + return stdio; + +failure: + if (stdio != NULL) { + free(stdio); + stdio = NULL; + } + if (p->stdio != NULL) { + free(p->stdio); + p->stdio = NULL; + } + for (i = 0; i < 3; i++) { + for (j = 0; j < 2; j++) { + if (stdio_fd[i][j] > 0) { + close(stdio_fd[i][j]); + } + } + } + + return NULL; +} + +static int open_terminal_io(process_t *p) +{ + int ret = SHIM_ERR; + + ret = new_temp_console_path(p); + if (ret != SHIM_OK) { + write_message(g_log_fd, ERR_MSG, "get temp console sock path failed"); + return SHIM_ERR; + } + + // begin listen and accept fd from p->console_sock_path + ret = console_init(p); + if (ret != SHIM_OK) { + write_message(g_log_fd, ERR_MSG, "init console failed:%d", ret); + return SHIM_ERR; + } + return SHIM_OK; +} + + +static int open_generic_io(process_t *p) +{ + int ret = SHIM_ERR; + + stdio_t *io = initialize_io(p); + if (io == NULL) { + return SHIM_ERR; + } + p->shim_io = io; + // stdin + ret = connect_to_isulad(p, stdid_in, p->state->isulad_stdin, io->in); + if (ret != SHIM_OK) { + return SHIM_ERR; + } + // stdout + ret = connect_to_isulad(p, stdid_out, p->state->isulad_stdout, io->out); + if (ret != SHIM_OK) { + return SHIM_ERR; + } + // stderr + ret = connect_to_isulad(p, stdid_err, p->state->isulad_stderr, io->err); + if (ret != SHIM_OK) { + return SHIM_ERR; + } + + return SHIM_OK; +} + +static void adapt_for_isulad_stdin(process_t *p) +{ + // iSulad: close stdin pipe if we do not want open_stdin with container stdin just like lxc + if (p->shim_io != NULL && p->shim_io->in != -1 && !file_exists(p->state->isulad_stdin)) { + close(p->shim_io->in); + p->shim_io->in = -1; + } +} + +process_t* new_process(char *id, char *bundle, char *runtime) +{ + shim_client_process_state* p_state; + process_t* p = NULL; + int i; + + p_state = load_process(); + if (p_state == NULL) { + return NULL; + } + + p = (process_t*)calloc(1, sizeof(process_t)); + if (p == NULL) { + return NULL; + } + p->id = id; + p->bundle = bundle; + p->runtime = runtime; + p->state = p_state; + + p->console_sock_path = NULL; + p->exit_fd = -1; + p->io_loop_fd = -1; + p->ctr_pid = -1; + p->stdio = NULL; + p->shim_io = NULL; + for (i = 0; i < 3; i ++) { + p->io_threads[i] = NULL; + } + + return p; +} + +int open_io(process_t *p) +{ + int ret = SHIM_ERR; + + ret = start_io_copy_threads(p); + if (ret != SHIM_OK) { + return SHIM_ERR; + } + + if (p->state->terminal) { + return open_terminal_io(p); + } + + return open_generic_io(p); +} + + +int process_io_init(process_t *p) +{ + int ret = SHIM_ERR; + + pthread_t tid_loop; + ret = pthread_create(&tid_loop, NULL, task_io_loop, p); + if (ret != SHIM_OK) { + return SHIM_SYS_ERR(errno); + } + + return SHIM_OK; +} + +static void get_runtime_cmd(process_t *p, const char *log_path, const char *pid_path, const char *process_desc, + const char *params[]) +{ + int i = 0; + int j; + params[i++] = p->runtime; + for (j = 0; j < p->state->runtime_args_len; j++) { + params[i++] = p->state->runtime_args[j]; + } + params[i++] = "--log"; + + params[i++] = log_path; + params[i++] = "--log-format"; + params[i++] = "json"; + if (p->state->exec && process_desc != NULL) { + params[i++] = "exec"; + params[i++] = "-d"; + params[i++] = "--process"; + params[i++] = process_desc; + } else { + params[i++] = "create"; + params[i++] = "--bundle"; + params[i++] = p->bundle; + } + params[i++] = "--pid-file"; + params[i++] = pid_path; + if (p->console_sock_path != NULL) { + params[i++] = "--console-socket"; + params[i++] = p->console_sock_path; + } + params[i++] = p->id; +} + +static int reap_container(int ctr_pid, int *status) +{ +#define EXIT_SIGNAL_OFFSET 128 + int st; + struct rusage rus; + + // block wait + int pid = wait4(-1, &st, 0, &rus); + if (pid <= 0) { + return SHIM_ERR_WAIT; + } else if (pid != ctr_pid) { + return SHIM_ERR; + } + + if (WIFSIGNALED(st)) { + *status = EXIT_SIGNAL_OFFSET + WTERMSIG(st); + } else { + *status = WEXITSTATUS(st); + } + + return SHIM_OK; +} + +static void process_kill_all(process_t *p) +{ + if (p->state->exec) { + return; + } + + const char *params[MAX_RUNTIME_ARGS] = { NULL }; + char output[BUFSIZ] = { 0 }; + int output_len = BUFSIZ; + int i = 0; + int j; + + params[i++] = p->runtime; + for (j = 0; j < p->state->runtime_args_len; j++) { + params[i++] = p->state->runtime_args[j]; + } + params[i++] = "kill"; + params[i++] = "--all"; + params[i++] = p->id; + params[i++] = "SIGKILL"; + + (void)cmd_combined_output(p->runtime, params, output, &output_len); + + return; +} + +void process_delete(process_t *p) +{ + if (p->state->exec) { + return; + } + + const char *params[MAX_RUNTIME_ARGS] = { NULL }; + char output[BUFSIZ] = { 0 }; + int output_len = BUFSIZ; + int i = 0; + int j; + char log_path[PATH_MAX] = { 0 }; + char *cwd; + + cwd = getcwd(NULL, 0); + if (cwd == NULL) { + write_message(g_log_fd, ERR_MSG, "get cwd failed when do process delete"); + return; + } + snprintf(log_path, PATH_MAX, "%s/log.json", cwd); + + params[i++] = "--log"; + params[i++] = log_path; + params[i++] = "--log-format"; + params[i++] = "json"; + params[i++] = p->runtime; + for (j = 0; j < p->state->runtime_args_len; j++) { + params[i++] = p->state->runtime_args[j]; + } + + params[i++] = "delete"; + params[i++] = p->id; + + cmd_combined_output(p->runtime, params, output, &output_len); + + return; +} + +int create_process(process_t *p) +{ + int ret = -1; + char *data = NULL; + int exec_fd[2] = { -1, -1 }; + char exec_buff[BUFSIZ + 1] = { 0 }; + int nread = -1; + + if (pipe2(exec_fd, O_CLOEXEC) != 0) { + write_message(g_log_fd, ERR_MSG, "create pipe failed when create process:%d", SHIM_SYS_ERR(errno)); + return SHIM_ERR; + } + + pid_t pid = fork(); + if (pid == (pid_t) - 1) { + write_message(g_log_fd, ERR_MSG, "fork failed when create process:%d", SHIM_SYS_ERR(errno)); + return SHIM_ERR; + } + + // child:runtime + if (pid == (pid_t)0) { + close_fd(&exec_fd[0]); + if (p->shim_io != NULL) { + if (p->shim_io->in != -1) { + close(p->shim_io->in); + p->shim_io->in = -1; + dup2(p->stdio->in, 0); + } + if (p->shim_io->out != -1) { + close(p->shim_io->out); + p->shim_io->out = -1; + dup2(p->stdio->out, 1); + } + if (p->shim_io->err != -1) { + close(p->shim_io->err); + p->shim_io->err = -1; + dup2(p->stdio->err, 2); + } + } + + char *cwd = getcwd(NULL, 0); + char *log_path = (char *)calloc(1, PATH_MAX); + char *pid_path = (char *)calloc(1, PATH_MAX); + if (cwd == NULL || log_path == NULL || pid_path == NULL) { + (void)dprintf(exec_fd[1], "memory error: %s", strerror(errno)); + _exit(EXIT_FAILURE); + } + + snprintf(log_path, PATH_MAX, "%s/log.json", cwd); + snprintf(pid_path, PATH_MAX, "%s/pid", cwd); + + char *process_desc = NULL; + if (p->state->exec) { + process_desc = (char *)calloc(1, PATH_MAX); + if (process_desc == NULL) { + (void)dprintf(exec_fd[1], "memory error: %s", strerror(errno)); + _exit(EXIT_FAILURE); + } + snprintf(process_desc, PATH_MAX, "%s/process.json", cwd); + } + + const char *params[MAX_RUNTIME_ARGS] = { 0 }; + get_runtime_cmd(p, log_path, pid_path, process_desc, params); + execvp(p->runtime, (char * const *)params); + (void)dprintf(exec_fd[1], "fork/exec error: %s", strerror(errno)); + _exit(EXIT_FAILURE); + } + + // parent + close_fd(&exec_fd[1]); + if (p->stdio != NULL) { + close_fd(&p->stdio->in); + close_fd(&p->stdio->out); + close_fd(&p->stdio->err); + } + nread = read_nointr(exec_fd[0], exec_buff, sizeof(exec_buff)); + if (nread > 0) { + write_message(g_log_fd, ERR_MSG, "runtime error"); + ret = SHIM_ERR; + goto out; + } + + // block to wait pid exit + ret = waitpid(pid, NULL, 0); + if (ret != pid) { + write_message(g_log_fd, ERR_MSG, "wait runtime failed:%d", SHIM_SYS_ERR(errno)); + ret = SHIM_ERR; + goto out; + } + + // save pid + data = read_text_file("pid"); + if (data == NULL) { + write_message(g_log_fd, ERR_MSG, "read pid of runtime failed"); + goto out; + } + int ctr_pid = atoi(data); + if (ctr_pid <= 0) { + goto out; + } + + p->ctr_pid = ctr_pid; + adapt_for_isulad_stdin(p); + ret = SHIM_OK; + +out: + close_fd(&exec_fd[0]); + if (data != NULL) { + free(data); + } + + return ret; +} + +int process_signal_handle_routine(process_t *p) +{ + int ret = SHIM_ERR; + bool exit_shim = false; + int i; + + for (;;) { + int status; + ret = reap_container(p->ctr_pid, &status); + if (ret == SHIM_OK) { + exit_shim = true; + if (p->exit_fd > 0) { + (void)write_nointr(p->exit_fd, &status, sizeof(int)); + } + if (status == CONTAINER_ACTION_REBOOT) { + ret = setenv("CONTAINER_ACTION", "reboot", 1); + if (ret != SHIM_OK) { + write_message(g_log_fd, WARN_MSG, "set reboot action failed:%d", SHIM_SYS_ERR(errno)); + } + } else if (status == CONTAINER_ACTION_SHUTDOWN) { + ret = setenv("CONTAINER_ACTION", "shutdown", 1); + if (ret != SHIM_OK) { + write_message(g_log_fd, WARN_MSG, "set shutdown action failed:%d", SHIM_SYS_ERR(errno)); + } + } + } else if (ret == SHIM_ERR_WAIT) { + // avoid thread entering the infinite loop + usleep(1000); + continue; + } + if (exit_shim) { + process_kill_all(p); + process_delete(p); + for (i = 0; i < 3; i ++) { + destory_io_thread(p, i); + } + return status; + } + } +} + diff --git a/src/cmd/isulad-shim/process.h b/src/cmd/isulad-shim/process.h new file mode 100644 index 0000000000000000000000000000000000000000..e641813c12664dc5089f0b8b6862fc99e04cfc40 --- /dev/null +++ b/src/cmd/isulad-shim/process.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: leizhongkai + * Create: 2020-1-20 + * Description: process definition + ******************************************************************************/ + +#ifndef __SHIM_PROCESS_H_ +#define __SHIM_PROCESS_H_ + +#include +#include +#include +#include "shim_client_process_state.h" + +enum { + stdid_in = 0, + stdid_out, + stdid_err +}; + +typedef struct { + int in; + int out; + int err; +} stdio_t; + +typedef struct fd_node { + int fd; + struct fd_node *next; +} fd_node_t; + +typedef struct { + int fd_from; + fd_node_t *fd_to; + int id;// 0,1,2 + pthread_mutex_t mutex; +} io_copy_t; + +typedef struct { + int epfd; + pthread_t tid; + pthread_attr_t attr; + sem_t sem_thd; + io_copy_t *ioc; + bool shutdown; +} io_thread_t; + +typedef struct process { + char *id; + char *bundle; + char *runtime; + char *console_sock_path; + int io_loop_fd; + int exit_fd; + int ctr_pid; + stdio_t *stdio; + stdio_t *shim_io; + io_thread_t *io_threads[3];// stdin,stdout,stderr + shim_client_process_state *state; +} process_t; + +typedef struct { + int listen_fd; + process_t *p; +} console_accept_t; + +typedef struct { + int pid; + int status; +} process_exit_t; + + + +process_t* new_process(char *id, char *bundle, char *runtime); + +int open_io(process_t *p); +int process_io_init(process_t *p); +int create_process(process_t *p); +int process_signal_handle_routine(process_t *p); +void process_delete(process_t *p); + + +#endif + diff --git a/src/config/isulad_config.c b/src/config/isulad_config.c index fbd00804341cd9394f89802fa2a10b604d247e00..a4d7e1ad3afa9e59ef607e312192077d39f45a2d 100644 --- a/src/config/isulad_config.c +++ b/src/config/isulad_config.c @@ -1206,6 +1206,28 @@ out: return result; } +char *conf_get_default_runtime() +{ + struct service_arguments *conf = NULL; + char *result = NULL; + + if (isulad_server_conf_rdlock()) { + ERROR("BUG conf_rdlock failed"); + return NULL; + } + + conf = conf_get_server_conf(); + if (conf == NULL || conf->json_confs == NULL) { + goto out; + } + + result = strings_to_lower(conf->json_confs->default_runtime); + +out: + (void)isulad_server_conf_unlock(); + return result; +} + bool conf_update_im_server_sock_addr(const char *new_sock_addr) { struct service_arguments *conf = NULL; @@ -1765,6 +1787,7 @@ int merge_json_confs_into_global(struct service_arguments *args) goto out; } + override_string_value(&args->json_confs->default_runtime, &tmp_json_confs->default_runtime); override_string_value(&args->json_confs->group, &tmp_json_confs->group); override_string_value(&args->json_confs->graph, &tmp_json_confs->graph); override_string_value(&args->json_confs->state, &tmp_json_confs->state); @@ -1790,6 +1813,9 @@ int merge_json_confs_into_global(struct service_arguments *args) override_string_value(&args->json_confs->cni_bin_dir, &tmp_json_confs->cni_bin_dir); override_string_value(&args->json_confs->cni_conf_dir, &tmp_json_confs->cni_conf_dir); + args->json_confs->runtimes = tmp_json_confs->runtimes; + tmp_json_confs->runtimes = NULL; + // Daemon storage-driver if (merge_storage_conf_into_global(args, tmp_json_confs)) { ret = -1; diff --git a/src/config/isulad_config.h b/src/config/isulad_config.h index 58ce0687eaa9b4f564b7f0fe71cdfcf281c1ce23..5e90c02e1c86e993daec354316a31266f7e1e62d 100644 --- a/src/config/isulad_config.h +++ b/src/config/isulad_config.h @@ -92,6 +92,8 @@ unsigned int conf_get_im_opt_timeout(); char *conf_get_im_server_sock_addr(); +char *conf_get_default_runtime(); + bool conf_update_im_server_sock_addr(const char *new_sock_addr); char *conf_get_graph_check_flag_file(); diff --git a/src/connect/client/grpc/grpc_containers_client.cc b/src/connect/client/grpc/grpc_containers_client.cc index 4a3a53f4c4e3e738d82a8e688ee998b6611862ae..e35592bc40ff6f0b0387813528c8895133663271 100644 --- a/src/connect/client/grpc/grpc_containers_client.cc +++ b/src/connect/client/grpc/grpc_containers_client.cc @@ -230,10 +230,6 @@ public: { int nret = -1; - if (req.runtime().empty()) { - ERROR("Missing runtime in the request"); - return nret; - } if (req.rootfs().empty() && req.image().empty()) { ERROR("Missing container rootfs or image arguments in the request"); return nret; diff --git a/src/connect/client/rest/rest_containers_client.c b/src/connect/client/rest/rest_containers_client.c index 26d8bdb7b77aed8a8ad9c0eb13b951999c4b9773..09d71350a39a708a05658ffcd1c3357686fdb8a9 100644 --- a/src/connect/client/rest/rest_containers_client.c +++ b/src/connect/client/rest/rest_containers_client.c @@ -330,7 +330,7 @@ static int unpack_create_response(const struct parsed_http_message *message, voi response->id = util_strdup_s(cresponse->id); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -364,7 +364,7 @@ static int unpack_start_response(const struct parsed_http_message *message, void start_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -455,7 +455,7 @@ static int unpack_list_response(const struct parsed_http_message *message, void response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } if (unpack_container_info_for_list_response(cresponse, response)) { @@ -493,7 +493,7 @@ static int unpack_attach_response(const struct parsed_http_message *message, voi attach_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -527,7 +527,7 @@ static int unpack_resume_response(const struct parsed_http_message *message, voi resume_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -562,7 +562,7 @@ static int unpack_wait_response(const struct parsed_http_message *message, void response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -830,7 +830,7 @@ static int unpack_stop_response(const struct parsed_http_message *message, void stop_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -930,7 +930,7 @@ static int unpack_restart_response(const struct parsed_http_message *message, vo response->errmsg = util_strdup_s(cres->errmsg); } ret = (cres->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -1043,7 +1043,7 @@ static int unpack_update_response(const struct parsed_http_message *message, voi update_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -1150,7 +1150,7 @@ static int unpack_version_response(const struct parsed_http_message *message, vo version_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -1249,7 +1249,7 @@ static int unpack_pause_response(const struct parsed_http_message *message, void pause_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -1349,7 +1349,7 @@ static int unpack_kill_response(const struct parsed_http_message *message, void kill_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -1449,7 +1449,7 @@ static int unpack_remove_response(const struct parsed_http_message *message, voi delete_response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -1554,7 +1554,7 @@ static int unpack_inspect_response(const struct parsed_http_message *message, vo response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -1704,7 +1704,7 @@ static int unpack_exec_response(const struct parsed_http_message *message, void response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } diff --git a/src/connect/client/rest/rest_images_client.c b/src/connect/client/rest/rest_images_client.c index 90ca4dbff06d1af7937c2ae2b1183d0a64a8bd9b..aaa71bcee932b19ae84fe9cbae7e41a8fe2b34eb 100644 --- a/src/connect/client/rest/rest_images_client.c +++ b/src/connect/client/rest/rest_images_client.c @@ -174,7 +174,7 @@ static int unpack_image_list_response(const struct parsed_http_message *message, response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -213,7 +213,7 @@ static int unpack_image_load_response(const struct parsed_http_message *message, c_load_response->errmsg = util_strdup_s(load_response->errmsg); } ret = (load_response->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -279,7 +279,7 @@ static int unpack_image_delete_response(const struct parsed_http_message *messag c_rmi_response->errmsg = util_strdup_s(delete_response->errmsg); } ret = (delete_response->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } @@ -416,7 +416,7 @@ static int unpack_inspect_response(const struct parsed_http_message *message, vo response->errmsg = util_strdup_s(cresponse->errmsg); } ret = (cresponse->cc == ISULAD_SUCCESS) ? 0 : -1; - if (message->status_code == EVHTP_RES_SERVERR) { + if (message->status_code == RESTFUL_RES_SERVERR) { ret = -1; } diff --git a/src/connect/service/grpc/runtime_runtime_service.cc b/src/connect/service/grpc/runtime_runtime_service.cc index 51f0cce8225e6bd9c787bda380272dc74d90ee6b..62e96a12eb55a37f5a4f1aab91badfabfa37bfca 100644 --- a/src/connect/service/grpc/runtime_runtime_service.cc +++ b/src/connect/service/grpc/runtime_runtime_service.cc @@ -194,7 +194,7 @@ grpc::Status RuntimeRuntimeServiceImpl::RunPodSandbox( runtime::v1alpha2::RunPodSandboxResponse *reply) { Errors error; - std::string responseID = rService.RunPodSandbox(request->config(), error); + std::string responseID = rService.RunPodSandbox(request->config(), request->runtime_handler(), error); if (!error.Empty() || responseID.empty()) { return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); } diff --git a/src/connect/service/rest/rest_containers_service.c b/src/connect/service/rest/rest_containers_service.c index 30ac09344e66e3ad8a9c8fa249983c1988a0feae..ed6c1ce47b7f2bc04d661a2f274cbb5c8197ebfe 100644 --- a/src/connect/service/rest/rest_containers_service.c +++ b/src/connect/service/rest/rest_containers_service.c @@ -208,14 +208,14 @@ static void evhtp_send_create_repsponse(evhtp_request_t *req, container_create_r if (response == NULL) { ERROR("Failed to generate create response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_create_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Create: failed to generate request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -345,14 +345,14 @@ static void evhtp_send_start_repsponse(evhtp_request_t *req, container_start_res if (response == NULL) { ERROR("Failed to generate start response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_start_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate start request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -373,14 +373,14 @@ static void evhtp_send_list_repsponse(evhtp_request_t *req, container_list_respo if (response == NULL) { ERROR("Failed to generate inspect response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_list_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate list request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -402,7 +402,7 @@ static void evhtp_send_wait_repsponse(evhtp_request_t *req, container_wait_respo responsedata = container_wait_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate wait request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -424,26 +424,26 @@ static void rest_create_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.create == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceCreate); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.create(crequest, &cresponse); - evhtp_send_create_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_create_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_create_response(cresponse); free_container_create_request(crequest); @@ -459,26 +459,26 @@ static void rest_start_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.start == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceStart); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.start(crequest, &cresponse, -1, NULL, NULL); - evhtp_send_start_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_start_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_start_request(crequest); free_container_start_response(cresponse); @@ -494,26 +494,26 @@ static void rest_wait_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.wait == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceWait); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.wait(crequest, &cresponse); - evhtp_send_wait_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_wait_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_wait_request(crequest); free_container_wait_response(cresponse); @@ -528,14 +528,14 @@ static void evhtp_send_stop_repsponse(evhtp_request_t *req, container_stop_respo if (response == NULL) { ERROR("Failed to generate stop response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_stop_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate stop request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -557,26 +557,26 @@ static void rest_stop_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.stop == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceStop); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.stop(crequest, &cresponse); - evhtp_send_stop_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_stop_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_stop_response(cresponse); free_container_stop_request(crequest); @@ -591,13 +591,13 @@ static void evhtp_send_restart_response(evhtp_request_t *req, container_restart_ if (response == NULL) { ERROR("Failed to generate restart response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_restart_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate restart response json: %s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -618,27 +618,27 @@ static void rest_restart_cb(evhtp_request_t *req, void *arg) container_restart_response *cresponse = NULL; if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.restart == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceRestart); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.restart(crequest, &cresponse); - evhtp_send_restart_response(req, cresponse, EVHTP_RES_OK); + evhtp_send_restart_response(req, cresponse, RESTFUL_RES_OK); out: free_container_restart_request(crequest); free_container_restart_response(cresponse); @@ -654,7 +654,7 @@ static void evhtp_send_version_repsponse(evhtp_request_t *req, container_version responsedata = container_version_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate version request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -676,26 +676,26 @@ static void rest_version_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.version == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceVersion); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.version(crequest, &cresponse); - evhtp_send_version_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_version_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_version_request(crequest); free_container_version_response(cresponse); @@ -710,14 +710,14 @@ static void evhtp_send_update_repsponse(evhtp_request_t *req, container_update_r if (response == NULL) { ERROR("Invalid NULL response"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_update_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate update request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -739,25 +739,25 @@ static void rest_update_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.update == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&container_req, ContainerServiceUpdate); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.update(container_req, &container_res); - evhtp_send_update_repsponse(req, container_res, EVHTP_RES_OK); + evhtp_send_update_repsponse(req, container_res, RESTFUL_RES_OK); out: free_container_update_request(container_req); @@ -773,13 +773,13 @@ static void evhtp_send_kill_repsponse(evhtp_request_t *req, container_kill_respo if (response == NULL) { ERROR("Failed to generate kill response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_kill_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate kill request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -801,26 +801,26 @@ static void rest_kill_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.kill == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceKill); if (tret < 0) { ERROR("bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.kill(crequest, &cresponse); - evhtp_send_kill_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_kill_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_kill_request(crequest); free_container_kill_response(cresponse); @@ -836,14 +836,14 @@ static void evhtp_send_container_inspect_repsponse(evhtp_request_t *req, contain if (response == NULL) { ERROR("Failed to generate inspect response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_inspect_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate inspect request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -865,26 +865,26 @@ static void rest_container_inspect_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.inspect == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceInspect); if (tret < 0) { ERROR("bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.inspect(crequest, &cresponse); - evhtp_send_container_inspect_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_container_inspect_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_inspect_request(crequest); free_container_inspect_response(cresponse); @@ -899,14 +899,14 @@ static void evhtp_send_exec_repsponse(evhtp_request_t *req, container_exec_respo if (response == NULL) { ERROR("Failed to generate exec response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_exec_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate exec request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -928,26 +928,26 @@ static void rest_exec_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || !cb->container.exec) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceExec); if (tret < 0) { ERROR("bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.exec(crequest, &cresponse, -1, NULL); - evhtp_send_exec_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_exec_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_exec_request(crequest); free_container_exec_response(cresponse); @@ -962,13 +962,13 @@ static void evhtp_send_remove_repsponse(evhtp_request_t *req, container_delete_r if (response == NULL) { ERROR("Failed to generate remove response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = container_delete_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate remove request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -990,26 +990,26 @@ static void rest_remove_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.remove == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceRemove); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.remove(crequest, &cresponse); - evhtp_send_remove_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_remove_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_delete_request(crequest); free_container_delete_response(cresponse); @@ -1025,26 +1025,26 @@ static void rest_list_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->container.list == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = action_request_from_rest(req, (void **)&crequest, ContainerServiceList); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->container.list(crequest, &cresponse); - evhtp_send_list_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_list_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_container_list_request(crequest); free_container_list_response(cresponse); diff --git a/src/connect/service/rest/rest_images_service.c b/src/connect/service/rest/rest_images_service.c index 5a90740caf5564d84036df96a3ca4f009b8b8bb6..d6cb37f6abededab8c3ba67d806dc8a2aba87a9d 100644 --- a/src/connect/service/rest/rest_images_service.c +++ b/src/connect/service/rest/rest_images_service.c @@ -78,7 +78,7 @@ static void evhtp_send_image_load_repsponse(evhtp_request_t *req, responsedata = image_load_image_response_generate_json(response, NULL, &err); if (responsedata == NULL) { ERROR("Load: failed to generate request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } evhtp_send_response(req, responsedata, rescode); @@ -126,7 +126,7 @@ static void evhtp_send_image_list_repsponse(evhtp_request_t *req, responsedata = image_list_images_response_generate_json(response, NULL, &err); if (responsedata == NULL) { ERROR("List: failed to generate request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } evhtp_send_response(req, responsedata, rescode); @@ -198,7 +198,7 @@ static void evhtp_send_image_delete_repsponse(evhtp_request_t *req, } ERROR("Delete: failed to generate request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); out: free(responsedata); free(err); @@ -259,14 +259,14 @@ static void evhtp_send_image_inspect_repsponse(evhtp_request_t *req, if (response == NULL) { ERROR("Failed to generate inspect response info"); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } responsedata = image_inspect_response_generate_json(response, &ctx, &err); if (responsedata == NULL) { ERROR("Failed to generate inspect request json:%s", err); - evhtp_send_reply(req, EVHTP_RES_ERROR); + evhtp_send_reply(req, RESTFUL_RES_ERROR); goto out; } @@ -288,26 +288,26 @@ static void rest_image_load_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->image.load == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = image_load_request_from_rest(req, &crequest); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->image.load(crequest, &cresponse); - evhtp_send_image_load_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_image_load_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_image_load_image_request(crequest); free_image_load_image_response(cresponse); @@ -323,26 +323,26 @@ static void rest_image_list_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->image.list == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = image_list_request_from_rest(req, &crequest); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->image.list(crequest, &cresponse); - evhtp_send_image_list_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_image_list_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_image_list_images_request(crequest); free_image_list_images_response(cresponse); @@ -358,26 +358,26 @@ static void rest_image_delete_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->image.remove == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = image_delete_request_from_rest(req, &crequest); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->image.remove(crequest, &cresponse); - evhtp_send_image_delete_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_image_delete_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_image_delete_image_request(crequest); free_image_delete_image_response(cresponse); @@ -393,26 +393,26 @@ static void rest_image_inspect_cb(evhtp_request_t *req, void *arg) // only deal with POST request if (evhtp_request_get_method(req) != htp_method_POST) { - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } cb = get_service_callback(); if (cb == NULL || cb->image.inspect == NULL) { ERROR("Unimplemented callback"); - evhtp_send_reply(req, EVHTP_RES_NOTIMPL); + evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); return; } tret = image_inspect_request_from_rest(req, &crequest); if (tret < 0) { ERROR("Bad request"); - evhtp_send_reply(req, EVHTP_RES_SERVERR); + evhtp_send_reply(req, RESTFUL_RES_SERVERR); goto out; } (void)cb->image.inspect(crequest, &cresponse); - evhtp_send_image_inspect_repsponse(req, cresponse, EVHTP_RES_OK); + evhtp_send_image_inspect_repsponse(req, cresponse, RESTFUL_RES_OK); out: free_image_inspect_request(crequest); free_image_inspect_response(cresponse); diff --git a/src/connect/service/rest/rest_service_common.h b/src/connect/service/rest/rest_service_common.h index 2192c3ab7bb11e6bdeb2a709acf953010833c66f..f007c21831220c22d4198d34a631411d56332538 100644 --- a/src/connect/service/rest/rest_service_common.h +++ b/src/connect/service/rest/rest_service_common.h @@ -17,6 +17,8 @@ #include +#include "rest_common.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/src/container_def.h b/src/container_def.h index c18c2a8dafc29a733a8df1ef438038e210e7a3b0..9aae2f44ebf1e521c1f1a2abad54532a9f43706a 100644 --- a/src/container_def.h +++ b/src/container_def.h @@ -40,7 +40,7 @@ extern "C" { #define SECCOMP_DEFAULT_PATH "/etc/isulad/seccomp_default.json" #endif #ifndef OCI_VERSION -#define OCI_VERSION "1.0.0-rc5-dev" +#define OCI_VERSION "1.0.1" #endif typedef enum { diff --git a/src/contrib/config/config.json b/src/contrib/config/config.json index 9a9ec870bcab56a9b99200900ebb31e3533e5b14..59c1bfb64428411494f28e70111d15893a1aa985 100644 --- a/src/contrib/config/config.json +++ b/src/contrib/config/config.json @@ -1,5 +1,5 @@ { - "ociVersion": "1.0.0-rc5-dev", + "ociVersion": "1.0.1", "process": { "terminal": true, "consoleSize": { @@ -96,18 +96,6 @@ "ro" ] }, - { - "destination": "/dev/shm", - "type": "tmpfs", - "source": "shm", - "options": [ - "nosuid", - "noexec", - "nodev", - "mode=1777", - "size=65536k" - ] - }, { "destination": "/sys/fs/cgroup", "type": "cgroup", diff --git a/src/contrib/config/daemon.json b/src/contrib/config/daemon.json index 7baea20d4dc41d0f354cb9ea9727ee20b2f12f1b..dfd2a63ad2edfe7a0637c759c6b21d7490e81402 100644 --- a/src/contrib/config/daemon.json +++ b/src/contrib/config/daemon.json @@ -1,5 +1,6 @@ { "group": "isulad", + "default-runtime": "lcr", "graph": "/var/lib/isulad", "state": "/var/run/isulad", "engine": "lcr", diff --git a/src/contrib/config/systemcontainer_config.json b/src/contrib/config/systemcontainer_config.json index 3d2bd899ab3da9391e52d5448390675a4815d834..dfef975eca69c46dba7f2705a2ee48adcd83130b 100644 --- a/src/contrib/config/systemcontainer_config.json +++ b/src/contrib/config/systemcontainer_config.json @@ -1,5 +1,5 @@ { - "ociVersion": "1.0.0-rc5-dev", + "ociVersion": "1.0.1", "process": { "terminal": true, "consoleSize": { @@ -96,18 +96,6 @@ "ro" ] }, - { - "destination": "/dev/shm", - "type": "tmpfs", - "source": "shm", - "options": [ - "nosuid", - "noexec", - "nodev", - "mode=1777", - "size=65536k" - ] - }, { "destination": "/sys/fs/cgroup", "type": "cgroup", diff --git a/src/cutils/utils.c b/src/cutils/utils.c index 1e30aafa52a5a4451eaef5933b78a42d6fc7b77c..092f72e878cc15603b2268ee6a255be0bfc5e58b 100644 --- a/src/cutils/utils.c +++ b/src/cutils/utils.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/src/cutils/utils_file.c b/src/cutils/utils_file.c index 95df5ba9104a28ab17b1fbdc752c71f1450554e8..182570d46ada17826eb4ac744c7681646865b383 100644 --- a/src/cutils/utils_file.c +++ b/src/cutils/utils_file.c @@ -552,7 +552,7 @@ char *util_full_file_digest(const char *filename) return full_digest; } -static char *util_path_dir(const char *path) +char *util_path_dir(const char *path) { char *dir = NULL; int len = 0; diff --git a/src/cutils/utils_file.h b/src/cutils/utils_file.h index 78ae5cd7713abb0bc3e189308eedda63b9c07020..d868fa722df856f3c40e1df1cd3b7e31797598f9 100644 --- a/src/cutils/utils_file.h +++ b/src/cutils/utils_file.h @@ -55,6 +55,8 @@ FILE *util_fopen(const char *filename, const char *mode); char *util_full_file_digest(const char *filename); +char *util_path_dir(const char *path); + char *util_add_path(const char *path, const char *name); char *util_read_text_file(const char *path); diff --git a/src/cutils/utils_string.c b/src/cutils/utils_string.c index 27136bbbe383ecd83ef70c52150ebadb62b8496a..80778bc7c229d19fefdcde5a88248eac4931b5fc 100644 --- a/src/cutils/utils_string.c +++ b/src/cutils/utils_string.c @@ -79,6 +79,18 @@ bool strings_contains_any(const char *str, const char *substr) return false; } +bool strings_contains_word(const char *str, const char *substr) +{ + if (str == NULL || substr == NULL) { + return false; + } + + if (strcasestr(str, substr) != NULL) { + return true; + } + return false; +} + int strings_count(const char *str, unsigned char c) { size_t i = 0; @@ -271,7 +283,8 @@ int util_parse_percent_string(const char *s, long *converted) { char *dup = NULL; - if (s == NULL || converted == NULL || s[0] == 0 || strlen(s) < 2 || s[strlen(s) - 1] != '%') { + if (s == NULL || converted == NULL || s[0] == 0 || strlen(s) < 2 || s[strlen(s) - 1] != '%' || + strspn(s, "0123456789%") != strlen(s)) { return -EINVAL; } dup = util_strdup_s(s); @@ -282,7 +295,7 @@ int util_parse_percent_string(const char *s, long *converted) *converted = strtol(dup, NULL, 10); if ((errno == ERANGE && (*converted == LONG_MAX || *converted == LONG_MIN)) || - (errno != 0 && *converted == 0) || *converted < 0 || *converted >= 100) { + (errno != 0 && *converted == 0) || *converted < 0 || *converted > 100) { free(dup); return -EINVAL; } diff --git a/src/cutils/utils_string.h b/src/cutils/utils_string.h index d8699361d6acbd35f29453cd7cc29a025d53a5e9..00cd5360d3b251ddff0f617c40df162ce019b4a0 100644 --- a/src/cutils/utils_string.h +++ b/src/cutils/utils_string.h @@ -25,6 +25,8 @@ extern "C" { bool strings_contains_any(const char *str, const char *substr); +bool strings_contains_word(const char *str, const char *substr); + int strings_count(const char *str, unsigned char c); bool strings_in_slice(const char **strarray, size_t alen, const char *str); diff --git a/src/cutils/utils_verify.c b/src/cutils/utils_verify.c index 562a942f56a3f3191c954cd642694db025bf7c3f..4793a4db74bf299bed9acb1ff25c856922c534f9 100644 --- a/src/cutils/utils_verify.c +++ b/src/cutils/utils_verify.c @@ -274,7 +274,7 @@ bool util_valid_runtime_name(const char *name) return false; } - return strcasecmp(name, "lcr") == 0; + return true; } bool util_valid_host_name(const char *name) diff --git a/src/http/rest_common.c b/src/http/rest_common.c index f195ecc4e373c006c75e4f401bd6ba29a6e9177a..ba2d44153f19d22715a4784b854e2f7052b83d7e 100644 --- a/src/http/rest_common.c +++ b/src/http/rest_common.c @@ -52,15 +52,15 @@ static int g_ops_status = 0; /* check status code */ int check_status_code(int status_code) { - if (status_code == EVHTP_RES_OK || status_code == EVHTP_RES_SERVERR) { + if (status_code == RESTFUL_RES_OK || status_code == RESTFUL_RES_SERVERR) { return 0; - } else if (status_code == EVHTP_RES_NOTIMPL) { + } else if (status_code == RESTFUL_RES_NOTIMPL) { ERROR("Not implement interface"); return -1; - } else if (status_code == EVHTP_RES_NOTFOUND) { + } else if (status_code == RESTFUL_RES_NOTFOUND) { ERROR("Can not connect to service"); return -1; - } else if (status_code == EVHTP_RES_ERROR) { + } else if (status_code == RESTFUL_RES_ERROR) { ERROR("Server internal error"); return -1; } diff --git a/src/http/rest_common.h b/src/http/rest_common.h index 7a369c02ddbcedcd0b0fb9f9d7fe2266cf0ca99c..8cefc8529294483319d3fe532726dfe7655e2cbc 100644 --- a/src/http/rest_common.h +++ b/src/http/rest_common.h @@ -15,8 +15,6 @@ #ifndef __REST_COMMON_H #define __REST_COMMON_H -#include - #include "http/buffer.h" #include "http/http.h" #include "parser.h" @@ -25,6 +23,13 @@ extern "C" { #endif +// Response status from restful server +#define RESTFUL_RES_ERROR 0 +#define RESTFUL_RES_OK 200 +#define RESTFUL_RES_NOTFOUND 404 +#define RESTFUL_RES_SERVERR 500 +#define RESTFUL_RES_NOTIMPL 501 + typedef int (*unpack_response_func_t)(const struct parsed_http_message *message, void *arg); int get_response(Buffer *output, unpack_response_func_t unpack_func, void *arg); diff --git a/src/image/oci/isula_rootfs_umount.c b/src/image/oci/isula_rootfs_umount.c index cca8e632b5b44085b11c54368ad266ece8e0b623..d468a5866864be1120f72ffccfe8f67177167678 100644 --- a/src/image/oci/isula_rootfs_umount.c +++ b/src/image/oci/isula_rootfs_umount.c @@ -41,6 +41,21 @@ static int generate_isula_umount_request(const char *name_id, bool force, struct return 0; } +static bool is_container_nonexist_error(const struct isula_umount_response *iresp) +{ +#define CONTAINER_NOT_KNOWN_ERR "container not known" + if (iresp == NULL || iresp->errmsg == NULL) { + return false; + } + + if (strstr(iresp->errmsg, CONTAINER_NOT_KNOWN_ERR) != NULL) { + DEBUG("Container may already removed"); + return true; + } + + return false; +} + int isula_rootfs_umount(const char *name_id, bool force) { int ret = 0; @@ -81,7 +96,7 @@ int isula_rootfs_umount(const char *name_id, bool force) INFO("Send umount rootfs GRPC request"); nret = im_ops->umount(ireq, iresp, &conf); - if (nret != 0) { + if (nret != 0 && !is_container_nonexist_error(iresp)) { ERROR("Remove rootfs %s failed: %s", name_id, iresp != NULL ? iresp->errmsg : "null"); ret = -1; } diff --git a/src/image/oci/oci_config_merge.c b/src/image/oci/oci_config_merge.c index f925fee1cf9b2657c8cbaf6bd01ee15858664c97..6005a656fbc91b6daaefae3bba9dc076266e575a 100644 --- a/src/image/oci/oci_config_merge.c +++ b/src/image/oci/oci_config_merge.c @@ -97,8 +97,6 @@ static int oci_image_merge_env(const oci_image_spec_config *config, container_co } out: return ret; - - return 0; } static int do_duplicate_commands(const oci_image_spec_config *config, container_config *container_spec) diff --git a/src/json/schema/schema/container/config-v2.json b/src/json/schema/schema/container/config-v2.json index 173886b884844554b03f777bc97ba80ce8911cbf..623e4e54e9258a87ef6a9ca074ae30274fd8a66a 100644 --- a/src/json/schema/schema/container/config-v2.json +++ b/src/json/schema/schema/container/config-v2.json @@ -40,6 +40,9 @@ "ResolvConfPath": { "type": "string" }, + "ShmPath": { + "type": "string" + }, "LogPath": { "type": "string" }, diff --git a/src/json/schema/schema/container/get-runtime-response.json b/src/json/schema/schema/container/get-runtime-response.json new file mode 100644 index 0000000000000000000000000000000000000000..f7676843165936d129eb300f01ae44370916363a --- /dev/null +++ b/src/json/schema/schema/container/get-runtime-response.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "runtime": { + "type": "string" + }, + "cc": { + "type": "uint32" + }, + "errmsg": { + "type": "string" + } + } +} diff --git a/src/json/schema/schema/defs.json b/src/json/schema/schema/defs.json index be56b15c941bb37363e4d5268e3dc71edee39b41..c493a8a11ea1bc2b18356bb7ef029636f9d3600a 100644 --- a/src/json/schema/schema/defs.json +++ b/src/json/schema/schema/defs.json @@ -232,6 +232,25 @@ } } }, + "mapStringObjectRuntimes": { + "type": "object", + "patternProperties": { + ".{1,}": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "runtime-args": { + "type":"array", + "items": { + "type":"string" + } + } + } + } + } + }, "ociVersion": { "description": "The version of Open Container Runtime Specification that the document complies with", "type": "string" diff --git a/src/json/schema/schema/isulad-daemon-configs.json b/src/json/schema/schema/isulad-daemon-configs.json index eb289c0412c8e8e1a4c472d6d13b5e88c6e49c3f..93fe33af091e931ebbbe15c7c5b5d00ee8a49fce 100644 --- a/src/json/schema/schema/isulad-daemon-configs.json +++ b/src/json/schema/schema/isulad-daemon-configs.json @@ -5,6 +5,9 @@ "hosts": { "type": "ArrayOfStrings" }, + "default-runtime": { + "type": "string" + }, "group": { "type": "string" }, @@ -144,6 +147,9 @@ } } } + }, + "runtimes": { + "$ref": "defs.json#/definitions/mapStringObjectRuntimes" } } } diff --git a/src/json/schema/schema/shim/client/process-state.json b/src/json/schema/schema/shim/client/process-state.json new file mode 100644 index 0000000000000000000000000000000000000000..8ee74392aba1b0dd0158df9b98f6bdeaac36bfe4 --- /dev/null +++ b/src/json/schema/schema/shim/client/process-state.json @@ -0,0 +1,187 @@ +{ + "description": "process state info", + "type": "object", + "required": [ + "cwd", + "args" + ], + "properties": { + "args": { + "id": "https://opencontainers.org/schema/bundle/process/args", + "$ref": "../../defs.json#/definitions/ArrayOfStrings" + }, + "consoleSize": { + "id": "https://opencontainers.org/schema/bundle/process/consoleSize", + "type": "object", + "required": [ + "height", + "width" + ], + "properties": { + "height": { + "id": "https://opencontainers.org/schema/bundle/process/consoleSize/height", + "$ref": "../../defs.json#/definitions/uint64" + }, + "width": { + "id": "https://opencontainers.org/schema/bundle/process/consoleSize/width", + "$ref": "../../defs.json#/definitions/uint64" + } + } + }, + "cwd": { + "id": "https://opencontainers.org/schema/bundle/process/cwd", + "type": "string" + }, + "env": { + "id": "https://opencontainers.org/schema/bundle/process/env", + "$ref": "../../defs.json#/definitions/Env" + }, + "terminal": { + "id": "https://opencontainers.org/schema/bundle/process/terminal", + "type": "boolean" + }, + "user": { + "id": "https://opencontainers.org/schema/bundle/process/user", + "type": "object", + "properties": { + "uid": { + "id": "https://opencontainers.org/schema/bundle/process/user/uid", + "$ref": "../../defs.json#/definitions/UID" + }, + "gid": { + "id": "https://opencontainers.org/schema/bundle/process/user/gid", + "$ref": "../../defs.json#/definitions/GID" + }, + "additionalGids": { + "id": "https://opencontainers.org/schema/bundle/process/user/additionalGids", + "$ref": "../../defs.json#/definitions/ArrayOfGIDs" + }, + "username": { + "id": "https://opencontainers.org/schema/bundle/process/user/username", + "type": "string" + } + } + }, + "capabilities": { + "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities", + "type": "object", + "properties": { + "bounding": { + "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/bounding", + "type": "array", + "items": { + "type": "string" + } + }, + "permitted": { + "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/permitted", + "type": "array", + "items": { + "type": "string" + } + }, + "effective": { + "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/effective", + "type": "array", + "items": { + "type": "string" + } + }, + "inheritable": { + "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/inheritable", + "type": "array", + "items": { + "type": "string" + } + }, + "ambient": { + "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/ambient", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "apparmorProfile": { + "id": "https://opencontainers.org/schema/bundle/process/linux/apparmorProfile", + "type": "string" + }, + "oomScoreAdj": { + "id": "https://opencontainers.org/schema/bundle/process/linux/oomScoreAdj", + "type": "integer" + }, + "selinuxLabel": { + "id": "https://opencontainers.org/schema/bundle/process/linux/selinuxLabel", + "type": "string" + }, + "noNewPrivileges": { + "id": "https://opencontainers.org/schema/bundle/process/linux/noNewPrivileges", + "type": "boolean" + }, + "rlimits": { + "id": "https://opencontainers.org/schema/bundle/linux/rlimits", + "type": "array", + "items": { + "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0", + "type": "object", + "required": [ + "type", + "soft", + "hard" + ], + "properties": { + "hard": { + "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0/hard", + "$ref": "../../defs.json#/definitions/uint64" + }, + "soft": { + "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0/soft", + "$ref": "../../defs.json#/definitions/uint64" + }, + "type": { + "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0/type", + "type": "string", + "pattern": "^RLIMIT_[A-Z]+$" + } + } + } + }, + "exit_fifo": { + "type": "string" + }, + "control_fifo": { + "type": "string" + }, + "exec": { + "type": "boolean" + }, + "isuladStdin": { + "type": "string" + }, + "isuladStdout": { + "type": "string" + }, + "isuladStderr": { + "type": "string" + }, + "runtimeArgs": { + "type": "array", + "items": { + "type": "string" + } + }, + "noPivotRoot": { + "tyoe": "boolean" + }, + "checkpoint": { + "type": "string" + }, + "rootUID": { + "type": "integer" + }, + "rootGID": { + "type": "integer" + } + } +} diff --git a/src/namespace.c b/src/namespace.c index 9f13b633b6715dbebea1f36966426877d8576fe1..3374ae3802757dcaa1d68cbb121b4637e6fe7482 100644 --- a/src/namespace.c +++ b/src/namespace.c @@ -21,7 +21,7 @@ #include "containers_store.h" -static char *connected_container(const char *mode) +char *connected_container(const char *mode) { const char *p = mode != NULL ? (mode + strlen(SHARE_NAMESPACE_PREFIX)) : NULL; diff --git a/src/namespace.h b/src/namespace.h index 7a7dc403083ff1c69818be6ef1e6aa55b820e242..6eb6a397e3daea1ef204f4dff1822c1fc071b1ce 100644 --- a/src/namespace.h +++ b/src/namespace.h @@ -18,9 +18,14 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define SHARE_NAMESPACE_PREFIX "container:" #define SHARE_NAMESPACE_HOST "host" #define SHARE_NAMESPACE_NONE "none" +#define SHARE_NAMESPACE_SHAREABLE "shareable" #define SHARE_NAMESPACE_PID_HOST_PATH "/proc/1/ns/pid" #define SHARE_NAMESPACE_NET_HOST_PATH "/proc/1/ns/net" @@ -68,7 +73,21 @@ static inline bool is_container(const char *mode) return false; } +static inline bool is_shareable(const char *mode) +{ + if (mode != NULL && strcmp(mode, SHARE_NAMESPACE_SHAREABLE) == 0) { + return true; + } + return false; +} + +char *connected_container(const char *mode); + char *get_share_namespace_path(const char *type, const char *src_path); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index 1a46eec08161ed493f9dbc47a08e34fa5457fd97..cdff93892b133f546903fa4cd8d7cec61d6f207a 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -2,15 +2,18 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} runtime_top_srcs) add_subdirectory(lcr) +add_subdirectory(isula) set(local_runtime_srcs ${runtime_top_srcs} ${LCR_SRCS} + ${ISULA_SRCS} ) set(local_runtime_incs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lcr + ${CMAKE_CURRENT_SOURCE_DIR}/isula ) set(RUNTIME_SRCS diff --git a/src/runtime/isula/CMakeLists.txt b/src/runtime/isula/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..021875d5c93a0d9ae0b81a35760a6797082babf4 --- /dev/null +++ b/src/runtime/isula/CMakeLists.txt @@ -0,0 +1,7 @@ +# get current directory sources files +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} local_isula_srcs) + +set(ISULA_SRCS + ${local_isula_srcs} + PARENT_SCOPE + ) diff --git a/src/runtime/isula/isula_rt_ops.c b/src/runtime/isula/isula_rt_ops.c new file mode 100644 index 0000000000000000000000000000000000000000..c5caf3552455e8cca3e2827a59257afb8922a0f2 --- /dev/null +++ b/src/runtime/isula/isula_rt_ops.c @@ -0,0 +1,999 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: jingrui + * Create: 2020-1-20 + * Description: runtime ops + ******************************************************************************/ + +#define _GNU_SOURCE + +#include +#include + +#include +#include "isula_rt_ops.h" +#include "log.h" +#include "error.h" +#include "runtime.h" +#include "engine.h" +#include "constants.h" +#include "shim_client_process_state.h" +#include "oci_runtime_state.h" +#include "isulad_config.h" + +#define SHIM_BINARY "isulad-shim" +#define PID_WAIT_TIME 120 + +static void copy_process(shim_client_process_state *p, defs_process *dp) +{ + p->args = dp->args; + p->args_len = dp->args_len; + p->console_size = (shim_client_process_state_console_size *)dp->console_size; + p->cwd = dp->cwd; + p->env = dp->env; + p->env_len = dp->env_len; + p->terminal = dp->terminal; + p->user = (shim_client_process_state_user *)dp->user; + p->capabilities = (shim_client_process_state_capabilities *)dp->capabilities; + p->apparmor_profile = dp->apparmor_profile; + p->oom_score_adj = dp->oom_score_adj; + p->selinux_label = dp->selinux_label; + p->no_new_privileges = dp->no_new_privileges; + p->rlimits = (shim_client_process_state_rlimits_element **)dp->rlimits; + p->rlimits_len = dp->rlimits_len; +} + +static int file_write_int(const char *fname, int val) +{ + char sint[UINT_LEN] = {0}; + + if (snprintf(sint, sizeof(sint), "%d", val) < 0) { + return -1; + } + + if (util_write_file(fname, sint, strlen(sint)) < 0) { + return -1; + } + + return 0; +} + +/* val will updated only when success. */ +static void file_read_int(const char *fname, int *val) +{ + char *sint = NULL; + int ival = 0; + + if (!util_file_exists(fname)) { + free(sint); + return; + } + + sint = util_read_text_file(fname); + if (sint == NULL) { + return; + } + + if (!util_safe_int(sint, &ival)) { + *val = ival; + } + + free(sint); +} + +static char *get_err_message(const char *workdir, const char *file) +{ + char fname[PATH_MAX] = {0}; + FILE *fp = NULL; + char *pline = NULL; + size_t length = 0; + + if (snprintf(fname, sizeof(fname), "%s/%s", workdir, file) < 0) { + ERROR("failed make full path %s/%s", workdir, file); + return NULL; + } + + fp = util_fopen(fname, "r"); + if (fp == NULL) { + return NULL; + } + + while (getline(&pline, &length, fp) != -1) { + if (pline == NULL) { + return NULL; + } + if (strings_contains_word(pline, "error")) { + return pline; + } + } + + if (pline != NULL) { + free(pline); + } + return NULL; +} + +static void show_shim_runtime_errlog(const char *workdir) +{ + char *msg = NULL; + + msg = get_err_message(workdir, "shim-log.json"); + if (msg != NULL) { + ERROR("shim-log error %s", msg); + isulad_set_error_message("shim-log error %s", msg); + free(msg); + } + msg = get_err_message(workdir, "log.json"); + if (msg != NULL) { + ERROR("runtime-log error %s", msg); + isulad_set_error_message("runtime-log error %s", msg); + free(msg); + } +} + +bool rt_isula_detect(const char *runtime) +{ + if (runtime != NULL && (strcasecmp(runtime, "lcr") != 0)) { + return true; + } + + return false; +} + +static int create_process_json_file(const char *workdir, bool exec, + const char *exit_fifo, const char *control_fifo, + const char *stdin, const char *stdout, const char *stderr, + const char **runtime_args, size_t runtime_args_len, defs_process *process) +{ + shim_client_process_state *p = NULL; + struct parser_context ctx = {OPT_GEN_SIMPLIFY, 0}; + parser_error perr = NULL; + char *data = NULL; + char fname[PATH_MAX] = {0}; + int retcode = 0; + + if (snprintf(fname, sizeof(fname), "%s/process.json", workdir) < 0) { + ERROR("failed make process.json full path"); + return -1; + } + + p = util_common_calloc_s(sizeof(shim_client_process_state)); + p->exec = exec; + p->exit_fifo = (char *)exit_fifo; + p->control_fifo = (char *)control_fifo; + p->isulad_stdin = (char *)stdin; + p->isulad_stdout = (char *)stdout; + p->isulad_stderr = (char *)stderr; + p->runtime_args = (char **)runtime_args; + p->runtime_args_len = runtime_args_len; + copy_process(p, process); + + data = shim_client_process_state_generate_json(p, &ctx, &perr); + if (data == NULL) { + retcode = -1; + ERROR("failed generate json for process.json error=%s", perr); + goto out; + } + + if (util_write_file(fname, data, strlen(data)) != 0) { + retcode = -1; + ERROR("failed write process.json"); + goto out; + } + +out: + UTIL_FREE_AND_SET_NULL(perr); + UTIL_FREE_AND_SET_NULL(p); /* field in p shall free by caller */ + UTIL_FREE_AND_SET_NULL(data); + + return retcode; +} + +static void get_runtime_cmd(const char *runtime, const char **cmd) +{ + struct service_arguments *args = NULL; + defs_map_string_object_runtimes *runtimes = NULL; + size_t i = 0; + + if (isulad_server_conf_rdlock()) { + ERROR("failed to lock server config"); + goto out; + } + + args = conf_get_server_conf(); + if (args == NULL) { + ERROR("failed to get server config"); + goto unlock_out; + } + + if (args->json_confs != NULL) { + runtimes = args->json_confs->runtimes; + } + if (runtimes == NULL) { + goto unlock_out; + } + + for (i = 0; i < runtimes->len; i++) { + if (strcmp(runtime, runtimes->keys[i]) == 0) { + *cmd = runtimes->values[i]->path; + goto unlock_out; + } + } + +unlock_out: + if (isulad_server_conf_unlock()) { + ERROR("failed to unlock server config"); + } +out: + if (strcmp(runtime, "runc") == 0) { + *cmd = "runc"; + return; + } + + if (strcmp(runtime, "kata-runtime") == 0) { + *cmd = "kata-runtime"; + return; + } + if (*cmd == NULL) { + ERROR("missing match runtime config for %s", runtime); + } +} + +static int get_runtime_args(const char *runtime, const char ***args) +{ + int ret = 0; + struct service_arguments *gargs = NULL; + defs_map_string_object_runtimes *runtimes = NULL; + size_t i = 0; + + if (isulad_server_conf_rdlock()) { + ERROR("failed to lock server config"); + goto out; + } + + gargs = conf_get_server_conf(); + if (gargs == NULL) { + ERROR("failed to get server config"); + goto unlock_out; + } + + if (gargs->json_confs != NULL) { + runtimes = gargs->json_confs->runtimes; + } + if (runtimes == NULL) { + goto unlock_out; + } + + for (i = 0; i < runtimes->len; i++) { + if (strcmp(runtime, runtimes->keys[i]) == 0) { + *args = (const char **)runtimes->values[i]->runtime_args; + ret = runtimes->values[i]->runtime_args_len; + goto unlock_out; + } + } +unlock_out: + if (isulad_server_conf_unlock()) { + ERROR("failed to unlock server config"); + } +out: + return ret; +} + +static bool shim_alive(const char *workdir) +{ + int pid = 0; + char fpid[PATH_MAX] = {0}; + int ret = 0; + + if (snprintf(fpid, sizeof(fpid), "%s/shim-pid", workdir) < 0) { + ERROR("failed make shim-pid full path"); + return false; + } + + file_read_int(fpid, &pid); + + if (pid == 0) { + ERROR("failed read shim-pid file %s", fpid); + return false; + } + + ret = kill(pid, 0); + if (ret != 0) { + INFO("kill 0 shim-pid with error: %s", strerror(errno)); + } + return ret == 0; +} + +typedef struct { + const char *workdir; + const char *runtime; + const char *cmd; + const char **args; + size_t args_len; + const char *subcmd; + const char **opts; + size_t opts_len; + const char *id; + char **params; + size_t params_num; +} runtime_exec_info; + +static void runtime_exec_param_dump(const char **params) +{ + char *full = NULL; + int i = 0; + + for (i = 0; i < PARAM_NUM; i++) { + if (*(params + i) == NULL) { + full = util_string_join(" ", params, i); + INFO("runtime call params[%d] %s", i, full); + UTIL_FREE_AND_SET_NULL(full); + return; + } + } +} + +static void runtime_exec_param_init(runtime_exec_info *rei) +{ + const char **params = (const char **)rei->params; + size_t j = 0; + + *params++ = rei->cmd; + + for (j = 0; j < rei->args_len; j++) { + *params++ = *(rei->args + j); + } + + *params++ = rei->subcmd; + for (j = 0; j < rei->opts_len; j++) { + *params++ = *(rei->opts + j); + } + + if (rei->id) { + *params++ = rei->id; + } +} + +static void runtime_exec_info_init(runtime_exec_info *rei, + const char *workdir, const char *runtime, + const char *subcmd, const char **opts, size_t opts_len, const char *id, + char **params, size_t params_num) +{ + rei->workdir = workdir; + rei->runtime = runtime; + rei->args_len = get_runtime_args(runtime, &rei->args); + get_runtime_cmd(runtime, &rei->cmd); + rei->subcmd = subcmd; + rei->opts = opts; + rei->opts_len = opts_len; + rei->id = id; + rei->params = params; + rei->params_num = params_num; + + runtime_exec_param_init(rei); + runtime_exec_param_dump((const char **)rei->params); +} + + +static void runtime_exec_func(void *arg) +{ + runtime_exec_info *rei = (runtime_exec_info *) arg; + + if (rei == NULL) { + dprintf(STDERR_FILENO, "missing runtime exec info"); + _exit(EXIT_FAILURE); + } + + if (chdir(rei->workdir) < 0) { + dprintf(STDERR_FILENO, "chdir %s failed", rei->workdir); + _exit(EXIT_FAILURE); + } + + execvp(rei->cmd, rei->params); + dprintf(STDERR_FILENO, "exec %s %s %s failed", rei->cmd, rei->subcmd, rei->id); + _exit(EXIT_FAILURE); +} + +static int status_string_to_int(const char *status) +{ + if (strcmp(status, "running") == 0) { + return ENGINE_CONTAINER_STATUS_RUNNING; + } + if (strcmp(status, "stopped") == 0) { + return ENGINE_CONTAINER_STATUS_STOPPED; + } + if (strcmp(status, "paused") == 0) { + return ENGINE_CONTAINER_STATUS_PAUSED; + } + return ENGINE_CONTAINER_STATUS_UNKNOWN; +} + +static int runtime_call_status(const char *workdir, const char *runtime, + const char *id, struct engine_container_status_info *ecsi) +{ + char *stdout = NULL; + char *stderr = NULL; + oci_runtime_state *state = NULL; + struct parser_context ctx = {OPT_GEN_SIMPLIFY, 0}; + parser_error perr = NULL; + runtime_exec_info rei = { 0 }; + int ret = 0; + char *params[PARAM_NUM] = {0}; + + runtime_exec_info_init(&rei, workdir, runtime, "state", NULL, 0, id, params, PARAM_NUM); + + if (!util_exec_cmd(runtime_exec_func, &rei, NULL, &stdout, &stderr)) { + ERROR("call runtime status failed: %s", stderr); + ret = -1; + goto out; + } + + if (stdout == NULL) { + ERROR("call runtime status no stdout"); + ret = -1; + goto out; + } + + state = oci_runtime_state_parse_data(stdout, &ctx, &perr); + if (state == NULL) { + ERROR("call runtime status parse json failed"); + ret = -1; + goto out; + } + + ecsi->status = status_string_to_int(state->status); + ecsi->pid = state->pid; + if (state->pid != 0) { + ecsi->has_pid = true; + } + + INFO("container %s status %s pid %d", id, state->status, state->pid); + +out: + free_oci_runtime_state(state); + UTIL_FREE_AND_SET_NULL(stdout); + UTIL_FREE_AND_SET_NULL(stderr); + UTIL_FREE_AND_SET_NULL(perr); + return ret; +} + +static int runtime_call_simple(const char *workdir, const char *runtime, + const char *subcmd, const char **opts, size_t opts_len, const char *id) +{ + runtime_exec_info rei = {0}; + char *stdout = NULL; + char *stderr = NULL; + int ret = 0; + char *params[PARAM_NUM] = {0}; + + runtime_exec_info_init(&rei, workdir, runtime, subcmd, opts, opts_len, id, params, PARAM_NUM); + if (!util_exec_cmd(runtime_exec_func, &rei, NULL, &stdout, &stderr)) { + ERROR("call runtime %s failed stderr %s", subcmd, stderr); + goto out; + } + +out: + UTIL_FREE_AND_SET_NULL(stdout); + UTIL_FREE_AND_SET_NULL(stderr); + return ret; +} + +static int runtime_call_delete_force(const char *workdir, const char *runtime, const char *id) +{ + const char *opts[1] = {"-f"}; + return runtime_call_simple(workdir, runtime, "delete", opts, 1, id); +} + +#define ExitSignalOffset 128 +static int status_to_exit_code(int status) +{ + int exit_code = 0; + + if (WIFEXITED(status)) { + exit_code = WEXITSTATUS(status); + } else { + exit_code = -1; + exit_code = -1; + } + if (WIFSIGNALED(status)) { + int signal; + signal = WTERMSIG(status); + exit_code = ExitSignalOffset + signal; + } + return exit_code; +} + +static int shim_create(bool fg, const char *id, const char *workdir, + const char *bundle, const char *runtime_cmd, + int *exit_code) +{ + pid_t pid = 0; + int exec_fd[2] = { -1, -1 }; + int num = 0; + int ret = 0; + char exec_buff[BUFSIZ + 1] = { 0 }; + char fpid[PATH_MAX] = {0}; + const char *params[PARAM_NUM] = {0}; + int i = 0; + int status = 0; + + params[i++] = SHIM_BINARY; + params[i++] = id; + params[i++] = bundle; + params[i++] = runtime_cmd; + params[i++] = "info"; + params[i++] = "2m0s"; + runtime_exec_param_dump(params); + + if (snprintf(fpid, sizeof(fpid), "%s/shim-pid", workdir) < 0) { + ERROR("failed make shim-pid full path"); + return -1; + } + + if (pipe2(exec_fd, O_CLOEXEC) != 0) { + ERROR("failed to create pipe for shim create"); + return -1; + } + + pid = fork(); + if (pid < 0) { + ERROR("failed fork for shim parent %s", strerror(errno)); + close(exec_fd[0]); + close(exec_fd[1]); + return -1; + } + + if (pid == (pid_t)0) { + if (chdir(workdir) < 0) { + (void)dprintf(exec_fd[1], "%s: failed chdir to %s", id, workdir); + exit(EXIT_FAILURE); + } + + if (fg) { + goto realexec; + } + + pid = fork(); + if (pid < 0) { + (void)dprintf(exec_fd[1], "%s: fork shim-process failed %s", id, strerror(errno)); + _exit(EXIT_FAILURE); + } + if (pid != 0) { + if (file_write_int(fpid, pid) != 0) { + (void)dprintf(exec_fd[1], "%s: write %s with %d failed", id, fpid, pid); + } + _exit(EXIT_SUCCESS); + } + +realexec: + /* real shim process. */ + close(exec_fd[0]); + if (setsid() < 0) { + (void)dprintf(exec_fd[1], "%s: failed setsid for process %d", id, getpid()); + exit(EXIT_FAILURE); + } + + if (util_check_inherited(true, exec_fd[1]) != 0) { + (void)dprintf(exec_fd[1], "close inherited fds failed"); + } + + execvp(SHIM_BINARY, (char * const *)params); + (void)dprintf(exec_fd[1], "exec failed: %s", strerror(errno)); + } + + close(exec_fd[1]); + num = util_read_nointr(exec_fd[0], exec_buff, sizeof(exec_buff)); + close(exec_fd[0]); + if (num > 0) { + ERROR("exec failed: %s", exec_buff); + ret = -1; + goto out; + } + + status = wait_for_pid_status(pid); + if (status < 0) { + ERROR("failed wait shim-parent %d exit %s", pid, strerror(errno)); + ret = -1; + goto out; + } + + if (exit_code != NULL) { + *exit_code = status_to_exit_code(status); + } + +out: + if (ret != 0) { + show_shim_runtime_errlog(workdir); + kill(pid, SIGKILL); /* can kill other process? */ + } + + return ret; +} + + +static int get_container_process_pid(const char *workdir) +{ + char fname[PATH_MAX] = {0}; + int pid = 0; + struct timespec beg = {0}; + struct timespec end = {0}; + + if (snprintf(fname, sizeof(fname), "%s/pid", workdir) < 0) { + ERROR("failed make pid full path"); + return -1; + } + + if (clock_gettime(CLOCK_MONOTONIC, &beg) != 0) { + ERROR("failed get time"); + return -1; + } + + while (1) { + if (clock_gettime(CLOCK_MONOTONIC, &end) != 0) { + ERROR("failed get time"); + return -1; + } + if (end.tv_sec - beg.tv_sec > PID_WAIT_TIME) { + ERROR("wait container process pid timeout %s", workdir); + return -1; + } + file_read_int(fname, &pid); + if (!pid) { + if (shim_alive(workdir)) { + usleep_nointerupt(100000); + continue; + } + ERROR("failed read pid from dead shim %s", workdir); + return -1; + } + return pid; /* success */ + } + return -1; +} + +static void shim_kill_force(const char *workdir) +{ + int pid = 0; + char fpid[PATH_MAX] = {0}; + + if (snprintf(fpid, sizeof(fpid), "%s/shim-pid", workdir) < 0) { + INFO("shim-pid not exist"); + return; + } + + file_read_int(fpid, &pid); + + if (pid == 0) { + goto out; + } + + kill(pid, SIGKILL); + +out: + INFO("kill shim force %s", workdir); +} + +int rt_isula_create(const char *id, const char *runtime, + const rt_create_params_t *params) +{ + oci_runtime_spec *config = params->oci_config_data; + const char *cmd = NULL; + const char **runtime_args = NULL; + size_t runtime_args_len = get_runtime_args(runtime, &runtime_args); + int ret = 0; + char workdir[PATH_MAX] = {0}; + + if (snprintf(workdir, sizeof(workdir), "%s/%s", params->state, id) < 0) { + INFO("make full workdir failed"); + ret = -1; + goto out; + } + + ret = create_process_json_file(workdir, false, params->exit_fifo, NULL, + params->stdin, params->stdout, params->stderr, runtime_args, + runtime_args_len, config->process); + if (ret != 0) { + ERROR("%s: failed create json file", id); + goto out; + } + + get_runtime_cmd(runtime, &cmd); + ret = shim_create(false, id, workdir, params->bundle, cmd, NULL); + if (ret != 0) { + runtime_call_delete_force(workdir, runtime, id); + ERROR("%s: failed create shim process", id); + goto out; + } + +out: + return ret; +} + +int rt_isula_start(const char *id, const char *runtime, + const rt_start_params_t *params, + container_pid_t *pid_info) +{ + char workdir[PATH_MAX] = {0}; + pid_t pid = 0; + int ret = 0; + + if (snprintf(workdir, sizeof(workdir), "%s/%s", params->state, id) < 0) { + ERROR("%s: missing shim workdir", id); + return -1; + } + + pid = get_container_process_pid(workdir); + if (pid < 0) { + ret = -1; + ERROR("%s: failed wait init pid", id); + goto out; + } + + if (container_read_proc(pid, pid_info) != 0) { + ret = -1; + ERROR("%s: failed read pid info", id); + goto out; + } + + if (runtime_call_simple(workdir, runtime, "start", NULL, 0, id) != 0) { + ERROR("call runtime start id failed"); + ret = -1; + goto out; + } + +out: + if (ret != 0) { + show_shim_runtime_errlog(workdir); + shim_kill_force(workdir); + } + + return ret; +} + +int rt_isula_restart(const char *name, const char *runtime, + const rt_restart_params_t *params) +{ + ERROR(">>> restart not implemented"); + return RUNTIME_NOT_IMPLEMENT_RESET; +} + +int rt_isula_clean_resource(const char *id, const char *runtime, + const rt_clean_params_t *params) +{ + char workdir[PATH_MAX] = {0}; + + if (snprintf(workdir, sizeof(workdir), "%s/%s", params->statepath, id) < 0) { + ERROR("failed get shim workdir"); + return -1; + } + + if (shim_alive(workdir)) { + shim_kill_force(workdir); + } + + (void)runtime_call_delete_force(workdir, runtime, id); + + if (util_recursive_rmdir(workdir, 0) != 0) { + ERROR("failed rmdir -r shim workdir"); + return -1; + } + + INFO("rmdir -r %s done", workdir); + return 0; +} + +int rt_isula_rm(const char *id, const char *runtime, const rt_rm_params_t *params) +{ + char libdir[PATH_MAX] = {0}; + + if (snprintf(libdir, sizeof(libdir), "%s/%s", params->rootpath, id) < 0) { + ERROR("failed get shim workdir"); + return -1; + } + + if (util_recursive_rmdir(libdir, 0) != 0) { + ERROR("failed rmdir -r shim workdir"); + return -1; + } + + INFO("rmdir -r %s done", libdir); + return 0; +} + +static char *try_generate_exec_id() +{ + char *id = NULL; + + id = util_common_calloc_s(sizeof(char) * (CONTAINER_EXEC_ID_MAX_LEN + 1)); + if (id == NULL) { + ERROR("Out of memory"); + return NULL; + } + + if (util_generate_random_str(id, (size_t)CONTAINER_EXEC_ID_MAX_LEN)) { + ERROR("Generate id failed"); + goto err_out; + } + + return id; + +err_out: + free(id); + return NULL; +} + +static bool fg_exec(const rt_exec_params_t *params) +{ + if (params->console_fifos[0] != NULL || params->console_fifos[1] != NULL || + params->console_fifos[2] != NULL) { + return true; + } + return false; +} + +int rt_isula_exec(const char *id, const char *runtime, + const rt_exec_params_t *params, int *exit_code) +{ + char *exec_id = NULL; + defs_process *process = params->spec; + const char **runtime_args = NULL; + size_t runtime_args_len = get_runtime_args(runtime, &runtime_args); + char workdir[PATH_MAX] = {0}; + const char *cmd = NULL; + int ret = 0; + char bundle[PATH_MAX] = {0}; + int pid = 0; + + ret = snprintf(bundle, sizeof(bundle), "%s/%s", params->rootpath, id); + if (ret < 0) { + ERROR("failed join bundle path for exec"); + goto out; + } + + exec_id = try_generate_exec_id(); + if (exec_id == NULL) { + ERROR("Failed to generate exec id"); + ret = -1; + goto out; + } + + ret = snprintf(workdir, sizeof(workdir), "%s/%s/exec/%s", params->state, id, exec_id); + if (ret < 0) { + ERROR("failed join exec full path"); + goto out; + } + ret = util_mkdir_p(workdir, DEFAULT_SECURE_DIRECTORY_MODE); + if (ret < 0) { + ERROR("failed mkdir exec workdir %s", workdir); + goto out; + } + + ret = create_process_json_file(workdir, true, NULL, NULL, + params->console_fifos[0], params->console_fifos[1], params->console_fifos[2], + runtime_args, runtime_args_len, process); + if (ret != 0) { + ERROR("%s: failed create exec json file"); + goto out; + } + + get_runtime_cmd(runtime, &cmd); + ret = shim_create(fg_exec(params), id, workdir, bundle, cmd, exit_code); + if (ret != 0) { + ERROR("%s: failed create shim process for exec %s", id, exec_id); + goto out; + } + + pid = get_container_process_pid(workdir); + if (pid < 0) { + ERROR("%s: failed get exec process id", workdir); + ret = -1; + goto out; + } + +out: + UTIL_FREE_AND_SET_NULL(exec_id); + if (ret != 0) { + show_shim_runtime_errlog(workdir); + } else { + if (util_recursive_rmdir(workdir, 0)) { + ERROR("rmdir %s failed", workdir); + } + } + return ret; +} + +int rt_isula_status(const char *id, const char *runtime, + const rt_status_params_t *params, + struct engine_container_status_info *status) +{ + char workdir[PATH_MAX] = {0}; + int ret = 0; + + ret = snprintf(workdir, sizeof(workdir), "%s/%s", params->state, id); + if (ret < 0) { + ERROR("failed join full workdir %s/%s", params->rootpath, id); + goto out; + } + + if (!shim_alive(workdir)) { + ERROR("shim dead %s", workdir); + ret = -1; + goto out; + } + + ret = runtime_call_status(workdir, runtime, id, status); + +out: + return ret; +} + +int rt_isula_attach(const char *id, const char *runtime, + const rt_attach_params_t *params) +{ + ERROR("rt_isula_attach not impl"); + return 0; +} + +int rt_isula_update(const char *id, const char *runtime, const rt_update_params_t *params) +{ + ERROR("rt_isula_update not impl"); + return 0; +} + +int rt_isula_pause(const char *id, const char *runtime, const rt_pause_params_t *params) +{ + char workdir[PATH_MAX] = {0}; + + if (snprintf(workdir, sizeof(workdir), "%s/%s", params->state, id) < 0) { + ERROR("failed join workdir %s/%s", params->state, id); + return -1; + } + + return runtime_call_simple(workdir, runtime, "pause", NULL, 0, id); +} + +int rt_isula_resume(const char *id, const char *runtime, const rt_resume_params_t *params) +{ + char workdir[PATH_MAX] = {0}; + + if (snprintf(workdir, sizeof(workdir), "%s/%s", params->state, id) < 0) { + ERROR("failed join workdir %s/%s", params->state, id); + return -1; + } + + return runtime_call_simple(workdir, runtime, "resume", NULL, 0, id); +} + +int rt_isula_listpids(const char *name, const char *runtime, const rt_listpids_params_t *params, rt_listpids_out_t *out) +{ + ERROR("rt_isula_listpids not impl"); + return 0; +} + +int rt_isula_resources_stats(const char *name, const char *runtime, + const rt_stats_params_t *params, + struct engine_container_resources_stats_info *rs_stats) +{ + ERROR("rt_isula_resources_stats not impl"); + return 0; +} + +int rt_isula_resize(const char *id, const char *runtime, const rt_resize_params_t *params) +{ + ERROR("rt_isula_resize not impl"); + return 0; +} + +int rt_isula_exec_resize(const char *id, const char *runtime, const rt_exec_resize_params_t *params) +{ + ERROR("rt_isula_exec_resize not impl"); + return 0; +} diff --git a/src/runtime/isula/isula_rt_ops.h b/src/runtime/isula/isula_rt_ops.h new file mode 100644 index 0000000000000000000000000000000000000000..5f46c04cf5b705ab77a4e6139dca434137ef5f8f --- /dev/null +++ b/src/runtime/isula/isula_rt_ops.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: jingrui + * Create: 2020-1-20 + * Description: runtime ops + ******************************************************************************/ + +#ifndef ISULA_RT_OPS_H +#define ISULA_RT_OPS_H /* ISULA_RT_OPS_H */ + +#include "runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool rt_isula_detect(const char *runtime); +int rt_isula_create(const char *name, const char *runtime, const rt_create_params_t *params); +int rt_isula_start(const char *name, const char *runtime, const rt_start_params_t *params, container_pid_t *pid_info); +int rt_isula_restart(const char *name, const char *runtime, const rt_restart_params_t *params); +int rt_isula_clean_resource(const char *name, const char *runtime, const rt_clean_params_t *params); +int rt_isula_rm(const char *name, const char *runtime, const rt_rm_params_t *params); +int rt_isula_exec(const char *id, const char *runtime, const rt_exec_params_t *params, int *exit_code); + + +int rt_isula_status(const char *name, const char *runtime, const rt_status_params_t *params, + struct engine_container_status_info *status); +int rt_isula_attach(const char *id, const char *runtime, const rt_attach_params_t *params); +int rt_isula_update(const char *id, const char *runtime, const rt_update_params_t *params); +int rt_isula_pause(const char *id, const char *runtime, const rt_pause_params_t *params); +int rt_isula_resume(const char *id, const char *runtime, const rt_resume_params_t *params); +int rt_isula_listpids(const char *name, const char *runtime, const rt_listpids_params_t *params, + rt_listpids_out_t *out); +int rt_isula_resources_stats(const char *name, const char *runtime, const rt_stats_params_t *params, + struct engine_container_resources_stats_info *rs_stats); +int rt_isula_resize(const char *id, const char *runtime, const rt_resize_params_t *params); +int rt_isula_exec_resize(const char *id, const char *runtime, const rt_exec_resize_params_t *params); + + +#ifdef __cplusplus +} +#endif + +#endif /* ISULA_RT_OPS_H */ diff --git a/src/runtime/lcr/lcr_rt_ops.c b/src/runtime/lcr/lcr_rt_ops.c index 8f17e2babfd6549c16279122967142a75105c0da..5b31974d0e9b6b9bf000b6b26d084b3a2b7a5fb2 100644 --- a/src/runtime/lcr/lcr_rt_ops.c +++ b/src/runtime/lcr/lcr_rt_ops.c @@ -20,7 +20,6 @@ #include "lcr_rt_ops.h" #include "log.h" #include "engine.h" -#include "callback.h" #include "error.h" #include "isulad_config.h" #include "runtime.h" @@ -58,7 +57,9 @@ int rt_lcr_create(const char *name, const char *runtime, const rt_create_params_ if (!engine_ops->engine_create_op(name, runtime_root, params->oci_config_data)) { ERROR("Failed to create container"); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Create container error: %s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); @@ -67,7 +68,7 @@ int rt_lcr_create(const char *name, const char *runtime, const rt_create_params_ } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } free(runtime_root); @@ -130,7 +131,9 @@ int rt_lcr_start(const char *name, const char *runtime, const rt_start_params_t if (!engine_ops->engine_start_op(&request)) { const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Start container error: %s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); @@ -146,7 +149,7 @@ int rt_lcr_start(const char *name, const char *runtime, const rt_start_params_t goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -171,7 +174,9 @@ int rt_lcr_clean_resource(const char *name, const char *runtime, const rt_clean_ if (!engine_ops->engine_clean_op(name, params->rootpath, params->logpath, params->loglevel, params->pid)) { const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_try_set_error_message("Clean resource container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); @@ -180,7 +185,7 @@ int rt_lcr_clean_resource(const char *name, const char *runtime, const rt_clean_ } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -223,8 +228,11 @@ int rt_lcr_rm(const char *name, const char *runtime, const rt_rm_params_t *param } if (!engine_ops->engine_delete_op(name, params->rootpath)) { + const char *tmpmsg = NULL; ret = -1; - const char *tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Runtime delete container error: %s", (tmpmsg != NULL && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); ERROR("Runtime delete container error: %s", @@ -241,7 +249,7 @@ int rt_lcr_rm(const char *name, const char *runtime, const rt_rm_params_t *param } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -263,13 +271,12 @@ int rt_lcr_status(const char *name, const char *runtime, const rt_status_params_ nret = engine_ops->engine_get_container_status_op(name, params->rootpath, status); if (nret != 0) { - engine_ops->engine_clear_errmsg_op(); ret = -1; goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -291,13 +298,12 @@ int rt_lcr_resources_stats(const char *name, const char *runtime, const rt_stats nret = engine_ops->engine_get_container_resources_stats_op(name, params->rootpath, rs_stats); if (nret != 0) { - engine_ops->engine_clear_errmsg_op(); ret = -1; goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -359,14 +365,16 @@ int rt_lcr_exec(const char *id, const char *runtime, const rt_exec_params_t *par request.lcrpath = params->rootpath; request.logpath = params->logpath; request.loglevel = params->loglevel; - request.args = (const char **)params->spec->args; - request.args_len = params->spec->args_len; - request.env = (const char **)params->spec->env; - request.env_len = params->spec->env_len; + if (params->spec != NULL) { + request.args = (const char **)params->spec->args; + request.args_len = params->spec->args_len; + request.env = (const char **)params->spec->env; + request.env_len = params->spec->env_len; + } request.console_fifos = params->console_fifos; request.timeout = params->timeout; request.suffix = params->suffix; - if (params->spec->user != NULL) { + if (params->spec != NULL && params->spec->user != NULL) { if (generate_user_string_by_uid_gid(params->spec->user, &user) != 0) { ret = -1; goto out; @@ -376,7 +384,9 @@ int rt_lcr_exec(const char *id, const char *runtime, const rt_exec_params_t *par if (!engine_ops->engine_exec_op(&request, exit_code)) { const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Exec container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); util_contain_errmsg(g_isulad_errmsg, exit_code); @@ -385,7 +395,7 @@ int rt_lcr_exec(const char *id, const char *runtime, const rt_exec_params_t *par } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } free(user); @@ -407,14 +417,16 @@ int rt_lcr_pause(const char *name, const char *runtime, const rt_pause_params_t if (!engine_ops->engine_pause_op(name, params->rootpath)) { DEBUG("Pause container %s failed", name); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Pause container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); ret = -1; goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -435,7 +447,9 @@ int rt_lcr_resume(const char *name, const char *runtime, const rt_resume_params_ if (!engine_ops->engine_resume_op(name, params->rootpath)) { DEBUG("Resume container %s failed", name); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Resume container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); @@ -443,7 +457,7 @@ int rt_lcr_resume(const char *name, const char *runtime, const rt_resume_params_ goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -465,14 +479,16 @@ int rt_lcr_attach(const char *name, const char *runtime, const rt_attach_params_ (char *)params->stderr)) { ERROR("attach failed"); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Attach container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); ret = -1; goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -514,14 +530,16 @@ int rt_lcr_update(const char *id, const char *runtime, const rt_update_params_t if (!engine_ops->engine_update_op(id, params->rootpath, &cr)) { DEBUG("Update container %s failed", id); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Cannot update container %s: %s", id, (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); ret = -1; goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -532,24 +550,32 @@ int rt_lcr_listpids(const char *name, const char *runtime, const rt_listpids_par int ret = 0; struct engine_operation *engine_ops = NULL; + if (out == NULL) { + ERROR("Invalid arguments"); + ret = -1; + goto out; + } + engine_ops = engines_get_handler(runtime); if (engine_ops == NULL || engine_ops->engine_get_container_pids_op == NULL) { - DEBUG("Failed to get engine top operations"); + ERROR("Failed to get engine top operations"); ret = -1; goto out; } if (!engine_ops->engine_get_container_pids_op(name, params->rootpath, &(out->pids), &(out->pids_len))) { - DEBUG("Top container %s failed", name); + ERROR("Top container %s failed", name); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Runtime top container error: %s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); ret = -1; goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -570,7 +596,9 @@ int rt_lcr_resize(const char *id, const char *runtime, const rt_resize_params_t if (!engine_ops->engine_resize_op(id, params->rootpath, params->height, params->width)) { DEBUG("resize container %s failed", id); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Resize container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); @@ -579,7 +607,7 @@ int rt_lcr_resize(const char *id, const char *runtime, const rt_resize_params_t goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; @@ -600,7 +628,9 @@ int rt_lcr_exec_resize(const char *id, const char *runtime, const rt_exec_resize if (!engine_ops->engine_exec_resize_op(id, params->rootpath, params->suffix, params->height, params->width)) { DEBUG("exec resize container %s failed", id); const char *tmpmsg = NULL; - tmpmsg = engine_ops->engine_get_errmsg_op(); + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } isulad_set_error_message("Resize container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR); @@ -608,7 +638,7 @@ int rt_lcr_exec_resize(const char *id, const char *runtime, const rt_exec_resize goto out; } out: - if (engine_ops != NULL) { + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { engine_ops->engine_clear_errmsg_op(); } return ret; diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index e9906de8fd261dfa60498f7d7d4822f6adec5c38..4f0a5156655a203e81bc2a4ca8e369215549c0be 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -25,6 +25,7 @@ #include "log.h" #include "utils.h" #include "lcr_rt_ops.h" +#include "isula_rt_ops.h" static const struct rt_ops g_lcr_rt_ops = { .detect = rt_lcr_detect, @@ -45,8 +46,28 @@ static const struct rt_ops g_lcr_rt_ops = { .rt_exec_resize = rt_lcr_exec_resize, }; +static const struct rt_ops g_isula_rt_ops = { + .detect = rt_isula_detect, + .rt_create = rt_isula_create, + .rt_start = rt_isula_start, + .rt_restart = rt_isula_restart, + .rt_clean_resource = rt_isula_clean_resource, + .rt_rm = rt_isula_rm, + .rt_status = rt_isula_status, + .rt_exec = rt_isula_exec, + .rt_pause = rt_isula_pause, + .rt_resume = rt_isula_resume, + .rt_attach = rt_isula_attach, + .rt_update = rt_isula_update, + .rt_listpids = rt_isula_listpids, + .rt_resources_stats = rt_isula_resources_stats, + .rt_resize = rt_isula_resize, + .rt_exec_resize = rt_isula_exec_resize, +}; + static const struct rt_ops *g_rt_ops[] = { - &g_lcr_rt_ops + &g_lcr_rt_ops, + &g_isula_rt_ops, }; static const size_t g_rt_nums = sizeof(g_rt_ops) / sizeof(struct rt_ops *); diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 161fb0b0c6967d7a2b30a2c7650480d8be5e0aa0..ed06062a2e1ef3a1e739eaefe63b61b8f81ef430 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -36,11 +36,13 @@ typedef struct _rt_create_params_t { const char *stdin; const char *stdout; const char *stderr; + const char *exit_fifo; } rt_create_params_t; typedef struct _rt_start_params_t { const char *rootpath; + const char *state; bool tty; bool open_stdin; @@ -73,6 +75,7 @@ typedef struct _rt_rm_params_t { typedef struct _rt_status_params_t { const char *rootpath; + const char *state; } rt_status_params_t; typedef struct _rt_stats_params_t { @@ -81,6 +84,7 @@ typedef struct _rt_stats_params_t { typedef struct _rt_exec_params_t { const char *rootpath; + const char *state; const char *logpath; const char *loglevel; const char **console_fifos; @@ -91,10 +95,12 @@ typedef struct _rt_exec_params_t { typedef struct _rt_pause_params_t { const char *rootpath; + const char *state; } rt_pause_params_t; typedef struct _rt_resume_params_t { const char *rootpath; + const char *state; } rt_resume_params_t; typedef struct _rt_attach_params_t { diff --git a/src/services/callback.h b/src/services/callback.h index 4fcdc02a23177d28e92f2359a9e2222673328534..05af4f1e84e1d8cb95fcef8f969f1129aec354fa 100644 --- a/src/services/callback.h +++ b/src/services/callback.h @@ -19,6 +19,7 @@ #include "console.h" #include "container_get_id_request.h" #include "container_get_id_response.h" +#include "container_get_runtime_response.h" #include "container_create_request.h" #include "container_create_response.h" #include "container_start_request.h" @@ -90,6 +91,8 @@ typedef struct { int(*get_id)(const container_get_id_request *request, container_get_id_response **response); + int(*get_runtime)(const char *real_id, container_get_runtime_response **response); + int(*create)(const container_create_request *request, container_create_response **response); int(*start)(const container_start_request *request, container_start_response **response, diff --git a/src/services/cri/cri_container.cc b/src/services/cri/cri_container.cc index ec408c712d005221666014c7fa18c4f245381816..86f5621a2ee6ab7cdea5c3de742880e2d402c537 100644 --- a/src/services/cri/cri_container.cc +++ b/src/services/cri/cri_container.cc @@ -85,6 +85,33 @@ cleanup: return realID; } +std::string CRIRuntimeServiceImpl::GetContainerOrSandboxRuntime(const std::string &realID, Errors &error) +{ + std::string runtime; + if (m_cb == nullptr || m_cb->container.get_runtime == nullptr) { + error.SetError("Unimplemented callback"); + return runtime; + } + container_get_runtime_response *response { nullptr }; + + if (m_cb->container.get_runtime(realID.c_str(), &response) != 0) { + if (response != nullptr && response->errmsg != nullptr) { + error.SetError(response->errmsg); + } else { + error.SetError("Failed to call get id callback"); + } + goto cleanup; + } + + if (response->runtime != nullptr) { + runtime = response->runtime; + } + +cleanup: + free_container_get_runtime_response(response); + return runtime; +} + void CRIRuntimeServiceImpl::GetContainerTimeStamps(container_inspect *inspect, int64_t *createdAt, int64_t *startedAt, int64_t *finishedAt, Errors &err) { @@ -155,6 +182,19 @@ container_config *CRIRuntimeServiceImpl::GenerateCreateContainerCustomConfig( } } + if (append_json_map_string_string(custom_config->annotations, + CRIHelpers::Constants::CONTAINER_TYPE_ANNOTATION_KEY.c_str(), + CRIHelpers::Constants::CONTAINER_TYPE_ANNOTATION_CONTAINER.c_str())) { + error.SetError("Append map string string failed"); + goto cleanup; + } + if (append_json_map_string_string(custom_config->annotations, + CRIHelpers::Constants::SANDBOX_ID_ANNOTATION_KEY.c_str(), + realPodSandboxID.c_str())) { + error.SetError("Append map string string failed"); + goto cleanup; + } + if (append_json_map_string_string(custom_config->labels, CRIHelpers::Constants::SANDBOX_ID_LABEL_KEY.c_str(), realPodSandboxID.c_str())) { error.SetError("Append map string string failed"); @@ -285,7 +325,7 @@ cleanup: container_create_request *CRIRuntimeServiceImpl::GenerateCreateContainerRequest( const std::string &realPodSandboxID, const runtime::v1alpha2::ContainerConfig &containerConfig, - const runtime::v1alpha2::PodSandboxConfig &podSandboxConfig, Errors &error) + const runtime::v1alpha2::PodSandboxConfig &podSandboxConfig, const std::string &podSandboxRuntime, Errors &error) { struct parser_context ctx { OPT_GEN_SIMPLIFY, 0 @@ -301,7 +341,9 @@ container_create_request *CRIRuntimeServiceImpl::GenerateCreateContainerRequest( std::string cname = CRINaming::MakeContainerName(podSandboxConfig, containerConfig); request->id = util_strdup_s(cname.c_str()); - request->runtime = util_strdup_s(CRIHelpers::Constants::DEFAULT_RUNTIME_NAME.c_str()); + if (!podSandboxRuntime.empty()) { + request->runtime = util_strdup_s(podSandboxRuntime.c_str()); + } if (!containerConfig.image().image().empty()) { request->image = util_strdup_s(containerConfig.image().image().c_str()); @@ -357,6 +399,7 @@ std::string CRIRuntimeServiceImpl::CreateContainer(const std::string &podSandbox Errors &error) { std::string response_id { "" }; + std::string podSandboxRuntime { "" }; if (m_cb == nullptr || m_cb->container.create == nullptr) { error.SetError("Unimplemented callback"); @@ -372,7 +415,9 @@ std::string CRIRuntimeServiceImpl::CreateContainer(const std::string &podSandbox goto cleanup; } - request = GenerateCreateContainerRequest(realPodSandboxID, containerConfig, podSandboxConfig, error); + podSandboxRuntime = GetContainerOrSandboxRuntime(realPodSandboxID, error); + + request = GenerateCreateContainerRequest(realPodSandboxID, containerConfig, podSandboxConfig, podSandboxRuntime, error); if (error.NotEmpty()) { error.SetError("Failed to generate create container request"); goto cleanup; @@ -388,6 +433,7 @@ std::string CRIRuntimeServiceImpl::CreateContainer(const std::string &podSandbox } response_id = response->id; + cleanup: free_container_create_request(request); free_container_create_response(response); diff --git a/src/services/cri/cri_helpers.cc b/src/services/cri/cri_helpers.cc index 82b762e08403dc4176c1594d7613986f34a0ac40..92d4054fdf1aff04ae7a6630614b1eb7afc0ef55 100644 --- a/src/services/cri/cri_helpers.cc +++ b/src/services/cri/cri_helpers.cc @@ -45,6 +45,10 @@ const std::string Constants::DOCKER_PULLABLE_IMAGEID_PREFIX { "docker-pullable:/ const std::string Constants::RUNTIME_READY { "RuntimeReady" }; const std::string Constants::NETWORK_READY { "NetworkReady" }; const std::string Constants::POD_CHECKPOINT_KEY { "cri.sandbox.isulad.checkpoint" }; +const std::string Constants::CONTAINER_TYPE_ANNOTATION_KEY { "io.kubernetes.cri.container-type" }; +const std::string Constants::CONTAINER_TYPE_ANNOTATION_CONTAINER { "container" }; +const std::string Constants::CONTAINER_TYPE_ANNOTATION_SANDBOX { "sandbox" }; +const std::string Constants::SANDBOX_ID_ANNOTATION_KEY { "io.kubernetes.cri.sandbox-id" }; const char *InternalLabelKeys[] = { CRIHelpers::Constants::CONTAINER_TYPE_LABEL_KEY.c_str(), diff --git a/src/services/cri/cri_helpers.h b/src/services/cri/cri_helpers.h index a22815ab26dd58ec37e09b5ca9cd3fed25b28303..ce3c0071b50feacb0913e4cdcd15913c4198f9bd 100644 --- a/src/services/cri/cri_helpers.h +++ b/src/services/cri/cri_helpers.h @@ -49,6 +49,10 @@ public: static const std::string NETWORK_READY; static const std::string POD_CHECKPOINT_KEY; static const size_t MAX_CHECKPOINT_KEY_LEN { 250 }; + static const std::string CONTAINER_TYPE_ANNOTATION_KEY; + static const std::string CONTAINER_TYPE_ANNOTATION_CONTAINER; + static const std::string CONTAINER_TYPE_ANNOTATION_SANDBOX; + static const std::string SANDBOX_ID_ANNOTATION_KEY; }; std::string GetDefaultSandboxImage(Errors &err); diff --git a/src/services/cri/cri_runtime_service.h b/src/services/cri/cri_runtime_service.h index b27120069218f1eaef4b577c6ba2659e2fa69464..fdd254b34af39983ef5cd0b761f14d46276e17bf 100644 --- a/src/services/cri/cri_runtime_service.h +++ b/src/services/cri/cri_runtime_service.h @@ -68,6 +68,8 @@ public: std::string GetRealContainerOrSandboxID(const std::string &id, bool isSandbox, Errors &error); + std::string GetContainerOrSandboxRuntime(const std::string &realID, Errors &error); + container_inspect *InspectContainer(const std::string &containerID, Errors &err); std::string GetNetNS(const std::string &podSandboxID, Errors &err); @@ -79,7 +81,8 @@ public: std::unique_ptr Status(Errors &error) override; - std::string RunPodSandbox(const runtime::v1alpha2::PodSandboxConfig &config, Errors &error) override; + std::string RunPodSandbox(const runtime::v1alpha2::PodSandboxConfig &config, const std::string &runtimeHandler, + Errors &error) override; void StopPodSandbox(const std::string &podSandboxID, Errors &error) override; @@ -218,7 +221,8 @@ private: container_create_request * GenerateCreateContainerRequest(const std::string &realPodSandboxID, const runtime::v1alpha2::ContainerConfig &containerConfig, - const runtime::v1alpha2::PodSandboxConfig &podSandboxConfig, Errors &error); + const runtime::v1alpha2::PodSandboxConfig &podSandboxConfig, + const std::string &podSandboxRuntime, Errors &error); host_config *GenerateCreateContainerHostConfig(const runtime::v1alpha2::ContainerConfig &containerConfig, Errors &error); int PackCreateContainerHostConfigSecurityContext(const runtime::v1alpha2::ContainerConfig &containerConfig, @@ -246,13 +250,14 @@ private: Errors &error); void StartSandboxContainer(const std::string &response_id, Errors &error); std::string CreateSandboxContainer(const runtime::v1alpha2::PodSandboxConfig &config, const std::string &image, - std::string &jsonCheckpoint, Errors &error); + std::string &jsonCheckpoint, const std::string &runtimeHandler, Errors &error); container_create_request *GenerateSandboxCreateContainerRequest(const runtime::v1alpha2::PodSandboxConfig &config, - const std::string &image, - std::string &jsonCheckpoint, Errors &error); + const std::string &image, std::string &jsonCheckpoint, + const std::string &runtimeHandler, Errors &error); container_create_request *PackCreateContainerRequest(const runtime::v1alpha2::PodSandboxConfig &config, const std::string &image, host_config *hostconfig, - container_config *container_config, Errors &error); + container_config *container_config, + const std::string &runtimeHandler, Errors &error); int GetRealSandboxIDToStop(const std::string &podSandboxID, bool &hostNetwork, std::string &name, std::string &ns, std::string &realSandboxID, std::map &stdAnnos, Errors &error); int StopAllContainersInSandbox(const std::string &realSandboxID, Errors &error); diff --git a/src/services/cri/cri_sandbox.cc b/src/services/cri/cri_sandbox.cc index 3f138f9ce12b9ee698d0b7b3658073c57c4e80cb..395d413621c58c624c4e2728d366161af7a03054 100644 --- a/src/services/cri/cri_sandbox.cc +++ b/src/services/cri/cri_sandbox.cc @@ -217,6 +217,12 @@ void CRIRuntimeServiceImpl::MakeSandboxIsuladConfig(const runtime::v1alpha2::Pod if (error.NotEmpty()) { return; } + if (append_json_map_string_string(custom_config->annotations, + CRIHelpers::Constants::CONTAINER_TYPE_ANNOTATION_KEY.c_str(), + CRIHelpers::Constants::CONTAINER_TYPE_ANNOTATION_SANDBOX.c_str()) != 0) { + error.SetError("Append container type into annotation failed"); + return; + } if (!c.hostname().empty()) { custom_config->hostname = util_strdup_s(c.hostname().c_str()); @@ -310,7 +316,8 @@ void CRIRuntimeServiceImpl::SetupSandboxFiles(const std::string &resolvPath, container_create_request *CRIRuntimeServiceImpl::PackCreateContainerRequest( const runtime::v1alpha2::PodSandboxConfig &config, const std::string &image, host_config *hostconfig, - container_config *custom_config, Errors &error) + container_config *custom_config, + const std::string &runtimeHandler, Errors &error) { struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 }; parser_error perror = nullptr; @@ -323,7 +330,11 @@ container_create_request *CRIRuntimeServiceImpl::PackCreateContainerRequest( std::string sandboxName = CRINaming::MakeSandboxName(config.metadata()); create_request->id = util_strdup_s(sandboxName.c_str()); - create_request->runtime = util_strdup_s(CRIHelpers::Constants::DEFAULT_RUNTIME_NAME.c_str()); + + if (!runtimeHandler.empty()) { + create_request->runtime = util_strdup_s(runtimeHandler.c_str()); + } + create_request->image = util_strdup_s(image.c_str()); create_request->hostconfig = host_config_generate_json(hostconfig, &ctx, &perror); @@ -348,6 +359,7 @@ error_out: container_create_request *CRIRuntimeServiceImpl::GenerateSandboxCreateContainerRequest( const runtime::v1alpha2::PodSandboxConfig &config, const std::string &image, std::string &jsonCheckpoint, + const std::string &runtimeHandler, Errors &error) { container_create_request *create_request = nullptr; @@ -388,7 +400,7 @@ container_create_request *CRIRuntimeServiceImpl::GenerateSandboxCreateContainerR goto error_out; } - create_request = PackCreateContainerRequest(config, image, hostconfig, custom_config, error); + create_request = PackCreateContainerRequest(config, image, hostconfig, custom_config, runtimeHandler, error); if (create_request == nullptr) { error.SetError("Failed to pack create container request"); goto error_out; @@ -406,11 +418,12 @@ cleanup: std::string CRIRuntimeServiceImpl::CreateSandboxContainer(const runtime::v1alpha2::PodSandboxConfig &config, const std::string &image, std::string &jsonCheckpoint, + const std::string &runtimeHandler, Errors &error) { std::string response_id { "" }; container_create_request *create_request = - GenerateSandboxCreateContainerRequest(config, image, jsonCheckpoint, error); + GenerateSandboxCreateContainerRequest(config, image, jsonCheckpoint, runtimeHandler, error); if (error.NotEmpty()) { return response_id; } @@ -537,7 +550,9 @@ cleanup: free_container_inspect(inspect_data); } -std::string CRIRuntimeServiceImpl::RunPodSandbox(const runtime::v1alpha2::PodSandboxConfig &config, Errors &error) +std::string CRIRuntimeServiceImpl::RunPodSandbox(const runtime::v1alpha2::PodSandboxConfig &config, + const std::string &runtimeHandler, + Errors &error) { std::string response_id; std::string jsonCheckpoint; @@ -555,7 +570,7 @@ std::string CRIRuntimeServiceImpl::RunPodSandbox(const runtime::v1alpha2::PodSan } // Step 2: Create the sandbox container. - response_id = CreateSandboxContainer(config, image, jsonCheckpoint, error); + response_id = CreateSandboxContainer(config, image, jsonCheckpoint, runtimeHandler, error); if (error.NotEmpty()) { goto cleanup; } diff --git a/src/services/cri/cri_services.h b/src/services/cri/cri_services.h index a5a143d2d34ec09e5e355df11b3db53b48a9f5f7..495ec89b53d571f31cd09d5a4281ddb613ec313e 100644 --- a/src/services/cri/cri_services.h +++ b/src/services/cri/cri_services.h @@ -69,7 +69,8 @@ public: class PodSandboxManager { public: - virtual std::string RunPodSandbox(const runtime::v1alpha2::PodSandboxConfig &config, Errors &error) = 0; + virtual std::string RunPodSandbox(const runtime::v1alpha2::PodSandboxConfig &config, const std::string &runtimeHandler, + Errors &error) = 0; virtual void StopPodSandbox(const std::string &podSandboxID, Errors &error) = 0; diff --git a/src/services/execution/execute/execution.c b/src/services/execution/execute/execution.c index 40e4376b2d8e977891b9220d3ba9360bbd9ab963..32125cf5c06122dba26c4a6bd822be4b79666eaf 100644 --- a/src/services/execution/execute/execution.c +++ b/src/services/execution/execute/execution.c @@ -52,6 +52,7 @@ #include "specs_extend.h" #include "utils.h" #include "error.h" +#include "namespace.h" static int filter_by_label(const container_t *cont, const container_get_id_request *request) @@ -114,6 +115,22 @@ static void pack_get_id_response(container_get_id_response *response, const char } } +static void pack_get_runtime_response(container_get_runtime_response *response, const char *runtime, uint32_t cc) +{ + if (response == NULL) { + return; + } + + response->cc = cc; + if (g_isulad_errmsg != NULL) { + response->errmsg = util_strdup_s(g_isulad_errmsg); + DAEMON_CLEAR_ERRMSG(); + } + if (runtime != NULL) { + response->runtime = util_strdup_s(runtime); + } +} + /* * This function gets long id of container by name or short id */ @@ -165,6 +182,49 @@ pack_response: return (cc == ISULAD_SUCCESS) ? 0 : -1; } +static int container_get_runtime_cb(const char *real_id, container_get_runtime_response **response) +{ + char *runtime = NULL; + uint32_t cc = ISULAD_SUCCESS; + container_t *cont = NULL; + + DAEMON_CLEAR_ERRMSG(); + if (real_id == NULL || response == NULL) { + ERROR("Invalid NULL input"); + return -1; + } + + *response = util_common_calloc_s(sizeof(container_get_runtime_response)); + if (*response == NULL) { + ERROR("Out of memory"); + cc = ISULAD_ERR_MEMOUT; + goto pack_response; + } + + if (!util_valid_container_id_or_name(real_id)) { + ERROR("Invalid container name: %s", real_id); + isulad_set_error_message("Invalid container name: %s", real_id); + cc = ISULAD_ERR_EXEC; + goto pack_response; + } + + cont = containers_store_get(real_id); + if (cont == NULL) { + cc = ISULAD_ERR_EXEC; + ERROR("No such container: %s", real_id); + isulad_set_error_message("No such container: %s", real_id); + goto pack_response; + } + + runtime = cont->runtime; + +pack_response: + pack_get_runtime_response(*response, runtime, cc); + + container_unref(cont); + return (cc == ISULAD_SUCCESS) ? 0 : -1; +} + static int send_signal_to_process(pid_t pid, unsigned long long start_time, uint32_t signal) { if (util_process_alive(pid, start_time) == false) { @@ -783,12 +843,25 @@ static int do_start_container(container_t *cont, const char *console_fifos[], bo goto close_exit_fd; } + if (save_oci_config(id, cont->root_path, oci_spec) != 0) { + ERROR("Failed to save container settings"); + ret = -1; + goto close_exit_fd; + } + start_timeout = conf_get_start_timeout(); if (cont->common_config->config != NULL) { tty = cont->common_config->config->tty; open_stdin = cont->common_config->config->open_stdin; } + if (plugin_event_container_pre_start(cont)) { + ERROR("Plugin event pre start failed "); + plugin_event_container_post_stop(cont); /* ignore error */ + ret = -1; + goto close_exit_fd; + } + create_params.bundle = bundle; create_params.state = cont->state_path; create_params.oci_config_data = oci_spec; @@ -796,20 +869,15 @@ static int do_start_container(container_t *cont, const char *console_fifos[], bo create_params.stdin = console_fifos[0]; create_params.stdout = console_fifos[1]; create_params.stderr = console_fifos[2]; + create_params.exit_fifo = exit_fifo; if (runtime_create(id, runtime, &create_params) != 0) { ret = -1; goto close_exit_fd; } - if (plugin_event_container_pre_start(cont)) { - ERROR("Plugin event pre start failed "); - plugin_event_container_post_stop(cont); /* ignore error */ - ret = -1; - goto close_exit_fd; - } - start_params.rootpath = cont->root_path; + start_params.state = cont->state_path; start_params.tty = tty; start_params.open_stdin = open_stdin; start_params.logpath = engine_log_path; @@ -1125,6 +1193,7 @@ static int kill_with_signal(container_t *cont, uint32_t signal) } if (signal == SIGKILL && need_unpause) { params.rootpath = cont->root_path; + params.state = cont->state_path; if (runtime_resume(id, cont->runtime, ¶ms) != 0) { ERROR("Cannot unpause container: %s", id); ret = -1; @@ -1631,6 +1700,23 @@ out: return ret; } +static void umouont_share_shm(container_t *cont) +{ + if (has_mount_for(cont, "/dev/shm")) { + return; + } + if (cont->hostconfig->ipc_mode == NULL || is_shareable(cont->hostconfig->ipc_mode)) { + if (cont->common_config == NULL || cont->common_config->shm_path == NULL) { + return; + } + + INFO("Umounting share shm: %s", cont->common_config->shm_path); + if (umount2(cont->common_config->shm_path, MNT_DETACH)) { + ERROR("Failed to umount the target: %s", cont->common_config->shm_path); + } + } +} + static int do_cleanup_container_resources(container_t *cont) { int ret = 0; @@ -1686,6 +1772,8 @@ static int do_cleanup_container_resources(container_t *cont) goto out; } + umouont_share_shm(cont); + umount_host_channel(cont->hostconfig->host_channel); if (do_runtime_rm_helper(id, runtime, rootpath) != 0) { @@ -1876,6 +1964,7 @@ pack_response: void container_callback_init(service_container_callback_t *cb) { cb->get_id = container_get_id_cb; + cb->get_runtime = container_get_runtime_cb; cb->create = container_create_cb; cb->start = container_start_cb; cb->stop = container_stop_cb; diff --git a/src/services/execution/execute/execution_create.c b/src/services/execution/execute/execution_create.c index 9e12bdd2398584ecfffd8fd78ee6b40c762c91aa..bdf4548ecbc4cbddaf5e202dc246ddef9dbd65cb 100644 --- a/src/services/execution/execute/execution_create.c +++ b/src/services/execution/execute/execution_create.c @@ -44,6 +44,57 @@ #include "error.h" #include "constants.h" +static int runtime_check(const char *name, bool *runtime_res) +{ + int ret = 0; + struct service_arguments *args = NULL; + defs_map_string_object_runtimes *runtimes = NULL; + + if (isulad_server_conf_rdlock()) { + ret = -1; + goto out; + } + + args = conf_get_server_conf(); + if (args == NULL) { + ERROR("Failed to get isulad server config"); + ret = -1; + goto unlock_out; + } + + if (args->json_confs != NULL) { + runtimes = args->json_confs->runtimes; + } + if (runtimes == NULL) { + EVENT("isulad runtimes param is null"); + goto unlock_out; + } + + size_t runtime_nums = runtimes->len; + size_t i; + for (i = 0; i < runtime_nums; i++) { + if (strcmp(name, runtimes->keys[i]) == 0) { + *runtime_res = true; + goto unlock_out; + } + } +unlock_out: + if (isulad_server_conf_unlock()) { + ERROR("Failed to unlock isulad server config"); + ret = -1; + } +out: + if (strcmp(name, "runc") == 0 || strcmp(name, "lcr") == 0) { + *runtime_res = true; + } + + if (strcmp(name, "kata-runtime") == 0) { + *runtime_res = true; + } + + return ret; +} + static int create_request_check(const container_create_request *request) { int ret = 0; @@ -68,20 +119,6 @@ static int create_request_check(const container_create_request *request) goto out; } - if (request->runtime == NULL) { - ERROR("Receive NULL Request runtime"); - ret = -1; - goto out; - } - - if (!util_valid_runtime_name(request->runtime)) { - ERROR("Invalid runtime name:%s", request->runtime); - isulad_set_error_message("Invalid runtime name (%s), only \"lcr\" supported.", - request->runtime); - ret = -1; - goto out; - } - if (request->hostconfig == NULL) { ERROR("Receive NULL Request hostconfig"); ret = -1; @@ -685,12 +722,30 @@ static int get_request_image_info(const container_create_request *request, char static int preparate_runtime_environment(const container_create_request *request, const char *id, char **runtime, char **runtime_root, uint32_t *cc) { - *runtime = get_runtime_from_request(request); + bool runtime_res = false; + + if (request->runtime) { + *runtime = get_runtime_from_request(request); + } else { + *runtime = conf_get_default_runtime(); + } if (*runtime == NULL) { *cc = ISULAD_ERR_INPUT; return -1; } + if (runtime_check(*runtime, &runtime_res) != 0) { + ERROR("Runtimes param check failed"); + return -1; + } + + if (!runtime_res) { + ERROR("Invalid runtime name:%s", *runtime); + isulad_set_error_message("Invalid runtime name (%s).", + *runtime); + return -1; + } + *runtime_root = conf_get_routine_rootdir(*runtime); if (*runtime_root == NULL) { *cc = ISULAD_ERR_EXEC; @@ -771,6 +826,9 @@ int container_create_cb(const container_create_request *request, cc = ISULAD_ERR_INPUT; goto clean_container_root_dir; } + // update runtime of host config + free(host_spec->runtime); + host_spec->runtime = util_strdup_s(runtime); v2_spec = util_common_calloc_s(sizeof(container_config_v2_common_config)); if (v2_spec == NULL) { @@ -816,6 +874,11 @@ int container_create_cb(const container_create_request *request, goto clean_rootfs; } + ret = merge_oci_cgroups_path(id, oci_spec, host_spec); + if (ret < 0) { + goto clean_rootfs; + } + if (merge_config_for_syscontainer(request, host_spec, v2_spec->config, oci_spec) != 0) { ERROR("Failed to merge config for syscontainer"); cc = ISULAD_ERR_EXEC; diff --git a/src/services/execution/execute/execution_extend.c b/src/services/execution/execute/execution_extend.c index b2b3bb2a069097d94e87899afebaa0b74a7b8946..7246d7a43880edea62d745fafbe292c8fa3a9472 100644 --- a/src/services/execution/execute/execution_extend.c +++ b/src/services/execution/execute/execution_extend.c @@ -521,7 +521,7 @@ static int do_resume_container(container_t *cont) } params.rootpath = cont->root_path; - + params.state = cont->state_path; if (runtime_resume(id, cont->runtime, ¶ms)) { ERROR("Failed to resume container:%s", id); ret = -1; @@ -708,7 +708,7 @@ static int pause_container(container_t *cont) } params.rootpath = cont->root_path; - + params.state = cont->state_path; if (runtime_pause(id, cont->runtime, ¶ms)) { ERROR("Failed to pause container:%s", id); ret = -1; @@ -1053,7 +1053,7 @@ static int do_update_resources(const container_update_request *request, containe } backup_oci_spec = load_oci_config(cont->root_path, id); - if (oci_spec == NULL) { + if (backup_oci_spec == NULL) { ERROR("Failed to load oci config"); ret = -1; goto restore_hostspec; diff --git a/src/services/execution/execute/execution_stream.c b/src/services/execution/execute/execution_stream.c index b5004ad758ba23e3e145d2c8903421b07a8ea013..366275f1ad3ad0a3558998766cc2ed51c2b3f51a 100644 --- a/src/services/execution/execute/execution_stream.c +++ b/src/services/execution/execute/execution_stream.c @@ -248,7 +248,115 @@ out: return ret; } -int merge_exec_process_env(defs_process *spec, const container_config *container_spec, const char **env, size_t env_len) +static int do_append_process_exec_env(const char **default_env, defs_process *spec) +{ + int ret = 0; + size_t new_size = 0; + size_t old_size = 0; + size_t i = 0; + size_t j = 0; + char **temp = NULL; + char **default_kv = NULL; + char **custom_kv = NULL; + size_t default_env_len = util_array_len(default_env); + + if (default_env_len == 0) { + return 0; + } + + if (default_env_len > LIST_ENV_SIZE_MAX - spec->env_len) { + ERROR("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX); + isulad_set_error_message("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX); + ret = -1; + goto out; + } + new_size = (spec->env_len + default_env_len) * sizeof(char *); + old_size = spec->env_len * sizeof(char *); + ret = mem_realloc((void **)&temp, new_size, spec->env, old_size); + if (ret != 0) { + ERROR("Failed to realloc memory for envionment variables"); + ret = -1; + goto out; + } + + spec->env = temp; + for (i = 0; i < default_env_len; i++) { + bool found = false; + default_kv = util_string_split(default_env[i], '='); + if (default_kv == NULL) { + continue; + } + + for (j = 0; j < spec->env_len; j++) { + custom_kv = util_string_split(spec->env[i], '='); + if (custom_kv == NULL) { + continue; + } + if (strcmp(default_kv[0], custom_kv[0]) == 0) { + found = true; + } + util_free_array(custom_kv); + custom_kv = NULL; + if (found) { + break; + } + } + + if (!found) { + spec->env[spec->env_len] = util_strdup_s(default_env[i]); + spec->env_len++; + } + util_free_array(default_kv); + default_kv = NULL; + } +out: + return ret; +} + +static int append_necessary_process_env(bool tty, const container_config *container_spec, defs_process *spec) +{ + int ret = 0; + int nret = 0; + char **default_env = NULL; + char host_name_str[MAX_HOST_NAME_LEN + 10] = { 0 }; + + if (util_array_append(&default_env, "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") != 0) { + ERROR("Failed to append default exec env"); + ret = -1; + goto out; + } + + if (container_spec->hostname != NULL) { + nret = snprintf(host_name_str, sizeof(host_name_str), "HOSTNAME=%s", container_spec->hostname); + if (nret < 0 || (size_t)nret >= sizeof(host_name_str)) { + ERROR("hostname is too long"); + ret = -1; + goto out; + } + if (util_array_append(&default_env, host_name_str) != 0) { + ERROR("Failed to append default exec env"); + ret = -1; + goto out; + } + } + + if (tty) { + if (util_array_append(&default_env, "TERM=xterm") != 0) { + ERROR("Failed to append default exec env"); + ret = -1; + goto out; + } + } + + ret = do_append_process_exec_env((const char **)default_env, spec); + +out: + util_free_array(default_env); + return ret; +} + +static int merge_exec_process_env(defs_process *spec, const container_config *container_spec, const char **env, + size_t env_len) { int ret = 0; size_t env_count = 0; @@ -340,6 +448,12 @@ static defs_process *make_exec_process_spec(const container_config *container_sp goto err_out; } + ret = append_necessary_process_env(request->tty, container_spec, spec); + if (ret != 0) { + ERROR("Failed to append necessary for exec process spec"); + goto err_out; + } + ret = dup_array_of_strings((const char **)request->argv, request->argv_len, &(spec->args), &(spec->args_len)); if (ret != 0) { ERROR("Failed to dup envs for exec process spec"); @@ -405,6 +519,7 @@ static int exec_container(container_t *cont, const char *runtime, char * const c params.rootpath = cont->root_path; params.timeout = request->timeout; params.suffix = request->suffix; + params.state = cont->state_path; params.spec = process_spec; if (runtime_exec(cont->common_config->id, runtime, ¶ms, exit_code)) { @@ -1055,7 +1170,7 @@ static int pause_container(const container_t *cont) const char *id = cont->common_config->id; params.rootpath = cont->root_path; - + params.state = cont->state_path; if (runtime_pause(id, cont->runtime, ¶ms)) { ERROR("Failed to pause container:%s", id); ret = -1; @@ -1081,7 +1196,7 @@ static int resume_container(const container_t *cont) const char *id = cont->common_config->id; params.rootpath = cont->root_path; - + params.state = cont->state_path; if (runtime_resume(id, cont->runtime, ¶ms)) { ERROR("Failed to resume container:%s", id); ret = -1; diff --git a/src/services/execution/manager/container_unix.c b/src/services/execution/manager/container_unix.c index 12035f8c39a7a45306f44d4501f3e9c608fac62c..18653620a9769e18e9cb4dd0db2d52d31af3b79a 100644 --- a/src/services/execution/manager/container_unix.c +++ b/src/services/execution/manager/container_unix.c @@ -1054,4 +1054,46 @@ out: return ret; } +/* + * @cont: check container + * @mpath: target mount path + * */ +bool has_mount_for(container_t *cont, const char *mpath) +{ + size_t i = 0; + char *work = NULL; + + if (cont == NULL || mpath == NULL) { + return false; + } + + if (cont->common_config == NULL) { + return false; + } + + if (cont->common_config->mount_points == NULL) { + return false; + } + + for (; i < cont->common_config->mount_points->len; i++) { + if (strcmp(cont->common_config->mount_points->keys[i], mpath) == 0) { + return true; + } + } + + if (cont->hostconfig == NULL) { + return false; + } + for (i = 0; i < cont->hostconfig->binds_len; i++) { + work = strrchr(cont->hostconfig->binds[i], ':'); + if (work == NULL) { + continue; + } + if (strcmp(work, mpath) == 0) { + return true; + } + } + + return false; +} diff --git a/src/services/execution/manager/container_unix.h b/src/services/execution/manager/container_unix.h index 1f7f9509e76697fd0aa772b5507cad9fe0ba9c68..c50937386d35784167f13de7fcbbaae4c76b0d9c 100644 --- a/src/services/execution/manager/container_unix.h +++ b/src/services/execution/manager/container_unix.h @@ -108,6 +108,8 @@ int save_config_v2_json(const char *id, const char *rootpath, const char *v2conf int container_read_proc(uint32_t pid, container_pid_t *pid_info); +bool has_mount_for(container_t *cont, const char *mpath); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/src/services/execution/manager/health_check.c b/src/services/execution/manager/health_check.c index ed05b83f2acb2484724e6114c8b25ffbcfedb4d4..8f006a5f61b8c3416c3608fa81940a97e761bb8e 100644 --- a/src/services/execution/manager/health_check.c +++ b/src/services/execution/manager/health_check.c @@ -559,7 +559,7 @@ void *health_check_run(void *arg) container_req->tty = false; container_req->attach_stdin = false; container_req->attach_stdout = true; - container_req->attach_stderr = true; + container_req->attach_stderr = false; container_req->timeout = timeout_with_default(config->health_check->timeout, DEFAULT_PROBE_TIMEOUT) / Time_Second; container_req->container_id = util_strdup_s(cont->common_config->id); container_req->argv = cmd_slice; diff --git a/src/services/execution/manager/restore.c b/src/services/execution/manager/restore.c index 6f6287cfdf08008e873c446b4a9b3682d4bbf511..cdd1c5b1ab542e4c52d57d00853f2c5533c5bd59 100644 --- a/src/services/execution/manager/restore.c +++ b/src/services/execution/manager/restore.c @@ -309,6 +309,7 @@ static int restore_state(container_t *cont) #endif params.rootpath = cont->root_path; + params.state = cont->state_path; nret = runtime_status(id, runtime, ¶ms, &real_status); if (nret != 0) { ERROR("Failed to restore container %s, make real status to STOPPED. Due to can not load container with status %d", id, diff --git a/src/services/execution/spec/specs.c b/src/services/execution/spec/specs.c index f2fdb20dfb8c7e7d99c2874965f659a94b9aa2f1..d0a67881c7af4dce8b47902e54f96ab9b9bc1391 100644 --- a/src/services/execution/spec/specs.c +++ b/src/services/execution/spec/specs.c @@ -206,7 +206,7 @@ static int make_annotations_cgroup_dir(const container_config *container_spec, c path = default_cgroup_parent; } if (path == NULL) { - goto out; + path = "/isulad"; } if (cleanpath(path, cleaned, sizeof(cleaned)) == NULL) { ERROR("Failed to clean path: %s", path); @@ -1221,6 +1221,11 @@ int merge_conf_cgroup(oci_runtime_spec *oci_spec, const host_config *host_spec) { int ret = 0; + if (oci_spec == NULL || host_spec == NULL) { + ret = -1; + goto out; + } + ret = merge_conf_cgroup_cpu(oci_spec, host_spec); if (ret != 0) { goto out; @@ -1764,6 +1769,44 @@ out: return ret; } +int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, const host_config *host_spec) +{ + int ret = 0; + char *default_cgroup_parent = NULL; + char *path = NULL; + + if (id == NULL || oci_spec == NULL || host_spec == NULL) { + ERROR("Invalid arguments"); + ret = -1; + goto out; + } + + if (make_sure_oci_spec_linux(oci_spec) != 0) { + ERROR("Failed to make oci spec linux"); + ret = -1; + goto out; + } + + default_cgroup_parent = conf_get_isulad_cgroup_parent(); + path = default_cgroup_parent; + if (host_spec->cgroup_parent != NULL) { + path = host_spec->cgroup_parent; + } + + if (path == NULL) { + free(oci_spec->linux->cgroups_path); + oci_spec->linux->cgroups_path = util_path_join("/isulad", id); + return 0; + } + + free(oci_spec->linux->cgroups_path); + oci_spec->linux->cgroups_path = util_path_join(path, id); + +out: + UTIL_FREE_AND_SET_NULL(default_cgroup_parent); + return ret; +} + /* merge the default config with host config and custom config */ int merge_global_config(oci_runtime_spec *oci_spec) { diff --git a/src/services/execution/spec/specs.h b/src/services/execution/spec/specs.h index 1b64574a7de53cec513cac176871e12e49ac3241..b2f596c4aad5d3122c2456fcc95df39ba0cbf48b 100644 --- a/src/services/execution/spec/specs.h +++ b/src/services/execution/spec/specs.h @@ -22,16 +22,24 @@ #include "oci_runtime_hooks.h" #include "oci_runtime_spec.h" +#ifdef __cplusplus +extern "C" { +#endif int merge_all_specs(host_config *host_spec, const char *real_rootfs, container_config_v2_common_config *v2_spec, oci_runtime_spec *oci_spec); - +int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, + const host_config *host_spec); int merge_global_config(oci_runtime_spec *oci_spec); oci_runtime_spec *load_oci_config(const char *rootpath, const char *name); oci_runtime_spec *default_spec(bool system_container); int merge_conf_cgroup(oci_runtime_spec *oci_spec, const host_config *host_spec); int save_oci_config(const char *id, const char *rootpath, const oci_runtime_spec *oci_spec); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/services/execution/spec/specs_mount.c b/src/services/execution/spec/specs_mount.c index df99cb48203d925c334c9a7fffc5b69ab0fc2928..e063405f5195846fb0d032566770a51e9ea07c86 100644 --- a/src/services/execution/spec/specs_mount.c +++ b/src/services/execution/spec/specs_mount.c @@ -16,10 +16,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -41,6 +43,7 @@ #include "parse_common.h" #include "specs_mount.h" #include "specs_extend.h" +#include "containers_store.h" static int get_devices(const char *dir, char ***devices, size_t *device_len, int recursive_depth); @@ -1918,14 +1921,18 @@ out_free: return ret; } -static int change_dev_shm_size(oci_runtime_spec *oci_spec, int64_t shm_size) +static int change_dev_shm_size(oci_runtime_spec *oci_spec, host_config *host_spec) { size_t i = 0; size_t j = 0; char size_opt[MOUNT_PROPERTIES_SIZE] = { 0 }; char *tmp = NULL; - int nret = snprintf(size_opt, sizeof(size_opt), "size=%lld", (long long int)shm_size); + if (is_none(host_spec->ipc_mode)) { + return 0; + } + + int nret = snprintf(size_opt, sizeof(size_opt), "size=%lld", (long long int)host_spec->shm_size); if (nret < 0 || (size_t)nret >= sizeof(size_opt)) { ERROR("Out of memory"); return -1; @@ -2026,6 +2033,238 @@ out: return ret; } +static int chown_for_shm(const char *shm_path, const char *user_remap) +{ + unsigned int host_uid = 0; + unsigned int host_gid = 0; + unsigned int size = 0; + + if (shm_path == NULL) { + return 0; + } + + if (user_remap != NULL) { + if (util_parse_user_remap(user_remap, &host_uid, &host_gid, &size)) { + ERROR("Failed to split string '%s'.", user_remap); + return -1; + } + if (chown(shm_path, host_uid, host_gid) != 0) { + ERROR("Failed to chown host path '%s'.", shm_path); + return -1; + } + } + return 0; +} + +static char *get_prepare_share_shm_path(const char *truntime, const char *cid) +{ +#define SHM_MOUNT_FILE_NAME "/mounts/shm/" + char *c_root_path = NULL; + size_t slen = 0; + char *spath = NULL; + int nret = 0; + + if (truntime == NULL) { + truntime = "lcr"; + } + c_root_path = conf_get_routine_rootdir(truntime); + if (c_root_path == NULL) { + goto err_out; + } + + // c_root_path + "/" + cid + "/mounts/shm" + if (strlen(c_root_path) > (((PATH_MAX - strlen(cid)) - 1) - strlen(SHM_MOUNT_FILE_NAME)) - 1) { + ERROR("Too large path"); + goto err_out; + } + slen = strlen(c_root_path) + 1 + strlen(cid) + strlen(SHM_MOUNT_FILE_NAME) + 1; + spath = util_smart_calloc_s(sizeof(char), slen); + if (spath == NULL) { + ERROR("Out of memory"); + goto err_out; + } + + nret = sprintf(spath, "%s/%s/mounts/shm/", c_root_path, cid); + if (nret < 0) { + ERROR("Sprintf failed"); + goto err_out; + } + + free(c_root_path); + return spath; +err_out: + free(spath); + free(c_root_path); + return NULL; +} + +static bool has_mount_shm(host_config *host_spec, container_config_v2_common_config *v2_spec) +{ + container_t *cont = NULL; + bool ret = false; + + cont = util_common_calloc_s(sizeof(container_t)); + if (cont == NULL) { + ERROR("Out of memory"); + goto out; + } + cont->common_config = v2_spec; + cont->hostconfig = host_spec; + + ret = has_mount_for(cont, "/dev/shm"); + + cont->common_config = NULL; + cont->hostconfig = NULL; +out: + free(cont); + return ret; +} + +static int prepare_share_shm(oci_runtime_spec *oci_spec, host_config *host_spec, + container_config_v2_common_config *v2_spec) +{ +#define MAX_PROPERTY_LEN 64 + char shmproperty[MAX_PROPERTY_LEN] = {0}; + int ret = -1; + int nret = 0; + bool has_mount = false; + char *spath = NULL; + + // has mount for /dev/shm + if (has_mount_shm(host_spec, v2_spec)) { + return 0; + } + + spath = get_prepare_share_shm_path(host_spec->runtime, v2_spec->id); + if (spath == NULL) { + goto out; + } + + nret = util_mkdir_p(spath, 0700); + if (nret != 0) { + ERROR("Build shm dir failed"); + goto out; + } + nret = sprintf(shmproperty, "mode=1777,size=%"PRId64, host_spec->shm_size); + if (nret < 0) { + ERROR("Sprintf failed"); + goto out; + } + + nret = mount("shm", spath, "tmpfs", MS_NOEXEC | MS_NODEV | MS_NOSUID, shmproperty); + if (nret < 0) { + ERROR("Mount %s failed: %s", spath, strerror(errno)); + goto out; + } + has_mount = true; + + nret = chown_for_shm(spath, host_spec->user_remap); + if (nret != 0) { + goto out; + } + + v2_spec->shm_path = spath; + spath = NULL; + ret = 0; +out: + if (ret != 0 && has_mount) { + (void)umount(spath); + } + free(spath); + return ret; +} + +static bool add_shm_mount(oci_runtime_spec *container, const char *shm_path) +{ + char **options = NULL; + size_t options_len = 3; + bool ret = false; + defs_mount *tmp_mounts = NULL; + + if (options_len > SIZE_MAX / sizeof(char *)) { + ERROR("Invalid option size"); + return ret; + } + options = util_common_calloc_s(options_len * sizeof(char *)); + if (options == NULL) { + ERROR("Out of memory"); + goto out_free; + } + options[0] = util_strdup_s("rbind"); + options[1] = util_strdup_s("rprivate"); + // default shm size is 64MB + options[2] = util_strdup_s("size=65536k"); + /* generate mount node */ + tmp_mounts = util_common_calloc_s(sizeof(defs_mount)); + if (tmp_mounts == NULL) { + ERROR("Malloc tmp_mounts memory failed"); + goto out_free; + } + + tmp_mounts->destination = util_strdup_s("/dev/shm"); + tmp_mounts->source = util_strdup_s(shm_path); + tmp_mounts->type = util_strdup_s("bind"); + tmp_mounts->options = options; + tmp_mounts->options_len = options_len; + options = NULL; + + /* expand mount array */ + if (!mounts_expand(container, 1)) { + goto out_free; + } + /* add a new mount node */ + container->mounts[container->mounts_len - 1] = tmp_mounts; + + ret = true; +out_free: + + if (!ret) { + util_free_array(options); + free_defs_mount(tmp_mounts); + } + return ret; +} + +#define SHM_MOUNT_POINT "/dev/shm" +static int setup_ipc_dirs(oci_runtime_spec *oci_spec, host_config *host_spec, + container_config_v2_common_config *v2_spec) +{ + int ret = 0; + container_t *cont = NULL; + char *tmp_cid = NULL; + char *right_path = NULL; + + // setup shareable dirs + if (host_spec->ipc_mode == NULL || is_shareable(host_spec->ipc_mode)) { + return prepare_share_shm(oci_spec, host_spec, v2_spec); + } + + if (is_container(host_spec->ipc_mode)) { + tmp_cid = connected_container(host_spec->ipc_mode); + cont = containers_store_get(tmp_cid); + if (cont == NULL) { + ERROR("Invalid share path: %s", host_spec->ipc_mode); + ret = -1; + goto out; + } + right_path = util_strdup_s(cont->common_config->shm_path); + container_unref(cont); + } else if (is_host(host_spec->ipc_mode)) { + if (!util_file_exists(SHM_MOUNT_POINT)) { + ERROR("/dev/shm is not mounted, but must be for --ipc=host"); + ret = -1; + goto out; + } + right_path = util_strdup_s(SHM_MOUNT_POINT); + } + + free(v2_spec->shm_path); + v2_spec->shm_path = right_path; +out: + free(tmp_cid); + return ret; +} + int merge_conf_mounts(oci_runtime_spec *oci_spec, host_config *host_spec, container_config_v2_common_config *v2_spec) { @@ -2062,12 +2301,24 @@ int merge_conf_mounts(oci_runtime_spec *oci_spec, host_config *host_spec, } } - if (host_spec->shm_size >= 0) { - if (host_spec->shm_size == 0) { - host_spec->shm_size = DEFAULT_SHM_SIZE; - } + if (host_spec->shm_size == 0) { + host_spec->shm_size = DEFAULT_SHM_SIZE; + } + + /* setup ipc dir */ + if (setup_ipc_dirs(oci_spec, host_spec, v2_spec) != 0) { + ret = -1; + goto out; + } + + /* add ipc mount */ + if (v2_spec->shm_path != NULL) { + // check whether duplication + add_shm_mount(oci_spec, v2_spec->shm_path); + } - ret = change_dev_shm_size(oci_spec, host_spec->shm_size); + if (host_spec->shm_size > 0) { + ret = change_dev_shm_size(oci_spec, host_spec); if (ret) { ERROR("Failed to set dev shm size"); goto out; diff --git a/src/services/graphdriver/devmapper/driver_devmapper.c b/src/services/graphdriver/devmapper/driver_devmapper.c index 4bd765cbf440f464c2344813e93fe5e2065c423f..c82bd3f40bf5f0955e077372805a2912306871e6 100644 --- a/src/services/graphdriver/devmapper/driver_devmapper.c +++ b/src/services/graphdriver/devmapper/driver_devmapper.c @@ -37,6 +37,10 @@ int devmapper_parse_options(struct graphdriver *driver, const char **options, si { size_t i = 0; + if (driver == NULL) { + return -1; + } + for (i = 0; options != NULL && i < options_len; i++) { char *dup = NULL; char *p = NULL; @@ -69,8 +73,9 @@ int devmapper_parse_options(struct graphdriver *driver, const char **options, si } else if (strcasecmp(dup, "dm.min_free_space") == 0) { long converted = 0; ret = util_parse_percent_string(val, &converted); - if (ret != 0) { + if (ret != 0 || converted == 100) { isulad_set_error_message("Invalid min free space: '%s': %s", val, strerror(-ret)); + ret = -1; } } else if (strcasecmp(dup, "dm.basesize") == 0) { int64_t converted = 0; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index baea137e47a357f3e77ad6b003c39d1d5c1dfa9b..36aa6d14a4e172bfb3caae906fdea8f4b2bd237a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,9 +1,46 @@ project(iSulad_LLT) +function(gmock_find_library _name) + find_library(${_name} + NAMES ${ARGN} + HINTS + $ENV{GMOCK_ROOT} + ${GMOCK_ROOT} + ) + mark_as_advanced(${_name}) +endfunction() + +find_path(GMOCK_INCLUDE_DIR gmock/gmock.h + HINTS + $ENV{GMOCK_ROOT}/include + ${GMOCK_ROOT}/include +) +mark_as_advanced(GMOCK_INCLUDE_DIR) + +gmock_find_library(GMOCK_LIBRARY gmock) +gmock_find_library(GMOCK_LIBRARY_DEBUG gmockd) +gmock_find_library(GMOCK_MAIN_LIBRARY gmock_main) +gmock_find_library(GMOCK_MAIN_LIBRARY_DEBUG gmock_maind) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMock DEFAULT_MSG GMOCK_LIBRARY GMOCK_INCLUDE_DIR GMOCK_MAIN_LIBRARY) + +if(GMOCK_FOUND) + set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIR}) + set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARIES} ${GMOCK_MAIN_LIBRARIES}) +endif() + # setup testing find_package(Threads REQUIRED) find_package(GTest REQUIRED) +include_directories(${GTEST_INCLUDE_DIR}) +include_directories(${GMOCK_INCLUDE_DIRS}) + add_subdirectory(cutils) add_subdirectory(image) add_subdirectory(path) +add_subdirectory(cmd) +add_subdirectory(runtime) +add_subdirectory(specs) +add_subdirectory(services) diff --git a/test/cmd/CMakeLists.txt b/test/cmd/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..69a7c3d6ad230a6d888d91e06fef206a7dc9f811 --- /dev/null +++ b/test/cmd/CMakeLists.txt @@ -0,0 +1,3 @@ +project(iSulad_LLT) + +add_subdirectory(isula) diff --git a/test/cmd/isula/CMakeLists.txt b/test/cmd/isula/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..56952aebd212069540313a413d001d44bdda5325 --- /dev/null +++ b/test/cmd/isula/CMakeLists.txt @@ -0,0 +1,3 @@ +project(iSulad_LLT) + +add_subdirectory(infomation) diff --git a/test/cmd/isula/infomation/CMakeLists.txt b/test/cmd/isula/infomation/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..80e0fb750909aefe8e66a700d1b4c4c72531551c --- /dev/null +++ b/test/cmd/isula/infomation/CMakeLists.txt @@ -0,0 +1,4 @@ +project(iSulad_LLT) + +add_subdirectory(ps) +add_subdirectory(info) diff --git a/test/cmd/isula/infomation/info/CMakeLists.txt b/test/cmd/isula/infomation/info/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c9ff6b62825fd6d569e6fe10be593a43ed9204e0 --- /dev/null +++ b/test/cmd/isula/infomation/info/CMakeLists.txt @@ -0,0 +1,54 @@ +project(iSulad_LLT) + +SET(EXE info_llt) + +add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/log.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_string.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_convert.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_verify.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_regex.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/path.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/commander.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/console/console.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula/arguments.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/libisulad.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/libisula.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/types_def.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/mainloop.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/container_def.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/error.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/connect/client/isula_connect.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/json/schema/src/read_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula/information/info.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../mocks/grpc_client_mock.cc + ${CMAKE_BINARY_DIR}/json/json_common.c + ${CMAKE_BINARY_DIR}/json/host_config.c + ${CMAKE_BINARY_DIR}/json/container_path_stat.c + ${CMAKE_BINARY_DIR}/json/timestamp.c + info_llt.cc) + +target_include_directories(${EXE} PUBLIC + ${GTEST_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/json + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/sha256 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/connect/client + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/http + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/console + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula/information + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/connect/client/grpc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/json/schema/src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../mocks + ${CMAKE_BINARY_DIR}/json + ${CMAKE_BINARY_DIR}/conf + ) +target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) diff --git a/test/cmd/isula/infomation/info/info_llt.cc b/test/cmd/isula/infomation/info/info_llt.cc new file mode 100644 index 0000000000000000000000000000000000000000..b4a6b18288e3f33070c03d25651f71eb6b1a0c8e --- /dev/null +++ b/test/cmd/isula/infomation/info/info_llt.cc @@ -0,0 +1,158 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wangfengtu + * Create: 2020-02-20 + * Description: provide info mock + ******************************************************************************/ +#include "info.h" +#include +#include +#include +#include +#include +#include "grpc_client_mock.h" +#include "utils.h" + +using ::testing::Args; +using ::testing::ByRef; +using ::testing::SetArgPointee; +using ::testing::DoAll; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::NotNull; +using ::testing::AtLeast; +using ::testing::Invoke; +using ::testing::_; + +using namespace std; + +class InfoUnitTest : public testing::Test { +public: + void SetUp() override + { + GrpcClient_SetMock(&m_grpcClient); + ::testing::Mock::AllowLeak(&m_grpcClient); + } + void TearDown() override + { + GrpcClient_SetMock(nullptr); + } + + NiceMock m_grpcClient; +}; + +int Info(const struct isula_info_request *request, + struct isula_info_response *response, void *arg) +{ + const char *driver_status = "Pool Name: isula-thinpool\n" + "Pool Blocksize: 524.3kB\n" + "Base Device Size: 10.74GB\n" + "Backing Filesystem: ext4\n" + "Data file: \n" + "Metadata file: \n" + "Data Space Used: 536.3MB\n" + "Data Space Total: 30.6GB\n" + "Data Space Available: 30.06GB\n" + "Metadata Space Used: 17.32MB\n" + "Metadata Space Total: 318.8MB\n" + "Metadata Space Available: 301.4MB\n" + "Thin Pool Minimum Free Space: 3.06GB\n" + "Udev Sync Supported: true\n" + "Deferred Removal Enabled: true\n" + "Deferred Deletion Enabled: true\n" + "Deferred Deleted Device Count: 0\n" + "Library Version: 1.02.150 (2018-08-01)\n" + "Semaphore Set Used: 0\n" + "Semaphore Set Total: 32000\n"; + + response->driver_name = util_strdup_s("devicemapper"); + response->driver_status = util_strdup_s(driver_status); + response->version = util_strdup_s("1.1.11"); + response->kversion = util_strdup_s("4.19.36-vhulk1904.3.1.h226.eulerosv2r8.aarch64"); + response->os_type = util_strdup_s("Linux"); + response->architecture = util_strdup_s("aarch64"); + response->nodename = NULL; + response->operating_system = util_strdup_s("EulerOS 2.0 (SP8)"); + response->cgroup_driver = util_strdup_s("cgroupfs"); + response->logging_driver = util_strdup_s("json-file"); + response->huge_page_size = util_strdup_s("2MB"); + response->isulad_root_dir = util_strdup_s("/var/lib/isulad"); + response->http_proxy = NULL; + response->https_proxy = NULL; + response->no_proxy = NULL; + response->errmsg = NULL; + + return 0; +} + +int invokeGrpcOpsInit(isula_connect_ops *ops) +{ + if (ops == nullptr) { + return -1; + } + ops->container.info = &Info; + return 0; +} + +TEST_F(InfoUnitTest, test_cmd_info_main_all) +{ + const char *argv[] = {"isula", "info"}; + const char *argv_failure[] = {"isula", "info", "-k"}; + isula_connect_ops ops; + const char *driver_status = " Pool Name: isula-thinpool\n" + " Pool Blocksize: 524.3kB\n" + " Base Device Size: 10.74GB\n" + " Backing Filesystem: ext4\n" + " Data file: \n" + " Metadata file: \n" + " Data Space Used: 536.3MB\n" + " Data Space Total: 30.6GB\n" + " Data Space Available: 30.06GB\n" + " Metadata Space Used: 17.32MB\n" + " Metadata Space Total: 318.8MB\n" + " Metadata Space Available: 301.4MB\n" + " Thin Pool Minimum Free Space: 3.06GB\n" + " Udev Sync Supported: true\n" + " Deferred Removal Enabled: true\n" + " Deferred Deletion Enabled: true\n" + " Deferred Deleted Device Count: 0\n" + " Library Version: 1.02.150 (2018-08-01)\n" + " Semaphore Set Used: 0\n" + " Semaphore Set Total: 32000\n"; + + ops.container.info = &Info; + EXPECT_CALL(m_grpcClient, GrpcOpsInit(_)) + .WillOnce(Return(-1)) + .WillOnce(DoAll(SetArgPointee<0>(ByRef(ops)), Return(0))); + ASSERT_EQ(connect_client_ops_init(), -1); + ASSERT_EQ(connect_client_ops_init(), 0); + EXPECT_EXIT(cmd_info_main(sizeof(argv) / sizeof(argv[0]), const_cast(argv)), + testing::ExitedWithCode(0), ""); + + testing::internal::CaptureStdout(); + + EXPECT_CALL(m_grpcClient, GrpcOpsInit(_)).WillRepeatedly(Invoke(invokeGrpcOpsInit)); + ASSERT_EQ(connect_client_ops_init(), 0); + EXPECT_EXIT(cmd_info_main(sizeof(argv) / sizeof(argv[0]), const_cast(argv)), + testing::ExitedWithCode(0), ""); + EXPECT_EXIT(cmd_info_main(sizeof(argv_failure) / sizeof(argv_failure[0]), const_cast(argv_failure)), + testing::ExitedWithCode(125), "Unkown flag found"); + + std::string output = testing::internal::GetCapturedStdout(); + if (output.find("devicemapper") == std::string::npos) { + FAIL() << "isula info should contain devicemapper"; + } + if (output.find(driver_status) == std::string::npos) { + FAIL() << "isula info should contain driver status"; + } + + testing::Mock::VerifyAndClearExpectations(&m_grpcClient); +} diff --git a/test/cmd/isula/infomation/ps/CMakeLists.txt b/test/cmd/isula/infomation/ps/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..31af7c5d399181ebf55b6a08b07895fa796bb4a9 --- /dev/null +++ b/test/cmd/isula/infomation/ps/CMakeLists.txt @@ -0,0 +1,54 @@ +project(iSulad_LLT) + +SET(EXE ps_llt) + +add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/log.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_string.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_convert.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_verify.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils/utils_regex.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/path.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/commander.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/console/console.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula/arguments.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/libisulad.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/libisula.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/types_def.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/mainloop.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/container_def.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/error.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/connect/client/isula_connect.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/json/schema/src/read_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula/information/ps.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../mocks/grpc_client_mock.cc + ${CMAKE_BINARY_DIR}/json/json_common.c + ${CMAKE_BINARY_DIR}/json/host_config.c + ${CMAKE_BINARY_DIR}/json/container_path_stat.c + ${CMAKE_BINARY_DIR}/json/timestamp.c + ps_llt.cc) + +target_include_directories(${EXE} PUBLIC + ${GTEST_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/json + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/sha256 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/connect/client + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/http + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/console + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/cmd/isula/information + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/connect/client/grpc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/json/schema/src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../mocks + ${CMAKE_BINARY_DIR}/json + ${CMAKE_BINARY_DIR}/conf + ) +target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} -lgrpc++ -lprotobuf -lcrypto -lyajl -lsecurec -lz) diff --git a/test/cmd/isula/infomation/ps/ps_llt.cc b/test/cmd/isula/infomation/ps/ps_llt.cc new file mode 100644 index 0000000000000000000000000000000000000000..e5e863b9c79ec450e57d7e5cc1bf50489e21e95e --- /dev/null +++ b/test/cmd/isula/infomation/ps/ps_llt.cc @@ -0,0 +1,224 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. + * Description: ps llt + * Author: wujing + * Create: 2019-12-19 + */ +#include "ps.h" +#include +#include +#include +#include +#include +#include "grpc_client_mock.h" +#include "utils.h" + +using ::testing::Args; +using ::testing::ByRef; +using ::testing::SetArgPointee; +using ::testing::DoAll; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::NotNull; +using ::testing::AtLeast; +using ::testing::Invoke; +using ::testing::_; + +using namespace std; + +class ContainerListUnitTest : public testing::Test { +public: + void SetUp() override + { + GrpcClient_SetMock(&m_grpcClient); + ::testing::Mock::AllowLeak(&m_grpcClient); + } + void TearDown() override + { + GrpcClient_SetMock(nullptr); + } + + NiceMock m_grpcClient; +}; + +namespace { +unsigned generate_random_pid() +{ + constexpr int pid_start = 10000; + constexpr int pid_end = 10000; + static default_random_engine e(time(0)); + static uniform_int_distribution u(pid_start, pid_end); + return u(e); +} + +long long generate_random_created() +{ + // unix nanos: 2019-01-01T00:00:00.000000000+08:00 + constexpr int64_t start = 1546272000000000000ll; + // unix nanos: 2019-12-31T00:00:00.000000000+08:00 + constexpr int64_t end = 1577721600000000000ll; + + static default_random_engine e(time(0)); + static uniform_int_distribution u(start, end); + return u(e); +} + +string generate_random_string(int length) +{ + static string chset = "abcdefghijklmnopqrstuvwxyz1234567890"; + string result; + result.resize(length); + + srand(time(NULL)); + for (int i = 0; i < length; i++) { + static default_random_engine e(time(0)); + static uniform_int_distribution u(0, chset.size() - 1); + result[i] = chset[u(e) % chset.length()]; + } + return result; +} + +int set_container_summary(struct isula_list_response *response, int index) +{ + constexpr int id_len = 64; + constexpr int name_len = 8; + + response->container_summary[index] = (struct isula_container_summary_info *)util_common_calloc_s( + sizeof(struct isula_container_summary_info)); + if (response->container_summary[index] == nullptr) { + return -1; + } + response->container_summary[index]->id = util_strdup_s(generate_random_string(id_len).c_str()); + response->container_summary[index]->name = util_strdup_s(generate_random_string(name_len).c_str()); + response->container_summary[index]->runtime = util_strdup_s("lcr"); + response->container_summary[index]->pid = generate_random_pid(); + response->container_summary[index]->status = (Container_Status)CONTAINER_STATUS_RUNNING; + response->container_summary[index]->image = util_strdup_s("busybox:latest"); + response->container_summary[index]->command = util_strdup_s("/bin/sh"); + response->container_summary[index]->startat = util_strdup_s("2019-12-31T23:55:50.867369507+08:00"); + response->container_summary[index]->finishat = util_strdup_s("2020-01-01T23:55:50.867369507+08:00"); + response->container_summary[index]->exit_code = 0; + response->container_summary[index]->restart_count = 0; + response->container_summary[index]->created = generate_random_created(); + response->container_summary[index]->health_state = util_strdup_s("(healthy)"); + response->container_num++; + + return 0; +} +} // namespace + +int ContainerList(const struct isula_list_request *request, + struct isula_list_response *response, void *arg) +{ + (void)request; + (void)arg; + constexpr int container_cnt = 5; + response->cc = 0; + response->server_errono = 0; + response->errmsg = nullptr; + response->container_summary = (struct isula_container_summary_info **)util_common_calloc_s( + sizeof(struct isula_container_summary_info *) * container_cnt); + if (response->container_summary == nullptr) { + return -1; + } + for (size_t i {}; i < container_cnt; ++i) { + if (set_container_summary(response, i)) { + return -1; + } + } + + return 0; +} + +int invokeGrpcOpsInit(isula_connect_ops *ops) +{ + if (ops == nullptr) { + return -1; + } + ops->container.list = &ContainerList; + return 0; +} + +TEST_F(ContainerListUnitTest, test_cmd_list_main_all) +{ + const char *argv[] = {"isula", "ps", "-a"}; + const char *argv_failure[] = {"isula", "ps", "-k"}; + isula_connect_ops ops; + + ops.container.list = &ContainerList; + EXPECT_CALL(m_grpcClient, GrpcOpsInit(_)) + .WillOnce(Return(-1)) + .WillOnce(DoAll(SetArgPointee<0>(ByRef(ops)), Return(0))); + ASSERT_EQ(connect_client_ops_init(), -1); + ASSERT_EQ(connect_client_ops_init(), 0); + EXPECT_EXIT(cmd_list_main(sizeof(argv) / sizeof(argv[0]), const_cast(argv)), + testing::ExitedWithCode(0), ""); + + EXPECT_CALL(m_grpcClient, GrpcOpsInit(_)).WillRepeatedly(Invoke(invokeGrpcOpsInit)); + ASSERT_EQ(connect_client_ops_init(), 0); + EXPECT_EXIT(cmd_list_main(sizeof(argv) / sizeof(argv[0]), const_cast(argv)), + testing::ExitedWithCode(0), ""); + EXPECT_EXIT(cmd_list_main(sizeof(argv_failure) / sizeof(argv_failure[0]), const_cast(argv_failure)), + testing::ExitedWithCode(125), "Unkown flag found"); + testing::Mock::VerifyAndClearExpectations(&m_grpcClient); +} + +TEST_F(ContainerListUnitTest, test_cmd_list_main_format) +{ + const char *argv[] = { + "isula", "ps", "-a", "--format", "\"table XXX{{.ID}}AAA{{.Image}}" + " {{.Status}} {{.Pid}} {{.Command}} {{.Created}} {{.Ports}} {{.ExitCode}} " + "{{.RestartCount}} {{.StartAt}} {{.FinishAt}} {{.Runtime}} \t{{.Names}} \n{{.State}}\"" + }; + const char *argv_failure[] = {"isula", "ps", "--format", "\"{{.ID}} {{.XXX}}"}; + + EXPECT_CALL(m_grpcClient, GrpcOpsInit(_)).WillRepeatedly(Invoke(invokeGrpcOpsInit)); + ASSERT_EQ(connect_client_ops_init(), 0); + EXPECT_EXIT(cmd_list_main(sizeof(argv) / sizeof(argv[0]), const_cast(argv)), + testing::ExitedWithCode(0), ""); + EXPECT_EXIT(cmd_list_main(sizeof(argv_failure) / sizeof(argv_failure[0]), const_cast(argv_failure)), + testing::ExitedWithCode(1), "not support the field"); + testing::Mock::VerifyAndClearExpectations(&m_grpcClient); +} + +TEST_F(ContainerListUnitTest, test_cmd_list_main_notrunc) +{ + const char *argv[] = {"isula", "ps", "-q", "--no-trunc"}; + testing::internal::CaptureStdout(); + + EXPECT_CALL(m_grpcClient, GrpcOpsInit(_)).WillRepeatedly(Invoke(invokeGrpcOpsInit)); + ASSERT_EQ(connect_client_ops_init(), 0); + EXPECT_EXIT(cmd_list_main(sizeof(argv) / sizeof(argv[0]), const_cast(argv)), + testing::ExitedWithCode(0), ""); + std::string output = testing::internal::GetCapturedStdout(); + if (output.find("CONTAINER ID") != std::string::npos) { + ADD_FAILURE() << "the output of command('isula ps -q --no-trunc') should not include table headers"; + } + std::cout << "Gtest Captured Stdout:" << std::endl << output; + testing::Mock::VerifyAndClearExpectations(&m_grpcClient); +} + +TEST_F(ContainerListUnitTest, test_cmd_list_main_debug) +{ + const char *argv[] = {"isula", "ps", "-a", "-D"}; + testing::internal::CaptureStdout(); + + EXPECT_CALL(m_grpcClient, GrpcOpsInit(_)).WillRepeatedly(Invoke(invokeGrpcOpsInit)); + ASSERT_EQ(connect_client_ops_init(), 0); + EXPECT_EXIT(cmd_list_main(sizeof(argv) / sizeof(argv[0]), const_cast(argv)), + testing::ExitedWithCode(0), ""); + std::string output = testing::internal::GetCapturedStdout(); + std::vector tableItems {"CONTAINER ID", "IMAGE", "COMMAND", "CREATED", "STATUS", "PORTS", "NAMES"}; + for (const auto &elem : tableItems) { + if (output.find(elem) == std::string::npos) { + ADD_FAILURE() << "container list info should include " << elem; + } + } + if (output.find("healthy") == std::string::npos) { + FAIL() << "container list info should include healthy"; + } + std::cout << "Gtest Captured Stdout:" << std::endl << output; + testing::Mock::VerifyAndClearExpectations(&m_grpcClient); + SUCCEED() << "test isula ps --debug success"; +} + diff --git a/test/cutils/utils_string/utils_string_llt.cc b/test/cutils/utils_string/utils_string_llt.cc index 04210bdf0db3f8c97bbcc2c1639bf4e81cb8846a..36dbcf9389840eae878f23bbbb5e6e0b2fb820c1 100644 --- a/test/cutils/utils_string/utils_string_llt.cc +++ b/test/cutils/utils_string/utils_string_llt.cc @@ -757,3 +757,52 @@ TEST(utils_string_llt, test_dup_array_of_strings) MOCK_CLEAR(calloc); } +TEST(utils_string_llt, test_parse_percent_string) +{ + long converted = 0; + int ret = 0; + const char *correct1 = "10%"; + const char *correct2 = "0%"; + const char *correct3 = "100%"; + const char *correct4 = "99%"; + const char *wrong1 = "50"; + const char *wrong2 = "-10%"; + const char *wrong3 = "101%"; + const char *wrong4 = "a10%"; + const char *wrong5 = "10%k"; + const char *wrong6 = "1x0%"; + + ret = util_parse_percent_string(correct1, &converted); + ASSERT_EQ(ret, 0); + ASSERT_EQ(converted, 10); + + ret = util_parse_percent_string(correct2, &converted); + ASSERT_EQ(ret, 0); + ASSERT_EQ(converted, 0); + + ret = util_parse_percent_string(correct3, &converted); + ASSERT_EQ(ret, 0); + ASSERT_EQ(converted, 100); + + ret = util_parse_percent_string(correct4, &converted); + ASSERT_EQ(ret, 0); + ASSERT_EQ(converted, 99); + + ret = util_parse_percent_string(wrong1, &converted); + ASSERT_NE(ret, 0); + + ret = util_parse_percent_string(wrong2, &converted); + ASSERT_NE(ret, 0); + + ret = util_parse_percent_string(wrong3, &converted); + ASSERT_NE(ret, 0); + + ret = util_parse_percent_string(wrong4, &converted); + ASSERT_NE(ret, 0); + + ret = util_parse_percent_string(wrong5, &converted); + ASSERT_NE(ret, 0); + + ret = util_parse_percent_string(wrong6, &converted); + ASSERT_NE(ret, 0); +} diff --git a/test/image/oci/oci_config_merge/CMakeLists.txt b/test/image/oci/oci_config_merge/CMakeLists.txt index 14d964aa10848b78eae2ddf154725243fd5c0e61..fd42c4722b766599748e7c8f1ff4bdde3eed3d8b 100644 --- a/test/image/oci/oci_config_merge/CMakeLists.txt +++ b/test/image/oci/oci_config_merge/CMakeLists.txt @@ -15,7 +15,6 @@ add_executable(${EXE} ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/sha256/sha256.c ${CMAKE_BINARY_DIR}/json/json_common.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/path.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/execution/spec/specs_mount.c ${CMAKE_BINARY_DIR}/json/host_config.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/execution/spec/specs_extend.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/libisulad.c @@ -31,6 +30,10 @@ add_executable(${EXE} ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/json/schema/src/read_file.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cmd/isulad/arguments.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/image/oci/oci_llt_common.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/containers_store_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/namespace_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/container_unix_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/execution/spec/specs_mount.c ${CMAKE_BINARY_DIR}/json/imagetool_image.c ${CMAKE_BINARY_DIR}/json/oci_image_spec.c oci_config_merge_llt.cc) @@ -41,8 +44,12 @@ target_include_directories(${EXE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/image/oci ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/map + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/engines ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/json ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/execution/spec + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/execution/manager + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/execution/events ${CMAKE_BINARY_DIR}/json ${CMAKE_BINARY_DIR}/conf ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/sha256 @@ -52,7 +59,8 @@ target_include_directories(${EXE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/json/schema/src ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/console ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/image/oci + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks ) set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_common_calloc_s -Wl,--wrap,util_smart_calloc_s -Wl,--wrap,merge_env") -target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} -lyajl -lz) +target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) diff --git a/test/image/oci/oci_config_merge/oci_runtime_spec.json b/test/image/oci/oci_config_merge/oci_runtime_spec.json index 50726e69e148f41ad27c3f385c771cdbf8495522..796375763fbda6598cbb426fc18ef51ed089841b 100644 --- a/test/image/oci/oci_config_merge/oci_runtime_spec.json +++ b/test/image/oci/oci_config_merge/oci_runtime_spec.json @@ -1,5 +1,5 @@ { - "ociVersion": "1.0.0-rc5-dev", + "ociVersion": "1.0.1", "hooks": { }, diff --git a/test/mocks/container_unix_mock.cc b/test/mocks/container_unix_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..51e6fbc3c22da96aaa1771fb71f4fb5e0779d36b --- /dev/null +++ b/test/mocks/container_unix_mock.cc @@ -0,0 +1,43 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: lifeng + * Create: 2020-02-14 + * Description: provide container unix mock + ******************************************************************************/ + +#include "container_unix_mock.h" + +namespace { +MockContainerUnix *g_container_unix_mock = NULL; +} + +void MockContainerUnix_SetMock(MockContainerUnix* mock) +{ + g_container_unix_mock = mock; +} + + +/* container unref */ +void container_unref(container_t *cont) +{ + if (g_container_unix_mock != nullptr) { + return g_container_unix_mock->ContainerUnref(cont); + } + return; +} + +bool has_mount_for(container_t *cont, const char *mpath) +{ + if (g_container_unix_mock != nullptr) { + return g_container_unix_mock->HasMountFor(cont, mpath); + } + return false; +} diff --git a/test/mocks/container_unix_mock.h b/test/mocks/container_unix_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..7939ddd72758449a204f5f773eb7a87c3c01465d --- /dev/null +++ b/test/mocks/container_unix_mock.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: lifeng + * Create: 2020-02-14 + * Description: provide container unix mock + ******************************************************************************/ + +#ifndef CONTAINER_UNIX_MOCK_H_ +#define CONTAINER_UNIX_MOCK_H_ + +#include +#include "container_unix.h" + +class MockContainerUnix { +public: + virtual ~MockContainerUnix() = default; + MOCK_METHOD2(HasMountFor, bool(container_t *cont, const char *mpath)); + MOCK_METHOD1(ContainerUnref, void(container_t *cont)); +}; + +void MockContainerUnix_SetMock(MockContainerUnix* mock); + +#endif // CONTAINER_UNIX_MOCK_H_ \ No newline at end of file diff --git a/test/mocks/containers_store_mock.cc b/test/mocks/containers_store_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..65022f5e77164f9359dfcd8a48e15dcbcea9e363 --- /dev/null +++ b/test/mocks/containers_store_mock.cc @@ -0,0 +1,132 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide containers store mock + ******************************************************************************/ + +#include "containers_store_mock.h" + +namespace { +MockContainersStore *g_containers_store_mock = NULL; +} + +void MockContainersStore_SetMock(MockContainersStore* mock) +{ + g_containers_store_mock = mock; +} + + +int containers_store_init(void) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->ContainersStoreInit(); + } + return -1; +} + +bool containers_store_add(const char *id, container_t *cont) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->ContainersStoreAdd(id, cont); + } + return false; +} + +container_t *containers_store_get(const char *id_or_name) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->ContainersStoreGet(id_or_name); + } + return nullptr; +} + +container_t *containers_store_get_by_prefix(const char *prefix) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->ContainersStoreGetByPrefix(prefix); + } + return nullptr; +} + +bool containers_store_remove(const char *id) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->ContainersStoreRemove(id); + } + return false; +} + +int containers_store_list(container_t ***out, size_t *size) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->ContainersStoreList(out, size); + } + return -1; +} + +char **containers_store_list_ids(void) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->ContainersStoreListIds(); + } + return nullptr; +} + + +int name_index_init(void) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->NameIndexInit(); + } + return -1; +} + +bool name_index_remove(const char *name) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->NameIndexRemove(name); + } + return false; +} + +char *name_index_get(const char *name) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->NameIndexGet(name); + } + return nullptr; +} + + +bool name_index_add(const char *name, const char *id) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->NameIndexAdd(name, id); + } + return false; +} + +map_t *name_index_get_all(void) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->NameIndexGetAll(); + } + return nullptr; +} + +bool name_index_rename(const char *new_name, const char *old_name, const char *id) +{ + if (g_containers_store_mock != nullptr) { + return g_containers_store_mock->NameIndexRename(new_name, old_name, id); + } + return false; +} diff --git a/test/mocks/containers_store_mock.h b/test/mocks/containers_store_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..3d0f16be41cc2b63628355bd9312889280bd5268 --- /dev/null +++ b/test/mocks/containers_store_mock.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide containers store mock + ******************************************************************************/ + +#ifndef CONTAINERS_STORE_MOCK_H_ +#define CONTAINERS_STORE_MOCK_H_ + +#include +#include "containers_store.h" + +class MockContainersStore { +public: + virtual ~MockContainersStore() = default; + MOCK_METHOD0(ContainersStoreInit, int(void)); + MOCK_METHOD2(ContainersStoreAdd, bool(const char *id, container_t *cont)); + MOCK_METHOD1(ContainersStoreGet, container_t *(const char *id_or_name)); + MOCK_METHOD1(ContainersStoreGetByPrefix, container_t *(const char *prefix)); + MOCK_METHOD1(ContainersStoreRemove, bool(const char *id)); + MOCK_METHOD2(ContainersStoreList, int(container_t ***out, size_t *size)); + MOCK_METHOD0(ContainersStoreListIds, char **(void)); + MOCK_METHOD0(NameIndexInit, int(void)); + MOCK_METHOD1(NameIndexRemove, bool(const char *name)); + MOCK_METHOD1(NameIndexGet, char *(const char *name)); + MOCK_METHOD2(NameIndexAdd, bool(const char *name, const char *id)); + MOCK_METHOD0(NameIndexGetAll, map_t * (void)); + MOCK_METHOD3(NameIndexRename, bool(const char *new_name, const char *old_name, const char *id)); +}; + +void MockContainersStore_SetMock(MockContainersStore* mock); + +#endif // CONTAINERS_STORE_MOCK_H_ \ No newline at end of file diff --git a/test/mocks/driver_overlay2_mock.cc b/test/mocks/driver_overlay2_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..8289dae9133904e76cf162ef09bc3967b622d811 --- /dev/null +++ b/test/mocks/driver_overlay2_mock.cc @@ -0,0 +1,49 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wangfengtu + * Create: 2020-02-19 + * Description: provide driver overlay2 mock + ******************************************************************************/ + +#include "driver_overlay2_mock.h" + +namespace { +MockDriverOverlay2 *g_driver_overlay2_mock = NULL; +} + +void MockDriverOverlay2_SetMock(MockDriverOverlay2* mock) +{ + g_driver_overlay2_mock = mock; +} + +int overlay2_init(struct graphdriver *driver) +{ + if (g_driver_overlay2_mock != nullptr) { + return g_driver_overlay2_mock->Overlay2Init(driver); + } + return -1; +} + +int overlay2_parse_options(struct graphdriver *driver, const char **options, size_t options_len) +{ + if (g_driver_overlay2_mock != nullptr) { + return g_driver_overlay2_mock->Overlay2ParseOptions(driver, options, options_len); + } + return -1; +} + +bool overlay2_is_quota_options(struct graphdriver *driver, const char *option) +{ + if (g_driver_overlay2_mock != nullptr) { + return g_driver_overlay2_mock->Overlay2IsQuotaOptions(driver, option); + } + return false; +} diff --git a/test/mocks/driver_overlay2_mock.h b/test/mocks/driver_overlay2_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..0653818c141d8e5028c6cea7370cc2126b9f246b --- /dev/null +++ b/test/mocks/driver_overlay2_mock.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wangfengtu + * Create: 2020-02-19 + * Description: provide driver overlay2 mock + ******************************************************************************/ + +#ifndef DRIVER_OVERLAY2_MOCK_H_ +#define DRIVER_OVERLAY2_MOCK_H_ + +#include +#include "driver_overlay2.h" + +class MockDriverOverlay2 { +public: + virtual ~MockDriverOverlay2() = default; + MOCK_METHOD1(Overlay2Init, int(struct graphdriver *)); + MOCK_METHOD3(Overlay2ParseOptions, int(struct graphdriver *, const char **, size_t)); + MOCK_METHOD2(Overlay2IsQuotaOptions, bool(struct graphdriver *, const char *)); +}; + +void MockDriverOverlay2_SetMock(MockDriverOverlay2* mock); + +#endif // DRIVER_OVERLAY2_MOCK_H_ diff --git a/test/mocks/engine_mock.cc b/test/mocks/engine_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..0e55f23cd4632e76f20b7d72e7331004210e36ae --- /dev/null +++ b/test/mocks/engine_mock.cc @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide namespace mock + ******************************************************************************/ + +#include "engine_mock.h" + +namespace { +MockEngine *g_engine_mock = NULL; +} + +void MockEngine_SetMock(MockEngine* mock) +{ + g_engine_mock = mock; +} + +struct engine_operation *engines_get_handler(const char *name) +{ + if (g_engine_mock != nullptr) { + return g_engine_mock->EngineGetHandler(name); + } + return nullptr; +} diff --git a/test/mocks/engine_mock.h b/test/mocks/engine_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..18e6d5e70a975d47d6ced6fc9fd7af6d7c1a8efd --- /dev/null +++ b/test/mocks/engine_mock.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide engine mock + ******************************************************************************/ + +#ifndef ENGINE_MOCK_H_ +#define ENGINE_MOCK_H_ + +#include +#include "engine.h" + +class MockEngine { +public: + virtual ~MockEngine() = default; + MOCK_METHOD1(EngineGetHandler, struct engine_operation * (const char *name)); +}; + +void MockEngine_SetMock(MockEngine* mock); + +#endif // ENGINE_MOCK_H_ diff --git a/test/mocks/grpc_client_mock.cc b/test/mocks/grpc_client_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..95502e9b0c9f92b998f688e4c9430afbc7792323 --- /dev/null +++ b/test/mocks/grpc_client_mock.cc @@ -0,0 +1,25 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. + * Description: grpc client mock + * Author: wujing + * Create: 2019-12-19 + */ +#include "grpc_client_mock.h" + +namespace { +MockGrpcClient *g_grpc_client_mock = NULL; +} + +void GrpcClient_SetMock(MockGrpcClient* mock) +{ + g_grpc_client_mock = mock; +} + +int grpc_ops_init(isula_connect_ops *ops) +{ + if (g_grpc_client_mock != nullptr) { + return g_grpc_client_mock->GrpcOpsInit(ops); + } + return 0; +} + diff --git a/test/mocks/grpc_client_mock.h b/test/mocks/grpc_client_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..7fac8c47391913d8d0a0fb9adbe07cbedc3a8c7f --- /dev/null +++ b/test/mocks/grpc_client_mock.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. + * Description: grpc client mock + * Author: wujing + * Create: 2019-12-19 + */ + +#ifndef GRPC_CLIENT_MOCK_H_ +#define GRPC_CLIENT_MOCK_H_ + +#include +#include "grpc_client.h" + +class MockGrpcClient { +public: + virtual ~MockGrpcClient() = default; + MOCK_METHOD1(GrpcOpsInit, int(isula_connect_ops *ops)); +}; + +void GrpcClient_SetMock(MockGrpcClient* mock); + +#endif // GRPC_CLIENT_MOCK_H_ diff --git a/test/mocks/image_mock.cc b/test/mocks/image_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..58b5d833e690cac81ba68840a9ca3be2a579df74 --- /dev/null +++ b/test/mocks/image_mock.cc @@ -0,0 +1,42 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wangfengtu + * Create: 2020-02-19 + * Description: provide image mock + ******************************************************************************/ + +#include "image_mock.h" + +namespace { +MockImage *g_image_mock = NULL; +} + +void MockImage_SetMock(MockImage* mock) +{ + g_image_mock = mock; +} + +int im_get_storage_status(const char *image_type, im_storage_status_response **response) +{ + if (g_image_mock != nullptr) { + return g_image_mock->ImGetStorageStatus(image_type, response); + } + return -1; +} + +void free_im_storage_status_response(im_storage_status_response *ptr) +{ + if (g_image_mock != nullptr) { + g_image_mock->FreeImStorageStatusResponse(ptr); + return; + } + return; +} diff --git a/test/mocks/image_mock.h b/test/mocks/image_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..58c293a27ade64870d882f1fd1c0962e018a5b06 --- /dev/null +++ b/test/mocks/image_mock.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wangfengtu + * Create: 2020-02-19 + * Description: provide image mock + ******************************************************************************/ + +#ifndef IMAGE_MOCK_H_ +#define IMAGE_MOCK_H_ + +#include +#include "image.h" + +class MockImage { +public: + virtual ~MockImage() = default; + MOCK_METHOD2(ImGetStorageStatus, int(const char *, im_storage_status_response **)); + MOCK_METHOD1(FreeImStorageStatusResponse, void(im_storage_status_response *)); +}; + +void MockImage_SetMock(MockImage* mock); + +#endif // IMAGE_MOCK_H_ diff --git a/test/mocks/isulad_config_mock.cc b/test/mocks/isulad_config_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..a42577a4ccd0c552ab53e959c9aef68dde917c3e --- /dev/null +++ b/test/mocks/isulad_config_mock.cc @@ -0,0 +1,99 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide namespace mock + ******************************************************************************/ + +#include "isulad_config_mock.h" + +namespace { +MockIsuladConf *g_isulad_conf_mock = NULL; +} + +void MockIsuladConf_SetMock(MockIsuladConf* mock) +{ + g_isulad_conf_mock = mock; +} + +char *conf_get_routine_rootdir(const char *runtime) +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->GetRuntimeDir(runtime); + } + return nullptr; +} + +int parse_log_opts(struct service_arguments *args, const char *key, const char *value) +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->ParseLogopts(args, key, value); + } + return -1; +} + +int conf_get_isulad_default_ulimit(host_config_ulimits_element ***ulimit) +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->GetUlimit(ulimit); + } + return -1; +} + +int conf_get_isulad_hooks(oci_runtime_spec_hooks **phooks) +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->GetHooks(phooks); + } + return -1; +} + +/* conf get isulad mount rootfs */ +char *conf_get_isulad_mount_rootfs() +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->GetMountrootfs(); + } + return nullptr; +} + +/* conf get isulad cgroup parent for containers */ +char *conf_get_isulad_cgroup_parent() +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->GetCgroupParent(); + } + return nullptr; +} + +char *conf_get_isulad_native_umask() +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->GetUmask(); + } + return nullptr; +} + +char *conf_get_graph_rootpath() +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->ConfGetGraphRootpath(); + } + return nullptr; +} + +char *conf_get_isulad_storage_driver() +{ + if (g_isulad_conf_mock != nullptr) { + return g_isulad_conf_mock->ConfGetIsuladStorageDriver(); + } + return nullptr; +} diff --git a/test/mocks/isulad_config_mock.h b/test/mocks/isulad_config_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..f66c5b05d5f03b44d67145a5e9f4237d4bcd0916 --- /dev/null +++ b/test/mocks/isulad_config_mock.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide isulad config mock + ******************************************************************************/ + +#ifndef ISULAD_CONFIG_MOCK_H_ +#define ISULAD_CONFIG_MOCK_H_ + +#include +#include "isulad_config.h" + +class MockIsuladConf { +public: + virtual ~MockIsuladConf() = default; + MOCK_METHOD1(GetRuntimeDir, char *(const char *name)); + MOCK_METHOD3(ParseLogopts, int(struct service_arguments *args, const char *key, const char *value)); + MOCK_METHOD0(GetMountrootfs, char *(void)); + MOCK_METHOD1(GetHooks, int(oci_runtime_spec_hooks **phooks)); + MOCK_METHOD1(GetUlimit, int(host_config_ulimits_element ***ulimit)); + MOCK_METHOD0(GetCgroupParent, char *(void)); + MOCK_METHOD0(GetUmask, char *(void)); + MOCK_METHOD0(ConfGetGraphRootpath, char *(void)); + MOCK_METHOD0(ConfGetIsuladStorageDriver, char *(void)); +}; + +void MockIsuladConf_SetMock(MockIsuladConf* mock); + +#endif // ISULAD_CONFIG_MOCK_H_ diff --git a/test/mocks/namespace_mock.cc b/test/mocks/namespace_mock.cc new file mode 100644 index 0000000000000000000000000000000000000000..33041ff60f9ee88a181dba7f6df0ead3b5535d60 --- /dev/null +++ b/test/mocks/namespace_mock.cc @@ -0,0 +1,49 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide namespace mock + ******************************************************************************/ + +#include "namespace_mock.h" + +namespace { +MockNamespace *g_namespace_mock = NULL; +} + +void MockNamespace_SetMock(MockNamespace* mock) +{ + g_namespace_mock = mock; +} + +char *connected_container(const char *mode) +{ + if (g_namespace_mock != nullptr) { + return g_namespace_mock->ConnectedContainer(mode); + } + return nullptr; +} + +char *get_share_namespace_path(const char *type, const char *src_path) +{ + if (g_namespace_mock != nullptr) { + return g_namespace_mock->GetShareNamespacePath(type, src_path); + } + return nullptr; +} + +char *get_container_process_label(const char *path) +{ + if (g_namespace_mock != nullptr) { + return g_namespace_mock->GetContainerProcessLabel(path); + } + return nullptr; +} diff --git a/test/mocks/namespace_mock.h b/test/mocks/namespace_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..85f7c8581f39b59e86935c37a43ce937eef0f99e --- /dev/null +++ b/test/mocks/namespace_mock.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Author: wujing + * Create: 2020-02-14 + * Description: provide namespace mock + ******************************************************************************/ + +#ifndef NAMESPACE_MOCK_H_ +#define NAMESPACE_MOCK_H_ + +#include +#include "namespace.h" + +class MockNamespace { +public: + virtual ~MockNamespace() = default; + MOCK_METHOD1(ConnectedContainer, char *(const char *mode)); + MOCK_METHOD2(GetShareNamespacePath, char *(const char *type, const char *src_path)); + MOCK_METHOD1(GetContainerProcessLabel, char *(const char *path)); +}; + +void MockNamespace_SetMock(MockNamespace* mock); + +#endif // NAMESPACE_MOCK_H_ diff --git a/test/runtime/CMakeLists.txt b/test/runtime/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5b955bdaa972cda0afd21adc28fc7de0858b62f9 --- /dev/null +++ b/test/runtime/CMakeLists.txt @@ -0,0 +1,3 @@ +project(iSulad_LLT) + +add_subdirectory(lcr) diff --git a/test/runtime/lcr/CMakeLists.txt b/test/runtime/lcr/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d64497152db2e082209f13b4bf2f701b998b7d04 --- /dev/null +++ b/test/runtime/lcr/CMakeLists.txt @@ -0,0 +1,65 @@ +project(iSulad_LLT) + +SET(EXE lcr_rt_ops_llt) + +add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_regex.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_verify.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_string.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_convert.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/log.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/sha256/sha256.c + ${CMAKE_BINARY_DIR}/json/json_common.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/path.c + ${CMAKE_BINARY_DIR}/json/host_config.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/libisulad.c + ${CMAKE_BINARY_DIR}/json/defs.c + ${CMAKE_BINARY_DIR}/json/container_config_v2.c + ${CMAKE_BINARY_DIR}/json/container_config.c + ${CMAKE_BINARY_DIR}/json/oci_runtime_spec.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec/sysinfo.c + ${CMAKE_BINARY_DIR}/json/oci_runtime_config_linux.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd/commander.c + ${CMAKE_BINARY_DIR}/json/isulad_daemon_configs.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json/schema/src/read_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd/isulad/arguments.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/image/oci/oci_llt_common.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/containers_store_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/namespace_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/container_unix_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/engine_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/isulad_config_mock.cc + ${CMAKE_BINARY_DIR}/json/imagetool_image.c + ${CMAKE_BINARY_DIR}/json/oci_image_spec.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/runtime/lcr/lcr_rt_ops.c + lcr_rt_ops_llt.cc) + +target_include_directories(${EXE} PUBLIC + ${GTEST_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/map + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/manager + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/events + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/runtime + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/runtime/lcr + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/engines + ${CMAKE_BINARY_DIR}/json + ${CMAKE_BINARY_DIR}/conf + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/sha256 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/config + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/graphdriver + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json/schema/src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/console + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks + ) + +#set_target_properties(${EXE} PROPERTIES LINK_FLAGS) +target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) diff --git a/test/runtime/lcr/lcr_rt_ops_llt.cc b/test/runtime/lcr/lcr_rt_ops_llt.cc new file mode 100644 index 0000000000000000000000000000000000000000..7afce7142b48ca1cfab28bcea0e137c11176c3b6 --- /dev/null +++ b/test/runtime/lcr/lcr_rt_ops_llt.cc @@ -0,0 +1,595 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Description: lcr runtime ops llt + * Author: lifeng + * Create: 2020-02-15 + */ + +#include +#include +#include +#include "mock.h" +#include "lcr_rt_ops.h" +#include +#include +#include "engine_mock.h" +#include "isulad_config_mock.h" +#include "utils.h" + +using ::testing::Args; +using ::testing::ByRef; +using ::testing::SetArgPointee; +using ::testing::DoAll; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::NotNull; +using ::testing::AtLeast; +using ::testing::Invoke; +using ::testing::_; + +using namespace std; + +class LcrRtOpsUnitTest : public testing::Test { +public: + void SetUp() override + { + MockEngine_SetMock(&m_engine); + ::testing::Mock::AllowLeak(&m_engine); + + MockIsuladConf_SetMock(&m_isulad_conf); + ::testing::Mock::AllowLeak(&m_isulad_conf); + } + void TearDown() override + { + MockEngine_SetMock(nullptr); + MockIsuladConf_SetMock(nullptr); + } + + NiceMock m_engine; + NiceMock m_isulad_conf; +}; + +TEST(lcr_rt_ops_llt, test_rt_lcr_detect) +{ + // All parameter NULL + ASSERT_FALSE(rt_lcr_detect(NULL)); + + ASSERT_TRUE(rt_lcr_detect("lcr")); + + ASSERT_TRUE(rt_lcr_detect("LCR")); + + ASSERT_FALSE(rt_lcr_detect("test")); +} + +bool RuntimeCreateContainer(const char *id, const char *root, void *config) +{ + + if (id == nullptr || root == nullptr) { + return false; + } + + return true; +} + +bool RuntimeStartContainer(const engine_start_request_t *request) +{ + + if (request == nullptr) { + return false; + } + + if (request->name == nullptr) { + return false; + } + + return true; +} + +bool RuntimeCleanContainer(const char *name, const char *lcrpath, const char *logpath, const char *loglevel, + pid_t pid) +{ + + if (name == nullptr) { + return false; + } + + return true; +} + +bool RuntimeRmContainer(const char *name, const char *enginepath) +{ + + if (name == nullptr || enginepath == nullptr) { + return false; + } + + return true; +} + +int RuntimeStatusContainer(const char *name, const char *enginepath, struct engine_container_status_info *status) +{ + + if (name == nullptr || enginepath == nullptr || status == nullptr) { + return -1; + } + + return 0; +} + +int RuntimeStatsContainer(const char *name, const char *enginepath, + struct engine_container_resources_stats_info *rs_stats) +{ + + if (name == nullptr || enginepath == nullptr || rs_stats == nullptr) { + return -1; + } + + return 0; +} + +bool RuntimeExecContainer(const engine_exec_request_t *request, int *exit_code) +{ + + if (request == nullptr || exit_code == nullptr || request->lcrpath == nullptr) { + return false; + } + + return true; +} + +bool RuntimePauseContainer(const char *name, const char *enginepath) +{ + + if (name == nullptr || enginepath == nullptr) { + return false; + } + + return true; +} + +bool RuntimeResumeContainer(const char *name, const char *enginepath) +{ + + if (name == nullptr || enginepath == nullptr) { + return false; + } + + return true; +} + +bool RuntimeAttachContainer(const char *name, const char *enginepath, char *in_fifo, char *out_fifo, + char *err_fifo) +{ + + if (name == nullptr || enginepath == nullptr) { + return false; + } + + return true; +} + +bool RuntimeUpdateContainer(const char *name, const char *enginepath, const struct engine_cgroup_resources *cr) +{ + + if (name == nullptr || enginepath == nullptr) { + return false; + } + + return true; +} + +bool RuntimeResizeContainer(const char *name, const char *lcrpath, unsigned int height, unsigned int width) +{ + + if (name == nullptr || lcrpath == nullptr) { + return false; + } + + return true; +} + +bool RuntimeExecResizeContainer(const char *name, const char *lcrpath, const char *suffix, unsigned int height, + unsigned int width) +{ + + if (name == nullptr || lcrpath == nullptr) { + return false; + } + + return true; +} + +bool RuntimeListPidsContainer(const char *name, const char *rootpath, pid_t **pids, size_t *pids_len) +{ + + if (name == nullptr || rootpath == nullptr) { + return false; + } + + return true; +} + +struct engine_operation g_engine_ops; + +struct engine_operation *invoke_engines_get_handler(const char *runtime) +{ + if (runtime == nullptr) { + return nullptr; + } + g_engine_ops.engine_create_op = &RuntimeCreateContainer; + g_engine_ops.engine_start_op = &RuntimeStartContainer; + g_engine_ops.engine_clean_op = &RuntimeCleanContainer; + g_engine_ops.engine_delete_op = &RuntimeRmContainer; + g_engine_ops.engine_get_container_status_op = &RuntimeStatusContainer; + g_engine_ops.engine_get_container_resources_stats_op = &RuntimeStatsContainer; + g_engine_ops.engine_exec_op = &RuntimeExecContainer; + g_engine_ops.engine_pause_op = &RuntimePauseContainer; + g_engine_ops.engine_resume_op = &RuntimeResumeContainer; + g_engine_ops.engine_console_op = &RuntimeAttachContainer; + g_engine_ops.engine_update_op = &RuntimeUpdateContainer; + g_engine_ops.engine_resize_op = &RuntimeResizeContainer; + g_engine_ops.engine_exec_resize_op = &RuntimeExecResizeContainer; + g_engine_ops.engine_get_container_pids_op = &RuntimeListPidsContainer; + + return &g_engine_ops; +} + +/* conf get routine rootdir */ +char *invoke_conf_get_routine_rootdir(const char *runtime) +{ + if (runtime == nullptr) { + return nullptr; + } + + return util_strdup_s("/var/lib/isulad/engines/lcr"); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_create) +{ + rt_create_params_t params = {}; + + ASSERT_EQ(rt_lcr_create(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_create("123", "lcr", ¶ms), 0); + + ASSERT_EQ(rt_lcr_create(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_create("123", nullptr, ¶ms), -1); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +static char *get_absolute_path(const char *file) +{ + char base_path[PATH_MAX] = {0}; + char *json_file = NULL; + + if (getcwd(base_path, PATH_MAX) == NULL) { + return NULL; + } + + json_file = util_path_join(base_path, file); + if (json_file == NULL) { + return NULL; + } + + return json_file; +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_start) +{ + rt_start_params_t params = {}; + container_pid_t pid_info = {}; + char *pid_path = get_absolute_path("runtime/lcr/pid.file"); + + ASSERT_EQ(rt_lcr_start(nullptr, nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + params.container_pidfile = pid_path; + + ASSERT_EQ(rt_lcr_start("123", "lcr", ¶ms, &pid_info), 0); + ASSERT_EQ(pid_info.pid, 18715); + ASSERT_EQ(pid_info.ppid, 18712); + ASSERT_EQ(pid_info.start_time, 98072004); + ASSERT_EQ(pid_info.pstart_time, 98072003); + + ASSERT_EQ(rt_lcr_start(nullptr, "lcr", ¶ms, &pid_info), -1); + + ASSERT_EQ(rt_lcr_start("123", nullptr, ¶ms, nullptr), -1); + + free(pid_path); + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_restart) +{ + ASSERT_EQ(rt_lcr_restart(nullptr, nullptr, nullptr), RUNTIME_NOT_IMPLEMENT_RESET); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_clean_resource) +{ + rt_clean_params_t params = {}; + + ASSERT_EQ(rt_lcr_clean_resource(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_clean_resource("123", "lcr", ¶ms), 0); + + ASSERT_EQ(rt_lcr_clean_resource(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_clean_resource("123", nullptr, ¶ms), -1); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_rm) +{ + rt_rm_params_t params = {}; + + ASSERT_EQ(rt_lcr_rm(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_rm("123", "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_rm(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_rm("123", nullptr, ¶ms), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_rm("123", "lcr", ¶ms), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_status) +{ + rt_status_params_t params = {}; + struct engine_container_status_info status = {}; + + ASSERT_EQ(rt_lcr_status(nullptr, nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_status("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_status(nullptr, "lcr", ¶ms, &status), -1); + + ASSERT_EQ(rt_lcr_status("123", nullptr, ¶ms, &status), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_status("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_status("123", "lcr", ¶ms, &status), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_resources_stats) +{ + rt_stats_params_t params = {}; + struct engine_container_resources_stats_info status = {}; + + ASSERT_EQ(rt_lcr_resources_stats(nullptr, nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_resources_stats("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_resources_stats(nullptr, "lcr", ¶ms, &status), -1); + + ASSERT_EQ(rt_lcr_resources_stats("123", nullptr, ¶ms, &status), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_resources_stats("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_resources_stats("123", "lcr", ¶ms, &status), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_exec) +{ + rt_exec_params_t params = {}; + int pid = 0; + + ASSERT_EQ(rt_lcr_exec(nullptr, nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_exec("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_exec(nullptr, "lcr", ¶ms, &pid), -1); + + ASSERT_EQ(rt_lcr_exec("123", nullptr, ¶ms, &pid), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_exec("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_exec("123", "lcr", ¶ms, &pid), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_pause) +{ + rt_pause_params_t params = {}; + + ASSERT_EQ(rt_lcr_pause(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_pause("123", "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_pause(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_pause("123", nullptr, ¶ms), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_pause("123", "lcr", ¶ms), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_resume) +{ + rt_resume_params_t params = {}; + + ASSERT_EQ(rt_lcr_resume(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_resume("123", "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_resume(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_resume("123", nullptr, ¶ms), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_resume("123", "lcr", ¶ms), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_attach) +{ + rt_attach_params_t params = {}; + + ASSERT_EQ(rt_lcr_attach(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_attach("123", "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_attach(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_attach("123", nullptr, ¶ms), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_attach("123", "lcr", ¶ms), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_update) +{ + rt_update_params_t params = {}; + + ASSERT_EQ(rt_lcr_update(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_update("123", "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_update(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_update("123", nullptr, ¶ms), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_update("123", "lcr", ¶ms), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_resize) +{ + rt_resize_params_t params = {}; + + ASSERT_EQ(rt_lcr_resize(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_resize("123", "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_resize(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_resize("123", nullptr, ¶ms), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_resize("123", "lcr", ¶ms), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_exec_resize) +{ + rt_exec_resize_params_t params = {}; + + ASSERT_EQ(rt_lcr_exec_resize(nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_exec_resize("123", "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_exec_resize(nullptr, "lcr", ¶ms), -1); + + ASSERT_EQ(rt_lcr_exec_resize("123", nullptr, ¶ms), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_exec_resize("123", "lcr", ¶ms), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(LcrRtOpsUnitTest, test_rt_lcr_listpids) +{ + rt_listpids_params_t params = {}; + rt_listpids_out_t out = {}; + + ASSERT_EQ(rt_lcr_listpids(nullptr, nullptr, nullptr, nullptr), -1); + + EXPECT_CALL(m_isulad_conf, GetRuntimeDir(_)).WillRepeatedly(Invoke(invoke_conf_get_routine_rootdir)); + EXPECT_CALL(m_engine, EngineGetHandler(_)).WillRepeatedly(Invoke(invoke_engines_get_handler)); + + ASSERT_EQ(rt_lcr_listpids("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_listpids(nullptr, "lcr", ¶ms, &out), -1); + + ASSERT_EQ(rt_lcr_listpids("123", nullptr, ¶ms, &out), -1); + + params.rootpath = "/var/lib/isulad"; + ASSERT_EQ(rt_lcr_listpids("123", "lcr", ¶ms, nullptr), -1); + + ASSERT_EQ(rt_lcr_listpids("123", "lcr", ¶ms, &out), 0); + + testing::Mock::VerifyAndClearExpectations(&m_engine); + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} diff --git a/test/runtime/lcr/pid.file b/test/runtime/lcr/pid.file new file mode 100644 index 0000000000000000000000000000000000000000..433b0e8b09fae998098c32dde45ebfea3a4feb3d --- /dev/null +++ b/test/runtime/lcr/pid.file @@ -0,0 +1 @@ +18715 98072004 18712 98072003 diff --git a/test/services/CMakeLists.txt b/test/services/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b95dde2a184ee519fd25625960832a348d6672e7 --- /dev/null +++ b/test/services/CMakeLists.txt @@ -0,0 +1,3 @@ +project(iSulad_LLT) + +add_subdirectory(graphdriver) diff --git a/test/services/graphdriver/CMakeLists.txt b/test/services/graphdriver/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..49f78e6f47adfab9e82155446dfad447c28a476b --- /dev/null +++ b/test/services/graphdriver/CMakeLists.txt @@ -0,0 +1,3 @@ +project(iSulad_LLT) + +add_subdirectory(driver) diff --git a/test/services/graphdriver/driver/CMakeLists.txt b/test/services/graphdriver/driver/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b17a48939eb11174b51533c85390dd207f10bbf4 --- /dev/null +++ b/test/services/graphdriver/driver/CMakeLists.txt @@ -0,0 +1,48 @@ +project(iSulad_LLT) + +SET(EXE driver_llt) + +add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils/utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils/utils_regex.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils/utils_verify.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils/utils_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils/utils_string.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils/utils_convert.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/log.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/path.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/driver_overlay2_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/image_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/isulad_config_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/graphdriver/driver.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/graphdriver/devmapper/driver_devmapper.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/libisulad.c + ${CMAKE_BINARY_DIR}/json/json_common.c + driver_llt.cc) + +target_include_directories(${EXE} PUBLIC + ${GTEST_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/json + ${ENGINES_INCS} + ${RUNTIME_INCS} + ${IMAGE_INCS} + ${CMAKE_BINARY_DIR}/json + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/sha256 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/graphdriver/devmapper + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/graphdriver + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/services/graphdriver/overlay2 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/image + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/image/oci + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/config + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/console + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/cmd + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks + ) + +#set_target_properties(${EXE} PROPERTIES LINK_FLAGS) +target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) diff --git a/test/services/graphdriver/driver/driver_llt.cc b/test/services/graphdriver/driver/driver_llt.cc new file mode 100644 index 0000000000000000000000000000000000000000..76f53f8e00d1e9a59faa141d0402b0df5fc2ca6c --- /dev/null +++ b/test/services/graphdriver/driver/driver_llt.cc @@ -0,0 +1,162 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Description: driver llt + * Author: wangfengtu + * Create: 2020-02-19 + */ + +#include +#include +#include +#include "mock.h" +#include +#include +#include "utils.h" +#include "driver_devmapper.h" +#include "image.h" +#include "image_mock.h" +#include "driver_overlay2_mock.h" +#include "isulad_config_mock.h" + +using ::testing::Args; +using ::testing::ByRef; +using ::testing::SetArgPointee; +using ::testing::DoAll; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::NotNull; +using ::testing::AtLeast; +using ::testing::Invoke; +using ::testing::_; + +using namespace std; + +class DriverUnitTest : public testing::Test { +public: + void SetUp() override + { + MockImage_SetMock(&m_image); + MockIsuladConf_SetMock(&m_isulad_config); + MockDriverOverlay2_SetMock(&m_driver_overlay2); + ::testing::Mock::AllowLeak(&m_image); + ::testing::Mock::AllowLeak(&m_isulad_config); + ::testing::Mock::AllowLeak(&m_driver_overlay2); + } + void TearDown() override + { + MockImage_SetMock(nullptr); + MockIsuladConf_SetMock(nullptr); + MockDriverOverlay2_SetMock(nullptr); + } + + NiceMock m_image; + NiceMock m_isulad_config; + NiceMock m_driver_overlay2; +}; + +// All parameter NULL +TEST(graphdriver_init_llt, test_graphdriver_init_1) +{ + ASSERT_TRUE(graphdriver_init(NULL, NULL, 0) == NULL); +} + +// All parameter correct +TEST(graphdriver_init_llt, test_graphdriver_init_2) +{ + struct graphdriver *driver = NULL; + char **options = NULL; + size_t options_len = 0; + + options = util_string_split("dm.fs=ext4#dm.thinpooldev=/dev/mapper/isula-thinpool#" + "dm.min_free_space=10%#dm.basesize=5G#dm.mountopt=nodiscard#" + "dm.mkfsarg=-O ^has_journal#dm.mountopt=nodiscard", '#'); + options_len = util_array_len((const char**)options); + driver = graphdriver_init("devicemapper", options, options_len); + ASSERT_TRUE(driver != NULL); + ASSERT_EQ(driver->name, "devicemapper"); + util_free_array(options); +} + +// Parameter dm.fs invalid +TEST(graphdriver_init_llt, test_graphdriver_init_3) +{ + struct graphdriver *driver = NULL; + char **options = NULL; + size_t options_len = 0; + + options = util_string_split("dm.fs=xfs", ' '); + options_len = util_array_len((const char**)options); + driver = graphdriver_init("devicemapper", options, options_len); + ASSERT_TRUE(driver == NULL); + util_free_array(options); +} + +// Parameter dm.thinpooldev invalid +TEST(graphdriver_init_llt, test_graphdriver_init_4) +{ + struct graphdriver *driver = NULL; + char **options = NULL; + size_t options_len = 0; + + options = util_string_split("dm.thinpooldev=", ' '); + options_len = util_array_len((const char**)options); + driver = graphdriver_init("devicemapper", options, options_len); + ASSERT_TRUE(driver == NULL); + util_free_array(options); +} + +// Parameter dm.min_free_space invalid +TEST(graphdriver_init_llt, test_graphdriver_init_5) +{ + struct graphdriver *driver = NULL; + char **options = NULL; + size_t options_len = 0; + + options = util_string_split("dm.min_free_space=101%", ' '); + options_len = util_array_len((const char**)options); + driver = graphdriver_init("devicemapper", options, options_len); + ASSERT_TRUE(driver == NULL); + util_free_array(options); + + options = util_string_split("dm.min_free_space=100%", ' '); + options_len = util_array_len((const char**)options); + driver = graphdriver_init("devicemapper", options, options_len); + ASSERT_TRUE(driver == NULL); + util_free_array(options); +} + +// Parameter dm.basesize invalid +TEST(graphdriver_init_llt, test_graphdriver_init_6) +{ + struct graphdriver *driver = NULL; + char **options = NULL; + size_t options_len = 0; + + options = util_string_split("dm.basesize=-1", ' '); + options_len = util_array_len((const char**)options); + driver = graphdriver_init("devicemapper", options, options_len); + ASSERT_TRUE(driver == NULL); + util_free_array(options); +} + +// None exist parameter +TEST(graphdriver_init_llt, test_graphdriver_init_7) +{ + struct graphdriver *driver = NULL; + char **options = NULL; + size_t options_len = 0; + + options = util_string_split("kkkk=aaa", ' '); + options_len = util_array_len((const char**)options); + driver = graphdriver_init("devicemapper", options, options_len); + ASSERT_TRUE(driver == NULL); + util_free_array(options); +} diff --git a/test/specs/CMakeLists.txt b/test/specs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2cd439b6b1bab360469779d167791b1840993cf5 --- /dev/null +++ b/test/specs/CMakeLists.txt @@ -0,0 +1,3 @@ +project(iSulad_LLT) + +add_subdirectory(specs) diff --git a/test/specs/specs/CMakeLists.txt b/test/specs/specs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b2287dee908a1bffaabde06b47aba3f1af3323f --- /dev/null +++ b/test/specs/specs/CMakeLists.txt @@ -0,0 +1,82 @@ +project(iSulad_LLT) + +SET(EXE specs_llt) + +add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_regex.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_verify.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_string.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_convert.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/log.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/sha256/sha256.c + ${CMAKE_BINARY_DIR}/json/json_common.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/path.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec/specs.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec/specs_mount.c + ${CMAKE_BINARY_DIR}/json/host_config.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec/specs_extend.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec/specs_security.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/libisulad.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json/oci_runtime_hooks.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json/parse_common.c + ${CMAKE_BINARY_DIR}/json/defs.c + ${CMAKE_BINARY_DIR}/json/container_config_v2.c + ${CMAKE_BINARY_DIR}/json/container_config.c + ${CMAKE_BINARY_DIR}/json/oci_runtime_spec.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec/sysinfo.c + ${CMAKE_BINARY_DIR}/json/oci_runtime_config_linux.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd/commander.c + ${CMAKE_BINARY_DIR}/json/isulad_daemon_configs.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json/schema/src/read_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd/isulad/arguments.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/image/oci/oci_llt_common.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/containers_store_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/namespace_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/container_unix_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/engine_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/isulad_config_mock.cc + ${CMAKE_BINARY_DIR}/json/imagetool_image.c + ${CMAKE_BINARY_DIR}/json/oci_image_spec.c + ${CMAKE_BINARY_DIR}/json/docker_seccomp.c + specs_llt.cc) + +target_include_directories(${EXE} PUBLIC + ${GTEST_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/image/oci + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/image + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/map + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/spec + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/manager + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/events + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/execution/execute + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/tar + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/plugin + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/http + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/engines + ${ENGINES_INCS} + #${EXECUTION_INCS} + ${RUNTIME_INCS} + ${IMAGE_INCS} + ${CMAKE_BINARY_DIR}/json + ${CMAKE_BINARY_DIR}/conf + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/sha256 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/config + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/services/graphdriver + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/json/schema/src + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/console + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/image/oci + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks + ) + +#set_target_properties(${EXE} PROPERTIES LINK_FLAGS) +target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) diff --git a/test/specs/specs/hostconfig.json b/test/specs/specs/hostconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..41255d6c9c091d2711fdc49ab878371598cc3226 --- /dev/null +++ b/test/specs/specs/hostconfig.json @@ -0,0 +1,6 @@ +{ + "ShmSize": 67108864, + "RestartPolicy": { + "Name": "no" + } +} diff --git a/test/specs/specs/oci_runtime_spec.json b/test/specs/specs/oci_runtime_spec.json new file mode 100644 index 0000000000000000000000000000000000000000..cdc3a4e2c22dc3133f31a5991567ee0adaaa63b4 --- /dev/null +++ b/test/specs/specs/oci_runtime_spec.json @@ -0,0 +1,741 @@ +{ + "ociVersion": "1.0.0-rc5-dev", + "hooks": { + + }, + "annotations": { + "log.console.file": "none", + "log.console.filerotate": "7", + "log.console.filesize": "1MB", + "rootfs.mount": "/var/lib/lcrd/mnt/rootfs", + "native.umask": "secure" + }, + "hostname": "localhost", + "mounts": [ + { + "source": "proc", + "destination": "/proc", + "options": [ + "nosuid", + "noexec", + "nodev" + ], + "type": "proc" + }, + { + "source": "tmpfs", + "destination": "/dev", + "options": [ + "nosuid", + "strictatime", + "mode=755", + "size=65536k" + ], + "type": "tmpfs" + }, + { + "source": "devpts", + "destination": "/dev/pts", + "options": [ + "nosuid", + "noexec", + "newinstance", + "ptmxmode=0666", + "mode=0620", + "gid=5" + ], + "type": "devpts" + }, + { + "source": "sysfs", + "destination": "/sys", + "options": [ + "nosuid", + "noexec", + "nodev", + "ro" + ], + "type": "sysfs" + }, + { + "source": "shm", + "destination": "/dev/shm", + "options": [ + "nosuid", + "noexec", + "nodev", + "mode=1777", + "size=67108864" + ], + "type": "tmpfs" + }, + { + "source": "cgroup", + "destination": "/sys/fs/cgroup", + "options": [ + "nosuid", + "noexec", + "nodev", + "ro" + ], + "type": "cgroup" + }, + { + "source": "mqueue", + "destination": "/dev/mqueue", + "options": [ + "nosuid", + "noexec", + "nodev" + ], + "type": "mqueue" + }, + { + "source": "/var/lib/lcrd/engines/lcr/ad6c3f33518ed7e17a6d889a1327aa386f8b869927e2540821fb02310f567310/hostname", + "destination": "/etc/hostname", + "options": [ + "rbind", + "rprivate" + ], + "type": "bind" + }, + { + "source": "/var/lib/lcrd/engines/lcr/ad6c3f33518ed7e17a6d889a1327aa386f8b869927e2540821fb02310f567310/resolv.conf", + "destination": "/etc/resolv.conf", + "options": [ + "rbind", + "rprivate" + ], + "type": "bind" + }, + { + "source": "/var/lib/lcrd/engines/lcr/ad6c3f33518ed7e17a6d889a1327aa386f8b869927e2540821fb02310f567310/hosts", + "destination": "/etc/hosts", + "options": [ + "rbind", + "rprivate" + ], + "type": "bind" + } + ], + "root": { + "path": "/var/lib/lcrd/storage/overlay/40c51530fc1b4610f7f56633ef78fc5e4ad1a6f14cad59d5a1d012ff800c4289/merged" + }, + "process": { + "args": [ + "sh" + ], + "consoleSize": { + + }, + "cwd": "/", + "env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "TERM=xterm", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "terminal": true, + "user": { + + }, + "capabilities": { + "bounding": [ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" + ] + } + }, + "linux": { + "namespaces": [ + { + "type": "pid" + }, + { + "type": "network" + }, + { + "type": "ipc" + }, + { + "type": "uts" + }, + { + "type": "mount" + } + ], + "resources": { + "devices": [ + { + "type": "a", + "major": -1, + "minor": -1, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": -1, + "minor": -1, + "access": "m" + }, + { + "allow": true, + "type": "b", + "major": -1, + "minor": -1, + "access": "m" + }, + { + "allow": true, + "type": "c", + "major": 1, + "minor": 3, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 1, + "minor": 5, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 1, + "minor": 7, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 5, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 5, + "minor": 1, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 5, + "minor": 2, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 1, + "minor": 8, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 1, + "minor": 9, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 136, + "minor": -1, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 10, + "minor": 200, + "access": "rwm" + }, + { + "type": "c", + "major": 10, + "minor": 229, + "access": "rwm" + } + ] + }, + "seccomp": { + "defaultAction": "SCMP_ACT_ERRNO", + "architectures": [ + "SCMP_ARCH_X86_64", + "SCMP_ARCH_X86", + "SCMP_ARCH_X32", + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_ARM" + ], + "syscalls": [ + { + "names": [ + "accept", + "accept4", + "access", + "adjtimex", + "alarm", + "bind", + "brk", + "capget", + "capset", + "chdir", + "chmod", + "chown", + "chown32", + "clock_getres", + "clock_gettime", + "clock_nanosleep", + "close", + "connect", + "copy_file_range", + "creat", + "dup", + "dup2", + "dup3", + "epoll_create", + "epoll_create1", + "epoll_ctl", + "epoll_ctl_old", + "epoll_pwait", + "epoll_wait", + "epoll_wait_old", + "eventfd", + "eventfd2", + "execve", + "execveat", + "exit", + "exit_group", + "faccessat", + "fadvise64", + "fadvise64_64", + "fallocate", + "fanotify_mark", + "fchdir", + "fchmod", + "fchmodat", + "fchown", + "fchown32", + "fchownat", + "fcntl", + "fcntl64", + "fdatasync", + "fgetxattr", + "flistxattr", + "flock", + "fork", + "fremovexattr", + "fsetxattr", + "fstat", + "fstat64", + "fstatat64", + "fstatfs", + "fstatfs64", + "fsync", + "ftruncate", + "ftruncate64", + "futex", + "futimesat", + "getcpu", + "getcwd", + "getdents", + "getdents64", + "getegid", + "getegid32", + "geteuid", + "geteuid32", + "getgid", + "getgid32", + "getgroups", + "getgroups32", + "getitimer", + "getpeername", + "getpgid", + "getpgrp", + "getpid", + "getppid", + "getpriority", + "getrandom", + "getresgid", + "getresgid32", + "getresuid", + "getresuid32", + "getrlimit", + "get_robust_list", + "getrusage", + "getsid", + "getsockname", + "getsockopt", + "get_thread_area", + "gettid", + "gettimeofday", + "getuid", + "getuid32", + "getxattr", + "inotify_add_watch", + "inotify_init", + "inotify_init1", + "inotify_rm_watch", + "io_cancel", + "ioctl", + "io_destroy", + "io_getevents", + "ioprio_get", + "ioprio_set", + "io_setup", + "io_submit", + "ipc", + "kill", + "lchown", + "lchown32", + "lgetxattr", + "link", + "linkat", + "listen", + "listxattr", + "llistxattr", + "_llseek", + "lremovexattr", + "lseek", + "lsetxattr", + "lstat", + "lstat64", + "madvise", + "memfd_create", + "mincore", + "mkdir", + "mkdirat", + "mknod", + "mknodat", + "mlock", + "mlock2", + "mlockall", + "mmap", + "mmap2", + "mprotect", + "mq_getsetattr", + "mq_notify", + "mq_open", + "mq_timedreceive", + "mq_timedsend", + "mq_unlink", + "mremap", + "msgctl", + "msgget", + "msgrcv", + "msgsnd", + "msync", + "munlock", + "munlockall", + "munmap", + "nanosleep", + "newfstatat", + "_newselect", + "open", + "openat", + "pause", + "pipe", + "pipe2", + "poll", + "ppoll", + "prctl", + "pread64", + "preadv", + "preadv2", + "prlimit64", + "pselect6", + "pwrite64", + "pwritev", + "pwritev2", + "read", + "readahead", + "readlink", + "readlinkat", + "readv", + "recv", + "recvfrom", + "recvmmsg", + "recvmsg", + "remap_file_pages", + "removexattr", + "rename", + "renameat", + "renameat2", + "restart_syscall", + "rmdir", + "rt_sigaction", + "rt_sigpending", + "rt_sigprocmask", + "rt_sigqueueinfo", + "rt_sigreturn", + "rt_sigsuspend", + "rt_sigtimedwait", + "rt_tgsigqueueinfo", + "sched_getaffinity", + "sched_getattr", + "sched_getparam", + "sched_get_priority_max", + "sched_get_priority_min", + "sched_getscheduler", + "sched_rr_get_interval", + "sched_setaffinity", + "sched_setattr", + "sched_setparam", + "sched_setscheduler", + "sched_yield", + "seccomp", + "select", + "semctl", + "semget", + "semop", + "semtimedop", + "send", + "sendfile", + "sendfile64", + "sendmmsg", + "sendmsg", + "sendto", + "setfsgid", + "setfsgid32", + "setfsuid", + "setfsuid32", + "setgid", + "setgid32", + "setgroups", + "setgroups32", + "setitimer", + "setpgid", + "setpriority", + "setregid", + "setregid32", + "setresgid", + "setresgid32", + "setresuid", + "setresuid32", + "setreuid", + "setreuid32", + "setrlimit", + "set_robust_list", + "setsid", + "setsockopt", + "set_thread_area", + "set_tid_address", + "setuid", + "setuid32", + "setxattr", + "shmat", + "shmctl", + "shmdt", + "shmget", + "shutdown", + "sigaltstack", + "signalfd", + "signalfd4", + "sigreturn", + "socket", + "socketcall", + "socketpair", + "splice", + "stat", + "stat64", + "statfs", + "statfs64", + "statx", + "symlink", + "symlinkat", + "sync", + "sync_file_range", + "syncfs", + "sysinfo", + "tee", + "tgkill", + "time", + "timer_create", + "timer_delete", + "timerfd_create", + "timerfd_gettime", + "timerfd_settime", + "timer_getoverrun", + "timer_gettime", + "timer_settime", + "times", + "tkill", + "truncate", + "truncate64", + "ugetrlimit", + "umask", + "uname", + "unlink", + "unlinkat", + "utime", + "utimensat", + "utimes", + "vfork", + "vmsplice", + "wait4", + "waitid", + "waitpid", + "write", + "writev" + ], + "action": "SCMP_ACT_ALLOW" + }, + { + "names": [ + "ptrace" + ], + "action": "SCMP_ACT_ALLOW" + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "value": 8, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "value": 131072, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "value": 131080, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "value": 4294967295, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "arm_fadvise64_64", + "arm_sync_file_range", + "sync_file_range2", + "breakpoint", + "cacheflush", + "set_tls" + ], + "action": "SCMP_ACT_ALLOW" + }, + { + "names": [ + "arch_prctl" + ], + "action": "SCMP_ACT_ALLOW" + }, + { + "names": [ + "modify_ldt" + ], + "action": "SCMP_ACT_ALLOW" + }, + { + "names": [ + "clone" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "value": 2080505856, + "op": "SCMP_CMP_MASKED_EQ" + } + ] + }, + { + "names": [ + "chroot" + ], + "action": "SCMP_ACT_ALLOW" + } + ] + }, + "maskedPaths": [ + "/proc/acpi", + "/proc/config.gz", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/proc/scsi", + "/proc/signo", + "/proc/sig_catch", + "/proc/kbox", + "/proc/oom_extend", + "/proc/fdthreshold", + "/proc/fdstat", + "/proc/fdenable", + "/proc/files_panic_enable", + "/sys/firmware", + "/proc/cpuirqstat", + "/proc/memstat", + "/proc/iomem_ext", + "/proc/livepatch" + ], + "readonlyPaths": [ + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger", + "/proc/sysrq-region-size" + ] + } +} diff --git a/test/specs/specs/specs_llt.cc b/test/specs/specs/specs_llt.cc new file mode 100644 index 0000000000000000000000000000000000000000..66ca31914471622c02a5336142269dad43dfb0e5 --- /dev/null +++ b/test/specs/specs/specs_llt.cc @@ -0,0 +1,337 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * http://license.coscl.org.cn/MulanPSL + * 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 v1 for more details. + * Description: specs llt + * Author: lifeng + * Create: 2020-02-18 + */ + +#include +#include +#include +#include "mock.h" +#include "oci_runtime_spec.h" +#include "specs.h" +#include "host_config.h" +#include "container_config.h" +#include "oci_llt_common.h" +#include +#include +#include "isulad_config_mock.h" +#include "utils.h" + +using ::testing::Args; +using ::testing::ByRef; +using ::testing::SetArgPointee; +using ::testing::DoAll; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::NotNull; +using ::testing::AtLeast; +using ::testing::Invoke; +using ::testing::_; + +using namespace std; + +class SpecsUnitTest : public testing::Test { +public: + void SetUp() override + { + MockIsuladConf_SetMock(&m_isulad_conf); + ::testing::Mock::AllowLeak(&m_isulad_conf); + } + void TearDown() override + { + MockIsuladConf_SetMock(nullptr); + } + + NiceMock m_isulad_conf; +}; + +#define HOST_CONFIG_FILE "specs/specs/hostconfig.json" +#define OCI_RUNTIME_SPEC_FILE "specs/specs/oci_runtime_spec.json" + +TEST(merge_conf_cgroup_llt, test_merge_conf_cgroup_1) +{ + // All parameter NULL + ASSERT_NE(merge_conf_cgroup(NULL, NULL), 0); +} + +TEST(merge_conf_cgroup_llt, test_merge_conf_cgroup_2) +{ + oci_runtime_spec *oci_spec = NULL; + + // Parameter host_spec is NULL + oci_spec = (oci_runtime_spec *) util_common_calloc_s(sizeof(oci_runtime_spec)); + ASSERT_TRUE(oci_spec != NULL); + ASSERT_NE(merge_conf_cgroup(oci_spec, NULL), 0); + free_oci_runtime_spec(oci_spec); + oci_spec = NULL; +} + +TEST(merge_conf_cgroup_llt, test_merge_conf_cgroup_3) +{ + char *host_config_file = NULL; + host_config *host_spec = NULL; + char *err = NULL; + + // Parameter oci_spec is NULL + host_config_file = json_path(HOST_CONFIG_FILE); + ASSERT_TRUE(host_config_file != NULL); + host_spec = host_config_parse_file(host_config_file, NULL, &err); + ASSERT_TRUE(host_spec != NULL); + free(err); + err = NULL; + free(host_config_file); + host_config_file = NULL; + ASSERT_NE(merge_conf_cgroup(NULL, host_spec), 0); + free_host_config(host_spec); + host_spec = NULL; +} + +TEST(merge_conf_cgroup_llt, test_merge_conf_cgroup) +{ + char *host_config_file = NULL; + host_config *host_spec = NULL; + oci_runtime_spec *oci_spec = NULL; + char *err = NULL; + + // All parameter correct + host_config_file = json_path(HOST_CONFIG_FILE); + ASSERT_TRUE(host_config_file != NULL); + host_spec = host_config_parse_file(host_config_file, NULL, &err); + ASSERT_TRUE(host_spec != NULL); + free(err); + err = NULL; + free(host_config_file); + host_config_file = NULL; + + oci_spec = (oci_runtime_spec *) util_common_calloc_s(sizeof(oci_runtime_spec)); + ASSERT_TRUE(oci_spec != NULL); + + ASSERT_EQ(merge_conf_cgroup(oci_spec, host_spec), 0); + + free_host_config(host_spec); + host_spec = NULL; + free_oci_runtime_spec(oci_spec); + oci_spec = NULL; +} + +TEST(merge_conf_cgroup_llt, test_merge_conf_cgroup_cpu) +{ + char *host_config_file = NULL; + host_config *host_spec = NULL; + char *oci_config_file = NULL; + oci_runtime_spec *oci_spec = NULL; + char *err = NULL; + + // cpu + host_config_file = json_path(HOST_CONFIG_FILE); + ASSERT_TRUE(host_config_file != NULL); + host_spec = host_config_parse_file(host_config_file, NULL, &err); + ASSERT_TRUE(host_spec != NULL); + free(err); + err = NULL; + free(host_config_file); + host_config_file = NULL; + + oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); + ASSERT_TRUE(oci_config_file != NULL); + oci_spec = oci_runtime_spec_parse_file(oci_config_file, NULL, &err); + ASSERT_TRUE(oci_spec != NULL); + free(err); + err = NULL; + free(oci_config_file); + oci_config_file = NULL; + + host_spec->cpu_period = 123; + host_spec->cpu_quota = 234; + host_spec->cpu_realtime_period = 456; + host_spec->cpu_realtime_runtime = 789; + host_spec->cpu_shares = 321; + free(host_spec->cpuset_cpus); + host_spec->cpuset_cpus = util_strdup_s("0-3"); + free(host_spec->cpuset_mems); + host_spec->cpuset_mems = util_strdup_s("0"); + + ASSERT_EQ(merge_conf_cgroup(oci_spec, host_spec), 0); + + ASSERT_EQ(oci_spec->linux->resources->cpu->period, 123); + ASSERT_EQ(oci_spec->linux->resources->cpu->quota, 234); + ASSERT_EQ(oci_spec->linux->resources->cpu->realtime_period, 456); + ASSERT_EQ(oci_spec->linux->resources->cpu->realtime_runtime, 789); + ASSERT_EQ(oci_spec->linux->resources->cpu->shares, 321); + ASSERT_STREQ(oci_spec->linux->resources->cpu->cpus, "0-3"); + ASSERT_STREQ(oci_spec->linux->resources->cpu->mems, "0"); + + free_host_config(host_spec); + host_spec = NULL; + free_oci_runtime_spec(oci_spec); + oci_spec = NULL; +} + +TEST(merge_conf_cgroup_llt, test_merge_conf_cgroup_mem) +{ + char *host_config_file = NULL; + host_config *host_spec = NULL; + char *oci_config_file = NULL; + oci_runtime_spec *oci_spec = NULL; + char *err = NULL; + + // mem + // int64_t kernel_memory; + // int64_t memory_reservation; + // int64_t memory_swap; + host_config_file = json_path(HOST_CONFIG_FILE); + ASSERT_TRUE(host_config_file != NULL); + host_spec = host_config_parse_file(host_config_file, NULL, &err); + ASSERT_TRUE(host_spec != NULL); + free(err); + err = NULL; + free(host_config_file); + host_config_file = NULL; + + oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); + ASSERT_TRUE(oci_config_file != NULL); + oci_spec = oci_runtime_spec_parse_file(oci_config_file, NULL, &err); + ASSERT_TRUE(oci_spec != NULL); + free(err); + err = NULL; + free(oci_config_file); + oci_config_file = NULL; + + host_spec->kernel_memory = 123; + host_spec->memory_reservation = 234; + host_spec->memory_swap = 456; + + ASSERT_EQ(merge_conf_cgroup(oci_spec, host_spec), 0); + + ASSERT_EQ(oci_spec->linux->resources->memory->kernel, 123); + ASSERT_EQ(oci_spec->linux->resources->memory->reservation, 234); + ASSERT_EQ(oci_spec->linux->resources->memory->swap, 456); + + free_host_config(host_spec); + host_spec = NULL; + free_oci_runtime_spec(oci_spec); + oci_spec = NULL; +} + +/* conf get routine rootdir */ +char *invoke_conf_get_isulad_cgroup_parent_null() +{ + return nullptr; +} + +/* conf get routine rootdir */ +char *invoke_conf_get_isulad_cgroup_parent() +{ + return util_strdup_s("/var/lib/isulad/engines/lcr"); +} + +TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_1) +{ + ASSERT_EQ(merge_oci_cgroups_path(nullptr, nullptr, nullptr), -1); +} + +TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_2) +{ + oci_runtime_spec *oci_spec = nullptr; + host_config *host_spec = nullptr; + + oci_spec = (oci_runtime_spec *) util_common_calloc_s(sizeof(oci_runtime_spec)); + ASSERT_TRUE(oci_spec != NULL); + + host_spec = (host_config *) util_common_calloc_s(sizeof(host_config)); + ASSERT_TRUE(host_spec != NULL); + + EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent_null)); + + ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0); + + ASSERT_STREQ(oci_spec->linux->cgroups_path, "/isulad/123"); + + free_oci_runtime_spec(oci_spec); + free_host_config(host_spec); + + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_3) +{ + oci_runtime_spec *oci_spec = nullptr; + host_config *host_spec = nullptr; + + oci_spec = (oci_runtime_spec *) util_common_calloc_s(sizeof(oci_runtime_spec)); + ASSERT_TRUE(oci_spec != NULL); + + host_spec = (host_config *) util_common_calloc_s(sizeof(host_config)); + ASSERT_TRUE(host_spec != NULL); + + host_spec->cgroup_parent = util_strdup_s("/test"); + + EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent_null)); + + ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0); + + ASSERT_STREQ(oci_spec->linux->cgroups_path, "/test/123"); + + free_oci_runtime_spec(oci_spec); + free_host_config(host_spec); + + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_4) +{ + oci_runtime_spec *oci_spec = nullptr; + host_config *host_spec = nullptr; + + oci_spec = (oci_runtime_spec *) util_common_calloc_s(sizeof(oci_runtime_spec)); + ASSERT_TRUE(oci_spec != NULL); + + host_spec = (host_config *) util_common_calloc_s(sizeof(host_config)); + ASSERT_TRUE(host_spec != NULL); + + EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent)); + + ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0); + + ASSERT_STREQ(oci_spec->linux->cgroups_path, "/var/lib/isulad/engines/lcr/123"); + + free_oci_runtime_spec(oci_spec); + free_host_config(host_spec); + + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +} + +TEST_F(SpecsUnitTest, test_merge_oci_cgroups_path_5) +{ + oci_runtime_spec *oci_spec = nullptr; + host_config *host_spec = nullptr; + + oci_spec = (oci_runtime_spec *) util_common_calloc_s(sizeof(oci_runtime_spec)); + ASSERT_TRUE(oci_spec != NULL); + + host_spec = (host_config *) util_common_calloc_s(sizeof(host_config)); + ASSERT_TRUE(host_spec != NULL); + + host_spec->cgroup_parent = util_strdup_s("/test"); + + EXPECT_CALL(m_isulad_conf, GetCgroupParent()).WillRepeatedly(Invoke(invoke_conf_get_isulad_cgroup_parent)); + + ASSERT_EQ(merge_oci_cgroups_path("123", oci_spec, host_spec), 0); + + ASSERT_STREQ(oci_spec->linux->cgroups_path, "/test/123"); + + free_oci_runtime_spec(oci_spec); + free_host_config(host_spec); + + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); +}