/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.geo.service;
import java.net.BindException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.crypto.SecretKey;
import com.emc.storageos.coordinator.client.service.impl.CoordinatorClientInetAddressMap;
import com.emc.storageos.coordinator.client.service.impl.DualInetAddress;
import com.emc.storageos.geomodel.*;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;
import com.emc.storageos.coordinator.client.model.CoordinatorSerializable;
import com.emc.storageos.coordinator.client.model.ProductName;
import com.emc.storageos.coordinator.client.model.RepositoryInfo;
import com.emc.storageos.coordinator.client.model.SoftwareVersion;
import com.emc.storageos.coordinator.client.service.CoordinatorClient;
import com.emc.storageos.coordinator.client.service.impl.CoordinatorClientImpl;
import com.emc.storageos.coordinator.common.Configuration;
import com.emc.storageos.coordinator.common.Service;
import com.emc.storageos.coordinator.common.impl.ConfigurationImpl;
import com.emc.storageos.coordinator.exceptions.CoordinatorException;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.constraint.Constraint;
import com.emc.storageos.db.client.constraint.QueryResultList;
import com.emc.storageos.db.client.model.DataObject;
import com.emc.storageos.db.client.model.NamedURI;
import com.emc.storageos.db.client.model.Operation;
import com.emc.storageos.db.client.model.Project;
import com.emc.storageos.db.client.model.StringMap;
import com.emc.storageos.db.client.model.Task;
import com.emc.storageos.db.client.model.TenantOrg;
import com.emc.storageos.db.client.model.TestGeoObject;
import com.emc.storageos.db.client.model.VirtualArray;
import com.emc.storageos.db.client.model.VirtualDataCenter;
import com.emc.storageos.db.client.model.VirtualDataCenterInUse;
import com.emc.storageos.db.client.model.VirtualPool;
import com.emc.storageos.db.common.VdcUtil;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.geo.service.impl.util.VdcConfigHelper;
import com.emc.storageos.geo.vdccontroller.impl.InternalDbClient;
import com.emc.storageos.geo.vdccontroller.impl.VdcControllerImpl;
import com.emc.storageos.geo.vdccontroller.impl.VdcOperationLockHelper;
import com.emc.storageos.model.property.PropertyInfo;
import com.emc.storageos.security.SignatureHelper;
import com.emc.storageos.security.authentication.InternalApiSignatureKeyGenerator;
import com.emc.storageos.security.authorization.BasePermissionsHelper;
import com.emc.storageos.security.geo.GeoClientCacheManager;
import com.emc.storageos.security.geo.GeoServiceClient;
import com.emc.storageos.security.geo.GeoServiceHelper;
import com.emc.storageos.security.geo.exceptions.FatalGeoException;
import com.emc.storageos.security.geo.exceptions.GeoException;
import com.emc.storageos.security.keystore.impl.KeystoreEngine;
import com.emc.storageos.svcs.errorhandling.model.ServiceCoded;
import com.emc.vipr.model.sys.ClusterInfo;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
/**
* Unit test for VdcControllerImpl with mock object
*/
public class VdcControllerTest {
private final static Logger log = LoggerFactory.getLogger(VdcControllerTest.class);
VdcControllerImpl vdcController;
MockDbClient dbClient;
MockGeoClientCacheManager clientManager;
KeyStore keystore;
X509Certificate[] chain;
PrivateKey privKey;
char[] password;
@BeforeClass
public static void setupAll() throws Exception {
ProductName name = new DummyProductName("vipr");
// Listening on port 4443 so that connectivity test could pass. See VdcConfigHelper.areNodesReachable()
try {
final ServerSocket serverSocket = new ServerSocket(4443, 0, InetAddress.getByName("127.0.0.1"));
Thread thread = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Socket sock = serverSocket.accept();
log.info("Got socket connection from {}", sock.getRemoteSocketAddress());
} catch (Exception ex) {
log.error("Connectivity check error ", ex);
}
}
}
});
thread.setDaemon(true);
thread.start();
} catch (BindException e) {
// Address is already in use, ignore
}
}
@Before
public void setup() throws Exception {
vdcController = new VdcControllerImpl();
MockCoordinatorClient coordinator = new MockCoordinatorClient();
// setup mock objects for vdc controller test
dbClient = new MockDbClient();
vdcController.setDbClient(dbClient);
InternalApiSignatureKeyGenerator secretKeyGenerator = new InternalApiSignatureKeyGenerator() {
public synchronized void loadKeys() {
}
public SecretKey getSignatureKey(SignatureKeyType type) {
return SignatureHelper.createKey("test", InternalApiSignatureKeyGenerator.CURRENT_INTERVDC_API_SIGN_ALGO);
}
};
clientManager = new MockGeoClientCacheManager(coordinator, secretKeyGenerator);
vdcController.setGeoClientManager(clientManager);
vdcController.setVdcOperationLockHelper(new MockVdcOperationLockHelper());
keystore = KeyStore.getInstance(KeyStore.getDefaultType());
password = "some password".toCharArray();
keystore.load(null, password);
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(512, new SecureRandom());
CertAndKeyGen keypair = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
X500Name x500Name = new X500Name("EMC", "EMC", "EMC", "EMC", "MA", "US");
keypair.generate(512);
PrivateKey privKey = keypair.getPrivateKey();
chain = new X509Certificate[1];
chain[0] = keypair.getSelfCertificate(x500Name, new Date(), (long) 365 * 24 * 60 * 60);
keystore.setKeyEntry(KeystoreEngine.ViPR_KEY_AND_CERTIFICATE_ALIAS, privKey, password, chain);
vdcController.setKeystore(keystore);
vdcController.setSignatureGenerator(secretKeyGenerator);
BasePermissionsHelper permissionsHelper = new BasePermissionsHelper(dbClient);
vdcController.setPermissionsHelper(permissionsHelper);
// Setup helper based on mocked db client
VdcConfigHelper helper = new VdcConfigHelper();
helper.setDbClient(dbClient);
helper.setGeoClientCacheManager(clientManager);
helper.setCoordinatorClient(coordinator);
vdcController.setVdcHelper(helper);
VdcUtil.setDbClient(dbClient);
dbClient.buildGeodbData();
}
/**
* Adding vdc2 to vdc1
*/
// Test hanging in IDE and "gradlew test"
@Test
public void testAddToSingleVdc() throws Exception {
dbClient.buildInitData(1);
// Treat as Geo strategy options already set to remove Cassandra, preventing calling to
// remote JMX
dbClient.getGeoStrategyOptions().put("vdc2", "abc");
VirtualDataCenter vdc1 = dbClient.vdcList.get(0);
VirtualDataCenter newVdc = newVdcForAdding("vdc2");
// dbClient.vdcList.add(newVdc);
log.info("Testing connect vdc2 {} to vdc1 {}", newVdc.getShortId(), vdc1.getId());
Properties vdcInfo = GeoServiceHelper.getVDCInfo(newVdc);
String reqId = "taskid-0000";
addTask(reqId, vdc1.getId());
// Start execute vdc connect
vdcController.connectVdc(vdc1, reqId, Arrays.asList(new Object[] { vdcInfo }));
// Verify result
URI newVDCId = null;
Iterator<URI> vdcIter = dbClient.queryByType(VirtualDataCenter.class, true).iterator();
while (vdcIter.hasNext()) {
URI id = vdcIter.next();
String vdcId = URIUtil.parseVdcIdFromURI(id.toASCIIString());
if (vdcId.equals("vdc2")) {
newVDCId = id;
break;
}
}
Assert.assertNotNull(newVDCId);
VirtualDataCenter vdc = dbClient.queryObject(VirtualDataCenter.class, newVDCId);
Assert.assertNotNull(vdc);
Assert.assertTrue(vdc.getShortId().equals("vdc2"));
Assert.assertNotNull(vdc.getHostCount());
Assert.assertNotNull(vdc.getHostIPv4AddressesMap());
Assert.assertTrue(vdc.getHostIPv4AddressesMap().size() == 1);
Assert.assertTrue(clientManager.client.countForSyncCall == 1);
}
/**
* Adding vdc4 to a connected vdc1/2/3
*/
// Test hanging in IDE and "gradlew test"
@Test
public void testAddToMultipleVdc() throws Exception {
// create a mockdb with 3 existing vdc
dbClient.buildInitData(3);
// Treat as Geo strategy options already set to remove Cassandra, preventing calling to
// remote JMX
dbClient.getGeoStrategyOptions().put("vdc4", "abc");
VirtualDataCenter vdc1 = dbClient.vdcList.get(0);
VirtualDataCenter newVdc = newVdcForAdding("vdc4");
// dbClient.vdcList.add(newVdc);
log.info("Testing connect new vdc {} to 3 existing vdc {}", newVdc.getShortId(), vdc1.getId());
Properties vdcInfo = GeoServiceHelper.getVDCInfo(newVdc);
String reqId = "taskid-0001";
addTask(reqId, vdc1.getId());
// Start execute vdc connect
vdcController.connectVdc(vdc1, reqId, Arrays.asList(new Object[] { vdcInfo }));
// Verify result
URI newVDCId = null;
Iterator<URI> vdcIter = dbClient.queryByType(VirtualDataCenter.class, true).iterator();
while (vdcIter.hasNext()) {
URI id = vdcIter.next();
String vdcId = URIUtil.parseVdcIdFromURI(id.toASCIIString());
if (vdcId.equals("vdc4")) {
newVDCId = id;
break;
}
}
Assert.assertNotNull(newVDCId);
VirtualDataCenter vdc = dbClient.queryObject(VirtualDataCenter.class, newVDCId);
Assert.assertNotNull(vdc);
Assert.assertTrue(vdc.getShortId().equals("vdc4"));
Assert.assertNotNull(vdc.getHostCount());
Assert.assertNotNull(vdc.getHostIPv4AddressesMap());
Assert.assertTrue(clientManager.client.countForSyncCall == 3);
}
// Test hanging in IDE and "gradlew test"
@Test
public void testAddVdcPrecheckFailure() throws Exception {
// create a mock db with 2 existing vdc
dbClient.buildInitData(2);
VirtualDataCenter vdc1 = dbClient.vdcList.get(0);
vdc1.setConnectionStatus(VirtualDataCenter.ConnectionStatus.CONNECTING);
VirtualDataCenter newVdc = newVdcForAdding("vdc2");
log.info("Testing connect vdc2 {} to vdc1 {}", newVdc.getShortId(), vdc1.getId());
// Start execute vdc connect
try {
Properties vdcInfo = GeoServiceHelper.getVDCInfo(newVdc);
String reqId = "taskid-0003";
addTask(reqId, vdc1.getId());
// Start execute vdc connect
vdcController.connectVdc(vdc1, reqId, Arrays.asList(new Object[] { vdcInfo }));
Assert.assertTrue("Precheck should throw an exception", false);
} catch (Exception ex) {
log.error("precheck error ", ex);
Assert.assertTrue(ex instanceof FatalGeoException);
}
}
/**
* Remove vdc2 from vdc1
*/
// Test hanging in IDE and "gradlew test"
@Test
public void testRemoveVdc() throws Exception {
// create a mock db with 2 existing vdc
dbClient.buildInitData(2);
VirtualDataCenter vdc1 = dbClient.vdcList.get(0);
VirtualDataCenter vdc2 = dbClient.vdcList.get(1);
log.info("Testing remove vdc2 {} from vdc1 {}", vdc2.getId(), vdc1.getId());
// Start execute vdc remove
vdc2.setConnectionStatus(VirtualDataCenter.ConnectionStatus.REMOVING);
dbClient.updateAndReindexObject(vdc2);
String reqId = "remove-taskid-0000";
addTask(reqId, vdc2.getId());
vdcController.removeVdc(vdc2, reqId, null);
// Verify result
Assert.assertTrue(dbClient.vdcList.size() == 1);
VirtualDataCenter vdc = dbClient.queryObject(VirtualDataCenter.class, vdc1.getId());
Assert.assertNotNull(vdc);
Assert.assertTrue(vdc.getShortId().equals("vdc1"));
Assert.assertNotNull(vdc.getHostCount());
Assert.assertNotNull(vdc.getHostIPv4AddressesMap());
Assert.assertTrue(clientManager.client.countForSyncCall == 1);
// vdc2 should be removed
vdc = dbClient.queryObject(VirtualDataCenter.class, vdc2.getId());
Assert.assertNull(vdc);
}
/**
* Remove vdc2 from vdc1
*/
// Test hanging in IDE and "gradlew test"
@Test
public void testRemoveVdcPreCheck() throws Exception {
// create a mock db with 2 existing vdc
dbClient.buildInitData(2);
VirtualDataCenter vdc1 = dbClient.vdcList.get(0);
VirtualDataCenter vdc2 = dbClient.vdcList.get(1);
log.info("Testing precheck for removing vdc2 {} from vdc1 {}", vdc2.getId(), vdc1.getId());
// create a geo object referencing a geo visible object in vdc2
TestGeoObject obj = new TestGeoObject();
obj.setId(URIUtil.createId(TestGeoObject.class));
String varrayId = URIUtil.createId(VirtualArray.class).toString();
varrayId = varrayId.replace("vdc1", "vdc2");
obj.setVarray(new URI(varrayId));
dbClient.testGeoList.add(obj);
// Start execute vdc remove
try {
String reqId = "remove-taskid-0002";
addTask(reqId, vdc2.getId());
vdcController.removeVdc(vdc2, reqId, null);
Assert.assertTrue("Precheck should throw an exception", false);
} catch (Exception ex) {
log.error("precheck error ", ex);
Assert.assertTrue(ex instanceof FatalGeoException);
}
}
/**
* Remove vdc2 from vdc1
*/
// Test hanging in IDE and "gradlew test"
@Test
public void testRemoveVdcInUsePreCheck() throws Exception {
// create a mock db with 2 existing vdc
dbClient.buildInitData(2);
VirtualDataCenter vdc1 = dbClient.vdcList.get(0);
VirtualDataCenter vdc2 = dbClient.vdcList.get(1);
log.info("Testing precheck for removing vdc2 {} from vdc1 {}", vdc2.getId(), vdc1.getId());
VirtualDataCenterInUse vdcInUse = new VirtualDataCenterInUse();
vdcInUse.setId(vdc2.getId());
vdcInUse.setInUse(true);
dbClient.createObject(vdcInUse);
// Start execute vdc remove
try {
String reqId = "remove-taskid-0003";
addTask(reqId, vdc2.getId());
vdcController.removeVdc(vdc2, reqId, null);
Assert.assertTrue("Precheck should throw an exception", false);
} catch (Exception ex) {
log.error("precheck error ", ex);
Assert.assertTrue(ex instanceof FatalGeoException);
}
}
/**
* Remove vdc3 from vdc1/vdc2
*/
// Test hanging in IDE and "gradlew test"
@Test
public void testRemoveVdcFromThreeSiteGeo() throws Exception {
// create a mock db with 3 existing vdc
dbClient.buildInitData(3);
VirtualDataCenter vdc1 = dbClient.vdcList.get(0);
VirtualDataCenter vdc2 = dbClient.vdcList.get(1);
VirtualDataCenter vdc3 = dbClient.vdcList.get(1);
log.info("Testing remove vdc3 {} ", vdc3.getId());
// Start execute vdc remove
vdc3.setConnectionStatus(VirtualDataCenter.ConnectionStatus.REMOVING);
dbClient.updateAndReindexObject(vdc3);
String reqId = "remove-taskid-0003";
addTask(reqId, vdc3.getId());
vdcController.removeVdc(vdc3, reqId, null);
// Verify result
Assert.assertTrue(dbClient.vdcList.size() == 2);
VirtualDataCenter vdc = dbClient.queryObject(VirtualDataCenter.class, vdc1.getId());
Assert.assertNotNull(vdc);
Assert.assertTrue(vdc.getShortId().equals("vdc1"));
Assert.assertNotNull(vdc.getHostCount());
Assert.assertNotNull(vdc.getHostIPv4AddressesMap());
Assert.assertTrue(clientManager.client.countForSyncCall == 2);
// vdc3 should be removed from local db
vdc = dbClient.queryObject(VirtualDataCenter.class, vdc3.getId());
Assert.assertNull(vdc);
}
/**
* Copy VDC attributes from one object to another
*
* @param src
* @param dest
*/
private void copyVdcObject(VirtualDataCenter src, VirtualDataCenter dest) {
log.info("Copy object {}", dest.getId());
dest.setShortId(src.getShortId());
dest.setVersion(src.getVersion());
dest.setApiEndpoint(src.getApiEndpoint());
dest.setConnectionStatus(src.getConnectionStatus());
dest.setLocal(src.getLocal());
dest.setHostCount(src.getHostCount());
dest.setHostIPv4AddressesMap(src.getHostIPv4AddressesMap());
dest.setHostIPv6AddressesMap(src.getHostIPv6AddressesMap());
Assert.assertNotNull(src.getHostIPv4AddressesMap());
}
/**
* Dump VirtualDataCenter object to log
*
* @param vdc
*/
private void dumpVdcObject(VirtualDataCenter vdc) {
log.info("VDC id = {}, ", vdc.getId());
log.info(" shortId {}", vdc.getShortId());
log.info(" version {}", vdc.getVersion());
log.info(" hostCount {}", vdc.getHostCount());
log.info(" local {}", vdc.getLocal());
log.info(" status {}", vdc.getConnectionStatus());
}
/**
* New Vdc object for adding
*
* @return
*/
private VirtualDataCenter newVdcForAdding(String shortId) {
VirtualDataCenter vdc = new VirtualDataCenter();
URI vdcId = URIUtil.createVirtualDataCenterId(shortId);
String vdcShortId = shortId;
vdc.setShortId(vdcShortId);
vdc.setId(vdcId);
vdc.setVersion(2L);
vdc.setLocal(false);
vdc.setApiEndpoint("127.0.0.2");
vdc.setHostCount(1);
vdc.setConnectionStatus(VirtualDataCenter.ConnectionStatus.CONNECTING);
vdc.setRepStatus(VirtualDataCenter.GeoReplicationStatus.REP_NONE);
vdc.setCertificateChain(TEST_CERT);
return vdc;
}
private void addTask(String requestId, URI vdcId) {
Task task = new Task();
task.setId(URIUtil.createId(Task.class));
task.setRequestId(requestId);
NamedURI resource = new NamedURI(vdcId, "vdc");
task.setResource(resource);
this.dbClient.createObject(task);
}
// Mock for dbclient who stores vdc config in memory
class MockDbClient extends InternalDbClient {
List<VirtualDataCenter> vdcList;
URI rootTenantId = URIUtil.createId(TenantOrg.class);
List<TestGeoObject> testGeoList;
Map<Class, List> inMemDb;
Map<String, String> geoStrategyOptions;
MockDbClient() {
inMemDb = new HashMap<Class, List>();
testGeoList = new ArrayList<TestGeoObject>();
vdcList = new ArrayList<VirtualDataCenter>();
geoStrategyOptions = new HashMap<String, String>();
}
void buildInitData(int numOfVdc) throws Exception {
// create a initial list for vdc config
for (int i = 1; i < numOfVdc + 1; i++) {
VirtualDataCenter vdc = new VirtualDataCenter();
String vdcShortId = "vdc" + i;
URI vdcId = URIUtil.createVirtualDataCenterId(vdcShortId);
vdc.setShortId(vdcShortId);
vdc.setId(vdcId);
vdc.setVersion(2L);
vdc.setLocal(i == 1);
vdc.setHostCount(1);
vdc.setRepStatus(VirtualDataCenter.GeoReplicationStatus.REP_ALL);
StringMap hostList = new StringMap();
hostList.put("node1", "127.0.0.1");
vdc.setHostIPv4AddressesMap(hostList);
vdc.setApiEndpoint("127.0.0.2");
vdc.setCertificateChain(TEST_CERT);
vdcList.add(vdc);
if (numOfVdc > 1) {
vdc.setConnectionStatus(VirtualDataCenter.ConnectionStatus.CONNECTED);
} else {
vdc.setConnectionStatus(VirtualDataCenter.ConnectionStatus.ISOLATED);
}
keystore.setCertificateEntry(vdcId.toString(), chain[0]);
}
inMemDb.put(TestGeoObject.class, testGeoList);
inMemDb.put(VirtualDataCenter.class, vdcList);
inMemDb.put(VirtualDataCenterInUse.class, new ArrayList<VirtualDataCenterInUse>());
}
void buildGeodbData() {
TestGeoObject obj = new TestGeoObject();
obj.setId(URIUtil.createId(TestGeoObject.class));
obj.setVarray(URIUtil.createId(VirtualArray.class));
obj.setVpool(URIUtil.createId(VirtualPool.class));
testGeoList.add(obj);
}
private <T extends DataObject> List<T> getObjectList(Class<T> clazz) {
List<T> objList = inMemDb.get(clazz);
if (objList == null) {
objList = new ArrayList<T>();
inMemDb.put(clazz, objList);
}
return objList;
}
@Override
public <T extends DataObject> List<URI> queryByType(Class<T> clazz, boolean activeOnly) throws DatabaseException {
log.info("queryByType in mock db client for {}", clazz);
List<URI> result = new ArrayList<URI>();
List<T> objList = getObjectList(clazz);
for (T obj : objList) {
if (activeOnly && obj.getInactive().booleanValue()) {
continue;
}
result.add(obj.getId());
}
return result;
}
@Override
public <T extends DataObject> T queryObject(Class<T> clazz, URI id) {
log.info("queryObject in mock db client for {}", id);
List<T> objList = getObjectList(clazz);
for (T obj : objList) {
if (id.equals(obj.getId())) {
log.info("queryObject {}", obj.getId());
return obj;
}
}
return null;
}
@Override
public void removeVdcNodesFromBlacklist(VirtualDataCenter vdc) {
}
@Override
public <T extends DataObject> List<T> queryObject(Class<T> clazz, Collection<URI> ids, boolean activeOnly)
throws DatabaseException {
List<T> result = new ArrayList<T>();
Iterator<URI> iter = ids.iterator();
while (iter.hasNext()) {
URI uri = iter.next();
result.add(queryObject(clazz, uri));
}
return result;
}
@Override
public <T extends DataObject> List<T> queryObjectField(Class<T> clazz, String fieldName, Collection<URI> ids)
throws DatabaseException {
log.info("queryObjectField in mock db client");
return queryObject(clazz, ids, true);
}
@Override
public <T extends DataObject> Collection<T> queryObjectFields(Class<T> clazz,
Collection<String> fieldNames, Collection<URI> ids) {
log.info("queryObjectFields in mock db client");
return queryObject(clazz, ids, true);
}
@Override
public <T extends DataObject> void createObject(T object) throws DatabaseException {
log.info("create Object {}", object);
List<T> objList = getObjectList((Class<T>) object.getClass());
objList.add(object);
}
@Override
public <T extends DataObject> void updateAndReindexObject(T object) throws DatabaseException {
log.info("updateAndReindexObject {}", object);
if (object instanceof VirtualDataCenter) {
VirtualDataCenter obj = (VirtualDataCenter) object;
dumpVdcObject(obj);
for (VirtualDataCenter vdc : vdcList) {
if (obj.getId().equals(vdc.getId())) {
copyVdcObject(obj, vdc);
}
}
}
else {
// BasePermissionsHelper.removeRootRoleAssignmentOnTenantAndProject may update projects or tenants
boolean isProject = object instanceof Project;
boolean isTenant = object instanceof TenantOrg;
Assert.assertTrue("Unexpected object update", isProject || isTenant);
}
}
public Operation ready(Class<? extends DataObject> clazz, URI id, String opId) throws DatabaseException {
Operation op = new Operation();
op.ready();
op.setProgress(100);
return op;
}
public Operation error(Class<? extends DataObject> clazz, URI id, String opId, ServiceCoded code) throws DatabaseException {
Operation op = new Operation();
op.error(code);
return op;
}
public void waitAllSitesDbStable() {
log.info("waitAllSitesDbStable - ");
}
public void waitDbRingRebuildDone(String vdcShortId, int vdcHosts) {
log.info("waitDbRingRebuildDone - ");
}
@Override
public <T> void queryByConstraint(Constraint constraint, QueryResultList<T> result)
throws DatabaseException {
Class<? extends DataObject> doType = constraint.getDataObjectType();
log.info("QueryByConstraint for {}", doType);
ArrayList<URI> list = new ArrayList<URI>();
if (doType.getSimpleName().equalsIgnoreCase("TenantOrg")) {
list.add(rootTenantId);
} else if (doType.getSimpleName().equalsIgnoreCase("TestGeoObject")) {
list.add(testGeoList.get(0).getId());
} else if (doType.getSimpleName().equalsIgnoreCase("Task")) {
List<URI> tasks = queryByType(Task.class, true);
log.info("Tasks {}", tasks.size());
list.addAll(tasks);
}
result.setResult((java.util.Iterator<T>) list.iterator());
// throw new IllegalStateException("Unsupported queryByConstraint for " + doType);
}
@Override
public void removeObject(DataObject... object) throws DatabaseException {
markForDeletion(object);
}
@Override
public void markForDeletion(Collection<? extends DataObject> objects) throws DatabaseException {
Iterator<? extends DataObject> it = objects.iterator();
while (it.hasNext()) {
DataObject obj = it.next();
List<? extends DataObject> objList = getObjectList((Class<? extends DataObject>) obj.getClass());
for (int i = 0; i < objList.size(); i++) {
DataObject existingObj = objList.get(i);
if (existingObj.getId().equals(obj.getId())) {
objList.remove(i);
log.info("markForDeletion: remove {}", obj.getId());
}
}
}
}
@Override
public Map<String, String> getGeoStrategyOptions() throws ConnectionException {
return this.geoStrategyOptions;
}
@Override
public CoordinatorClient getCoordinatorClient() {
return new MockCoordinatorClient();
}
@Override
public void stopClusterGossiping() {
log.info("Stop cluster gossiping");
}
public void waitVdcRemoveDone(String vdcShortId) {
}
public String getSchemaVersion() {
return "2.0";
}
public boolean isGeoDbClientEncrypted() {
return false;
}
}
// mock object for GeoServiceClient
class MockGeoServiceClient extends GeoServiceClient {
int countForSyncCall = 0;
int countForApplyCall = 0;
int countForPostCheckCall = 0;
public MockGeoServiceClient() {
setServer("127.0.0.1");
}
// called on vdc2 to fetch its information
@Override
public VdcPreCheckResponse syncVdcConfigPreCheck(VdcPreCheckParam param, String vdcName) throws GeoException {
log.info("getVdcConfig on new vdc");
VdcPreCheckResponse resp = new VdcPreCheckResponse();
resp.setId(URIUtil.createVirtualDataCenterId("vdc99"));
resp.setShortId("vdc99");
resp.setApiEndpoint("127.0.0.2");
resp.setVersion(1L);
resp.setHostCount(1);
StringMap hostList = new StringMap();
hostList.put("node1", "127.0.0.1");
resp.setHostIPv4AddressesMap(hostList);
resp.setApiEndpoint("127.0.0.2");
resp.setHasData(false);
resp.setClusterStable(true);
resp.setSoftwareVersion("vipr-2.3.0.0.100");
return resp;
}
@Override
public VdcNatCheckResponse vdcNatCheck(VdcNatCheckParam checkParam) {
VdcNatCheckResponse resp = new VdcNatCheckResponse();
resp.setBehindNAT(false);
return resp;
}
// called on vdc2 to update Vdc config list
@Override
public void syncVdcConfig(VdcConfigSyncParam vdcConfigList, String vdcName) throws GeoException {
countForSyncCall++;
log.info("GeoClient: SyncVdcConfig " + countForSyncCall);
}
public void applyVdcConfig() throws Exception {
log.info("GeoClient: applyVdcConfig for config change");
countForApplyCall++;
}
@Override
public void syncVdcConfigPostCheck(VdcPostCheckParam checkParam, String vdcName) throws GeoException {
log.info("GeoClient: syncVdcConfigPostCheck");
countForPostCheckCall++;
}
@Override
public void syncVdcCerts(VdcCertListParam vdcCertListParam, String vdcName) throws GeoException {
log.info("GeoClient: syncVdcCerts {}", vdcCertListParam);
}
@Override
public VdcNodeCheckResponse vdcNodeCheck(VdcNodeCheckParam checkParam) {
log.info("VdcNodeCheckResponse: {}", checkParam);
VdcNodeCheckResponse resp = new VdcNodeCheckResponse();
resp.setNodesReachable(true);
return resp;
}
}
class MockGeoClientCacheManager extends GeoClientCacheManager {
MockGeoServiceClient client = new MockGeoServiceClient();
public MockGeoClientCacheManager(CoordinatorClient coordinatorClient, InternalApiSignatureKeyGenerator keyGenerator) {
super();
client = new MockGeoServiceClient();
client.setCoordinatorClient(coordinatorClient);
client.setKeyGenerator(keyGenerator);
}
public GeoServiceClient getGeoClient(String shortVdcId) {
return client;
}
public GeoServiceClient getGeoClient(Properties vdcInfo) {
return client;
}
public GeoServiceClient getNonSharedGeoClient(String shortVdcId) {
return client;
}
public void clearCache() {
log.info("Invalidate client cache");
}
}
class MockCoordinatorClient extends CoordinatorClientImpl {
@Override
public CoordinatorClientInetAddressMap getInetAddessLookupMap() {
CoordinatorClientInetAddressMap coordinatorClientInetAddressMap = new CoordinatorClientInetAddressMap();
try {
coordinatorClientInetAddressMap.setDualInetAddress(DualInetAddress.fromAddress("127.0.0.1"));
} catch (Exception e) {
log.debug("Ingore this issue.");
}
return coordinatorClientInetAddressMap;
}
public String getDbConfigPath(String serviceName) {
return "/config/dbsvc";
}
public List<Configuration> queryAllConfiguration(String kind) throws CoordinatorException {
ArrayList<Configuration> configList = new ArrayList<Configuration>();
ConfigurationImpl config = new ConfigurationImpl();
configList.add(config);
return configList;
}
public Configuration queryConfiguration(String kind, String id) {
ConfigurationImpl config = new ConfigurationImpl();
config.setConfig(VdcConfigHelper.ENCRYPTION_CONFIG_KIND, "testEncryptionKey");
return config;
}
public void persistServiceConfiguration(Configuration... config) throws CoordinatorException {
log.info("Mock coordinator - persistServiceConfiguration {}", config);
}
public List<Service> locateAllServices(String name, String version, String tag, String endpointKey)
throws CoordinatorException {
log.info("LocateAllServices {}", name);
ArrayList<Service> result = new ArrayList<Service>();
return result;
}
public ClusterInfo.ClusterState getControlNodesState() {
return ClusterInfo.ClusterState.STABLE;
}
public ClusterInfo.ClusterState getExtraNodesState() {
return ClusterInfo.ClusterState.STABLE;
}
public <T extends CoordinatorSerializable> T getTargetInfo(final Class<T> clazz) throws CoordinatorException {
if (RepositoryInfo.class.equals(clazz)) {
SoftwareVersion current = new SoftwareVersion("vipr-2.3.0.0.100");
List<SoftwareVersion> versions = new ArrayList<SoftwareVersion>();
versions.add(current);
RepositoryInfo info = new RepositoryInfo(current, versions);
return (T) info;
}
throw new IllegalStateException("Unexpected getTargetInfo");
}
public PropertyInfo getPropertyInfo() throws CoordinatorException {
PropertyInfo info = new PropertyInfo();
Map prop = new HashMap<String, String>();
prop.put("network_standalone_ipaddr", "127.0.0.1");
info.getProperties().putAll(prop);
return info;
}
}
static class DummyProductName extends ProductName {
public DummyProductName(String name) {
super.setName(name);
}
}
class MockVdcOperationLockHelper extends VdcOperationLockHelper {
public MockVdcOperationLockHelper() {
}
public void acquire(String vdcShortId) {
log.info("Acquire global lock for {}", vdcShortId);
}
public void release(String vdcShortId) {
log.info("Release global lock for {}", vdcShortId);
}
}
private static final String TEST_CERT = "-----BEGIN CERTIFICATE-----\nMIIDCTCCAfGgAwIBAgIIaA2AN2akqo0wDQYJKoZIhvcNAQELBQAwFzEVMBMGA1UE\nAxMMMTAuMjQ3Ljk3Ljg5MB4XDTE0MDUwODA3MDczMFoXDTI0MDUwNTA3MDczMFow\nFzEVMBMGA1UEAxMMMTAuMjQ3Ljk3Ljg5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAlufPeMLLqOwwnrMasu2zr/RRMYqJzT/Qy+Szqh+nDOy7ZYZoixH8\nxZi/Og2guGO8yd6s7bt0PnAqpwR6xrjt5LTb1+egzIfoA4Yz6/mGQIoDbK65agzL\nisgY9GowCliJ4vCnNEMUC0qdFLNOF2rvF8VpPS4/+CURCw3GUdE4ZizNy2XOpQpF\nV1Ke50Lc42uRX3LOuHYZ4SDIfYuSteWTOgGIevsRyPm0cCFPEiX3R7hbAqGNvTy2\n31oAPSzo/eiMRRNfuPHdJXqFq33epHQ2uS2M+0adXX81hO0VUXu/EUN6BrAesTT0\ntjsPj2AxlHX2LpcLVmS9VPb4W5DE1sBm7QIDAQABo1kwVzAfBgNVHSMEGDAWgBRE\n4ltXnjGKleTZ2/12iynVY8z3qTAVBgNVHREEDjAMhwQK92FZhwQK92FXMB0GA1Ud\nDgQWBBRE4ltXnjGKleTZ2/12iynVY8z3qTANBgkqhkiG9w0BAQsFAAOCAQEAC5vA\navBCVZFY/KxgGEmqv+dKsCs7o2/h7K6ItqyPr0gTVR3pKEGbl8zi0Ol5N4rcDbmY\nWu7VKsKun6gMJ9JIMzdKnPXlell35ZxvSTmagzEID0QZAfW4b/xZHQT1AfskUp00\nhQwpqcXcXPdgE/N45ieiNHnfROC8AIXaGJM8D5GrpX6btcgvEEzgFOsXDCmc260R\nehkqnpKvGmskp1BYKt8G7KbCe6WdfX63ca0YF9SFvtvYH7czjZTmFCt1MH4cHvTX\n7IAvnRiV8MKRifdtVNUtpjrcdAEmp6lgZe0jYFMfUPAb/fCI1vA2ybVKFzR6ixm/\ngzGGLxtQBWK4Nqe2rg==\n-----END CERTIFICATE-----";
}