/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.upgrade.callbacks;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.constraint.ContainmentConstraint;
import com.emc.storageos.db.client.constraint.URIQueryResultList;
import com.emc.storageos.db.client.impl.DbClientImpl;
import com.emc.storageos.db.client.model.AbstractChangeTrackingSet;
import com.emc.storageos.db.client.model.StringSetMap;
import com.emc.storageos.db.client.model.TenantOrg;
import com.emc.storageos.db.client.model.VirtualDataCenter;
import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback;
import com.emc.storageos.db.common.VdcUtil;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.svcs.errorhandling.resources.MigrationCallbackException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.net.URI;
import java.util.Iterator;
import java.util.Map;
/**
* This callback is for 1.1 to 2.0. Move all VDC role assignments from root tenant to new CF VirtualDataCenter.
*/
public class VDCRoleMigrationCallback extends BaseCustomMigrationCallback {
private static final Logger _log = LoggerFactory.getLogger(VDCRoleMigrationCallback.class);
public enum Role {
// VDC roles
SECURITY_ADMIN,
SYSTEM_ADMIN,
SYSTEM_MONITOR,
SYSTEM_AUDITOR,
PROXY_USER,
// Tenant Roles
TENANT_ADMIN,
PROJECT_ADMIN,
TENANT_APPROVER,
// Internal VDC roles
RESTRICTED_SECURITY_ADMIN,
RESTRICTED_SYSTEM_ADMIN
}
@Override
public void process() throws MigrationCallbackException {
_log.info("VDC Role Migration Started ...");
DbClient dbClient = getDbClient();
TenantOrg rootTenant = findRootTenant(dbClient);
StringSetMap tenantRoles = rootTenant.getRoleAssignments();
if (tenantRoles == null) {
_log.info("No Role Assignments in original Root Tenant. Skip moving.");
return;
}
VirtualDataCenter vdc = VdcUtil.getLocalVdc();
if (vdc == null) {
throw new IllegalStateException("the CF of Local VDC is not found.");
}
// only copy VDC role assignments
copyRoleAssignments(tenantRoles, vdc);
removeRoleFromRootTenant(vdc, rootTenant);
dbClient.persistObject(vdc);
dbClient.persistObject(rootTenant);
_log.info("VDC Role Migration Done.");
}
private TenantOrg findRootTenant(DbClient _dbClient) {
URIQueryResultList tenants = new URIQueryResultList();
try {
_dbClient.queryByConstraint(
ContainmentConstraint.Factory.getTenantOrgSubTenantConstraint(URI.create(TenantOrg.NO_PARENT)),
tenants);
if (tenants.iterator().hasNext() == false) {
throw new IllegalStateException("The CF of Root Tenant is not found");
}
URI root = tenants.iterator().next();
return _dbClient.queryObject(TenantOrg.class, root);
} catch (DatabaseException ex) {
throw new IllegalStateException("Error in finding the CF of root tenant", ex);
}
}
/*
* copy all Non VDC roles from rootTenantOrg to VDC
* the structure of role assignments is: <key: user id, value: role list>
*/
private void copyRoleAssignments(StringSetMap tenantRoleAssignments, VirtualDataCenter vdc) {
for (Map.Entry<String, AbstractChangeTrackingSet<String>> roleAssignment : tenantRoleAssignments.entrySet()) {
String uid = roleAssignment.getKey();
Iterator<String> itr = roleAssignment.getValue().iterator();
while (itr.hasNext()) {
String role = itr.next();
if (isVDCRole(role)) {
_log.info("Found VDC Role [ {} ] for the user [ {} ]. Copy to VDC", role, uid);
vdc.addRole(uid, role);
}
}
}
}
/**
* remove VDC roles from rootTenantOrg
*
* @param vdc
* @param rootTenant
*/
private void removeRoleFromRootTenant(VirtualDataCenter vdc, TenantOrg rootTenant) {
StringSetMap vdcRoles = vdc.getRoleAssignments();
for (Map.Entry<String, AbstractChangeTrackingSet<String>> roleAssignment : vdcRoles.entrySet()) {
String uid = roleAssignment.getKey();
Iterator<String> itr = roleAssignment.getValue().iterator();
while (itr.hasNext()) {
String role = itr.next();
rootTenant.removeRole(uid, role);
}
}
}
private boolean isVDCRole(String role) {
return (role.equalsIgnoreCase(Role.SYSTEM_ADMIN.toString()) ||
role.equalsIgnoreCase(Role.SECURITY_ADMIN.toString()) ||
role.equalsIgnoreCase(Role.SYSTEM_MONITOR.toString()) || role.equalsIgnoreCase(Role.SYSTEM_AUDITOR.toString()));
}
// below all are for test only
private static void logRole(StringSetMap roleAssignment) {
for (String key : roleAssignment.keySet()) {
_log.debug("Role key = {}, value = ", key, roleAssignment.get(key));
}
}
public static DbClient buildDbClient() {
try {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/dbclient-conf.xml");
DbClientImpl dbClient = (DbClientImpl) ctx.getBean("dbclient");
dbClient.start();
return dbClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// for test only
public static void main(String[] args) throws Exception {
VDCRoleMigrationCallback cb = new VDCRoleMigrationCallback();
cb.setDbClient(buildDbClient());
cb.process();
}
}