[DATALAB-1895] Sync up DataLab instance statuses with cloud statuses
diff --git a/services/datalab-model/src/main/java/com/epam/datalab/dto/UserEnvironmentResources.java b/services/datalab-model/src/main/java/com/epam/datalab/dto/UserEnvironmentResources.java
index 6fc6319..3c74d45 100644
--- a/services/datalab-model/src/main/java/com/epam/datalab/dto/UserEnvironmentResources.java
+++ b/services/datalab-model/src/main/java/com/epam/datalab/dto/UserEnvironmentResources.java
@@ -22,7 +22,9 @@
 import com.epam.datalab.dto.status.EnvResourceList;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects.ToStringHelper;
+import lombok.EqualsAndHashCode;
 
+@EqualsAndHashCode
 public class UserEnvironmentResources extends ResourceSysBaseDTO<UserEnvironmentResources> {
     @JsonProperty("edge_list_resources")
     private EnvResourceList resourceList;
diff --git a/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResource.java b/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResource.java
index f18ebe9..10b90ac 100644
--- a/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResource.java
+++ b/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResource.java
@@ -25,6 +25,7 @@
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
+import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
 
 import java.time.LocalDateTime;
@@ -33,6 +34,7 @@
  * Describe the resource (host, cluster, storage) for check status in Cloud.
  */
 @NoArgsConstructor
+@EqualsAndHashCode
 public class EnvResource {
     @JsonProperty
     private String id;
@@ -141,15 +143,39 @@
         return this;
     }
 
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public EnvResource withProject(String project) {
+        setProject(project);
+        return this;
+    }
+
     public String getEndpoint() {
         return endpoint;
     }
 
+    public void setEndpoint(String endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    public EnvResource withEndpoint(String endpoint) {
+        setEndpoint(endpoint);
+        return this;
+    }
+
     public ToStringHelper toStringHelper(Object self) {
         return MoreObjects.toStringHelper(self)
                 .add("id", id)
                 .add("status", status)
                 .add("name", name)
+                .add("project", project)
+                .add("endpoint", endpoint)
                 .add("resourceType", resourceType)
                 .add("lastActivity", lastActivity);
     }
diff --git a/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResourceList.java b/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResourceList.java
index 0a3d292..018e736 100644
--- a/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResourceList.java
+++ b/services/datalab-model/src/main/java/com/epam/datalab/dto/status/EnvResourceList.java
@@ -22,12 +22,14 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
+import lombok.EqualsAndHashCode;
 
 import java.util.List;
 
 /**
  * Describe the lists of resources (host, cluster, storage) for check status in Cloud.
  */
+@EqualsAndHashCode
 public class EnvResourceList {
     @JsonProperty("host")
     private List<EnvResource> hostList;
diff --git a/services/provisioning-service/pom.xml b/services/provisioning-service/pom.xml
index 055bbe7..eda6624 100644
--- a/services/provisioning-service/pom.xml
+++ b/services/provisioning-service/pom.xml
@@ -127,6 +127,11 @@
             <version>${commons-fileupload.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.4</version>
+        </dependency>
+        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <version>${org.mockito.version}</version>
diff --git a/services/provisioning-service/src/main/java/com/epam/datalab/backendapi/core/response/handlers/ResourcesStatusCallbackHandler.java b/services/provisioning-service/src/main/java/com/epam/datalab/backendapi/core/response/handlers/ResourcesStatusCallbackHandler.java
index 9ca477b..347d650 100644
--- a/services/provisioning-service/src/main/java/com/epam/datalab/backendapi/core/response/handlers/ResourcesStatusCallbackHandler.java
+++ b/services/provisioning-service/src/main/java/com/epam/datalab/backendapi/core/response/handlers/ResourcesStatusCallbackHandler.java
@@ -21,6 +21,7 @@
 package com.epam.datalab.backendapi.core.response.handlers;
 
 import com.epam.datalab.backendapi.core.commands.DockerAction;
+import com.epam.datalab.dto.status.EnvResource;
 import com.epam.datalab.dto.status.EnvResourceList;
 import com.epam.datalab.dto.status.EnvStatusDTO;
 import com.epam.datalab.exceptions.DatalabException;
@@ -30,10 +31,15 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.JsonNode;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 
 import java.io.IOException;
 import java.time.Instant;
+import java.util.Collections;
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static com.epam.datalab.rest.contracts.ApiCallbacks.INFRASTRUCTURE;
 import static com.epam.datalab.rest.contracts.ApiCallbacks.STATUS_URI;
@@ -41,14 +47,13 @@
 @Slf4j
 public class ResourcesStatusCallbackHandler extends ResourceCallbackHandler<EnvStatusDTO> {
 
-    private EnvResourceList datalabResourceList;
+    private Map<String, EnvResource> datalabHostResources;
 
     @JsonCreator
-    public ResourcesStatusCallbackHandler(
-            @JacksonInject RESTService selfService, @JsonProperty("action") DockerAction action, @JsonProperty("uuid") String uuid,
-            @JsonProperty("user") String user, EnvResourceList resourceList) {
+    public ResourcesStatusCallbackHandler(@JacksonInject RESTService selfService, @JsonProperty("action") DockerAction action,
+                                          @JsonProperty("uuid") String uuid, @JsonProperty("user") String user, EnvResourceList resourceList) {
         super(selfService, user, uuid, action);
-        this.datalabResourceList = resourceList;
+        this.datalabHostResources = getEnvResources(resourceList.getHostList());
     }
 
     @Override
@@ -64,8 +69,15 @@
             throw new DatalabException("Docker response for UUID " + getUUID() + " not valid: " + e.getLocalizedMessage(), e);
         }
 
+        EnvResourceList envResourceList = new EnvResourceList();
+        if (CollectionUtils.isNotEmpty(cloudResourceList.getHostList())) {
+            envResourceList.withHostList(getChangedEnvResources(cloudResourceList.getHostList()));
+        } else {
+            envResourceList.withHostList(Collections.emptyList());
+        }
+
         baseStatus
-                .withResourceList(cloudResourceList)
+                .withResourceList(envResourceList)
                 .withUptime(Date.from(Instant.now()));
 
         log.trace("Inner status {}", baseStatus);
@@ -93,4 +105,19 @@
     public void handleError(String errorMessage) {
         // Nothing action for status response
     }
+
+    private List<EnvResource> getChangedEnvResources(List<EnvResource> envResources) {
+        return envResources
+                .stream()
+                .filter(e -> !e.getStatus().equals(datalabHostResources.get(e.getId()).getStatus()))
+                .map(e -> datalabHostResources.get(e.getId())
+                        .withStatus(e.getStatus()))
+                .collect(Collectors.toList());
+    }
+
+    private Map<String, EnvResource> getEnvResources(List<EnvResource> envResources) {
+        return envResources
+                .stream()
+                .collect(Collectors.toMap(EnvResource::getId, e -> e));
+    }
 }
diff --git a/services/provisioning-service/src/main/resources/mock_response/aws/notebook_status.json b/services/provisioning-service/src/main/resources/mock_response/aws/notebook_status.json
index 7ecad18..4ede40b 100644
--- a/services/provisioning-service/src/main/resources/mock_response/aws/notebook_status.json
+++ b/services/provisioning-service/src/main/resources/mock_response/aws/notebook_status.json
@@ -1,10 +1,9 @@
 {
   "status": "ok",
   "response": {
-    "result": ${
-  LIST_RESOURCES
-},
-"log": "/var/log/datalab/status/status_${EDGE_USER_NAME}_${REQUEST_ID}.log"
-},
+    "result": {
+    },
+    "log": "/var/log/datalab/status/status_${EDGE_USER_NAME}_${REQUEST_ID}.log"
+  },
 "request_id": "${REQUEST_ID}"
 }
\ No newline at end of file
diff --git a/services/provisioning-service/src/main/resources/mock_response/azure/notebook_status.json b/services/provisioning-service/src/main/resources/mock_response/azure/notebook_status.json
index 7ecad18..5b9d881 100644
--- a/services/provisioning-service/src/main/resources/mock_response/azure/notebook_status.json
+++ b/services/provisioning-service/src/main/resources/mock_response/azure/notebook_status.json
@@ -1,10 +1,9 @@
 {
   "status": "ok",
   "response": {
-    "result": ${
-  LIST_RESOURCES
-},
-"log": "/var/log/datalab/status/status_${EDGE_USER_NAME}_${REQUEST_ID}.log"
-},
-"request_id": "${REQUEST_ID}"
+    "result": {
+    },
+    "log": "/var/log/datalab/status/status_${EDGE_USER_NAME}_${REQUEST_ID}.log"
+  },
+  "request_id": "${REQUEST_ID}"
 }
\ No newline at end of file
diff --git a/services/provisioning-service/src/main/resources/mock_response/gcp/notebook_status.json b/services/provisioning-service/src/main/resources/mock_response/gcp/notebook_status.json
index 7ecad18..dc74f4f 100644
--- a/services/provisioning-service/src/main/resources/mock_response/gcp/notebook_status.json
+++ b/services/provisioning-service/src/main/resources/mock_response/gcp/notebook_status.json
@@ -1,10 +1,8 @@
 {
   "status": "ok",
   "response": {
-    "result": ${
-  LIST_RESOURCES
-},
-"log": "/var/log/datalab/status/status_${EDGE_USER_NAME}_${REQUEST_ID}.log"
-},
-"request_id": "${REQUEST_ID}"
+    "result": {},
+    "log": "/var/log/datalab/status/status_${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/datalab/backendapi/dao/ComputationalDAO.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ComputationalDAO.java
index 50c7a02..ef0203c 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ComputationalDAO.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ComputationalDAO.java
@@ -76,6 +76,7 @@
     static final String COMPUTATIONAL_NAME = "computational_name";
     static final String COMPUTATIONAL_ID = "computational_id";
     static final String PROJECT = "project";
+    static final String ENDPOINT = "endpoint";
 
     static final String IMAGE = "image";
     private static final String COMPUTATIONAL_URL = "computational_url";
@@ -400,4 +401,11 @@
                 set(computationalFieldFilter(COMPUTATIONAL_LAST_ACTIVITY),
                         Date.from(lastActivity.atZone(ZoneId.systemDefault()).toInstant())));
     }
+
+    public void updateComputeStatus(String project, String endpoint, String computeName, String instanceId, UserInstanceStatus status) {
+        updateOne(USER_INSTANCES,
+                and(eq(PROJECT, project), eq(ENDPOINT, endpoint), eq(COMPUTATIONAL_RESOURCES + "." + INSTANCE_ID, instanceId),
+                        eq(COMPUTATIONAL_RESOURCES + "." + COMPUTATIONAL_NAME, computeName)),
+                set(computationalFieldFilter(STATUS), status.toString()));
+    }
 }
\ No newline at end of file
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ExploratoryDAO.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ExploratoryDAO.java
index 0657107..b925d81 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ExploratoryDAO.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ExploratoryDAO.java
@@ -364,6 +364,12 @@
                 set(STATUS, newStatus.toString()));
     }
 
+    public UpdateResult updateExploratoryStatus(String project, String endpoint, String name, String instanceId, UserInstanceStatus status) {
+        return updateOne(USER_INSTANCES,
+                and(eq(ENDPOINT, endpoint), eq(PROJECT, project), eq(EXPLORATORY_NAME, name), eq(INSTANCE_ID, instanceId)),
+                set(STATUS, status.toString()));
+    }
+
     /**
      * Updates the scheduler's data for exploratory in Mongo database.
      *
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/callback/EnvironmentStatusCallback.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/callback/EnvironmentStatusCallback.java
index 7775164..c8caa0c 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/callback/EnvironmentStatusCallback.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/callback/EnvironmentStatusCallback.java
@@ -21,7 +21,10 @@
 
 import com.epam.datalab.backendapi.dao.EnvDAO;
 import com.epam.datalab.backendapi.domain.RequestId;
+import com.epam.datalab.backendapi.service.EnvironmentService;
+import com.epam.datalab.dto.UserInstanceStatus;
 import com.epam.datalab.dto.status.EnvStatusDTO;
+import com.epam.datalab.exceptions.DatalabException;
 import com.epam.datalab.rest.contracts.ApiCallbacks;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
@@ -39,10 +42,16 @@
 @Slf4j
 public class EnvironmentStatusCallback {
 
+    private final EnvDAO envDAO;
+    private final RequestId requestId;
+    private final EnvironmentService environmentService;
+
     @Inject
-    private EnvDAO envDAO;
-    @Inject
-    private RequestId requestId;
+    public EnvironmentStatusCallback(EnvDAO envDAO, RequestId requestId, EnvironmentService environmentService) {
+        this.envDAO = envDAO;
+        this.requestId = requestId;
+        this.environmentService = environmentService;
+    }
 
     /**
      * Updates the status of the resources for user.
@@ -53,18 +62,17 @@
     @POST
     @Path(ApiCallbacks.STATUS_URI)
     public Response status(EnvStatusDTO dto) {
-        log.info("EnvStatusDTO__ {} ", dto);
-//        log.trace("Updating the status of resources for user {}: {}", dto.getUser(), dto);
-//        requestId.checkAndRemove(dto.getRequestId());
-//        try {
-//            if (UserInstanceStatus.FAILED == UserInstanceStatus.of(dto.getStatus())) {
-//                log.warn("Request for the status of resources for user {} fails: {}", dto.getUser(), dto.getErrorMessage());
-//            } else {
-//                envDAO.updateEnvStatus(dto.getUser(), null, dto.getResourceList());
-//            }
-//        } catch (DatalabException e) {
-//            log.warn("Could not update status of resources for user {}: {}", dto.getUser(), e.getLocalizedMessage(), e);
-//        }
+        requestId.checkAndRemove(dto.getRequestId());
+        log.info("Updating statuses of following resources {} ", dto.getResourceList());
+        try {
+            if (UserInstanceStatus.FAILED == UserInstanceStatus.of(dto.getStatus())) {
+                log.warn("Request for the status of resources for user {} fails: {}", dto.getUser(), dto.getErrorMessage());
+            } else {
+                environmentService.updateEnvironmentStatuses(dto.getResourceList());
+            }
+        } catch (DatalabException e) {
+            log.warn("Could not update status of resources for user {}: {}", dto.getUser(), e.getLocalizedMessage(), e);
+        }
         return Response.ok().build();
     }
 }
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/schedulers/CheckInfrastructureStatusScheduler.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/schedulers/CheckInfrastructureStatusScheduler.java
index 55caf85..de56486 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/schedulers/CheckInfrastructureStatusScheduler.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/schedulers/CheckInfrastructureStatusScheduler.java
@@ -23,6 +23,7 @@
 import com.epam.datalab.backendapi.dao.ExploratoryDAO;
 import com.epam.datalab.backendapi.domain.EndpointDTO;
 import com.epam.datalab.backendapi.domain.ProjectDTO;
+import com.epam.datalab.backendapi.domain.ProjectEndpointDTO;
 import com.epam.datalab.backendapi.schedulers.internal.Scheduled;
 import com.epam.datalab.backendapi.service.EndpointService;
 import com.epam.datalab.backendapi.service.InfrastructureInfoService;
@@ -50,6 +51,7 @@
 public class CheckInfrastructureStatusScheduler implements Job {
 
 	private static final List<UserInstanceStatus> statusesToCheck = Arrays.asList(UserInstanceStatus.RUNNING, UserInstanceStatus.STOPPED);
+
 	private final InfrastructureInfoService infrastructureInfoService;
 	private final SecurityService securityService;
 	private final EndpointService endpointService;
@@ -98,6 +100,8 @@
 				.map(r -> new EnvResource()
 						.withId(r.getInstanceId())
 						.withName(r.getComputationalName())
+						.withProject(userInstanceDTO.getProject())
+						.withEndpoint(userInstanceDTO.getEndpoint())
 						.withStatus(r.getStatus())
 						.withResourceType(ResourceType.COMPUTATIONAL))
 				.collect(Collectors.toList());
@@ -105,6 +109,8 @@
 		instances.add(new EnvResource()
 				.withId(userInstanceDTO.getInstanceId())
 				.withName(userInstanceDTO.getExploratoryName())
+				.withProject(userInstanceDTO.getProject())
+				.withEndpoint(userInstanceDTO.getEndpoint())
 				.withStatus(userInstanceDTO.getStatus())
 				.withResourceType(ResourceType.EXPLORATORY));
 
@@ -114,14 +120,25 @@
 	private List<EnvResource> getEdgeInstances(String endpoint) {
 		return projectService.getProjectsByEndpoint(endpoint)
 				.stream()
-				.map(ProjectDTO::getEndpoints)
+				.collect(Collectors.toMap(ProjectDTO::getName, ProjectDTO::getEndpoints))
+				.entrySet()
+				.stream()
+				.map(entry -> getEdgeInstances(endpoint, entry))
 				.flatMap(Collection::stream)
+				.collect(Collectors.toList());
+	}
+
+	private List<EnvResource> getEdgeInstances(String endpoint, Map.Entry<String, List<ProjectEndpointDTO>> entry) {
+		return entry.getValue()
+				.stream()
 				.filter(e -> statusesToCheck.contains(e.getStatus()))
 				.filter(e -> e.getName().equals(endpoint))
 				.filter(e -> Objects.nonNull(e.getEdgeInfo()))
 				.map(e -> new EnvResource()
 						.withId(e.getEdgeInfo().getInstanceId())
 						.withName(e.getName())
+						.withProject(entry.getKey())
+						.withEndpoint(endpoint)
 						.withStatus(e.getStatus().toString())
 						.withResourceType(ResourceType.EDGE)
 				)
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ComputationalService.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ComputationalService.java
index a930d9f..63e6544 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ComputationalService.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ComputationalService.java
@@ -23,6 +23,7 @@
 import com.epam.datalab.backendapi.resources.dto.ComputationalCreateFormDTO;
 import com.epam.datalab.backendapi.resources.dto.ComputationalTemplatesDTO;
 import com.epam.datalab.backendapi.resources.dto.SparkStandaloneClusterCreateForm;
+import com.epam.datalab.dto.UserInstanceStatus;
 import com.epam.datalab.dto.aws.computational.ClusterConfig;
 import com.epam.datalab.dto.computational.UserComputationalResource;
 
@@ -71,4 +72,6 @@
                                                                  String computationalName);
 
     List<ClusterConfig> getClusterConfig(UserInfo userInfo, String project, String exploratoryName, String computationalName);
+
+    void updateAfterStatusCheck(UserInfo systemUser, String project, String endpoint, String name, String instanceID, UserInstanceStatus status, String auditInfo);
 }
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/EnvironmentService.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/EnvironmentService.java
index 549a405..ad9fa3c 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/EnvironmentService.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/EnvironmentService.java
@@ -22,6 +22,7 @@
 import com.epam.datalab.auth.UserInfo;
 import com.epam.datalab.backendapi.resources.dto.UserDTO;
 import com.epam.datalab.backendapi.resources.dto.UserResourceInfo;
+import com.epam.datalab.dto.status.EnvResourceList;
 
 import java.util.List;
 
@@ -43,4 +44,6 @@
     void terminateExploratory(UserInfo userInfo, String user, String project, String exploratoryName);
 
     void terminateComputational(UserInfo userInfo, String user, String project, String exploratoryName, String computationalName);
+
+    void updateEnvironmentStatuses(EnvResourceList resourceList);
 }
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ExploratoryService.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ExploratoryService.java
index f16bcfc..3711c52 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ExploratoryService.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ExploratoryService.java
@@ -59,4 +59,6 @@
     List<ClusterConfig> getClusterConfig(UserInfo user, String project, String exploratoryName);
 
     ExploratoryCreatePopUp getUserInstances(UserInfo user);
+
+    void updateAfterStatusCheck(UserInfo userInfo, String project, String endpoint, String name, String instanceID, UserInstanceStatus status, String auditInfo);
 }
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ProjectService.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ProjectService.java
index 01b9028..4ecd014 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ProjectService.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/ProjectService.java
@@ -23,6 +23,7 @@
 import com.epam.datalab.backendapi.domain.ProjectDTO;
 import com.epam.datalab.backendapi.domain.UpdateProjectBudgetDTO;
 import com.epam.datalab.backendapi.domain.UpdateProjectDTO;
+import com.epam.datalab.dto.UserInstanceStatus;
 
 import java.util.List;
 
@@ -51,13 +52,15 @@
 
     void stop(UserInfo userInfo, String endpoint, String name, String auditInfo);
 
-    void stopWithResources(UserInfo userInfo, List<String> endpoints, String projectName);
+	void stopWithResources(UserInfo userInfo, List<String> endpoints, String projectName);
 
-    void update(UserInfo userInfo, UpdateProjectDTO projectDTO, String projectName);
+	void update(UserInfo userInfo, UpdateProjectDTO projectDTO, String projectName);
 
-    void updateBudget(UserInfo userInfo, List<UpdateProjectBudgetDTO> projects);
+	void updateBudget(UserInfo userInfo, List<UpdateProjectBudgetDTO> projects);
 
-    boolean isAnyProjectAssigned(UserInfo userInfo);
+	boolean isAnyProjectAssigned(UserInfo userInfo);
 
-    boolean checkExploratoriesAndComputationalProgress(String projectName, List<String> endpoints);
+	boolean checkExploratoriesAndComputationalProgress(String projectName, List<String> endpoints);
+
+	void updateAfterStatusCheck(UserInfo userInfo, String project, String endpoint, String instanceID, UserInstanceStatus status, String auditInfo);
 }
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ComputationalServiceImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ComputationalServiceImpl.java
index 9e0e129..245f4c4 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ComputationalServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ComputationalServiceImpl.java
@@ -74,6 +74,7 @@
 import static com.epam.datalab.backendapi.domain.AuditActionEnum.START;
 import static com.epam.datalab.backendapi.domain.AuditActionEnum.STOP;
 import static com.epam.datalab.backendapi.domain.AuditActionEnum.TERMINATE;
+import static com.epam.datalab.backendapi.domain.AuditActionEnum.UPDATE;
 import static com.epam.datalab.backendapi.domain.AuditResourceTypeEnum.COMPUTE;
 import static com.epam.datalab.dto.UserInstanceStatus.CREATING;
 import static com.epam.datalab.dto.UserInstanceStatus.FAILED;
@@ -272,7 +273,6 @@
         } else {
             throw new IllegalStateException(String.format(DATAENGINE_NOT_PRESENT_FORMAT, requiredStatus.toString(), compName, expName));
         }
-
     }
 
     @BudgetLimited
@@ -323,7 +323,6 @@
                 .withStatus(RECONFIGURING.toString())
                 .withUser(userName));
         requestId.put(userName, uuid);
-
     }
 
     /**
@@ -350,6 +349,13 @@
         return computationalDAO.getClusterConfig(userInfo.getName(), project, exploratoryName, computationalName);
     }
 
+    @Audit(action = UPDATE, type = COMPUTE)
+    @Override
+    public void updateAfterStatusCheck(@User UserInfo systemUser, @Project String project, String endpoint, @ResourceName String name, String instanceID,
+                                       UserInstanceStatus status, @Info String auditInfo) {
+        computationalDAO.updateComputeStatus(project, endpoint, name, instanceID, status);
+    }
+
     /**
      * Updates the status of computational resource in database.
      *
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImpl.java
index 628d9b6..aedf269 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImpl.java
@@ -35,6 +35,9 @@
 import com.epam.datalab.backendapi.service.ProjectService;
 import com.epam.datalab.backendapi.service.SecurityService;
 import com.epam.datalab.dto.UserInstanceDTO;
+import com.epam.datalab.dto.UserInstanceStatus;
+import com.epam.datalab.dto.status.EnvResource;
+import com.epam.datalab.dto.status.EnvResourceList;
 import com.epam.datalab.exceptions.ResourceConflictException;
 import com.epam.datalab.model.ResourceEnum;
 import com.google.inject.Inject;
@@ -44,6 +47,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Stream;
 
@@ -61,6 +65,7 @@
 public class EnvironmentServiceImpl implements EnvironmentService {
     private static final String ERROR_MSG_FORMAT = "Can not %s environment because on of user resource is in status CREATING or STARTING";
     private static final String AUDIT_QUOTA_MESSAGE = "Billing quota reached";
+    private static final String AUDIT_UPDATE_STATUS = "Sync up with console status";
     private static final String DATALAB_SYSTEM_USER = "DataLab system user";
 
     private final EnvDAO envDAO;
@@ -167,6 +172,39 @@
         computationalService.terminateComputational(userInfo, user, project, exploratoryName, computationalName, String.format(AUDIT_MESSAGE, exploratoryName));
     }
 
+    @Override
+    public void updateEnvironmentStatuses(EnvResourceList resourceList) {
+        resourceList.getHostList()
+                .forEach(this::updateHostStatuses);
+    }
+
+    private void updateHostStatuses(EnvResource envResource) {
+        final UserInstanceStatus status = UserInstanceStatus.of(envResource.getStatus());
+        if (Objects.nonNull(status)) {
+            UserInfo systemUser = new UserInfo(DATALAB_SYSTEM_USER, null);
+            final String endpoint = envResource.getEndpoint();
+            final String instanceID = envResource.getId();
+            final String name = envResource.getName();
+            final String project = envResource.getProject();
+
+            switch (envResource.getResourceType()) {
+                case EDGE:
+                    projectService.updateAfterStatusCheck(systemUser, project, endpoint, instanceID, status, AUDIT_UPDATE_STATUS);
+                    break;
+                case EXPLORATORY:
+                    exploratoryService.updateAfterStatusCheck(systemUser, project, endpoint, name, instanceID, status, AUDIT_UPDATE_STATUS);
+                    break;
+                case COMPUTATIONAL:
+                    computationalService.updateAfterStatusCheck(systemUser, project, endpoint, name, instanceID, status, AUDIT_UPDATE_STATUS);
+                    break;
+                default:
+                    log.warn("Resource {} has unknown resource type {}", envResource, envResource.getResourceType());
+            }
+        } else {
+            log.warn("Resource {} has unknown status {}", envResource, envResource.getStatus());
+        }
+    }
+
     private UserDTO toUserDTO(String u, UserDTO.Status status) {
         return new UserDTO(u, settingsDAO.getAllowedBudget(u).orElse(null), status);
     }
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ExploratoryServiceImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ExploratoryServiceImpl.java
index 6ef627a..72f0801 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ExploratoryServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ExploratoryServiceImpl.java
@@ -79,6 +79,7 @@
 import static com.epam.datalab.backendapi.domain.AuditActionEnum.START;
 import static com.epam.datalab.backendapi.domain.AuditActionEnum.STOP;
 import static com.epam.datalab.backendapi.domain.AuditActionEnum.TERMINATE;
+import static com.epam.datalab.backendapi.domain.AuditActionEnum.UPDATE;
 import static com.epam.datalab.backendapi.domain.AuditResourceTypeEnum.NOTEBOOK;
 import static com.epam.datalab.dto.UserInstanceStatus.CREATING;
 import static com.epam.datalab.dto.UserInstanceStatus.FAILED;
@@ -271,6 +272,13 @@
         return new ExploratoryCreatePopUp(userProjects, collect);
     }
 
+    @Audit(action = UPDATE, type = NOTEBOOK)
+    @Override
+    public void updateAfterStatusCheck(@User UserInfo userInfo, @Project String project, String endpoint, @ResourceName String name,
+                                       String instanceID, UserInstanceStatus status, @Info String auditInfo) {
+        exploratoryDAO.updateExploratoryStatus(project, endpoint, name, instanceID, status);
+    }
+
     private List<String> getProjectExploratoryNames(ProjectDTO project) {
         return exploratoryDAO.fetchExploratoryFieldsForProject(project.getName()).stream()
                 .map(UserInstanceDTO::getExploratoryName)
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
index efd4088..e0c63d0 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
@@ -68,7 +68,7 @@
     private static final String PERMISSION_UPLOAD = "/api/bucket/upload";
     private static final String PERMISSION_DOWNLOAD = "/api/bucket/download";
     private static final String PERMISSION_DELETE = "/api/bucket/delete";
-    private static final String INFRASTRUCTURE_STAUS = "infrastructure/status";
+    private static final String INFRASTRUCTURE_STATUS = "infrastructure/status";
 
     private final ExploratoryDAO expDAO;
     private final SelfServiceApplicationConfiguration configuration;
@@ -152,7 +152,7 @@
                 .withHostList(hostInstances);
 
         EndpointDTO endpointDTO = endpointService.get(endpoint);
-        String uuid = provisioningService.post(endpointDTO.getUrl() + INFRASTRUCTURE_STAUS, user.getAccessToken(),
+        String uuid = provisioningService.post(endpointDTO.getUrl() + INFRASTRUCTURE_STATUS, user.getAccessToken(),
                 requestBuilder.newInfrastructureStatus(user.getName(), endpointDTO.getCloudProvider(), envResourceList),
                 String.class);
         requestId.put(user.getName(), uuid);
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ProjectServiceImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ProjectServiceImpl.java
index bc66131..1a1974c 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ProjectServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ProjectServiceImpl.java
@@ -283,6 +283,13 @@
                 UserInstanceStatus.TERMINATING).isEmpty();
     }
 
+    @Audit(action = UPDATE, type = EDGE_NODE)
+    @Override
+    public void updateAfterStatusCheck(@User UserInfo userInfo, @Project String project, @ResourceName String endpoint, String instanceID,
+                                       UserInstanceStatus status, @Info String auditInfo) {
+        projectDAO.updateEdgeStatus(project, endpoint, status);
+    }
+
     private void createProjectOnCloud(UserInfo user, ProjectDTO project) {
         try {
             project.getEndpoints().forEach(e -> createEndpoint(user, project, e.getName(), project.getName(), String.format(AUDIT_ADD_EDGE_NODE, e.getName(), project.getName())));
diff --git a/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImplTest.java b/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImplTest.java
index 8127874..3f35e47 100644
--- a/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImplTest.java
+++ b/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/EnvironmentServiceImplTest.java
@@ -34,9 +34,12 @@
 import com.epam.datalab.dto.UserInstanceDTO;
 import com.epam.datalab.dto.UserInstanceStatus;
 import com.epam.datalab.dto.base.edge.EdgeInfo;
+import com.epam.datalab.dto.status.EnvResource;
+import com.epam.datalab.dto.status.EnvResourceList;
 import com.epam.datalab.exceptions.DatalabException;
 import com.epam.datalab.exceptions.ResourceConflictException;
 import com.epam.datalab.model.ResourceEnum;
+import com.epam.datalab.model.ResourceType;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -66,12 +69,14 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 @RunWith(MockitoJUnitRunner.class)
 public class EnvironmentServiceImplTest {
 
     private static final String AUDIT_QUOTA_MESSAGE = "Billing quota reached";
+    private static final String AUDIT_UPDATE_STATUS = "Sync up with console status";
     private static final String AUDIT_MESSAGE = "Notebook name %s";
     private static final String DATALAB_SYSTEM_USER = "DataLab system user";
     private static final String DATALAB_SYSTEM_USER_TOKEN = "token";
@@ -84,6 +89,12 @@
     private static final String ENDPOINT_NAME = "endpointName";
     private static final String SHAPE = "shape";
 
+    private static final String INSTANCE_ID = "instance_id";
+    private static final String NAME = "name";
+    private static final String PROJECT = "project";
+    private static final String ENDPOINT = "endpoint";
+    private static final String STATUS = "running";
+
     @Mock
     private EnvDAO envDAO;
     @Mock
@@ -312,6 +323,45 @@
         verifyNoMoreInteractions(securityService, computationalService);
     }
 
+    @Test
+    public void updateEnvironmentStatuses() {
+        environmentService.updateEnvironmentStatuses(getEnvResourceList());
+
+        verify(projectService).updateAfterStatusCheck(getSystemUser(), PROJECT, ENDPOINT, INSTANCE_ID, UserInstanceStatus.of(STATUS), AUDIT_UPDATE_STATUS);
+        verify(exploratoryService).updateAfterStatusCheck(getSystemUser(), PROJECT, ENDPOINT, NAME, INSTANCE_ID, UserInstanceStatus.of(STATUS), AUDIT_UPDATE_STATUS);
+        verify(computationalService).updateAfterStatusCheck(getSystemUser(), PROJECT, ENDPOINT, NAME, INSTANCE_ID, UserInstanceStatus.of(STATUS), AUDIT_UPDATE_STATUS);
+        verifyNoMoreInteractions(projectService, exploratoryService, computationalService);
+    }
+
+    @Test
+    public void updateEnvironmentStatusesWithUnknownStatus() {
+        EnvResourceList envResourceList = new EnvResourceList().withHostList(Collections.singletonList(new EnvResource().withStatus("unknown status")));
+        environmentService.updateEnvironmentStatuses(envResourceList);
+
+        verifyZeroInteractions(projectService, exploratoryService, computationalService);
+    }
+
+    private UserInfo getSystemUser() {
+        return new UserInfo(DATALAB_SYSTEM_USER, null);
+    }
+
+    private EnvResourceList getEnvResourceList() {
+        List<EnvResource> hostList = Arrays.asList(getEnvResource(ResourceType.EDGE), getEnvResource(ResourceType.EXPLORATORY),
+                getEnvResource(ResourceType.COMPUTATIONAL));
+        return new EnvResourceList()
+                .withHostList(hostList);
+    }
+
+    private EnvResource getEnvResource(ResourceType resourceType) {
+        return new EnvResource()
+                .withId(INSTANCE_ID)
+                .withName(NAME)
+                .withProject(PROJECT)
+                .withEndpoint(ENDPOINT)
+                .withStatus(STATUS)
+                .withResourceType(resourceType);
+    }
+
     private UserResourceInfo getUserResourceInfoEdge() {
         return UserResourceInfo.builder()
                 .resourceType(ResourceEnum.EDGE_NODE)
diff --git a/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImplTest.java b/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImplTest.java
index 56e4533..85f6380 100644
--- a/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImplTest.java
+++ b/services/self-service/src/test/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImplTest.java
@@ -26,13 +26,17 @@
 import com.epam.datalab.backendapi.domain.BillingReportLine;
 import com.epam.datalab.backendapi.domain.ProjectDTO;
 import com.epam.datalab.backendapi.domain.ProjectEndpointDTO;
+import com.epam.datalab.backendapi.domain.RequestId;
 import com.epam.datalab.backendapi.resources.TestBase;
 import com.epam.datalab.backendapi.resources.dto.HealthStatusPageDTO;
 import com.epam.datalab.backendapi.resources.dto.ProjectInfrastructureInfo;
 import com.epam.datalab.backendapi.service.BillingService;
 import com.epam.datalab.backendapi.service.EndpointService;
 import com.epam.datalab.backendapi.service.ProjectService;
+import com.epam.datalab.backendapi.util.RequestBuilder;
+import com.epam.datalab.cloud.CloudProvider;
 import com.epam.datalab.dto.InfrastructureMetaInfoDTO;
+import com.epam.datalab.dto.UserEnvironmentResources;
 import com.epam.datalab.dto.UserInstanceDTO;
 import com.epam.datalab.dto.UserInstanceStatus;
 import com.epam.datalab.dto.aws.edge.EdgeInfoAws;
@@ -41,6 +45,9 @@
 import com.epam.datalab.dto.billing.BillingResourceType;
 import com.epam.datalab.dto.computational.UserComputationalResource;
 import com.epam.datalab.dto.gcp.edge.EdgeInfoGcp;
+import com.epam.datalab.dto.status.EnvResource;
+import com.epam.datalab.dto.status.EnvResourceList;
+import com.epam.datalab.rest.client.RESTService;
 import com.jcabi.manifests.Manifests;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,6 +78,8 @@
     private static final String EXPLORATORY_NAME = "exploratoryName";
     private static final String COMPUTE_NAME = "computeName";
     private static final String CURRENCY = "currency";
+    private static final String UUID = "uuid";
+    private static final String INFRASTRUCTURE_STATUS = "infrastructure/status";
 
     @Mock
     private ExploratoryDAO expDAO;
@@ -82,6 +91,12 @@
     private EndpointService endpointService;
     @Mock
     private BillingService billingService;
+    @Mock
+    private RESTService provisioningService;
+    @Mock
+    private RequestBuilder requestBuilder;
+    @Mock
+    private RequestId requestId;
 
     @InjectMocks
     private InfrastructureInfoServiceImpl infoService;
@@ -196,6 +211,25 @@
         assertEquals("InfrastructureMetaInfoDTO should be equal", getInfrastructureMetaInfoDTO(), actualInfrastructureMetaInfo);
     }
 
+    @Test
+    public void updateInfrastructureStatuses() {
+        List<EnvResource> envResources = Collections.singletonList(new EnvResource().withId("id"));
+        when(endpointService.get(anyString())).thenReturn(getEndpointDTO());
+        when(provisioningService.post(anyString(), anyString(), any(UserEnvironmentResources.class), any())).thenReturn(UUID);
+        when(requestBuilder.newInfrastructureStatus(anyString(), any(CloudProvider.class), any(EnvResourceList.class))).thenReturn(
+                new UserEnvironmentResources());
+
+        infoService.updateInfrastructureStatuses(getUserInfo(), ENDPOINT_NAME, envResources, envResources);
+
+        verify(endpointService).get(ENDPOINT_NAME);
+        verify(requestBuilder).newInfrastructureStatus(USER.toLowerCase(), CloudProvider.AWS, new EnvResourceList()
+                .withHostList(envResources)
+                .withClusterList(envResources));
+        verify(provisioningService).post(ENDPOINT_URL + INFRASTRUCTURE_STATUS, TOKEN, new UserEnvironmentResources(), String.class);
+        verify(requestId).put(USER.toLowerCase(), UUID);
+        verifyNoMoreInteractions(endpointService, provisioningService, requestBuilder, requestId);
+    }
+
     private InfrastructureMetaInfoDTO getInfrastructureMetaInfoDTO() {
         return InfrastructureMetaInfoDTO.builder()
                 .branch("branch")