You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2016/06/24 06:00:49 UTC

[20/44] sentry git commit: SENTRY-1287: Create sentry-service-server module(Colin Ma, reviewed by Dapeng Sun)

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
new file mode 100644
index 0000000..3058650
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java
@@ -0,0 +1,233 @@
+/**
+ * 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.sentry.provider.db.log.util;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.model.db.AccessConstants;
+import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
+import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleGrantPrivilegeRequest;
+import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleRevokePrivilegeRequest;
+import org.apache.sentry.provider.db.service.thrift.TSentryGrantOption;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public final class CommandUtil {
+    
+  public CommandUtil() {
+    // Make constructor private to avoid instantiation
+  }
+
+  public static String createCmdForCreateOrDropRole(String roleName,
+      boolean isCreate) {
+    if (isCreate) {
+      return "CREATE ROLE " + roleName;
+    }
+    return "DROP ROLE " + roleName;
+  }
+
+  public static String createCmdForRoleAddGroup(String roleName, String groups) {
+    return createCmdForRoleGrant(roleName, groups, true, true);
+  }
+
+  public static String createCmdForRoleDeleteGroup(String roleName, String groups) {
+    return createCmdForRoleGrant(roleName, groups, false, true);
+  }
+
+  private static String createCmdForRoleGrant(String roleName, String principals,
+      boolean isGrant, boolean isGroup) {
+    StringBuilder sb = new StringBuilder();
+    if (isGrant) {
+      sb.append("GRANT ROLE ");
+    } else {
+      sb.append("REVOKE ROLE ");
+    }
+    sb.append(roleName);
+    if (isGrant) {
+      sb.append(" TO ");
+    } else {
+      sb.append(" FROM ");
+    }
+
+    String principalType = isGroup ? "GROUP" : "USER";
+    if (!StringUtils.isEmpty(principals)) {
+      sb.append(principalType).append(" ").append(principals);
+    } else {
+      sb = new StringBuilder("Missing " + principalType + " information.");
+    }
+
+    return sb.toString();
+  }
+
+  public static String createCmdForRoleAddUser(String roleName, String users) {
+    return createCmdForRoleGrant(roleName, users, true, false);
+  }
+
+  public static String createCmdForRoleDeleteUser(String roleName, String users) {
+    return createCmdForRoleGrant(roleName, users, false, false);
+  }
+
+  public static String createCmdForGrantPrivilege(
+      TAlterSentryRoleGrantPrivilegeRequest request) {
+    return createCmdForGrantOrRevokePrivileges(request.getRoleName(),
+        request.getPrivileges(), true);
+  }
+
+  public static String createCmdForRevokePrivilege(
+      TAlterSentryRoleRevokePrivilegeRequest request) {
+    return createCmdForGrantOrRevokePrivileges(request.getRoleName(),
+        request.getPrivileges(), false);
+  }
+
+  private static String createCmdForGrantOrRevokePrivileges(String roleName,
+      Set<TSentryPrivilege> privileges, boolean isGrant) {
+    StringBuilder sb = new StringBuilder();
+    if (privileges != null) {
+      for (TSentryPrivilege privilege : privileges) {
+        sb.append(createCmdForGrantOrRevokePrivilege(roleName, privilege, isGrant));
+      }
+    }
+    return sb.toString();
+  }
+
+  private static String createCmdForGrantOrRevokePrivilege(String roleName,
+      TSentryPrivilege privilege, boolean isGrant) {
+    StringBuilder sb = new StringBuilder();
+    if (isGrant) {
+      sb.append("GRANT ");
+    } else {
+      sb.append("REVOKE ");
+    }
+
+    String action = privilege.getAction();
+    String privilegeScope = privilege.getPrivilegeScope();
+    if (AccessConstants.ALL.equalsIgnoreCase(action)) {
+      sb.append("ALL");
+    } else {
+      if (action != null) {
+        action = action.toUpperCase();
+      }
+      sb.append(action);
+    }
+
+    sb.append(" ON ").append(privilege.getPrivilegeScope()).append(" ");
+    if (PrivilegeScope.DATABASE.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getDbName());
+    } else if (PrivilegeScope.TABLE.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getTableName());
+    } else if (PrivilegeScope.SERVER.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getServerName());
+    } else if (PrivilegeScope.URI.name().equalsIgnoreCase(privilegeScope)) {
+      sb.append(privilege.getURI());
+    }
+
+    if (isGrant) {
+      sb.append(" TO ROLE ");
+    } else {
+      sb.append(" FROM ROLE ");
+    }
+    sb.append(roleName);
+
+    if (privilege.getGrantOption() == TSentryGrantOption.TRUE) {
+      sb.append(" WITH GRANT OPTION");
+    }
+
+    return sb.toString();
+  }
+
+  public static String createCmdForGrantGMPrivilege(
+      org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest request) {
+    return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), request.getPrivilege(), true);
+  }
+
+  public static String createCmdForRevokeGMPrivilege(
+      org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest request) {
+    return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), request.getPrivilege(),
+        false);
+  }
+
+  private static String createCmdForGrantOrRevokeGMPrivilege(String roleName,
+      org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege privilege,
+      boolean isGrant) {
+    StringBuilder sb = new StringBuilder();
+    if (isGrant) {
+      sb.append("GRANT ");
+    } else {
+      sb.append("REVOKE ");
+    }
+
+    String action = privilege.getAction();
+    if (AccessConstants.ALL.equalsIgnoreCase(action)) {
+      sb.append("ALL");
+    } else {
+      if (action != null) {
+        action = action.toUpperCase();
+      }
+      sb.append(action);
+    }
+
+    sb.append(" ON");
+
+    List<TAuthorizable> authorizables = privilege.getAuthorizables();
+    if (authorizables != null) {
+      for (TAuthorizable authorizable : authorizables) {
+        sb.append(" ").append(authorizable.getType()).append(" ").append(authorizable.getName());
+      }
+    }
+
+    if (isGrant) {
+      sb.append(" TO ROLE ");
+    } else {
+      sb.append(" FROM ROLE ");
+    }
+    sb.append(roleName);
+
+    if (privilege.getGrantOption() == org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption.TRUE) {
+      sb.append(" WITH GRANT OPTION");
+    }
+
+    return sb.toString();
+  }
+
+  // Check if the given IP is one of the local IP.
+  @VisibleForTesting
+  public static boolean assertIPInAuditLog(String ipInAuditLog) throws Exception {
+    if (ipInAuditLog == null) {
+      return false;
+    }
+    Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
+    while (netInterfaces.hasMoreElements()) {
+      NetworkInterface ni = netInterfaces.nextElement();
+      Enumeration<InetAddress> ips = ni.getInetAddresses();
+      while (ips.hasMoreElements()) {
+        if (ipInAuditLog.indexOf(ips.nextElement().getHostAddress()) != -1) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
new file mode 100644
index 0000000..2e71ce0
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java
@@ -0,0 +1,162 @@
+/**
+ * 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.sentry.provider.db.log.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sentry.provider.db.service.thrift.*;
+
+public final class Constants {
+  public final static String AUDIT_LOGGER_NAME = "sentry.hive.authorization.ddl.logger";
+  public final static String AUDIT_LOGGER_NAME_GENERIC = "sentry.generic.authorization.ddl.logger";
+
+  public final static String LOG_FIELD_SERVICE_NAME = "serviceName";
+  public final static String LOG_FIELD_USER_NAME = "userName";
+  public final static String LOG_FIELD_IMPERSONATOR = "impersonator";
+  public final static String LOG_FIELD_IP_ADDRESS = "ipAddress";
+  public final static String LOG_FIELD_OPERATION = "operation";
+  public final static String LOG_FIELD_EVENT_TIME = "eventTime";
+  public final static String LOG_FIELD_OPERATION_TEXT = "operationText";
+  public final static String LOG_FIELD_ALLOWED = "allowed";
+  public final static String LOG_FIELD_DATABASE_NAME = "databaseName";
+  public final static String LOG_FIELD_TABLE_NAME = "tableName";
+  public final static String LOG_FIELD_COLUMN_NAME = "column";
+  public final static String LOG_FIELD_RESOURCE_PATH = "resourcePath";
+  public final static String LOG_FIELD_OBJECT_TYPE = "objectType";
+  public final static String LOG_FIELD_COMPONENT = "component";
+
+  public final static String OPERATION_CREATE_ROLE = "CREATE_ROLE";
+  public final static String OPERATION_DROP_ROLE = "DROP_ROLE";
+  public final static String OPERATION_ADD_ROLE = "ADD_ROLE_TO_GROUP";
+  public final static String OPERATION_DELETE_ROLE = "DELETE_ROLE_FROM_GROUP";
+  public final static String OPERATION_ADD_ROLE_USER = "ADD_ROLE_TO_USER";
+  public final static String OPERATION_DELETE_ROLE_USER = "DELETE_ROLE_FROM_USER";
+  public final static String OPERATION_GRANT_PRIVILEGE = "GRANT_PRIVILEGE";
+  public final static String OPERATION_REVOKE_PRIVILEGE = "REVOKE_PRIVILEGE";
+
+  public final static String OBJECT_TYPE_PRINCIPAL = "PRINCIPAL";
+  public final static String OBJECT_TYPE_ROLE = "ROLE";
+
+  public final static String TRUE = "true";
+  public final static String FALSE = "false";
+
+  public static final Map<String, String> requestTypeToOperationMap = new HashMap<String, String>();
+  public static final Map<String, String> requestTypeToObjectTypeMap = new HashMap<String, String>();
+
+  static {
+    // for hive audit log
+    requestTypeToOperationMap.put(TCreateSentryRoleRequest.class.getName(),
+        Constants.OPERATION_CREATE_ROLE);
+    requestTypeToOperationMap.put(
+        TAlterSentryRoleGrantPrivilegeRequest.class.getName(),
+        Constants.OPERATION_GRANT_PRIVILEGE);
+    requestTypeToOperationMap.put(
+        TAlterSentryRoleRevokePrivilegeRequest.class.getName(),
+        Constants.OPERATION_REVOKE_PRIVILEGE);
+    requestTypeToOperationMap.put(TDropSentryRoleRequest.class.getName(),
+        Constants.OPERATION_DROP_ROLE);
+    requestTypeToOperationMap.put(
+        TAlterSentryRoleAddGroupsRequest.class.getName(),
+        Constants.OPERATION_ADD_ROLE);
+    requestTypeToOperationMap.put(
+        TAlterSentryRoleDeleteGroupsRequest.class.getName(),
+        Constants.OPERATION_DELETE_ROLE);
+    requestTypeToOperationMap.put(
+        TAlterSentryRoleAddUsersRequest.class.getName(),
+        Constants.OPERATION_ADD_ROLE_USER);
+    requestTypeToOperationMap.put(
+        TAlterSentryRoleDeleteUsersRequest.class.getName(),
+        Constants.OPERATION_DELETE_ROLE_USER);
+
+    // for generic model audit log
+    requestTypeToOperationMap.put(
+        org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest.class
+            .getName(), Constants.OPERATION_CREATE_ROLE);
+    requestTypeToOperationMap
+        .put(org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest.class
+            .getName(), Constants.OPERATION_DROP_ROLE);
+    requestTypeToOperationMap
+        .put(
+            org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest.class
+                .getName(), Constants.OPERATION_GRANT_PRIVILEGE);
+    requestTypeToOperationMap
+        .put(
+            org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest.class
+                .getName(), Constants.OPERATION_REVOKE_PRIVILEGE);
+    requestTypeToOperationMap.put(
+        org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest.class
+            .getName(), Constants.OPERATION_ADD_ROLE);
+    requestTypeToOperationMap
+        .put(
+            org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest.class
+                .getName(), Constants.OPERATION_DELETE_ROLE);
+
+    // for hive audit log
+    requestTypeToObjectTypeMap.put(TCreateSentryRoleRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(TDropSentryRoleRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(
+        TAlterSentryRoleAddGroupsRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(
+        TAlterSentryRoleDeleteGroupsRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(
+        TAlterSentryRoleAddUsersRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(
+        TAlterSentryRoleDeleteUsersRequest.class.getName(),
+        Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(
+        TAlterSentryRoleGrantPrivilegeRequest.class.getName(),
+        Constants.OBJECT_TYPE_PRINCIPAL);
+    requestTypeToObjectTypeMap.put(
+        TAlterSentryRoleRevokePrivilegeRequest.class.getName(),
+        Constants.OBJECT_TYPE_PRINCIPAL);
+    // for generic model audit log
+    requestTypeToObjectTypeMap.put(
+        org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest.class
+            .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap
+        .put(org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest.class
+            .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap.put(
+        org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest.class
+            .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap
+        .put(
+            org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest.class
+                .getName(), Constants.OBJECT_TYPE_ROLE);
+    requestTypeToObjectTypeMap
+        .put(
+            org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest.class
+                .getName(), Constants.OBJECT_TYPE_PRINCIPAL);
+    requestTypeToObjectTypeMap
+        .put(
+            org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest.class
+                .getName(), Constants.OBJECT_TYPE_PRINCIPAL);
+  }
+
+  private Constants() {
+    // Make constructor private to avoid instantiation
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
new file mode 100644
index 0000000..55b61ac
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java
@@ -0,0 +1,497 @@
+/**
+vim  * 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.sentry.provider.db.service.model;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_JOINER;
+import static org.apache.sentry.core.common.utils.SentryConstants.KV_JOINER;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.model.db.AccessConstants;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+/**
+ * Database backed Sentry Generic Privilege for new authorization Model
+ * Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryGMPrivilege {
+  private static final String PREFIX_RESOURCE_NAME = "resourceName";
+  private static final String PREFIX_RESOURCE_TYPE = "resourceType";
+  private static final String NULL_COL = "__NULL__";
+  private static final String SERVICE_SCOPE = "Server";
+  private static final int AUTHORIZABLE_LEVEL = 4;
+  /**
+   * The authorizable List has been stored into resourceName and resourceField columns
+   * We assume that the generic model privilege for any component(hive/impala or solr) doesn't exceed four level.
+   * This generic model privilege currently can support maximum 4 level.
+   **/
+  private String resourceName0 = NULL_COL; //NOPMD
+  private String resourceType0 = NULL_COL; //NOPMD
+  private String resourceName1 = NULL_COL; //NOPMD
+  private String resourceType1 = NULL_COL; //NOPMD
+  private String resourceName2 = NULL_COL; //NOPMD
+  private String resourceType2 = NULL_COL; //NOPMD
+  private String resourceName3 = NULL_COL; //NOPMD
+  private String resourceType3 = NULL_COL; //NOPMD
+
+
+  private String serviceName;
+  private String componentName;
+  private String action;
+  private String scope;
+
+  private Boolean grantOption = false;
+  // roles this privilege is a part of
+  private Set<MSentryRole> roles;
+  private long createTime;
+
+  public MSentryGMPrivilege() {
+    this.roles = new HashSet<MSentryRole>();
+  }
+
+  public MSentryGMPrivilege(String componentName, String serviceName,
+                                 List<? extends Authorizable> authorizables,
+                                 String action, Boolean grantOption) {
+    this.componentName = componentName;
+    this.serviceName = serviceName;
+    this.action = action;
+    this.grantOption = grantOption;
+    this.roles = new HashSet<MSentryRole>();
+    this.createTime = System.currentTimeMillis();
+    setAuthorizables(authorizables);
+  }
+
+  public MSentryGMPrivilege(MSentryGMPrivilege copy) {
+    this.action = copy.action;
+    this.componentName = copy.componentName;
+    this.serviceName = copy.serviceName;
+    this.grantOption = copy.grantOption;
+    this.scope = copy.scope;
+    this.createTime = copy.createTime;
+    setAuthorizables(copy.getAuthorizables());
+    this.roles = new HashSet<MSentryRole>();
+    for (MSentryRole role : copy.roles) {
+      roles.add(role);
+    }
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  public String getComponentName() {
+    return componentName;
+  }
+
+  public void setComponentName(String componentName) {
+    this.componentName = componentName;
+  }
+
+  public String getAction() {
+    return action;
+  }
+
+  public void setAction(String action) {
+    this.action = action;
+  }
+
+  public Boolean getGrantOption() {
+    return grantOption;
+  }
+
+  public void setGrantOption(Boolean grantOption) {
+    this.grantOption = grantOption;
+  }
+
+  public Set<MSentryRole> getRoles() {
+    return roles;
+  }
+
+  public void setRoles(Set<MSentryRole> roles) {
+    this.roles = roles;
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTime = createTime;
+  }
+
+  public String getScope() {
+    return scope;
+  }
+
+  public List<? extends Authorizable> getAuthorizables() {
+    List<Authorizable> authorizables = Lists.newArrayList();
+    //construct atuhorizable lists
+    for (int i = 0; i < AUTHORIZABLE_LEVEL; i++) {
+      final String resourceName = (String) getField(this, PREFIX_RESOURCE_NAME + String.valueOf(i));
+      final String resourceTYpe = (String) getField(this, PREFIX_RESOURCE_TYPE + String.valueOf(i));
+
+      if (notNULL(resourceName) && notNULL(resourceTYpe)) {
+        authorizables.add(new Authorizable() {
+          @Override
+          public String getTypeName() {
+            return resourceTYpe;
+          }
+          @Override
+          public String getName() {
+            return resourceName;
+          }
+        });
+      }
+    }
+    return authorizables;
+  }
+
+  /**
+   * Only allow strict hierarchies. That is, can level =1 be not null when level = 0 is null
+   * @param authorizables
+   */
+  public void setAuthorizables(List<? extends Authorizable> authorizables) {
+    if (authorizables == null || authorizables.isEmpty()) {
+      //service scope
+      scope = SERVICE_SCOPE;
+      return;
+    }
+    if (authorizables.size() > AUTHORIZABLE_LEVEL) {
+      throw new IllegalStateException("This generic privilege model only supports maximum 4 level.");
+    }
+
+    for (int i = 0; i < authorizables.size(); i++) {
+      Authorizable authorizable = authorizables.get(i);
+      if (authorizable == null) {
+        String msg = String.format("The authorizable can't be null. Please check authorizables[%d]:", i);
+        throw new IllegalStateException(msg);
+      }
+      String resourceName = authorizable.getName();
+      String resourceTYpe = authorizable.getTypeName();
+      if (isNULL(resourceName) || isNULL(resourceTYpe)) {
+        String msg = String.format("The name and type of authorizable can't be empty or null.Please check authorizables[%d]", i);
+        throw new IllegalStateException(msg);
+      }
+      setField(this, PREFIX_RESOURCE_NAME + String.valueOf(i), toNULLCol(resourceName));
+      setField(this, PREFIX_RESOURCE_TYPE + String.valueOf(i), toNULLCol(resourceTYpe));
+      scope = resourceTYpe;
+    }
+  }
+
+  public void appendRole(MSentryRole role) {
+    if (roles.add(role)) {
+      role.appendGMPrivilege(this);
+    }
+  }
+
+  public void removeRole(MSentryRole role) {
+    if(roles.remove(role)) {
+      role.removeGMPrivilege(this);
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((action == null) ? 0 : action.hashCode());
+    result = prime * result + ((componentName == null) ? 0 : componentName.hashCode());
+    result = prime * result + ((serviceName == null) ? 0 : serviceName.hashCode());
+    result = prime * result + ((grantOption == null) ? 0 : grantOption.hashCode());
+    result = prime * result + ((scope == null) ? 0 : scope.hashCode());
+
+    for (Authorizable authorizable : getAuthorizables()) {
+      result = prime * result + authorizable.getName().hashCode();
+      result = prime * result + authorizable.getTypeName().hashCode();
+    }
+
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    List<String> unifiedNames = Lists.newArrayList();
+    for (Authorizable auth : getAuthorizables()) {
+      unifiedNames.add(KV_JOINER.join(auth.getTypeName(),auth.getName()));
+    }
+
+    return "MSentryGMPrivilege ["
+        + "serverName=" + serviceName + ", componentName=" + componentName
+        + ", authorizables=" + AUTHORIZABLE_JOINER.join(unifiedNames)+ ", scope=" + scope
+        + ", action=" + action + ", roles=[...]"  + ", createTime="
+        + createTime + ", grantOption=" + grantOption +"]";
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+      if (this == obj) {
+          return true;
+      }
+      if (obj == null) {
+          return false;
+      }
+      if (getClass() != obj.getClass()) {
+          return false;
+      }
+      MSentryGMPrivilege other = (MSentryGMPrivilege) obj;
+      if (action == null) {
+          if (other.action != null) {
+              return false;
+          }
+      } else if (!action.equalsIgnoreCase(other.action)) {
+          return false;
+      }
+      if (scope == null) {
+        if (other.scope != null) {
+            return false;
+        }
+      } else if (!scope.equals(other.scope)) {
+        return false;
+      }
+      if (serviceName == null) {
+          if (other.serviceName != null) {
+              return false;
+          }
+      } else if (!serviceName.equals(other.serviceName)) {
+          return false;
+      }
+      if (componentName == null) {
+          if (other.componentName != null) {
+              return false;
+          }
+      } else if (!componentName.equals(other.componentName)) {
+          return false;
+      }
+      if (grantOption == null) {
+        if (other.grantOption != null) {
+          return false;
+        }
+      } else if (!grantOption.equals(other.grantOption)) {
+        return false;
+      }
+
+      List<? extends Authorizable> authorizables = getAuthorizables();
+      List<? extends Authorizable> otherAuthorizables = other.getAuthorizables();
+
+      if (authorizables.size() != otherAuthorizables.size()) {
+        return false;
+      }
+      for (int i = 0; i < authorizables.size(); i++) {
+        String o1 = KV_JOINER.join(authorizables.get(i).getTypeName(),
+                                         authorizables.get(i).getName());
+        String o2 = KV_JOINER.join(otherAuthorizables.get(i).getTypeName(),
+                                   otherAuthorizables.get(i).getName());
+        if (!o1.equals(o2)) {
+          return false;
+        }
+      }
+      return true;
+  }
+
+  /**
+   * Return true if this privilege implies request privilege
+   * Otherwise, return false
+   * @param other, other privilege
+   */
+  public boolean implies(MSentryGMPrivilege request) {
+    //component check
+    if (!componentName.equals(request.getComponentName())) {
+      return false;
+    }
+    //service check
+    if (!serviceName.equals(request.getServiceName())) {
+      return false;
+    }
+    // check action implies
+    if (!action.equalsIgnoreCase(AccessConstants.ALL)
+        && !action.equalsIgnoreCase(request.getAction())
+        && !action.equalsIgnoreCase(AccessConstants.ACTION_ALL)) {
+      return false;
+    }
+    //check authorizable list implies
+    Iterator<? extends Authorizable> existIterator = getAuthorizables().iterator();
+    Iterator<? extends Authorizable> requestIterator = request.getAuthorizables().iterator();
+    while (existIterator.hasNext() && requestIterator.hasNext()) {
+      Authorizable existAuth = existIterator.next();
+      Authorizable requestAuth = requestIterator.next();
+      //check authorizable type
+      if (!existAuth.getTypeName().equals(requestAuth.getTypeName())) {
+        return false;
+      }
+      //check authorizable name
+      if (!existAuth.getName().equals(requestAuth.getName())) {
+        /**The persistent authorizable isn't equal the request authorizable
+        * but the following situations are pass check
+        * The name of persistent authorizable is ALL or "*"
+        */
+        if (existAuth.getName().equalsIgnoreCase(AccessConstants.ACTION_ALL)
+            || existAuth.getName().equalsIgnoreCase(AccessConstants.ALL)) {
+          continue;
+        } else {
+          return false;
+        }
+      }
+    }
+
+    if ( !existIterator.hasNext() && !requestIterator.hasNext() ){
+      /**
+       * The persistent privilege has the same authorizables size as the requested privilege
+       * The check is pass
+       */
+      return true;
+
+    } else if (existIterator.hasNext()) {
+      /**
+       * The persistent privilege has much more authorizables than request privilege,so its scope is less
+       * than the requested privilege.
+       * There is a situation that the check is pass, the name of the exceeding authorizables is ALL or "*".
+       * Take the Solr for example,the exist privilege is collection=c1->field=*->action=query
+       * the request privilege is collection=c1->action=query, the check is pass
+       */
+      while (existIterator.hasNext()) {
+        Authorizable existAuthorizable = existIterator.next();
+        if (existAuthorizable.getName().equalsIgnoreCase(AccessConstants.ALL)
+            || existAuthorizable.getName().equalsIgnoreCase(AccessConstants.ACTION_ALL)) {
+          continue;
+        } else {
+          return false;
+        }
+      }
+    } else {
+      /**
+       * The requested privilege has much more authorizables than persistent privilege, so its scope is less
+       * than the persistent privilege
+       * The check is pass
+       */
+      return true;
+    }
+
+    return true;
+  }
+
+  public static String toNULLCol(String col) {
+    return Strings.isNullOrEmpty(col) ? NULL_COL : col;
+  }
+
+  public static boolean notNULL(String s) {
+    return !(Strings.isNullOrEmpty(s) || NULL_COL.equals(s));
+  }
+
+  public static boolean isNULL(String s) {
+    return !notNULL(s);
+  }
+
+  public static <T> void setField(Object obj, String fieldName, T fieldValue) {
+    try {
+      Class<?> clazz = obj.getClass();
+      Field field=clazz.getDeclaredField(fieldName);
+      field.setAccessible(true);
+      field.set(obj, fieldValue);
+    } catch (Exception e) {
+      throw new RuntimeException("setField error: " + e.getMessage(), e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> T getField(Object obj, String fieldName) {
+    try {
+      Class<?> clazz = obj.getClass();
+      Field field=clazz.getDeclaredField(fieldName);
+      field.setAccessible(true);
+      return (T)field.get(obj);
+    } catch (Exception e) {
+      throw new RuntimeException("getField error: " + e.getMessage(), e);
+    }
+  }
+
+  /**
+   * return the query to execute in JDO for search the given privilege
+   * @param privilege
+   * @return query
+   */
+  public static String toQuery(MSentryGMPrivilege privilege) {
+    StringBuilder query = new StringBuilder();
+    query.append("serviceName == \"" + toNULLCol(privilege.getServiceName()) + "\" ");
+    query.append("&& componentName == \"" + toNULLCol(privilege.getComponentName()) + "\" ");
+    query.append("&& scope == \"" + toNULLCol(privilege.getScope()) + "\" ");
+    query.append("&& action == \"" + toNULLCol(privilege.getAction()) + "\"");
+    if (privilege.getGrantOption() == null) {
+      query.append("&& this.grantOption == null ");
+    } else if (privilege.getGrantOption()) {
+      query.append("&& grantOption ");
+    } else {
+      query.append("&& !grantOption ");
+    }
+    List<? extends Authorizable> authorizables = privilege.getAuthorizables();
+    for (int i = 0; i < AUTHORIZABLE_LEVEL; i++) {
+      String resourceName = PREFIX_RESOURCE_NAME + String.valueOf(i);
+      String resourceType = PREFIX_RESOURCE_TYPE + String.valueOf(i);
+
+      if (i >= authorizables.size()) {
+        query.append("&& " + resourceName + " == \"" + NULL_COL + "\" ");
+        query.append("&& " + resourceType + " == \"" + NULL_COL + "\" ");
+      } else {
+        query.append("&& " + resourceName + " == \"" + authorizables.get(i).getName() + "\" ");
+        query.append("&& " + resourceType + " == \"" + authorizables.get(i).getTypeName() + "\" ");
+      }
+    }
+    return query.toString();
+  }
+
+  /**
+   * Get the query to execute in the JDO deducing privileges include the scope of according to the given privilege
+   * The query was used in three privilege operations:
+   * 1.revoking privilege
+   * 2.renaming privilege
+   * 3.dropping privilege
+   * Take the Solr for example, if there exists three privileges such as p1:Collection=c1->action=query,
+   * p2:Collection=c1->Field=f1->action=query and p3:Collection=c1->Field=f2->action=query.
+   * When the revoking operation happens, the request privilege is p4:Collection=c1->action=query.
+   * The result is that not only p1 should be revoked, but also p2 and p3 should be revoked together.
+   * So the populateIncludePrivilegesQuery should be Collection=c1
+   * @param privilege
+   * @return query
+   */
+  public static String populateIncludePrivilegesQuery(MSentryGMPrivilege privilege) {
+    StringBuilder query = new StringBuilder();
+    query.append("serviceName == \"" + toNULLCol(privilege.getServiceName()) + "\" ");
+    query.append("&& componentName == \"" + toNULLCol(privilege.getComponentName()) + "\" ");
+    List<? extends Authorizable> authorizables = privilege.getAuthorizables();
+    for (int i= 0 ; i < authorizables.size(); i++) {
+      String resourceName = PREFIX_RESOURCE_NAME + String.valueOf(i);
+      String resourceType = PREFIX_RESOURCE_TYPE + String.valueOf(i);
+      query.append("&& " + resourceName + " == \"" + authorizables.get(i).getName() + "\" ");
+      query.append("&& " + resourceType + " == \"" + authorizables.get(i).getTypeName() + "\" ");
+    }
+    return query.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
new file mode 100644
index 0000000..7e41c93
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
@@ -0,0 +1,116 @@
+/**
+ * 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.sentry.provider.db.service.model;
+
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+/**
+ * Database backed Sentry Group. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryGroup {
+
+  /**
+   * Group name is unique
+   */
+  private String groupName;
+  // set of roles granted to this group
+  private Set<MSentryRole> roles;
+  private long createTime;
+
+  public MSentryGroup(String groupName, long createTime, Set<MSentryRole> roles) {
+    this.setGroupName(groupName);
+    this.createTime = createTime;
+    this.roles = roles;
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTime = createTime;
+  }
+
+  public Set<MSentryRole> getRoles() {
+    return roles;
+  }
+
+  public String getGroupName() {
+    return groupName;
+  }
+
+  public void setGroupName(String groupName) {
+    this.groupName = groupName;
+  }
+
+  public void appendRole(MSentryRole role) {
+    if (roles.add(role)) {
+      role.appendGroup(this);
+    }
+  }
+
+  public void removeRole(MSentryRole role) {
+    if (roles.remove(role)) {
+      role.removeGroup(this);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryGroup [groupName=" + groupName + ", roles=[...]"
+        + ", createTime=" + createTime +  "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((groupName == null) ? 0 : groupName.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    MSentryGroup other = (MSentryGroup) obj;
+    if (createTime != other.createTime) {
+      return false;
+    }
+    if (groupName == null) {
+      if (other.groupName != null) {
+        return false;
+      }
+    } else if (!groupName.equals(other.groupName)) {
+      return false;
+    }
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java
new file mode 100644
index 0000000..4c3af79
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java
@@ -0,0 +1,332 @@
+/**
+ * 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.sentry.provider.db.service.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+import org.apache.sentry.core.common.utils.PathUtils;
+import org.apache.sentry.core.model.db.AccessConstants;
+import org.apache.sentry.provider.db.service.persistent.SentryStore;
+
+/**
+ * Database backed Sentry Privilege. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryPrivilege {
+
+  private String privilegeScope;
+  /**
+   * Privilege name is unique
+   */
+  private String serverName = "";
+  private String dbName = "";
+  private String tableName = "";
+  private String columnName = "";
+  private String URI = "";
+  private String action = "";
+  private Boolean grantOption = false;
+  // roles this privilege is a part of
+  private Set<MSentryRole> roles;
+  private long createTime;
+
+  public MSentryPrivilege() {
+    this.roles = new HashSet<MSentryRole>();
+  }
+
+  public MSentryPrivilege(String privilegeScope,
+      String serverName, String dbName, String tableName, String columnName,
+      String URI, String action, Boolean grantOption) {
+    this.privilegeScope = privilegeScope;
+    this.serverName = serverName;
+    this.dbName = SentryStore.toNULLCol(dbName);
+    this.tableName = SentryStore.toNULLCol(tableName);
+    this.columnName = SentryStore.toNULLCol(columnName);
+    this.URI = SentryStore.toNULLCol(URI);
+    this.action = SentryStore.toNULLCol(action);
+    this.grantOption = grantOption;
+    this.roles = new HashSet<MSentryRole>();
+  }
+
+  public MSentryPrivilege(String privilegeScope,
+      String serverName, String dbName, String tableName, String columnName,
+      String URI, String action) {
+    this(privilegeScope, serverName, dbName, tableName,
+        columnName, URI, action, false);
+  }
+
+  public MSentryPrivilege(MSentryPrivilege other) {
+    this.privilegeScope = other.privilegeScope;
+    this.serverName = other.serverName;
+    this.dbName = SentryStore.toNULLCol(other.dbName);
+    this.tableName = SentryStore.toNULLCol(other.tableName);
+    this.columnName = SentryStore.toNULLCol(other.columnName);
+    this.URI = SentryStore.toNULLCol(other.URI);
+    this.action = SentryStore.toNULLCol(other.action);
+    this.grantOption = other.grantOption;
+    this.roles = new HashSet<MSentryRole>();
+    for (MSentryRole role : other.roles) {
+      roles.add(role);
+    }
+  }
+
+  public String getServerName() {
+    return serverName;
+  }
+
+  public void setServerName(String serverName) {
+    this.serverName = (serverName == null) ? "" : serverName;
+  }
+
+  public String getDbName() {
+    return dbName;
+  }
+
+  public void setDbName(String dbName) {
+    this.dbName = (dbName == null) ? "" : dbName;
+  }
+
+  public String getTableName() {
+    return tableName;
+  }
+
+  public void setTableName(String tableName) {
+    this.tableName = (tableName == null) ? "" : tableName;
+  }
+
+  public String getColumnName() {
+    return columnName;
+  }
+
+  public void setColumnName(String columnName) {
+    this.columnName = (columnName == null) ? "" : columnName;
+  }
+
+  public String getURI() {
+    return URI;
+  }
+
+  public void setURI(String uRI) {
+    URI = (uRI == null) ? "" : uRI;
+  }
+
+  public String getAction() {
+    return action;
+  }
+
+  public void setAction(String action) {
+    this.action = (action == null) ? "" : action;
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTime = createTime;
+  }
+
+  public String getPrivilegeScope() {
+    return privilegeScope;
+  }
+
+  public void setPrivilegeScope(String privilegeScope) {
+    this.privilegeScope = privilegeScope;
+  }
+
+   public Boolean getGrantOption() {
+     return grantOption;
+   }
+
+   public void setGrantOption(Boolean grantOption) {
+     this.grantOption = grantOption;
+   }
+
+  public void appendRole(MSentryRole role) {
+    roles.add(role);
+  }
+
+  public Set<MSentryRole> getRoles() {
+    return roles;
+  }
+
+  public void removeRole(MSentryRole role) {
+    roles.remove(role);
+    role.removePrivilege(this);
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryPrivilege [privilegeScope=" + privilegeScope
+        + ", serverName=" + serverName + ", dbName=" + dbName
+        + ", tableName=" + tableName + ", columnName=" + columnName
+        + ", URI=" + URI + ", action=" + action + ", roles=[...]"
+        + ", createTime=" + createTime + ", grantOption=" + grantOption +"]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((URI == null) ? 0 : URI.hashCode());
+    result = prime * result + ((action == null) ? 0 : action.hashCode());
+    result = prime * result + ((dbName == null) ? 0 : dbName.hashCode());
+    result = prime * result
+        + ((serverName == null) ? 0 : serverName.hashCode());
+    result = prime * result + ((tableName == null) ? 0 : tableName.hashCode());
+    result = prime * result
+        + ((columnName == null) ? 0 : columnName.hashCode());
+    result = prime * result
+        + ((grantOption == null) ? 0 : grantOption.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    MSentryPrivilege other = (MSentryPrivilege) obj;
+    if (URI == null) {
+      if (other.URI != null) {
+        return false;
+      }
+    } else if (!URI.equals(other.URI)) {
+      return false;
+    }
+    if (action == null) {
+      if (other.action != null) {
+        return false;
+      }
+    } else if (!action.equals(other.action)) {
+      return false;
+    }
+    if (dbName == null) {
+      if (other.dbName != null) {
+        return false;
+      }
+    } else if (!dbName.equals(other.dbName)) {
+      return false;
+    }
+    if (serverName == null) {
+      if (other.serverName != null) {
+        return false;
+      }
+    } else if (!serverName.equals(other.serverName)) {
+      return false;
+    }
+    if (tableName == null) {
+      if (other.tableName != null) {
+        return false;
+      }
+    } else if (!tableName.equals(other.tableName)) {
+      return false;
+    }
+    if (columnName == null) {
+      if (other.columnName != null) {
+        return false;
+      }
+    } else if (!columnName.equals(other.columnName)) {
+      return false;
+    }
+    if (grantOption == null) {
+      if (other.grantOption != null) {
+        return false;
+      }
+    } else if (!grantOption.equals(other.grantOption)) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Return true if this privilege implies other privilege
+   * Otherwise, return false
+   * @param other, other privilege
+   */
+  public boolean implies(MSentryPrivilege other) {
+    // serverName never be null
+    if (isNULL(serverName) || isNULL(other.serverName)) {
+      return false;
+    } else if (!serverName.equals(other.serverName)) {
+      return false;
+    }
+
+    // check URI implies
+    if (!isNULL(URI) && !isNULL(other.URI)) {
+      if (!PathUtils.impliesURI(URI, other.URI)) {
+        return false;
+      }
+      // if URI is NULL, check dbName and tableName
+    } else if (isNULL(URI) && isNULL(other.URI)) {
+      if (!isNULL(dbName)) {
+        if (isNULL(other.dbName)) {
+          return false;
+        } else if (!dbName.equals(other.dbName)) {
+          return false;
+        }
+      }
+      if (!isNULL(tableName)) {
+        if (isNULL(other.tableName)) {
+          return false;
+        } else if (!tableName.equals(other.tableName)) {
+          return false;
+        }
+      }
+      if (!isNULL(columnName)) {
+        if (isNULL(other.columnName)) {
+          return false;
+        } else if (!columnName.equals(other.columnName)) {
+          return false;
+        }
+      }
+      // if URI is not NULL, but other's URI is NULL, return false
+    } else if (!isNULL(URI) && isNULL(other.URI)){
+      return false;
+    }
+
+    // check action implies
+    if (!action.equalsIgnoreCase(AccessConstants.ALL)
+        && !action.equalsIgnoreCase(other.action)
+        && !action.equalsIgnoreCase(AccessConstants.ACTION_ALL)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  private boolean isNULL(String s) {
+    return SentryStore.isNULL(s);
+  }
+
+  public boolean isActionALL() {
+    return AccessConstants.ACTION_ALL.equalsIgnoreCase(action)
+        || AccessConstants.ALL.equals(action);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java
new file mode 100644
index 0000000..0484eaa
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java
@@ -0,0 +1,216 @@
+/**
+ * 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.sentry.provider.db.service.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Database backed Sentry Role. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryRole {
+
+  private String roleName;
+  // set of privileges granted to this role
+  private Set<MSentryPrivilege> privileges;
+  // set of generic model privileges grant ro this role
+  private Set<MSentryGMPrivilege> gmPrivileges;
+
+  // set of groups this role belongs to
+  private Set<MSentryGroup> groups;
+  // set of users this role belongs to
+  private Set<MSentryUser> users;
+  private long createTime;
+
+  public MSentryRole(String roleName, long createTime) {
+    this.roleName = roleName;
+    this.createTime = createTime;
+    privileges = new HashSet<MSentryPrivilege>();
+    gmPrivileges = new HashSet<MSentryGMPrivilege>();
+    groups = new HashSet<MSentryGroup>();
+    users = new HashSet<MSentryUser>();
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTime = createTime;
+  }
+
+  public String getRoleName() {
+    return roleName;
+  }
+
+  public void setRoleName(String roleName) {
+    this.roleName = roleName;
+  }
+
+  public void setPrivileges(Set<MSentryPrivilege> privileges) {
+    this.privileges = privileges;
+  }
+
+  public Set<MSentryPrivilege> getPrivileges() {
+    return privileges;
+  }
+
+  public Set<MSentryGMPrivilege> getGmPrivileges() {
+    return gmPrivileges;
+  }
+
+  public void setGmPrivileges(Set<MSentryGMPrivilege> gmPrivileges) {
+    this.gmPrivileges = gmPrivileges;
+  }
+
+  public void setGroups(Set<MSentryGroup> groups) {
+    this.groups = groups;
+  }
+
+  public Set<MSentryGroup> getGroups() {
+    return groups;
+  }
+
+  public Set<MSentryUser> getUsers() {
+    return users;
+  }
+
+  public void setUsers(Set<MSentryUser> users) {
+    this.users = users;
+  }
+
+  public void removePrivilege(MSentryPrivilege privilege) {
+    if (privileges.remove(privilege)) {
+      privilege.removeRole(this);
+    }
+  }
+
+  public void appendPrivileges(Set<MSentryPrivilege> privileges) {
+    this.privileges.addAll(privileges);
+  }
+
+  public void appendPrivilege(MSentryPrivilege privilege) {
+    if (privileges.add(privilege)) {
+      privilege.appendRole(this);
+    }
+  }
+
+  public void removeGMPrivilege(MSentryGMPrivilege gmPrivilege) {
+    if (gmPrivileges.remove(gmPrivilege)) {
+      gmPrivilege.removeRole(this);
+    }
+  }
+
+  public void appendGMPrivilege(MSentryGMPrivilege gmPrivilege) {
+    if (gmPrivileges.add(gmPrivilege)) {
+      gmPrivilege.appendRole(this);
+    }
+  }
+
+  public void removeGMPrivileges() {
+    for (MSentryGMPrivilege privilege : ImmutableSet.copyOf(gmPrivileges)) {
+      privilege.removeRole(this);
+    }
+    Preconditions.checkState(gmPrivileges.isEmpty(), "gmPrivileges should be empty: " + gmPrivileges);
+  }
+
+  public void appendGroups(Set<MSentryGroup> groups) {
+    this.groups.addAll(groups);
+  }
+
+  public void appendGroup(MSentryGroup group) {
+    if (groups.add(group)) {
+      group.appendRole(this);
+    }
+  }
+
+  public void removeGroup(MSentryGroup group) {
+    if (groups.remove(group)) {
+      group.removeRole(this);
+    }
+  }
+
+  public void appendUsers(Set<MSentryUser> users) {
+    this.users.addAll(users);
+  }
+
+  public void appendUser(MSentryUser user) {
+    if (users.add(user)) {
+      user.appendRole(this);
+    }
+  }
+
+  public void removeUser(MSentryUser user) {
+    if (users.remove(user)) {
+      user.removeRole(this);
+    }
+  }
+
+  public void removePrivileges() {
+    // copy is required since privilege.removeRole will call remotePrivilege
+    for (MSentryPrivilege privilege : ImmutableSet.copyOf(privileges)) {
+      privilege.removeRole(this);
+    }
+    Preconditions.checkState(privileges.isEmpty(), "Privileges should be empty: " + privileges);
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryRole [roleName=" + roleName + ", privileges=[..]" + ", gmPrivileges=[..]"
+        + ", groups=[...]" + ", users=[...]" + ", createTime=" + createTime + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((roleName == null) ? 0 : roleName.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    MSentryRole other = (MSentryRole) obj;
+    if (roleName == null) {
+      if (other.roleName != null) {
+        return false;
+      }
+    } else if (!roleName.equals(other.roleName)) {
+      return false;
+    }
+    return true;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryUser.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryUser.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryUser.java
new file mode 100644
index 0000000..ff57249
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryUser.java
@@ -0,0 +1,116 @@
+/**
+ * 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.sentry.provider.db.service.model;
+
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+/**
+ * Database backed Sentry User. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryUser {
+
+  /**
+   * User name is unique
+   */
+  private String userName;
+  // set of roles granted to this user
+  private Set<MSentryRole> roles;
+  private long createTime;
+
+  public MSentryUser(String userName, long createTime, Set<MSentryRole> roles) {
+    this.setUserName(userName);
+    this.createTime = createTime;
+    this.roles = roles;
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(long createTime) {
+    this.createTime = createTime;
+  }
+
+  public Set<MSentryRole> getRoles() {
+    return roles;
+  }
+
+  public String getUserName() {
+    return userName;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public void appendRole(MSentryRole role) {
+    if (roles.add(role)) {
+      role.appendUser(this);
+    }
+  }
+
+  public void removeRole(MSentryRole role) {
+    if (roles.remove(role)) {
+      role.removeUser(this);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryUser [userName=" + userName + ", roles=[...]" + ", createTime=" + createTime
+        + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((userName == null) ? 0 : userName.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    MSentryUser other = (MSentryUser) obj;
+    if (createTime != other.createTime) {
+      return false;
+    }
+    if (userName == null) {
+      if (other.userName != null) {
+        return false;
+      }
+    } else if (!userName.equals(other.userName)) {
+      return false;
+    }
+    return true;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryVersion.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryVersion.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryVersion.java
new file mode 100644
index 0000000..ff8830f
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryVersion.java
@@ -0,0 +1,66 @@
+/**
+ * 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.sentry.provider.db.service.model;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+@PersistenceCapable
+public class MSentryVersion {
+  private String schemaVersion;
+  private String versionComment;
+
+  public MSentryVersion() {
+  }
+
+  public MSentryVersion(String schemaVersion, String versionComment) {
+    this.schemaVersion = schemaVersion;
+    this.versionComment = versionComment;
+  }
+
+  /**
+   * @return the versionComment
+   */
+  public String getVersionComment() {
+    return versionComment;
+  }
+
+  /**
+   * @param versionComment
+   *          the versionComment to set
+   */
+  public void setVersionComment(String versionComment) {
+    this.versionComment = versionComment;
+  }
+
+  /**
+   * @return the schemaVersion
+   */
+  public String getSchemaVersion() {
+    return schemaVersion;
+  }
+
+  /**
+   * @param schemaVersion
+   *          the schemaVersion to set
+   */
+  public void setSchemaVersion(String schemaVersion) {
+    this.schemaVersion = schemaVersion;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
new file mode 100644
index 0000000..b3b9494
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
@@ -0,0 +1,242 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+  "http://java.sun.com/dtd/jdo_2_0.dtd">
+<!--
+  Size Limitations:
+
+  Indexed VARCHAR: 767 bytes (MySQL running on InnoDB Engine http://bugs.mysql.com/bug.php?id=13315)
+  Non-indexed VARCHAR: 4000 bytes (max length on Oracle 9i/10g/11g)
+
+-->
+<jdo>
+  <package name="org.apache.sentry.provider.db.service.model">
+    <class name="MSentryGroup" identity-type="datastore" table="SENTRY_GROUP" detachable="true">
+      <datastore-identity>
+        <column name="GROUP_ID"/>
+      </datastore-identity>
+      <field name="groupName">
+        <column name="GROUP_NAME" length="128" jdbc-type="VARCHAR"/>
+        <index name="SentryGroupName" unique="true"/>
+      </field>
+      <field name = "createTime">
+        <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+      </field>
+
+      <field name="roles" mapped-by="groups">
+         <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/>
+      </field>
+
+    </class>
+
+    <class name="MSentryUser" identity-type="datastore" table="SENTRY_USER" detachable="true">
+      <datastore-identity>
+        <column name="USER_ID"/>
+      </datastore-identity>
+      <field name="userName">
+        <column name="USER_NAME" length="128" jdbc-type="VARCHAR"/>
+        <index name="SentryUserName" unique="true"/>
+      </field>
+      <field name = "createTime">
+        <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+      </field>
+
+      <field name="roles" mapped-by="users">
+         <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/>
+      </field>
+
+    </class>
+
+    <class name="MSentryRole" identity-type="datastore" table="SENTRY_ROLE" detachable="true">
+      <datastore-identity>
+        <column name="ROLE_ID"/>
+      </datastore-identity>
+      <field name="roleName">
+        <column name="ROLE_NAME" length="128" jdbc-type="VARCHAR"/>
+        <index name="SentryRoleName" unique="true"/>
+      </field>
+      <field name = "createTime">
+        <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+      </field>
+      <field name = "privileges" table="SENTRY_ROLE_DB_PRIVILEGE_MAP" default-fetch-group="true">
+        <collection element-type="org.apache.sentry.provider.db.service.model.MSentryPrivilege"/>
+            <join>
+                <column name="ROLE_ID"/>
+            </join>
+            <element>
+                <column name="DB_PRIVILEGE_ID"/>
+            </element>
+      </field>
+
+      <field name = "gmPrivileges" table="SENTRY_ROLE_GM_PRIVILEGE_MAP" default-fetch-group="true">
+        <collection element-type="org.apache.sentry.provider.db.service.model.MSentryGMPrivilege"/>
+            <join>
+                <column name="ROLE_ID"/>
+            </join>
+            <element>
+                <column name="GM_PRIVILEGE_ID"/>
+            </element>
+      </field>
+
+      <field name = "groups" table="SENTRY_ROLE_GROUP_MAP" default-fetch-group="true">
+        <collection element-type="org.apache.sentry.provider.db.service.model.MSentryGroup"/>
+            <join>
+                <column name="ROLE_ID"/>
+            </join>
+            <element>
+                <column name="GROUP_ID"/>
+            </element>
+      </field>
+
+      <field name = "users" table="SENTRY_ROLE_USER_MAP" default-fetch-group="true">
+        <collection element-type="org.apache.sentry.provider.db.service.model.MSentryUser"/>
+            <join>
+                <column name="ROLE_ID"/>
+            </join>
+            <element>
+                <column name="USER_ID"/>
+            </element>
+      </field>
+    </class>
+
+    <class name="MSentryPrivilege" identity-type="datastore" table="SENTRY_DB_PRIVILEGE" detachable="true">
+      <datastore-identity>
+        <column name="DB_PRIVILEGE_ID"/>
+      </datastore-identity>
+      <index name="PRIVILEGE_INDEX" unique="true">
+        <field name="serverName"/>
+        <field name="dbName"/>
+        <field name="tableName"/>
+        <field name="columnName"/>
+        <field name="URI"/>
+        <field name="action"/>
+        <field name="grantOption"/>
+      </index>
+      <field name="privilegeScope">
+        <column name="PRIVILEGE_SCOPE" length="40" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="serverName">
+        <column name="SERVER_NAME" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="dbName">
+        <column name="DB_NAME" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="tableName">
+        <column name="TABLE_NAME" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="columnName">
+        <column name="COLUMN_NAME" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="URI">
+        <column name="URI" length="4000" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="action">
+        <column name="ACTION" length="40" jdbc-type="VARCHAR"/>
+      </field>
+      <field name = "createTime">
+        <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+      </field>
+      <field name="grantOption">
+        <column name="WITH_GRANT_OPTION" length="1" jdbc-type="CHAR"/>
+      </field>
+      <field name="roles" mapped-by="privileges">
+         <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/>
+      </field>
+    </class>
+
+    <class name="MSentryGMPrivilege" identity-type="datastore" table="SENTRY_GM_PRIVILEGE" detachable="true">
+      <datastore-identity>
+        <column name="GM_PRIVILEGE_ID"/>
+      </datastore-identity>
+      <index name="GM_PRIVILEGE_INDEX" unique="true">
+        <field name="componentName"/>
+        <field name="serviceName"/>
+        <field name="resourceName0"/>
+        <field name="resourceType0"/>
+        <field name="resourceName1"/>
+        <field name="resourceType1"/>
+        <field name="resourceName2"/>
+        <field name="resourceType2"/>
+        <field name="resourceName3"/>
+        <field name="resourceType3"/>
+        <field name="action"/>
+        <field name="grantOption"/>
+      </index>
+      <field name="componentName">
+        <column name="COMPONENT_NAME" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="serviceName">
+        <column name="SERVICE_NAME" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceName0">
+        <column name="RESOURCE_NAME_0" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceType0">
+        <column name="RESOURCE_TYPE_0" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceName1">
+        <column name="RESOURCE_NAME_1" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceType1">
+        <column name="RESOURCE_TYPE_1" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceName2">
+        <column name="RESOURCE_NAME_2" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceType2">
+        <column name="RESOURCE_TYPE_2" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceName3">
+        <column name="RESOURCE_NAME_3" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="resourceType3">
+        <column name="RESOURCE_TYPE_3" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="action">
+        <column name="ACTION" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name="scope">
+        <column name="SCOPE" length="100" jdbc-type="VARCHAR"/>
+      </field>
+      <field name = "createTime">
+        <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+      </field>
+      <field name="grantOption">
+        <column name="WITH_GRANT_OPTION" length="1" jdbc-type="CHAR"/>
+      </field>
+      <field name="roles" mapped-by="gmPrivileges">
+        <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/>
+      </field>
+    </class>
+
+    <class name="MSentryVersion" table="SENTRY_VERSION" identity-type="datastore" detachable="true">
+      <datastore-identity>
+        <column name="VER_ID"/>
+      </datastore-identity>
+      <field name ="schemaVersion">
+        <column name="SCHEMA_VERSION" length="127" jdbc-type="VARCHAR" allows-null="false"/>
+      </field>
+      <field name ="versionComment">
+        <column name="VERSION_COMMENT" length="255" jdbc-type="VARCHAR" allows-null="false"/>
+      </field>
+     </class>
+
+  </package>
+</jdo>
+

http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java
new file mode 100644
index 0000000..c74dbf3
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java
@@ -0,0 +1,42 @@
+/**
+ * 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.sentry.provider.db.service.persistent;
+
+import java.util.UUID;
+
+/**
+ * Stores the UUID associated with the server who processed
+ * a commit and a commit order sequence id.
+ */
+public class CommitContext {
+
+  private final String serverUUID;
+  private final long sequenceId;
+
+  public CommitContext(UUID serverUUID, long sequenceId) {
+    this.serverUUID = serverUUID.toString();
+    this.sequenceId = sequenceId;
+  }
+  public String getServerUUID() {
+    return serverUUID;
+  }
+  public long getSequenceId() {
+    return sequenceId;
+  }
+}
\ No newline at end of file