You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mr...@apache.org on 2018/09/28 21:20:36 UTC

[ambari] 05/20: AMBARI-21523: DELETE Api for Mpacks (mradhakrishnan)

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

mradhakrishnan pushed a commit to branch AMBARI-24711
in repository https://gitbox.apache.org/repos/asf/ambari.git

commit ab5721cc761c2992c8c238d20b3b48b60ae8437e
Author: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
AuthorDate: Tue Jul 25 10:10:50 2017 -0700

    AMBARI-21523: DELETE Api for Mpacks  (mradhakrishnan)
---
 .../ambari/server/api/services/AmbariMetaInfo.java | 18 +++++++
 .../ambari/server/api/services/MpacksService.java  | 23 ++++++++
 .../controller/AmbariManagementController.java     | 10 ++++
 .../controller/AmbariManagementControllerImpl.java | 18 ++++++-
 .../AbstractControllerResourceProvider.java        |  2 +
 .../internal/AbstractResourceProvider.java         |  2 +-
 .../controller/internal/MpackResourceProvider.java | 61 ++++++++++++++++++++--
 .../apache/ambari/server/mpack/MpackManager.java   | 45 +++++++++++++++-
 .../org/apache/ambari/server/orm/dao/MpackDAO.java |  4 ++
 .../org/apache/ambari/server/orm/dao/StackDAO.java | 25 +++++++++
 .../ambari/server/orm/entities/StackEntity.java    |  1 +
 .../apache/ambari/server/stack/StackManager.java   |  5 ++
 12 files changed, 207 insertions(+), 7 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index ea0c68b..1ea5369 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@ -61,6 +61,9 @@ import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.MetainfoDAO;
 import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.MpackEntity;
+import org.apache.ambari.server.orm.entities.StackEntity;
+import org.apache.ambari.server.stack.StackDirectory;
 import org.apache.ambari.server.stack.StackManager;
 import org.apache.ambari.server.stack.StackManagerFactory;
 import org.apache.ambari.server.stack.upgrade.ConfigUpgradePack;
@@ -1541,4 +1544,19 @@ public class AmbariMetaInfo {
     return commonWidgetsDescriptorFile;
   }
 
+  /***
+   * Remove Mpack from the mpackMap and stackMap which is used to power the Mpack and Stack APIs.
+   * Stack should be removed from stackMap only if it points to the mpack that is being removed.
+   * @param mpackEntity
+   * @param stackEntity
+   * @throws IOException
+   */
+  public void removeMpack(MpackEntity mpackEntity, StackEntity stackEntity) throws IOException {
+
+    boolean stackDelete = mpackManager.removeMpack(mpackEntity, stackEntity);
+
+    if(stackDelete) {
+      stackManager.removeStack(stackEntity);
+    }
+  }
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/MpacksService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/MpacksService.java
index 32dae0f..c69ed01 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/MpacksService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/MpacksService.java
@@ -19,7 +19,10 @@ package org.apache.ambari.server.api.services;
 
 import org.apache.ambari.server.api.resources.ResourceInstance;
 
+
 import org.apache.ambari.server.controller.spi.Resource;
+
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -154,6 +157,26 @@ public class MpacksService extends BaseService {
             createMpackResource(mpackId));
   }
 
+  @DELETE
+  @Path("{mpack_id}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Deletes a selected management pack")
+  @ApiImplicitParams({
+    @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING,
+                  paramType = PARAM_TYPE_QUERY, defaultValue = MpackResourceProvider.ALL_PROPERTIES),
+  })
+  @ApiResponses({
+          @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+          @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_CLUSTER_OR_HOST_NOT_FOUND),
+          @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+          @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+          @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response deleteMpack(String body, @Context HttpHeaders headers, @Context UriInfo ui, @PathParam("mpack_id") String mpackId) {
+    return handleRequest(headers, body, ui, Request.Type.DELETE,
+            createMpackResource(mpackId));
+  }
+
   /**
    * Create an mpack resource instance
    * @param mpackId
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index 74a75b5..78f5f94 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -45,6 +45,8 @@ import org.apache.ambari.server.events.TopologyUpdateEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
 import org.apache.ambari.server.orm.entities.ExtensionLinkEntity;
+import org.apache.ambari.server.orm.entities.MpackEntity;
+import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
@@ -974,5 +976,13 @@ public interface AmbariManagementController {
    */
   ArrayList<Packlet> getPacklets(Long mpackId);
 
+  /***
+   * Remove Mpack from the mpackMap and stackMap which is used to power the Mpack and Stack APIs.
+   * @param mpackEntity
+   * @param stackEntity
+   * @throws IOException
+   */
+  void removeMpack(MpackEntity mpackEntity, StackEntity stackEntity) throws IOException;
+
 }
 
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 9632d47..6d4d090 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -159,9 +159,11 @@ import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.RepoDefinitionEntity;
 import org.apache.ambari.server.orm.entities.RepoOsEntity;
+import org.apache.ambari.server.orm.entities.MpackEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.SettingEntity;
+import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.orm.entities.WidgetEntity;
 import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
 import org.apache.ambari.server.orm.entities.WidgetLayoutUserWidgetEntity;
@@ -591,7 +593,12 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     createHostComponents(requests, false);
   }
 
-  public MpackResponse registerMpack(MpackRequest request) throws IOException, AuthorizationException, ResourceAlreadyExistsException{
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public MpackResponse registerMpack(MpackRequest request)
+    throws IOException, AuthorizationException, ResourceAlreadyExistsException{
     MpackResponse mpackResponse = ambariMetaInfo.registerMpack(request);
     updateStacks();
     return mpackResponse;
@@ -3806,6 +3813,15 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void removeMpack(MpackEntity mpackEntity, StackEntity stackEntity) throws IOException{
+
+    ambariMetaInfo.removeMpack(mpackEntity, stackEntity);
+  }
+
+  /**
    * Get a request response for the given request ids.  Note that this method
    * fully populates a request resource including the set of task sub-resources
    * in the request response.
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 06dbc7b..2ec5b77 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -64,6 +64,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
     this.managementController = managementController;
   }
 
+
+
   public static void init(ResourceProviderFactory factory) {
     resourceProviderFactory = factory;
   }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
index 40e1b2d..21a70ca 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
@@ -68,7 +68,7 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
    */
   private final Set<ResourceProviderObserver> observers = new HashSet<>();
 
-  private static final Logger LOG = LoggerFactory.getLogger(AbstractResourceProvider.class);
+  protected static final Logger LOG = LoggerFactory.getLogger(AbstractResourceProvider.class);
   protected final static String PROPERTIES_ATTRIBUTES_REGEX = "properties_attributes/[a-zA-Z][a-zA-Z._-]*$";
   public static Pattern propertiesAttributesPattern = Pattern.compile(".*/" + PROPERTIES_ATTRIBUTES_REGEX);
 
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MpackResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MpackResourceProvider.java
index f939da7..7366390 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MpackResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/MpackResourceProvider.java
@@ -29,6 +29,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.StaticallyInject;
 import org.apache.ambari.server.api.services.parsers.BodyParseException;
 import org.apache.ambari.server.controller.spi.RequestStatus;
@@ -106,7 +107,7 @@ public class MpackResourceProvider extends AbstractControllerResourceProvider {
   }
 
   MpackResourceProvider(AmbariManagementController controller) {
-    super(PROPERTY_IDS, KEY_PROPERTY_IDS, controller);
+    super(Resource.Type.Mpack, PROPERTY_IDS, KEY_PROPERTY_IDS, controller);
   }
 
   @Override
@@ -187,8 +188,8 @@ public class MpackResourceProvider extends AbstractControllerResourceProvider {
         resource.setProperty(REGISTRY_ID, entity.getRegistryId());
         results.add(resource);
       }
-    } //Fetch a particular mpack based on id
-    else {
+    } else {
+      // Fetch a particular mpack based on id
       Map<String, Object> propertyMap = new HashMap<>(PredicateHelper.getProperties(predicate));
       if (propertyMap.containsKey(STACK_NAME_PROPERTY_ID) && propertyMap.containsKey(STACK_VERSION_PROPERTY_ID)) {
         String stackName = (String) propertyMap.get(STACK_NAME_PROPERTY_ID);
@@ -237,5 +238,59 @@ public class MpackResourceProvider extends AbstractControllerResourceProvider {
     return results;
   }
 
+  @Override
+  protected RequestStatus deleteResourcesAuthorized(final Request request, Predicate predicate)
+          throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    final Long mpackId;
+    Map<String, Object> propertyMap = new HashMap<>(PredicateHelper.getProperties(predicate));
+    DeleteStatusMetaData deleteStatusMetaData = null;
+
+    //Allow deleting mpack only if there are no cluster services deploying using this mpack. Support deleting mpacks only if no cluster has been deployed
+    // (i.e. you should be able to delete an mpack during install wizard only).
+    //Todo : Relax the rule
+    if (getManagementController().getClusters().getClusters().size() > 0) {
+      throw new SystemException("Delete request cannot be completed since there is a cluster deployed");
+    } else {
+      if (propertyMap.containsKey(MPACK_ID)) {
+        Object objMpackId = propertyMap.get(MPACK_ID);
+        if (objMpackId != null) {
+          mpackId = Long.valueOf((String) objMpackId);
+          LOG.info("Deleting Mpack, id = " + mpackId.toString());
+
+          MpackEntity mpackEntity = mpackDAO.findById(mpackId);
+          StackEntity stackEntity = stackDAO.findByMpack(mpackId);
+          try {
+            getManagementController().removeMpack(mpackEntity, stackEntity);
+            if (mpackEntity != null) {
+              deleteStatusMetaData = modifyResources(new Command<DeleteStatusMetaData>() {
+                @Override
+                public DeleteStatusMetaData invoke() throws AmbariException {
+                  if (stackEntity != null) {
+                    stackDAO.removeByMpack(mpackId);
+                    notifyDelete(Resource.Type.Stack, predicate);
+                  }
+                  mpackDAO.removeById(mpackId);
+
+                  return new DeleteStatusMetaData();
+                }
+              });
+              notifyDelete(Resource.Type.Mpack, predicate);
+              deleteStatusMetaData.addDeletedKey(mpackId.toString());
+            } else {
+              throw new NoSuchResourceException("The requested resource doesn't exist: " + predicate);
+            }
+          } catch (IOException e) {
+            throw new SystemException("There is an issue with the Files");
+          }
+        }
+      } else {
+        throw new UnsupportedPropertyException(Resource.Type.Mpack, null);
+      }
+
+      return getRequestStatus(null, null, deleteStatusMetaData);
+    }
+  }
+
 }
 
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/mpack/MpackManager.java b/ambari-server/src/main/java/org/apache/ambari/server/mpack/MpackManager.java
index f19320e..619823c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/mpack/MpackManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/mpack/MpackManager.java
@@ -32,6 +32,7 @@ import org.apache.ambari.server.state.Packlet;
 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -328,8 +329,8 @@ public class MpackManager {
       MpackEntity mpackEntity = new MpackEntity();
       mpackEntity.setMpackName(mpackName);
       mpackEntity.setMpackVersion(mpackVersion);
-      mpackEntity.setMpackUri(mpacks.getMpacksUri());
-
+      mpackEntity.setMpackUri(mpack.getMpacksUri());
+      mpackEntity.setRegistryId(mpack.getRegistryId());
       Long mpackId = mpackDAO.create(mpackEntity);
       return mpackId;
     }
@@ -375,4 +376,44 @@ public class MpackManager {
       return mpack.getPacklets();
     return null;
   }
+
+  /***
+   * Remove the mpack and stack directories when a request comes in to delete a particular mpack.
+   * @param mpackEntity
+   * @throws IOException
+   */
+  public boolean removeMpack(MpackEntity mpackEntity, StackEntity stackEntity) throws IOException {
+
+    boolean stackDelete = false;
+    File mpackDirToDelete = new File(mpackStaging + File.separator + mpackEntity.getMpackName() + File.separator + mpackEntity.getMpackVersion());
+    File mpackDirectory = new File(mpackStaging + "/" + mpackEntity.getMpackName());
+    String mpackName = mpackEntity.getMpackName() + "-" + mpackEntity.getMpackVersion() + ".tar.gz";
+    Path mpackTarFile = Paths.get(mpackStaging + File.separator + MPACK_TAR_LOCATION +File.separator + mpackName);
+
+    mpackMap.remove(mpackEntity.getMpackId());
+    FileUtils.deleteDirectory(mpackDirToDelete);
+
+    if (mpackDirectory.isDirectory()) {
+      if (mpackDirectory.list().length == 0) {
+        Files.delete(mpackDirectory.toPath());
+      }
+    }
+    if (stackEntity != null) {
+      Path stackPath = Paths.get(stackRoot + "/" + stackEntity.getStackName() + "/" + stackEntity.getStackVersion());
+      File stackDirectory = new File(stackRoot + "/" + stackEntity.getStackName());
+      if (!Files.exists(stackPath))
+        Files.delete(stackPath);
+      if (stackDirectory.isDirectory()) {
+        if (stackDirectory.list().length == 0) {
+          Files.delete(stackDirectory.toPath());
+        }
+      }
+      stackDelete = true;
+    }
+
+    if (Files.exists(mpackTarFile)){
+      Files.delete(mpackTarFile);
+    }
+    return stackDelete;
+  }
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackDAO.java
index a19ceaf..fb4e101 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MpackDAO.java
@@ -95,5 +95,9 @@ public class MpackDAO {
     return m_daoUtils.selectList(query);
   }
 
+  @Transactional
+  public void removeById(Long mpackId) {
+    m_entityManagerProvider.get().remove(findById(mpackId));
+  }
 
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/StackDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/StackDAO.java
index f7c5dbe..57327c6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/StackDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/StackDAO.java
@@ -175,4 +175,29 @@ public class StackDAO {
       entityManager.remove(stack);
     }
   }
+
+  /**
+   * Removes the specified stack based on mpackid.
+   *
+   * @param mpackId
+   *
+   */
+  @Transactional
+  public void removeByMpack(Long mpackId) {
+    entityManagerProvider.get().remove(findByMpack(mpackId));
+  }
+
+  /**
+   * Gets the stack that matches the specified mpackid.
+   *
+   * @return the stack matching the specified mpackid or {@code null}
+   *         if none.
+   */
+  public StackEntity findByMpack(Long mpackId) {
+    TypedQuery<StackEntity> query = entityManagerProvider.get().createNamedQuery(
+            "StackEntity.findByMpack", StackEntity.class);
+    query.setParameter("currentMpackId", mpackId);
+
+    return daoUtils.selectOne(query);
+  }
 }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java
index 0cb8628..bee53b6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StackEntity.java
@@ -40,6 +40,7 @@ import javax.persistence.UniqueConstraint;
 @TableGenerator(name = "stack_id_generator", table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value", pkColumnValue = "stack_id_seq", initialValue = 0)
 @NamedQueries({
     @NamedQuery(name = "StackEntity.findAll", query = "SELECT stack FROM StackEntity stack"),
+    @NamedQuery(name = "StackEntity.findByMpack", query = "SELECT stack FROM StackEntity stack where stack.currentMpackId = :currentMpackId"),
     @NamedQuery(name = "StackEntity.findByNameAndVersion", query = "SELECT stack FROM StackEntity stack WHERE stack.stackName = :stackName AND stack.stackVersion = :stackVersion",
                 hints = {
                   @QueryHint(name = "eclipselink.query-results-cache", value = "true"),
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
index fbd0d8c..ca3ff30 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/StackManager.java
@@ -677,4 +677,9 @@ public class StackManager {
     }
     return extensionModules;
   }
+
+  public void removeStack(StackEntity stackEntity) {
+    String stackKey = stackEntity.getStackName() + StackManager.PATH_DELIMITER +  stackEntity.getStackVersion();
+    stackMap.remove(stackKey);
+  }
 }