package org.xmlsh.aws;
import java.io.IOException;
import java.util.List;
import javax.xml.stream.XMLStreamException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.xmlsh.aws.util.AWSEC2Command;
import org.xmlsh.core.CoreException;
import org.xmlsh.core.InvalidArgumentException;
import org.xmlsh.core.Options;
import org.xmlsh.core.UnexpectedException;
import org.xmlsh.core.XValue;
import org.xmlsh.util.Util;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.ec2.model.CreateVolumeRequest;
import com.amazonaws.services.ec2.model.CreateVolumeResult;
import com.amazonaws.services.ec2.model.VolumeType;
import net.sf.saxon.s9api.SaxonApiException;
public class ec2CreateVolume extends AWSEC2Command {
private static Logger mLogger = LogManager.getLogger();
/**
* @param args
* @throws IOException
*/
@Override
public int run(List<XValue> args) throws Exception {
Options opts = getOptions(
"t=type:,s=size:,zone=availability-zone:,iops:,snapshot=snapshot-id:,spec=volspec:,+encrypted");
parseOptions(opts, args);
args = opts.getRemainingArgs();
setSerializeOpts(this.getSerializeOpts(opts));
rateRetry = opts.getOptInt("rate-retry", 0);
try {
getEC2Client(opts);
} catch (UnexpectedException e) {
usage(e.getLocalizedMessage());
return 1;
}
int ret = create(opts);
return ret;
}
private int create(Options opts) throws IOException, XMLStreamException,
SaxonApiException, InterruptedException, CoreException {
CreateVolumeRequest request = new CreateVolumeRequest()
.withAvailabilityZone(opts.getOptStringRequired("zone"))
.withVolumeType(VolumeType.Gp2); // Default to GP2
/**
* The volume type. This can be <code>gp2</code> for General Purpose
* (SSD) volumes, <code>io1</code> for Provisioned IOPS (SSD) volumes, or
* <code>standard</code> for Magnetic volumes.
* <p>
* Default:
* <code>standard</code>
* <p>
* <b>Constraints:</b><br/>
* <b>Allowed Values: </b>standard, io1, gp2
*/
if(opts.hasOpt("spec"))
parseVolumeSpec(opts.getOptStringRequired("spec"), request);
// Overrides
if(opts.hasOpt("type"))
request.setVolumeType(opts.getOptStringRequired("type"));
if(opts.hasOpt("size"))
request.setSize(opts.getOptInt("size", 10));
if(opts.hasOpt("snapshot"))
request.setSnapshotId(opts.getOptStringRequired("snapshot"));
if(opts.hasOpt("iops"))
request.setIops(opts.getOptInt("iops", 100));
if(opts.hasOpt("encrypted"))
request.setEncrypted(opts.getOptFlag("encrypted", false));
traceCall("createVolume");
CreateVolumeResult result = null;
int retry = rateRetry;
int delay = retryDelay;
do {
try {
result = getAWSClient().createVolume(request);
break;
} catch (AmazonServiceException e) {
mShell.printErr("AmazonServiceException", e);
if(retry > 0
&& Util.isEqual("RequestLimitExceeded", e.getErrorCode())) {
mShell.printErr("AWS RequestLimitExceeded - sleeping " + delay);
Thread.sleep(delay);
retry--;
delay *= 2;
}
else
throw e;
}
} while(retry > 0);
writeResult(result);
return 0;
}
// [snapshot-id]:[volume-size]:[delete-on-termination]:[volume-type[:iops]]:[encrypted
private void parseVolumeSpec(String spec,
CreateVolumeRequest request) throws InvalidArgumentException {
// Parse out the EBS stuff
// [snapshot-id]:[volume-size]:[volume-type[:iops]]:[encrypted]
String aebs[] = spec.split(":");
// [snapshot-id]:
if(aebs.length >= 1) {
String snapshotId = aebs[0];
if(!Util.isBlank(snapshotId))
request.setSnapshotId(snapshotId);
}
// :[volume-size]:
if(aebs.length >= 2) {
if(!Util.isBlank(aebs[1]))
request.setSize(new Integer(aebs[1]));
}
// [delete-on-termination] ignored for create-volume but keep placeholder
if(aebs.length >= 3) {
if(!Util.isBlank(aebs[2]))
printErr(
"delete-on-termination flag ignored for dynamicly created volumes");
// ebs.setDeleteOnTermination( Boolean.valueOf(
// Util.parseBoolean(aebs[2])));
}
if(aebs.length >= 4) {
// [volume-type[:iops]]:[encrypted]
int i = 3;
if(!Util.isBlank(aebs[i])) {
request.setVolumeType(aebs[i]);
if(aebs[i].equals(VolumeType.Io1.toString())) {
i++;
if(aebs.length <= i || Util.isBlank(aebs[i]))
throw new InvalidArgumentException(
"EBS block mapping with VolumeType io1 MUST have PIOPS");
request.setIops(Integer.valueOf(aebs[i]));
}
i++;
if(aebs.length > i && !Util.isBlank(aebs[i]))
request.setEncrypted(Util.parseBoolean(aebs[i]));
}
}
}
private void writeResult(CreateVolumeResult result)
throws IOException, XMLStreamException, SaxonApiException, CoreException {
startResult();
writeVolume(result.getVolume());
endResult();
}
}