Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CHE-1489: rework workspaces folder usage to fix Che on some configs #1733

Merged
merged 7 commits into from
Jul 18, 2016
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,44 @@ public class WindowsHostUtils {
public static final String WINDOWS_CHE_HOME_PATH = "\\AppData\\Local\\Eclipse Che";

/**
* Create Che Home directory if not exist on Windows hosts it will be locate in
* Creates Che home folder if not exist on Windows host. Che home folder is located in
* System.getProperty("user.home") + {@link WindowsHostUtils#WINDOWS_CHE_HOME_PATH}
*
* @return Path to Che home dir
* @throws IOException
* @throws IOException if implicit folders creation failed
*/
public static Path ensureCheHomeExist() throws IOException {
return ensureCheHomeExist(true);
}

/**
* Creates Che home folder if not exist on Windows host. Che home folder is located in
* System.getProperty("user.home") + {@link WindowsHostUtils#WINDOWS_CHE_HOME_PATH}
*
* @param allowFoldersCreation
* whether creation of needed directories is allowed
* @return Path to Che home dir
* @throws IOException
* if folders creation failed or needed folder is missing (depends on value of parameter of the method)
*/
public static Path ensureCheHomeExist(boolean allowFoldersCreation) throws IOException {
Path cheHome = Paths.get(System.getProperty("user.home") + WINDOWS_CHE_HOME_PATH);
if (Files.notExists(cheHome)) {
Files.createDirectories(cheHome);
if (allowFoldersCreation) {
Files.createDirectories(cheHome);
} else {
throw new IOException(String.format("Folder %s is missing and its creation is disallowed", cheHome));
}
}
return cheHome;
}

/**
* Returns Che home directory on Windows hosts
*
* @return path to Che home dir
*/
public static Path getCheHome() {
return Paths.get(System.getProperty("user.home") + WINDOWS_CHE_HOME_PATH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import org.eclipse.che.plugin.docker.machine.DockerInstance;
import org.eclipse.che.plugin.docker.machine.DockerInstanceRuntimeInfo;
import org.eclipse.che.plugin.docker.machine.DockerProcess;
import org.eclipse.che.plugin.docker.machine.local.interceptor.AllowOfflineMachineCreationModule;
import org.eclipse.che.plugin.docker.machine.local.provider.CheHostVfsRootDirProvider;
import org.eclipse.che.plugin.docker.machine.node.DockerNode;

/**
Expand Down Expand Up @@ -51,9 +49,6 @@ protected void configure() {
bind(org.eclipse.che.plugin.docker.machine.node.WorkspaceFolderPathProvider.class)
.to(org.eclipse.che.plugin.docker.machine.local.node.provider.LocalWorkspaceFolderPathProvider.class);

bind(String.class).annotatedWith(Names.named("host.workspaces.root"))
.toProvider(CheHostVfsRootDirProvider.class);

bind(org.eclipse.che.plugin.docker.client.DockerRegistryChecker.class).asEagerSingleton();

Multibinder<String> devMachineEnvVars = Multibinder.newSetBinder(binder(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,30 @@
*******************************************************************************/
package org.eclipse.che.plugin.docker.machine.local.node.provider;

import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;

import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.workspace.Workspace;
import org.eclipse.che.api.core.util.SystemInfo;
import org.eclipse.che.api.workspace.server.WorkspaceManager;
import org.eclipse.che.plugin.docker.machine.WindowsHostUtils;
import org.eclipse.che.plugin.docker.machine.node.WorkspaceFolderPathProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static java.lang.String.format;

/**
* Provides path to workspace folder in CHE.
*
Expand All @@ -37,18 +42,17 @@
@Singleton
public class LocalWorkspaceFolderPathProvider implements WorkspaceFolderPathProvider {

private static final Logger LOG = LoggerFactory.getLogger(LocalWorkspaceFolderPathProvider.class);
public static final String ALLOW_FOLDERS_CREATION_ENV_VARIABLE = "CHE_ALLOW_CREATION_WORKSPACE_FOLDERS";
/**
* Value provide path to directory on host machine where will by all created and mount to the
* created workspaces folder that become root of workspace inside machine.
* Inside machine it will point to the directory described by @see che.machine.projects.internal.storage.
* Inside machine it will point to the directory described by {@literal che.machine.projects.internal.storage}.
* <p>
* For example:
* if you set "che.user.workspaces.storage" to the /home/user/che/workspaces after creating new workspace will be created new folder
* /home/user/che/workspaces/{workspaceName} and it will be mount to the dev-machine to "che.machine.projects.internal.storage"
* if you set {@literal che.user.workspaces.storage} to the /home/user/che/workspaces after creating new workspace will be created new folder
* /home/user/che/workspaces/{workspaceName} and it will be mount to the dev-machine to {@literal che.machine.projects.internal.storage}
*/
private final String workspacesMountPoint;

private final String workspacesMountPoint;
private final Provider<WorkspaceManager> workspaceManager;
/**
* this value provide path to projects on local host
Expand All @@ -59,68 +63,101 @@ public class LocalWorkspaceFolderPathProvider implements WorkspaceFolderPathProv
@Named("host.projects.root")
private String hostProjectsFolder;

/**
* If environment variable with name {@link #ALLOW_FOLDERS_CREATION_ENV_VARIABLE} is equal (ignoring case) to
* {@literal false} then this field is set to false. Otherwise it is set to true.
* It is also possible to overwrite with named constant.
*/
@Inject(optional = true)
@Named("che.user.workspaces.storage.create_folders")
private boolean createFolders = true;

@Inject
public LocalWorkspaceFolderPathProvider(@Named("host.workspaces.root") String workspacesMountPoint,
public LocalWorkspaceFolderPathProvider(@Named("che.user.workspaces.storage") String workspacesMountPoint,
Provider<WorkspaceManager> workspaceManager) throws IOException {
this.workspacesMountPoint = workspacesMountPoint;
this.workspacesMountPoint = getWorkspacesRootPath(workspacesMountPoint);
this.workspaceManager = workspaceManager;
checkProps(workspacesMountPoint, hostProjectsFolder);
String allowFoldersCreationEnvVar = System.getenv(ALLOW_FOLDERS_CREATION_ENV_VARIABLE);
if (allowFoldersCreationEnvVar != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this check. Or merge with next by &&
I prefer first variant

if ("false".equalsIgnoreCase(allowFoldersCreationEnvVar)) {
createFolders = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createFolders = Boolean.parseBoolean(allowFoldersCreationEnvVar);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to have this behavior. Prefer opposite.

}
}
}

//used for testing
@VisibleForTesting
protected LocalWorkspaceFolderPathProvider(String workspacesMountPoint,
String projectsFolder,
Provider<WorkspaceManager> workspaceManager) throws IOException {
checkProps(workspacesMountPoint, projectsFolder);
Provider<WorkspaceManager> workspaceManager,
boolean createFolders) throws IOException {
this.workspaceManager = workspaceManager;
this.workspacesMountPoint = workspacesMountPoint;
this.workspacesMountPoint = getWorkspacesRootPath(workspacesMountPoint);
this.hostProjectsFolder = projectsFolder;
this.createFolders = createFolders;
}

private void checkProps(String workspacesFolder, String projectsFolder) throws IOException {
if (workspacesFolder == null && projectsFolder == null) {
throw new IOException(
"Can't mount host file system. Check che.user.workspaces.storage or host.projects.root configuration property.");
@Override
public String getPath(@Assisted("workspace") String workspaceId) throws IOException {
if (hostProjectsFolder != null) {
return hostProjectsFolder;
} else {
Path workspaceFolder = null;
try {
WorkspaceManager workspaceManager = this.workspaceManager.get();
Workspace workspace = workspaceManager.getWorkspace(workspaceId);
String wsName = workspace.getConfig().getName();
workspaceFolder = Paths.get(workspacesMountPoint).resolve(wsName);
if (Files.notExists(workspaceFolder) && createFolders) {
Files.createDirectory(workspaceFolder);
}
return workspaceFolder.toString();
} catch (NotFoundException | ServerException e) {
throw new IOException(e.getMessage());
} catch (AccessDeniedException e) {
throw new IOException(format("Workspace folder '%s' creation failed. Please check permissions of this folder. Cause: %s",
workspaceFolder,
e.getLocalizedMessage()),
e);
}
}
if (workspacesFolder != null) {
ensureExist(workspacesFolder, "che.user.workspaces.storage");
}

@VisibleForTesting
@PostConstruct
void createNeededFolders() throws IOException {
if (SystemInfo.isWindows()) {
final Path cheHome = WindowsHostUtils.ensureCheHomeExist(createFolders);
final Path vfs = cheHome.resolve("vfs");
if (createFolders) {
if (!vfs.toFile().mkdir()) {
Copy link
Contributor

@voievodin voievodin Jul 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to use nested if statement

throw new IOException(format("Can't create folder %s for projects of workspaces", vfs));
}
}
}

if (workspacesMountPoint != null && createFolders) {
ensureExist(workspacesMountPoint, "che.user.workspaces.storage");
}
if (projectsFolder != null) {
ensureExist(projectsFolder, "host.projects.root");
if (hostProjectsFolder != null && createFolders) {
ensureExist(hostProjectsFolder, "host.projects.root");
}
}

private String getWorkspacesRootPath(String configuredPath) throws IOException {
if (SystemInfo.isWindows()) {
Path cheHome = WindowsHostUtils.getCheHome();
return cheHome.resolve("vfs").toString();
}
return configuredPath;
}

private void ensureExist(String path, String prop) throws IOException {
Path folder = Paths.get(path);
if (Files.notExists(folder)) {
Files.createDirectory(folder);
}
if (!Files.isDirectory(folder)) {
throw new IOException(String.format("Projects %s is not directory. Check %s configuration property.", path, prop));
}
}

@Override
public String getPath(@Assisted("workspace") String workspaceId) throws IOException {
if (hostProjectsFolder != null) {
return hostProjectsFolder;
} else {
String wsName;
try {
WorkspaceManager workspaceManager = this.workspaceManager.get();
final Workspace workspace = workspaceManager.getWorkspace(workspaceId);
wsName = workspace.getConfig().getName();
} catch (NotFoundException | ServerException e) {
//should never happens
LOG.error(e.getMessage());
throw new RuntimeException(e.getMessage());
}
Path folder = Paths.get(workspacesMountPoint).resolve(wsName);
if (Files.notExists(folder)) {
Files.createDirectory(folder);
}
return folder.toString();
throw new IOException(format("Projects %s is not directory. Check %s configuration property.", path, prop));
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ protected void configure() {
bindConstant().annotatedWith(Names.named("machine.docker.memory_swap_multiplier")).to(1.0);
bindConstant().annotatedWith(Names.named("che.machine.projects.internal.storage")).to("/tmp");
bindConstant().annotatedWith(Names.named("machine.docker.machine_extra_hosts")).to("");
bindConstant().annotatedWith(Names.named("host.workspaces.root")).to("/tmp");
bindConstant().annotatedWith(Names.named("che.user.workspaces.storage")).to("/tmp");
install(new DockerMachineModule());

install(new AllowOfflineMachineCreationModule());
Expand Down
Loading