Skip to content

Commit

Permalink
Allow EBS volumes to be created from snapshots
Browse files Browse the repository at this point in the history
Note that you can also specify a size for the new volume, allowing the
disk to be resized.
  • Loading branch information
edolstra committed Dec 20, 2013
1 parent 2e4a522 commit 6fa395f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
25 changes: 23 additions & 2 deletions nix/ebs-volume.nix
Expand Up @@ -36,11 +36,32 @@ with pkgs.lib;
size = mkOption {
example = 100;
type = types.int;
description = "Volume size (in gigabytes).";
description = ''
Volume size (in gigabytes). This may be left unset if you are
creating the volume from a snapshot, in which case the size of
the volume will be equal to the size of the snapshot.
However, you can set a size larger than the snapshot, allowing
the volume to be larger than the snapshot from which it is
created.
'';
};

snapshot = mkOption {
default = "";
example = "snap-1cbda474";
type = types.str;
description = ''
The snapshot ID from which this volume will be created. If
not specified, an empty volume is created. Changing the
snapshot ID has no effect if the volume already exists.
'';
};

};

config._type = "ebs-volume";
config = {
_type = "ebs-volume";
size = mkIf (config.snapshot != "") (mkDefault 0);
};

}
20 changes: 15 additions & 5 deletions nixops/resources/ebs_volume.py
Expand Up @@ -22,7 +22,8 @@ def __init__(self, xml):
self.region = xml.find("attrs/attr[@name='region']/string").get("value")
self.zone = xml.find("attrs/attr[@name='zone']/string").get("value")
self.access_key_id = xml.find("attrs/attr[@name='accessKeyId']/string").get("value")
self.size = xml.find("attrs/attr[@name='size']/int").get("value")
self.size = int(xml.find("attrs/attr[@name='size']/int").get("value"))
self.snapshot = xml.find("attrs/attr[@name='snapshot']/string").get("value")

def show_type(self):
return "{0} [{1}]".format(self.get_type(), self.region)
Expand All @@ -36,7 +37,7 @@ class EBSVolumeState(nixops.resources.ResourceState):
region = nixops.util.attr_property("ec2.region", None)
zone = nixops.util.attr_property("ec2.zone", None)
volume_id = nixops.util.attr_property("ec2.volumeId", None)
size = nixops.util.attr_property("ec2.size", None)
size = nixops.util.attr_property("ec2.size", None, int)


@classmethod
Expand Down Expand Up @@ -74,15 +75,24 @@ def create(self, defn, check, allow_reboot, allow_recreate):
if self.state == self.UP and (self.region != defn.region or self.zone != defn.zone):
raise Exception("changing the region or availability zone of an EBS volume is not supported")

if self.state == self.UP and (self.size != defn.size):
if self.state == self.UP and (defn.size != 0 and self.size != defn.size):
raise Exception("changing the size an EBS volume is currently not supported")

if self.state != self.UP:

self.connect(defn.region)

self.log("creating EBS volume of {0} GiB...".format(defn.size))
volume = self._conn.create_volume(size=defn.size, zone=defn.zone)
if defn.size == 0 and defn.snapshot != "":
snapshots = self._conn.get_all_snapshots(snapshot_ids=[defn.snapshot])
assert len(snapshots) == 1
defn.size = snapshots[0].volume_size

if defn.snapshot:
self.log("creating EBS volume of {0} GiB from snapshot ‘{1}’...".format(defn.size, defn.snapshot))
else:
self.log("creating EBS volume of {0} GiB...".format(defn.size))

volume = self._conn.create_volume(zone=defn.zone, size=defn.size, snapshot=defn.snapshot)

# FIXME: if we crash before the next step, we forget the
# volume we just created. Doesn't seem to be anything we
Expand Down

0 comments on commit 6fa395f

Please sign in to comment.