mirror of https://github.com/apache/jclouds.git
Issue 226: use jclouds-native objects (mostly) where ever
possible, including adding a single-step create-and-attach option for create-volume
This commit is contained in:
parent
da9847ab7f
commit
e1a5f58bd4
|
@ -23,7 +23,8 @@
|
||||||
(:require (org.jclouds [compute :as compute]))
|
(:require (org.jclouds [compute :as compute]))
|
||||||
(:use (clojure.contrib def core))
|
(:use (clojure.contrib def core))
|
||||||
(:import org.jclouds.aws.domain.Region
|
(:import org.jclouds.aws.domain.Region
|
||||||
org.jclouds.aws.ec2.domain.AvailabilityZone
|
org.jclouds.compute.domain.NodeMetadata
|
||||||
|
(org.jclouds.aws.ec2.domain Volume Snapshot AvailabilityZone)
|
||||||
(org.jclouds.aws.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
|
(org.jclouds.aws.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
|
||||||
|
|
||||||
(defn #^org.jclouds.aws.ec2.services.ElasticBlockStoreClient
|
(defn #^org.jclouds.aws.ec2.services.ElasticBlockStoreClient
|
||||||
|
@ -34,7 +35,7 @@
|
||||||
(-> (or compute compute/*compute*)
|
(-> (or compute compute/*compute*)
|
||||||
.getContext .getProviderSpecificContext .getApi .getElasticBlockStoreServices))
|
.getContext .getProviderSpecificContext .getApi .getElasticBlockStoreServices))
|
||||||
|
|
||||||
(defn as-region
|
(defn get-region
|
||||||
"Returns the first argument as the corresponding Region if it is a
|
"Returns the first argument as the corresponding Region if it is a
|
||||||
keyword or already a Region instance. An optional second argument
|
keyword or already a Region instance. An optional second argument
|
||||||
is returned if the first cannot be coerced into a Region.
|
is returned if the first cannot be coerced into a Region.
|
||||||
|
@ -43,8 +44,23 @@
|
||||||
(cond
|
(cond
|
||||||
(keyword? v) (Region/fromValue (name v))
|
(keyword? v) (Region/fromValue (name v))
|
||||||
(instance? Region v) v
|
(instance? Region v) v
|
||||||
|
(instance? NodeMetadata v) (let [zone (.getLocationId v)]
|
||||||
|
; no easier way to go from zone -> region?
|
||||||
|
(Region/fromValue (if (> (.indexOf zone "-") -1)
|
||||||
|
(subs zone 0 (-> zone count dec))
|
||||||
|
zone)))
|
||||||
:else default-region))
|
:else default-region))
|
||||||
|
|
||||||
|
(defn get-volume-id
|
||||||
|
"Returns a string volume ID taken from the given string, keyword, or Volume argument."
|
||||||
|
[v]
|
||||||
|
(cond
|
||||||
|
(instance? Volume v) (.getId #^Volume v)
|
||||||
|
(keyword? v) (name v)
|
||||||
|
(string? v) v
|
||||||
|
:else (throw (IllegalArgumentException.
|
||||||
|
(str "Can't obtain volume id from argument of type " (class v))))))
|
||||||
|
|
||||||
(defn describe-volumes
|
(defn describe-volumes
|
||||||
"Returns a set of org.jclouds.aws.ec2.domain.Volume instances corresponding to the
|
"Returns a set of org.jclouds.aws.ec2.domain.Volume instances corresponding to the
|
||||||
volumes in the specified region (defaulting to your account's default region).
|
volumes in the specified region (defaulting to your account's default region).
|
||||||
|
@ -54,51 +70,46 @@
|
||||||
[& [region & volume-ids]]
|
[& [region & volume-ids]]
|
||||||
(set
|
(set
|
||||||
(.describeVolumesInRegion (ebs-services)
|
(.describeVolumesInRegion (ebs-services)
|
||||||
(as-region region Region/DEFAULT)
|
(get-region region Region/DEFAULT)
|
||||||
(into-array String (if (as-region region)
|
(into-array String (map get-volume-id
|
||||||
volume-ids
|
(if (get-region region)
|
||||||
(cons region volume-ids))))))
|
volume-ids
|
||||||
|
(when region (cons region volume-ids))))))))
|
||||||
(defvar- snapshot-options-ops
|
|
||||||
{:ids #(.snapshotIds % (into-array %2))
|
|
||||||
:owners #(.ownedBy % (into-array %2))
|
|
||||||
:restorable-by #(.restorableBy % (into-array %2))})
|
|
||||||
|
|
||||||
(defn- snapshot-options
|
(defn- snapshot-options
|
||||||
[options-seq]
|
[optmap]
|
||||||
(let [optmap (apply hash-map options-seq)
|
(let [string-array #(let [v (% optmap)]
|
||||||
string-array #(let [v (% optmap)]
|
(into-array String (cond
|
||||||
(into-array String (if (string? v) [v] v)))]
|
(keyword? v) [(name v)]
|
||||||
|
(string? v) [v]
|
||||||
|
:else (map as-string v))))]
|
||||||
(-> (DescribeSnapshotsOptions.)
|
(-> (DescribeSnapshotsOptions.)
|
||||||
(.ownedBy (string-array :owner))
|
(.ownedBy (string-array :owner))
|
||||||
(.snapshotIds (string-array :ids))
|
(.snapshotIds (string-array :ids))
|
||||||
(.restorableBy (string-array :restorable-by)))))
|
(.restorableBy (string-array :restorable-by)))))
|
||||||
|
|
||||||
(defn describe-snapshots
|
(defn describe-snapshots
|
||||||
"Returns a set of org.jclouds.aws.ec2.domain.Snapshot instances corresponding to the
|
"Returns a set of org.jclouds.aws.ec2.domain.Snapshot instances that match
|
||||||
snapshots in the specified region (defaulting to your account's default region)
|
the criteria provided. Options include:
|
||||||
limited according to the further options provided.
|
|
||||||
|
|
||||||
This returns all of the snapshots you own (you can also provide \"amazon\" or an AWS
|
:region - region string or keyword
|
||||||
account ID here):
|
:owner - AWS account id (or \"amazon\" or \"self\")
|
||||||
(with-compute-service [compute]
|
:restorable-by - AWS account id
|
||||||
(describe-snapshots [:owner \"self\"]))
|
|
||||||
|
|
||||||
This returns metadata on the two specified snapshots in us-west-1 (assuming you have access to them):
|
Multiple values for each type of criteria can be provided by passing a seq
|
||||||
(with-compute-service [compute]
|
of the appropriate types as values.
|
||||||
(describe-snapshots :us-west-1 [:ids [\"snap-44b3ab2d\" \"snap-9e8821f7\"]]))
|
|
||||||
|
|
||||||
There is also a :restorable-by option. Option values can be provided as strings, or
|
(with-compute-service [compute]
|
||||||
collections of strings."
|
(describe-snapshots :owner \"self\")
|
||||||
[& [region & option-keyvals]]
|
(describe-snapshots :region :us-west-1 :ids [\"snap-44b3ab2d\" \"snap-9e8821f7\"]))"
|
||||||
(let [options (apply snapshot-options
|
[& options]
|
||||||
(if (as-region region)
|
(let [options (apply hash-map options)
|
||||||
option-keyvals
|
region (:region options)
|
||||||
(cons region option-keyvals)))]
|
options (snapshot-options (dissoc options :region))]
|
||||||
(set
|
(set
|
||||||
(.describeSnapshotsInRegion (ebs-services)
|
(.describeSnapshotsInRegion (ebs-services)
|
||||||
(as-region region Region/DEFAULT)
|
(get-region region Region/DEFAULT)
|
||||||
(into-array DescribeSnapshotsOptions [options])))))
|
(into-array DescribeSnapshotsOptions [options])))))
|
||||||
|
|
||||||
(defn- as-string
|
(defn- as-string
|
||||||
[v]
|
[v]
|
||||||
|
@ -123,14 +134,17 @@
|
||||||
org.jclouds.aws.ec2.domain.Snapshot object representing the created snapshot.
|
org.jclouds.aws.ec2.domain.Snapshot object representing the created snapshot.
|
||||||
|
|
||||||
e.g. (with-compute-service [compute]
|
e.g. (with-compute-service [compute]
|
||||||
(create-snapshot :us-east-1 \"vol-1dbe6785\")
|
(create-snapshot some-volume-instance)
|
||||||
|
(create-snapshot :us-east-1 \"vol-1dbe6785\" nil)
|
||||||
(create-snapshot :us-east-1 \"vol-1dbe6785\" \"super-important data\"))"
|
(create-snapshot :us-east-1 \"vol-1dbe6785\" \"super-important data\"))"
|
||||||
[region volume-id & [description]]
|
([#^Volume volume] (create-snapshot volume nil))
|
||||||
(.createSnapshotInRegion (ebs-services)
|
([#^Volume volume description] (create-snapshot (.getRegion volume) (.getId volume) description))
|
||||||
(as-region region)
|
([region volume-id description]
|
||||||
(as-string volume-id)
|
(.createSnapshotInRegion (ebs-services)
|
||||||
(into-array CreateSnapshotOptions (when description
|
(get-region region)
|
||||||
[(.withDescription (CreateSnapshotOptions.) description)]))))
|
(as-string volume-id)
|
||||||
|
(into-array CreateSnapshotOptions (when description
|
||||||
|
[(.withDescription (CreateSnapshotOptions.) description)])))))
|
||||||
|
|
||||||
(defn delete-snapshot
|
(defn delete-snapshot
|
||||||
"Deletes a snapshot in the specified region.
|
"Deletes a snapshot in the specified region.
|
||||||
|
@ -138,19 +152,83 @@
|
||||||
e.g. (with-compute-service [compute]
|
e.g. (with-compute-service [compute]
|
||||||
(delete-snapshot :us-east-1 :snap-252310af)
|
(delete-snapshot :us-east-1 :snap-252310af)
|
||||||
(delete-snapshot :us-east-1 \"snap-242adf03\"))"
|
(delete-snapshot :us-east-1 \"snap-242adf03\"))"
|
||||||
[region snapshot-id]
|
([#^Snapshot snapshot] (delete-snapshot (.getRegion snapshot) (.getId snapshot)))
|
||||||
|
([region snapshot-id]
|
||||||
(.deleteSnapshotInRegion (ebs-services)
|
(.deleteSnapshotInRegion (ebs-services)
|
||||||
(as-region region)
|
(get-region region)
|
||||||
(as-string snapshot-id)))
|
(as-string snapshot-id))))
|
||||||
|
|
||||||
|
(defn get-zone
|
||||||
|
[v]
|
||||||
|
(cond
|
||||||
|
(instance? AvailabilityZone v) v
|
||||||
|
(instance? NodeMetadata v) (AvailabilityZone/fromValue (.getLocationId #^NodeMetadata v))
|
||||||
|
(string? v) (AvailabilityZone/fromValue v)
|
||||||
|
(keyword? v) (AvailabilityZone/fromValue (name v))
|
||||||
|
:else (throw (IllegalArgumentException.
|
||||||
|
(str "Can't obtain zone from argument of type " (class v))))))
|
||||||
|
|
||||||
|
(defn attach-volume
|
||||||
|
"Attaches a volume to an instance, returning the resulting org.jclouds.aws.ec2.domain.Attachment.
|
||||||
|
|
||||||
|
e.g. (with-compute-service [compute]
|
||||||
|
(attach-volume :us-east-1 \"i-a92358c1\" :vol-45228a6d \"/dev/sdh\")
|
||||||
|
(attach-volume some-node-instance :vol-45228a6d \"/dev/sdh\")
|
||||||
|
(attach-volume some-node-instance some-volume-instance \"/dev/sdh\"))"
|
||||||
|
([#^NodeMetadata node volume device]
|
||||||
|
(attach-volume node (.getId node) (get-volume-id volume) device))
|
||||||
|
([region instance-id volume-id device]
|
||||||
|
(apply #(.attachVolumeInRegion (ebs-services)
|
||||||
|
(get-region region) % %2 %3)
|
||||||
|
(map as-string [volume-id instance-id device]))))
|
||||||
|
|
||||||
|
(defn detach-volume
|
||||||
|
"Detatches a volume from the instance to which it is currently attached.
|
||||||
|
The volume may be specified with a Volume instance, a string, or a keyword.
|
||||||
|
Providing a logical true value for the :force option will cause the volume
|
||||||
|
to be forcibly detached, regardless of whether it is in-use (mounted) or not.
|
||||||
|
|
||||||
|
If the volume is specified as a string or keyword, one of the following options
|
||||||
|
is additionally required:
|
||||||
|
|
||||||
|
:region - the region where the volume is allocated
|
||||||
|
:node - a node in the region where the volume is allocated
|
||||||
|
|
||||||
|
FYI: It appears that issuing a detatch-volume command while the volume in question is mounted
|
||||||
|
will cause the volume to be detatched immediately upon the volume beign unmounted."
|
||||||
|
[volume & options]
|
||||||
|
(let [options (apply hash-map options)
|
||||||
|
volume-id (get-volume-id volume)
|
||||||
|
region (get-region (if (instance? Volume volume)
|
||||||
|
(.getRegion volume)
|
||||||
|
(or (:region options) (:node options))))]
|
||||||
|
(when (not region)
|
||||||
|
(throw (IllegalArgumentException.
|
||||||
|
"Must specify volume's region via :region or :node options, or by providing a Volume instance.")))
|
||||||
|
(.detachVolumeInRegion (ebs-services)
|
||||||
|
region
|
||||||
|
volume-id
|
||||||
|
(boolean (:force options))
|
||||||
|
(into-array DetachVolumeOptions []))))
|
||||||
|
|
||||||
(defn create-volume
|
(defn create-volume
|
||||||
"Creates a new volume given a set of options. :zone is required, one
|
"Creates a new volume given a set of options:
|
||||||
or both of :size and :snapshot may also be provided; all values can be strings or keywords,
|
|
||||||
:size may be a number, and :zone may be a org.jclouds.aws.ec2.domain.AvailabilityZone.
|
- one of :zone (keyword, string, or AvailabilityZone) or :node (NodeMetadata)
|
||||||
Returns the created org.jclouds.aws.ec2.domain.Volume.
|
- one or both of :snapshot (keyword or string) or :size (string, keyword, or number)
|
||||||
|
- only if also attaching the new volume: :attach (logical boolean) and :device (string or keyword)
|
||||||
|
|
||||||
|
Returns a vector of [created org.jclouds.aws.ec2.domain.Volume,
|
||||||
|
optional org.jclouds.aws.ec2.domain.Attachment]
|
||||||
|
|
||||||
|
Note that specifying :node instead of :zone will only attach the created volume
|
||||||
|
if :attach is logically true, and :device is provided. Otherwise, the node is only
|
||||||
|
used to obtain the desired availability zone.
|
||||||
|
|
||||||
e.g. (with-compute-service [compute]
|
e.g. (with-compute-service [compute]
|
||||||
(create-volume :zone :us-east-1a :size 250)
|
(create-volume :zone :us-east-1a :size 250)
|
||||||
|
(create-volume :node node-instance :size 250)
|
||||||
|
(create-volume :node node-instance :size 250 :attach true :device \"/dev/sdj\")
|
||||||
(create-volume :zone :eu-west-1b :snapshot \"snap-252310af\")
|
(create-volume :zone :eu-west-1b :snapshot \"snap-252310af\")
|
||||||
(create-volume :zone :eu-west-1b :snapshot \"snap-252310af\" :size :1024))"
|
(create-volume :zone :eu-west-1b :snapshot \"snap-252310af\" :size :1024))"
|
||||||
[& options]
|
[& options]
|
||||||
|
@ -159,18 +237,21 @@
|
||||||
(let [options (apply hash-map options)
|
(let [options (apply hash-map options)
|
||||||
snapshot (get-string options :snapshot)
|
snapshot (get-string options :snapshot)
|
||||||
size (-?> (get-string options :size) as-int)
|
size (-?> (get-string options :size) as-int)
|
||||||
zone (get-string options :zone)
|
#^NodeMetadata node (:node options)
|
||||||
|
zone (or node (get-string options :zone))
|
||||||
zone (if zone
|
zone (if zone
|
||||||
(if (instance? AvailabilityZone zone)
|
(get-zone zone)
|
||||||
zone
|
(throw (IllegalArgumentException. "Must supply a :zone or :node option.")))
|
||||||
(AvailabilityZone/fromValue zone))
|
|
||||||
(throw (IllegalArgumentException. "Must supply a :zone option.")))
|
|
||||||
ebs (ebs-services)]
|
ebs (ebs-services)]
|
||||||
(cond
|
(when (and (:attach options) (or (not node) (not (:device options))))
|
||||||
(and snapshot size) (.createVolumeFromSnapshotInAvailabilityZone ebs zone size snapshot)
|
(throw (IllegalArgumentException. "Cannot create and attach new volume; no :node and/or :device specified")))
|
||||||
snapshot (.createVolumeFromSnapshotInAvailabilityZone ebs zone snapshot)
|
(let [new-volume (cond
|
||||||
size (.createVolumeInAvailabilityZone ebs zone size)
|
(and snapshot size) (.createVolumeFromSnapshotInAvailabilityZone ebs zone size snapshot)
|
||||||
:else (throw (IllegalArgumentException. "Must supply :size and/or :snapshot options.")))))
|
snapshot (.createVolumeFromSnapshotInAvailabilityZone ebs zone snapshot)
|
||||||
|
size (.createVolumeInAvailabilityZone ebs zone size)
|
||||||
|
:else (throw (IllegalArgumentException. "Must supply :size and/or :snapshot options.")))]
|
||||||
|
[new-volume (when (:attach options)
|
||||||
|
(attach-volume node new-volume (:device options)))])))
|
||||||
|
|
||||||
(defn delete-volume
|
(defn delete-volume
|
||||||
"Deletes a volume in the specified region.
|
"Deletes a volume in the specified region.
|
||||||
|
@ -178,33 +259,9 @@
|
||||||
e.g. (with-compute-service [compute]
|
e.g. (with-compute-service [compute]
|
||||||
(delete-volume :us-east-1 :vol-45228a6d)
|
(delete-volume :us-east-1 :vol-45228a6d)
|
||||||
(delete-volume :us-east-1 \"vol-052b846c\"))"
|
(delete-volume :us-east-1 \"vol-052b846c\"))"
|
||||||
[region volume-id]
|
([#^Volume volume]
|
||||||
(.deleteVolumeInRegion (ebs-services)
|
(delete-volume (.getRegion volume) (.getId volume)))
|
||||||
(as-region region)
|
([region volume-id]
|
||||||
(as-string volume-id)))
|
(.deleteVolumeInRegion (ebs-services)
|
||||||
|
(get-region region)
|
||||||
(defn attach-volume
|
(as-string volume-id))))
|
||||||
"Attaches a volume to an instance, returning the resulting org.jclouds.aws.ec2.domain.Attachment.
|
|
||||||
The region must be a keyword or Region instance; the remaining parameters may be
|
|
||||||
strings or keywords.
|
|
||||||
|
|
||||||
e.g. (with-compute-service [compute]
|
|
||||||
(attach-volume :us-east-1 :vol-45228a6d \"i-a92358c1\" \"/dev/sdh\"))"
|
|
||||||
[region & [volume-id instance-id device :as options]]
|
|
||||||
(apply #(.attachVolumeInRegion (ebs-services)
|
|
||||||
(as-region region) % %2 %3)
|
|
||||||
(map as-string options)))
|
|
||||||
|
|
||||||
(defn detach-volume
|
|
||||||
"Detatches a volume from the instance to which it is currently attached.
|
|
||||||
The optional force? parameter, if logically true, will cause the volume to be forcibly
|
|
||||||
detached, regardless of whether it is in-use (mounted) or not.
|
|
||||||
|
|
||||||
(It appears that issuing a detatch-volume command while the volume in question is mounted
|
|
||||||
will cause the volume to be detatched immediately upon the volume beign unmounted."
|
|
||||||
[region volume-id & [force?]]
|
|
||||||
(.detachVolumeInRegion (ebs-services)
|
|
||||||
(as-region region)
|
|
||||||
(as-string volume-id)
|
|
||||||
(boolean force?)
|
|
||||||
(into-array DetachVolumeOptions [])))
|
|
Loading…
Reference in New Issue