You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ja...@apache.org on 2015/04/10 21:49:22 UTC

ambari git commit: AMBARI-10407. Create API endpoint for widgets.

Repository: ambari
Updated Branches:
  refs/heads/trunk f71f175e2 -> 2f2e37267


AMBARI-10407. Create API endpoint for widgets.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2f2e3726
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2f2e3726
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2f2e3726

Branch: refs/heads/trunk
Commit: 2f2e372672e908628de5e0dbd40d0b491bee4eb6
Parents: f71f175
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Thu Apr 9 12:37:35 2015 -0700
Committer: Jaimin Jetly <ja...@hortonworks.com>
Committed: Fri Apr 10 12:49:15 2015 -0700

----------------------------------------------------------------------
 .../server/api/services/ClusterService.java     |  10 +
 .../server/api/services/WidgetService.java      | 131 ++++++
 .../AbstractControllerResourceProvider.java     |   2 +
 .../internal/WidgetResourceProvider.java        | 383 +++++++++++++++
 .../server/orm/entities/WidgetEntity.java       |  11 +-
 .../entities/WidgetLayoutUserWidgetEntity.java  |   4 +-
 .../WidgetLayoutUserWidgetEntityPK.java         |   2 +-
 .../server/upgrade/UpgradeCatalog210.java       |  14 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  14 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  14 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  14 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  16 +-
 .../internal/WidgetResourceProviderTest.java    | 465 +++++++++++++++++++
 .../server/upgrade/UpgradeCatalog210Test.java   |  14 +-
 14 files changed, 1044 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
index 87a4f7f..be40bc4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
@@ -644,6 +644,16 @@ public class ClusterService extends BaseService {
     return new WidgetLayoutService(clusterName);
   }
 
+  /**
+   * Gets the widget service
+   */
+  @Path("{clusterName}/widgets")
+  public WidgetService getWidgetService(@Context javax.ws.rs.core.Request request,
+                                                    @PathParam ("clusterName") String clusterName) {
+
+    return new WidgetService(clusterName);
+  }
+
   // ----- helper methods ----------------------------------------------------
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetService.java
new file mode 100644
index 0000000..ead0985
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/WidgetService.java
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.api.services;
+
+import com.sun.jersey.core.util.Base64;
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Widget Service
+ */
+public class WidgetService extends BaseService {
+
+  private final String clusterName;
+
+  public WidgetService(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  @GET
+  @Path("{widgetId}")
+  @Produces("text/plain")
+  public Response getService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                             @PathParam("widgetId") String widgetId) {
+
+    return handleRequest(headers, body, ui, Request.Type.GET,
+            createResource(getUserName(headers), widgetId));
+  }
+
+  /**
+   * Handles URL: /widget
+   * Get all instances for a view.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   *
+   * @return instance collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getServices(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.GET,
+            createResource(getUserName(headers), null));
+  }
+
+  @POST
+  @Path("{widgetId}")
+  @Produces("text/plain")
+  public Response createService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("widgetId") String widgetId) {
+    return handleRequest(headers, body, ui, Request.Type.POST,
+            createResource(getUserName(headers), widgetId));
+  }
+
+  @POST
+  @Produces("text/plain")
+  public Response createServices(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST,
+            createResource(getUserName(headers), null));
+  }
+
+  @PUT
+  @Path("{widgetId}")
+  @Produces("text/plain")
+  public Response updateService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("widgetId") String widgetId) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResource(getUserName(headers), widgetId));
+  }
+
+  @PUT
+  @Produces("text/plain")
+  public Response updateServices(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResource(getUserName(headers), null));
+  }
+
+  @DELETE
+  @Path("{widgetId}")
+  @Produces("text/plain")
+  public Response deleteService(@Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("widgetId") String widgetId) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createResource(getUserName(headers), widgetId));
+  }
+
+  private ResourceInstance createResource(String userName, String widgetId) {
+    Map<Resource.Type,String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.Cluster, clusterName);
+    mapIds.put(Resource.Type.Widget, widgetId);
+    mapIds.put(Resource.Type.User, userName);
+    return createResource(Resource.Type.Widget, mapIds);
+  }
+
+  private String getUserName(HttpHeaders headers) {
+    String authorizationString = headers.getRequestHeaders().get("Authorization").get(0);
+    if (authorizationString != null && authorizationString.startsWith("Basic")) {
+      String base64Credentials = authorizationString.substring("Basic".length()).trim();
+      String clearCredentials = new String(Base64.decode(base64Credentials), Charset.forName("UTF-8"));
+      return clearCredentials.split(":", 2)[0];
+    } else {
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
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 2c3f0b0..eb1a818 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
@@ -159,6 +159,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
         return new ThemeArtifactResourceProvider(managementController);
       case WidgetLayout:
         return new WidgetLayoutResourceProvider(managementController);
+      case Widget:
+        return new WidgetResourceProvider(managementController);
 
       default:
         throw new IllegalArgumentException("Unknown type " + type);

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetResourceProvider.java
new file mode 100644
index 0000000..87ae723
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/WidgetResourceProvider.java
@@ -0,0 +1,383 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller.internal;
+
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ObjectNotFoundException;
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.WidgetDAO;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
+import org.apache.ambari.server.orm.entities.WidgetEntity;
+import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.dao.PermissionDeniedDataAccessException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Resource provider for repository versions resources.
+ */
+@StaticallyInject
+public class WidgetResourceProvider extends AbstractControllerResourceProvider {
+
+  // ----- Property ID constants ---------------------------------------------
+
+  public static final String WIDGET_ID_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "id");
+  public static final String WIDGET_CLUSTER_NAME_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "cluster_name");
+  public static final String WIDGET_WIDGET_NAME_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "widget_name");
+  public static final String WIDGET_DISPLAY_NAME_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "display_name");
+  public static final String WIDGET_WIDGET_TYPE_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "widget_type");
+  public static final String WIDGET_TIME_CREATED_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "time_created");
+  public static final String WIDGET_AUTHOR_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "author");
+  public static final String WIDGET_DESCRIPTION_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "description");
+  public static final String WIDGET_SCOPE_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "scope");
+  public static final String WIDGET_METRICS_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "metrics");
+  public static final String WIDGET_VALUES_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "values");
+  public static final String WIDGET_PROPERTIES_PROPERTY_ID                 = PropertyHelper.getPropertyId("Widgets", "properties");
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>() {
+    {
+      add(WIDGET_ID_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  public static Set<String> propertyIds = new HashSet<String>() {
+    {
+      add(WIDGET_ID_PROPERTY_ID);
+      add(WIDGET_WIDGET_NAME_PROPERTY_ID);
+      add(WIDGET_DISPLAY_NAME_PROPERTY_ID);
+      add(WIDGET_WIDGET_TYPE_PROPERTY_ID);
+      add(WIDGET_TIME_CREATED_PROPERTY_ID);
+      add(WIDGET_CLUSTER_NAME_PROPERTY_ID);
+      add(WIDGET_AUTHOR_PROPERTY_ID);
+      add(WIDGET_DESCRIPTION_PROPERTY_ID);
+      add(WIDGET_SCOPE_PROPERTY_ID);
+      add(WIDGET_METRICS_PROPERTY_ID);
+      add(WIDGET_VALUES_PROPERTY_ID);
+      add(WIDGET_PROPERTIES_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  public static Map<Type, String> keyPropertyIds = new HashMap<Type, String>() {
+    {
+      put(Type.Widget, WIDGET_ID_PROPERTY_ID);
+      put(Type.Cluster, WIDGET_CLUSTER_NAME_PROPERTY_ID);
+      put(Type.User, WIDGET_AUTHOR_PROPERTY_ID);
+    }
+  };
+
+  @Inject
+  private static WidgetDAO widgetDAO;
+
+  @Inject
+  private static Gson gson;
+
+  /**
+   * Create a new resource provider.
+   *
+   */
+  public WidgetResourceProvider(AmbariManagementController managementController) {
+    super(propertyIds, keyPropertyIds, managementController);
+  }
+
+  @Override
+  public RequestStatus createResources(final Request request)
+      throws SystemException,
+      UnsupportedPropertyException,
+      ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+
+    for (final Map<String, Object> properties : request.getProperties()) {
+      createResources(new Command<Void>() {
+
+        @Override
+        public Void invoke() throws AmbariException {
+          final String[] requiredProperties = {
+              WIDGET_CLUSTER_NAME_PROPERTY_ID,
+              WIDGET_WIDGET_NAME_PROPERTY_ID,
+              WIDGET_DISPLAY_NAME_PROPERTY_ID,
+              WIDGET_WIDGET_TYPE_PROPERTY_ID,
+              WIDGET_SCOPE_PROPERTY_ID
+          };
+          for (String propertyName: requiredProperties) {
+            if (properties.get(propertyName) == null) {
+              throw new AmbariException("Property " + propertyName + " should be provided");
+            }
+          }
+          final WidgetEntity entity = new WidgetEntity();
+          String clusterName = properties.get(WIDGET_CLUSTER_NAME_PROPERTY_ID).toString();
+          String userName = properties.get(WIDGET_AUTHOR_PROPERTY_ID).toString();
+          String scope = properties.get(WIDGET_SCOPE_PROPERTY_ID).toString();
+
+          if (!isScopeAllowedForUser(scope)) {
+            throw new AmbariException("Only cluster operator can create widgets with cluster scope");
+          }
+
+          entity.setDisplayName(properties.get(WIDGET_DISPLAY_NAME_PROPERTY_ID).toString());
+          entity.setWidgetName(properties.get(WIDGET_WIDGET_NAME_PROPERTY_ID).toString());
+          entity.setWidgetType(properties.get(WIDGET_WIDGET_TYPE_PROPERTY_ID).toString());
+          entity.setClusterId(getManagementController().getClusters().getCluster(clusterName).getClusterId());
+          entity.setDisplayName(properties.get(WIDGET_DISPLAY_NAME_PROPERTY_ID).toString());
+          entity.setScope(scope);
+
+          String metrics = (properties.containsKey(WIDGET_METRICS_PROPERTY_ID)) ?
+                  gson.toJson(properties.get(WIDGET_METRICS_PROPERTY_ID)) : null;
+          entity.setMetrics(metrics);
+
+          entity.setAuthor(userName);
+
+          String description = (properties.containsKey(WIDGET_DESCRIPTION_PROPERTY_ID)) ?
+                  properties.get(WIDGET_DESCRIPTION_PROPERTY_ID).toString() : null;
+          entity.setDescription(description);
+
+          String values = (properties.containsKey(WIDGET_VALUES_PROPERTY_ID)) ?
+                  gson.toJson(properties.get(WIDGET_VALUES_PROPERTY_ID)) : null;
+          entity.setWidgetValues(values);
+
+          Map<String, Object> widgetPropertiesMap = new HashMap<String, Object>();
+          for (Map.Entry<String, Object> entry : properties.entrySet()) {
+            if (PropertyHelper.getPropertyCategory(entry.getKey()).equals(WIDGET_PROPERTIES_PROPERTY_ID)) {
+              widgetPropertiesMap.put(PropertyHelper.getPropertyName(entry.getKey()), entry.getValue());
+            }
+          }
+
+          String widgetProperties = (widgetPropertiesMap.isEmpty()) ?
+                  null : gson.toJson(widgetPropertiesMap);
+          entity.setProperties(widgetProperties);
+
+          widgetDAO.create(entity);
+          notifyCreate(Type.Widget, request);
+          return null;
+        }
+      });
+    }
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Resource> resources = new HashSet<Resource>();
+    final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+    final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
+
+    List<WidgetEntity> requestedEntities = new ArrayList<WidgetEntity>();
+
+    for (Map<String, Object> propertyMap: propertyMaps) {
+      if (propertyMap.get(WIDGET_ID_PROPERTY_ID) != null) {
+        final Long id;
+        try {
+          id = Long.parseLong(propertyMap.get(WIDGET_ID_PROPERTY_ID).toString());
+        } catch (Exception ex) {
+          throw new SystemException("WidgetLayout should have numerical id");
+        }
+        final WidgetEntity entity = widgetDAO.findById(id);
+        if (entity == null) {
+          throw new NoSuchResourceException("WidgetLayout with id " + id + " does not exists");
+        }
+        requestedEntities.add(entity);
+      } else {
+        requestedEntities.addAll(widgetDAO.findAll());
+      }
+    }
+
+    for (WidgetEntity entity: requestedEntities) {
+      final Resource resource = new ResourceImpl(Type.Widget);
+      resource.setProperty(WIDGET_ID_PROPERTY_ID, entity.getId());
+      resource.setProperty(WIDGET_WIDGET_NAME_PROPERTY_ID, entity.getWidgetName());
+      resource.setProperty(WIDGET_WIDGET_TYPE_PROPERTY_ID, entity.getWidgetType());
+      setResourceProperty(resource, WIDGET_METRICS_PROPERTY_ID, gson.fromJson(entity.getMetrics(), ArrayList.class), requestedIds);
+      setResourceProperty(resource, WIDGET_TIME_CREATED_PROPERTY_ID, entity.getTimeCreated(), requestedIds);
+      resource.setProperty(WIDGET_AUTHOR_PROPERTY_ID, entity.getAuthor());
+      setResourceProperty(resource, WIDGET_DESCRIPTION_PROPERTY_ID, entity.getDescription(), requestedIds);
+      resource.setProperty(WIDGET_DISPLAY_NAME_PROPERTY_ID, entity.getDisplayName());
+      resource.setProperty(WIDGET_SCOPE_PROPERTY_ID, entity.getScope());
+      setResourceProperty(resource, WIDGET_VALUES_PROPERTY_ID, gson.fromJson(entity.getWidgetValues(), ArrayList.class), requestedIds);
+      setResourceProperty(resource, WIDGET_PROPERTIES_PROPERTY_ID, gson.fromJson(entity.getProperties(), Map.class), requestedIds);
+
+      String clusterName = null;
+      try {
+        clusterName = getManagementController().getClusters().getClusterById(entity.getClusterId()).getClusterName();
+      } catch (AmbariException e) {
+        throw new SystemException(e.getMessage());
+      }
+      setResourceProperty(resource, WIDGET_CLUSTER_NAME_PROPERTY_ID, clusterName, requestedIds);
+
+      resources.add(resource);
+    }
+
+    return resources;
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+    throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    final Set<Map<String, Object>> propertyMaps = request.getProperties();
+
+    modifyResources(new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException {
+        for (Map<String, Object> propertyMap : propertyMaps) {
+          final Long id;
+          try {
+            id = Long.parseLong(propertyMap.get(WIDGET_ID_PROPERTY_ID).toString());
+          } catch (Exception ex) {
+            throw new AmbariException("Widget should have numerical id");
+          }
+
+          final WidgetEntity entity = widgetDAO.findById(id);
+          if (entity == null) {
+            throw new ObjectNotFoundException("There is no widget with id " + id);
+          }
+
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGET_WIDGET_NAME_PROPERTY_ID)))) {
+            entity.setWidgetName(propertyMap.get(WIDGET_WIDGET_NAME_PROPERTY_ID).toString());
+          }
+
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGET_WIDGET_TYPE_PROPERTY_ID)))) {
+            entity.setWidgetType(propertyMap.get(WIDGET_WIDGET_TYPE_PROPERTY_ID).toString());
+          }
+
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGET_METRICS_PROPERTY_ID)))) {
+            entity.setMetrics(gson.toJson(propertyMap.get(WIDGET_METRICS_PROPERTY_ID)));
+          }
+
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGET_AUTHOR_PROPERTY_ID)))) {
+            entity.setAuthor(propertyMap.get(WIDGET_AUTHOR_PROPERTY_ID).toString());
+          }
+
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGET_DESCRIPTION_PROPERTY_ID)))) {
+            entity.setDescription(propertyMap.get(WIDGET_DESCRIPTION_PROPERTY_ID).toString());
+          }
+
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGET_SCOPE_PROPERTY_ID)))) {
+            String scope = propertyMap.get(WIDGET_SCOPE_PROPERTY_ID).toString();
+            if (!isScopeAllowedForUser(scope)) {
+              throw new AmbariException("Only cluster operator can create widgets with cluster scope");
+            }
+            entity.setScope(scope);
+          }
+
+          if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(WIDGET_VALUES_PROPERTY_ID)))) {
+            entity.setWidgetValues(gson.toJson(propertyMap.get(WIDGET_VALUES_PROPERTY_ID)));
+          }
+
+          Map<String, Object> widgetPropertiesMap = new HashMap<String, Object>();
+          for (Map.Entry<String, Object> entry : propertyMap.entrySet()) {
+            if (PropertyHelper.getPropertyCategory(entry.getKey()).equals(WIDGET_PROPERTIES_PROPERTY_ID)) {
+              widgetPropertiesMap.put(PropertyHelper.getPropertyName(entry.getKey()), entry.getValue());
+            }
+          }
+
+          if (!widgetPropertiesMap.isEmpty()) {
+            entity.setProperties(gson.toJson(widgetPropertiesMap));
+          }
+
+          widgetDAO.merge(entity);
+        }
+        return null;
+      }
+    });
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
+
+    final List<WidgetEntity> entitiesToBeRemoved = new ArrayList<WidgetEntity>();
+    for (Map<String, Object> propertyMap : propertyMaps) {
+      final Long id;
+      try {
+        id = Long.parseLong(propertyMap.get(WIDGET_ID_PROPERTY_ID).toString());
+      } catch (Exception ex) {
+        throw new SystemException("Widget should have numerical id");
+      }
+      final WidgetEntity entity = widgetDAO.findById(id);
+      if (entity == null) {
+        throw new NoSuchResourceException("There is no widget with id " + id);
+      }
+      entitiesToBeRemoved.add(entity);
+    }
+
+    for (WidgetEntity entity: entitiesToBeRemoved) {
+      widgetDAO.remove(entity);
+    }
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+  private boolean isScopeAllowedForUser(String scope) {
+    if (scope.equals(WidgetEntity.USER_SCOPE)) {
+      return true;
+    }
+
+    // Only cluster operators are allowed to create widgets with cluster scope
+    SecurityContext securityContext = SecurityContextHolder.getContext();
+    securityContext.getAuthentication().getAuthorities();
+    boolean hasPermissionForClusterScope = false;
+    for (GrantedAuthority grantedAuthority : securityContext.getAuthentication().getAuthorities()) {
+      if (((AmbariGrantedAuthority) grantedAuthority).getPrivilegeEntity().getPermission().getId()
+              == PermissionEntity.AMBARI_ADMIN_PERMISSION ||
+              ((AmbariGrantedAuthority) grantedAuthority).getPrivilegeEntity().getPermission().getId()
+                      == PermissionEntity.CLUSTER_OPERATE_PERMISSION) {
+        hasPermissionForClusterScope = true;
+      }
+    }
+    if (hasPermissionForClusterScope) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java
index 4fd6fbf..d383a62 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetEntity.java
@@ -33,7 +33,7 @@ import javax.persistence.TableGenerator;
 import java.util.List;
 
 @Entity
-@Table(name = "user_widget")
+@Table(name = "widget")
 @TableGenerator(name = "widget_id_generator",
         table = "ambari_sequences",
         pkColumnName = "sequence_name",
@@ -53,15 +53,18 @@ import java.util.List;
         })
 public class WidgetEntity {
 
+  public static final String CLUSTER_SCOPE = "CLUSTER";
+  public static final String USER_SCOPE = "USER";
+
   @Id
   @GeneratedValue(strategy = GenerationType.TABLE, generator = "widget_id_generator")
   @Column(name = "id", nullable = false, updatable = false)
   private Long id;
 
-  @Column(name = "user_widget_name", nullable = false, length = 255)
+  @Column(name = "widget_name", nullable = false, length = 255)
   private String widgetName;
 
-  @Column(name = "user_widget_type", nullable = false, length = 255)
+  @Column(name = "widget_type", nullable = false, length = 255)
   private String widgetType;
 
   @Column(name = "metrics", length = 32672)
@@ -95,7 +98,7 @@ public class WidgetEntity {
   @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false, updatable = false, insertable = false)
   private ClusterEntity clusterEntity;
 
-  @OneToMany(cascade = CascadeType.ALL, mappedBy = "widget")
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "widget", orphanRemoval = true)
   private List<WidgetLayoutUserWidgetEntity> listWidgetLayoutUserWidgetEntity;
 
   public Long getId() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
index df00eb3..1d6e1b5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntity.java
@@ -36,7 +36,7 @@ public class WidgetLayoutUserWidgetEntity {
   private Long widgetLayoutId;
 
   @Id
-  @Column(name = "user_widget_id", nullable = false, updatable = false, insertable = false)
+  @Column(name = "widget_id", nullable = false, updatable = false, insertable = false)
   private Long userWidgetId;
 
   @ManyToOne
@@ -44,7 +44,7 @@ public class WidgetLayoutUserWidgetEntity {
   private WidgetLayoutEntity widgetLayout;
 
   @ManyToOne
-  @JoinColumn(name = "user_widget_id", referencedColumnName = "id")
+  @JoinColumn(name = "widget_id", referencedColumnName = "id")
   private WidgetEntity widget;
 
   @Column(name = "widget_order")

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
index 4fdd977..386870f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/WidgetLayoutUserWidgetEntityPK.java
@@ -39,7 +39,7 @@ public class WidgetLayoutUserWidgetEntityPK  implements Serializable {
   private Long userWidgetId;
 
   @Id
-  @Column(name = "user_widget_id", nullable = false, updatable = false)
+  @Column(name = "widget_id", nullable = false, updatable = false)
   public Long getUserWidgetId() {
     return userWidgetId;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
index 1518811..e94d5f4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
@@ -51,7 +51,7 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
   private static final String CONFIG_GROUP_HOST_MAPPING_TABLE = "configgrouphostmapping";
   private static final String KERBEROS_PRINCIPAL_HOST_TABLE = "kerberos_principal_host";
   private static final String CLUSTER_HOST_MAPPING_TABLE = "ClusterHostMapping";
-  private static final String USER_WIDGET_TABLE = "user_widget";
+  private static final String WIDGET_TABLE = "widget";
   private static final String WIDGET_LAYOUT_TABLE = "widget_layout";
   private static final String WIDGET_LAYOUT_USER_WIDGET_TABLE = "widget_layout_user_widget";
   private static final String VIEW_INSTANCE_TABLE = "viewinstance";
@@ -303,8 +303,8 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
     List<DBColumnInfo> columns = new ArrayList<DBColumnInfo>();
 
     columns.add(new DBColumnInfo("id", Long.class,    null,  null, false));
-    columns.add(new DBColumnInfo("user_widget_name", String.class,  255,   null, false));
-    columns.add(new DBColumnInfo("user_widget_type", String.class,  255,   null, false));
+    columns.add(new DBColumnInfo("widget_name", String.class,  255,   null, false));
+    columns.add(new DBColumnInfo("widget_type", String.class,  255,   null, false));
     columns.add(new DBColumnInfo("metrics", String.class,  32672,   null, true));
     columns.add(new DBColumnInfo("time_created", Long.class,  255,   null, false));
     columns.add(new DBColumnInfo("author", String.class,  255,   null, true));
@@ -314,7 +314,7 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
     columns.add(new DBColumnInfo("widget_values", String.class,  255,   null, true));
     columns.add(new DBColumnInfo("properties", String.class,  255,   null, true));
     columns.add(new DBColumnInfo("cluster_id", Long.class,  255,   null, false));
-    dbAccessor.createTable(USER_WIDGET_TABLE, columns, "id");
+    dbAccessor.createTable(WIDGET_TABLE, columns, "id");
 
     columns = new ArrayList<DBColumnInfo>();
     columns.add(new DBColumnInfo("id", Long.class,    null,  null, false));
@@ -329,11 +329,11 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
 
     columns = new ArrayList<DBColumnInfo>();
     columns.add(new DBColumnInfo("widget_layout_id", Long.class,    null,  null, false));
-    columns.add(new DBColumnInfo("user_widget_id", Long.class,    null,  null, false));
+    columns.add(new DBColumnInfo("widget_id", Long.class,    null,  null, false));
     columns.add(new DBColumnInfo("widget_order", Integer.class,    null,  null, false));
-    dbAccessor.createTable(WIDGET_LAYOUT_USER_WIDGET_TABLE, columns, "widget_layout_id", "user_widget_id");
+    dbAccessor.createTable(WIDGET_LAYOUT_USER_WIDGET_TABLE, columns, "widget_layout_id", "widget_id");
     dbAccessor.addFKConstraint(WIDGET_LAYOUT_USER_WIDGET_TABLE, "FK_widget_layout_id", "widget_layout_id", "widget_layout", "id", true, false);
-    dbAccessor.addFKConstraint(WIDGET_LAYOUT_USER_WIDGET_TABLE, "FK_user_widget_id", "user_widget_id", "user_widget", "id", true, false);
+    dbAccessor.addFKConstraint(WIDGET_LAYOUT_USER_WIDGET_TABLE, "FK_widget_id", "widget_id", "widget", "id", true, false);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index d947a1b..2ae970c 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -534,12 +534,12 @@ CREATE TABLE repo_version (
   PRIMARY KEY(repo_version_id)
 );
 
-CREATE TABLE user_widget (
+CREATE TABLE widget (
   id BIGINT NOT NULL,
-  user_widget_name VARCHAR(255) NOT NULL,
-  user_widget_type VARCHAR(255) NOT NULL,
+  widget_name VARCHAR(255) NOT NULL,
+  widget_type VARCHAR(255) NOT NULL,
   metrics LONGTEXT,
-  time_created TIMESTAMP DEFAULT NOW(),
+  time_created BIGINT NOT NULL,
   author VARCHAR(255),
   description VARCHAR(255),
   display_name VARCHAR(255) NOT NULL,
@@ -563,9 +563,9 @@ CREATE TABLE widget_layout (
 
 CREATE TABLE widget_layout_user_widget (
   widget_layout_id BIGINT NOT NULL,
-  user_widget_id BIGINT NOT NULL,
+  widget_id BIGINT NOT NULL,
   widget_order smallint,
-  PRIMARY KEY(widget_layout_id, user_widget_id)
+  PRIMARY KEY(widget_layout_id, widget_id)
 );
 
 CREATE TABLE artifact (
@@ -653,7 +653,7 @@ ALTER TABLE users ADD CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id
 ALTER TABLE groups ADD CONSTRAINT FK_groups_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id);
 ALTER TABLE clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id);
 ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_layout_id FOREIGN KEY (widget_layout_id) REFERENCES widget_layout(id);
-ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id FOREIGN KEY (user_widget_id) REFERENCES user_widget(id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_id FOREIGN KEY (widget_id) REFERENCES widget(id);
 
 -- Kerberos
 CREATE TABLE kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index a1b22d4..8db0e32 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -522,12 +522,12 @@ CREATE TABLE repo_version (
   PRIMARY KEY(repo_version_id)
 );
 
-CREATE TABLE user_widget (
+CREATE TABLE widget (
   id NUMBER(19) NOT NULL,
-  user_widget_name VARCHAR2(255) NOT NULL,
-  user_widget_type VARCHAR2(255) NOT NULL,
+  widget_name VARCHAR2(255) NOT NULL,
+  widget_type VARCHAR2(255) NOT NULL,
   metrics CLOB,
-  time_created TIMESTAMP DEFAULT NOW(),
+  time_created NUMBER(19) NOT NULL,
   author VARCHAR2(255),
   description VARCHAR2(255),
   display_name VARCHAR2(255) NOT NULL,
@@ -551,9 +551,9 @@ CREATE TABLE widget_layout (
 
 CREATE TABLE widget_layout_user_widget (
   widget_layout_id NUMBER(19) NOT NULL,
-  user_widget_id NUMBER(19) NOT NULL,
+  widget_id NUMBER(19) NOT NULL,
   widget_order smallint,
-  PRIMARY KEY(widget_layout_id, user_widget_id)
+  PRIMARY KEY(widget_layout_id, widget_id)
 );
 
 CREATE TABLE artifact (
@@ -641,7 +641,7 @@ ALTER TABLE users ADD CONSTRAINT FK_users_principal_id FOREIGN KEY (principal_id
 ALTER TABLE groups ADD CONSTRAINT FK_groups_principal_id FOREIGN KEY (principal_id) REFERENCES adminprincipal(principal_id);
 ALTER TABLE clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id);
 ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_layout_id FOREIGN KEY (widget_layout_id) REFERENCES widget_layout(id);
-ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id FOREIGN KEY (user_widget_id) REFERENCES user_widget(id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_id FOREIGN KEY (widget_id) REFERENCES widget(id);
 
 -- Kerberos
 CREATE TABLE kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 66e3117..ca27989 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -527,12 +527,12 @@ CREATE TABLE repo_version (
   PRIMARY KEY(repo_version_id)
 );
 
-CREATE TABLE user_widget (
+CREATE TABLE widget (
   id BIGINT NOT NULL,
-  user_widget_name VARCHAR(255) NOT NULL,
-  user_widget_type VARCHAR(255) NOT NULL,
+  widget_name VARCHAR(255) NOT NULL,
+  widget_type VARCHAR(255) NOT NULL,
   metrics TEXT,
-  time_created TIMESTAMP DEFAULT NOW(),
+  time_created BIGINT NOT NULL,
   author VARCHAR(255),
   description VARCHAR(255),
   display_name VARCHAR(255) NOT NULL,
@@ -556,9 +556,9 @@ CREATE TABLE widget_layout (
 
 CREATE TABLE widget_layout_user_widget (
   widget_layout_id BIGINT NOT NULL,
-  user_widget_id BIGINT NOT NULL,
+  widget_id BIGINT NOT NULL,
   widget_order smallint,
-  PRIMARY KEY(widget_layout_id, user_widget_id)
+  PRIMARY KEY(widget_layout_id, widget_id)
 );
 
 CREATE TABLE artifact (
@@ -643,7 +643,7 @@ ALTER TABLE serviceconfigmapping ADD CONSTRAINT FK_scvm_config FOREIGN KEY (conf
 ALTER TABLE serviceconfighosts ADD CONSTRAINT  FK_scvhosts_scv FOREIGN KEY (service_config_id) REFERENCES serviceconfig(service_config_id);
 ALTER TABLE clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id);
 ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_layout_id FOREIGN KEY (widget_layout_id) REFERENCES widget_layout(id);
-ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id FOREIGN KEY (user_widget_id) REFERENCES user_widget(id);
+ALTER TABLE widget_layout_user_widget ADD CONSTRAINT FK_widget_id FOREIGN KEY (widget_id) REFERENCES widget(id);
 
 -- Kerberos
 CREATE TABLE kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index e944ebb..e1f9d6c 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -602,12 +602,12 @@ CREATE TABLE ambari.artifact (
   PRIMARY KEY (artifact_name, foreign_keys));
 GRANT ALL PRIVILEGES ON TABLE ambari.artifact TO :username;
 
-CREATE TABLE ambari.user_widget (
+CREATE TABLE ambari.widget (
   id BIGINT NOT NULL,
-  user_widget_name VARCHAR(255) NOT NULL,
-  user_widget_type VARCHAR(255) NOT NULL,
+  widget_name VARCHAR(255) NOT NULL,
+  widget_type VARCHAR(255) NOT NULL,
   metrics TEXT,
-  time_created TIMESTAMP DEFAULT NOW(),
+  time_created BIGINT NOT NULL,
   author VARCHAR(255),
   description VARCHAR(255),
   display_name VARCHAR(255) NOT NULL,
@@ -617,7 +617,7 @@ CREATE TABLE ambari.user_widget (
   cluster_id BIGINT NOT NULL,
   PRIMARY KEY(id)
 );
-GRANT ALL PRIVILEGES ON TABLE ambari.user_widget TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.widget TO :username;
 
 CREATE TABLE ambari.widget_layout (
   id BIGINT NOT NULL,
@@ -633,9 +633,9 @@ GRANT ALL PRIVILEGES ON TABLE ambari.widget_layout TO :username;
 
 CREATE TABLE ambari.widget_layout_user_widget (
   widget_layout_id BIGINT NOT NULL,
-  user_widget_id BIGINT NOT NULL,
+  widget_id BIGINT NOT NULL,
   widget_order smallint,
-  PRIMARY KEY(widget_layout_id, user_widget_id)
+  PRIMARY KEY(widget_layout_id, widget_id)
 );
 GRANT ALL PRIVILEGES ON TABLE ambari.widget_layout_user_widget TO :username;
 
@@ -715,7 +715,7 @@ ALTER TABLE ambari.users ADD CONSTRAINT FK_users_principal_id FOREIGN KEY (princ
 ALTER TABLE ambari.groups ADD CONSTRAINT FK_groups_principal_id FOREIGN KEY (principal_id) REFERENCES ambari.adminprincipal(principal_id);
 ALTER TABLE ambari.clusters ADD CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES ambari.adminresource(resource_id);
 ALTER TABLE ambari.widget_layout_user_widget ADD CONSTRAINT FK_widget_layout_id FOREIGN KEY (widget_layout_id) REFERENCES ambari.widget_layout(id);
-ALTER TABLE ambari.widget_layout_user_widget ADD CONSTRAINT FK_user_widget_id FOREIGN KEY (user_widget_id) REFERENCES ambari.user_widget(id);
+ALTER TABLE ambari.widget_layout_user_widget ADD CONSTRAINT FK_widget_id FOREIGN KEY (widget_id) REFERENCES ambari.widget(id);
 
 -- Kerberos
 CREATE TABLE ambari.kerberos_principal (

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/WidgetResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/WidgetResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/WidgetResourceProviderTest.java
new file mode 100644
index 0000000..568a89c
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/WidgetResourceProviderTest.java
@@ -0,0 +1,465 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller.internal;
+
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.WidgetDAO;
+import org.apache.ambari.server.orm.entities.WidgetEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.resetToStrict;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Widget tests
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest( {WidgetResourceProvider.class, SecurityContextHolder.class} )
+@PowerMockIgnore( {"javax.management.*"} )
+public class WidgetResourceProviderTest {
+
+  private WidgetDAO dao = null;
+  private Injector m_injector;
+
+  @Before
+  public void before() {
+    dao = createStrictMock(WidgetDAO.class);
+
+    m_injector = Guice.createInjector(Modules.override(
+        new InMemoryDefaultTestModule()).with(new MockModule()));
+  }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testGetResourcesNoPredicate() throws Exception {
+    WidgetResourceProvider provider = createProvider(null);
+
+    Request request = PropertyHelper.getReadRequest("Widgets/id");
+
+    Set<Resource> results = provider.getResources(request, null);
+
+    assertEquals(0, results.size());
+  }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testGetSingleResource() throws Exception {
+    Request request = PropertyHelper.getReadRequest(
+      WidgetResourceProvider.WIDGET_ID_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_WIDGET_NAME_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_DISPLAY_NAME_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_WIDGET_TYPE_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_TIME_CREATED_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_DESCRIPTION_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_SCOPE_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_METRICS_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_VALUES_PROPERTY_ID,
+      WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID);
+
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+    Clusters clusters = createMock(Clusters.class);
+    Cluster cluster = createMock(Cluster.class);
+    expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    expect(clusters.getClusterById(1L)).andReturn(cluster).atLeastOnce();
+    expect(cluster.getClusterName()).andReturn("c1").anyTimes();
+
+    Predicate predicate = new PredicateBuilder().property(
+        WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID).equals("c1")
+          .and().property(WidgetResourceProvider.WIDGET_ID_PROPERTY_ID).equals("1")
+            .and().property(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID).equals("username").toPredicate();
+
+    expect(dao.findById(1L)).andReturn(getMockEntities().get(0));
+
+    replay(amc, clusters, cluster, dao);
+
+    WidgetResourceProvider provider = createProvider(amc);
+    Set<Resource> results = provider.getResources(request, predicate);
+
+    assertEquals(1, results.size());
+
+    Resource r = results.iterator().next();
+    Assert.assertEquals("GAUGE", r.getPropertyValue(WidgetResourceProvider.WIDGET_WIDGET_TYPE_PROPERTY_ID));
+    Assert.assertEquals("USER", r.getPropertyValue(WidgetResourceProvider.WIDGET_SCOPE_PROPERTY_ID));
+    Assert.assertEquals("username", r.getPropertyValue(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID));
+    Assert.assertEquals("displ_name", r.getPropertyValue(WidgetResourceProvider.WIDGET_DISPLAY_NAME_PROPERTY_ID));
+    Assert.assertEquals("widget name", r.getPropertyValue(WidgetResourceProvider.WIDGET_WIDGET_NAME_PROPERTY_ID));
+    Object metrics = r.getPropertyValue(WidgetResourceProvider.WIDGET_METRICS_PROPERTY_ID);
+    Assert.assertTrue(metrics instanceof List);
+    Assert.assertEquals(2, ((List) metrics).size());
+    Object values = r.getPropertyValue(WidgetResourceProvider.WIDGET_VALUES_PROPERTY_ID);
+    Assert.assertTrue(values instanceof List);
+    Assert.assertEquals(1, ((List) values).size());
+  }
+
+
+  /**
+   * @throws Exception
+   */
+
+  @Test
+  public void testCreateResources() throws Exception {
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+    Clusters clusters = createMock(Clusters.class);
+    Cluster cluster = createMock(Cluster.class);
+    expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    expect(clusters.getCluster((String) anyObject())).andReturn(cluster).atLeastOnce();
+    expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).anyTimes();
+
+    Capture<WidgetEntity> entityCapture = new Capture<WidgetEntity>();
+    dao.create(capture(entityCapture));
+    expectLastCall();
+
+    replay(amc, clusters, cluster, dao);
+
+    WidgetResourceProvider provider = createProvider(amc);
+
+    Map<String, Object> requestProps = new HashMap<String, Object>();
+    requestProps.put(WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID, "c1");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_NAME_PROPERTY_ID, "widget name");
+    requestProps.put(WidgetResourceProvider.WIDGET_DISPLAY_NAME_PROPERTY_ID, "display_name");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_TYPE_PROPERTY_ID, "GAUGE");
+    requestProps.put(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID, "admin");
+    requestProps.put(WidgetResourceProvider.WIDGET_SCOPE_PROPERTY_ID, "USER");
+    Set testSet = new LinkedHashSet();
+    HashMap testMap = new HashMap();
+    testMap.put("name","value");
+    testMap.put("name2","value2");
+    testSet.add(testMap);
+    requestProps.put(WidgetResourceProvider.WIDGET_METRICS_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_VALUES_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/property1", "value1");
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/property2", "value2");
+
+    Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+    provider.createResources(request);
+
+    Assert.assertTrue(entityCapture.hasCaptured());
+    WidgetEntity entity = entityCapture.getValue();
+    Assert.assertNotNull(entity);
+
+    Assert.assertEquals(Long.valueOf(1), entity.getClusterId());
+    Assert.assertEquals("USER", entity.getScope());
+    Assert.assertEquals("widget name", entity.getWidgetName());
+    Assert.assertEquals("display_name", entity.getDisplayName());
+    Assert.assertEquals("GAUGE", entity.getWidgetType());
+    Assert.assertEquals("admin", entity.getAuthor());
+    Assert.assertEquals("[{\"name\":\"value\",\"name2\":\"value2\"}]", entity.getMetrics());
+    Assert.assertEquals("[{\"name\":\"value\",\"name2\":\"value2\"}]", entity.getWidgetValues());
+    Assert.assertEquals("{\"property2\":\"value2\",\"property1\":\"value1\"}", entity.getProperties());
+
+    verify(amc, clusters, cluster, dao);
+  }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testUpdateResources() throws Exception {
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+    Clusters clusters = createMock(Clusters.class);
+    Cluster cluster = createMock(Cluster.class);
+    expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    expect(clusters.getCluster((String) anyObject())).andReturn(cluster).atLeastOnce();
+    expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).atLeastOnce();
+
+    Capture<WidgetEntity> entityCapture = new Capture<WidgetEntity>();
+    dao.create(capture(entityCapture));
+    expectLastCall();
+
+    replay(amc, clusters, cluster, dao);
+
+    Map<String, Object> requestProps = new HashMap<String, Object>();
+    requestProps.put(WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID, "c1");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_NAME_PROPERTY_ID, "widget name");
+    requestProps.put(WidgetResourceProvider.WIDGET_DISPLAY_NAME_PROPERTY_ID, "display_name");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_TYPE_PROPERTY_ID, "GAUGE");
+    requestProps.put(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID, "admin");
+    requestProps.put(WidgetResourceProvider.WIDGET_SCOPE_PROPERTY_ID, "USER");
+    Set testSet = new LinkedHashSet();
+    HashMap testMap = new HashMap();
+    testMap.put("name","value");
+    testMap.put("name2","value2");
+    testSet.add(testMap);
+    requestProps.put(WidgetResourceProvider.WIDGET_METRICS_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_VALUES_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/property1", "value1");
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/property2", "value2");
+
+    Request request = PropertyHelper.getCreateRequest(
+        Collections.singleton(requestProps), null);
+
+    WidgetResourceProvider provider = createProvider(amc);
+
+    provider.createResources(request);
+
+    Assert.assertTrue(entityCapture.hasCaptured());
+    WidgetEntity entity = entityCapture.getValue();
+    Assert.assertNotNull(entity);
+
+    Predicate predicate = new PredicateBuilder().property(
+            WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID).equals("c1")
+            .and().property(WidgetResourceProvider.WIDGET_ID_PROPERTY_ID).equals("1")
+            .and().property(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID).equals("username").toPredicate();
+
+    // everything is mocked, there is no DB
+    entity.setId(Long.valueOf(1));
+
+    String oldMetrics = entity.getMetrics();
+    String oldProperties = entity.getProperties();
+    String oldName = entity.getWidgetName();
+
+    resetToStrict(dao);
+    expect(dao.findById(1L)).andReturn(entity).anyTimes();
+    expect(dao.merge((WidgetEntity) anyObject())).andReturn(entity).anyTimes();
+    replay(dao);
+
+    requestProps = new HashMap<String, Object>();
+    requestProps.put(WidgetResourceProvider.WIDGET_ID_PROPERTY_ID, "1");
+    requestProps.put(WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID, "c1");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_NAME_PROPERTY_ID, "widget name2");
+    requestProps.put(WidgetResourceProvider.WIDGET_DISPLAY_NAME_PROPERTY_ID, "display_name");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_TYPE_PROPERTY_ID, "GAUGE");
+    requestProps.put(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID, "admin");
+    requestProps.put(WidgetResourceProvider.WIDGET_SCOPE_PROPERTY_ID, "USER");
+    testSet = new LinkedHashSet();
+    testMap = new HashMap();
+    testMap.put("name","new_value");
+    testMap.put("new_name","new_value2");
+    testSet.add(testMap);
+    requestProps.put(WidgetResourceProvider.WIDGET_METRICS_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_VALUES_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/property1", "new_value1");
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/new_property", "new_value2");
+
+    request = PropertyHelper.getUpdateRequest(requestProps, null);
+
+    provider.updateResources(request, predicate);
+
+    Assert.assertFalse(oldName.equals(entity.getWidgetName()));
+    Assert.assertFalse(oldMetrics.equals(entity.getMetrics()));
+    Assert.assertFalse(oldProperties.equals(entity.getProperties()));
+    Assert.assertEquals("[{\"name\":\"new_value\",\"new_name\":\"new_value2\"}]",entity.getMetrics());
+    Assert.assertEquals("{\"new_property\":\"new_value2\",\"property1\":\"new_value1\"}",entity.getProperties());
+    Assert.assertEquals("widget name2",entity.getWidgetName());
+    Assert.assertEquals("display_name",entity.getDisplayName());
+
+    verify(amc, clusters, cluster, dao);
+  }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testDeleteResources() throws Exception {
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+    Clusters clusters = createMock(Clusters.class);
+    Cluster cluster = createMock(Cluster.class);
+    expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    expect(clusters.getCluster((String) anyObject())).andReturn(cluster).atLeastOnce();
+    expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).anyTimes();
+
+    Capture<WidgetEntity> entityCapture = new Capture<WidgetEntity>();
+    dao.create(capture(entityCapture));
+    expectLastCall();
+
+    replay(amc, clusters, cluster, dao);
+
+    WidgetResourceProvider provider = createProvider(amc);
+
+    Map<String, Object> requestProps = new HashMap<String, Object>();
+    requestProps.put(WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID, "c1");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_NAME_PROPERTY_ID, "widget name");
+    requestProps.put(WidgetResourceProvider.WIDGET_DISPLAY_NAME_PROPERTY_ID, "display_name");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_TYPE_PROPERTY_ID, "GAUGE");
+    requestProps.put(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID, "admin");
+    requestProps.put(WidgetResourceProvider.WIDGET_SCOPE_PROPERTY_ID, "USER");
+    Set testSet = new LinkedHashSet();
+    HashMap testMap = new HashMap();
+    testMap.put("name","value");
+    testMap.put("name2","value2");
+    testSet.add(testMap);
+    requestProps.put(WidgetResourceProvider.WIDGET_METRICS_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_VALUES_PROPERTY_ID, testSet);
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/property1", "value1");
+    requestProps.put(WidgetResourceProvider.WIDGET_PROPERTIES_PROPERTY_ID+"/property2", "value2");
+
+    Request request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
+
+    provider.createResources(request);
+
+    Assert.assertTrue(entityCapture.hasCaptured());
+    WidgetEntity entity = entityCapture.getValue();
+    Assert.assertNotNull(entity);
+
+    Predicate predicate = new PredicateBuilder().property(
+            WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID).equals("c1")
+            .and().property(WidgetResourceProvider.WIDGET_ID_PROPERTY_ID).equals("1")
+            .and().property(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID).equals("username").toPredicate();
+
+    // everything is mocked, there is no DB
+    entity.setId(Long.valueOf(1));
+
+    resetToStrict(dao);
+    expect(dao.findById(1L)).andReturn(entity).anyTimes();
+    dao.remove(capture(entityCapture));
+    expectLastCall();
+    replay(dao);
+
+    provider.deleteResources(predicate);
+
+    WidgetEntity entity1 = entityCapture.getValue();
+    Assert.assertEquals(Long.valueOf(1), entity1.getId());
+
+    verify(amc, clusters, cluster, dao);
+  }
+
+  @Test
+  public void testScopePrivilegeCheck() throws Exception {
+    AmbariManagementController amc = createMock(AmbariManagementController.class);
+    Clusters clusters = createMock(Clusters.class);
+    Cluster cluster = createMock(Cluster.class);
+    expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    expect(clusters.getCluster((String) anyObject())).andReturn(cluster).atLeastOnce();
+    expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).atLeastOnce();
+    WidgetResourceProvider widgetResourceProvider = PowerMock.createPartialMock(WidgetResourceProvider.class, "isScopeAllowedForUser");
+    PowerMock.expectPrivate(widgetResourceProvider, "isScopeAllowedForUser", "CLUSTER").andReturn(false);
+
+    Capture<WidgetEntity> entityCapture = new Capture<WidgetEntity>();
+    dao.create(capture(entityCapture));
+    expectLastCall();
+
+    replay(amc, clusters, cluster, dao);
+    PowerMock.replayAll();
+
+    Map<String, Object> requestProps = new HashMap<String, Object>();
+    requestProps.put(WidgetResourceProvider.WIDGET_CLUSTER_NAME_PROPERTY_ID, "c1");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_NAME_PROPERTY_ID, "widget name");
+    requestProps.put(WidgetResourceProvider.WIDGET_DISPLAY_NAME_PROPERTY_ID, "display_name");
+    requestProps.put(WidgetResourceProvider.WIDGET_WIDGET_TYPE_PROPERTY_ID, "GAUGE");
+    requestProps.put(WidgetResourceProvider.WIDGET_AUTHOR_PROPERTY_ID, "admin");
+    requestProps.put(WidgetResourceProvider.WIDGET_SCOPE_PROPERTY_ID, "CLUSTER");
+    Request request = PropertyHelper.getCreateRequest(
+            Collections.singleton(requestProps), null);
+
+    try {
+      widgetResourceProvider.createResources(request);
+    } catch (SystemException ex) {
+      //Expected exception
+    }
+
+  }
+
+  /**
+   * @param amc
+   * @return
+   */
+  private WidgetResourceProvider createProvider(AmbariManagementController amc) {
+    return new WidgetResourceProvider(amc);
+  }
+
+  /**
+   * @return
+   */
+  private List<WidgetEntity> getMockEntities() throws Exception {
+
+    WidgetEntity widgetEntity = new WidgetEntity();
+    widgetEntity.setClusterId(Long.valueOf(1L));
+    widgetEntity.setWidgetName("widget name");
+    widgetEntity.setWidgetType("GAUGE");
+    widgetEntity.setAuthor("username");
+    widgetEntity.setScope("USER");
+    widgetEntity.setDisplayName("displ_name");
+    widgetEntity.setDescription("Description");
+    widgetEntity.setMetrics("[{\"widget_id\":\"metrics/jvm/HeapMemoryUsed\"," +
+            "\"host_component_criteria\":\"host_components/metrics/dfs/FSNamesystem/HAState\\u003dactive\"," +
+            "\"service_name\":\"HDFS\",\"component_na\n" +
+            "me\":\"NAMENODE\",\"name\":\"java.lang:type\\u003dMemory.HeapMemoryUsage[used]\",\"category\":\"\"}," +
+            "{\"widget_id\":\"metrics/jvm/HeapMemoryMax\",\"host_component_criteria\":\"host_compone\n" +
+            "nts/metrics/dfs/FSNamesystem/HAState\\u003dactive\",\"service_name\":\"HDFS\"," +
+            "\"component_name\":\"NAMENODE\",\"name\":\"java.lang:type\\u003dMemory.HeapMemoryUsage[max]\"," +
+            "\"category\":\n\"\"}]");
+    widgetEntity.setWidgetValues("[{\"name\":\"NameNode Heap\"," +
+            "\"value\":\"${java.lang:type\\u003dMemory.HeapMemoryUsage[used] / " +
+            "java.lang:type\\u003dMemory.HeapMemoryUsage[max]}\"}]");
+    widgetEntity.setProperties("{\"name\":\"value\"}");
+    return Arrays.asList(widgetEntity);
+  }
+
+  /**
+  *
+  */
+  private class MockModule implements Module {
+    /**
+    *
+    */
+    @Override
+    public void configure(Binder binder) {
+      binder.bind(WidgetDAO.class).toInstance(dao);
+      binder.bind(Clusters.class).toInstance(
+          EasyMock.createNiceMock(Clusters.class));
+      binder.bind(Cluster.class).toInstance(
+              EasyMock.createNiceMock(Cluster.class));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2e3726/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
index 9d068f8..af9dcda 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
@@ -217,7 +217,7 @@ public class UpgradeCatalog210Test {
   }
 
   /**
-   * Verify that the user_widget, widget_layout, and widget_layout_user_widget tables are created correctly.
+   * Verify that the widget, widget_layout, and widget_layout_user_widget tables are created correctly.
    */
   class WidgetSectionDDL implements SectionDDL {
 
@@ -230,7 +230,7 @@ public class UpgradeCatalog210Test {
       Capture<List<DBColumnInfo>> widgetLayoutColumnsCapture = new Capture<List<DBColumnInfo>>();
       Capture<List<DBColumnInfo>> widgetLayoutUserWidgetColumnsCapture = new Capture<List<DBColumnInfo>>();
 
-      captures.put("user_widget", userWidgetColumnsCapture);
+      captures.put("widget", userWidgetColumnsCapture);
       captures.put("widget_layout", widgetLayoutColumnsCapture);
       captures.put("widget_layout_user_widget", widgetLayoutUserWidgetColumnsCapture);
     }
@@ -240,12 +240,12 @@ public class UpgradeCatalog210Test {
      */
     @Override
     public void execute(DBAccessor dbAccessor) throws SQLException {
-      Capture<List<DBColumnInfo>> userWidgetColumnsCapture = captures.get("user_widget");
+      Capture<List<DBColumnInfo>> userWidgetColumnsCapture = captures.get("widget");
       Capture<List<DBColumnInfo>> widgetLayoutColumnsCapture = captures.get("widget_layout");
       Capture<List<DBColumnInfo>> widgetLayoutUserWidgetColumnsCapture = captures.get("widget_layout_user_widget");
 
       // User Widget
-      dbAccessor.createTable(eq("user_widget"),
+      dbAccessor.createTable(eq("widget"),
           capture(userWidgetColumnsCapture), eq("id"));
 
       // Widget Layout
@@ -254,7 +254,7 @@ public class UpgradeCatalog210Test {
 
       // Widget Layout User Widget
       dbAccessor.createTable(eq("widget_layout_user_widget"),
-          capture(widgetLayoutUserWidgetColumnsCapture), eq("widget_layout_id"), eq("user_widget_id"));
+          capture(widgetLayoutUserWidgetColumnsCapture), eq("widget_layout_id"), eq("widget_id"));
     }
 
     /**
@@ -262,12 +262,12 @@ public class UpgradeCatalog210Test {
      */
     @Override
     public void verify(DBAccessor dbAccessor) throws SQLException {
-      Capture<List<DBColumnInfo>> userWidgetColumnsCapture = captures.get("user_widget");
+      Capture<List<DBColumnInfo>> widgetColumnsCapture = captures.get("widget");
       Capture<List<DBColumnInfo>> widgetLayoutColumnsCapture = captures.get("widget_layout");
       Capture<List<DBColumnInfo>> widgetLayoutUserWidgetColumnsCapture = captures.get("widget_layout_user_widget");
 
       // Verify widget tables
-      assertEquals(12, userWidgetColumnsCapture.getValue().size());
+      assertEquals(12, widgetColumnsCapture.getValue().size());
       assertEquals(7, widgetLayoutColumnsCapture.getValue().size());
       assertEquals(3, widgetLayoutUserWidgetColumnsCapture.getValue().size());
     }