blob: b3d93dcecf3ee6e72a745e2c64cb8eabaa2dda41 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <vector>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <gtest/gtest.h>
#include <sstream>
extern "C" {
#include "configuration.h"
#include "container-executor.h"
#include "modules/cgroups/cgroups-operations.h"
#include "modules/gpu/gpu-module.h"
#include "test/test-container-executor-common.h"
#include "util.h"
}
namespace ContainerExecutor {
class TestGpuModule : public ::testing::Test {
protected:
virtual void SetUp() {
if (mkdirs(TEST_ROOT, 0755) != 0) {
fprintf(ERRORFILE, "Failed to mkdir TEST_ROOT: %s\n", TEST_ROOT);
exit(1);
}
LOGFILE = stdout;
ERRORFILE = stderr;
}
virtual void TearDown() {
}
};
static std::vector<const char*> cgroups_parameters_invoked;
static int mock_update_cgroups_parameters(
const char* controller_name,
const char* param_name,
const char* group_id,
const char* value) {
char* buf = (char*) malloc(128);
strcpy(buf, controller_name);
cgroups_parameters_invoked.push_back(buf);
buf = (char*) malloc(128);
strcpy(buf, param_name);
cgroups_parameters_invoked.push_back(buf);
buf = (char*) malloc(128);
strcpy(buf, group_id);
cgroups_parameters_invoked.push_back(buf);
buf = (char*) malloc(128);
strcpy(buf, value);
cgroups_parameters_invoked.push_back(buf);
return 0;
}
static void verify_param_updated_to_cgroups(
int argc, const char** argv) {
ASSERT_EQ(argc, cgroups_parameters_invoked.size());
int offset = 0;
while (offset < argc) {
ASSERT_STREQ(argv[offset], cgroups_parameters_invoked[offset]);
offset++;
}
}
static void write_and_load_gpu_module_to_cfg(const char* cfg_filepath, int enabled) {
FILE *file = fopen(cfg_filepath, "w");
if (file == NULL) {
printf("FAIL: Could not open configuration file: %s\n", cfg_filepath);
exit(1);
}
fprintf(file, "[gpu]\n");
if (enabled) {
fprintf(file, "module.enabled=true\n");
} else {
fprintf(file, "module.enabled=false\n");
}
fclose(file);
// Read config file
read_executor_config(cfg_filepath);
reload_gpu_configuration();
}
static void test_gpu_module_enabled_disabled(int enabled) {
// Write config file.
const char *filename = TEST_ROOT "/test_cgroups_module_enabled_disabled.cfg";
write_and_load_gpu_module_to_cfg(filename, enabled);
char* argv[] = { (char*) "--module-gpu", (char*) "--excluded_gpus", (char*) "0,1",
(char*) "--container_id",
(char*) "container_1498064906505_0001_01_000001" };
int rc = handle_gpu_request(&mock_update_cgroups_parameters,
"gpu", 5, argv);
int EXPECTED_RC;
if (enabled) {
EXPECTED_RC = 0;
} else {
EXPECTED_RC = -1;
}
ASSERT_EQ(EXPECTED_RC, rc);
}
TEST_F(TestGpuModule, test_verify_gpu_module_calls_cgroup_parameter) {
// Write config file.
const char *filename = TEST_ROOT "/test_verify_gpu_module_calls_cgroup_parameter.cfg";
write_and_load_gpu_module_to_cfg(filename, 1);
char* container_id = (char*) "container_1498064906505_0001_01_000001";
char* argv[] = { (char*) "--module-gpu", (char*) "--excluded_gpus", (char*) "0,1",
(char*) "--container_id",
container_id };
/* Test case 1: block 2 devices */
cgroups_parameters_invoked.clear();
int rc = handle_gpu_request(&mock_update_cgroups_parameters,
"gpu", 5, argv);
ASSERT_EQ(0, rc) << "Should success.\n";
// Verify cgroups parameters
const char* expected_cgroups_argv[] = { "devices", "deny", container_id, "c 195:0 rwm",
"devices", "deny", container_id, "c 195:1 rwm"};
verify_param_updated_to_cgroups(8, expected_cgroups_argv);
/* Test case 2: block 0 devices */
cgroups_parameters_invoked.clear();
char* argv_1[] = { (char*) "--module-gpu", (char*) "--container_id", container_id };
rc = handle_gpu_request(&mock_update_cgroups_parameters,
"gpu", 3, argv_1);
ASSERT_EQ(0, rc) << "Should success.\n";
// Verify cgroups parameters
verify_param_updated_to_cgroups(0, NULL);
/* Test case 3: block 2 non-sequential devices */
cgroups_parameters_invoked.clear();
char* argv_2[] = { (char*) "--module-gpu", (char*) "--excluded_gpus", (char*) "1,3",
(char*) "--container_id", container_id };
rc = handle_gpu_request(&mock_update_cgroups_parameters,
"gpu", 5, argv_2);
ASSERT_EQ(0, rc) << "Should success.\n";
// Verify cgroups parameters
const char* expected_cgroups_argv_2[] = { "devices", "deny", container_id, "c 195:1 rwm",
"devices", "deny", container_id, "c 195:3 rwm"};
verify_param_updated_to_cgroups(8, expected_cgroups_argv_2);
}
TEST_F(TestGpuModule, test_illegal_cli_parameters) {
// Write config file.
const char *filename = TEST_ROOT "/test_illegal_cli_parameters.cfg";
write_and_load_gpu_module_to_cfg(filename, 1);
// Illegal container id - 1
char* argv[] = { (char*) "--module-gpu", (char*) "--excluded_gpus", (char*) "0,1",
(char*) "--container_id", (char*) "xxxx" };
int rc = handle_gpu_request(&mock_update_cgroups_parameters,
"gpu", 5, argv);
ASSERT_NE(0, rc) << "Should fail.\n";
// Illegal container id - 2
char* argv_1[] = { (char*) "--module-gpu", (char*) "--excluded_gpus", (char*) "0,1",
(char*) "--container_id", (char*) "container_1" };
rc = handle_gpu_request(&mock_update_cgroups_parameters,
"gpu", 5, argv_1);
ASSERT_NE(0, rc) << "Should fail.\n";
// Illegal container id - 3
char* argv_2[] = { (char*) "--module-gpu", (char*) "--excluded_gpus", (char*) "0,1" };
rc = handle_gpu_request(&mock_update_cgroups_parameters,
"gpu", 3, argv_2);
ASSERT_NE(0, rc) << "Should fail.\n";
}
TEST_F(TestGpuModule, test_gpu_module_disabled) {
test_gpu_module_enabled_disabled(0);
}
TEST_F(TestGpuModule, test_gpu_module_enabled) {
test_gpu_module_enabled_disabled(1);
}
} // namespace ContainerExecutor