diff --git a/priam-cass-extensions/src/main/java/com/netflix/priam/cassandra/extensions/PriamStartupAgent.java b/priam-cass-extensions/src/main/java/com/netflix/priam/cassandra/extensions/PriamStartupAgent.java index ad644cb14..a6597def2 100644 --- a/priam-cass-extensions/src/main/java/com/netflix/priam/cassandra/extensions/PriamStartupAgent.java +++ b/priam-cass-extensions/src/main/java/com/netflix/priam/cassandra/extensions/PriamStartupAgent.java @@ -44,6 +44,7 @@ private void setPriamProperties() String token = null; String seeds = null; boolean isReplace = false; + boolean isExternallyDefinedToken = false; String replacedIp = ""; String extraEnvParams = null; @@ -51,7 +52,10 @@ private void setPriamProperties() { try { - token = DataFetcher.fetchData("http://127.0.0.1:8080/Priam/REST/v1/cassconfig/get_token"); + isExternallyDefinedToken = Boolean.parseBoolean(DataFetcher.fetchData("http://127.0.0.1:8080/Priam/REST/v1/cassconfig/is_externally_defined_token")); + if (isExternallyDefinedToken) { + token = DataFetcher.fetchData("http://127.0.0.1:8080/Priam/REST/v1/cassconfig/get_token"); + } seeds = DataFetcher.fetchData("http://127.0.0.1:8080/Priam/REST/v1/cassconfig/get_seeds"); isReplace = Boolean.parseBoolean(DataFetcher.fetchData("http://127.0.0.1:8080/Priam/REST/v1/cassconfig/is_replace_token")); replacedIp = DataFetcher.fetchData("http://127.0.0.1:8080/Priam/REST/v1/cassconfig/get_replaced_ip"); @@ -64,7 +68,7 @@ private void setPriamProperties() e.printStackTrace(); } - if (token != null && seeds != null) + if ((token != null || !isExternallyDefinedToken) && seeds != null) break; try { @@ -75,8 +79,10 @@ private void setPriamProperties() // do nothing. } } - - System.setProperty("cassandra.initial_token", token); + + if (isExternallyDefinedToken) { + System.setProperty("cassandra.initial_token", token); + } setExtraEnvParams(extraEnvParams); diff --git a/priam/src/main/java/com/netflix/priam/IConfiguration.java b/priam/src/main/java/com/netflix/priam/IConfiguration.java index c3b9e3187..8d31e5368 100644 --- a/priam/src/main/java/com/netflix/priam/IConfiguration.java +++ b/priam/src/main/java/com/netflix/priam/IConfiguration.java @@ -310,6 +310,11 @@ public interface IConfiguration { */ public String getHostIP(); + /** + * @return Gets the number of tokens assigned to the node when using virtual nodes. + */ + public int getNumTokens(); + /** * @return Bytes per second to throttle for backups */ diff --git a/priam/src/main/java/com/netflix/priam/PriamServer.java b/priam/src/main/java/com/netflix/priam/PriamServer.java index e5752200b..bebd90e21 100644 --- a/priam/src/main/java/com/netflix/priam/PriamServer.java +++ b/priam/src/main/java/com/netflix/priam/PriamServer.java @@ -66,7 +66,7 @@ public PriamServer(IConfiguration config, PriamScheduler scheduler, InstanceIden } public void intialize() throws Exception { - if (id.getInstance().isOutOfService()) + if (id.isOutOfService()) return; // start to schedule jobs diff --git a/priam/src/main/java/com/netflix/priam/aws/S3BackupPath.java b/priam/src/main/java/com/netflix/priam/aws/S3BackupPath.java index 632d3d5b7..d00717923 100644 --- a/priam/src/main/java/com/netflix/priam/aws/S3BackupPath.java +++ b/priam/src/main/java/com/netflix/priam/aws/S3BackupPath.java @@ -54,7 +54,7 @@ public String getRemotePath() { buff.append(baseDir).append(S3BackupPath.PATH_SEP); // Base dir buff.append(region).append(S3BackupPath.PATH_SEP); buff.append(clusterName).append(S3BackupPath.PATH_SEP);// Cluster name - buff.append(token).append(S3BackupPath.PATH_SEP); + buff.append(nodeIdentifier).append(S3BackupPath.PATH_SEP); buff.append(formatDate(time)).append(S3BackupPath.PATH_SEP); buff.append(type).append(S3BackupPath.PATH_SEP); if (type != BackupFileType.META && type != BackupFileType.CL) { @@ -83,7 +83,7 @@ public void parseRemote(String remoteFilePath) { baseDir = pieces.get(0); region = pieces.get(1); clusterName = pieces.get(2); - token = pieces.get(3); + nodeIdentifier = pieces.get(3); time = parseDate(pieces.get(4)); type = BackupFileType.valueOf(pieces.get(5)); if (type != BackupFileType.META && type != BackupFileType.CL) { @@ -109,14 +109,14 @@ public void parsePartialPrefix(String remoteFilePath) { baseDir = pieces.get(0); region = pieces.get(1); clusterName = pieces.get(2); - token = pieces.get(3); + nodeIdentifier = pieces.get(3); } @Override public String remotePrefix(Date start, Date end, String location) { StringBuffer buff = new StringBuffer(clusterPrefix(location)); - token = factory.getInstance().getToken(); - buff.append(token).append(S3BackupPath.PATH_SEP); + nodeIdentifier = instanceIdentity.getBackupIdentifier(); + buff.append(nodeIdentifier).append(S3BackupPath.PATH_SEP); // match the common characters to prefix. buff.append(match(start, end)); return buff.toString(); diff --git a/priam/src/main/java/com/netflix/priam/aws/SDBInstanceData.java b/priam/src/main/java/com/netflix/priam/aws/SDBInstanceData.java index d06ee2ca1..826a6b52a 100644 --- a/priam/src/main/java/com/netflix/priam/aws/SDBInstanceData.java +++ b/priam/src/main/java/com/netflix/priam/aws/SDBInstanceData.java @@ -138,7 +138,9 @@ protected List createAttributesToRegister(PriamInstance in instance.setUpdatetime(new Date().getTime()); List attrs = new ArrayList(); attrs.add(new ReplaceableAttribute(Attributes.INSTANCE_ID, instance.getInstanceId(), false)); - attrs.add(new ReplaceableAttribute(Attributes.TOKEN, instance.getToken(), true)); + if (instance.getToken() != null) { + attrs.add(new ReplaceableAttribute(Attributes.TOKEN, instance.getToken(), true)); + } attrs.add(new ReplaceableAttribute(Attributes.APP_ID, instance.getApp(), true)); attrs.add(new ReplaceableAttribute(Attributes.ID, Integer.toString(instance.getId()), true)); attrs.add(new ReplaceableAttribute(Attributes.AVAILABILITY_ZONE, instance.getRac(), true)); @@ -152,7 +154,9 @@ protected List createAttributesToRegister(PriamInstance in protected List createAttributesToDeRegister(PriamInstance instance) { List attrs = new ArrayList(); attrs.add(new Attribute(Attributes.INSTANCE_ID, instance.getInstanceId())); - attrs.add(new Attribute(Attributes.TOKEN, instance.getToken())); + if (instance.getToken() != null) { + attrs.add(new Attribute(Attributes.TOKEN, instance.getToken())); + } attrs.add(new Attribute(Attributes.APP_ID, instance.getApp())); attrs.add(new Attribute(Attributes.ID, Integer.toString(instance.getId()))); attrs.add(new Attribute(Attributes.AVAILABILITY_ZONE, instance.getRac())); diff --git a/priam/src/main/java/com/netflix/priam/aws/UpdateSecuritySettings.java b/priam/src/main/java/com/netflix/priam/aws/UpdateSecuritySettings.java index 7c2bbb430..583c733b3 100644 --- a/priam/src/main/java/com/netflix/priam/aws/UpdateSecuritySettings.java +++ b/priam/src/main/java/com/netflix/priam/aws/UpdateSecuritySettings.java @@ -115,7 +115,7 @@ public static TaskTimer getTimer(InstanceIdentity id) { logger.info("Seed node. Instance id: {}" + ", host ip: {}" + ", host name: {}", - id.getInstance().getInstanceId(), id.getInstance().getHostIP(), id.getInstance().getHostName()); + id.getInstanceId(), id.getHostIP(), id.getHostName()); return_ = new SimpleTimer(JOBNAME, 120 * 1000 + ran.nextInt(120 * 1000)); } else return_ = new SimpleTimer(JOBNAME); diff --git a/priam/src/main/java/com/netflix/priam/backup/AbstractBackupPath.java b/priam/src/main/java/com/netflix/priam/backup/AbstractBackupPath.java index 3b9545909..5ee89cb8c 100644 --- a/priam/src/main/java/com/netflix/priam/backup/AbstractBackupPath.java +++ b/priam/src/main/java/com/netflix/priam/backup/AbstractBackupPath.java @@ -53,21 +53,21 @@ public enum BackupFileType { protected String columnFamily; protected String fileName; protected String baseDir; - protected String token; + protected String nodeIdentifier; protected String region; protected Date time; protected long size; //uncompressed file size protected long compressedFileSize = 0; protected boolean isCassandra1_0; - protected final InstanceIdentity factory; + protected final InstanceIdentity instanceIdentity; protected final IConfiguration config; protected File backupFile; protected Date uploadedTs; protected int awsSlowDownExceptionCounter = 0; - public AbstractBackupPath(IConfiguration config, InstanceIdentity factory) { - this.factory = factory; + public AbstractBackupPath(IConfiguration config, InstanceIdentity instanceIdentity) { + this.instanceIdentity = instanceIdentity; this.config = config; } @@ -93,7 +93,7 @@ public void parseLocal(File file, BackupFileType type) throws ParseException { this.clusterName = config.getAppName(); this.baseDir = config.getBackupLocation(); this.region = config.getDC(); - this.token = factory.getInstance().getToken(); + this.nodeIdentifier = instanceIdentity.getBackupIdentifier(); this.type = type; if (type != BackupFileType.META && type != BackupFileType.CL) { this.keyspace = elements[0]; @@ -214,8 +214,8 @@ public String getBaseDir() { return baseDir; } - public String getToken() { - return token; + public String getNodeIdentifier() { + return nodeIdentifier; } public String getRegion() { @@ -262,7 +262,7 @@ public void setFileName(String fileName) { } public InstanceIdentity getInstanceIdentity() { - return this.factory; + return this.instanceIdentity; } public void setUploadedTs(Date uploadedTs) { diff --git a/priam/src/main/java/com/netflix/priam/backup/SnapshotBackup.java b/priam/src/main/java/com/netflix/priam/backup/SnapshotBackup.java index c3f7f6b2c..dff65f827 100644 --- a/priam/src/main/java/com/netflix/priam/backup/SnapshotBackup.java +++ b/priam/src/main/java/com/netflix/priam/backup/SnapshotBackup.java @@ -83,10 +83,10 @@ public void execute() throws Exception { Date startTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime(); snapshotName = pathFactory.get().formatDate(startTime); - String token = instanceIdentity.getInstance().getToken(); + String backupIdentifier = instanceIdentity.getBackupIdentifier(); // Save start snapshot status - BackupMetadata backupMetadata = new BackupMetadata(token, startTime); + BackupMetadata backupMetadata = new BackupMetadata(backupIdentifier, startTime); snapshotStatusMgr.start(backupMetadata); try { diff --git a/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java b/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java index b53a68499..bdc5b113b 100644 --- a/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java +++ b/priam/src/main/java/com/netflix/priam/defaultimpl/PriamConfiguration.java @@ -772,6 +772,7 @@ public String getCassProcessName() { return config.get(CONFIG_CASS_PROCESS_NAME, DEFAULT_CASS_PROCESS_NAME); } + @Override public int getNumTokens() { return config.get(CONFIG_VNODE_NUM_TOKENS, DEFAULT_VNODE_NUM_TOKENS); } diff --git a/priam/src/main/java/com/netflix/priam/identity/InstanceIdentity.java b/priam/src/main/java/com/netflix/priam/identity/InstanceIdentity.java index fa9a0c988..8924baabf 100644 --- a/priam/src/main/java/com/netflix/priam/identity/InstanceIdentity.java +++ b/priam/src/main/java/com/netflix/priam/identity/InstanceIdentity.java @@ -31,6 +31,7 @@ import com.netflix.priam.utils.ITokenManager; import com.netflix.priam.utils.RetryableCallable; import com.netflix.priam.utils.Sleeper; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,6 +74,8 @@ public boolean test(PriamInstance input) { }; private PriamInstance myInstance; + private String backupIdentifier; + private boolean outOfService = false; private boolean isReplace = false; private boolean isTokenPregenerated = false; private String replacedIp = ""; @@ -99,7 +102,7 @@ public InstanceIdentity(IPriamInstanceFactory factory, IMembership membership, I init(); } - public PriamInstance getInstance() { + PriamInstance getInstance() { return myInstance; } @@ -113,7 +116,7 @@ public PriamInstance retriableCall() throws Exception { for (PriamInstance ins : deadInstances) { logger.info("[Dead] Iterating though the hosts: {}", ins.getInstanceId()); if (ins.getInstanceId().equals(config.getInstanceName())) { - ins.setOutOfService(true); + outOfService = true; logger.info("[Dead] found that this node is dead." + " application: {}" + ", id: {}" @@ -237,6 +240,13 @@ public void forEachExecution() { } logger.info("My token: {}", myInstance.getToken()); + + if (myInstance.getToken() == null || myInstance.getToken().isEmpty()) { + backupIdentifier = "virual" + Integer.toString(myInstance.getId()); + } else + { + backupIdentifier = myInstance.getToken(); + } } private void populateRacMap() { @@ -299,4 +309,44 @@ public String getReplacedIp() { private static boolean isInstanceDummy(PriamInstance instance) { return instance.getInstanceId().equals(DUMMY_INSTANCE_ID); } + + public boolean isOutOfService() + { + return outOfService; + } + + public String getBackupIdentifier() + { + return backupIdentifier; + } + + public void setBackupIdentifier(String backupIdentifier) + { + this.backupIdentifier = backupIdentifier; + } + + public String getToken() + { + return myInstance.getToken(); + } + + public String getInstanceId() + { + return myInstance.getInstanceId(); + } + + public String getHostIP() + { + return myInstance.getHostIP(); + } + + public String getHostName() + { + return myInstance.getHostName(); + } + + public boolean isExternallyDefinedToken() + { + return StringUtils.isNotBlank(getToken()); + } } \ No newline at end of file diff --git a/priam/src/main/java/com/netflix/priam/identity/PriamInstance.java b/priam/src/main/java/com/netflix/priam/identity/PriamInstance.java index 90d8d2287..be46569b9 100644 --- a/priam/src/main/java/com/netflix/priam/identity/PriamInstance.java +++ b/priam/src/main/java/com/netflix/priam/identity/PriamInstance.java @@ -130,13 +130,5 @@ public void setUpdatetime(long updatetime) { this.updatetime = updatetime; } - public boolean isOutOfService() { - return outOfService; - } - - public void setOutOfService(boolean outOfService) { - this.outOfService = outOfService; - } - } \ No newline at end of file diff --git a/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java b/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java index 3eae531c0..ac416d75b 100755 --- a/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java +++ b/priam/src/main/java/com/netflix/priam/identity/token/DeadTokenRetriever.java @@ -132,21 +132,23 @@ public String getReplaceIp() { private String findReplaceIp(List allIds, String token, String location) { String ip = null; - for (PriamInstance ins : allIds) { - logger.info("Calling getIp on hostname[{}] and token[{}]", ins.getHostName(), token); - if (ins.getToken().equals(token) || !ins.getDC().equals(location)) { //avoid using dead instance and other regions' instances - continue; - } - - try { - ip = getIp(ins.getHostName(), token); - } catch (ParseException e) { - ip = null; - } - - if (ip != null) { - logger.info("Found the IP: {}", ip); - return ip; + if (token != null) { + for (PriamInstance ins : allIds) { + logger.info("Calling getIp on hostname[{}] and token[{}]", ins.getHostName(), token); + if (token.equalsIgnoreCase(ins.getToken()) || !ins.getDC().equals(location)) { //avoid using dead instance and other regions' instances + continue; + } + + try { + ip = getIp(ins.getHostName(), token); + } catch (ParseException e) { + ip = null; + } + + if (ip != null) { + logger.info("Found the IP: {}", ip); + return ip; + } } } diff --git a/priam/src/main/java/com/netflix/priam/identity/token/NewTokenRetriever.java b/priam/src/main/java/com/netflix/priam/identity/token/NewTokenRetriever.java index ea8a0c618..0f699e947 100755 --- a/priam/src/main/java/com/netflix/priam/identity/token/NewTokenRetriever.java +++ b/priam/src/main/java/com/netflix/priam/identity/token/NewTokenRetriever.java @@ -52,7 +52,7 @@ public NewTokenRetriever(IPriamInstanceFactory factory, IMembership membership, @Override public PriamInstance get() throws Exception { - logger.info("Generating my own and grabbing new token"); + logger.info("Generating my own and grabbing new identifier"); // Sleep random interval - upto 15 sec sleeper.sleep(new Random().nextInt(15000)); int hash = tokenManager.regionOffset(config.getDC()); @@ -74,10 +74,16 @@ public PriamInstance get() throws Exception { } else my_slot = config.getRacs().size() + maxSlot; - logger.info("Trying to createToken with slot {} with rac count {} with rac membership size {} with dc {}", - my_slot, membership.getRacCount(), membership.getRacMembershipSize(), config.getDC()); - String payload = tokenManager.createToken(my_slot, membership.getRacCount(), membership.getRacMembershipSize(), config.getDC()); - return factory.create(config.getAppName(), my_slot + hash, config.getInstanceName(), config.getHostname(), config.getHostIP(), config.getRac(), null, payload); + int identifier = my_slot + hash; + String token = null; + if (config.getNumTokens() == 1) + { + logger.info("Trying to createToken with slot {} with rac count {} with rac membership size {} with dc {}", + my_slot, membership.getRacCount(), membership.getRacMembershipSize(), config.getDC()); + token = tokenManager.createToken( + my_slot, membership.getRacCount(), membership.getRacMembershipSize(), config.getDC()); + } + return factory.create(config.getAppName(), identifier, config.getInstanceName(), config.getHostname(), config.getHostIP(), config.getRac(), null, token); } diff --git a/priam/src/main/java/com/netflix/priam/notification/BackupNotificationMgr.java b/priam/src/main/java/com/netflix/priam/notification/BackupNotificationMgr.java index a624f0bfb..5a24e02fe 100644 --- a/priam/src/main/java/com/netflix/priam/notification/BackupNotificationMgr.java +++ b/priam/src/main/java/com/netflix/priam/notification/BackupNotificationMgr.java @@ -51,7 +51,8 @@ private void notify(AbstractBackupPath abp, String uploadStatus) { jsonObject.put("cf", abp.getColumnFamily()); jsonObject.put("region", abp.getRegion()); jsonObject.put("rack", this.config.getRac()); - jsonObject.put("token", abp.getToken()); + jsonObject.put("token", abp.getNodeIdentifier()); + jsonObject.put("nodeIdentifier", abp.getNodeIdentifier()); jsonObject.put("filename", abp.getFileName()); jsonObject.put("uncompressfilesize", abp.getSize()); jsonObject.put("compressfilesize", abp.getCompressedFileSize()); diff --git a/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java b/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java index 066455f64..17f6972e1 100644 --- a/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java +++ b/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java @@ -29,6 +29,7 @@ import com.netflix.priam.identity.PriamInstance; import com.netflix.priam.restore.Restore; import com.netflix.priam.scheduler.PriamScheduler; +import com.netflix.priam.restore.RestoreTokenSelector; import com.netflix.priam.tuner.ICassandraTuner; import com.netflix.priam.utils.*; import org.apache.commons.lang3.StringUtils; @@ -81,8 +82,7 @@ public class BackupServlet { private Provider pathProvider; private ICassandraTuner tuner; private SnapshotBackup snapshotBackup; - private IPriamInstanceFactory factory; - private final ITokenManager tokenManager; + private final RestoreTokenSelector tokenSelector; private final ICassandraProcess cassProcess; private BackupVerification backupVerification; @Inject @@ -93,9 +93,10 @@ public class BackupServlet { private IBackupStatusMgr completedBkups; @Inject - public BackupServlet(PriamServer priamServer, IConfiguration config, @Named("backup") IBackupFileSystem backupFs, @Named("backup_status") IBackupFileSystem bkpStatusFs, Restore restoreObj, Provider pathProvider, ICassandraTuner tuner, - SnapshotBackup snapshotBackup, IPriamInstanceFactory factory, ITokenManager tokenManager, ICassandraProcess cassProcess - , IBackupStatusMgr completedBkups, BackupVerification backupVerification) { + public BackupServlet(PriamServer priamServer, IConfiguration config, @Named("backup")IBackupFileSystem backupFs,@Named("backup_status")IBackupFileSystem bkpStatusFs, Restore restoreObj, Provider pathProvider, ICassandraTuner tuner, + SnapshotBackup snapshotBackup, RestoreTokenSelector tokenSelector, ICassandraProcess cassProcess + ,IBackupStatusMgr completedBkups, BackupVerification backupVerification) + { this.priamServer = priamServer; this.config = config; this.backupFs = backupFs; @@ -104,8 +105,7 @@ public BackupServlet(PriamServer priamServer, IConfiguration config, @Named("bac this.pathProvider = pathProvider; this.tuner = tuner; this.snapshotBackup = snapshotBackup; - this.factory = factory; - this.tokenManager = tokenManager; + this.tokenSelector = tokenSelector; this.cassProcess = cassProcess; this.completedBkups = completedBkups; this.backupVerification = backupVerification; @@ -408,18 +408,23 @@ public Response restore_verify_key( */ private void restore(String token, String region, Date startTime, Date endTime, String keyspaces) throws Exception { String origRegion = config.getDC(); - String origToken = priamServer.getId().getInstance().getToken(); + String origBackupIdentifier = priamServer.getId().getBackupIdentifier(); if (StringUtils.isNotBlank(token)) - priamServer.getId().getInstance().setToken(token); + { + priamServer.getId().setBackupIdentifier(token); + } + else { + token = priamServer.getId().getToken(); + } if (config.isRestoreClosestToken()) - priamServer.getId().getInstance().setToken(closestToken(priamServer.getId().getInstance().getToken(), config.getDC())); + priamServer.getId().setBackupIdentifier(tokenSelector.getClosestToken(token, config.getAppName(), config.getDC()).toString()); if (StringUtils.isNotBlank(region)) { config.setDC(region); logger.info("Restoring from region {}", region); - priamServer.getId().getInstance().setToken(closestToken(priamServer.getId().getInstance().getToken(), region)); - logger.info("Restore will use token {}", priamServer.getId().getInstance().getToken()); + priamServer.getId().setBackupIdentifier(tokenSelector.getClosestToken(token, config.getAppName(), region).toString()); + logger.info("Restore will use backup identifier {}", priamServer.getId().getBackupIdentifier()); } setRestoreKeyspaces(keyspaces); @@ -428,25 +433,12 @@ private void restore(String token, String region, Date startTime, Date endTime, restoreObj.restore(startTime, endTime); } finally { config.setDC(origRegion); - priamServer.getId().getInstance().setToken(origToken); + priamServer.getId().setBackupIdentifier(origBackupIdentifier); } tuner.updateAutoBootstrap(config.getYamlLocation(), false); cassProcess.start(true); } - /** - * Find closest token in the specified region - */ - private String closestToken(String token, String region) { - List plist = factory.getAllIds(config.getAppName()); - List tokenList = Lists.newArrayList(); - for (PriamInstance ins : plist) { - if (ins.getDC().equalsIgnoreCase(region)) - tokenList.add(new BigInteger(ins.getToken())); - } - return tokenManager.findClosestToken(new BigInteger(token), tokenList).toString(); - } - /* * TODO: decouple the servlet, config, and restorer. this should not rely on a side * effect of a list mutation on the config object (treating it as global var). @@ -483,10 +475,10 @@ private JSONObject constructJsonResponse(JSONObject object, Iterator pathProvider; private PriamServer priamServer; - private IPriamInstanceFactory factory; private ICassandraTuner tuner; private ICassandraProcess cassProcess; - private ITokenManager tokenManager; + private RestoreTokenSelector tokenSelector; private InstanceState instanceState; @Inject public RestoreServlet(IConfiguration config, Restore restoreObj, Provider pathProvider, PriamServer priamServer - , IPriamInstanceFactory factory, ICassandraTuner tuner, ICassandraProcess cassProcess, ITokenManager tokenManager, InstanceState instanceState) { + , RestoreTokenSelector tokenSelector, ICassandraTuner tuner, ICassandraProcess cassProcess, InstanceState instanceState) { this.config = config; this.restoreObj = restoreObj; this.pathProvider = pathProvider; this.priamServer = priamServer; - this.factory = factory; this.tuner = tuner; this.cassProcess = cassProcess; - this.tokenManager = tokenManager; this.instanceState = instanceState; } @@ -140,18 +138,23 @@ public Response restore(@QueryParam(REST_HEADER_RANGE) String daterange, @QueryP */ private void restore(String token, String region, Date startTime, Date endTime, String keyspaces) throws Exception { String origRegion = config.getDC(); - String origToken = priamServer.getId().getInstance().getToken(); + String origBackupIdentifier = priamServer.getId().getBackupIdentifier(); if (StringUtils.isNotBlank(token)) - priamServer.getId().getInstance().setToken(token); + { + priamServer.getId().setBackupIdentifier(token); + } + else { + token = priamServer.getId().getToken(); + } if (config.isRestoreClosestToken()) - priamServer.getId().getInstance().setToken(closestToken(priamServer.getId().getInstance().getToken(), config.getDC())); + priamServer.getId().setBackupIdentifier(tokenSelector.getClosestToken(token, config.getAppName(), config.getDC()).toString()); if (StringUtils.isNotBlank(region)) { config.setDC(region); logger.info("Restoring from region {}", region); - priamServer.getId().getInstance().setToken(closestToken(priamServer.getId().getInstance().getToken(), region)); - logger.info("Restore will use token {}", priamServer.getId().getInstance().getToken()); + priamServer.getId().setBackupIdentifier(tokenSelector.getClosestToken(token, config.getAppName(), region).toString()); + logger.info("Restore will use backup identifier {}", priamServer.getId().getBackupIdentifier()); } setRestoreKeyspaces(keyspaces); @@ -160,25 +163,12 @@ private void restore(String token, String region, Date startTime, Date endTime, restoreObj.restore(startTime, endTime); } finally { config.setDC(origRegion); - priamServer.getId().getInstance().setToken(origToken); + priamServer.getId().setBackupIdentifier(origBackupIdentifier); } tuner.updateAutoBootstrap(config.getYamlLocation(), false); cassProcess.start(true); } - /** - * Find closest token in the specified region - */ - private String closestToken(String token, String region) { - List plist = factory.getAllIds(config.getAppName()); - List tokenList = Lists.newArrayList(); - for (PriamInstance ins : plist) { - if (ins.getDC().equalsIgnoreCase(region)) - tokenList.add(new BigInteger(ins.getToken())); - } - return tokenManager.findClosestToken(new BigInteger(token), tokenList).toString(); - } - /* * TODO: decouple the servlet, config, and restorer. this should not rely on a side * effect of a list mutation on the config object (treating it as global var). diff --git a/priam/src/main/java/com/netflix/priam/restore/AbstractRestore.java b/priam/src/main/java/com/netflix/priam/restore/AbstractRestore.java index cb671d324..1792601f0 100644 --- a/priam/src/main/java/com/netflix/priam/restore/AbstractRestore.java +++ b/priam/src/main/java/com/netflix/priam/restore/AbstractRestore.java @@ -205,12 +205,12 @@ public void restore(Date startTime, Date endTime) throws Exception { instanceState.getRestoreStatus().setEndDateRange(DateUtil.convert(endTime)); instanceState.getRestoreStatus().setExecutionStartTime(LocalDateTime.now()); instanceState.setRestoreStatus(Status.STARTED); - String origToken = id.getInstance().getToken(); + String origBackupIdentifier = id.getBackupIdentifier(); try { if (config.isRestoreClosestToken()) { - restoreToken = tokenSelector.getClosestToken(new BigInteger(origToken), startTime); - id.getInstance().setToken(restoreToken.toString()); + restoreToken = tokenSelector.getClosestToken(id.getToken(), startTime); + id.setBackupIdentifier(restoreToken.toString()); } // Stop cassandra if its running and restoring all keyspaces @@ -278,7 +278,7 @@ public void restore(Date startTime, Date endTime) throws Exception { logger.error("Error while trying to restore: {}", e.getMessage(), e); throw e; } finally { - id.getInstance().setToken(origToken); + id.setBackupIdentifier(origBackupIdentifier); } } diff --git a/priam/src/main/java/com/netflix/priam/restore/RestoreTokenSelector.java b/priam/src/main/java/com/netflix/priam/restore/RestoreTokenSelector.java index 8b1207854..8ae502201 100644 --- a/priam/src/main/java/com/netflix/priam/restore/RestoreTokenSelector.java +++ b/priam/src/main/java/com/netflix/priam/restore/RestoreTokenSelector.java @@ -1,26 +1,30 @@ -/* +/** * Copyright 2013 Netflix, Inc. * * Licensed 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 + * 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 com.netflix.priam.restore; +import com.google.common.collect.Lists; import com.google.inject.Inject; import com.google.inject.name.Named; import com.netflix.priam.backup.AbstractBackupPath; import com.netflix.priam.backup.IBackupFileSystem; +import com.netflix.priam.identity.IPriamInstanceFactory; +import com.netflix.priam.identity.PriamInstance; import com.netflix.priam.utils.ITokenManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.math.BigInteger; import java.util.ArrayList; @@ -31,17 +35,21 @@ /** * Runs algorithms as finding closest token from a list of token (in a backup) */ -public class RestoreTokenSelector { +public class RestoreTokenSelector +{ + private static final Logger logger = LoggerFactory.getLogger(RestoreTokenSelector.class); private final ITokenManager tokenManager; private final IBackupFileSystem fs; + private final IPriamInstanceFactory factory; @Inject - public RestoreTokenSelector(ITokenManager tokenManager, @Named("backup") IBackupFileSystem fs) + public RestoreTokenSelector(ITokenManager tokenManager,@Named("backup")IBackupFileSystem fs, IPriamInstanceFactory factory) { this.tokenManager = tokenManager; this.fs = fs; + this.factory = factory; } /** @@ -52,11 +60,52 @@ public RestoreTokenSelector(ITokenManager tokenManager, @Named("backup") IBackup * @param startDate Date for which the backups are available * @return Token as BigInteger */ - public BigInteger getClosestToken(BigInteger tokenToSearch, Date startDate) { + public BigInteger getClosestToken(String tokenToSearch, Date startDate) + { + BigInteger tokenToSearchInteger = parseToken(tokenToSearch, "Instance does not have a valid, single token to find the closest backup to. Token: %s"); List tokenList = new ArrayList(); Iterator iter = fs.listPrefixes(startDate); - while (iter.hasNext()) - tokenList.add(new BigInteger(iter.next().getToken())); - return tokenManager.findClosestToken(tokenToSearch, tokenList); + while (iter.hasNext()) { + BigInteger backupToken = parseToken(iter.next().getNodeIdentifier(), "Backup is not identified by a token. BackupNodeIdentifier: %s"); + tokenList.add(backupToken); + } + return tokenManager.findClosestToken(tokenToSearchInteger, tokenList); + } + + /** + * Get the closest token to current token among existing nodes in the specified region + * + * @param tokenToSearch + * Token to search for + * @param appName + * the cluster name + * @param region + * Region to search for a node with the closest token + * @return Token as BigInteger + */ + public BigInteger getClosestToken(String tokenToSearch, String appName, String region) + { + BigInteger tokenToSearchInteger = parseToken(tokenToSearch, "Instance does not have a valid, single token to find the closest backup to. Token: %s"); + List plist = factory.getAllIds(appName); + List tokenList = Lists.newArrayList(); + for (PriamInstance ins : plist) + { + if (ins.getDC().equalsIgnoreCase(region)) { + BigInteger otherNodeToken = parseToken(ins.getToken(), "Remote instance does not have a valid, single token to find the closest backup to. Token: %s"); + tokenList.add(otherNodeToken); + } + } + return tokenManager.findClosestToken(tokenToSearchInteger, tokenList); + } + + private BigInteger parseToken(String tokenString, String errorMessageFormat) + { + try { + return new BigInteger(tokenString); + } + catch (NumberFormatException ex) { + logger.error(String.format(errorMessageFormat, tokenString), ex); + throw ex; + } } -} +} \ No newline at end of file diff --git a/priam/src/main/java/com/netflix/priam/tuner/StandardTuner.java b/priam/src/main/java/com/netflix/priam/tuner/StandardTuner.java index ac4ea2ffd..1aab91896 100644 --- a/priam/src/main/java/com/netflix/priam/tuner/StandardTuner.java +++ b/priam/src/main/java/com/netflix/priam/tuner/StandardTuner.java @@ -114,7 +114,7 @@ public void writeAllProperties(String yamlLocation, String hostname, String seed configfureSecurity(map); configureGlobalCaches(config, map); //force to 1 until vnodes are properly supported - map.put("num_tokens", 1); + map.put("num_tokens", config.getNumTokens()); addExtraCassParams(map); diff --git a/priam/src/test/java/com/netflix/priam/FakeConfiguration.java b/priam/src/test/java/com/netflix/priam/FakeConfiguration.java index 31a85e7a2..7433c2786 100644 --- a/priam/src/test/java/com/netflix/priam/FakeConfiguration.java +++ b/priam/src/test/java/com/netflix/priam/FakeConfiguration.java @@ -37,6 +37,7 @@ public class FakeConfiguration implements IConfiguration { public String zone; public String instance_id; public String restorePrefix; + public int numTokens; public FakeConfiguration() { this(FAKE_REGION, "my_fake_cluster", "my_zone", "i-01234567"); @@ -48,6 +49,7 @@ public FakeConfiguration(String region, String appName, String zone, String ins_ this.zone = zone; this.instance_id = ins_id; this.restorePrefix = ""; + this.numTokens = 1; } @Override @@ -416,7 +418,7 @@ public String getCassProcessName() { } public int getNumTokens() { - return 1; + return numTokens; } public String getYamlLocation() { diff --git a/priam/src/test/java/com/netflix/priam/backup/BRTestModule.java b/priam/src/test/java/com/netflix/priam/backup/BRTestModule.java index 5409cd8ef..e72ff70cb 100644 --- a/priam/src/test/java/com/netflix/priam/backup/BRTestModule.java +++ b/priam/src/test/java/com/netflix/priam/backup/BRTestModule.java @@ -25,7 +25,7 @@ import com.netflix.priam.aws.S3BackupPath; import com.netflix.priam.aws.auth.IS3Credential; import com.netflix.priam.aws.auth.S3RoleAssumptionCredential; -import com.netflix.priam.backup.identity.FakeInstanceEnvIdentity; +import com.netflix.priam.identity.FakeInstanceEnvIdentity; import com.netflix.priam.compress.ICompression; import com.netflix.priam.compress.SnappyCompression; import com.netflix.priam.cryptography.IFileCryptography; diff --git a/priam/src/test/java/com/netflix/priam/backup/TestBackupFile.java b/priam/src/test/java/com/netflix/priam/backup/TestBackupFile.java index b08735535..30a6afc71 100644 --- a/priam/src/test/java/com/netflix/priam/backup/TestBackupFile.java +++ b/priam/src/test/java/com/netflix/priam/backup/TestBackupFile.java @@ -57,8 +57,8 @@ public static void setup() throws IOException { bos1.flush(); bos1.close(); } - InstanceIdentity factory = injector.getInstance(InstanceIdentity.class); - factory.getInstance().setToken("1234567");//Token + InstanceIdentity instanceIdentity = injector.getInstance(InstanceIdentity.class); + instanceIdentity.setBackupIdentifier("1234567"); } @AfterClass @@ -76,7 +76,7 @@ public void testBackupFileCreation() throws ParseException { Assert.assertEquals(BackupFileType.SNAP, backupfile.type); Assert.assertEquals("Keyspace1", backupfile.keyspace); Assert.assertEquals("Standard1", backupfile.columnFamily); - Assert.assertEquals("1234567", backupfile.token); + Assert.assertEquals("1234567", backupfile.nodeIdentifier); Assert.assertEquals("fake-app", backupfile.clusterName); Assert.assertEquals(FakeConfiguration.FAKE_REGION, backupfile.region); Assert.assertEquals("casstestbackup", backupfile.baseDir); @@ -92,7 +92,7 @@ public void testIncBackupFileCreation() throws ParseException { Assert.assertEquals(BackupFileType.SST, backupfile.type); Assert.assertEquals("Keyspace1", backupfile.keyspace); Assert.assertEquals("Standard1", backupfile.columnFamily); - Assert.assertEquals("1234567", backupfile.token); + Assert.assertEquals("1234567", backupfile.nodeIdentifier); Assert.assertEquals("fake-app", backupfile.clusterName); Assert.assertEquals(FakeConfiguration.FAKE_REGION, backupfile.region); Assert.assertEquals("casstestbackup", backupfile.baseDir); @@ -109,7 +109,7 @@ public void testMetaFileCreation() throws ParseException { backupfile.time = backupfile.parseDate("201108082320"); backupfile.parseLocal(bfile, BackupFileType.META); Assert.assertEquals(BackupFileType.META, backupfile.type); - Assert.assertEquals("1234567", backupfile.token); + Assert.assertEquals("1234567", backupfile.nodeIdentifier); Assert.assertEquals("fake-app", backupfile.clusterName); Assert.assertEquals(FakeConfiguration.FAKE_REGION, backupfile.region); Assert.assertEquals("casstestbackup", backupfile.baseDir); diff --git a/priam/src/test/java/com/netflix/priam/backup/TestFileIterator.java b/priam/src/test/java/com/netflix/priam/backup/TestFileIterator.java index fc3405532..7861f5b16 100644 --- a/priam/src/test/java/com/netflix/priam/backup/TestFileIterator.java +++ b/priam/src/test/java/com/netflix/priam/backup/TestFileIterator.java @@ -52,8 +52,7 @@ public class TestFileIterator { private static AmazonS3Client s3client; private static IConfiguration conf; - private static InstanceIdentity factory; - + private static InstanceIdentity instanceIdentity; @BeforeClass public static void setup() throws InterruptedException, IOException { s3client = new MockAmazonS3Client().getMockInstance(); @@ -61,7 +60,7 @@ public static void setup() throws InterruptedException, IOException { injector = Guice.createInjector(new BRTestModule()); conf = injector.getInstance(IConfiguration.class); - factory = injector.getInstance(InstanceIdentity.class); + instanceIdentity = injector.getInstance(InstanceIdentity.class); cal = Calendar.getInstance(); cal.set(2011, 7, 11, 0, 30, 0); @@ -132,7 +131,7 @@ public void testIteratorEmptySet() { cal.add(Calendar.HOUR, 5); Date etime = cal.getTime(); MockAmazonS3Client.bucketName = "TESTBUCKET"; - MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + factory.getInstance().getToken(); + MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + instanceIdentity.getBackupIdentifier(); MockAmazonS3Client.prefix += "/20110811"; S3FileIterator fileIterator = new S3FileIterator(injector.getProvider(AbstractBackupPath.class), s3client, "TESTBUCKET", stime, etime); @@ -148,7 +147,7 @@ public void testIterator() { MockObjectListing.firstcall = true; MockObjectListing.simfilter = false; MockAmazonS3Client.bucketName = "TESTBUCKET"; - MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + factory.getInstance().getToken(); + MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + instanceIdentity.getBackupIdentifier(); MockAmazonS3Client.prefix += "/20110811"; S3FileIterator fileIterator = new S3FileIterator(injector.getProvider(AbstractBackupPath.class), s3client, "TESTBUCKET", startTime, endTime); @@ -168,7 +167,7 @@ public void testIteratorTruncated() { MockObjectListing.firstcall = true; MockObjectListing.simfilter = false; MockAmazonS3Client.bucketName = "TESTBUCKET"; - MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + factory.getInstance().getToken(); + MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + instanceIdentity.getBackupIdentifier(); MockAmazonS3Client.prefix += "/20110811"; S3FileIterator fileIterator = new S3FileIterator(injector.getProvider(AbstractBackupPath.class), s3client, "TESTBUCKET", startTime, endTime); @@ -193,7 +192,7 @@ public void testIteratorTruncatedOOR() { MockObjectListing.firstcall = true; MockObjectListing.simfilter = true; MockAmazonS3Client.bucketName = "TESTBUCKET"; - MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + factory.getInstance().getToken(); + MockAmazonS3Client.prefix = conf.getBackupLocation() + "/" + conf.getDC() + "/" + conf.getAppName() + "/" + instanceIdentity.getBackupIdentifier(); MockAmazonS3Client.prefix += "/20110811"; S3FileIterator fileIterator = new S3FileIterator(injector.getProvider(AbstractBackupPath.class), s3client, "TESTBUCKET", startTime, endTime); @@ -218,7 +217,7 @@ public void testRestorePathIteration() { MockObjectListing.firstcall = true; MockObjectListing.simfilter = false; MockAmazonS3Client.bucketName = "RESTOREBUCKET"; - MockAmazonS3Client.prefix = "test_restore_backup/fake-restore-region/fakerestorecluster" + "/" + factory.getInstance().getToken(); + MockAmazonS3Client.prefix = "test_restore_backup/fake-restore-region/fakerestorecluster" + "/" + instanceIdentity.getBackupIdentifier(); MockAmazonS3Client.prefix += "/20110811"; S3FileIterator fileIterator = new S3FileIterator(injector.getProvider(AbstractBackupPath.class), s3client, "RESTOREBUCKET/test_restore_backup/fake-restore-region/fakerestorecluster", startTime, endTime); diff --git a/priam/src/test/java/com/netflix/priam/backup/identity/DoubleRingTest.java b/priam/src/test/java/com/netflix/priam/identity/DoubleRingTest.java similarity index 92% rename from priam/src/test/java/com/netflix/priam/backup/identity/DoubleRingTest.java rename to priam/src/test/java/com/netflix/priam/identity/DoubleRingTest.java index 7d329c7de..0712d1fad 100644 --- a/priam/src/test/java/com/netflix/priam/backup/identity/DoubleRingTest.java +++ b/priam/src/test/java/com/netflix/priam/identity/DoubleRingTest.java @@ -15,12 +15,9 @@ * */ -package com.netflix.priam.backup.identity; +package com.netflix.priam.identity; import com.google.common.collect.Lists; -import com.netflix.priam.identity.DoubleRing; -import com.netflix.priam.identity.InstanceIdentity; -import com.netflix.priam.identity.PriamInstance; import org.junit.Test; import java.util.List; diff --git a/priam/src/test/java/com/netflix/priam/backup/identity/FakeInstanceEnvIdentity.java b/priam/src/test/java/com/netflix/priam/identity/FakeInstanceEnvIdentity.java similarity index 95% rename from priam/src/test/java/com/netflix/priam/backup/identity/FakeInstanceEnvIdentity.java rename to priam/src/test/java/com/netflix/priam/identity/FakeInstanceEnvIdentity.java index 381a2b0af..038457a04 100644 --- a/priam/src/test/java/com/netflix/priam/backup/identity/FakeInstanceEnvIdentity.java +++ b/priam/src/test/java/com/netflix/priam/identity/FakeInstanceEnvIdentity.java @@ -15,7 +15,7 @@ * */ -package com.netflix.priam.backup.identity; +package com.netflix.priam.identity; import com.netflix.priam.identity.InstanceEnvIdentity; diff --git a/priam/src/test/java/com/netflix/priam/backup/identity/InstanceIdentityTest.java b/priam/src/test/java/com/netflix/priam/identity/InstanceIdentityTest.java similarity index 85% rename from priam/src/test/java/com/netflix/priam/backup/identity/InstanceIdentityTest.java rename to priam/src/test/java/com/netflix/priam/identity/InstanceIdentityTest.java index 7e5bad4e0..02bf58eec 100644 --- a/priam/src/test/java/com/netflix/priam/backup/identity/InstanceIdentityTest.java +++ b/priam/src/test/java/com/netflix/priam/identity/InstanceIdentityTest.java @@ -15,16 +15,13 @@ * */ -package com.netflix.priam.backup.identity; +package com.netflix.priam.identity; -import com.netflix.priam.identity.DoubleRing; -import com.netflix.priam.identity.InstanceIdentity; -import com.netflix.priam.identity.PriamInstance; import org.junit.Test; import java.util.List; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; public class InstanceIdentityTest extends InstanceTestUtils { @@ -60,6 +57,7 @@ public void testCreateToken() throws Exception { identity = createInstanceIdentity("az3", "fakeinstance9"); assertEquals(8, identity.getInstance().getId() - hash); + assertTrue(identity.isExternallyDefinedToken()); } @Test @@ -69,8 +67,19 @@ public void testGetSeeds() throws Exception { assertEquals(3, identity.getSeeds().size()); } + public void testVirtualNodesCreated() throws Exception + { + config.numTokens = 2; + createInstances(); + identity = createInstanceIdentity("az1", "fakeinstance1"); + assertEquals("virual" + Integer.toString(identity.getInstance().getId()), identity.getBackupIdentifier()); + assertNull(identity.getToken()); + assertFalse(identity.isExternallyDefinedToken()); + } + @Test - public void testDoubleSlots() throws Exception { + public void testDoubleSlots() throws Exception + { createInstances(); int before = factory.getAllIds("fake-app").size(); new DoubleRing(config, factory, tokenManager).doubleSlots(); diff --git a/priam/src/test/java/com/netflix/priam/backup/identity/InstanceTestUtils.java b/priam/src/test/java/com/netflix/priam/identity/InstanceTestUtils.java similarity index 98% rename from priam/src/test/java/com/netflix/priam/backup/identity/InstanceTestUtils.java rename to priam/src/test/java/com/netflix/priam/identity/InstanceTestUtils.java index f0ed33b4b..78b0ce7b4 100644 --- a/priam/src/test/java/com/netflix/priam/backup/identity/InstanceTestUtils.java +++ b/priam/src/test/java/com/netflix/priam/identity/InstanceTestUtils.java @@ -15,7 +15,7 @@ * */ -package com.netflix.priam.backup.identity; +package com.netflix.priam.identity; import com.netflix.priam.FakeConfiguration; import com.netflix.priam.FakeMembership; diff --git a/priam/src/test/java/com/netflix/priam/resources/BackupServletTest.java b/priam/src/test/java/com/netflix/priam/resources/BackupServletTest.java index 97045845b..450875974 100644 --- a/priam/src/test/java/com/netflix/priam/resources/BackupServletTest.java +++ b/priam/src/test/java/com/netflix/priam/resources/BackupServletTest.java @@ -31,6 +31,7 @@ import com.netflix.priam.identity.InstanceIdentity; import com.netflix.priam.identity.PriamInstance; import com.netflix.priam.restore.Restore; +import com.netflix.priam.restore.RestoreTokenSelector; import com.netflix.priam.tuner.ICassandraTuner; import com.netflix.priam.utils.ITokenManager; import com.netflix.priam.utils.TokenManager; @@ -82,7 +83,7 @@ public class BackupServletTest { private @Mocked BackupStatusMgr bkupStatusMgr; - private ITokenManager tokenManager; + private @Mocked IBackupFileSystem backupFileSystem; private BackupServlet resource; private RestoreServlet restoreResource; private BackupVerification backupVerification; @@ -94,11 +95,12 @@ public void setUp() { injector = Guice.createInjector(new BRTestModule()); config = injector.getInstance(IConfiguration.class); instanceState = injector.getInstance(InstanceState.class); - this.tokenManager = new TokenManager(config); + RestoreTokenSelector tokenSelector = new RestoreTokenSelector(new TokenManager(config), backupFileSystem, factory); resource = new BackupServlet(priamServer, config, bkpFs, bkpStatusFs, restoreObj, pathProvider, - tuner, snapshotBackup, factory, tokenManager, cassProcess, bkupStatusMgr, backupVerification); - restoreResource = new RestoreServlet(config, restoreObj, pathProvider,priamServer, factory, tuner, cassProcess - , tokenManager, instanceState); + tuner, snapshotBackup, tokenSelector, cassProcess, bkupStatusMgr,backupVerification); + + restoreResource = new RestoreServlet(config, restoreObj, pathProvider,priamServer, tokenSelector, tuner, cassProcess + , instanceState); } @Test @@ -114,8 +116,8 @@ public void backup() throws Exception { } @Test - public void restore_minimal(@Mocked final InstanceIdentity identity, - @Mocked final PriamInstance instance) throws Exception { + public void restore_minimal(@Mocked final InstanceIdentity identity) throws Exception + { final String dateRange = null; final String newRegion = null; final String newToken = null; @@ -128,7 +130,7 @@ public void restore_minimal(@Mocked final InstanceIdentity identity, { priamServer.getId(); result = identity; - times = 2; + times = 3; } }; @@ -137,10 +139,7 @@ public void restore_minimal(@Mocked final InstanceIdentity identity, { config.getDC(); result = oldRegion; - identity.getInstance(); - result = instance; - times = 2; - instance.getToken(); + identity.getBackupIdentifier(); result = oldToken; config.isRestoreClosestToken(); @@ -149,7 +148,7 @@ public void restore_minimal(@Mocked final InstanceIdentity identity, restoreObj.restore((Date) any, (Date) any); // TODO: test default value config.setDC(oldRegion); - instance.setToken(oldToken); + identity.setBackupIdentifier(oldToken); tuner.updateAutoBootstrap(config.getYamlLocation(), false); } }; @@ -164,7 +163,8 @@ public void restore_minimal(@Mocked final InstanceIdentity identity, @Test public void restore_withDateRange(@Mocked final InstanceIdentity identity, - @Mocked final PriamInstance instance, @Mocked final AbstractBackupPath backupPath) throws Exception { + @Mocked final AbstractBackupPath backupPath) throws Exception + { final String dateRange = "201101010000,20111231259"; final String newRegion = null; final String newToken = null; @@ -177,7 +177,7 @@ public void restore_withDateRange(@Mocked final InstanceIdentity identity, { priamServer.getId(); result = identity; - times = 2; + times = 3; } }; new Expectations() { @@ -193,10 +193,7 @@ public void restore_withDateRange(@Mocked final InstanceIdentity identity, times = 1; // config.getDC(); result = oldRegion; - identity.getInstance(); - result = instance; - times = 2; - instance.getToken(); + identity.getBackupIdentifier(); result = oldToken; // config.isRestoreClosestToken(); result = false; @@ -206,7 +203,7 @@ public void restore_withDateRange(@Mocked final InstanceIdentity identity, new DateTime(2011, 12, 31, 23, 59).toDate()); // config.setDC(oldRegion); - instance.setToken(oldToken); + identity.setBackupIdentifier(oldToken); tuner.updateAutoBootstrap(config.getYamlLocation(), false); } }; @@ -275,8 +272,8 @@ public void restore_withDateRange(@Mocked final InstanceIdentity identity, // } @Test - public void restore_withToken(@Mocked final InstanceIdentity identity, - @Mocked final PriamInstance instance) throws Exception { + public void restore_withToken(@Mocked final InstanceIdentity identity) throws Exception + { final String dateRange = null; final String newRegion = null; final String newToken = "myNewToken"; @@ -297,19 +294,16 @@ public void restore_withToken(@Mocked final InstanceIdentity identity, { config.getDC(); result = oldRegion; - identity.getInstance(); - result = instance; - times = 3; - instance.getToken(); + identity.getBackupIdentifier(); result = oldToken; - instance.setToken(newToken); + identity.setBackupIdentifier(newToken); //config.isRestoreClosestToken(); result = false; restoreObj.restore((Date) any, (Date) any); // TODO: test default value config.setDC(oldRegion); - instance.setToken(oldToken); + identity.setBackupIdentifier(oldToken); tuner.updateAutoBootstrap(config.getYamlLocation(), false); } }; @@ -323,8 +317,8 @@ public void restore_withToken(@Mocked final InstanceIdentity identity, } @Test - public void restore_withKeyspaces(@Mocked final InstanceIdentity identity, - @Mocked final PriamInstance instance) throws Exception { + public void restore_withKeyspaces(@Mocked final InstanceIdentity identity) throws Exception + { final String dateRange = null; final String newRegion = null; final String newToken = null; @@ -349,21 +343,18 @@ public void restore_withKeyspaces(@Mocked final InstanceIdentity identity, config.setDC(oldRegion); priamServer.getId(); result = identity; - times = 2; + times = 3; } }; new Expectations() { { - identity.getInstance(); - result = instance; - times = 2; - instance.getToken(); + identity.getBackupIdentifier(); result = oldToken; restoreObj.restore((Date) any, (Date) any); // TODO: test default value - instance.setToken(oldToken); + identity.setBackupIdentifier(oldToken); tuner.updateAutoBootstrap(config.getYamlLocation(), false); } }; diff --git a/priam/src/test/java/com/netflix/priam/resources/CassandraConfigTest.java b/priam/src/test/java/com/netflix/priam/resources/CassandraConfigTest.java index 8e3ee0cff..9f5fc25e6 100644 --- a/priam/src/test/java/com/netflix/priam/resources/CassandraConfigTest.java +++ b/priam/src/test/java/com/netflix/priam/resources/CassandraConfigTest.java @@ -21,7 +21,6 @@ import com.netflix.priam.PriamServer; import com.netflix.priam.identity.DoubleRing; import com.netflix.priam.identity.InstanceIdentity; -import com.netflix.priam.identity.PriamInstance; import mockit.Expectations; import mockit.Mocked; import mockit.integration.junit4.JMockit; @@ -105,17 +104,15 @@ public void getSeeds_handlesUnknownHostException(@Mocked final InstanceIdentity } @Test - public void getToken(@Mocked final InstanceIdentity identity, @Mocked final PriamInstance instance) { + public void getToken(@Mocked final InstanceIdentity identity) + { final String token = "myToken"; new Expectations() { { priamServer.getId(); result = identity; times = 2; - identity.getInstance(); - result = instance; - times = 2; - instance.getToken(); + identity.getToken(); result = token; times = 2; } @@ -127,15 +124,14 @@ public void getToken(@Mocked final InstanceIdentity identity, @Mocked final Pria } @Test - public void getToken_notFound(@Mocked final InstanceIdentity identity, @Mocked final PriamInstance instance) { + public void getToken_notFound(@Mocked final InstanceIdentity identity) + { final String token = ""; new Expectations() { { priamServer.getId(); result = identity; - identity.getInstance(); - result = instance; - instance.getToken(); + identity.getToken(); result = token; } }; @@ -145,14 +141,13 @@ public void getToken_notFound(@Mocked final InstanceIdentity identity, @Mocked f } @Test - public void getToken_handlesException(@Mocked final InstanceIdentity identity, @Mocked final PriamInstance instance) { + public void getToken_handlesException(@Mocked final InstanceIdentity identity) + { new Expectations() { { priamServer.getId(); result = identity; - identity.getInstance(); - result = instance; - instance.getToken(); + identity.getToken(); result = new RuntimeException(); } }; @@ -178,7 +173,25 @@ public void isReplaceToken(@Mocked final InstanceIdentity identity) { } @Test - public void isReplaceToken_handlesException(@Mocked final InstanceIdentity identity) { + public void isExternallyDefinedToken(@Mocked final InstanceIdentity identity) + { + new Expectations() { + { + priamServer.getId(); + result = identity; + identity.isExternallyDefinedToken(); + result = true; + } + }; + + Response response = resource.isExternallyDefinedToken(); + assertEquals(200, response.getStatus()); + assertEquals("true", response.getEntity()); + } + + @Test + public void isReplaceToken_handlesException(@Mocked final InstanceIdentity identity) + { new Expectations() { { priamServer.getId();