You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by bh...@apache.org on 2019/06/25 13:11:46 UTC

[incubator-dlab] 01/05: DLAB-745, 746 introduced edge per project

This is an automated email from the ASF dual-hosted git repository.

bhliva pushed a commit to branch feature/projects
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git

commit 22583969384fe31db44f434b14a3753a91673b4f
Author: bhliva <bo...@epam.com>
AuthorDate: Mon Jun 24 15:17:07 2019 +0300

    DLAB-745, 746 introduced edge per project
---
 .../java/com/epam/dlab/dto/ProjectCreateDTO.java   | 15 ++++++
 .../dlab/dto/base/project/CreateProjectResult.java | 15 ++++++
 .../dlab/dto/base/project/ProjectEdgeInfo.java     | 28 ++++++++++
 .../backendapi/ProvisioningServiceApplication.java |  1 +
 .../core/commands/CommandExecutorMockAsync.java    |  4 +-
 .../response/handlers/ProjectCallbackHandler.java  | 45 +++++++++++++++++
 .../backendapi/modules/ProvisioningDevModule.java  |  3 ++
 .../dlab/backendapi/resources/ProjectResource.java | 31 ++++++++++++
 .../dlab/backendapi/service/ProjectService.java    |  9 ++++
 .../service/impl/ProjectServiceImpl.java           | 59 ++++++++++++++++++++++
 .../mock_response/gcp/project_create.json          | 56 ++++++++++++++++++++
 .../dlab/backendapi/SelfServiceApplication.java    |  4 +-
 .../com/epam/dlab/backendapi/dao/ProjectDAO.java   |  5 ++
 .../epam/dlab/backendapi/dao/ProjectDAOImpl.java   | 21 ++++++++
 .../epam/dlab/backendapi/domain/ProjectDTO.java    | 10 ++++
 .../dlab/backendapi/resources/ProjectResource.java |  5 +-
 .../resources/callback/ProjectCallback.java        | 46 +++++++++++++++++
 .../dlab/backendapi/service/ProjectService.java    |  2 +-
 .../service/impl/ProjectServiceImpl.java           | 34 ++++++++++++-
 .../InfrastructureTemplateServiceBaseTest.java     |  6 +--
 20 files changed, 388 insertions(+), 11 deletions(-)

diff --git a/services/dlab-model/src/main/java/com/epam/dlab/dto/ProjectCreateDTO.java b/services/dlab-model/src/main/java/com/epam/dlab/dto/ProjectCreateDTO.java
new file mode 100644
index 0000000..a5ec693
--- /dev/null
+++ b/services/dlab-model/src/main/java/com/epam/dlab/dto/ProjectCreateDTO.java
@@ -0,0 +1,15 @@
+package com.epam.dlab.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class ProjectCreateDTO extends ResourceBaseDTO<ProjectCreateDTO> {
+	private final String key;
+	@JsonProperty("project_name")
+	private final String name;
+	@JsonProperty("project_tag")
+	private final String tag;
+}
diff --git a/services/dlab-model/src/main/java/com/epam/dlab/dto/base/project/CreateProjectResult.java b/services/dlab-model/src/main/java/com/epam/dlab/dto/base/project/CreateProjectResult.java
new file mode 100644
index 0000000..3059b0e
--- /dev/null
+++ b/services/dlab-model/src/main/java/com/epam/dlab/dto/base/project/CreateProjectResult.java
@@ -0,0 +1,15 @@
+package com.epam.dlab.dto.base.project;
+
+import com.epam.dlab.dto.StatusBaseDTO;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CreateProjectResult extends StatusBaseDTO<CreateProjectResult> {
+	private ProjectEdgeInfo edgeInfo;
+	@JsonProperty("project_name")
+	private String projectName;
+
+}
diff --git a/services/dlab-model/src/main/java/com/epam/dlab/dto/base/project/ProjectEdgeInfo.java b/services/dlab-model/src/main/java/com/epam/dlab/dto/base/project/ProjectEdgeInfo.java
new file mode 100644
index 0000000..0bf1c20
--- /dev/null
+++ b/services/dlab-model/src/main/java/com/epam/dlab/dto/base/project/ProjectEdgeInfo.java
@@ -0,0 +1,28 @@
+package com.epam.dlab.dto.base.project;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ProjectEdgeInfo {
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private String id;
+
+	@JsonProperty("instance_id")
+	private String instanceId;
+
+	@JsonProperty
+	private String hostname;
+
+	@JsonProperty("public_ip")
+	private String publicIp;
+
+	@JsonProperty
+	private String ip;
+
+	@JsonProperty("key_name")
+	private String keyName;
+}
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java
index 4f063c6..2353f2d 100644
--- a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java
@@ -102,6 +102,7 @@ public class ProvisioningServiceApplication extends Application<ProvisioningServ
 		jersey.register(injector.getInstance(BackupResource.class));
 		jersey.register(injector.getInstance(KeyResource.class));
 		jersey.register(injector.getInstance(CallbackHandlerResource.class));
+		jersey.register(injector.getInstance(ProjectResource.class));
 
 	}
 }
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/core/commands/CommandExecutorMockAsync.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/core/commands/CommandExecutorMockAsync.java
index 5af48e3..7277961 100644
--- a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/core/commands/CommandExecutorMockAsync.java
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/core/commands/CommandExecutorMockAsync.java
@@ -294,8 +294,8 @@ public class CommandExecutorMockAsync implements Supplier<Boolean> {
 	private void action(String user, DockerAction action) {
 		String resourceType = parser.getResourceType();
 
-		String prefixFileName = (Lists.newArrayList("edge", "dataengine", "dataengine-service").contains
-				(resourceType) ? resourceType : "notebook") + "_";
+		String prefixFileName = (Lists.newArrayList("project", "edge", "dataengine", "dataengine-service")
+				.contains(resourceType) ? resourceType : "notebook") + "_";
 		String templateFileName = "mock_response/" + cloudProvider.getName() + '/' + prefixFileName +
 				action.toString() + JSON_FILE_ENDING;
 		responseFileName = getAbsolutePath(parser.getResponsePath(), prefixFileName + user + "_" +
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/core/response/handlers/ProjectCallbackHandler.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/core/response/handlers/ProjectCallbackHandler.java
new file mode 100644
index 0000000..6f7f9eb
--- /dev/null
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/core/response/handlers/ProjectCallbackHandler.java
@@ -0,0 +1,45 @@
+package com.epam.dlab.backendapi.core.response.handlers;
+
+import com.epam.dlab.auth.SystemUserInfoService;
+import com.epam.dlab.backendapi.core.commands.DockerAction;
+import com.epam.dlab.dto.UserInstanceStatus;
+import com.epam.dlab.dto.base.project.CreateProjectResult;
+import com.epam.dlab.dto.base.project.ProjectEdgeInfo;
+import com.epam.dlab.exceptions.DlabException;
+import com.epam.dlab.rest.client.RESTService;
+import com.fasterxml.jackson.databind.JsonNode;
+
+import java.io.IOException;
+
+public class ProjectCallbackHandler extends ResourceCallbackHandler<CreateProjectResult> {
+
+
+	private final String callbackUri;
+
+	public ProjectCallbackHandler(SystemUserInfoService systemUserInfoService, RESTService selfService, String user,
+								  String uuid, DockerAction action, String callbackUri) {
+		super(systemUserInfoService, selfService, user, uuid, action);
+		this.callbackUri = callbackUri;
+	}
+
+	@Override
+	protected String getCallbackURI() {
+		return callbackUri;
+	}
+
+	@Override
+	protected CreateProjectResult parseOutResponse(JsonNode resultNode, CreateProjectResult baseStatus) {
+		if (resultNode != null && getAction() == DockerAction.CREATE
+				&& UserInstanceStatus.of(baseStatus.getStatus()) != UserInstanceStatus.FAILED) {
+			try {
+				final ProjectEdgeInfo projectEdgeInfo = mapper.readValue(resultNode.toString(), ProjectEdgeInfo.class);
+				baseStatus.setEdgeInfo(projectEdgeInfo);
+				baseStatus.setProjectName(resultNode.get("project_name").asText());
+			} catch (IOException e) {
+				throw new DlabException("Cannot parse the EDGE info in JSON: " + e.getLocalizedMessage(), e);
+			}
+		}
+
+		return baseStatus;
+	}
+}
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/modules/ProvisioningDevModule.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/modules/ProvisioningDevModule.java
index 3ec1035..9817a65 100644
--- a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/modules/ProvisioningDevModule.java
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/modules/ProvisioningDevModule.java
@@ -31,9 +31,11 @@ import com.epam.dlab.backendapi.core.commands.CommandExecutorMock;
 import com.epam.dlab.backendapi.core.commands.ICommandExecutor;
 import com.epam.dlab.backendapi.core.response.handlers.dao.CallbackHandlerDao;
 import com.epam.dlab.backendapi.core.response.handlers.dao.FileSystemCallbackHandlerDao;
+import com.epam.dlab.backendapi.service.ProjectService;
 import com.epam.dlab.backendapi.service.RestoreCallbackHandlerService;
 import com.epam.dlab.backendapi.service.CheckInactivityService;
 import com.epam.dlab.backendapi.service.impl.CheckInactivityServiceImpl;
+import com.epam.dlab.backendapi.service.impl.ProjectServiceImpl;
 import com.epam.dlab.backendapi.service.impl.RestoreCallbackHandlerServiceImpl;
 import com.epam.dlab.constants.ServiceConsts;
 import com.epam.dlab.mongo.MongoService;
@@ -91,6 +93,7 @@ public class ProvisioningDevModule extends ModuleBase<ProvisioningServiceApplica
 		bind(CallbackHandlerDao.class).to(FileSystemCallbackHandlerDao.class);
 		bind(RestoreCallbackHandlerService.class).to(RestoreCallbackHandlerServiceImpl.class);
 		bind(CheckInactivityService.class).to(CheckInactivityServiceImpl.class);
+		bind(ProjectService.class).to(ProjectServiceImpl.class);
 	}
 
 	/**
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
new file mode 100644
index 0000000..6bb8826
--- /dev/null
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
@@ -0,0 +1,31 @@
+package com.epam.dlab.backendapi.resources;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.dto.ProjectCreateDTO;
+import com.google.inject.Inject;
+import io.dropwizard.auth.Auth;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("infrastructure/project")
+public class ProjectResource {
+	private final ProjectService projectService;
+
+	@Inject
+	public ProjectResource(ProjectService projectService) {
+		this.projectService = projectService;
+	}
+
+	@POST
+	@Consumes(MediaType.APPLICATION_JSON)
+	@Produces(MediaType.APPLICATION_JSON)
+	public Response createProject(@Auth UserInfo userInfo, ProjectCreateDTO dto) {
+		return Response.ok(projectService.create(userInfo, dto)).build();
+	}
+}
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
new file mode 100644
index 0000000..60656f4
--- /dev/null
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
@@ -0,0 +1,9 @@
+package com.epam.dlab.backendapi.service;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.dto.ProjectCreateDTO;
+
+public interface ProjectService {
+
+	String create(UserInfo userInfo, ProjectCreateDTO projectCreateDTO);
+}
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
new file mode 100644
index 0000000..dc6401a
--- /dev/null
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
@@ -0,0 +1,59 @@
+package com.epam.dlab.backendapi.service.impl;
+
+import com.epam.dlab.auth.SystemUserInfoService;
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.ProvisioningServiceApplicationConfiguration;
+import com.epam.dlab.backendapi.core.commands.*;
+import com.epam.dlab.backendapi.core.response.folderlistener.FolderListenerExecutor;
+import com.epam.dlab.backendapi.core.response.handlers.ProjectCallbackHandler;
+import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.dto.ProjectCreateDTO;
+import com.epam.dlab.rest.client.RESTService;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ProjectServiceImpl implements ProjectService {
+	@Inject
+	protected RESTService selfService;
+	@Inject
+	protected SystemUserInfoService systemUserInfoService;
+	@Inject
+	private ProvisioningServiceApplicationConfiguration configuration;
+	@Inject
+	private FolderListenerExecutor folderListenerExecutor;
+	@Inject
+	private ICommandExecutor commandExecutor;
+	@Inject
+	private CommandBuilder commandBuilder;
+
+	@Override
+	public String create(UserInfo userInfo, ProjectCreateDTO dto) {
+		String uuid = DockerCommands.generateUUID();
+
+		folderListenerExecutor.start(configuration.getKeyLoaderDirectory(),
+				configuration.getKeyLoaderPollTimeout(),
+				new ProjectCallbackHandler(systemUserInfoService, selfService, userInfo.getName(), uuid,
+						DockerAction.CREATE, "/api/project/status"));
+
+		RunDockerCommand runDockerCommand = new RunDockerCommand()
+				.withInteractive()
+				.withName(String.join("_", dto.getName(), "project"))
+				.withVolumeForRootKeys(configuration.getKeyDirectory())
+				.withVolumeForResponse(configuration.getKeyLoaderDirectory())
+				.withVolumeForLog(configuration.getDockerLogDirectory(), "project")
+				.withResource("project")
+				.withRequestId(uuid)
+				.withConfKeyName(configuration.getAdminKey())
+				.withImage("docker.dlab-project")
+				.withAction(DockerAction.CREATE);
+
+		try {
+			commandExecutor.executeAsync(userInfo.getName(), uuid, commandBuilder.buildCommand(runDockerCommand, dto));
+		} catch (JsonProcessingException e) {
+			e.printStackTrace();
+		}
+		return uuid;
+	}
+}
diff --git a/services/provisioning-service/src/main/resources/mock_response/gcp/project_create.json b/services/provisioning-service/src/main/resources/mock_response/gcp/project_create.json
new file mode 100644
index 0000000..9f59b6d
--- /dev/null
+++ b/services/provisioning-service/src/main/resources/mock_response/gcp/project_create.json
@@ -0,0 +1,56 @@
+{
+  "status": "ok",
+  "response": {
+    "result": {
+      "tunnel_port": "22",
+      "full_edge_conf": {
+        "edge_service_account_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge",
+        "fw_edge_egress_internal": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge-egress-internal",
+        "dlab_ssh_user": "dlab-user",
+        "ps_role_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-ps",
+        "fw_ps_egress_public": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-ps-egress-public",
+        "private_ip": "10.10.0.3",
+        "fw_ps_ingress": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-ps-ingress",
+        "ssh_key_path": "/root/keys/BDCC-DSS-POC.pem",
+        "zone": "us-west1-a ",
+        "fw_edge_egress_public": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge-egress-public",
+        "ami_name": "/projects/ubuntu-os-cloud/global/images/ubuntu-1604-xenial-v20170721",
+        "edge_role_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge",
+        "private_subnet_prefix": "24",
+        "subnet_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-subnet",
+        "vpc_cidr": "10.10.0.0/16",
+        "key_name": "${CONF_KEY_NAME}",
+        "service_base_name": "${CONF_SERVICE_BASE_NAME}",
+        "static_address_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-ip",
+        "fw_ps_egress_private": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-ps-egress-private",
+        "vpc_name": "${CONF_SERVICE_BASE_NAME}-ssn-vpc",
+        "static_ip": "104.198.5.3",
+        "bucket_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-bucket",
+        "fw_edge_ingress_public": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge-ingress-public",
+        "ps_service_account_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-ps",
+        "firewall_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge-firewall",
+        "region": "us-west1",
+        "fw_common_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-ps",
+        "instance_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge",
+        "user_keyname": "${EDGE_USER_NAME}",
+        "edge_user_name": "${EDGE_USER_NAME}",
+        "private_subnet_cidr": "10.10.16.0/24",
+        "fw_edge_ingress_internal": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-edge-ingress-internal",
+        "vpc_selflink": "https://www.googleapis.com/compute/v1/projects/or2-msq-epmc-dlab-t1iylu/global/networks/${CONF_SERVICE_BASE_NAME}-ssn-vpc",
+        "instance_size": "n1-standard-1",
+        "notebook_firewall_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-nb-firewall"
+      },
+      "key_name": "BDCC-DSS-POC",
+      "hostname": "104.198.5.3",
+      "public_ip": "104.198.5.3",
+      "ip": "10.10.0.3",
+      "Action": "Create new EDGE server",
+      "user_own_bucket_name": "${CONF_SERVICE_BASE_NAME}-${EDGE_USER_NAME}-bucket",
+      "socks_port": "1080",
+      "notebook_subnet": "10.10.16.0/24",
+      "project_name" : "${PROJECT_NAME}"
+    },
+    "log": "/var/log/dlab/edge/edge_${EDGE_USER_NAME}_${REQUEST_ID}.log"
+  },
+  "request_id": "${REQUEST_ID}"
+}
\ No newline at end of file
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
index 8271fb2..8cc143e 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
@@ -100,7 +100,8 @@ public class SelfServiceApplication extends Application<SelfServiceApplicationCo
 
 		/*bootstrap.addBundle(new SwaggerBundle<SelfServiceApplicationConfiguration>() {
 			@Override
-			protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(SelfServiceApplicationConfiguration configuration) {
+			protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(SelfServiceApplicationConfiguration
+			configuration) {
 				return configuration.getSwaggerConfiguration();
 			}
 		});*/
@@ -181,6 +182,7 @@ public class SelfServiceApplication extends Application<SelfServiceApplicationCo
 		jersey.register(injector.getInstance(ApplicationSettingResource.class));
 		jersey.register(injector.getInstance(EndpointResource.class));
 		jersey.register(injector.getInstance(ProjectResource.class));
+		jersey.register(injector.getInstance(ProjectCallback.class));
 		OpenAPI oas = new OpenAPI();
 		Info info = new Info()
 				.title("Hello World API")
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
index 9939bc5..35cfd1b 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
@@ -1,6 +1,7 @@
 package com.epam.dlab.backendapi.dao;
 
 import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.dto.base.project.ProjectEdgeInfo;
 
 import java.util.List;
 import java.util.Optional;
@@ -11,6 +12,10 @@ public interface ProjectDAO {
 
 	void create(ProjectDTO projectDTO);
 
+	void updateStatus(String projectName, ProjectDTO.Status status);
+
+	void updateEdgeInfoAndStatus(String projectName, ProjectEdgeInfo edgeInfo, ProjectDTO.Status status);
+
 	Optional<ProjectDTO> get(String name);
 
 	boolean update(ProjectDTO projectDTO);
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
index 3fd5e6b..c3a6752 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
@@ -1,7 +1,10 @@
 package com.epam.dlab.backendapi.dao;
 
 import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.dto.base.project.ProjectEdgeInfo;
 import com.google.common.collect.Iterables;
+import com.mongodb.BasicDBObject;
+import com.mongodb.client.result.UpdateResult;
 import org.bson.Document;
 import org.bson.conversions.Bson;
 
@@ -16,6 +19,8 @@ public class ProjectDAOImpl extends BaseDAO implements ProjectDAO {
 
 	private static final String PROJECTS_COLLECTION = "Projects";
 	private static final String GROUPS = "groups";
+	private static final String STATUS_FIELD = "status";
+	private static final String EDGE_INFO_FIELD = "edgeInfo";
 
 	@Override
 	public List<ProjectDTO> getProjects() {
@@ -28,6 +33,22 @@ public class ProjectDAOImpl extends BaseDAO implements ProjectDAO {
 	}
 
 	@Override
+	public void updateStatus(String projectName, ProjectDTO.Status status) {
+		updateOne(PROJECTS_COLLECTION, projectCondition(projectName),
+				new Document(SET, new Document(STATUS_FIELD, status.toString())));
+	}
+
+	@Override
+	public void updateEdgeInfoAndStatus(String projectName, ProjectEdgeInfo edgeInfo, ProjectDTO.Status status) {
+		BasicDBObject dbObject = new BasicDBObject();
+		dbObject.put(STATUS_FIELD, status.toString());
+		dbObject.put(EDGE_INFO_FIELD, convertToBson(edgeInfo));
+		final UpdateResult updateResult = updateOne(PROJECTS_COLLECTION, projectCondition(projectName),
+				new Document(SET, dbObject));
+		System.out.println(updateResult);
+	}
+
+	@Override
 	public Optional<ProjectDTO> get(String name) {
 		return findOne(PROJECTS_COLLECTION, projectCondition(name), ProjectDTO.class);
 	}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
index 07b281f..ac47bd8 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
@@ -16,6 +16,16 @@ public class ProjectDTO {
 	@NotNull
 	private final Set<String> groups;
 	@NotNull
+	private final String key;
+	@NotNull
 	private final String tag;
 	private final Integer budget;
+	private final Status status = Status.CREATING;
+
+
+	public enum Status {
+		CREATING,
+		CREATED,
+		FAILED
+	}
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
index 85029dd..36d078c 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
@@ -16,6 +16,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.responses.ApiResponses;
 
 import javax.annotation.security.RolesAllowed;
+import javax.validation.Valid;
 import javax.ws.rs.*;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
@@ -51,8 +52,8 @@ public class ProjectResource {
 	})
 	@POST
 	@Consumes(MediaType.APPLICATION_JSON)
-	public Response createProject(@Parameter(hidden = true) @Auth UserInfo userInfo, ProjectDTO projectDTO) {
-		projectService.create(projectDTO);
+	public Response createProject(@Parameter(hidden = true) @Auth UserInfo userInfo, @Valid ProjectDTO projectDTO) {
+		projectService.create(userInfo, projectDTO);
 		final URI uri = uriInfo.getRequestUriBuilder().path(projectDTO.getName()).build();
 		return Response
 				.ok()
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ProjectCallback.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ProjectCallback.java
new file mode 100644
index 0000000..9807119
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ProjectCallback.java
@@ -0,0 +1,46 @@
+package com.epam.dlab.backendapi.resources.callback;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.dao.ProjectDAO;
+import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.backendapi.domain.RequestId;
+import com.epam.dlab.dto.UserInstanceStatus;
+import com.epam.dlab.dto.base.project.CreateProjectResult;
+import com.google.inject.Inject;
+import io.dropwizard.auth.Auth;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/project/status")
+@Consumes(MediaType.APPLICATION_JSON)
+@Slf4j
+public class ProjectCallback {
+
+	private final ProjectDAO projectDAO;
+	private final RequestId requestId;
+
+	@Inject
+	public ProjectCallback(ProjectDAO projectDAO, RequestId requestId) {
+		this.projectDAO = projectDAO;
+		this.requestId = requestId;
+	}
+
+
+	@POST
+	public Response updateProjectStatus(@Auth UserInfo userInfo, CreateProjectResult projectResult) {
+		requestId.checkAndRemove(projectResult.getRequestId());
+		if (UserInstanceStatus.of(projectResult.getStatus()) == UserInstanceStatus.FAILED) {
+			projectDAO.updateStatus(projectResult.getProjectName(), ProjectDTO.Status.FAILED);
+		} else {
+			projectDAO.updateEdgeInfoAndStatus(projectResult.getProjectName(), projectResult.getEdgeInfo(),
+					ProjectDTO.Status.CREATED);
+		}
+		return Response.ok().build();
+	}
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
index bde43b2..03c979c 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
@@ -8,7 +8,7 @@ import java.util.List;
 public interface ProjectService {
 	List<ProjectDTO> getProjects();
 
-	void create(ProjectDTO projectDTO);
+	void create(UserInfo userInfo, ProjectDTO projectDTO);
 
 	ProjectDTO get(String name);
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
index d118844..0343583 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
@@ -4,11 +4,17 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.ProjectDAO;
 import com.epam.dlab.backendapi.dao.UserGroupDao;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.backendapi.domain.RequestId;
 import com.epam.dlab.backendapi.service.EnvironmentService;
 import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.constants.ServiceConsts;
+import com.epam.dlab.dto.ProjectCreateDTO;
 import com.epam.dlab.exceptions.ResourceConflictException;
 import com.epam.dlab.exceptions.ResourceNotFoundException;
+import com.epam.dlab.rest.client.RESTService;
 import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import lombok.extern.slf4j.Slf4j;
 
 import java.util.List;
 import java.util.Set;
@@ -17,18 +23,26 @@ import java.util.function.Supplier;
 import static java.util.stream.Collectors.toSet;
 import static java.util.stream.Stream.concat;
 
+@Slf4j
 public class ProjectServiceImpl implements ProjectService {
 
+	private static final String CREATE_PRJ_API = "infrastructure/project";
 	private final ProjectDAO projectDAO;
 	private final EnvironmentService environmentService;
 	private final UserGroupDao userGroupDao;
+	private final RESTService provisioningService;
+	private final RequestId requestId;
 
 	@Inject
 	public ProjectServiceImpl(ProjectDAO projectDAO, EnvironmentService environmentService,
-							  UserGroupDao userGroupDao) {
+							  UserGroupDao userGroupDao,
+							  @Named(ServiceConsts.PROVISIONING_SERVICE_NAME) RESTService provisioningService,
+							  RequestId requestId) {
 		this.projectDAO = projectDAO;
 		this.environmentService = environmentService;
 		this.userGroupDao = userGroupDao;
+		this.provisioningService = provisioningService;
+		this.requestId = requestId;
 	}
 
 	@Override
@@ -37,9 +51,10 @@ public class ProjectServiceImpl implements ProjectService {
 	}
 
 	@Override
-	public void create(ProjectDTO projectDTO) {
+	public void create(UserInfo user, ProjectDTO projectDTO) {
 		if (!projectDAO.get(projectDTO.getName()).isPresent()) {
 			projectDAO.create(projectDTO);
+			createProjectOnCloud(user, projectDTO);
 		} else {
 			throw new ResourceConflictException("Project with passed name already exist in system");
 		}
@@ -77,6 +92,21 @@ public class ProjectServiceImpl implements ProjectService {
 		return projectDAO.isAnyProjectAssigned(userGroups);
 	}
 
+	private void createProjectOnCloud(UserInfo user, ProjectDTO projectDTO) {
+		try {
+			final ProjectCreateDTO projectDto = ProjectCreateDTO.builder()
+					.key(projectDTO.getKey())
+					.name(projectDTO.getName())
+					.tag(projectDTO.getTag())
+					.build();
+			String uuid = provisioningService.post(CREATE_PRJ_API, user.getAccessToken(), projectDto, String.class);
+			requestId.put(user.getName(), uuid);
+		} catch (Exception e) {
+			log.error("Can not create project due to: {}", e.getMessage());
+			projectDAO.updateStatus(projectDTO.getName(), ProjectDTO.Status.FAILED);
+		}
+	}
+
 	private Supplier<ResourceNotFoundException> projectNotFound() {
 		return () -> new ResourceNotFoundException("Project with passed name not found");
 	}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceBaseTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceBaseTest.java
index b2979fa..834f2f1 100644
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceBaseTest.java
+++ b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceBaseTest.java
@@ -77,7 +77,7 @@ public class InfrastructureTemplateServiceBaseTest {
 		emDto2.setExploratoryEnvironmentShapes(shapes2);
 		List<ExploratoryMetadataDTO> expectedEmdDtoList = Arrays.asList(emDto1, emDto2);
 		when(projectDAO.get(anyString())).thenReturn(Optional.of(new ProjectDTO("project", Collections.emptySet(),
-				Collections.singleton("project"), null, null)));
+				Collections.singleton("project"), null, null, null)));
 		when(provisioningService.get(anyString(), anyString(), any())).thenReturn(expectedEmdDtoList.toArray());
 		when(settingsDAO.getConfOsFamily()).thenReturn("someConfOsFamily");
 
@@ -116,7 +116,7 @@ public class InfrastructureTemplateServiceBaseTest {
 				computationalMetadataDTO
 		);
 		when(projectDAO.get(anyString())).thenReturn(Optional.of(new ProjectDTO("project", Collections.emptySet(),
-				Collections.singleton("project"), null, null)));
+				Collections.singleton("project"), null, null, null)));
 		when(provisioningService.get(anyString(), anyString(), any())).thenReturn(expectedCmdDtoList.toArray(new ComputationalMetadataDTO[]{}));
 
 		List<FullComputationalTemplate> expectedFullCmdDtoList = expectedCmdDtoList.stream()
@@ -158,7 +158,7 @@ public class InfrastructureTemplateServiceBaseTest {
 		List<ComputationalMetadataDTO> expectedCmdDtoList = Collections.singletonList(computationalMetadataDTO);
 		when(provisioningService.get(anyString(), anyString(), any())).thenReturn(expectedCmdDtoList.toArray(new ComputationalMetadataDTO[]{}));
 		when(projectDAO.get(anyString())).thenReturn(Optional.of(new ProjectDTO("project", Collections.emptySet(),
-				Collections.singleton("project"), null, null)));
+				Collections.singleton("project"), null, null,null)));
 
 		UserInfo userInfo = new UserInfo("test", "token");
 		try {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org