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(); } }