Merge branch 'master' of git@github.com:jclouds/jclouds

* 'master' of git@github.com:jclouds/jclouds:
  Cleaning up API for ebs2 and elastic-ip2 after review. Minor changes to doc-strings, code formatting and order of args in release fn.
  Issue 550: Global ATMOS refactoring for identity.
  Issue 550: Added ProviderMetadata for Ninefold Storage.
  Issue 550: Added ProviderMetadata for OpenHosting East1 provider.
  Issue 550: Addressed the verbiage used for credentials for the synaptic-storage provider.
  Issue 550: Cleaned up a few minor formatting nits and implemented linked services for Eucalyptus.
  Issue 550: Added ProviderMetadata for AT&T Synaptic Storage.
  cleanup and refine vmclientlivetest
  added test dependency
  added providermetadata test for savvis-symphonyvpdc
  cleanup tests, added ProviderMetadata implementation for savis-symphonyvpdc
  fixed firewallservice url
  cleanup
  fixed tests for savvis
  Fixed typo
  First version of elastic_ip2.clj
  First version of ebs2.clj
This commit is contained in:
Adrian Cole 2011-06-03 01:12:38 -07:00
commit 6a8f52e210
27 changed files with 1093 additions and 145 deletions

View File

@ -0,0 +1,289 @@
;
;
; Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
;
; ====================================================================
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
; ====================================================================
;
(ns
#^{:author "Chas Emerick, cemerick@snowtide.com"
:doc "A clojure binding to the jclouds EBS service interface."}
org.jclouds.ec2.ebs2
(:use [org.jclouds.compute2])
(:use (clojure.contrib def core))
(:import org.jclouds.aws.domain.Region
org.jclouds.compute.domain.NodeMetadata
(org.jclouds.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZoneInfo)
(org.jclouds.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
(defn snapshot?
"Returns true iff the argument is a org.jclouds.ec2.domain.Snapshot."
[s]
(instance? Snapshot s))
(defn volume?
"Returns true iff the argument is a org.jclouds.ec2.domain.Volume."
[v]
(instance? Volume v))
(defn ^org.jclouds.ec2.services.ElasticBlockStoreClient
ebs-service
""
[compute]
(-> compute
.getContext
.getProviderSpecificContext
.getApi
.getElasticBlockStoreServices))
(defn get-region
"Coerces the first parameter into a Region string; strings, keywords, and
NodeMetadata instances are acceptable arguments. An optional second argument
is returned if the first cannot be coerced into a region string.
Returns nil otherwise."
([v] (get-region v nil))
([v default-region]
(cond
(string? v) v
(keyword? v) (name v)
(instance? NodeMetadata v) (let [zone (location v)]
; no easier way to go from zone -> region?
(if (> (.indexOf zone "-") -1)
(subs zone 0 (-> zone count dec))
zone))
: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 volumes
"Returns a set of org.jclouds.ec2.domain.Volume instances corresponding to the
volumes in the specified region (defaulting to your account's default region)."
[compute & [region & volume-ids]]
(set
(.describeVolumesInRegion (ebs-service compute)
(get-region region)
(into-array String (map get-volume-id
(if (get-region region)
volume-ids
(when region (cons region volume-ids))))))))
(defn- as-string
[v]
(cond
(string? v) v
(keyword? v) (name v)
:else v))
(defn- get-string
[map key]
(as-string (get map key)))
(defn- as-int
[v]
(cond
(number? v) (int v)
(string? v) (Integer/parseInt v)
:else (throw (IllegalArgumentException.
(str "Don't know how to convert object of type " (class v) " to a string")))))
(defn- snapshot-options
[optmap]
(let [string-array #(let [v (% optmap)]
(into-array String (cond
(keyword? v) [(name v)]
(string? v) [v]
:else (map as-string v))))]
(-> (DescribeSnapshotsOptions.)
(.ownedBy (string-array :owner))
(.snapshotIds (string-array :ids))
(.restorableBy (string-array :restorable-by)))))
(defn snapshots
"Returns a set of org.jclouds.aws.ec2.domain.Snapshot instances that match
the criteria provided. Options include:
:region - region string, keyword, or NodeMetadata
:owner - AWS account id (or \"amazon\" or \"self\")
:restorable-by - AWS account id
Multiple values for each type of criteria can be provided by passing a seq
of the appropriate types as values."
[compute & options]
(let [options (apply hash-map options)
region (:region options)
options (snapshot-options (dissoc options :region))]
(set
(.describeSnapshotsInRegion (ebs-service compute)
(get-region region)
(into-array DescribeSnapshotsOptions [options])))))
(defn create-snapshot
"Creates a snapshot of a volume in the specified region with an optional description.
If provided, the description must be < 255 characters in length. Returns the
org.jclouds.aws.ec2.domain.Snapshot object representing the created snapshot."
([compute ^Volume volume] (create-snapshot compute volume nil))
([compute ^Volume volume description] (create-snapshot compute (.getRegion volume) (.getId volume) description))
([compute region volume-id description]
(.createSnapshotInRegion (ebs-service compute)
(get-region region)
(as-string volume-id)
(into-array CreateSnapshotOptions (when description
[(.withDescription (CreateSnapshotOptions.) description)])))))
(defn delete-snapshot
"Deletes a snapshot in the specified region."
([compute ^Snapshot snapshot] (delete-snapshot compute (.getRegion snapshot) (.getId snapshot)))
([compute region snapshot-id]
(.deleteSnapshotInRegion (ebs-service compute)
(get-region region)
(as-string snapshot-id))))
(defn get-zone
[v]
(cond
(instance? AvailabilityZoneInfo v) (.getZone v)
(instance? NodeMetadata v) (location ^NodeMetadata v)
(string? v) v
(keyword? v) (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."
([compute ^NodeMetadata node volume device]
(attach-volume compute node (.getProviderId node) (get-volume-id volume) device))
([compute region instance-id volume-id device]
(apply #(.attachVolumeInRegion (ebs-service compute)
(get-region region) % %2 %3)
(map as-string [volume-id instance-id device]))))
(defn detach-volume
"Detaches 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."
[compute 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-service compute)
region
volume-id
(boolean (:force options))
(into-array DetachVolumeOptions []))))
(defn create-volume
"Creates a new volume given a set of options:
- one of :zone (keyword, string, or AvailabilityZoneInfo) or :node (NodeMetadata)
- one or both of :snapshot (keyword, string, or Snapshot instance) or :size
(string, keyword, or number)
- :device (string or keyword) provided *only* when you want to attach the new volume to
the :node you specified!
Returns a vector of [created org.jclouds.ec2.domain.Volume,
optional org.jclouds.ec2.domain.Attachment]
Note that specifying :node instead of :zone will only attach the created volume
:device is also provided. Otherwise, the node is only used to obtain the desired
availability zone.
Note also that if :device and :node are specified, and the attach operation fails,
you will have \"leaked\" the newly-created volume
(volume creation and attachment cannot be done atomically)."
[compute & options]
(when (-> options count odd?)
(throw (IllegalArgumentException. "Must provide key-value pairs, e.g. :zone :us-east-1d :size 200")))
(let [options (apply hash-map options)
snapshot (get-string options :snapshot)
snapshot (if (snapshot? snapshot) (.getId snapshot) snapshot)
size (-?> (get-string options :size) as-int)
^NodeMetadata node (:node options)
zone (or node (get-string options :zone))
zone (if zone
(get-zone zone)
(throw (IllegalArgumentException. "Must supply a :zone or :node option.")))
ebs (ebs-service compute)]
(when (and (:device options) (not node))
(throw (IllegalArgumentException. "Cannot create and attach new volume; no :node specified")))
(let [new-volume (cond
(and snapshot size) (.createVolumeFromSnapshotInAvailabilityZone ebs zone size snapshot)
snapshot (.createVolumeFromSnapshotInAvailabilityZone ebs zone snapshot)
size (.createVolumeInAvailabilityZone ebs zone size)
:else (throw (IllegalArgumentException. "Must supply :size and/or :snapshot options.")))]
[new-volume (when (:device options)
(attach-volume compute node new-volume (as-string (:device options))))])))
(defn delete-volume
"Deletes a volume in the specified region."
([compute ^Volume volume]
(delete-volume (.getRegion volume) (.getId volume)))
([compute region volume-id]
(.deleteVolumeInRegion (ebs-service compute)
(get-region region)
(as-string volume-id))))
(defn status
"Returns the status of the given entity; works for Volumes and Snapshots."
[k]
(.getStatus k))
(defn status-available?
[^Volume v]
(= Volume$Status/AVAILABLE (status v)))
(defn status-creating?
[^Volume v]
(= Volume$Status/CREATING (status v)))
(defn status-deleting?
[^Volume v]
(= Volume$Status/DELETING (status v)))
(defn status-in-use?
[^Volume v]
(= Volume$Status/IN_USE (status v)))
(defn status-completed?
[^Snapshot s]
(= Snapshot$Status/COMPLETED (status s)))
(defn status-error?
[^Snapshot s]
(= Snapshot$Status/ERROR (status s)))
(defn status-pending?
[^Snapshot s]
(= Snapshot$Status/PENDING (status s)))

View File

@ -0,0 +1,83 @@
;
;
; Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
;
; ====================================================================
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
; ====================================================================
;
(ns
#^{:author "Chas Emerick, cemerick@snowtide.com"
:doc "A clojure binding for the jclouds AWS elastic IP address interface."}
org.jclouds.ec2.elastic-ip2
(:require (org.jclouds [compute2 :as compute])
[org.jclouds.ec2.ebs :as ebs])
(:use (clojure.contrib def core))
(:import org.jclouds.compute.domain.NodeMetadata
(org.jclouds.ec2.domain PublicIpInstanceIdPair)))
(defn ^org.jclouds.ec2.services.ElasticIPAddressClient
eip-service
"Returns an ElasticIPAddressClient for the given ComputeService"
[compute]
(-> compute
.getContext .getProviderSpecificContext .getApi .getElasticIPAddressServices))
(defn allocate
"Claims a new elastic IP address within the (optionally) specified region for your account.
Region may be a string, keyword, or a node from which the region
is inferred. Returns the IP address as a string."
([compute] (allocate compute nil))
([compute region]
(.allocateAddressInRegion (eip-service compute) (ebs/get-region region))))
(defn associate
"Associates an elastic IP address with a node."
([compute ^NodeMetadata node public-ip]
(associate node public-ip (.getProviderId node)))
([compute region public-ip instance-id]
(.associateAddressInRegion (eip-service compute)
(ebs/get-region region)
public-ip
instance-id)))
(defn addresses
"Returns a map of elastic IP addresses to maps with slots:
:region - the region (string/keyword/NodeMetadata) the IP address is allocated within
:node-id - the ID of the instance with which the IP address is associated (optional)
You may optionally specify which IP addresses you would like to query."
([compute] (addresses compute nil))
([compute region & public-ips]
(into {} (for [^PublicIpInstanceIdPair pair (.describeAddressesInRegion (eip-service compute)
(ebs/get-region region)
(into-array String public-ips))]
[(.getPublicIp pair) (merge {:region (.getRegion pair)}
(when (.getInstanceId pair) {:node-id (.getInstanceId pair)}))]))))
(defn dissociate
"Dissociates an elastic IP address from the node with which it is currently associated."
[compute region public-ip]
(.disassociateAddressInRegion (eip-service compute)
(ebs/get-region region)
public-ip))
(defn release
"Disclaims an elastic IP address from your account."
([compute public-ip] (release compute public-ip nil))
([compute public-ip region]
(.releaseAddressInRegion (eip-service compute)
(ebs/get-region region)
public-ip)))

View File

@ -27,7 +27,7 @@ import org.jclouds.providers.BaseProviderMetadata;
import org.jclouds.providers.ProviderMetadata;
/**
* Implementation of @ link org.jclouds.types.ProviderMetadata} for Amazon's Simple Storage Service
* Implementation of {@link org.jclouds.types.ProviderMetadata} for Amazon's Simple Storage Service
* (S3) provider.
*
* @author Adrian Cole

View File

@ -23,7 +23,7 @@ import org.jclouds.providers.ProviderMetadata;
import org.testng.annotations.Test;
/**
* The AWSS3ProviderTest tests the org.jclouds.providers.AWSS3Provider class.
* The AWSS3ProviderTest tests the {@link org.jclouds.aws.s3.AWSS3ProviderMetadata} class.
*
* @author Adrian Cole
*/
@ -33,4 +33,5 @@ public class AWSS3ProviderTest extends BaseProviderMetadataTest {
public AWSS3ProviderTest() {
super(new AWSS3ProviderMetadata(), ProviderMetadata.BLOBSTORE_TYPE);
}
}

View File

@ -62,7 +62,7 @@ public class CloudOneStorageProviderMetadata extends BaseProviderMetadata {
*/
@Override
public String getIdentityName() {
return "Subtenant ID";
return "Subtenant ID (UID)";
}
/**

View File

@ -97,6 +97,14 @@ public class EucalyptusPartnerCloudEC2ProviderMetadata extends BaseProviderMetad
return URI.create("http://open.eucalyptus.com/wiki/IntroducingEucalyptus_v2.0");
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> getLinkedServices() {
return ImmutableSet.of("eucalyptus-partnercloud-ec2", "eucalyptus-partnercloud-s3");
}
/**
* {@inheritDoc}
*/

View File

@ -97,6 +97,14 @@ public class EucalyptusPartnerCloudS3ProviderMetadata extends BaseProviderMetada
return URI.create("http://open.eucalyptus.com/wiki/IntroducingEucalyptus_v2.0");
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> getLinkedServices() {
return ImmutableSet.of("eucalyptus-partnercloud-ec2", "eucalyptus-partnercloud-s3");
}
/**
* {@inheritDoc}
*/

View File

@ -0,0 +1,108 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.ninefold.storage;
import com.google.common.collect.ImmutableSet;
import java.net.URI;
import java.util.Set;
import org.jclouds.providers.BaseProviderMetadata;
/**
* Implementation of {@link org.jclouds.types.ProviderMetadata} for Ninefold's
* Storage provider.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
public class NinefoldStorageProviderMetadata extends BaseProviderMetadata {
/**
* {@inheritDoc}
*/
@Override
public String getId() {
return "ninefold-storage";
}
/**
* {@inheritDoc}
*/
@Override
public String getType() {
return BLOBSTORE_TYPE;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return "Ninefold Storage";
}
/**
* {@inheritDoc}
*/
@Override
public String getIdentityName() {
return "Subtenant ID (UID)";
}
/**
* {@inheritDoc}
*/
@Override
public String getCredentialName() {
return "Shared Secret";
}
/**
* {@inheritDoc}
*/
@Override
public URI getHomepage() {
return URI.create("http://ninefold.com/cloud-storage/");
}
/**
* {@inheritDoc}
*/
@Override
public URI getConsole() {
return URI.create("https://ninefold.com/portal/");
}
/**
* {@inheritDoc}
*/
@Override
public URI getApiDocumentation() {
return URI.create("https://ninefold.com/support/display/SPT/API+Documentation");
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> getIso3166Codes() {
return ImmutableSet.of("AU-NSW");
}
}

View File

@ -0,0 +1 @@
org.jclouds.ninefold.storage.NinefoldStorageProviderMetadata

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.ninefold.storage;
import org.jclouds.providers.BaseProviderMetadataTest;
import org.jclouds.providers.ProviderMetadata;
import org.testng.annotations.Test;
/**
* The NinefoldStorageProviderTest tests the {@link NinefoldStorageProviderMetadata} class.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
@Test(groups = "unit", testName = "NinefoldStorageProviderTest")
public class NinefoldStorageProviderTest extends BaseProviderMetadataTest {
public NinefoldStorageProviderTest() {
super(new NinefoldStorageProviderMetadata(), ProviderMetadata.BLOBSTORE_TYPE);
}
}

View File

@ -0,0 +1,108 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.openhosting;
import com.google.common.collect.ImmutableSet;
import java.net.URI;
import java.util.Set;
import org.jclouds.providers.BaseProviderMetadata;
/**
* Implementation of {@link org.jclouds.types.ProviderMetadata} for OpenHosting's
* East1 provider.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
public class OpenHostingEast1ProviderMetadata extends BaseProviderMetadata {
/**
* {@inheritDoc}
*/
@Override
public String getId() {
return "openhosting-east1";
}
/**
* {@inheritDoc}
*/
@Override
public String getType() {
return COMPUTE_TYPE;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return "OpenHosting East1";
}
/**
* {@inheritDoc}
*/
@Override
public String getIdentityName() {
return "User UUID";
}
/**
* {@inheritDoc}
*/
@Override
public String getCredentialName() {
return "Secret API Key";
}
/**
* {@inheritDoc}
*/
@Override
public URI getHomepage() {
return URI.create("https://east1.openhosting.com/");
}
/**
* {@inheritDoc}
*/
@Override
public URI getConsole() {
return URI.create("https://east1.openhosting.com/accounts/login");
}
/**
* {@inheritDoc}
*/
@Override
public URI getApiDocumentation() {
return URI.create("http://www.openhosting.com/support/api/");
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> getIso3166Codes() {
return ImmutableSet.of("US-VA");
}
}

View File

@ -0,0 +1 @@
org.jclouds.openhosting.OpenHostingEast1ProviderMetadata

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.openhosting;
import org.jclouds.providers.BaseProviderMetadataTest;
import org.jclouds.providers.ProviderMetadata;
import org.testng.annotations.Test;
/**
* The OpenHostingEast1ProviderTest tests the {@link OpenHostingEast1ProviderMetadata} class.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
@Test(groups = "unit", testName = "OpenHostingEast1ProviderTest")
public class OpenHostingEast1ProviderTest extends BaseProviderMetadataTest {
public OpenHostingEast1ProviderTest() {
super(new OpenHostingEast1ProviderMetadata(), ProviderMetadata.COMPUTE_TYPE);
}
}

View File

@ -126,6 +126,7 @@
<goal>test</goal>
</goals>
<configuration>
<threadCount>1</threadCount>
<systemProperties>
<property>
<name>test.savvis-symphonyvpdc.endpoint</name>

View File

@ -0,0 +1,141 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.savvis.vpdc;
import com.google.common.collect.ImmutableSet;
import java.net.URI;
import java.util.Set;
import org.jclouds.providers.BaseProviderMetadata;
import org.jclouds.providers.ProviderMetadata;
/**
* Implementation of {@link org.jclouds.types.ProviderMetadata} for Savvis Symphony VPDC services.
*
* @author Kedar Dave
*/
public class SavvisSymphonyVPDCProviderMetadata extends BaseProviderMetadata {
/**
* {@inheritDoc}
*/
@Override
public String getId() {
return "savvis-symphonyvpdc";
}
/**
* {@inheritDoc}
*/
@Override
public String getType() {
return ProviderMetadata.COMPUTE_TYPE;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return "Savvis Symphony VPDC";
}
/**
* {@inheritDoc}
*/
@Override
public String getIdentityName() {
return "username";
}
/**
* {@inheritDoc}
*/
@Override
public String getCredentialName() {
return "password";
}
/**
* {@inheritDoc}
*/
@Override
public URI getHomepage() {
return URI.create("http://www.savvis.com/en-US/infrastructure-services/Cloud/Pages/SavvisSymphonyVPDC.aspx");
}
/**
* {@inheritDoc}
*/
@Override
public URI getConsole() {
return URI.create("https://www.savvisstation.com");
}
/**
* {@inheritDoc}
*/
@Override
public URI getApiDocumentation() {
return URI.create("https://api.symphonyvpdc.savvis.net/doc/spec/api/index.html");
}
/**
* {@inheritDoc}
* list of data centers from savvisstation colocation guide
* https://www.savvisstation.com/DocumentViewer?GUID=a95f0387-cbfe-43eb-b25b-4f2b0f68498f&sessionid=SavvisCCC%3ac9a8984b9655b01916be587e5204b2cf
* Once we have confirmation from Savvis as to what data centers are used for vpdc deployments,
* iso codes for those will be entered here
*
* City Code
* Lithia Springs, GA AT1
* Waltham, MA BO1
* Waltham, MA BO2
* Waltham, MA B03
* Elk Grove Village, IL CH3
* Chicago, IL CH4
* Sterling, VA DC2
* Sterling, VA DC3
* Sterling, VA DC4 Phase I
* Sterling, VA DC4 Phase II
* Fort Worth, TX DL1
* Fort Worth, TX DL2
* El Segundo, CA LA1
* Jersey City, NJ NJ1
* Weehawken, NJ NJ2
* Piscataway, NJ NJ3
* Piscataway, NJ 2nd floor NJ3
* Weehawken, NJ NJ2X
* Irvine, CA OC2
* Santa Clara, CA SC4
* Santa Clara, CA SC5
* Santa Clara, CA SC8
* Santa Clara, CA SC9
* Tukwila, WA 1st floor SE2
* Montreal, Canada MR1
* Toronto, Canada TR1
* Vancouver, Canada VC1
*/
@Override
public Set<String> getIso3166Codes() {
return ImmutableSet.of("");
}
}

View File

@ -55,7 +55,7 @@ public interface FirewallAsyncClient {
*/
@PUT
@XMLResponseParser(TaskHandler.class)
@Path("v{jclouds.api-version}/org/{billingSiteId}/vdc/{vpdcId}/FirewallService/")
@Path("v{jclouds.api-version}/org/{billingSiteId}/vdc/{vpdcId}/FirewallService")
@MapBinder(BindFirewallRuleToXmlPayload.class)
ListenableFuture<Task> addFirewallRule(
@PathParam("billingSiteId") @Nullable @ParamParser(DefaultOrgIfNull.class) String billingSiteId,
@ -66,7 +66,7 @@ public interface FirewallAsyncClient {
*/
@DELETE
@XMLResponseParser(TaskHandler.class)
@Path("v{jclouds.api-version}/org/{billingSiteId}/vdc/{vpdcId}/FirewallService/")
@Path("v{jclouds.api-version}/org/{billingSiteId}/vdc/{vpdcId}/FirewallService")
@MapBinder(BindFirewallRuleToXmlPayload.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> deleteFirewallRule(

View File

@ -0,0 +1 @@
org.jclouds.savvis.vpdc.SavvisSymphonyVPDCProviderMetadata

View File

@ -0,0 +1,36 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.savvis.vpdc;
import org.jclouds.providers.BaseProviderMetadataTest;
import org.jclouds.providers.ProviderMetadata;
import org.testng.annotations.Test;
/**
* The SavvisSymphonyVPDCProviderTest tests the org.jclouds.savvis.vpdc.SavvisSymphonyVPDCProviderMetadata class.
*
* @author Kedar Dave
*/
@Test(groups = "unit", testName = "SavvisSymphonyVPDCProviderTest")
public class SavvisSymphonyVPDCProviderTest extends BaseProviderMetadataTest {
public SavvisSymphonyVPDCProviderTest() {
super(new SavvisSymphonyVPDCProviderMetadata(), ProviderMetadata.COMPUTE_TYPE);
}
}

View File

@ -24,6 +24,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
@ -79,6 +80,9 @@ public class BaseVPDCClientLiveTest {
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
// TODO savvis uses untrusted certificates, remove these once savvis fixes the issue
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
return overrides;
}

View File

@ -115,11 +115,13 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
}
}
// test for a single vm, as savvis response times are very slow. So if there are multiple vpdc's with numerous vm's,
// test execution will invariably take a long time
@Test
public void testVM() throws Exception {
for (Resource org1 : restContext.getApi().listOrgs()) {
Org org = client.getOrg(org1.getId());
for (Resource vdc : org.getVDCs()) {
VDC_LOOP : for (Resource vdc : org.getVDCs()) {
VDC VDC = client.getVDCInOrg(org.getId(), vdc.getId());
for (Resource vApp : Iterables.filter(VDC.getResourceEntities(), new Predicate<Resource>() {
@ -151,11 +153,15 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
String ip = Iterables.get(response.getNetworkConnectionSections(), 0).getIpAddress();
assert HostSpecifier.isValid(ip) : response;
if (InetAddresses2.isPrivateIPAddress(ip)) {
// get public ip
ip = Iterables.get(response.getNetworkConfigSections(), 0).getInternalToExternalNATRules().get(ip);
}
// could be null
if(ip != null){
assert HostSpecifier.isValid(ip) : response;
}
}
break VDC_LOOP;
}
}
}
}

View File

@ -48,7 +48,7 @@ public class FirewallAsyncClientTest extends BaseVPDCAsyncClientTest<FirewallAsy
"Tcp").policy("allow").description("Server Tier Firewall Rule").isLogged(false).build());
assertRequestLineEquals(request,
"PUT https://api.symphonyvpdc.savvis.net/vpdc/v1.0/org/11/vdc/22/FirewallService/ HTTP/1.1");
"PUT https://api.symphonyvpdc.savvis.net/vpdc/v1.0/org/11/vdc/22/FirewallService HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, Strings2.toStringAndClose(getClass().getResourceAsStream(
"/firewallService-default.xml")), "application/xml", false);
@ -67,7 +67,7 @@ public class FirewallAsyncClientTest extends BaseVPDCAsyncClientTest<FirewallAsy
"Tcp").policy("allow").description("Server Tier Firewall Rule").isLogged(false).build());
assertRequestLineEquals(request,
"DELETE https://api.symphonyvpdc.savvis.net/vpdc/v1.0/org/11/vdc/22/FirewallService/ HTTP/1.1");
"DELETE https://api.symphonyvpdc.savvis.net/vpdc/v1.0/org/11/vdc/22/FirewallService HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, Strings2.toStringAndClose(getClass().getResourceAsStream(
"/firewallService-default.xml")), "application/xml", false);

View File

@ -66,7 +66,7 @@ public class FirewallClientLiveTest extends BaseVPDCClientLiveTest {
FirewallRule firewallRule = FirewallRule.builder().firewallType("SERVER_TIER_FIREWALL").isEnabled(true).source("internet")
.destination(networkTierName).port("10000").protocol("Tcp").policy("allow").description("Server Tier Firewall Rule").isLogged(false).build();
System.out.printf("adding firewall rule:%s %n", firewallRule.toString());
System.out.printf("adding firewall rule:%s in vpdc %s %n", firewallRule.toString(), vpdcId);
Task task = client.addFirewallRule(billingSiteId, vpdcId, firewallRule);
@ -101,7 +101,7 @@ public class FirewallClientLiveTest extends BaseVPDCClientLiveTest {
FirewallRule firewallRule = FirewallRule.builder().firewallType("SERVER_TIER_FIREWALL").isEnabled(true).source("internet")
.destination(networkTierName).port("10000").protocol("Tcp").policy("allow").description("Server Tier Firewall Rule").isLogged(false).build();
System.out.printf("deleting firewall rule:%s %n", firewallRule.toString());
System.out.printf("deleting firewall rule:%s in vpdc %s %n", firewallRule.toString(), vpdcId);
Task task = client.deleteFirewallRule(billingSiteId, vpdcId, firewallRule);

View File

@ -27,6 +27,7 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.savvis.vpdc.domain.Org;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.domain.Task;
import org.jclouds.savvis.vpdc.domain.VDC;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.reference.VCloudMediaType;
@ -48,10 +49,12 @@ public class ServiceManagementClientLiveTest extends BaseVPDCClientLiveTest {
client = restContext.getApi().getServiceManagementClient();
}
// test for a single vm, as savvis response times are very slow. So if there are multiple vpdc's with numerous vm's,
// test execution will invariably take a long time
public void testLifeCycle() throws InterruptedException, ExecutionException, TimeoutException, IOException {
for (Resource org1 : restContext.getApi().listOrgs()) {
Org org = restContext.getApi().getBrowsingClient().getOrg(org1.getId());
for (Resource vdc : org.getVDCs()) {
VDC_LOOP : for (Resource vdc : org.getVDCs()) {
VDC VDC = restContext.getApi().getBrowsingClient().getVDCInOrg(org.getId(), vdc.getId());
for (Resource vmHandle : Iterables.filter(VDC.getResourceEntities(), new Predicate<Resource>() {
@ -62,17 +65,20 @@ public class ServiceManagementClientLiveTest extends BaseVPDCClientLiveTest {
})) {
assert taskTester.apply(client.powerOffVM(vmHandle.getHref()).getId());
Task powerOffTask = client.powerOffVM(vmHandle.getHref());
assert taskTester.apply(powerOffTask.getId());
VM vm = restContext.getApi().getBrowsingClient().getVM(vmHandle.getHref(), withPowerState());
assertEquals(vm.getStatus(), VM.Status.OFF);
assert taskTester.apply(client.powerOnVM(vmHandle.getHref()).getId());
Task powerOnTask = client.powerOnVM(vmHandle.getHref());
assert taskTester.apply(powerOnTask.getId());
vm = restContext.getApi().getBrowsingClient().getVM(vmHandle.getHref(), withPowerState());
assertEquals(vm.getStatus(), VM.Status.ON);
break VDC_LOOP;
}
}
}

View File

@ -21,7 +21,6 @@ package org.jclouds.savvis.vpdc.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -38,7 +37,6 @@ import org.jclouds.savvis.vpdc.domain.Task;
import org.jclouds.savvis.vpdc.domain.VDC;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.domain.VMSpec;
import org.jclouds.savvis.vpdc.domain.VM.Status;
import org.jclouds.savvis.vpdc.options.GetVMOptions;
import org.jclouds.savvis.vpdc.reference.VCloudMediaType;
import org.jclouds.ssh.SshClient;
@ -49,8 +47,8 @@ import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Iterables;
import com.google.common.net.HostSpecifier;
@Test(groups = "live")
@ -98,13 +96,8 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
.getName();
String name = prefix;
// delete any old VM
VDC vpdc = restContext.getApi().getBrowsingClient().getVDCInOrg(billingSiteId, vpdcId);
for (Resource resource : vpdc.getResourceEntities()) {
if (resource.getName().equals(prefix)) {
taskTester.apply(client.removeVMFromVDC(billingSiteId, vpdcId, resource.getId()).getId());
}
}
CIMOperatingSystem os = Iterables.find(restContext.getApi().listPredefinedOperatingSystems(),
new Predicate<CIMOperatingSystem>() {
@ -114,7 +107,7 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
}
});
System.out.printf("vpdcId %s, networkName %s, name %s, os %s%n", vpdcId, networkTierName, name, os);
System.out.printf("Creating vm - vpdcId %s, vpdcName %s, networkName %s, name %s, os %s%n", vpdcId, vpdc.getName(), networkTierName, name, os);
// TODO: determine the sizes available in the VDC, for example there's
// a minimum size of boot disk, and also a preset combination of cpu count vs ram
@ -125,11 +118,19 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
assert task.getId() != null && task.getError() == null : task;
assert this.taskTester.apply(task.getId());
vm = restContext.getApi().getBrowsingClient().getVMInVDC(billingSiteId, vpdcId, task.getOwner().getId());
conditionallyCheckSSH();
// fetch the task again, in savvis, task.getOwner is populated with vApp after task has finished
task = restContext.getApi().getBrowsingClient().getTask(task.getId());
vm = restContext.getApi().getBrowsingClient().getVM(task.getOwner().getHref(), GetVMOptions.NONE);
assert vm.getHref() != null : vm;
// cannot ssh in savvis, as no public ip is assigned by default
// conditionallyCheckSSH();
}
public void testCreateMultipleVMs() throws Exception {
@Test(dependsOnMethods="testCloneVApp")
public void testZCreateMultipleVMs() throws Exception {
billingSiteId = restContext.getApi().getBrowsingClient().getOrg(null).getId();// default
vpdcId = Iterables.find(restContext.getApi().getBrowsingClient().getOrg(billingSiteId).getVDCs(),
new Predicate<Resource>() {
@ -168,7 +169,7 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
// TODO: Savvis returns network names with a - instead of space on getNetworkInVDC call,
// fix this once savvis api starts returning correctly
System.out.printf("vpdcId %s, vpdcName %s, networkName %s, name %s, os %s%n", vpdcId, vpdc.getName(), networkTier
System.out.printf("Creating vm's - vpdcId %s, vpdcName %s, networkName %s, name %s, os %s%n", vpdcId, vpdc.getName(), networkTier
.getName().replace("-", " "), name, os);
Builder<VMSpec> vmSpecs = ImmutableSet.<VMSpec> builder();
@ -186,11 +187,21 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
for (Task task : tasks) {
// make sure there's no error
assert task.getId() != null && task.getError() == null : task;
assert this.taskTester.apply(task.getId());
// fetch the task again, in savvis, task.getOwner is populated with vApp after task has finished
task = restContext.getApi().getBrowsingClient().getTask(task.getId());
VM newVM = restContext.getApi().getBrowsingClient().getVM(task.getOwner().getHref(), GetVMOptions.NONE);
assert newVM.getHref() != null : newVM;
}
}
/**
* disabled because it not currently supported by savvis. Planned for august release by savvis.
* @throws Exception
*/
@Test(enabled=false)
public void testCaptureVAppTemplate() throws Exception {
billingSiteId = restContext.getApi().getBrowsingClient().getOrg(null).getId();// default
vpdcId = Iterables.find(restContext.getApi().getBrowsingClient().getOrg(billingSiteId).getVDCs(),
@ -229,6 +240,7 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
}
}
@Test(dependsOnMethods="testCreateVirtualMachine")
public void testCloneVApp() throws Exception {
billingSiteId = restContext.getApi().getBrowsingClient().getOrg(null).getId();// default
vpdcId = Iterables.find(restContext.getApi().getBrowsingClient().getOrg(billingSiteId).getVDCs(),
@ -246,28 +258,25 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
}).getId();
VDC vpdc = restContext.getApi().getBrowsingClient().getVDCInOrg(billingSiteId, vpdcId);
String networkTierName = Iterables.get(
restContext.getApi().getBrowsingClient().getVDCInOrg(billingSiteId, vpdcId).getAvailableNetworks(), 0)
.getId();
String networkTierName = Iterables.get(vpdc.getAvailableNetworks(), 0).getId();
String clonedVMName = vm.getName() + "clone";
for (Resource vApp : Iterables.filter(vpdc.getResourceEntities(), new Predicate<Resource>() {
System.out.printf("Cloning vm - name %s in vpdcId %s in network %s, newVM name is %s%n", vm.getName(), vpdcId, networkTierName, clonedVMName);
@Override
public boolean apply(Resource arg0) {
return VCloudMediaType.VAPP_XML.equals(arg0.getType());
}
})) {
System.out.printf("Cloning VApp - %s%n", vApp.getName());
Task task = client.cloneVApp(vApp.getHref(), "clonedvm", networkTierName);
Task task = client.cloneVApp(vm.getHref(), clonedVMName, networkTierName);
// make sure there's no error
assert task.getId() != null && task.getError() == null : task;
assert this.taskTester.apply(task.getId());
}
// fetch the task again, in savvis, task.getOwner is populated with vApp after task has finished
task = restContext.getApi().getBrowsingClient().getTask(task.getId());
VM clonedVM = restContext.getApi().getBrowsingClient().getVM(task.getOwner().getHref(), GetVMOptions.NONE);
assert clonedVM.getHref() != null : clonedVM;
}
private void conditionallyCheckSSH() {
@ -297,90 +306,6 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest {
}
}
@Test(enabled = false)
public void testPowerOffVM() throws Exception {
billingSiteId = restContext.getApi().getBrowsingClient().getOrg(null).getId();// default
vpdcId = Iterables.find(restContext.getApi().getBrowsingClient().getOrg(billingSiteId).getVDCs(),
new Predicate<Resource>() {
// try to find the first VDC owned by the current user
// check here for what the email property might be, or in
// the jclouds-wire.log
@Override
public boolean apply(Resource arg0) {
String description = restContext.getApi().getBrowsingClient().getVDCInOrg(billingSiteId,
arg0.getId()).getDescription();
return description.indexOf(email) != -1;
}
}).getId();
VDC vpdc = restContext.getApi().getBrowsingClient().getVDCInOrg(billingSiteId, vpdcId);
URI vmURI = Iterables.find(vpdc.getResourceEntities(), new Predicate<Resource>() {
@Override
public boolean apply(Resource arg0) {
if (VCloudMediaType.VAPP_XML.equals(arg0.getType())) {
VM response1 = restContext.getApi().getBrowsingClient().getVM(arg0.getHref(), (GetVMOptions[]) null);
System.out.printf("powering off vm - %s%n", response1.getName());
if (response1.getStatus().equals(Status.ON)) {
return true;
}
}
return false;
}
}).getHref();
Task task = client.powerOffVM(vmURI);
// make sure there's no error
assert task.getId() != null && task.getError() == null : task;
assert this.taskTester.apply(task.getId());
}
@Test(enabled = false)
public void testPowerOnVM() throws Exception {
billingSiteId = restContext.getApi().getBrowsingClient().getOrg(null).getId();// default
vpdcId = Iterables.find(restContext.getApi().getBrowsingClient().getOrg(billingSiteId).getVDCs(),
new Predicate<Resource>() {
// try to find the first VDC owned by the current user
// check here for what the email property might be, or in
// the jclouds-wire.log
@Override
public boolean apply(Resource arg0) {
String description = restContext.getApi().getBrowsingClient().getVDCInOrg(billingSiteId,
arg0.getId()).getDescription();
return description.indexOf(email) != -1;
}
}).getId();
VDC vpdc = restContext.getApi().getBrowsingClient().getVDCInOrg(billingSiteId, vpdcId);
URI vmURI = Iterables.find(vpdc.getResourceEntities(), new Predicate<Resource>() {
@Override
public boolean apply(Resource arg0) {
if (VCloudMediaType.VAPP_XML.equals(arg0.getType())) {
VM response1 = restContext.getApi().getBrowsingClient().getVM(arg0.getHref(), (GetVMOptions[]) null);
System.out.printf("powering on vm - %s%n", response1.getName());
if (response1.getStatus().equals(Status.OFF)) {
return true;
}
}
return false;
}
}).getHref();
Task task = client.powerOnVM(vmURI);
// make sure there's no error
assert task.getId() != null && task.getError() == null : task;
assert this.taskTester.apply(task.getId());
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (vm != null) {

View File

@ -0,0 +1,109 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.synaptic.storage;
import com.google.common.collect.ImmutableSet;
import java.net.URI;
import java.util.Set;
import org.jclouds.providers.BaseProviderMetadata;
import org.jclouds.providers.ProviderMetadata;
/**
* Implementation of {@link org.jclouds.types.ProviderMetadata} for AT&T's
* Synaptic Storage provider.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
public class SynapticStorageProviderMetadata extends BaseProviderMetadata {
/**
* {@inheritDoc}
*/
@Override
public String getId() {
return "synaptic-storage";
}
/**
* {@inheritDoc}
*/
@Override
public String getType() {
return ProviderMetadata.BLOBSTORE_TYPE;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return "AT&T Synaptic Storage";
}
/**
* {@inheritDoc}
*/
@Override
public String getIdentityName() {
return "Subtenant ID (UID)";
}
/**
* {@inheritDoc}
*/
@Override
public String getCredentialName() {
return "Shared Secret";
}
/**
* {@inheritDoc}
*/
@Override
public URI getHomepage() {
return URI.create("https://www.synaptic.att.com/");
}
/**
* {@inheritDoc}
*/
@Override
public URI getConsole() {
return URI.create("https://www.synaptic.att.com/clouduser/login.htm");
}
/**
* {@inheritDoc}
*/
@Override
public URI getApiDocumentation() {
return URI.create("https://www.synaptic.att.com/clouduser/emc_atmos_api.htm");
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> getIso3166Codes() {
return ImmutableSet.of("US-VA", "US-TX");
}
}

View File

@ -0,0 +1 @@
org.jclouds.synaptic.storage.SynapticStorageProviderMetadata

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.synaptic.storage;
import org.jclouds.providers.BaseProviderMetadataTest;
import org.jclouds.providers.ProviderMetadata;
import org.testng.annotations.Test;
/**
* The SynapticStorageProviderTest tests the {@link org.jclouds.synaptic.storage.SynapticStorageProviderMetadata} class.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
@Test(groups = "unit", testName = "SynapticStorageProviderTest")
public class SynapticStorageProviderTest extends BaseProviderMetadataTest {
public SynapticStorageProviderTest() {
super(new SynapticStorageProviderMetadata(), ProviderMetadata.BLOBSTORE_TYPE);
}
}