YARN-7487. Ensure volume to include GPU base libraries after created by plugin. Contributed by Wangda Tan.
This commit is contained in:
parent
4653aa3eb3
commit
556aea3f36
|
@ -337,7 +337,7 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runDockerVolumeCommand(DockerVolumeCommand dockerVolumeCommand,
|
private String runDockerVolumeCommand(DockerVolumeCommand dockerVolumeCommand,
|
||||||
Container container) throws ContainerExecutionException {
|
Container container) throws ContainerExecutionException {
|
||||||
try {
|
try {
|
||||||
String commandFile = dockerClient.writeCommandToTempFile(
|
String commandFile = dockerClient.writeCommandToTempFile(
|
||||||
|
@ -351,6 +351,7 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
|
||||||
LOG.info("ContainerId=" + container.getContainerId()
|
LOG.info("ContainerId=" + container.getContainerId()
|
||||||
+ ", docker volume output for " + dockerVolumeCommand + ": "
|
+ ", docker volume output for " + dockerVolumeCommand + ": "
|
||||||
+ output);
|
+ output);
|
||||||
|
return output;
|
||||||
} catch (ContainerExecutionException e) {
|
} catch (ContainerExecutionException e) {
|
||||||
LOG.error("Error when writing command to temp file, command="
|
LOG.error("Error when writing command to temp file, command="
|
||||||
+ dockerVolumeCommand,
|
+ dockerVolumeCommand,
|
||||||
|
@ -378,14 +379,72 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
|
||||||
plugin.getDockerCommandPluginInstance();
|
plugin.getDockerCommandPluginInstance();
|
||||||
if (dockerCommandPlugin != null) {
|
if (dockerCommandPlugin != null) {
|
||||||
DockerVolumeCommand dockerVolumeCommand =
|
DockerVolumeCommand dockerVolumeCommand =
|
||||||
dockerCommandPlugin.getCreateDockerVolumeCommand(ctx.getContainer());
|
dockerCommandPlugin.getCreateDockerVolumeCommand(
|
||||||
|
ctx.getContainer());
|
||||||
if (dockerVolumeCommand != null) {
|
if (dockerVolumeCommand != null) {
|
||||||
runDockerVolumeCommand(dockerVolumeCommand, container);
|
runDockerVolumeCommand(dockerVolumeCommand, container);
|
||||||
|
|
||||||
|
// After volume created, run inspect to make sure volume properly
|
||||||
|
// created.
|
||||||
|
if (dockerVolumeCommand.getSubCommand().equals(
|
||||||
|
DockerVolumeCommand.VOLUME_CREATE_SUB_COMMAND)) {
|
||||||
|
checkDockerVolumeCreated(dockerVolumeCommand, container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDockerVolumeCreated(
|
||||||
|
DockerVolumeCommand dockerVolumeCreationCommand, Container container)
|
||||||
|
throws ContainerExecutionException {
|
||||||
|
DockerVolumeCommand dockerVolumeInspectCommand = new DockerVolumeCommand(
|
||||||
|
DockerVolumeCommand.VOLUME_LS_SUB_COMMAND);
|
||||||
|
dockerVolumeInspectCommand.setFormat("{{.Name}},{{.Driver}}");
|
||||||
|
String output = runDockerVolumeCommand(dockerVolumeInspectCommand,
|
||||||
|
container);
|
||||||
|
|
||||||
|
// Parse output line by line and check if it matches
|
||||||
|
String volumeName = dockerVolumeCreationCommand.getVolumeName();
|
||||||
|
String driverName = dockerVolumeCreationCommand.getDriverName();
|
||||||
|
if (driverName == null) {
|
||||||
|
driverName = "local";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String line : output.split("\n")) {
|
||||||
|
line = line.trim();
|
||||||
|
String[] arr = line.split(",");
|
||||||
|
String v = arr[0].trim();
|
||||||
|
String d = null;
|
||||||
|
if (arr.length > 1) {
|
||||||
|
d = arr[1].trim();
|
||||||
|
}
|
||||||
|
if (d != null && volumeName.equals(v) && driverName.equals(d)) {
|
||||||
|
// Good we found it.
|
||||||
|
LOG.info(
|
||||||
|
"Docker volume-name=" + volumeName + " driver-name=" + driverName
|
||||||
|
+ " already exists for container=" + container
|
||||||
|
.getContainerId() + ", continue...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't find the volume
|
||||||
|
String message =
|
||||||
|
" Couldn't find volume=" + volumeName + " driver=" + driverName
|
||||||
|
+ " for container=" + container.getContainerId()
|
||||||
|
+ ", please check error message in log to understand "
|
||||||
|
+ "why this happens.";
|
||||||
|
LOG.error(message);
|
||||||
|
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
LOG.debug("All docker volumes in the system, command="
|
||||||
|
+ dockerVolumeInspectCommand.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ContainerExecutionException(message);
|
||||||
|
}
|
||||||
|
|
||||||
private void validateContainerNetworkType(String network)
|
private void validateContainerNetworkType(String network)
|
||||||
throws ContainerExecutionException {
|
throws ContainerExecutionException {
|
||||||
|
|
|
@ -27,23 +27,50 @@ import java.util.regex.Pattern;
|
||||||
*/
|
*/
|
||||||
public class DockerVolumeCommand extends DockerCommand {
|
public class DockerVolumeCommand extends DockerCommand {
|
||||||
public static final String VOLUME_COMMAND = "volume";
|
public static final String VOLUME_COMMAND = "volume";
|
||||||
public static final String VOLUME_CREATE_COMMAND = "create";
|
public static final String VOLUME_CREATE_SUB_COMMAND = "create";
|
||||||
|
public static final String VOLUME_LS_SUB_COMMAND = "ls";
|
||||||
|
|
||||||
// Regex pattern for volume name
|
// Regex pattern for volume name
|
||||||
public static final Pattern VOLUME_NAME_PATTERN = Pattern.compile(
|
public static final Pattern VOLUME_NAME_PATTERN = Pattern.compile(
|
||||||
"[a-zA-Z0-9][a-zA-Z0-9_.-]*");
|
"[a-zA-Z0-9][a-zA-Z0-9_.-]*");
|
||||||
|
|
||||||
|
private String volumeName;
|
||||||
|
private String driverName;
|
||||||
|
private String subCommand;
|
||||||
|
|
||||||
public DockerVolumeCommand(String subCommand) {
|
public DockerVolumeCommand(String subCommand) {
|
||||||
super(VOLUME_COMMAND);
|
super(VOLUME_COMMAND);
|
||||||
|
this.subCommand = subCommand;
|
||||||
super.addCommandArguments("sub-command", subCommand);
|
super.addCommandArguments("sub-command", subCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DockerVolumeCommand setVolumeName(String volumeName) {
|
public DockerVolumeCommand setVolumeName(String volumeName) {
|
||||||
super.addCommandArguments("volume", volumeName);
|
super.addCommandArguments("volume", volumeName);
|
||||||
|
this.volumeName = volumeName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DockerVolumeCommand setDriverName(String driverName) {
|
public DockerVolumeCommand setDriverName(String driverName) {
|
||||||
super.addCommandArguments("driver", driverName);
|
super.addCommandArguments("driver", driverName);
|
||||||
|
this.driverName = driverName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getVolumeName() {
|
||||||
|
return volumeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDriverName() {
|
||||||
|
return driverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubCommand() {
|
||||||
|
return subCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DockerVolumeCommand setFormat(String format) {
|
||||||
|
super.addCommandArguments("format", format);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,7 +301,7 @@ public class NvidiaDockerV1CommandPlugin implements DockerCommandPlugin {
|
||||||
|
|
||||||
if (newVolumeName != null) {
|
if (newVolumeName != null) {
|
||||||
DockerVolumeCommand command = new DockerVolumeCommand(
|
DockerVolumeCommand command = new DockerVolumeCommand(
|
||||||
DockerVolumeCommand.VOLUME_CREATE_COMMAND);
|
DockerVolumeCommand.VOLUME_CREATE_SUB_COMMAND);
|
||||||
command.setDriverName(volumeDriver);
|
command.setDriverName(volumeDriver);
|
||||||
command.setVolumeName(newVolumeName);
|
command.setVolumeName(newVolumeName);
|
||||||
return command;
|
return command;
|
||||||
|
|
|
@ -299,32 +299,22 @@ static int value_permitted(const struct configuration* executor_cfg,
|
||||||
int get_docker_volume_command(const char *command_file, const struct configuration *conf, char *out,
|
int get_docker_volume_command(const char *command_file, const struct configuration *conf, char *out,
|
||||||
const size_t outlen) {
|
const size_t outlen) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *driver = NULL, *volume_name = NULL, *sub_command = NULL;
|
char *driver = NULL, *volume_name = NULL, *sub_command = NULL, *format = NULL;
|
||||||
struct configuration command_config = {0, NULL};
|
struct configuration command_config = {0, NULL};
|
||||||
ret = read_and_verify_command_file(command_file, DOCKER_VOLUME_COMMAND, &command_config);
|
ret = read_and_verify_command_file(command_file, DOCKER_VOLUME_COMMAND, &command_config);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
sub_command = get_configuration_value("sub-command", DOCKER_COMMAND_FILE_SECTION, &command_config);
|
sub_command = get_configuration_value("sub-command", DOCKER_COMMAND_FILE_SECTION, &command_config);
|
||||||
if (sub_command == NULL || 0 != strcmp(sub_command, "create")) {
|
|
||||||
fprintf(ERRORFILE, "\"create\" is the only acceptable sub-command of volume.\n");
|
if ((sub_command == NULL) || ((0 != strcmp(sub_command, "create")) &&
|
||||||
|
(0 != strcmp(sub_command, "ls")))) {
|
||||||
|
fprintf(ERRORFILE, "\"create/ls\" are the only acceptable sub-command of volume, input sub_command=\"%s\"\n",
|
||||||
|
sub_command);
|
||||||
ret = INVALID_DOCKER_VOLUME_COMMAND;
|
ret = INVALID_DOCKER_VOLUME_COMMAND;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
volume_name = get_configuration_value("volume", DOCKER_COMMAND_FILE_SECTION, &command_config);
|
|
||||||
if (volume_name == NULL || validate_volume_name(volume_name) != 0) {
|
|
||||||
fprintf(ERRORFILE, "%s is not a valid volume name.\n", volume_name);
|
|
||||||
ret = INVALID_DOCKER_VOLUME_NAME;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
driver = get_configuration_value("driver", DOCKER_COMMAND_FILE_SECTION, &command_config);
|
|
||||||
if (driver == NULL) {
|
|
||||||
ret = INVALID_DOCKER_VOLUME_DRIVER;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(out, 0, outlen);
|
memset(out, 0, outlen);
|
||||||
|
|
||||||
ret = add_docker_config_param(&command_config, out, outlen);
|
ret = add_docker_config_param(&command_config, out, outlen);
|
||||||
|
@ -338,6 +328,20 @@ int get_docker_volume_command(const char *command_file, const struct configurati
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 == strcmp(sub_command, "create")) {
|
||||||
|
volume_name = get_configuration_value("volume", DOCKER_COMMAND_FILE_SECTION, &command_config);
|
||||||
|
if (volume_name == NULL || validate_volume_name(volume_name) != 0) {
|
||||||
|
fprintf(ERRORFILE, "%s is not a valid volume name.\n", volume_name);
|
||||||
|
ret = INVALID_DOCKER_VOLUME_NAME;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver = get_configuration_value("driver", DOCKER_COMMAND_FILE_SECTION, &command_config);
|
||||||
|
if (driver == NULL) {
|
||||||
|
ret = INVALID_DOCKER_VOLUME_DRIVER;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
ret = add_to_buffer(out, outlen, " create");
|
ret = add_to_buffer(out, outlen, " create");
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -369,11 +373,31 @@ int get_docker_volume_command(const char *command_file, const struct configurati
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
} else if (0 == strcmp(sub_command, "ls")) {
|
||||||
|
format = get_configuration_value("format", DOCKER_COMMAND_FILE_SECTION, &command_config);
|
||||||
|
|
||||||
|
ret = add_to_buffer(out, outlen, " ls");
|
||||||
|
if (ret != 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format) {
|
||||||
|
ret = add_to_buffer(out, outlen, " --format=");
|
||||||
|
if (ret != 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ret = add_to_buffer(out, outlen, format);
|
||||||
|
if (ret != 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(driver);
|
free(driver);
|
||||||
free(volume_name);
|
free(volume_name);
|
||||||
free(sub_command);
|
free(sub_command);
|
||||||
|
free(format);
|
||||||
|
|
||||||
// clean up out buffer
|
// clean up out buffer
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
|
|
|
@ -1132,12 +1132,15 @@ namespace ContainerExecutor {
|
||||||
file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
|
file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
|
||||||
"[docker-command-execution]\n docker-command=volume\n sub-command=create\n volume=volume1 \n driver=driver1",
|
"[docker-command-execution]\n docker-command=volume\n sub-command=create\n volume=volume1 \n driver=driver1",
|
||||||
"volume create --name=volume1 --driver=driver1"));
|
"volume create --name=volume1 --driver=driver1"));
|
||||||
|
file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
|
||||||
|
"[docker-command-execution]\n docker-command=volume\n format={{.Name}},{{.Driver}}\n sub-command=ls",
|
||||||
|
"volume ls --format={{.Name}},{{.Driver}}"));
|
||||||
|
|
||||||
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
|
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
|
||||||
|
|
||||||
// Wrong subcommand
|
// Wrong subcommand
|
||||||
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
|
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
|
||||||
"[docker-command-execution]\n docker-command=volume\n sub-command=ls\n volume=volume1 \n driver=driver1",
|
"[docker-command-execution]\n docker-command=volume\n sub-command=inspect\n volume=volume1 \n driver=driver1",
|
||||||
static_cast<int>(INVALID_DOCKER_VOLUME_COMMAND)));
|
static_cast<int>(INVALID_DOCKER_VOLUME_COMMAND)));
|
||||||
|
|
||||||
// Volume not specified
|
// Volume not specified
|
||||||
|
|
|
@ -1301,7 +1301,7 @@ public class TestDockerContainerRuntime {
|
||||||
//single invocation expected
|
//single invocation expected
|
||||||
//due to type erasure + mocking, this verification requires a suppress
|
//due to type erasure + mocking, this verification requires a suppress
|
||||||
// warning annotation on the entire method
|
// warning annotation on the entire method
|
||||||
verify(mockExecutor, times(1))
|
verify(mockExecutor, times(2))
|
||||||
.executePrivilegedOperation(anyList(), opCaptor.capture(), any(
|
.executePrivilegedOperation(anyList(), opCaptor.capture(), any(
|
||||||
File.class), anyMap(), anyBoolean(), anyBoolean());
|
File.class), anyMap(), anyBoolean(), anyBoolean());
|
||||||
|
|
||||||
|
@ -1309,7 +1309,9 @@ public class TestDockerContainerRuntime {
|
||||||
// hence, reset mock here
|
// hence, reset mock here
|
||||||
Mockito.reset(mockExecutor);
|
Mockito.reset(mockExecutor);
|
||||||
|
|
||||||
PrivilegedOperation op = opCaptor.getValue();
|
List<PrivilegedOperation> allCaptures = opCaptor.getAllValues();
|
||||||
|
|
||||||
|
PrivilegedOperation op = allCaptures.get(0);
|
||||||
Assert.assertEquals(PrivilegedOperation.OperationType
|
Assert.assertEquals(PrivilegedOperation.OperationType
|
||||||
.RUN_DOCKER_CMD, op.getOperationType());
|
.RUN_DOCKER_CMD, op.getOperationType());
|
||||||
|
|
||||||
|
@ -1317,22 +1319,32 @@ public class TestDockerContainerRuntime {
|
||||||
FileInputStream fileInputStream = new FileInputStream(commandFile);
|
FileInputStream fileInputStream = new FileInputStream(commandFile);
|
||||||
String fileContent = new String(IOUtils.toByteArray(fileInputStream));
|
String fileContent = new String(IOUtils.toByteArray(fileInputStream));
|
||||||
Assert.assertEquals("[docker-command-execution]\n"
|
Assert.assertEquals("[docker-command-execution]\n"
|
||||||
+ " docker-command=volume\n" + " sub-command=create\n"
|
+ " docker-command=volume\n" + " driver=local\n"
|
||||||
+ " volume=volume1\n", fileContent);
|
+ " sub-command=create\n" + " volume=volume1\n", fileContent);
|
||||||
|
fileInputStream.close();
|
||||||
|
|
||||||
|
op = allCaptures.get(1);
|
||||||
|
Assert.assertEquals(PrivilegedOperation.OperationType
|
||||||
|
.RUN_DOCKER_CMD, op.getOperationType());
|
||||||
|
|
||||||
|
commandFile = new File(StringUtils.join(",", op.getArguments()));
|
||||||
|
fileInputStream = new FileInputStream(commandFile);
|
||||||
|
fileContent = new String(IOUtils.toByteArray(fileInputStream));
|
||||||
|
Assert.assertEquals("[docker-command-execution]\n"
|
||||||
|
+ " docker-command=volume\n" + " format={{.Name}},{{.Driver}}\n"
|
||||||
|
+ " sub-command=ls\n", fileContent);
|
||||||
|
fileInputStream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private static class MockDockerCommandPlugin implements DockerCommandPlugin {
|
||||||
public void testDockerCommandPlugin() throws Exception {
|
private final String volume;
|
||||||
DockerLinuxContainerRuntime runtime =
|
private final String driver;
|
||||||
new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler);
|
|
||||||
|
|
||||||
Context nmContext = mock(Context.class);
|
public MockDockerCommandPlugin(String volume, String driver) {
|
||||||
ResourcePluginManager rpm = mock(ResourcePluginManager.class);
|
this.volume = volume;
|
||||||
Map<String, ResourcePlugin> pluginsMap = new HashMap<>();
|
this.driver = driver;
|
||||||
ResourcePlugin plugin1 = mock(ResourcePlugin.class);
|
}
|
||||||
|
|
||||||
// Create the docker command plugin logic, which will set volume driver
|
|
||||||
DockerCommandPlugin dockerCommandPlugin = new DockerCommandPlugin() {
|
|
||||||
@Override
|
@Override
|
||||||
public void updateDockerRunCommand(DockerRunCommand dockerRunCommand,
|
public void updateDockerRunCommand(DockerRunCommand dockerRunCommand,
|
||||||
Container container) throws ContainerExecutionException {
|
Container container) throws ContainerExecutionException {
|
||||||
|
@ -1344,15 +1356,123 @@ public class TestDockerContainerRuntime {
|
||||||
@Override
|
@Override
|
||||||
public DockerVolumeCommand getCreateDockerVolumeCommand(Container container)
|
public DockerVolumeCommand getCreateDockerVolumeCommand(Container container)
|
||||||
throws ContainerExecutionException {
|
throws ContainerExecutionException {
|
||||||
return new DockerVolumeCommand("create").setVolumeName("volume1");
|
return new DockerVolumeCommand("create").setVolumeName(volume)
|
||||||
|
.setDriverName(driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DockerVolumeCommand getCleanupDockerVolumesCommand(Container container)
|
public DockerVolumeCommand getCleanupDockerVolumesCommand(
|
||||||
throws ContainerExecutionException {
|
Container container) throws ContainerExecutionException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
private void testDockerCommandPluginWithVolumesOutput(
|
||||||
|
String dockerVolumeListOutput, boolean expectFail)
|
||||||
|
throws PrivilegedOperationException, ContainerExecutionException,
|
||||||
|
IOException {
|
||||||
|
mockExecutor = Mockito
|
||||||
|
.mock(PrivilegedOperationExecutor.class);
|
||||||
|
|
||||||
|
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
|
||||||
|
mockExecutor, mockCGroupsHandler);
|
||||||
|
when(mockExecutor
|
||||||
|
.executePrivilegedOperation(anyList(), any(PrivilegedOperation.class),
|
||||||
|
any(File.class), anyMap(), anyBoolean(), anyBoolean())).thenReturn(
|
||||||
|
null);
|
||||||
|
when(mockExecutor
|
||||||
|
.executePrivilegedOperation(anyList(), any(PrivilegedOperation.class),
|
||||||
|
any(File.class), anyMap(), anyBoolean(), anyBoolean())).thenReturn(
|
||||||
|
dockerVolumeListOutput);
|
||||||
|
|
||||||
|
Context nmContext = mock(Context.class);
|
||||||
|
ResourcePluginManager rpm = mock(ResourcePluginManager.class);
|
||||||
|
Map<String, ResourcePlugin> pluginsMap = new HashMap<>();
|
||||||
|
ResourcePlugin plugin1 = mock(ResourcePlugin.class);
|
||||||
|
|
||||||
|
// Create the docker command plugin logic, which will set volume driver
|
||||||
|
DockerCommandPlugin dockerCommandPlugin = new MockDockerCommandPlugin(
|
||||||
|
"volume1", "local");
|
||||||
|
|
||||||
|
when(plugin1.getDockerCommandPluginInstance()).thenReturn(
|
||||||
|
dockerCommandPlugin);
|
||||||
|
ResourcePlugin plugin2 = mock(ResourcePlugin.class);
|
||||||
|
pluginsMap.put("plugin1", plugin1);
|
||||||
|
pluginsMap.put("plugin2", plugin2);
|
||||||
|
|
||||||
|
when(rpm.getNameToPlugins()).thenReturn(pluginsMap);
|
||||||
|
|
||||||
|
when(nmContext.getResourcePluginManager()).thenReturn(rpm);
|
||||||
|
|
||||||
|
runtime.initialize(conf, nmContext);
|
||||||
|
|
||||||
|
ContainerRuntimeContext containerRuntimeContext = builder.build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
runtime.prepareContainer(containerRuntimeContext);
|
||||||
|
|
||||||
|
checkVolumeCreateCommand();
|
||||||
|
|
||||||
|
runtime.launchContainer(containerRuntimeContext);
|
||||||
|
} catch (ContainerExecutionException e) {
|
||||||
|
if (expectFail) {
|
||||||
|
// Expected
|
||||||
|
return;
|
||||||
|
} else{
|
||||||
|
Assert.fail("Should successfully prepareContainers" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (expectFail) {
|
||||||
|
Assert.fail(
|
||||||
|
"Should fail because output is illegal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDockerCommandPluginCheckVolumeAfterCreation()
|
||||||
|
throws Exception {
|
||||||
|
// For following tests, we expect to have volume1,local in output
|
||||||
|
|
||||||
|
// Failure cases
|
||||||
|
testDockerCommandPluginWithVolumesOutput("", true);
|
||||||
|
testDockerCommandPluginWithVolumesOutput("volume1", true);
|
||||||
|
testDockerCommandPluginWithVolumesOutput("local", true);
|
||||||
|
testDockerCommandPluginWithVolumesOutput("volume2,local", true);
|
||||||
|
testDockerCommandPluginWithVolumesOutput("volum1,something", true);
|
||||||
|
testDockerCommandPluginWithVolumesOutput("volum1,something\nvolum2,local",
|
||||||
|
true);
|
||||||
|
|
||||||
|
// Success case
|
||||||
|
testDockerCommandPluginWithVolumesOutput("volume1,local\n", false);
|
||||||
|
testDockerCommandPluginWithVolumesOutput(
|
||||||
|
"volume_xyz,nvidia\nvolume1,local\n\n", false);
|
||||||
|
testDockerCommandPluginWithVolumesOutput(" volume1, local \n", false);
|
||||||
|
testDockerCommandPluginWithVolumesOutput(
|
||||||
|
"volume_xyz,\tnvidia\n volume1,\tlocal\n\n", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDockerCommandPlugin() throws Exception {
|
||||||
|
DockerLinuxContainerRuntime runtime =
|
||||||
|
new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler);
|
||||||
|
when(mockExecutor
|
||||||
|
.executePrivilegedOperation(anyList(), any(PrivilegedOperation.class),
|
||||||
|
any(File.class), anyMap(), anyBoolean(), anyBoolean())).thenReturn(
|
||||||
|
null);
|
||||||
|
when(mockExecutor
|
||||||
|
.executePrivilegedOperation(anyList(), any(PrivilegedOperation.class),
|
||||||
|
any(File.class), anyMap(), anyBoolean(), anyBoolean())).thenReturn(
|
||||||
|
"volume1,local");
|
||||||
|
|
||||||
|
Context nmContext = mock(Context.class);
|
||||||
|
ResourcePluginManager rpm = mock(ResourcePluginManager.class);
|
||||||
|
Map<String, ResourcePlugin> pluginsMap = new HashMap<>();
|
||||||
|
ResourcePlugin plugin1 = mock(ResourcePlugin.class);
|
||||||
|
|
||||||
|
// Create the docker command plugin logic, which will set volume driver
|
||||||
|
DockerCommandPlugin dockerCommandPlugin = new MockDockerCommandPlugin(
|
||||||
|
"volume1", "local");
|
||||||
|
|
||||||
when(plugin1.getDockerCommandPluginInstance()).thenReturn(
|
when(plugin1.getDockerCommandPluginInstance()).thenReturn(
|
||||||
dockerCommandPlugin);
|
dockerCommandPlugin);
|
||||||
|
|
Loading…
Reference in New Issue