Search code examples
amazon-web-servicesamazon-ec2jcloudsbrooklyn

extend EC2HardwareBuilder class to set an other size for the boot volume as 10GB


I use Apache Brooklyn in combination with jCloud EC2 to create ec2 instances on AWS.

ec2 instance setting:

  • region: eu-central-1 (Frankfurt)
  • imageId: ami-10d1367f
    • Name: amzn-ami-minimal-hvm-2016.03.0.x86_64-s3
    • RootDeviceType: instance-store
    • VirtualizationType: hvm
  • hardwareId: d2x_large
    • vCPU: 4
    • Memory: 30,5 GB
    • Storage: 3x2000 GB

Everytime when I create a ec2 instance the root partition has only 10GB disc space. I found the problem in the jCloud [ECHardwareBuilder]:(https://github.com/jclouds/jclouds/blob/master/apis/ec2/src/main/java/org/jclouds/ec2/compute/domain/EC2HardwareBuilder.java#L731)

/**
 * @see InstanceType#D2_XLARGE
 */
public static EC2HardwareBuilder d2_xlarge() {
  return new EC2HardwareBuilder(InstanceType.D2_XLARGE).d2()
    .ram(31232)`enter code here`
    .processors(ImmutableList.of(new Processor(4.0, 3.5)))
    .volumes(ImmutableList.<Volume>of(
      new VolumeBuilder().type(LOCAL).size(10.0f).device("/dev/sda1").bootDevice(true).durable(false).build(),
      new VolumeBuilder().type(LOCAL).size(2000.0f).device("/dev/sdb").bootDevice(false).durable(false).build(),
      new VolumeBuilder().type(LOCAL).size(2000.0f).device("/dev/sdc").bootDevice(false).durable(false).build(),
      new VolumeBuilder().type(LOCAL).size(2000.0f).device("/dev/sdd").bootDevice(false).durable(false).build()))
    .is64Bit(true);
}

My questions are:

  1. Is it possible to create my own class which extends EC2HardwareBuilder, so that I can change the root volume size to 2000?
  2. How can inject this class to brooklyn, so that it will be used instead of the old EC2HardwareBuilder class?

Solution

  • The EC2HardwareBuilder.d2_xlarge method just represents the defaults for that instance type. It doesn't control what is actually provisioned.

    You can see this if you provision manually - under storage, it offers /dev/sdb, /dev/sdc, and /dev/sdd. If you try to edit this "storage" section, it only lets you choose the device of /dev/sd{b-m}. It doesn't let you choose /dev/sda1. When I deploy with the defaults, it actually gives me a 2G partition for /dev/xvda1:

    [ec2-user@ip-172-31-5-36 ~]$ df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 2.0G 686M 1.3G 36% / devtmpfs 15G 72K 15G 1% /dev tmpfs 15G 0 15G 0% /dev/shm

    When I deploy with Brooklyn using the blueprint below (with brooklyn master), it also gives me a 2G partition for /dev/xvda1:

    location: jclouds:aws-ec2:eu-central-1: hardwareId: d2.xlarge imageId: eu-central-1/ami-10d1367f services: - type: org.apache.brooklyn.entity.machine.MachineEntity

    Can you confirm that you are definitely getting 10G rather than 2G? I suspect that size is dependent on the AMI.

    From jclouds perspective, the problem is this information is not discoverable through the EC2 api, so was hard-coded within jclouds!

    We could add a jclouds feature enhancement for changing which of /dev/sd{b-m} is used (as can be done in the AWS web-console), but that wouldn't solve your problem.


    As described in http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device, the size limit for a "root device volume" of an Amazon Instance Store-Backed AMI is 10 GiB.

    To have a bigger root partition, you could:

    • use an EBS-Backed AMI
    • try to resize it on-the-fly (but that would actually be a move to a different partition, rather than just resizing to the right; for a discussion of this, see https://askubuntu.com/a/728141, which links to https://unix.stackexchange.com/a/227318)
    • work around it: what in / needs all the space? can you just mount /dev/sdb to an appropriate directory?

    I personally favour the "work around it" approach (assuming EBS-Backed is not right for you).


    For future reference, if you did want to override the behaviour of methods like EC2HardwareBuilder.d2_xlarge, then unfortunately you can't! These are static methods. You'd have to build a jar with your own version of that class (compiled against the right version of jclouds of course), and put it in $BROOKLYN_HOME./lib/patch/.

    Usually, jclouds is extremely good for allowing things to be overridden and customized by configuring things in guice (to change the dependencies that are injected), but unfortunately not here.

    If you did want to use guice, you might be able to bind a different implementation of the entire EC2HardwareSupplier (to thus avoid the static calls), but we'd need to be very careful that nothing else was making calls to these static methods as well.