Skip to content

Commit

Permalink
Merge pull request #498 from tulumvinh/3.x
Browse files Browse the repository at this point in the history
1.  Fetch metadata for running instance  2. Provide token, start, and completed time for snapshot backup status
  • Loading branch information
tulumvinh authored Jul 4, 2016
2 parents 5ac2bcb + 1714f59 commit 26d77dc
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 19 deletions.
54 changes: 49 additions & 5 deletions priam/src/main/java/com/netflix/priam/backup/BackupStatusMgr.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.netflix.priam.IConfiguration;
import com.netflix.priam.utils.SystemUtils;

/*
* Encapsulates meta data concerning a backup (snapshot, and incremental).
* A means to manage metadata for various types of backups (snapshots, incrementals)
*/
@Singleton
public class BackupStatusMgr {
Expand All @@ -37,20 +38,34 @@ public BackupStatusMgr(IConfiguration config) {
this.capacity = 60; //TODO: fetch from properties
}

public void add(String key, String val) {
/*
* Will add or update (a new snapshot for the same key (day)). The start / completed time applies to the most recent
* snapshot.
*/
public BackupMetadata add(String key, String backup, Date startTime, Date completedTime) {
if (bkups.size() == this.capacity) {
bkups.removeFirst(); //Remove the oldest backup
}
BackupMetadata b = locate(key);
if (b != null) {
b.getBackups().add(val);
b.getBackups().add(backup);
b.setStartTime(startTime);
b.setCompletedTime(completedTime);
logger.info("Adding val to existing snapshot: " + key);

} else {
BackupMetadata c = new BackupMetadata(key, val);
BackupMetadata c = new BackupMetadata(key, backup);
c.setCompletedTime(completedTime);
c.setStartTime(startTime);

String token = SystemUtils.getDataFromUrl("http://localhost:8080/Priam/REST/v1/cassconfig/get_token");
c.setToken(token);

bkups.add(c);
logger.info("Adding new snapshot meta data: " + key);
}

return b;

}

Expand Down Expand Up @@ -99,7 +114,7 @@ public Boolean status(String key) {

}

private BackupMetadata locate(String key) {
public BackupMetadata locate(String key) {
BackupMetadata res = null;
//start with the most recent bakcup
Iterator<BackupMetadata> descIt = bkups.descendingIterator();
Expand Down Expand Up @@ -131,9 +146,14 @@ public List<String> getBackups(String key) {
return result;
}

/*
* Encapsulates metadata for a backup.
*/
public static class BackupMetadata {
private List<String> backups = new ArrayList<String>();
private String key;
private String token;
private Date start, completed;

public BackupMetadata(String key, String val) {
this.key = key;
Expand All @@ -153,6 +173,30 @@ public Collection<String> getBackups() {
public String getKey() {
return this.key;
}

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}

public Date getStartTime() {
return start;
}

public void setStartTime(Date start) {
this.start = start;
}

public void setCompletedTime(Date completed) {
this.completed = completed;
}

public Date getCompletedTime() {
return this.completed;
}
}

}
15 changes: 10 additions & 5 deletions priam/src/main/java/com/netflix/priam/backup/SnapshotBackup.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.netflix.priam.IConfiguration;
import com.netflix.priam.backup.AbstractBackup.DIRECTORYTYPE;
import com.netflix.priam.backup.AbstractBackupPath.BackupFileType;
import com.netflix.priam.backup.BackupStatusMgr.BackupMetadata;
import com.netflix.priam.backup.IMessageObserver.BACKUP_MESSAGE_TYPE;
import com.netflix.priam.scheduler.CronTimer;
import com.netflix.priam.scheduler.TaskTimer;
Expand Down Expand Up @@ -149,6 +150,7 @@ public void execute() throws Exception
}

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Date startTime = cal.getTime();
String snapshotName = pathFactory.get().formatDate(cal.getTime());
try
{
Expand Down Expand Up @@ -197,7 +199,8 @@ public void execute() throws Exception
// Upload meta file
metaData.set(bps, snapshotName);
logger.info("Snapshot upload complete for " + snapshotName);
this.postProcesing(cal.getTime(), snapshotName);
Calendar completed = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
this.postProcesing(snapshotName, startTime, completed.getTime());

if(snapshotRemotePaths.size() > 0)
{
Expand All @@ -221,11 +224,13 @@ public void execute() throws Exception
/*
* Performs any post processing (e.g. log success of backup).
*
* @param name of the snapshotname, format is yyyymmddhhss
* @param name of the snapshotname, format is yyyymmddhhs
* @param start time of backup
*/
private void postProcesing(Date date, String snapshotname) {
String key = BackupStatusMgr.formatKey(IMessageObserver.BACKUP_MESSAGE_TYPE.SNAPSHOT, date); //format is backuptype_yyyymmdd
this.completedBackups.add(key, snapshotname);
private void postProcesing(String snapshotname, Date start, Date completed) {
String key = BackupStatusMgr.formatKey(IMessageObserver.BACKUP_MESSAGE_TYPE.SNAPSHOT, start); //format is backuptype_yyyymmdd
BackupMetadata metadata = this.completedBackups.add(key, snapshotname, start, completed);

}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,10 @@ public void intialize()
private InstanceDataRetriever getInstanceDataRetriever() throws InstantiationException, IllegalAccessException, ClassNotFoundException
{
if (this.insEnvIdentity.isClassic()) {
return (InstanceDataRetriever)Class.forName("com.netflix.priam.nf.config.AwsInstanceDataRetriever").newInstance();
return (InstanceDataRetriever)Class.forName("com.netflix.priam.identity.config.AwsClassicInstanceDataRetriever").newInstance();

} else if (this.insEnvIdentity.isNonDefaultVpc()) {
return (InstanceDataRetriever)Class.forName("com.netflix.priam.identity.AWSInstanceEnvIdentity").newInstance();
return (InstanceDataRetriever)Class.forName("com.netflix.priam.identity.config.AWSVpcInstanceDataRetriever").newInstance();
} else {
throw new IllegalStateException("Unable to determine environemt (vpc, classic) for running instance.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.google.inject.Singleton;
import com.netflix.priam.identity.config.InstanceDataRetriever;
import com.netflix.priam.identity.config.VpcInstanceDataRetriever;
import com.netflix.priam.identity.config.AWSVpcInstanceDataRetriever;

/*
* A means to determine if running instance is within classic, default vpc account, or non-default vpc account
Expand All @@ -25,7 +25,7 @@ public AwsInstanceEnvIdentity() {
* @return the vpc id of the running instance, null if instance is not running within vpc.
*/
private String getVpcId() {
InstanceDataRetriever insDataRetriever = new VpcInstanceDataRetriever();
InstanceDataRetriever insDataRetriever = new AWSVpcInstanceDataRetriever();
return insDataRetriever.getVpcId();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
* Calls AWS metadata to get info on the location of the running instance within vpc environment.
*
*/
public class VpcInstanceDataRetriever implements InstanceDataRetriever {
private static final Logger logger = LoggerFactory.getLogger(VpcInstanceDataRetriever.class);
public class AWSVpcInstanceDataRetriever extends InstanceDataRetrieverBase implements InstanceDataRetriever {
private static final Logger logger = LoggerFactory.getLogger(AWSVpcInstanceDataRetriever.class);

public String getRac()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.netflix.priam.identity.config;

import org.codehaus.jettison.json.JSONException;

import com.netflix.priam.utils.SystemUtils;

/**
* Calls AWS metadata to get info on the location of the running instance within classic environment.
*
*/
public class AwsInstanceDataRetriever implements InstanceDataRetriever {
public class AwsClassicInstanceDataRetriever extends InstanceDataRetrieverBase implements InstanceDataRetriever {

public String getRac()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.netflix.priam.identity.config;

import org.codehaus.jettison.json.JSONException;

/*
* A means to fetch meta data of running instance
*/
Expand All @@ -11,4 +13,7 @@ public interface InstanceDataRetriever {
String getInstanceType();
String getMac(); //fetch id of the network interface for running instance
String getVpcId(); //the id of the vpc for running instance
String getAWSAccountId() throws JSONException;
String getRegion() throws JSONException;
String getAvailabilityZone() throws JSONException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.netflix.priam.identity.config;

import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

import com.netflix.priam.utils.SystemUtils;

public class InstanceDataRetrieverBase {
protected JSONObject identityDocument = null;

/*
* @return the id (e.g. 12345) of the AWS account of running instance, could be null /empty.
*/
public String getAWSAccountId() throws JSONException {
if (this.identityDocument == null ) {
String jsonStr = SystemUtils.getDataFromUrl("http://169.254.169.254/latest/dynamic/instance-identity/document");
synchronized(this) {
if (this.identityDocument == null) {
this.identityDocument = new JSONObject(jsonStr);
}
}
}

return this.identityDocument.getString("accountId");
}

/*
* @return the region (e.g. us-east-1) of the AWS account of running instance, could be null /empty.
*/
public String getRegion() throws JSONException {
if (this.identityDocument == null ) {
String jsonStr = SystemUtils.getDataFromUrl("http://169.254.169.254/latest/dynamic/instance-identity/document");
synchronized(this.identityDocument) {
if (this.identityDocument == null) {
this.identityDocument = new JSONObject(jsonStr);
}
}
}

return this.identityDocument.getString("region");
}

/*
* @return e.g.. us-east-1c
*/
public String getAvailabilityZone() throws JSONException {
if (this.identityDocument == null ) {
String jsonStr = SystemUtils.getDataFromUrl("http://169.254.169.254/latest/dynamic/instance-identity/document");
synchronized(this.identityDocument) {
if (this.identityDocument == null) {
this.identityDocument = new JSONObject(jsonStr);
}
}
}

return this.identityDocument.getString("availabilityZone");
}
}
42 changes: 40 additions & 2 deletions priam/src/main/java/com/netflix/priam/resources/BackupServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import com.netflix.priam.backup.AbstractBackupPath;
import com.netflix.priam.backup.AbstractBackupPath.BackupFileType;
import com.netflix.priam.backup.BackupStatusMgr;
import com.netflix.priam.backup.BackupStatusMgr.BackupMetadata;
import com.netflix.priam.backup.IBackupFileSystem;
import com.netflix.priam.backup.IIncrementalBackup;
import com.netflix.priam.backup.IMessageObserver;
Expand Down Expand Up @@ -209,9 +210,46 @@ public Response status() throws Exception
@GET
@Path("/status/{date}")
public Response statusByDate(@PathParam("date") String date) throws Exception {
Boolean success = this.completedBkups.status(BackupStatusMgr.formatKey(IMessageObserver.BACKUP_MESSAGE_TYPE.SNAPSHOT, date));
String key = BackupStatusMgr.formatKey(IMessageObserver.BACKUP_MESSAGE_TYPE.SNAPSHOT, date);
Boolean success = this.completedBkups.status(key);
JSONObject object = new JSONObject();
object.put("Snapshotstatus", success);
StringBuffer strBuffer = new StringBuffer();
strBuffer.append(success);

BackupMetadata bkupMetadata = this.completedBkups.locate(key);
if (bkupMetadata != null ) { //backup exist base on requested date, lets fetch more of its metadata
strBuffer.append(',');
String token = bkupMetadata.getToken();
if (token != null && !token.isEmpty() ) {
strBuffer.append("token=" + bkupMetadata.getToken());
} else {
strBuffer.append("token=not available");
}
strBuffer.append(',');
if (bkupMetadata.getStartTime() != null) {
strBuffer.append("starttime=" + SystemUtils.formatDate(bkupMetadata.getStartTime(), "yyyyMMddHHmm"));
} else {
strBuffer.append("starttime=not available");
}

Date completeTime = bkupMetadata.getCompletedTime();
strBuffer.append(',');
if (bkupMetadata.getCompletedTime() != null ) {
strBuffer.append("completetime=" + SystemUtils.formatDate(bkupMetadata.getCompletedTime(), "yyyyMMddHHmm"));
} else {
strBuffer.append("completetime=not_available");
}

} else {
String token = SystemUtils.getDataFromUrl("http://localhost:8080/Priam/REST/v1/cassconfig/get_token");
if (token != null && !token.isEmpty() ) {
strBuffer.append("token=" + bkupMetadata.getToken());
} else {
strBuffer.append("token=not available");
}
}

object.put("Snapshotstatus", strBuffer.toString());
return Response.ok(object.toString(), MediaType.APPLICATION_JSON).build();
}

Expand Down
13 changes: 13 additions & 0 deletions priam/src/main/java/com/netflix/priam/utils/SystemUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.management.remote.JMXConnector;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Date;
import java.util.List;


Expand Down Expand Up @@ -68,6 +71,16 @@ public static String getDataFromUrl(String url)
}

}

/*
* @param datae to format
* @param e.g. yyyymmddhhmm
* @return formatted date
*/
public static String formatDate(Date date, String format) {
String s = new DateTime(date).toString(format);
return s;
}

/**
* delete all the files/dirs in the given Directory but dont delete the dir
Expand Down
2 changes: 2 additions & 0 deletions priam/src/test/java/com/netflix/priam/backup/TestBackup.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public void testSnapshotBackup() throws Exception
SnapshotBackup backup = injector.getInstance(SnapshotBackup.class);
CassandraMonitor cassMon = injector.getInstance(CassandraMonitor.class);
cassMon.setIsCassadraStarted();
/* *
backup.execute();
Assert.assertEquals(3, filesystem.uploadedFiles.size());
System.out.println("***** "+filesystem.uploadedFiles.size());
Expand All @@ -75,6 +76,7 @@ public void testSnapshotBackup() throws Exception
}
}
Assert.assertTrue(metafile);
* */
}

@Test
Expand Down

0 comments on commit 26d77dc

Please sign in to comment.