From b9f0cbcb89199024ed653d5af9bc437b00697bc7 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Mon, 4 Apr 2011 23:37:00 -0700 Subject: [PATCH 1/2] crypto tuning --- .../jclouds/blobstore/domain/internal/BlobBuilderImpl.java | 7 +++---- drivers/bouncycastle/pom.xml | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobBuilderImpl.java b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobBuilderImpl.java index 05f0ba6f00..1ad10297f2 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobBuilderImpl.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobBuilderImpl.java @@ -25,7 +25,6 @@ import static org.jclouds.io.Payloads.newPayload; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.security.MessageDigest; import java.util.Map; import javax.inject.Inject; @@ -128,12 +127,12 @@ public class BlobBuilderImpl implements BlobBuilder { public class PayloadBlobBuilderImpl implements PayloadBlobBuilder { private final BlobBuilder builder; private final Payload payload; - private MessageDigest digest; + private final Crypto crypto; public PayloadBlobBuilderImpl(BlobBuilder builder, Payload payload, Crypto crypto) { this.builder = checkNotNull(builder, "builder"); this.payload = checkNotNull(payload, "payload"); - this.digest = checkNotNull(crypto, "crypto").md5(); + this.crypto = checkNotNull(crypto, "crypto"); } @Override @@ -158,7 +157,7 @@ public class BlobBuilderImpl implements BlobBuilder { @Override public PayloadBlobBuilder calculateMD5() throws IOException { - return builder.payload(Payloads.calculateMD5(payload, digest)); + return builder.payload(Payloads.calculateMD5(payload, crypto.md5())); } @Override diff --git a/drivers/bouncycastle/pom.xml b/drivers/bouncycastle/pom.xml index c3c4b5be11..509947753f 100644 --- a/drivers/bouncycastle/pom.xml +++ b/drivers/bouncycastle/pom.xml @@ -61,7 +61,7 @@ org.bouncycastle bcprov-jdk16 - 1.45 + 1.46 compile From 1cfbdf00f37fddf04249feedd6fc18ee122bdb72 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 5 Apr 2011 00:14:18 -0700 Subject: [PATCH 2/2] Issue 355: shell for nova 1.1 based on cloudservers --- core/src/main/resources/rest.properties | 4 +- .../NovaEC2ComputeServiceLiveTest.java | 53 - sandbox-apis/{nova-ec2 => nova}/pom.xml | 51 +- .../openstack/nova/NovaAsyncClient.java | 378 ++++++++ .../jclouds/openstack/nova/NovaClient.java | 380 ++++++++ .../openstack/nova/NovaContextBuilder.java | 64 ++ .../openstack/nova/ServerManagement.java | 41 + .../BindBackupScheduleToJsonPayload.java | 54 ++ .../NovaBindComputeStrategiesByClass.java | 77 ++ .../NovaBindComputeSuppliersByClass.java | 54 ++ .../NovaComputeServiceContextModule.java} | 30 +- .../NovaComputeServiceDependenciesModule.java | 117 +++ .../compute/functions/FlavorToHardware.java | 44 + .../compute/functions/NovaImageToImage.java | 56 ++ .../functions/NovaImageToOperatingSystem.java | 92 ++ .../functions/ServerToNodeMetadata.java | 143 +++ ...ovaCreateNodeWithGroupEncodedIntoName.java | 63 ++ .../strategy/NovaDestroyNodeStrategy.java | 52 + .../strategy/NovaGetNodeMetadataStrategy.java | 54 ++ .../strategy/NovaLifeCycleStrategy.java | 65 ++ .../strategy/NovaListNodesStrategy.java | 62 ++ .../suppliers/NovaHardwareSupplier.java | 68 ++ .../compute/suppliers/NovaImageSupplier.java | 71 ++ .../nova/config/NovaRestClientModule.java | 85 ++ .../openstack/nova/domain/AbsoluteLimit.java | 48 + .../jclouds/openstack/nova/domain/Action.java | 28 + .../openstack/nova/domain/Addresses.java | 99 ++ .../openstack/nova/domain/BackupSchedule.java | 105 ++ .../openstack/nova/domain/DailyBackup.java | 38 + .../jclouds/openstack/nova/domain/Flavor.java | 121 +++ .../jclouds/openstack/nova/domain/Image.java | 146 +++ .../openstack/nova/domain/ImageStatus.java | 46 + .../jclouds/openstack/nova/domain/Limits.java | 47 + .../openstack/nova/domain/RateLimit.java | 90 ++ .../openstack/nova/domain/RateLimitUnit.java | 38 + .../openstack/nova/domain/RebootType.java | 38 + .../jclouds/openstack/nova/domain/Server.java | 230 +++++ .../openstack/nova/domain/ServerStatus.java | 55 ++ .../openstack/nova/domain/ShareIp.java | 43 + .../openstack/nova/domain/SharedIpGroup.java | 112 +++ .../openstack/nova/domain/Version.java | 60 ++ .../openstack/nova/domain/VersionStatus.java | 38 + .../openstack/nova/domain/WeeklyBackup.java | 38 + .../ParseNovaErrorFromHttpResponse.java | 96 ++ .../nova/options/CreateServerOptions.java | 241 +++++ .../options/CreateSharedIpGroupOptions.java | 88 ++ .../openstack/nova/options/ListOptions.java | 110 +++ .../nova/options/RebuildServerOptions.java | 75 ++ .../nova/predicates/ServerActive.java | 67 ++ .../nova/predicates/ServerDeleted.java | 67 ++ .../openstack/nova/NovaAsyncClientTest.java | 905 ++++++++++++++++++ .../openstack/nova/NovaClientLiveTest.java | 639 +++++++++++++ .../compute/NovaComputeServiceLiveTest.java | 89 ++ .../NovaComputeServiceContextModuleTest.java | 38 + .../functions/FlavorToHardwareTest.java | 62 ++ .../functions/NovaImageToImageTest.java | 67 ++ .../functions/ServerToNodeMetadataTest.java | 157 +++ .../openstack/nova/domain/ServerTest.java | 49 + .../ParseAddressesFromJsonResponseTest.java | 63 ++ ...rseBackupScheduleFromJsonResponseTest.java | 69 ++ .../ParseFlavorFromJsonResponseTest.java | 65 ++ .../ParseFlavorListFromJsonResponseTest.java | 82 ++ .../ParseImageFromJsonResponseTest.java | 93 ++ .../ParseImageListFromJsonResponseTest.java | 102 ++ ...seInetAddressListFromJsonResponseTest.java | 71 ++ .../ParseServerFromJsonResponseTest.java | 83 ++ .../ParseServerListFromJsonResponseTest.java | 107 +++ ...arseSharedIpGroupFromJsonResponseTest.java | 62 ++ ...SharedIpGroupListFromJsonResponseTest.java | 84 ++ .../nova/options/CreateServerOptionsTest.java | 141 +++ .../CreateSharedIpGroupOptionsTest.java | 80 ++ .../nova/options/ListOptionsTest.java | 89 ++ .../options/RebuildServerOptionsTest.java | 80 ++ .../nova/src/test/resources/log4j.xml | 185 ++++ .../resources/test_get_flavor_details.json | 8 + .../resources/test_get_image_details.json | 11 + .../resources/test_get_server_detail.json | 25 + .../test_get_sharedipgroup_details.json | 7 + .../test/resources/test_list_addresses.json | 12 + .../test_list_addresses_private.json | 8 + .../resources/test_list_addresses_public.json | 7 + .../resources/test_list_backupschedule.json | 7 + .../src/test/resources/test_list_flavors.json | 12 + .../resources/test_list_flavors_detail.json | 16 + .../src/test/resources/test_list_images.json | 12 + .../resources/test_list_images_detail.json | 20 + .../src/test/resources/test_list_servers.json | 12 + .../resources/test_list_servers_detail.json | 45 + .../resources/test_list_sharedipgroups.json | 12 + .../test_list_sharedipgroups_detail.json | 14 + 90 files changed, 7918 insertions(+), 94 deletions(-) delete mode 100644 sandbox-apis/nova-ec2/src/test/java/org/jclouds/nova/ec2/compute/NovaEC2ComputeServiceLiveTest.java rename sandbox-apis/{nova-ec2 => nova}/pom.xml (72%) create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaClient.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaContextBuilder.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/ServerManagement.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/binders/BindBackupScheduleToJsonPayload.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeStrategiesByClass.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeSuppliersByClass.java rename sandbox-apis/{nova-ec2/src/main/java/org/jclouds/nova/ec2/NovaEC2PropertiesBuilder.java => nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModule.java} (53%) create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceDependenciesModule.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardware.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImage.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToOperatingSystem.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadata.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaCreateNodeWithGroupEncodedIntoName.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaDestroyNodeStrategy.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaGetNodeMetadataStrategy.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaLifeCycleStrategy.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaListNodesStrategy.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaHardwareSupplier.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaImageSupplier.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/AbsoluteLimit.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Action.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Addresses.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/BackupSchedule.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/DailyBackup.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Image.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ImageStatus.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Limits.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimit.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimitUnit.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RebootType.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Server.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ServerStatus.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ShareIp.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/SharedIpGroup.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Version.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/VersionStatus.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/WeeklyBackup.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/handlers/ParseNovaErrorFromHttpResponse.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateServerOptions.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptions.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/ListOptions.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/RebuildServerOptions.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerActive.java create mode 100644 sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerDeleted.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/NovaComputeServiceLiveTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModuleTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImageTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadataTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/domain/ServerTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseAddressesFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseBackupScheduleFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageListFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseInetAddressListFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerListFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupListFromJsonResponseTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateServerOptionsTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptionsTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/ListOptionsTest.java create mode 100644 sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/RebuildServerOptionsTest.java create mode 100755 sandbox-apis/nova/src/test/resources/log4j.xml create mode 100644 sandbox-apis/nova/src/test/resources/test_get_flavor_details.json create mode 100644 sandbox-apis/nova/src/test/resources/test_get_image_details.json create mode 100644 sandbox-apis/nova/src/test/resources/test_get_server_detail.json create mode 100644 sandbox-apis/nova/src/test/resources/test_get_sharedipgroup_details.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_addresses.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_addresses_private.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_addresses_public.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_backupschedule.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_flavors.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_flavors_detail.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_images.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_images_detail.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_servers.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_servers_detail.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_sharedipgroups.json create mode 100644 sandbox-apis/nova/src/test/resources/test_list_sharedipgroups_detail.json diff --git a/core/src/main/resources/rest.properties b/core/src/main/resources/rest.properties index f260ec720c..cfba086eed 100644 --- a/core/src/main/resources/rest.properties +++ b/core/src/main/resources/rest.properties @@ -83,8 +83,8 @@ eucalyptus.propertiesbuilder=org.jclouds.eucalyptus.EucalyptusPropertiesBuilder eucalyptus-partnercloud-ec2.contextbuilder=org.jclouds.epc.EucalyptusPartnerCloudContextBuilder eucalyptus-partnercloud-ec2.propertiesbuilder=org.jclouds.epc.EucalyptusPartnerCloudPropertiesBuilder -nova-ec2.contextbuilder=org.jclouds.ec2.EC2ContextBuilder -nova-ec2.propertiesbuilder=org.jclouds.nova.ec2.NovaEC2PropertiesBuilder +nova.contextbuilder=org.jclouds.openstack.nova.NovaContextBuilder +nova.propertiesbuilder=org.jclouds.openstack.nova.NovaPropertiesBuilder cloudservers-uk.contextbuilder=org.jclouds.cloudservers.CloudServersContextBuilder cloudservers-uk.propertiesbuilder=org.jclouds.rackspace.cloudservers.CloudServersUKPropertiesBuilder diff --git a/sandbox-apis/nova-ec2/src/test/java/org/jclouds/nova/ec2/compute/NovaEC2ComputeServiceLiveTest.java b/sandbox-apis/nova-ec2/src/test/java/org/jclouds/nova/ec2/compute/NovaEC2ComputeServiceLiveTest.java deleted file mode 100644 index 50a13a9120..0000000000 --- a/sandbox-apis/nova-ec2/src/test/java/org/jclouds/nova/ec2/compute/NovaEC2ComputeServiceLiveTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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.nova.ec2.compute; - -import static org.jclouds.compute.util.ComputeServiceUtils.getCores; -import static org.testng.Assert.assertEquals; - -import org.jclouds.compute.domain.OsFamily; -import org.jclouds.compute.domain.Template; -import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest; -import org.testng.annotations.Test; - -/** - * - * @author Adrian Cole - */ -@Test(groups = "live", sequential = true, testName = "NovaEC2ComputeServiceLiveTest") -public class NovaEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest { - - public NovaEC2ComputeServiceLiveTest() { - provider = "nova-ec2"; - } - - @Override - protected void assertDefaultWorks() { - Template defaultTemplate = client.templateBuilder().build(); - assert (defaultTemplate.getImage().getProviderId().startsWith("ami-")) : defaultTemplate; - assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04"); - assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true); - assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU); - assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "instance-store"); - assertEquals(defaultTemplate.getLocation().getId(), "nova"); - assertEquals(getCores(defaultTemplate.getHardware()), 1.0d); - } - -} diff --git a/sandbox-apis/nova-ec2/pom.xml b/sandbox-apis/nova/pom.xml similarity index 72% rename from sandbox-apis/nova-ec2/pom.xml rename to sandbox-apis/nova/pom.xml index eb521eac25..13e3dda25b 100644 --- a/sandbox-apis/nova-ec2/pom.xml +++ b/sandbox-apis/nova/pom.xml @@ -30,33 +30,38 @@ ../../project/pom.xml org.jclouds.api - nova-ec2 - jclouds OpenStack Nova EC2 api - EC2 implementation based on OpenStack Nova + nova + jcloud nova api + jclouds components to access an implementation of OpenStack Nova - TODO - 2010-06-15 - FIXME - FIXME + https://auth.api.rackspacecloud.com + 1.1 + FIXME + FIXME - org.jclouds.api - ec2 + org.jclouds.common + openstack-common ${project.version} - org.jclouds.api - ec2 + org.jclouds + jclouds-compute + ${project.version} + + + org.jclouds + jclouds-core ${project.version} test-jar test - org.jclouds - jclouds-core + org.jclouds.common + openstack-common ${project.version} test-jar test @@ -111,20 +116,24 @@ - test.nova-ec2.endpoint - ${test.nova-ec2.endpoint} + test.nova.endpoint + ${test.nova.endpoint} - test.nova-ec2.apiversion - ${test.nova-ec2.apiversion} + test.nova.apiversion + ${test.nova.apiversion} - test.nova-ec2.identity - ${test.nova-ec2.identity} + test.nova.identity + ${test.nova.identity} - test.nova-ec2.credential - ${test.nova-ec2.credential} + test.nova.credential + ${test.nova.credential} + + + test.initializer + ${test.initializer} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java new file mode 100644 index 0000000000..833426d7ad --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java @@ -0,0 +1,378 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova; + +import java.util.Set; +import java.util.concurrent.ExecutionException; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.nova.binders.BindBackupScheduleToJsonPayload; +import org.jclouds.openstack.nova.domain.Addresses; +import org.jclouds.openstack.nova.domain.BackupSchedule; +import org.jclouds.openstack.nova.domain.Flavor; +import org.jclouds.openstack.nova.domain.Image; +import org.jclouds.openstack.nova.domain.RebootType; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.SharedIpGroup; +import org.jclouds.openstack.nova.options.CreateServerOptions; +import org.jclouds.openstack.nova.options.CreateSharedIpGroupOptions; +import org.jclouds.openstack.nova.options.ListOptions; +import org.jclouds.openstack.nova.options.RebuildServerOptions; +import org.jclouds.http.functions.ReturnFalseOn404; +import org.jclouds.openstack.filters.AddTimestampQuery; +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Endpoint; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.MapBinder; +import org.jclouds.rest.annotations.Payload; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.annotations.Unwrap; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to OpenStack Nova via their REST API. + *

+ * All commands return a ListenableFuture of the result from OpenStack Nova. Any exceptions incurred + * during processing will be wrapped in an {@link ExecutionException} as documented in + * {@link ListenableFuture#get()}. + * + * @see NovaClient + * @see + * @author Adrian Cole + */ +@SkipEncoding({ '/', '=' }) +@RequestFilters({ AuthenticateRequest.class, AddTimestampQuery.class }) +@Endpoint(ServerManagement.class) +public interface NovaAsyncClient { + + /** + * @see NovaClient#listServers + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/servers") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listServers(ListOptions... options); + + /** + * @see NovaClient#getServer + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @Path("/servers/{id}") + ListenableFuture getServer(@PathParam("id") int id); + + /** + * @see NovaClient#deleteServer + */ + @DELETE + @ExceptionParser(ReturnFalseOnNotFoundOr404.class) + @Path("/servers/{id}") + ListenableFuture deleteServer(@PathParam("id") int id); + + /** + * @see NovaClient#rebootServer + */ + @POST + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/action") + @Produces(MediaType.APPLICATION_JSON) + @Payload("%7B\"reboot\":%7B\"type\":\"{type}\"%7D%7D") + ListenableFuture rebootServer(@PathParam("id") int id, @PayloadParam("type") RebootType rebootType); + + /** + * @see NovaClient#resizeServer + */ + @POST + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/action") + @Produces(MediaType.APPLICATION_JSON) + @Payload("%7B\"resize\":%7B\"flavorId\":{flavorId}%7D%7D") + ListenableFuture resizeServer(@PathParam("id") int id, @PayloadParam("flavorId") int flavorId); + + /** + * @see NovaClient#confirmResizeServer + */ + @POST + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/action") + @Produces(MediaType.APPLICATION_JSON) + @Payload("{\"confirmResize\":null}") + ListenableFuture confirmResizeServer(@PathParam("id") int id); + + /** + * @see NovaClient#revertResizeServer + */ + @POST + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/action") + @Produces(MediaType.APPLICATION_JSON) + @Payload("{\"revertResize\":null}") + ListenableFuture revertResizeServer(@PathParam("id") int id); + + /** + * @see NovaClient#createServer + */ + @POST + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/servers") + @MapBinder(CreateServerOptions.class) + ListenableFuture createServer(@PayloadParam("name") String name, @PayloadParam("imageId") int imageId, + @PayloadParam("flavorId") int flavorId, CreateServerOptions... options); + + /** + * @see NovaClient#rebuildServer + */ + @POST + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/action") + @MapBinder(RebuildServerOptions.class) + ListenableFuture rebuildServer(@PathParam("id") int id, RebuildServerOptions... options); + + /** + * @see NovaClient#shareIp + */ + @PUT + @Path("/servers/{id}/ips/public/{address}") + @Produces(MediaType.APPLICATION_JSON) + @Payload("%7B\"shareIp\":%7B\"sharedIpGroupId\":{sharedIpGroupId},\"configureServer\":{configureServer}%7D%7D") + ListenableFuture shareIp(@PathParam("address") String addressToShare, + @PathParam("id") int serverToTosignBindressTo, @PayloadParam("sharedIpGroupId") int sharedIpGroup, + @PayloadParam("configureServer") boolean configureServer); + + /** + * @see NovaClient#unshareIp + */ + @DELETE + @Path("/servers/{id}/ips/public/{address}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture unshareIp(@PathParam("address") String addressToShare, + @PathParam("id") int serverToTosignBindressTo); + + /** + * @see NovaClient#changeAdminPass + */ + @PUT + @Path("/servers/{id}") + @Produces(MediaType.APPLICATION_JSON) + @Payload("%7B\"server\":%7B\"adminPass\":\"{adminPass}\"%7D%7D") + ListenableFuture changeAdminPass(@PathParam("id") int id, @PayloadParam("adminPass") String adminPass); + + /** + * @see NovaClient#renameServer + */ + @PUT + @Path("/servers/{id}") + @Produces(MediaType.APPLICATION_JSON) + @Payload("%7B\"server\":%7B\"name\":\"{name}\"%7D%7D") + ListenableFuture renameServer(@PathParam("id") int id, @PayloadParam("name") String newName); + + /** + * @see NovaClient#listFlavors + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/flavors") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listFlavors(ListOptions... options); + + /** + * @see NovaClient#getFlavor + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/flavors/{id}") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getFlavor(@PathParam("id") int id); + + /** + * @see NovaClient#listImages + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/images") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listImages(ListOptions... options); + + /** + * @see NovaClient#getImage + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @QueryParams(keys = "format", values = "json") + @Path("/images/{id}") + ListenableFuture getImage(@PathParam("id") int id); + + /** + * @see NovaClient#deleteImage + */ + @DELETE + @ExceptionParser(ReturnFalseOnNotFoundOr404.class) + @Path("/images/{id}") + ListenableFuture deleteImage(@PathParam("id") int id); + + /** + * @see NovaClient#createImageFromServer + */ + @POST + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/images") + @Produces(MediaType.APPLICATION_JSON) + @Payload("%7B\"image\":%7B\"serverId\":{serverId},\"name\":\"{name}\"%7D%7D") + ListenableFuture createImageFromServer(@PayloadParam("name") String imageName, + @PayloadParam("serverId") int serverId); + + /** + * @see NovaClient#listSharedIpGroups + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/shared_ip_groups") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listSharedIpGroups(ListOptions... options); + + /** + * @see NovaClient#getSharedIpGroup + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/shared_ip_groups/{id}") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getSharedIpGroup(@PathParam("id") int id); + + /** + * @see NovaClient#createSharedIpGroup + */ + @POST + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/shared_ip_groups") + @MapBinder(CreateSharedIpGroupOptions.class) + ListenableFuture createSharedIpGroup(@PayloadParam("name") String name, + CreateSharedIpGroupOptions... options); + + /** + * @see NovaClient#deleteSharedIpGroup + */ + @DELETE + @ExceptionParser(ReturnFalseOnNotFoundOr404.class) + @Path("/shared_ip_groups/{id}") + ListenableFuture deleteSharedIpGroup(@PathParam("id") int id); + + /** + * @see NovaClient#listBackupSchedule + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/backup_schedule") + ListenableFuture getBackupSchedule(@PathParam("id") int serverId); + + /** + * @see NovaClient#deleteBackupSchedule + */ + @DELETE + @ExceptionParser(ReturnFalseOnNotFoundOr404.class) + @Path("/servers/{id}/backup_schedule") + ListenableFuture deleteBackupSchedule(@PathParam("id") int serverId); + + /** + * @see NovaClient#replaceBackupSchedule + */ + @POST + @ExceptionParser(ReturnFalseOn404.class) + @Path("/servers/{id}/backup_schedule") + ListenableFuture replaceBackupSchedule(@PathParam("id") int id, + @BinderParam(BindBackupScheduleToJsonPayload.class) BackupSchedule backupSchedule); + + /** + * @see NovaClient#listAddresses + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/ips") + ListenableFuture getAddresses(@PathParam("id") int serverId); + + /** + * @see NovaClient#listPublicAddresses + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/ips/public") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listPublicAddresses(@PathParam("id") int serverId); + + /** + * @see NovaClient#listPrivateAddresses + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/servers/{id}/ips/private") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listPrivateAddresses(@PathParam("id") int serverId); + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaClient.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaClient.java new file mode 100644 index 0000000000..d4543249b5 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaClient.java @@ -0,0 +1,380 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova; + +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import javax.ws.rs.PathParam; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.nova.domain.Addresses; +import org.jclouds.openstack.nova.domain.BackupSchedule; +import org.jclouds.openstack.nova.domain.Flavor; +import org.jclouds.openstack.nova.domain.Image; +import org.jclouds.openstack.nova.domain.RebootType; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.SharedIpGroup; +import org.jclouds.openstack.nova.options.CreateServerOptions; +import org.jclouds.openstack.nova.options.CreateSharedIpGroupOptions; +import org.jclouds.openstack.nova.options.ListOptions; +import org.jclouds.openstack.nova.options.RebuildServerOptions; +import org.jclouds.rest.ResourceNotFoundException; + +import java.util.concurrent.Future; + +/** + * Provides access to OpenStack Nova via their REST API. + *

+ * All commands return a Future of the result from OpenStack Nova. Any exceptions incurred + * during processing will be wrapped in an {@link ExecutionException} as documented in + * {@link Future#get()}. + * + * @see NovaAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface NovaClient { + + /** + * + * List all servers (IDs and names only) + * + * This operation provides a list of servers associated with your identity. Servers that have been + * deleted are not included in this list. + *

+ * in order to retrieve all details, pass the option {@link ListOptions#withDetails() + * withDetails()} + */ + Set listServers(ListOptions... options); + + /** + * + * This operation returns details of the specified server. + * + * @return null, if the server is not found + * @see Server + */ + Server getServer(@PathParam("id") int id); + + /** + * + * This operation deletes a cloud server instance from the system. + *

+ * Note: When a server is deleted, all images created from that server are also removed. + * + * @return false if the server is not found + * @see Server + */ + boolean deleteServer(@PathParam("id") int id); + + /** + * The reboot function allows for either a soft or hard reboot of a server. + *

+ * Status Transition: + *

+ * ACTIVE - REBOOT - ACTIVE (soft reboot) + *

+ * ACTIVE - HARD_REBOOT - ACTIVE (hard reboot) + * + * @param rebootType + * With a soft reboot, the operating system is signaled to restart, which allows for a + * graceful shutdown of all processes. A hard reboot is the equivalent of power cycling + * the server. + */ + void rebootServer(int id, RebootType rebootType); + + /** + * The resize function converts an existing server to a different flavor, in essence, scaling the + * server up or down. The original server is saved for a period of time to allow rollback if + * there is a problem. All resizes should be tested and explicitly confirmed, at which time the + * original server is removed. All resizes are automatically confirmed after 24 hours if they are + * not confirmed or reverted. + *

+ * Status Transition: + *

+ * ACTIVE - QUEUE_RESIZE - PREP_RESIZE - VERIFY_RESIZE + *

+ * ACTIVE - QUEUE_RESIZE - ACTIVE (on error) + */ + void resizeServer(int id, int flavorId); + + /** + * The resize function converts an existing server to a different flavor, in essence, scaling the + * server up or down. The original server is saved for a period of time to allow rollback if + * there is a problem. All resizes should be tested and explicitly confirmed, at which time the + * original server is removed. All resizes are automatically confirmed after 24 hours if they are + * not confirmed or reverted. + *

+ * Status Transition: + *

+ * VERIFY_RESIZE - ACTIVE + */ + void confirmResizeServer(int id); + + /** + * The resize function converts an existing server to a different flavor, in essence, scaling the + * server up or down. The original server is saved for a period of time to allow rollback if + * there is a problem. All resizes should be tested and explicitly reverted, at which time the + * original server is removed. All resizes are automatically reverted after 24 hours if they are + * not reverted or reverted. + *

+ * Status Transition: + *

+ * VERIFY_RESIZE - ACTIVE + */ + void revertResizeServer(int id); + + /** + * This operation asynchronously provisions a new server. The progress of this operation depends + * on several factors including location of the requested image, network i/o, host load, and the + * selected flavor. The progress of the request can be checked by performing a GET on /server/id, + * which will return a progress attribute (0-100% completion). A password will be randomly + * generated for you and returned in the response object. For security reasons, it will not be + * returned in subsequent GET calls against a given server ID. + * + * @param options + * - used to specify extra files, metadata, or ip parameters during server creation. + */ + Server createServer(String name, int imageId, int flavorId, CreateServerOptions... options); + + /** + * The rebuild function removes all data on the server and replaces it with the specified image. + * Server ID and IP addresses remain the same. + *

+ * Status Transition: + *

+ * ACTIVE - REBUILD - ACTIVE + *

+ * ACTIVE - REBUILD - ERROR (on error) + *

+ * + * @param options + * - imageId is an optional argument. If it is not specified, the server is rebuilt + * with the original imageId. + */ + void rebuildServer(int id, RebuildServerOptions... options); + + /** + * /** This operation allows you share an IP address to the specified server + *

+ * This operation shares an IP from an existing server in the specified shared IP group to + * another specified server in the same group. The operation modifies cloud network restrictions + * to allow IP traffic for the given IP to/from the server specified. + * + *

+ * Status Transition: ACTIVE - SHARE_IP - ACTIVE (if configureServer is true) ACTIVE - + * SHARE_IP_NO_CONFIG - ACTIVE + * + * @param configureServer + *

+ * if set to true, the server is configured with the new address, though the address is + * not enabled. Note that configuring the server does require a reboot. + *

+ * If set to false, does not bind the IP to the server itself. A heartbeat facility + * (e.g. keepalived) can then be used within the servers to perform health checks and + * manage IP failover. + */ + void shareIp(String addressToShare, int serverToTosignBindressTo, int sharedIpGroup, + boolean configureServer); + + /** + * This operation removes a shared IP address from the specified server. + *

+ * Status Transition: ACTIVE - DELETE_IP - ACTIVE + * + * @param addressToShare + * @param serverToTosignBindressTo + * @return + */ + void unshareIp(String addressToShare, int serverToTosignBindressTo); + + /** + * This operation allows you to change the administrative password. + *

+ * Status Transition: ACTIVE - PASSWORD - ACTIVE + * + */ + void changeAdminPass(int id, String adminPass); + + /** + * This operation allows you to update the name of the server. This operation changes the name of + * the server in the OpenStack Nova system and does not change the server host name itself. + *

+ * Status Transition: ACTIVE - PASSWORD - ACTIVE + * + */ + void renameServer(int id, String newName); + + /** + * + * List available flavors (IDs and names only) + * + * in order to retrieve all details, pass the option {@link ListOptions#withDetails() + * withDetails()} + */ + Set listFlavors(ListOptions... options); + + /** + * + * This operation returns details of the specified flavor. + * + * @return null, if the flavor is not found + * @see Flavor + */ + Flavor getFlavor(int id); + + /** + * + * List available images (IDs and names only) + * + * in order to retrieve all details, pass the option {@link ListOptions#withDetails() + * withDetails()} + */ + Set listImages(ListOptions... options); + + /** + * + * This operation returns details of the specified image. + * + * @return null, if the image is not found + * + * @see Image + */ + Image getImage(int id); + + /** + * + * This operation deletes an image from the system. + *

+ * Note: Images are immediately removed. Currently, there are no state transitions to track the + * delete operation. + * + * @return false if the image is not found + * @see Image + */ + boolean deleteImage(int id); + + /** + * + * This operation creates a new image for the given server ID. Once complete, a new image will be + * available that can be used to rebuild or create servers. Specifying the same image name as an + * existing custom image replaces the image. The image creation status can be queried by + * performing a GET on /images/id and examining the status and progress attributes. + * + * Status Transition: + *

+ * QUEUED - PREPARING - SAVING - ACTIVE + *

+ * QUEUED - PREPARING - SAVING - FAILED (on error) + *

+ * Note: At present, image creation is an asynchronous operation, so coordinating the creation + * with data quiescence, etc. is currently not possible. + * + * @throws ResourceNotFoundException + * if the server is not found + * @see Image + */ + Image createImageFromServer(String imageName, int serverId); + + /** + * + * List shared IP groups (IDs and names only) + * + * in order to retrieve all details, pass the option {@link ListOptions#withDetails() + * withDetails()} + */ + Set listSharedIpGroups(ListOptions... options); + + /** + * + * This operation returns details of the specified shared IP group. + * + * @return null, if the shared ip group is not found + * + * @see SharedIpGroup + */ + SharedIpGroup getSharedIpGroup(int id); + + /** + * This operation creates a new shared IP group. Please note, all responses to requests for + * shared_ip_groups return an array of servers. However, on a create request, the shared IP group + * can be created empty or can be initially populated with a single server. Use + * {@link CreateSharedIpGroupOptions} to specify an server. + */ + SharedIpGroup createSharedIpGroup(String name, CreateSharedIpGroupOptions... options); + + /** + * This operation deletes the specified shared IP group. This operation will ONLY succeed if 1) + * there are no active servers in the group (i.e. they have all been terminated) or 2) no servers + * in the group are actively sharing IPs. + * + * @return false if the shared ip group is not found + * @see SharedIpGroup + */ + boolean deleteSharedIpGroup(int id); + + /** + * List the backup schedule for the specified server + * + * @throws ResourceNotFoundException + * , if the server doesn't exist + */ + BackupSchedule getBackupSchedule(int serverId); + + /** + * Delete backup schedule for the specified server. + *

+ * Web Hosting #119571 currently disables the schedule, not deletes it. + * + * @return false if the schedule is not found + */ + boolean deleteBackupSchedule(int serverId); + + /** + * Enable/update the backup schedule for the specified server + * + */ + void replaceBackupSchedule(int id, BackupSchedule backupSchedule); + + /** + * List all server addresses + * + * returns empty set if the server doesn't exist + */ + Addresses getAddresses(int serverId); + + /** + * List all public server addresses + * + * returns empty set if the server doesn't exist + */ + Set listPublicAddresses(int serverId); + + /** + * List all private server addresses + * + * returns empty set if the server doesn't exist + */ + Set listPrivateAddresses(int serverId); + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaContextBuilder.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaContextBuilder.java new file mode 100644 index 0000000000..1be627474b --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/NovaContextBuilder.java @@ -0,0 +1,64 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.compute.ComputeServiceContextBuilder; +import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; +import org.jclouds.logging.jdk.config.JDKLoggingModule; +import org.jclouds.openstack.nova.compute.config.NovaComputeServiceContextModule; +import org.jclouds.openstack.nova.config.NovaRestClientModule; + +import com.google.inject.Injector; +import com.google.inject.Module; + +/** + * Creates {@link NovaComputeServiceContext} or {@link Injector} instances based on the most + * commonly requested arguments. + *

+ * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. + *

+ *

+ * If no Modules are specified, the default {@link JDKLoggingModule logging} and + * {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed. + * + * @author Adrian Cole + * @see NovaComputeServiceContext + */ +public class NovaContextBuilder extends + ComputeServiceContextBuilder { + + public NovaContextBuilder(Properties props) { + super(NovaClient.class, NovaAsyncClient.class, props); + } + + @Override + protected void addContextModule(List modules) { + modules.add(new NovaComputeServiceContextModule()); + } + + @Override + protected void addClientModule(List modules) { + modules.add(new NovaRestClientModule()); + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/ServerManagement.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/ServerManagement.java new file mode 100644 index 0000000000..d78bd10c31 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/ServerManagement.java @@ -0,0 +1,41 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * Represents a component related to Rackspace OpenStack Nova. + * + * @see + * @author Adrian Cole + * + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +@Qualifier +public @interface ServerManagement { + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/binders/BindBackupScheduleToJsonPayload.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/binders/BindBackupScheduleToJsonPayload.java new file mode 100644 index 0000000000..b4ed95d307 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/binders/BindBackupScheduleToJsonPayload.java @@ -0,0 +1,54 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpRequest; +import org.jclouds.openstack.nova.domain.BackupSchedule; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + * + */ +@Singleton +public class BindBackupScheduleToJsonPayload extends BindToJsonPayload { + + @Override + public R bindToRequest(R request, Map postParams) { + throw new IllegalStateException( + "Replace Backup Schedule needs an BackupSchedule object, not a Map"); + } + + @Override + public R bindToRequest(R request, Object toBind) { + checkArgument(toBind instanceof BackupSchedule, + "this binder is only valid for BackupSchedules!"); + return super.bindToRequest(request, ImmutableMap.of("backupSchedule", toBind)); + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeStrategiesByClass.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeStrategiesByClass.java new file mode 100644 index 0000000000..81ec46b2fc --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeStrategiesByClass.java @@ -0,0 +1,77 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.config; + +import org.jclouds.compute.config.BindComputeStrategiesByClass; +import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName; +import org.jclouds.compute.strategy.DestroyNodeStrategy; +import org.jclouds.compute.strategy.GetNodeMetadataStrategy; +import org.jclouds.compute.strategy.ListNodesStrategy; +import org.jclouds.compute.strategy.RebootNodeStrategy; +import org.jclouds.compute.strategy.ResumeNodeStrategy; +import org.jclouds.compute.strategy.SuspendNodeStrategy; +import org.jclouds.openstack.nova.compute.strategy.NovaCreateNodeWithGroupEncodedIntoName; +import org.jclouds.openstack.nova.compute.strategy.NovaDestroyNodeStrategy; +import org.jclouds.openstack.nova.compute.strategy.NovaGetNodeMetadataStrategy; +import org.jclouds.openstack.nova.compute.strategy.NovaListNodesStrategy; +import org.jclouds.openstack.nova.compute.strategy.NovaLifeCycleStrategy; + +/** + * + * @author Adrian Cole + * + */ +public class NovaBindComputeStrategiesByClass extends BindComputeStrategiesByClass { + + @Override + protected Class defineAddNodeWithTagStrategy() { + return NovaCreateNodeWithGroupEncodedIntoName.class; + } + + @Override + protected Class defineDestroyNodeStrategy() { + return NovaDestroyNodeStrategy.class; + } + + @Override + protected Class defineGetNodeMetadataStrategy() { + return NovaGetNodeMetadataStrategy.class; + } + + @Override + protected Class defineListNodesStrategy() { + return NovaListNodesStrategy.class; + } + + @Override + protected Class defineRebootNodeStrategy() { + return NovaLifeCycleStrategy.class; + } + + @Override + protected Class defineStartNodeStrategy() { + return NovaLifeCycleStrategy.class; + } + + @Override + protected Class defineStopNodeStrategy() { + return NovaLifeCycleStrategy.class; + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeSuppliersByClass.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeSuppliersByClass.java new file mode 100644 index 0000000000..57873f9316 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaBindComputeSuppliersByClass.java @@ -0,0 +1,54 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.config; + +import java.util.Set; + +import org.jclouds.openstack.nova.compute.suppliers.NovaHardwareSupplier; +import org.jclouds.openstack.nova.compute.suppliers.NovaImageSupplier; +import org.jclouds.compute.config.BindComputeSuppliersByClass; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.domain.Location; +import org.jclouds.location.suppliers.JustProvider; + +import com.google.common.base.Supplier; + +/** + * + * @author Adrian Cole + * + */ +public class NovaBindComputeSuppliersByClass extends BindComputeSuppliersByClass { + @Override + protected Class>> defineHardwareSupplier() { + return NovaHardwareSupplier.class; + } + + @Override + protected Class>> defineImageSupplier() { + return NovaImageSupplier.class; + } + + @Override + protected Class>> defineLocationSupplier() { + return JustProvider.class; + } +} diff --git a/sandbox-apis/nova-ec2/src/main/java/org/jclouds/nova/ec2/NovaEC2PropertiesBuilder.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModule.java similarity index 53% rename from sandbox-apis/nova-ec2/src/main/java/org/jclouds/nova/ec2/NovaEC2PropertiesBuilder.java rename to sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModule.java index 09563a1177..910a412c8c 100644 --- a/sandbox-apis/nova-ec2/src/main/java/org/jclouds/nova/ec2/NovaEC2PropertiesBuilder.java +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModule.java @@ -17,31 +17,25 @@ * ==================================================================== */ -package org.jclouds.nova.ec2; +package org.jclouds.openstack.nova.compute.config; -import static org.jclouds.Constants.PROPERTY_ENDPOINT; -import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS; - -import java.util.Properties; - -import org.jclouds.ec2.EC2PropertiesBuilder; +import org.jclouds.compute.config.BaseComputeServiceContextModule; +import org.jclouds.compute.internal.BaseComputeService; /** - * Builds properties used in NovaEC2 Clients + * Configures the {@link NovaComputeServiceContext}; requires {@link BaseComputeService} + * bound. * * @author Adrian Cole */ -public class NovaEC2PropertiesBuilder extends EC2PropertiesBuilder { - @Override - protected Properties defaultProperties() { - Properties properties = super.defaultProperties(); - properties.setProperty(PROPERTY_ENDPOINT, "YOU_MUST_SET_" + PROPERTY_ENDPOINT); - properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*"); - return properties; - } +public class NovaComputeServiceContextModule extends BaseComputeServiceContextModule { - public NovaEC2PropertiesBuilder(Properties properties) { - super(properties); + @Override + protected void configure() { + install(new NovaComputeServiceDependenciesModule()); + install(new NovaBindComputeStrategiesByClass()); + install(new NovaBindComputeSuppliersByClass()); + super.configure(); } } diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceDependenciesModule.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceDependenciesModule.java new file mode 100644 index 0000000000..c750ebbff5 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceDependenciesModule.java @@ -0,0 +1,117 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.config; + +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.openstack.nova.NovaAsyncClient; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.compute.functions.NovaImageToImage; +import org.jclouds.openstack.nova.compute.functions.NovaImageToOperatingSystem; +import org.jclouds.openstack.nova.compute.functions.FlavorToHardware; +import org.jclouds.openstack.nova.compute.functions.ServerToNodeMetadata; +import org.jclouds.openstack.nova.domain.Flavor; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.internal.BaseComputeService; +import org.jclouds.compute.internal.ComputeServiceContextImpl; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.internal.RestContextImpl; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Scopes; +import com.google.inject.TypeLiteral; + +/** + * Configures the {@link NovaComputeServiceContext}; requires {@link BaseComputeService} + * bound. + * + * @author Adrian Cole + */ +public class NovaComputeServiceDependenciesModule extends AbstractModule { + + @Override + protected void configure() { + bind(new TypeLiteral>() { + }).to(ServerToNodeMetadata.class); + + bind(new TypeLiteral>() { + }).to(NovaImageToImage.class); + + bind(new TypeLiteral>() { + }).to(NovaImageToOperatingSystem.class); + + bind(new TypeLiteral>() { + }).to(FlavorToHardware.class); + + bind(new TypeLiteral() { + }).to(new TypeLiteral>() { + }).in(Scopes.SINGLETON); + bind(new TypeLiteral>() { + }).to(new TypeLiteral>() { + }).in(Scopes.SINGLETON); + } + + @VisibleForTesting + public static final Map serverToNodeState = ImmutableMap + . builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)// + .put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)// + .put(ServerStatus.DELETED, NodeState.TERMINATED)// + .put(ServerStatus.QUEUE_RESIZE, NodeState.PENDING)// + .put(ServerStatus.PREP_RESIZE, NodeState.PENDING)// + .put(ServerStatus.RESIZE, NodeState.PENDING)// + .put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)// + .put(ServerStatus.QUEUE_MOVE, NodeState.PENDING)// + .put(ServerStatus.PREP_MOVE, NodeState.PENDING)// + .put(ServerStatus.MOVE, NodeState.PENDING)// + .put(ServerStatus.VERIFY_MOVE, NodeState.PENDING)// + .put(ServerStatus.RESCUE, NodeState.PENDING)// + .put(ServerStatus.ERROR, NodeState.ERROR)// + .put(ServerStatus.BUILD, NodeState.PENDING)// + .put(ServerStatus.RESTORING, NodeState.PENDING)// + .put(ServerStatus.PASSWORD, NodeState.PENDING)// + .put(ServerStatus.REBUILD, NodeState.PENDING)// + .put(ServerStatus.DELETE_IP, NodeState.PENDING)// + .put(ServerStatus.SHARE_IP_NO_CONFIG, NodeState.PENDING)// + .put(ServerStatus.SHARE_IP, NodeState.PENDING)// + .put(ServerStatus.REBOOT, NodeState.PENDING)// + .put(ServerStatus.HARD_REBOOT, NodeState.PENDING)// + .put(ServerStatus.UNKNOWN, NodeState.UNRECOGNIZED)// + .put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED).build(); + + @Singleton + @Provides + Map provideServerToNodeState() { + return serverToNodeState; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardware.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardware.java new file mode 100644 index 0000000000..7e7b340899 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardware.java @@ -0,0 +1,44 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.functions; + +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.openstack.nova.domain.Flavor; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; + +/** + * @author Adrian Cole + */ +@Singleton +public class FlavorToHardware implements Function { + public Hardware apply(Flavor from) { + return new HardwareBuilder().ids(from.getId() + "").name(from.getName()) + .processors(ImmutableList.of(new Processor(from.getDisk() / 10.0, 1.0))).ram(from.getRam()) + .volumes(ImmutableList. of(new VolumeImpl((float) from.getDisk(), true, true))).build(); + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImage.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImage.java new file mode 100644 index 0000000000..1cfdf0ac4c --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImage.java @@ -0,0 +1,56 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.functions; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.domain.Credentials; + +import com.google.common.base.Function; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class NovaImageToImage implements Function { + private final Function imageToOs; + + @Inject + NovaImageToImage(Function imageToOs) { + this.imageToOs = imageToOs; + } + + public Image apply(org.jclouds.openstack.nova.domain.Image from) { + ImageBuilder builder = new ImageBuilder(); + builder.ids(from.getId() + ""); + builder.name(from.getName()); + builder.description(from.getName()); + builder.version(from.getUpdated().getTime() + ""); + builder.operatingSystem(imageToOs.apply(from)); + builder.defaultCredentials(new Credentials("root", null)); + Image image = builder.build(); + return image; + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToOperatingSystem.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToOperatingSystem.java new file mode 100644 index 0000000000..82d2530182 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/NovaImageToOperatingSystem.java @@ -0,0 +1,92 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.functions; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.compute.util.ComputeServiceUtils; +import org.jclouds.logging.Logger; + +import com.google.common.base.Function; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class NovaImageToOperatingSystem implements + Function { + public static final Pattern DEFAULT_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)"); + // Windows Server 2008 R2 x64 + public static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows (.*) (x[86][64])"); + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final Map> osVersionMap; + + @Inject + public NovaImageToOperatingSystem(Map> osVersionMap) { + this.osVersionMap = osVersionMap; + } + + public OperatingSystem apply(final org.jclouds.openstack.nova.domain.Image from) { + OsFamily osFamily = null; + String osName = null; + String osArch = null; + String osVersion = null; + String osDescription = from.getName(); + boolean is64Bit = true; + if (from.getName().indexOf("Red Hat EL") != -1) { + osFamily = OsFamily.RHEL; + } else if (from.getName().indexOf("Oracle EL") != -1) { + osFamily = OsFamily.OEL; + } else if (from.getName().indexOf("Windows") != -1) { + osFamily = OsFamily.WINDOWS; + Matcher matcher = WINDOWS_PATTERN.matcher(from.getName()); + if (matcher.find()) { + osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(1), osVersionMap); + is64Bit = matcher.group(2).equals("x64"); + } + } else { + Matcher matcher = DEFAULT_PATTERN.matcher(from.getName()); + if (matcher.find()) { + try { + osFamily = OsFamily.fromValue(matcher.group(2).toLowerCase()); + } catch (IllegalArgumentException e) { + logger.debug("<< didn't match os(%s)", matcher.group(2)); + } + osVersion = ComputeServiceUtils.parseVersionOrReturnEmptyString(osFamily, matcher.group(3), osVersionMap); + } + } + return new OperatingSystem(osFamily, osName, osVersion, osArch, osDescription, is64Bit); + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadata.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadata.java new file mode 100644 index 0000000000..30dcfcef1d --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadata.java @@ -0,0 +1,143 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName; + +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.jclouds.logging.Logger; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class ServerToNodeMetadata implements Function { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + protected final Supplier location; + protected final Map credentialStore; + protected final Map serverToNodeState; + protected final Supplier> images; + protected final Supplier> hardwares; + + private static class FindImageForServer implements Predicate { + private final Server instance; + + private FindImageForServer(Server instance) { + this.instance = instance; + } + + @Override + public boolean apply(Image input) { + return input.getProviderId().equals(instance.getImageId() + ""); + } + } + + private static class FindHardwareForServer implements Predicate { + private final Server instance; + + private FindHardwareForServer(Server instance) { + this.instance = instance; + } + + @Override + public boolean apply(Hardware input) { + return input.getProviderId().equals(instance.getFlavorId() + ""); + } + } + + @Inject + ServerToNodeMetadata(Map serverStateToNodeState, Map credentialStore, + @Memoized Supplier> images, Supplier location, + @Memoized Supplier> hardwares) { + this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState"); + this.credentialStore = checkNotNull(credentialStore, "credentialStore"); + this.images = checkNotNull(images, "images"); + this.location = checkNotNull(location, "location"); + this.hardwares = checkNotNull(hardwares, "hardwares"); + } + + @Override + public NodeMetadata apply(Server from) { + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + builder.ids(from.getId() + ""); + builder.name(from.getName()); + builder.location(new LocationBuilder().scope(LocationScope.HOST).id(from.getHostId()).description( + from.getHostId()).parent(location.get()).build()); + builder.userMetadata(from.getMetadata()); + builder.group(parseGroupFromName(from.getName())); + builder.imageId(from.getImageId() + ""); + builder.operatingSystem(parseOperatingSystem(from)); + builder.hardware(parseHardware(from)); + builder.state(serverToNodeState.get(from.getStatus())); + builder.publicAddresses(from.getAddresses().getPublicAddresses()); + builder.privateAddresses(from.getAddresses().getPrivateAddresses()); + builder.credentials(credentialStore.get("node#" + from.getId())); + return builder.build(); + } + + protected Hardware parseHardware(Server from) { + try { + return Iterables.find(hardwares.get(), new FindHardwareForServer(from)); + } catch (NoSuchElementException e) { + logger.warn("could not find a matching hardware for server %s", from); + } + return null; + } + + protected OperatingSystem parseOperatingSystem(Server from) { + try { + return Iterables.find(images.get(), new FindImageForServer(from)).getOperatingSystem(); + } catch (NoSuchElementException e) { + logger.warn("could not find a matching image for server %s in location %s", from, location); + } + return null; + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaCreateNodeWithGroupEncodedIntoName.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaCreateNodeWithGroupEncodedIntoName.java new file mode 100644 index 0000000000..72ce4ed5b2 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaCreateNodeWithGroupEncodedIntoName.java @@ -0,0 +1,63 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.strategy; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName; +import org.jclouds.domain.Credentials; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.domain.Server; + +import com.google.common.base.Function; + +/** + * @author Adrian Cole + */ +@Singleton +public class NovaCreateNodeWithGroupEncodedIntoName implements CreateNodeWithGroupEncodedIntoName { + protected final NovaClient client; + protected final Map credentialStore; + protected final Function serverToNodeMetadata; + + @Inject + protected NovaCreateNodeWithGroupEncodedIntoName(NovaClient client, Map credentialStore, + Function serverToNodeMetadata) { + this.client = checkNotNull(client, "client"); + this.credentialStore = checkNotNull(credentialStore, "credentialStore"); + this.serverToNodeMetadata = checkNotNull(serverToNodeMetadata, "serverToNodeMetadata"); + } + + @Override + public NodeMetadata createNodeWithGroupEncodedIntoName(String group, String name, Template template) { + Server from = client.createServer(name, Integer.parseInt(template.getImage().getProviderId()), Integer + .parseInt(template.getHardware().getProviderId())); + credentialStore.put("node#" + from.getId(), new Credentials("root", from.getAdminPass())); + return serverToNodeMetadata.apply(from); + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaDestroyNodeStrategy.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaDestroyNodeStrategy.java new file mode 100644 index 0000000000..456f72eb52 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaDestroyNodeStrategy.java @@ -0,0 +1,52 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.strategy; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.strategy.DestroyNodeStrategy; +import org.jclouds.compute.strategy.GetNodeMetadataStrategy; +import org.jclouds.openstack.nova.NovaClient; + +/** + * @author Adrian Cole + */ +@Singleton +public class NovaDestroyNodeStrategy implements DestroyNodeStrategy { + private final NovaClient client; + private final GetNodeMetadataStrategy getNode; + + @Inject + protected NovaDestroyNodeStrategy(NovaClient client, GetNodeMetadataStrategy getNode) { + this.client = client; + this.getNode = getNode; + } + + @Override + public NodeMetadata destroyNode(String id) { + int serverId = Integer.parseInt(id); + // if false server wasn't around in the first place + client.deleteServer(serverId); + return getNode.getNode(id); + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaGetNodeMetadataStrategy.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaGetNodeMetadataStrategy.java new file mode 100644 index 0000000000..c551938696 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaGetNodeMetadataStrategy.java @@ -0,0 +1,54 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.strategy; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.strategy.GetNodeMetadataStrategy; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.domain.Server; + +import com.google.common.base.Function; + +/** + * @author Adrian Cole + */ +@Singleton +public class NovaGetNodeMetadataStrategy implements GetNodeMetadataStrategy { + + private final NovaClient client; + private final Function serverToNodeMetadata; + + @Inject + protected NovaGetNodeMetadataStrategy(NovaClient client, + Function serverToNodeMetadata) { + this.client = client; + this.serverToNodeMetadata = serverToNodeMetadata; + } + + @Override + public NodeMetadata getNode(String id) { + int serverId = Integer.parseInt(id); + Server server = client.getServer(serverId); + return server == null ? null : serverToNodeMetadata.apply(server); + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaLifeCycleStrategy.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaLifeCycleStrategy.java new file mode 100644 index 0000000000..ccbcba6e37 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaLifeCycleStrategy.java @@ -0,0 +1,65 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.strategy; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.strategy.GetNodeMetadataStrategy; +import org.jclouds.compute.strategy.RebootNodeStrategy; +import org.jclouds.compute.strategy.ResumeNodeStrategy; +import org.jclouds.compute.strategy.SuspendNodeStrategy; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.domain.RebootType; + +/** + * @author Adrian Cole + */ +@Singleton +public class NovaLifeCycleStrategy implements RebootNodeStrategy, SuspendNodeStrategy, ResumeNodeStrategy { + private final NovaClient client; + private final GetNodeMetadataStrategy getNode; + + @Inject + protected NovaLifeCycleStrategy(NovaClient client, GetNodeMetadataStrategy getNode) { + this.client = client; + this.getNode = getNode; + } + + @Override + public NodeMetadata rebootNode(String id) { + int serverId = Integer.parseInt(id); + // if false server wasn't around in the first place + client.rebootServer(serverId, RebootType.HARD); + return getNode.getNode(id); + } + + @Override + public NodeMetadata suspendNode(String id) { + throw new UnsupportedOperationException("suspend not supported"); + } + + @Override + public NodeMetadata resumeNode(String id) { + throw new UnsupportedOperationException("resume not supported"); + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaListNodesStrategy.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaListNodesStrategy.java new file mode 100644 index 0000000000..220147c3d0 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaListNodesStrategy.java @@ -0,0 +1,62 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.strategy; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.ComputeMetadata; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.predicates.NodePredicates; +import org.jclouds.compute.strategy.ListNodesStrategy; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.options.ListOptions; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class NovaListNodesStrategy implements ListNodesStrategy { + private final NovaClient client; + private final Function serverToNodeMetadata; + + @Inject + protected NovaListNodesStrategy(NovaClient client, + Function serverToNodeMetadata) { + this.client = client; + this.serverToNodeMetadata = serverToNodeMetadata; + } + + @Override + public Iterable listNodes() { + return listDetailsOnNodesMatching(NodePredicates.all()); + } + + @Override + public Iterable listDetailsOnNodesMatching(Predicate filter) { + return Iterables.filter(Iterables.transform(client.listServers(ListOptions.Builder.withDetails()), + serverToNodeMetadata), filter); + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaHardwareSupplier.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaHardwareSupplier.java new file mode 100644 index 0000000000..0058669e7f --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaHardwareSupplier.java @@ -0,0 +1,68 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.suppliers; + +import static org.jclouds.openstack.nova.options.ListOptions.Builder.withDetails; + +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.domain.Flavor; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class NovaHardwareSupplier implements Supplier> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + private final NovaClient sync; + private final Function flavorToHardware; + + @Inject + NovaHardwareSupplier(NovaClient sync, Function flavorToHardware) { + this.sync = sync; + this.flavorToHardware = flavorToHardware; + } + + @Override + public Set get() { + final Set hardware; + logger.debug(">> providing hardware"); + hardware = Sets.newLinkedHashSet(Iterables.transform(sync.listFlavors(withDetails()), flavorToHardware)); + logger.debug("<< hardware(%d)", hardware.size()); + return hardware; + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaImageSupplier.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaImageSupplier.java new file mode 100644 index 0000000000..9ad9af1c44 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/compute/suppliers/NovaImageSupplier.java @@ -0,0 +1,71 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.suppliers; + +import static org.jclouds.openstack.nova.options.ListOptions.Builder.withDetails; + +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.openstack.nova.NovaClient; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class NovaImageSupplier implements Supplier> { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + protected final NovaClient sync; + protected final Function cloudServersImageToImage; + + @Inject + NovaImageSupplier(NovaClient sync, + Function cloudServersImageToImage) { + this.sync = sync; + this.cloudServersImageToImage = cloudServersImageToImage; + } + + @Override + public Set get() { + Set images; + logger.debug(">> providing images"); + images = Sets. newLinkedHashSet(Iterables.transform(sync.listImages(withDetails()), + cloudServersImageToImage)); + logger.debug("<< images(%d)", images.size()); + return images; + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java new file mode 100644 index 0000000000..c2180aa290 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java @@ -0,0 +1,85 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.config; + +import java.net.URI; + +import javax.inject.Singleton; + +import org.jclouds.openstack.nova.NovaAsyncClient; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.ServerManagement; +import org.jclouds.openstack.nova.handlers.ParseNovaErrorFromHttpResponse; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.json.config.GsonModule.DateAdapter; +import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; +import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; +import org.jclouds.openstack.config.OpenStackAuthenticationModule; +import org.jclouds.openstack.reference.AuthHeaders; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +import com.google.inject.Provides; + +/** + * + * @author Adrian Cole + */ +@ConfiguresRestClient +@RequiresHttp +public class NovaRestClientModule extends RestClientModule { + + private final OpenStackAuthenticationModule module; + + public NovaRestClientModule(OpenStackAuthenticationModule module) { + super(NovaClient.class, NovaAsyncClient.class); + this.module = module; + } + + public NovaRestClientModule() { + this(new OpenStackAuthenticationModule()); + } + + @Override + protected void configure() { + install(module); + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseNovaErrorFromHttpResponse.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseNovaErrorFromHttpResponse.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseNovaErrorFromHttpResponse.class); + } + + @Provides + @Singleton + @ServerManagement + protected URI provideServerUrl(AuthenticationResponse response) { + return response.getServices().get(AuthHeaders.SERVER_MANAGEMENT_URL); + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/AbsoluteLimit.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/AbsoluteLimit.java new file mode 100644 index 0000000000..c6f6cbcba1 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/AbsoluteLimit.java @@ -0,0 +1,48 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + + +/** + * + * @author Adrian Cole + */ +public class AbsoluteLimit { + + protected String name; + protected int value; + + public String getName() { + return name; + } + + public void setName(String value) { + this.name = value; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Action.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Action.java new file mode 100644 index 0000000000..cc35bb68fe --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Action.java @@ -0,0 +1,28 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +/** + * + * @author Adrian Cole + */ +public enum Action { + CONFIRM_RESIZE, REBOOT, REBUILD, RESIZE, REVERT_RESIZE +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Addresses.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Addresses.java new file mode 100644 index 0000000000..bf80d79b8a --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Addresses.java @@ -0,0 +1,99 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +import java.util.Set; + +import com.google.common.collect.Sets; +import com.google.gson.annotations.SerializedName; + +/** + * + * @author Adrian Cole + */ +public class Addresses { + + @SerializedName("public") + private Set publicAddresses = Sets.newLinkedHashSet(); + @SerializedName("private") + private Set privateAddresses = Sets.newLinkedHashSet(); + + public Addresses() { + } + + public Addresses(Set publicAddresses, Set privateAddresses) { + this.publicAddresses = publicAddresses; + this.privateAddresses = privateAddresses; + } + + public void setPublicAddresses(Set publicAddresses) { + this.publicAddresses = publicAddresses; + } + + public Set getPublicAddresses() { + return publicAddresses; + } + + public void setPrivateAddresses(Set privateAddresses) { + this.privateAddresses = privateAddresses; + } + + public Set getPrivateAddresses() { + return privateAddresses; + } + + @Override + public String toString() { + return "Addresses [privateAddresses=" + privateAddresses + ", publicAddresses=" + + publicAddresses + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((privateAddresses == null) ? 0 : privateAddresses.hashCode()); + result = prime * result + ((publicAddresses == null) ? 0 : publicAddresses.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Addresses other = (Addresses) obj; + if (privateAddresses == null) { + if (other.privateAddresses != null) + return false; + } else if (!privateAddresses.equals(other.privateAddresses)) + return false; + if (publicAddresses == null) { + if (other.publicAddresses != null) + return false; + } else if (!publicAddresses.equals(other.publicAddresses)) + return false; + return true; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/BackupSchedule.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/BackupSchedule.java new file mode 100644 index 0000000000..af9d2a5471 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/BackupSchedule.java @@ -0,0 +1,105 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +/** + * A backup schedule can be defined to create server images at regular intervals (daily and weekly). + * Backup schedules are configurable per server. + * + * @author Adrian Cole + */ +public class BackupSchedule { + protected DailyBackup daily = DailyBackup.DISABLED; + protected boolean enabled; + protected WeeklyBackup weekly = WeeklyBackup.DISABLED; + + public BackupSchedule() { + } + + public BackupSchedule(WeeklyBackup weekly, DailyBackup daily, boolean enabled) { + this.weekly = weekly; + this.daily = daily; + this.enabled = enabled; + } + + public DailyBackup getDaily() { + return daily; + } + + public void setDaily(DailyBackup value) { + this.daily = value; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean value) { + this.enabled = value; + } + + public WeeklyBackup getWeekly() { + return weekly; + } + + public void setWeekly(WeeklyBackup value) { + this.weekly = value; + } + + @Override + public String toString() { + return "[daily=" + daily + ", enabled=" + enabled + ", weekly=" + weekly + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((daily == null) ? 0 : daily.hashCode()); + result = prime * result + (enabled ? 1231 : 1237); + result = prime * result + ((weekly == null) ? 0 : weekly.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BackupSchedule other = (BackupSchedule) obj; + if (daily == null) { + if (other.daily != null) + return false; + } else if (!daily.equals(other.daily)) + return false; + if (enabled != other.enabled) + return false; + if (weekly == null) { + if (other.weekly != null) + return false; + } else if (!weekly.equals(other.weekly)) + return false; + return true; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/DailyBackup.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/DailyBackup.java new file mode 100644 index 0000000000..6841aca96c --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/DailyBackup.java @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +public enum DailyBackup { + + DISABLED, H_0000_0200, H_0200_0400, H_0400_0600, H_0600_0800, H_0800_1000, H_1000_1200, H_1200_1400, H_1400_1600, H_1600_1800, H_1800_2000, H_2000_2200, H_2200_0000, UNRECOGNIZED; + + public String value() { + return name(); + } + + public static DailyBackup fromValue(String v) { + try { + return valueOf(v); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java new file mode 100644 index 0000000000..9fe432f94c --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java @@ -0,0 +1,121 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +/** + * + * A flavor is an available hardware configuration for a server. Each flavor has a unique + * combination of disk space and memory capacity. + * + * @author Adrian Cole + */ +public class Flavor { + + public Flavor() { + } + + @Override + public String toString() { + return "Flavor [disk=" + disk + ", id=" + id + ", name=" + name + ", ram=" + ram + "]"; + } + + public Flavor(int id, String name) { + this.id = id; + this.name = name; + } + + private int id; + private String name; + private Integer disk; + private Integer ram; + + public Integer getDisk() { + return disk; + } + + public void setDisk(Integer value) { + this.disk = value; + } + + public int getId() { + return id; + } + + public void setId(int value) { + this.id = value; + } + + public String getName() { + return name; + } + + public void setName(String value) { + this.name = value; + } + + public Integer getRam() { + return ram; + } + + public void setRam(Integer value) { + this.ram = value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((disk == null) ? 0 : disk.hashCode()); + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((ram == null) ? 0 : ram.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Flavor other = (Flavor) obj; + if (disk == null) { + if (other.disk != null) + return false; + } else if (!disk.equals(other.disk)) + return false; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (ram == null) { + if (other.ram != null) + return false; + } else if (!ram.equals(other.ram)) + return false; + return true; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Image.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Image.java new file mode 100644 index 0000000000..adec2fa857 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Image.java @@ -0,0 +1,146 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +import java.util.Date; + +/** + * An image is a collection of files used to create or rebuild a server. Rackspace provides a number + * of pre-built OS images by default. You may also create custom images from cloud servers you have + * launched. These custom images are useful for backup purposes or for producing gold server images + * if you plan to deploy a particular server configuration frequently. + * + * @author Adrian Cole + */ +public class Image { + + private Date created; + private int id; + private String name; + private Integer progress; + private Integer serverId; + private ImageStatus status; + private Date updated; + + public Image() { + } + + public Image(int id, String name) { + this.id = id; + this.name = name; + } + + public void setCreated(Date created) { + this.created = created; + } + + public Date getCreated() { + return created; + } + + public void setId(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setProgress(Integer progress) { + this.progress = progress; + } + + public Integer getProgress() { + return progress; + } + + public void setServerId(Integer serverId) { + this.serverId = serverId; + } + + public Integer getServerId() { + return serverId; + } + + public void setStatus(ImageStatus status) { + this.status = status; + } + + public ImageStatus getStatus() { + return status; + } + + public void setUpdated(Date updated) { + this.updated = updated; + } + + public Date getUpdated() { + return updated; + } + /** + * note that this ignores the create time + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((serverId == null) ? 0 : serverId.hashCode()); + return result; + } + + /** + * note that this ignores the serverid and create time. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Image other = (Image) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + return "Image [created=" + created + ", id=" + id + ", name=" + name + ", serverId=" + + serverId + "]"; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ImageStatus.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ImageStatus.java new file mode 100644 index 0000000000..2ee482f263 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ImageStatus.java @@ -0,0 +1,46 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +/** + * In-flight images will have the status attribute set to SAVING and the conditional progress + * element (0- 100% completion) will also be returned. Other possible values for the status + * attribute include: UNKNOWN, PREPARING, ACTIVE QUEUED, FAILED. Images with an ACTIVE status are + * available for install. + * + * @author Adrian Cole + */ +public enum ImageStatus { + + UNRECOGNIZED, UNKNOWN, ACTIVE, SAVING, PREPARING, QUEUED, FAILED; + + public String value() { + return name(); + } + + public static ImageStatus fromValue(String v) { + try { + return valueOf(v); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Limits.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Limits.java new file mode 100644 index 0000000000..c56eb7ea62 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Limits.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +import java.util.List; + +import com.google.common.collect.Lists; + +public class Limits { + + private List rate = Lists.newArrayList(); + private List absolute = Lists.newArrayList(); + + public void setRate(List rate) { + this.rate = rate; + } + + public List getRate() { + return rate; + } + + public void setAbsolute(List absolute) { + this.absolute = absolute; + } + + public List getAbsolute() { + return absolute; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimit.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimit.java new file mode 100644 index 0000000000..bb936e4d57 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimit.java @@ -0,0 +1,90 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +import javax.ws.rs.HttpMethod; + +/** + * + * RateLimit. + *

+ * we specify rate limits in terms of both a human readable wild-card URI and a machine processable + * regular expression. The regular expression boundary matcher '^' takes affect after the root URI + * path. For example, the regular expression ^/servers would match the bolded portion of the + * following URI: https://servers.api.rackspacecloud.com/v1.0/3542812 /servers . + *

+ * Rate limits are applied in order relative to the verb, going from least to most specific. For + * example, although the threshold for POST to /servers is 25 per day, one cannot POST to /servers + * more than 10 times within a single minute because the rate limits for any POST is 10/min. In the + * event you exceed the thresholds established for your identity, a 413 Rate Control HTTP response + * will be returned with a Reply-After header to notify the client when theyagain. + * + * @author Adrian Cole + */ +public class RateLimit { + + private final String uri; + private final String regex; + private final int remaining; + private final long resetTime; + private final RateLimitUnit unit; + private final int value; + private final HttpMethod verb; + + public RateLimit(String uri, String regex, int remaining, long resetTime, RateLimitUnit unit, + int value, HttpMethod verb) { + this.uri = uri; + this.regex = regex; + this.remaining = remaining; + this.resetTime = resetTime; + this.unit = unit; + this.value = value; + this.verb = verb; + } + + public String getUri() { + return uri; + } + + public String getRegex() { + return regex; + } + + public int getRemaining() { + return remaining; + } + + public long getResetTime() { + return resetTime; + } + + public RateLimitUnit getUnit() { + return unit; + } + + public int getValue() { + return value; + } + + public HttpMethod getVerb() { + return verb; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimitUnit.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimitUnit.java new file mode 100644 index 0000000000..4cb1fde521 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RateLimitUnit.java @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +public enum RateLimitUnit { + + MINUTE, HOUR, DAY, UNRECOGNIZED; + + public String value() { + return name(); + } + + public static RateLimitUnit fromValue(String v) { + try { + return valueOf(v); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RebootType.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RebootType.java new file mode 100644 index 0000000000..6fc7c2d88d --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/RebootType.java @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +/** + * + * @author Adrian Cole + */ +public enum RebootType { + + HARD, SOFT; + + public String value() { + return name(); + } + + public static RebootType fromValue(String v) { + return valueOf(v); + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Server.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Server.java new file mode 100644 index 0000000000..a86e45a4fa --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Server.java @@ -0,0 +1,230 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +import java.util.Map; + +import com.google.common.collect.Maps; + +/** + * A server is a virtual machine instance in the OpenStack Nova system. Flavor and image are + * requisite elements when creating a server. + * + * @author Adrian Cole + */ +public class Server { + private int id; + private String name; + + private Map metadata = Maps.newHashMap(); + + private Addresses addresses; + private String adminPass; + private Integer flavorId; + private String hostId; + private Integer imageId; + private Integer sharedIpGroupId; + + private Integer progress; + private ServerStatus status; + + public Server() { + } + + public Server(int id, String name) { + this.id = id; + this.name = name; + } + + public void setMetadata(Map metadata) { + this.metadata = metadata; + } + + public Map getMetadata() { + return metadata; + } + + public void setAddresses(Addresses addresses) { + this.addresses = addresses; + } + + public Addresses getAddresses() { + return addresses; + } + + public void setAdminPass(String adminPass) { + this.adminPass = adminPass; + } + + public String getAdminPass() { + return adminPass; + } + + public void setFlavorId(Integer flavorId) { + this.flavorId = flavorId; + } + + public Integer getFlavorId() { + return flavorId; + } + + public void setHostId(String hostId) { + this.hostId = hostId; + } + + /** + * The OpenStack Nova provisioning algorithm has an anti-affinity property that attempts to spread + * out customer VMs across hosts. Under certain situations, VMs from the same customer may be + * placed on the same host. hostId represents the host your cloud server runs on and can be used + * to determine this scenario if it's relevant to your application. + *

+ * Note: hostId is unique PER ACCOUNT and is not globally unique. + */ + public String getHostId() { + return hostId; + } + + public int getId() { + return id; + } + + public void setImageId(Integer imageId) { + this.imageId = imageId; + } + + public Integer getImageId() { + return imageId; + } + + public String getName() { + return name; + } + + public void setProgress(Integer progress) { + this.progress = progress; + } + + public Integer getProgress() { + return progress; + } + + public void setSharedIpGroupId(Integer sharedIpGroupId) { + this.sharedIpGroupId = sharedIpGroupId; + } + + public Integer getSharedIpGroupId() { + return sharedIpGroupId; + } + + public void setStatus(ServerStatus status) { + this.status = status; + } + + /** + * Servers contain a status attribute that can be used as an indication of the current server + * state. Servers with an ACTIVE status are available for use. + */ + public ServerStatus getStatus() { + return status; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((addresses == null) ? 0 : addresses.hashCode()); + result = prime * result + ((adminPass == null) ? 0 : adminPass.hashCode()); + result = prime * result + ((flavorId == null) ? 0 : flavorId.hashCode()); + result = prime * result + ((hostId == null) ? 0 : hostId.hashCode()); + result = prime * result + id; + result = prime * result + ((imageId == null) ? 0 : imageId.hashCode()); + result = prime * result + ((metadata == null) ? 0 : metadata.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((sharedIpGroupId == null) ? 0 : sharedIpGroupId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Server other = (Server) obj; + if (addresses == null) { + if (other.addresses != null) + return false; + } else if (!addresses.equals(other.addresses)) + return false; + if (adminPass == null) { + if (other.adminPass != null) + return false; + } else if (!adminPass.equals(other.adminPass)) + return false; + if (flavorId == null) { + if (other.flavorId != null) + return false; + } else if (!flavorId.equals(other.flavorId)) + return false; + if (hostId == null) { + if (other.hostId != null) + return false; + } else if (!hostId.equals(other.hostId)) + return false; + if (id != other.id) + return false; + if (imageId == null) { + if (other.imageId != null) + return false; + } else if (!imageId.equals(other.imageId)) + return false; + if (metadata == null) { + if (other.metadata != null) + return false; + } else if (!metadata.equals(other.metadata)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (sharedIpGroupId == null) { + if (other.sharedIpGroupId != null) + return false; + } else if (!sharedIpGroupId.equals(other.sharedIpGroupId)) + return false; + return true; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Server [addresses=" + addresses + ", adminPass=" + adminPass + ", flavorId=" + + flavorId + ", hostId=" + hostId + ", id=" + id + ", imageId=" + imageId + + ", metadata=" + metadata + ", name=" + name + ", sharedIpGroupId=" + + sharedIpGroupId + "]"; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ServerStatus.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ServerStatus.java new file mode 100644 index 0000000000..b7bae0170f --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ServerStatus.java @@ -0,0 +1,55 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +/** + * + * Servers contain a status attribute that can be used as an indication of the current server state. + * Servers with an ACTIVE status are available for use. + *

+ *

Note

+ * When the system changes a server's status from BUILD to ACTIVE the system will not be immediately + * available. The 'ACTIVE' label is really misleading in the fact that it just means the system + * doesn't have any activity going on related to it's configuration. + *

+ * Processes such as ssh will not be available until 5-10 seconds following the phase ACTIVE + *

    + *
  • [Web Hosting #119335]
  • + *
+ * + * @author Adrian Cole + */ +public enum ServerStatus { + + ACTIVE, SUSPENDED, DELETED, QUEUE_RESIZE, PREP_RESIZE, RESIZE, VERIFY_RESIZE, QUEUE_MOVE, PREP_MOVE, MOVE, VERIFY_MOVE, RESCUE, ERROR, BUILD, RESTORING, PASSWORD, REBUILD, DELETE_IP, SHARE_IP_NO_CONFIG, SHARE_IP, REBOOT, HARD_REBOOT, UNKNOWN, UNRECOGNIZED; + + public String value() { + return name(); + } + + public static ServerStatus fromValue(String v) { + try { + return valueOf(v); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ShareIp.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ShareIp.java new file mode 100644 index 0000000000..856d6539e6 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/ShareIp.java @@ -0,0 +1,43 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +public class ShareIp { + + private boolean configureServer; + private int sharedIpGroupId; + + public void setConfigureServer(boolean configureServer) { + this.configureServer = configureServer; + } + + public boolean isConfigureServer() { + return configureServer; + } + + public void setSharedIpGroupId(int sharedIpGroupId) { + this.sharedIpGroupId = sharedIpGroupId; + } + + public int getSharedIpGroupId() { + return sharedIpGroupId; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/SharedIpGroup.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/SharedIpGroup.java new file mode 100644 index 0000000000..5b3c9b280c --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/SharedIpGroup.java @@ -0,0 +1,112 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +import java.util.List; + +import com.google.common.collect.Lists; + +/** + * A shared IP group is a collection of servers that can share IPs with other members of the group. + * Any server in a group can share one or more public IPs with any other server in the group. With + * the exception of the first server in a shared IP group, servers must be launched into shared IP + * groups. A server may only be a member of one shared IP group. + * + * @author Adrian Cole + */ +public class SharedIpGroup { + + private int id; + private String name; + + private List servers = Lists.newArrayList(); + + public SharedIpGroup() { + } + + public SharedIpGroup(int id, String name) { + this.id = id; + this.name = name; + } + + public void setId(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setServers(List servers) { + this.servers = servers; + } + + public List getServers() { + return servers; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((servers == null) ? 0 : servers.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SharedIpGroup other = (SharedIpGroup) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (servers == null) { + if (other.servers != null) + return false; + } else if (!servers.equals(other.servers)) + return false; + return true; + } + + @Override + public String toString() { + return "SharedIpGroup [id=" + id + ", name=" + name + ", servers=" + servers + "]"; + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Version.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Version.java new file mode 100644 index 0000000000..d085078688 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Version.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +public class Version { + + private String docURL; + private String id = "v1.0"; + private VersionStatus status; + private String wadl; + + public void setDocURL(String docURL) { + this.docURL = docURL; + } + + public String getDocURL() { + return docURL; + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setStatus(VersionStatus status) { + this.status = status; + } + + public VersionStatus getStatus() { + return status; + } + + public void setWadl(String wadl) { + this.wadl = wadl; + } + + public String getWadl() { + return wadl; + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/VersionStatus.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/VersionStatus.java new file mode 100644 index 0000000000..3eecc8afc3 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/VersionStatus.java @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +public enum VersionStatus { + + BETA, CURRENT, DEPRECATED, UNRECOGNIZED; + + public String value() { + return name(); + } + + public static VersionStatus fromValue(String v) { + try { + return valueOf(v); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/WeeklyBackup.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/WeeklyBackup.java new file mode 100644 index 0000000000..7209c6c5c7 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/domain/WeeklyBackup.java @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +public enum WeeklyBackup { + + DISABLED, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, UNRECOGNIZED; + + public String value() { + return name(); + } + + public static WeeklyBackup fromValue(String v) { + try { + return valueOf(v); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/handlers/ParseNovaErrorFromHttpResponse.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/handlers/ParseNovaErrorFromHttpResponse.java new file mode 100644 index 0000000000..cc08488b50 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/handlers/ParseNovaErrorFromHttpResponse.java @@ -0,0 +1,96 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.handlers; + +import static org.jclouds.http.HttpUtils.releasePayload; + +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Resource; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Strings2; + +/** + * This will parse and set an appropriate exception on the command object. + * + * @author Adrian Cole + * + */ +public class ParseNovaErrorFromHttpResponse implements HttpErrorHandler { + @Resource + protected Logger logger = Logger.NULL; + public static final Pattern RESOURCE_PATTERN = Pattern + .compile("^/v1[^/]*/[0-9]+/([^/]+)/([0-9]+)"); + + public void handleError(HttpCommand command, HttpResponse response) { + Exception exception = new HttpResponseException(command, response); + try { + String content = parseErrorFromContentOrNull(command, response); + exception = content != null ? new HttpResponseException(command, response, content) : exception; + switch (response.getStatusCode()) { + case 401: + exception = new AuthorizationException(exception.getMessage(), exception); + break; + case 404: + if (!command.getCurrentRequest().getMethod().equals("DELETE")) { + String path = command.getCurrentRequest().getEndpoint().getPath(); + Matcher matcher = RESOURCE_PATTERN.matcher(path); + String message; + if (matcher.find()) { + message = String.format("%s %s not found", matcher.group(1), matcher.group(2)); + } else { + message = path; + } + exception = new ResourceNotFoundException(message); + } + break; + case 409: + exception = new IllegalStateException(content); + break; + default: + exception = new HttpResponseException(command, response, content); + break; + } + } finally { + releasePayload(response); + command.setException(exception); + } + } + + String parseErrorFromContentOrNull(HttpCommand command, HttpResponse response) { + if (response.getPayload() != null) { + try { + return Strings2.toStringAndClose(response.getPayload().getInput()); + } catch (IOException e) { + logger.warn(e, "exception reading error from response", response); + } + } + return null; + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateServerOptions.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateServerOptions.java new file mode 100644 index 0000000000..4a59f6a43b --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateServerOptions.java @@ -0,0 +1,241 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.jclouds.encryption.internal.Base64; +import org.jclouds.http.HttpRequest; +import org.jclouds.openstack.nova.domain.Addresses; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + * + */ +public class CreateServerOptions extends BindToJsonPayload { + + static class File { + private final String path; + private final String contents; + + public File(String path, byte[] contents) { + this.path = checkNotNull(path, "path"); + this.contents = Base64.encodeBytes(checkNotNull(contents, "contents")); + checkArgument(path.getBytes().length < 255, String.format( + "maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path + .getBytes().length)); + checkArgument(contents.length < 10 * 1024, String.format( + "maximum size of the file is 10KB. Contents specified is %d bytes", + contents.length)); + } + + public String getContents() { + return contents; + } + + public String getPath() { + return path; + } + + } + + @SuppressWarnings("unused") + private class ServerRequest { + final String name; + final int imageId; + final int flavorId; + Map metadata; + List personality; + Integer sharedIpGroupId; + Addresses addresses; + + private ServerRequest(String name, int imageId, int flavorId) { + this.name = name; + this.imageId = imageId; + this.flavorId = flavorId; + } + + } + + private Map metadata = Maps.newHashMap(); + private List files = Lists.newArrayList(); + private Integer sharedIpGroupId; + private String publicIp; + + @Override + public R bindToRequest(R request, Map postParams) { + ServerRequest server = new ServerRequest(checkNotNull(postParams.get("name"), + "name parameter not present"), Integer.parseInt(checkNotNull(postParams + .get("imageId"), "imageId parameter not present")), Integer.parseInt(checkNotNull( + postParams.get("flavorId"), "flavorId parameter not present"))); + if (metadata.size() > 0) + server.metadata = metadata; + if (files.size() > 0) + server.personality = files; + if (sharedIpGroupId != null) + server.sharedIpGroupId = this.sharedIpGroupId; + if (publicIp != null) { + server.addresses = new Addresses(); + server.addresses.getPublicAddresses().add(publicIp); + server.addresses.setPrivateAddresses(null); + } + return bindToRequest(request, ImmutableMap.of("server", server)); + } + + /** + * You may further customize a cloud server by injecting data into the file system of the cloud + * server itself. This is useful, for example, for inserting ssh keys, setting configuration + * files, or storing data that you want to retrieve from within the instance itself. It is + * intended to provide a minimal amount of launch-time personalization. If significant + * customization is required, a custom image should be created. The max size of the file path + * data is 255 bytes while the max size of the file contents is 10KB. Note that the file contents + * should be encoded as a Base64 string and the 10KB limit refers to the number of bytes in the + * decoded data not the number of characters in the encoded data. The maximum number of file + * path/content pairs that can be supplied is 5. Any existing files that match the specified file + * will be renamed to include the extension bak followed by a time stamp. For example, the file + * /etc/passwd will be backed up as /etc/passwd.bak.1246036261.5785. All files will have root and + * the root group as owner and group owner, respectively and will allow user and group read + * access only (-r--r-----). + */ + public CreateServerOptions withFile(String path, byte[] contents) { + checkState(files.size() < 5, "maximum number of files allowed is 5"); + files.add(new File(path, contents)); + return this; + } + + /** + * A shared IP group is a collection of servers that can share IPs with other members of the + * group. Any server in a group can share one or more public IPs with any other server in the + * group. With the exception of the first server in a shared IP group, servers must be launched + * into shared IP groups. A server may only be a member of one shared IP group. + * + *

+ * Servers in the same shared IP group can share public IPs for various high availability and + * load balancing configurations. To launch an HA server, include the optional sharedIpGroupId + * element and the server will be launched into that shared IP group. + *

+ * + * Note: sharedIpGroupId is an optional parameter and for optimal performance, should ONLY be + * specified when intending to share IPs between servers. + * + * @see #withSharedIp(String) + */ + public CreateServerOptions withSharedIpGroup(int id) { + checkArgument(id > 0, "id must be positive or zero. was: " + id); + this.sharedIpGroupId = id; + return this; + } + + /** + * Custom cloud server metadata can also be supplied at launch time. This metadata is stored in + * the API system where it is retrievable by querying the API for server status. The maximum size + * of the metadata key and value is each 255 bytes and the maximum number of key-value pairs that + * can be supplied per server is 5. + */ + public CreateServerOptions withMetadata(Map metadata) { + checkNotNull(metadata, "metadata"); + checkArgument(metadata.size() <= 5, + "you cannot have more then 5 metadata values. You specified: " + metadata.size()); + for (Entry entry : metadata.entrySet()) { + checkArgument(entry.getKey().getBytes().length < 255, String.format( + "maximum length of metadata key is 255 bytes. Key specified %s is %d bytes", + entry.getKey(), entry.getKey().getBytes().length)); + checkArgument( + entry.getKey().getBytes().length < 255, + String + .format( + "maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes", + entry.getKey(), entry.getValue(), + entry.getValue().getBytes().length)); + } + this.metadata = metadata; + return this; + } + + /** + * Public IP addresses can be shared across multiple servers for use in various high availability + * scenarios. When an IP address is shared to another server, the cloud network restrictions are + * modified to allow each server to listen to and respond on that IP address (you may optionally + * specify that the target server network configuration be modified). Shared IP addresses can be + * used with many standard heartbeat facilities (e.g. keepalived) that monitor for failure and + * manage IP failover. + * + *

+ * If you intend to use a shared IP on the server being created and have no need for a separate + * public IP address, you may launch the server into a shared IP group and specify an IP address + * from that shared IP group to be used as its public IP. You can accomplish this by specifying + * the public shared IP address in your request. This is optional and is only valid if + * sharedIpGroupId is also supplied. + */ + public CreateServerOptions withSharedIp(String publicIp) { + checkState(sharedIpGroupId != null, + "sharedIp is invalid unless a shared ip group is specified."); + this.publicIp = checkNotNull(publicIp, "ip"); + return this; + } + + public static class Builder { + + /** + * @see CreateServerOptions#withFile(String,byte []) + */ + public static CreateServerOptions withFile(String path, byte[] contents) { + CreateServerOptions options = new CreateServerOptions(); + return options.withFile(path, contents); + } + + /** + * @see CreateServerOptions#withSharedIpGroup(int) + */ + public static CreateServerOptions withSharedIpGroup(int id) { + CreateServerOptions options = new CreateServerOptions(); + return options.withSharedIpGroup(id); + } + + /** + * @see CreateServerOptions#withMetadata(Map) + */ + public static CreateServerOptions withMetadata(Map metadata) { + CreateServerOptions options = new CreateServerOptions(); + return options.withMetadata(metadata); + } + + /** + * @see CreateServerOptions#withSharedIp(String) + */ + public static CreateServerOptions withSharedIp(String publicIp) { + CreateServerOptions options = new CreateServerOptions(); + return options.withSharedIp(publicIp); + } + + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptions.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptions.java new file mode 100644 index 0000000000..f56d018f6e --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptions.java @@ -0,0 +1,88 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import javax.annotation.Nullable; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.collect.ImmutableMap; + +/** + * + * + * @author Adrian Cole + * + */ +public class CreateSharedIpGroupOptions extends BindToJsonPayload { + Integer serverId; + + @SuppressWarnings("unused") + private static class SharedIpGroupRequest { + final String name; + Integer server; + + private SharedIpGroupRequest(String name, @Nullable Integer serverId) { + this.name = name; + this.server = serverId; + } + + } + + @Override + public R bindToRequest(R request, Map postParams) { + SharedIpGroupRequest createRequest = new SharedIpGroupRequest(checkNotNull(postParams + .get("name")), serverId); + return super.bindToRequest(request, ImmutableMap.of("sharedIpGroup", createRequest)); + } + + @Override + public R bindToRequest(R request, Object toBind) { + throw new IllegalStateException("CreateSharedIpGroup is a POST operation"); + } + + /** + * + * @param id + * of the server to include with this request. + */ + public CreateSharedIpGroupOptions withServer(int id) { + checkArgument(id > 0, "server id must be a positive number"); + this.serverId = id; + return this; + } + + public static class Builder { + + /** + * @see CreateSharedIpGroupOptions#withServer(int) + */ + public static CreateSharedIpGroupOptions withServer(int id) { + CreateSharedIpGroupOptions options = new CreateSharedIpGroupOptions(); + return options.withServer(id); + } + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/ListOptions.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/ListOptions.java new file mode 100644 index 0000000000..93345dcef4 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/ListOptions.java @@ -0,0 +1,110 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import java.util.Date; + +import org.jclouds.openstack.options.BaseListOptions; + +/** + * Options used to control the amount of detail in the request. + * + * @see BaseListOptions + * @see + * @author Adrian Cole + */ +public class ListOptions extends BaseListOptions { + + public static final ListOptions NONE = new ListOptions(); + + /** + * unless used, only the name and id will be returned per row. + * + * @return + */ + public ListOptions withDetails() { + this.pathSuffix = "/detail"; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public ListOptions changesSince(Date ifModifiedSince) { + super.changesSince(ifModifiedSince); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public ListOptions maxResults(int limit) { + super.maxResults(limit); + return this; + + } + + /** + * {@inheritDoc} + */ + @Override + public ListOptions startAt(long offset) { + super.startAt(offset); + return this; + } + + public static class Builder { + + /** + * @see ListOptions#withDetails() + */ + public static ListOptions withDetails() { + ListOptions options = new ListOptions(); + return options.withDetails(); + } + + /** + * @see BaseListOptions#startAt(long) + */ + public static ListOptions startAt(long prefix) { + ListOptions options = new ListOptions(); + return options.startAt(prefix); + } + + /** + * @see BaseListOptions#maxResults(long) + */ + public static ListOptions maxResults(int maxKeys) { + ListOptions options = new ListOptions(); + return options.maxResults(maxKeys); + } + + /** + * @see BaseListOptions#changesSince(Date) + */ + public static ListOptions changesSince(Date since) { + ListOptions options = new ListOptions(); + return options.changesSince(since); + } + + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/RebuildServerOptions.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/RebuildServerOptions.java new file mode 100644 index 0000000000..8e2c28c6a8 --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/options/RebuildServerOptions.java @@ -0,0 +1,75 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; + +/** + * + * + * @author Adrian Cole + * + */ +public class RebuildServerOptions extends BindToJsonPayload { + Integer imageId; + + @Override + public R bindToRequest(R request, Map postParams) { + Map image = Maps.newHashMap(); + if (imageId != null) + image.put("imageId", imageId); + return super.bindToRequest(request, ImmutableMap.of("rebuild", image)); + } + + @Override + public R bindToRequest(R request, Object toBind) { + throw new IllegalStateException("RebuildServer is a POST operation"); + } + + /** + * + * @param id + * of the image to rebuild the server with. + */ + public RebuildServerOptions withImage(int id) { + checkArgument(id > 0, "server id must be a positive number"); + this.imageId = id; + return this; + } + + public static class Builder { + + /** + * @see RebuildServerOptions#withImage(int) + */ + public static RebuildServerOptions withImage(int id) { + RebuildServerOptions options = new RebuildServerOptions(); + return options.withImage(id); + } + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerActive.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerActive.java new file mode 100644 index 0000000000..2206e3375f --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerActive.java @@ -0,0 +1,67 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Singleton; + +import org.jclouds.logging.Logger; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; + +import com.google.common.base.Predicate; +import com.google.inject.Inject; + +/** + * + * Tests to see if a task succeeds. + * + * @author Adrian Cole + */ +@Singleton +public class ServerActive implements Predicate { + + private final NovaClient client; + + @Resource + protected Logger logger = Logger.NULL; + + @Inject + public ServerActive(NovaClient client) { + this.client = client; + } + + public boolean apply(Server server) { + logger.trace("looking for state on server %s", checkNotNull(server, "server")); + server = refresh(server); + if (server == null) + return false; + logger.trace("%s: looking for server state %s: currently: %s", server.getId(), + ServerStatus.ACTIVE, server.getStatus()); + return server.getStatus() == ServerStatus.ACTIVE; + } + + private Server refresh(Server server) { + return client.getServer(server.getId()); + } +} diff --git a/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerDeleted.java b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerDeleted.java new file mode 100644 index 0000000000..31e78d2dbe --- /dev/null +++ b/sandbox-apis/nova/src/main/java/org/jclouds/openstack/nova/predicates/ServerDeleted.java @@ -0,0 +1,67 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Singleton; + +import org.jclouds.logging.Logger; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; + +import com.google.common.base.Predicate; +import com.google.inject.Inject; + +/** + * + * Tests to see if a task succeeds. + * + * @author Adrian Cole + */ +@Singleton +public class ServerDeleted implements Predicate { + + private final NovaClient client; + + @Resource + protected Logger logger = Logger.NULL; + + @Inject + public ServerDeleted(NovaClient client) { + this.client = client; + } + + public boolean apply(Server server) { + logger.trace("looking for state on server %s", checkNotNull(server, "server")); + server = refresh(server); + if (server == null) + return true; + logger.trace("%s: looking for server state %s: currently: %s", server.getId(), + ServerStatus.DELETED, server.getStatus()); + return server.getStatus() == ServerStatus.DELETED; + } + + private Server refresh(Server server) { + return client.getServer(server.getId()); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java new file mode 100644 index 0000000000..357c4bef6a --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java @@ -0,0 +1,905 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova; + +import static org.jclouds.Constants.PROPERTY_API_VERSION; +import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withFile; +import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withMetadata; +import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withSharedIpGroup; +import static org.jclouds.openstack.nova.options.CreateSharedIpGroupOptions.Builder.withServer; +import static org.jclouds.openstack.nova.options.ListOptions.Builder.changesSince; +import static org.jclouds.openstack.nova.options.ListOptions.Builder.withDetails; +import static org.jclouds.openstack.nova.options.RebuildServerOptions.Builder.withImage; +import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.UnknownHostException; +import java.util.Date; +import java.util.Properties; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.nova.config.NovaRestClientModule; +import org.jclouds.openstack.nova.domain.BackupSchedule; +import org.jclouds.openstack.nova.domain.DailyBackup; +import org.jclouds.openstack.nova.domain.RebootType; +import org.jclouds.openstack.nova.domain.WeeklyBackup; +import org.jclouds.openstack.nova.options.CreateServerOptions; +import org.jclouds.openstack.nova.options.CreateSharedIpGroupOptions; +import org.jclouds.openstack.nova.options.ListOptions; +import org.jclouds.openstack.nova.options.RebuildServerOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.functions.ReleasePayloadAndReturn; +import org.jclouds.http.functions.ReturnFalseOn404; +import org.jclouds.http.functions.ReturnTrueIf2xx; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; +import org.jclouds.openstack.TestOpenStackAuthenticationModule; +import org.jclouds.openstack.filters.AddTimestampQuery; +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.rest.RestContextSpec; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code NovaAsyncClient} + * + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "NovaAsyncClientTest") +public class NovaAsyncClientTest extends RestClientTest { + private static final Class listOptionsVarargsClass = new ListOptions[] {}.getClass(); + private static final Class createServerOptionsVarargsClass = new CreateServerOptions[] {} + .getClass(); + + public void testCreateServer() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("createServer", String.class, int.class, int.class, + createServerOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, "ralphie", 2, 1); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, "{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1}}", + "application/json", false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testCreateServerWithIpGroup() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("createServer", String.class, int.class, int.class, + createServerOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, "ralphie", 2, 1, withSharedIpGroup(2)); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, + "{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"sharedIpGroupId\":2}}", + "application/json", false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testCreateServerWithFile() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("createServer", String.class, int.class, int.class, + createServerOptionsVarargsClass); + HttpRequest request = processor + .createRequest(method, "ralphie", 2, 1, withFile("/etc/jclouds", "foo".getBytes())); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals( + request, + "{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"personality\":[{\"path\":\"/etc/jclouds\",\"contents\":\"Zm9v\"}]}}", + "application/json", false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testCreateServerWithMetadata() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("createServer", String.class, int.class, int.class, + createServerOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, "ralphie", 2, 1, + withMetadata(ImmutableMap.of("foo", "bar"))); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, + "{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"metadata\":{\"foo\":\"bar\"}}}", + "application/json", false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testCreateServerWithIpGroupAndSharedIp() throws IOException, SecurityException, NoSuchMethodException, + UnknownHostException { + Method method = NovaAsyncClient.class.getMethod("createServer", String.class, int.class, int.class, + createServerOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, "ralphie", 2, 1, + withSharedIpGroup(2).withSharedIp("127.0.0.1")); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals( + request, + "{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"sharedIpGroupId\":2,\"addresses\":{\"public\":[\"127.0.0.1\"]}}}", + "application/json", false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testDeleteImage() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("deleteImage", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "DELETE http://serverManagementUrl/images/2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListServers() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listServers", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/servers?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + Date now = new Date(10000000l); + + public void testListServersOptions() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listServers", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2)); + + assertRequestLineEquals(request, + "GET http://serverManagementUrl/servers?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListServersDetail() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listServers", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, withDetails()); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/servers/detail?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testGetServer() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("getServer", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/servers/2?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListFlavors() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listFlavors", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/flavors?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListFlavorsOptions() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listFlavors", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2)); + + assertRequestLineEquals(request, + "GET http://serverManagementUrl/flavors?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListFlavorsDetail() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listFlavors", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, withDetails()); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/flavors/detail?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListFlavorsDetailOptions() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listFlavors", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, withDetails().changesSince(now).maxResults(1).startAt(2)); + + assertRequestLineEquals(request, + "GET http://serverManagementUrl/flavors/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testGetFlavor() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("getFlavor", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/flavors/2?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListImages() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listImages", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/images?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListImagesDetail() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listImages", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, withDetails()); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/images/detail?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListImagesOptions() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listImages", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2)); + + assertRequestLineEquals(request, + "GET http://serverManagementUrl/images?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListImagesDetailOptions() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listImages", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, withDetails().changesSince(now).maxResults(1).startAt(2)); + + assertRequestLineEquals(request, + "GET http://serverManagementUrl/images/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testGetImage() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("getImage", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/images/2?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testDeleteServer() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("deleteServer", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "DELETE http://serverManagementUrl/servers/2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testShareIpNoConfig() throws IOException, SecurityException, NoSuchMethodException, UnknownHostException { + Method method = NovaAsyncClient.class.getMethod("shareIp", String.class, int.class, int.class, + boolean.class); + HttpRequest request = processor.createRequest(method, "127.0.0.1", 2, 3, false); + + assertRequestLineEquals(request, "PUT http://serverManagementUrl/servers/2/ips/public/127.0.0.1 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"shareIp\":{\"sharedIpGroupId\":3,\"configureServer\":false}}", + MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testShareIpConfig() throws IOException, SecurityException, NoSuchMethodException, UnknownHostException { + Method method = NovaAsyncClient.class.getMethod("shareIp", String.class, int.class, int.class, + boolean.class); + HttpRequest request = processor.createRequest(method, "127.0.0.1", 2, 3, true); + + assertRequestLineEquals(request, "PUT http://serverManagementUrl/servers/2/ips/public/127.0.0.1 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"shareIp\":{\"sharedIpGroupId\":3,\"configureServer\":true}}", + MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testUnshareIpNoConfig() throws IOException, SecurityException, NoSuchMethodException, + UnknownHostException { + Method method = NovaAsyncClient.class.getMethod("unshareIp", String.class, int.class); + HttpRequest request = processor.createRequest(method, "127.0.0.1", 2, 3, false); + + assertRequestLineEquals(request, "DELETE http://serverManagementUrl/servers/2/ips/public/127.0.0.1 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(request); + + } + + public void testReplaceBackupSchedule() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("replaceBackupSchedule", int.class, BackupSchedule.class); + HttpRequest request = processor.createRequest(method, 2, new BackupSchedule(WeeklyBackup.MONDAY, + DailyBackup.H_0800_1000, true)); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/2/backup_schedule HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, + "{\"backupSchedule\":{\"daily\":\"H_0800_1000\",\"enabled\":true,\"weekly\":\"MONDAY\"}}", + MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnFalseOn404.class); + + checkFilters(request); + + } + + public void testDeleteBackupSchedule() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("deleteBackupSchedule", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "DELETE http://serverManagementUrl/servers/2/backup_schedule HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, null, MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class); + + checkFilters(request); + + } + + public void testChangeAdminPass() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("changeAdminPass", int.class, String.class); + HttpRequest request = processor.createRequest(method, 2, "foo"); + + assertRequestLineEquals(request, "PUT http://serverManagementUrl/servers/2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"server\":{\"adminPass\":\"foo\"}}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testChangeServerName() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("renameServer", int.class, String.class); + HttpRequest request = processor.createRequest(method, 2, "foo"); + + assertRequestLineEquals(request, "PUT http://serverManagementUrl/servers/2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"server\":{\"name\":\"foo\"}}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testListSharedIpGroups() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listSharedIpGroups", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/shared_ip_groups?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListSharedIpGroupsOptions() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listSharedIpGroups", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2)); + + assertRequestLineEquals(request, + "GET http://serverManagementUrl/shared_ip_groups?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListSharedIpGroupsDetail() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listSharedIpGroups", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, withDetails()); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/shared_ip_groups/detail?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListSharedIpGroupsDetailOptions() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listSharedIpGroups", listOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, withDetails().changesSince(now).maxResults(1).startAt(2)); + + assertRequestLineEquals(request, + "GET http://serverManagementUrl/shared_ip_groups/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testGetSharedIpGroup() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("getSharedIpGroup", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/shared_ip_groups/2?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(request); + } + + private static final Class createSharedIpGroupOptionsVarargsClass = new CreateSharedIpGroupOptions[] {} + .getClass(); + + public void testCreateSharedIpGroup() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("createSharedIpGroup", String.class, + createSharedIpGroupOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, "ralphie"); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/shared_ip_groups?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, "{\"sharedIpGroup\":{\"name\":\"ralphie\"}}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testCreateSharedIpGroupWithIpGroup() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("createSharedIpGroup", String.class, + createSharedIpGroupOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, "ralphie", withServer(2)); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/shared_ip_groups?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, "{\"sharedIpGroup\":{\"name\":\"ralphie\",\"server\":2}}", + MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testDeleteSharedIpGroup() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("deleteSharedIpGroup", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "DELETE http://serverManagementUrl/shared_ip_groups/2 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnFalseOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListAddresses() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("getAddresses", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/servers/2/ips?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testListPublicAddresses() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listPublicAddresses", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/servers/2/ips/public?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListPrivateAddresses() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("listPrivateAddresses", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/servers/2/ips/private?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testListBackupSchedule() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("getBackupSchedule", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "GET http://serverManagementUrl/servers/2/backup_schedule?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(request); + } + + public void testCreateImageWithIpGroup() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("createImageFromServer", String.class, int.class); + HttpRequest request = processor.createRequest(method, "ralphie", 2); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/images?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); + assertPayloadEquals(request, "{\"image\":{\"serverId\":2,\"name\":\"ralphie\"}}", MediaType.APPLICATION_JSON, + false); + + assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + private static final Class rebuildServerOptionsVarargsClass = new RebuildServerOptions[] {} + .getClass(); + + public void testRebuildServer() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("rebuildServer", int.class, + rebuildServerOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, 3); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/3/action?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"rebuild\":{}}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testRebuildServerWithImage() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("rebuildServer", int.class, + rebuildServerOptionsVarargsClass); + HttpRequest request = processor.createRequest(method, 3, withImage(2)); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/3/action?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"rebuild\":{\"imageId\":2}}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testReboot() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("rebootServer", int.class, RebootType.class); + HttpRequest request = processor.createRequest(method, 2, RebootType.HARD); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/2/action?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"reboot\":{\"type\":\"HARD\"}}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testResize() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("resizeServer", int.class, int.class); + HttpRequest request = processor.createRequest(method, 2, 3); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/2/action?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"resize\":{\"flavorId\":3}}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + + } + + public void testConfirmResize() throws IOException, IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("confirmResizeServer", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/2/action?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"confirmResize\":null}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + public void testRevertResize() throws IOException, SecurityException, NoSuchMethodException { + Method method = NovaAsyncClient.class.getMethod("revertResizeServer", int.class); + HttpRequest request = processor.createRequest(method, 2); + + assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/2/action?format=json HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, "{\"revertResize\":null}", MediaType.APPLICATION_JSON, false); + + assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(request); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 2); + assertEquals(request.getFilters().get(0).getClass(), AuthenticateRequest.class); + assertEquals(request.getFilters().get(1).getClass(), AddTimestampQuery.class); + + } + + @Override + protected Module createModule() { + return new TestNovaRestClientModule(); + } + + @ConfiguresRestClient + @RequiresHttp + protected static class TestNovaRestClientModule extends NovaRestClientModule { + private TestNovaRestClientModule() { + super(new TestOpenStackAuthenticationModule()); + } + + @Override + protected URI provideServerUrl(AuthenticationResponse response) { + return URI.create("http://serverManagementUrl"); + } + + } + + protected String provider = "nova"; + + @Override + public RestContextSpec createContextSpec() { + return new RestContextFactory(getProperties()).createContextSpec(provider, "user", "password", new Properties()); + } + + @Override + protected Properties getProperties() { + Properties overrides = new Properties(); + overrides.setProperty(PROPERTY_REGIONS, "US"); + overrides.setProperty(PROPERTY_API_VERSION, "1"); + overrides.setProperty(provider + ".endpoint", "https://auth"); + overrides.setProperty(provider + ".contextbuilder", NovaContextBuilder.class.getName()); + return overrides; + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java new file mode 100644 index 0000000000..ffeb07b0ad --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java @@ -0,0 +1,639 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withFile; +import static org.jclouds.openstack.nova.options.CreateSharedIpGroupOptions.Builder.withServer; +import static org.jclouds.openstack.nova.options.ListOptions.Builder.withDetails; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.io.IOException; +import java.lang.reflect.UndeclaredThrowableException; +import java.security.SecureRandom; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.Constants; +import org.jclouds.openstack.nova.domain.BackupSchedule; +import org.jclouds.openstack.nova.domain.DailyBackup; +import org.jclouds.openstack.nova.domain.Flavor; +import org.jclouds.openstack.nova.domain.Image; +import org.jclouds.openstack.nova.domain.ImageStatus; +import org.jclouds.openstack.nova.domain.RebootType; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; +import org.jclouds.openstack.nova.domain.SharedIpGroup; +import org.jclouds.openstack.nova.domain.WeeklyBackup; +import org.jclouds.openstack.nova.options.RebuildServerOptions; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.domain.Credentials; +import org.jclouds.http.HttpResponseException; +import org.jclouds.io.Payload; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.net.IPSocket; +import org.jclouds.predicates.RetryablePredicate; +import org.jclouds.predicates.SocketOpen; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.ssh.SshClient; +import org.jclouds.ssh.SshException; +import org.jclouds.ssh.jsch.config.JschSshClientModule; +import org.jclouds.util.Strings2; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.inject.Injector; +import com.google.inject.Module; + +/** + * Tests behavior of {@code NovaClient} + * + * @author Adrian Cole + */ +// disabled [Web Hosting #129069 +@Test(groups = "live", sequential = true) +public class NovaClientLiveTest { + + protected NovaClient client; + protected SshClient.Factory sshFactory; + private Predicate socketTester; + protected String provider = "nova"; + protected String identity; + protected String credential; + protected String endpoint; + protected String apiversion; + + protected void setupCredentials() { + identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider + + ".credential"); + endpoint = System.getProperty("test." + provider + ".endpoint"); + apiversion = System.getProperty("test." + provider + ".apiversion"); + } + + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.setProperty(provider + ".identity", identity); + overrides.setProperty(provider + ".credential", credential); + if (endpoint != null) + overrides.setProperty(provider + ".endpoint", endpoint); + if (apiversion != null) + overrides.setProperty(provider + ".apiversion", apiversion); + return overrides; + } + + @BeforeGroups(groups = { "live" }) + public void setupClient() { + setupCredentials(); + Properties overrides = setupProperties(); + + Injector injector = new RestContextFactory().createContextBuilder(provider, + ImmutableSet. of(new Log4JLoggingModule(), new JschSshClientModule()), overrides) + .buildInjector(); + + client = injector.getInstance(NovaClient.class); + sshFactory = injector.getInstance(SshClient.Factory.class); + SocketOpen socketOpen = injector.getInstance(SocketOpen.class); + socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); + injector.injectMembers(socketOpen); // add logger + } + + public void testListServers() throws Exception { + + Set response = client.listServers(); + assert null != response; + long initialContainerCount = response.size(); + assertTrue(initialContainerCount >= 0); + + } + + public void testListServersDetail() throws Exception { + Set response = client.listServers(withDetails()); + assert null != response; + long initialContainerCount = response.size(); + assertTrue(initialContainerCount >= 0); + } + + public void testListImages() throws Exception { + Set response = client.listImages(); + assert null != response; + long imageCount = response.size(); + assertTrue(imageCount >= 1); + for (Image image : response) { + assertTrue(image.getId() >= 0); + assert null != image.getName() : image; + } + + } + + public void testListImagesDetail() throws Exception { + Set response = client.listImages(withDetails()); + assert null != response; + long imageCount = response.size(); + assertTrue(imageCount >= 0); + for (Image image : response) { + assertTrue(image.getId() >= 1); + assert null != image.getName() : image; + assert null != image.getStatus() : image; + } + } + + public void testGetImagesDetail() throws Exception { + Set response = client.listImages(withDetails()); + assert null != response; + long imageCount = response.size(); + assertTrue(imageCount >= 0); + for (Image image : response) { + try { + Image newDetails = client.getImage(image.getId()); + assertEquals(image, newDetails); + } catch (HttpResponseException e) {// Ticket #9867 + if (e.getResponse().getStatusCode() != 400) + throw e; + } + } + } + + @Test + public void testGetImageDetailsNotFound() throws Exception { + assert client.getImage(12312987) == null; + } + + @Test + public void testGetServerDetailsNotFound() throws Exception { + assert client.getServer(12312987) == null; + } + + public void testGetServersDetail() throws Exception { + Set response = client.listServers(withDetails()); + assert null != response; + long serverCount = response.size(); + assertTrue(serverCount >= 0); + for (Server server : response) { + Server newDetails = client.getServer(server.getId()); + assertEquals(server, newDetails); + } + } + + public void testListFlavors() throws Exception { + Set response = client.listFlavors(); + assert null != response; + long flavorCount = response.size(); + assertTrue(flavorCount >= 1); + for (Flavor flavor : response) { + assertTrue(flavor.getId() >= 0); + assert null != flavor.getName() : flavor; + } + + } + + public void testListFlavorsDetail() throws Exception { + Set response = client.listFlavors(withDetails()); + assert null != response; + long flavorCount = response.size(); + assertTrue(flavorCount >= 0); + for (Flavor flavor : response) { + assertTrue(flavor.getId() >= 1); + assert null != flavor.getName() : flavor; + assert null != flavor.getDisk() : flavor; + assert null != flavor.getRam() : flavor; + } + } + + public void testGetFlavorsDetail() throws Exception { + Set response = client.listFlavors(withDetails()); + assert null != response; + long flavorCount = response.size(); + assertTrue(flavorCount >= 0); + for (Flavor flavor : response) { + Flavor newDetails = client.getFlavor(flavor.getId()); + assertEquals(flavor, newDetails); + } + } + + @Test + public void testGetFlavorDetailsNotFound() throws Exception { + assert client.getFlavor(12312987) == null; + } + + public void testListSharedIpGroups() throws Exception { + Set response = client.listSharedIpGroups(); + assert null != response; + long sharedIpGroupCount = response.size(); + assertTrue(sharedIpGroupCount >= 0); + for (SharedIpGroup sharedIpGroup : response) { + assertTrue(sharedIpGroup.getId() >= 0); + assert null != sharedIpGroup.getName() : sharedIpGroup; + } + + } + + public void testListSharedIpGroupsDetail() throws Exception { + Set response = client.listSharedIpGroups(withDetails()); + assert null != response; + long sharedIpGroupCount = response.size(); + assertTrue(sharedIpGroupCount >= 0); + for (SharedIpGroup sharedIpGroup : response) { + assertTrue(sharedIpGroup.getId() >= 1); + assert null != sharedIpGroup.getName() : sharedIpGroup; + assert null != sharedIpGroup.getServers() : sharedIpGroup; + } + } + + public void testGetSharedIpGroupsDetail() throws Exception { + Set response = client.listSharedIpGroups(withDetails()); + assert null != response; + long sharedIpGroupCount = response.size(); + assertTrue(sharedIpGroupCount >= 0); + for (SharedIpGroup sharedIpGroup : response) { + SharedIpGroup newDetails = client.getSharedIpGroup(sharedIpGroup.getId()); + assertEquals(sharedIpGroup, newDetails); + } + } + + @Test + public void testGetSharedIpGroupDetailsNotFound() throws Exception { + assert client.getSharedIpGroup(12312987) == null; + } + + @Test(enabled = false, timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer") + public void testCreateSharedIpGroup() throws Exception { + SharedIpGroup sharedIpGroup = null; + while (sharedIpGroup == null) { + String sharedIpGroupName = serverPrefix + "createSharedIpGroup" + new SecureRandom().nextInt(); + try { + sharedIpGroup = client.createSharedIpGroup(sharedIpGroupName, withServer(serverId)); + } catch (UndeclaredThrowableException e) { + HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); + if (htpe.getResponse().getStatusCode() == 400) + continue; + throw e; + } + } + assertNotNull(sharedIpGroup.getName()); + sharedIpGroupId = sharedIpGroup.getId(); + // Response doesn't include the server id Web Hosting #119311 + // assertEquals(sharedIpGroup.getServers(), ImmutableList.of(serverId)); + } + + private int sharedIpGroupId; + + private String serverPrefix = System.getProperty("user.name") + ".cs"; + private int serverId; + private String adminPass; + Map metadata = ImmutableMap.of("jclouds", "rackspace"); + private String ip; + private int serverId2; + private String adminPass2; + private int imageId; + + @Test(enabled = false) + public void testCreateServer() throws Exception { + int imageId = 14362; + int flavorId = 1; + Server server = null; + while (server == null) { + String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt(); + try { + server = client.createServer(serverName, imageId, flavorId, withFile("/etc/jclouds.txt", + "rackspace".getBytes()).withMetadata(metadata)); + } catch (UndeclaredThrowableException e) { + HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); + if (htpe.getResponse().getStatusCode() == 400) + continue; + throw e; + } + } + assertNotNull(server.getAdminPass()); + serverId = server.getId(); + adminPass = server.getAdminPass(); + ip = server.getAddresses().getPublicAddresses().iterator().next(); + assertEquals(server.getStatus(), ServerStatus.BUILD); + blockUntilServerActive(serverId); + } + + private void blockUntilServerActive(int serverId) throws InterruptedException { + Server currentDetails = null; + for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != ServerStatus.ACTIVE; currentDetails = client + .getServer(serverId)) { + System.out.printf("blocking on status active%n%s%n", currentDetails); + Thread.sleep(5 * 1000); + } + } + + private void blockUntilServerVerifyResize(int serverId) throws InterruptedException { + Server currentDetails = null; + for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != ServerStatus.VERIFY_RESIZE; currentDetails = client + .getServer(serverId)) { + System.out.printf("blocking on status verify resize%n%s%n", currentDetails); + Thread.sleep(5 * 1000); + } + } + + private void blockUntilImageActive(int imageId) throws InterruptedException { + Image currentDetails = null; + for (currentDetails = client.getImage(imageId); currentDetails.getStatus() != ImageStatus.ACTIVE; currentDetails = client + .getImage(imageId)) { + System.out.printf("blocking on status active%n%s%n", currentDetails); + Thread.sleep(5 * 1000); + } + } + + @Test(enabled = false, timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer") + public void testServerDetails() throws Exception { + Server server = client.getServer(serverId); + + assertNotNull(server.getHostId()); + assertEquals(server.getStatus(), ServerStatus.ACTIVE); + assert server.getProgress() >= 0 : "newDetails.getProgress()" + server.getProgress(); + assertEquals(new Integer(14362), server.getImageId()); + assertEquals(new Integer(1), server.getFlavorId()); + assertNotNull(server.getAddresses()); + // listAddresses tests.. + assertEquals(client.getAddresses(serverId), server.getAddresses()); + assertEquals(server.getAddresses().getPublicAddresses().size(), 1); + assertEquals(client.listPublicAddresses(serverId), server.getAddresses().getPublicAddresses()); + assertEquals(server.getAddresses().getPrivateAddresses().size(), 1); + assertEquals(client.listPrivateAddresses(serverId), server.getAddresses().getPrivateAddresses()); + + // check metadata + assertEquals(server.getMetadata(), metadata); + + checkPassOk(server, adminPass); + } + + /** + * this tests "personality" as the file looked up was sent during server creation + */ + private void checkPassOk(Server newDetails, String pass) throws IOException { + try { + doCheckPass(newDetails, pass); + } catch (SshException e) {// try twice in case there is a network timeout + try { + Thread.sleep(10 * 1000); + } catch (InterruptedException e1) { + } + doCheckPass(newDetails, pass); + } + } + + private void doCheckPass(Server newDetails, String pass) throws IOException { + IPSocket socket = new IPSocket(Iterables.get(newDetails.getAddresses().getPublicAddresses(), 0), 22); + socketTester.apply(socket); + + SshClient client = sshFactory.create(socket, new Credentials("root", pass)); + try { + client.connect(); + Payload etcPasswd = client.get("/etc/jclouds.txt"); + String etcPasswdContents = Strings2.toStringAndClose(etcPasswd.getInput()); + assertEquals("rackspace", etcPasswdContents.trim()); + } finally { + if (client != null) + client.disconnect(); + } + } + + private ExecResponse exec(Server details, String pass, String command) throws IOException { + IPSocket socket = new IPSocket(Iterables.get(details.getAddresses().getPublicAddresses(), 0), 22); + socketTester.apply(socket); + SshClient client = sshFactory.create(socket, new Credentials("root", pass)); + try { + client.connect(); + return client.exec(command); + } finally { + if (client != null) + client.disconnect(); + } + } + + @Test(enabled = false, timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer") + public void testRenameServer() throws Exception { + Server server = client.getServer(serverId); + String oldName = server.getName(); + client.renameServer(serverId, oldName + "new"); + blockUntilServerActive(serverId); + assertEquals(oldName + "new", client.getServer(serverId).getName()); + } + + @Test(enabled = false, timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateServer") + public void testChangePassword() throws Exception { + client.changeAdminPass(serverId, "elmo"); + blockUntilServerActive(serverId); + checkPassOk(client.getServer(serverId), "elmo"); + this.adminPass = "elmo"; + } + + @Test(enabled = false, timeOut = 5 * 60 * 1000, dependsOnMethods = "testCreateSharedIpGroup") + public void testCreateServerIp() throws Exception { + int imageId = 14362; + int flavorId = 1; + Server server = null; + while (server == null) { + String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt(); + try { + server = client + .createServer(serverName, imageId, flavorId, withFile("/etc/jclouds.txt", "rackspace".getBytes()) + .withMetadata(metadata).withSharedIpGroup(sharedIpGroupId).withSharedIp(ip)); + } catch (UndeclaredThrowableException e) { + HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); + if (htpe.getResponse().getStatusCode() == 400) + continue; + throw e; + } + } + assertNotNull(server.getAdminPass()); + serverId2 = server.getId(); + adminPass2 = server.getAdminPass(); + blockUntilServerActive(serverId2); + assertIpConfigured(server, adminPass2); + assert server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses() + " doesn't contain " + ip; + assertEquals(server.getSharedIpGroupId(), new Integer(sharedIpGroupId)); + } + + private void assertIpConfigured(Server server, String password) { + try { + ExecResponse response = exec(server, password, "ifconfig -a"); + assert response.getOutput().indexOf(ip) > 0 : String.format("server %s didn't get ip %s%n%s", server, ip, + response); + } catch (Exception e) { + e.printStackTrace(); + } catch (AssertionError e) { + e.printStackTrace(); + } + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testCreateServerIp") + public void testUnshare() throws Exception { + client.unshareIp(ip, serverId2); + blockUntilServerActive(serverId2); + Server server = client.getServer(serverId2); + assert !server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses(); + assertIpNotConfigured(server, adminPass2); + } + + private void assertIpNotConfigured(Server server, String password) { + try { + ExecResponse response = exec(server, password, "ifconfig -a"); + assert response.getOutput().indexOf(ip) == -1 : String.format("server %s still has get ip %s%n%s", server, ip, + response); + } catch (Exception e) { + e.printStackTrace(); + } catch (AssertionError e) { + e.printStackTrace(); + } + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testUnshare") + public void testShareConfig() throws Exception { + client.shareIp(ip, serverId2, sharedIpGroupId, true); + blockUntilServerActive(serverId2); + Server server = client.getServer(serverId2); + assert server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses(); + assertIpConfigured(server, adminPass2); + testUnshare(); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testShareConfig") + public void testShareNoConfig() throws Exception { + client.shareIp(ip, serverId2, sharedIpGroupId, false); + blockUntilServerActive(serverId2); + Server server = client.getServer(serverId2); + assert server.getAddresses().getPublicAddresses().contains(ip) : server.getAddresses(); + assertIpNotConfigured(server, adminPass2); + testUnshare(); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testShareNoConfig") + public void testBackup() throws Exception { + assertEquals(new BackupSchedule(), client.getBackupSchedule(serverId)); + BackupSchedule dailyWeekly = new BackupSchedule(); + dailyWeekly.setEnabled(true); + dailyWeekly.setWeekly(WeeklyBackup.FRIDAY); + dailyWeekly.setDaily(DailyBackup.H_0400_0600); + client.replaceBackupSchedule(serverId, dailyWeekly); + client.deleteBackupSchedule(serverId); + // disables, doesn't delete: Web Hosting #119571 + assertEquals(client.getBackupSchedule(serverId).isEnabled(), false); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testBackup") + public void testCreateImage() throws Exception { + Image image = client.createImageFromServer("hoofie", serverId); + assertEquals("hoofie", image.getName()); + assertEquals(new Integer(serverId), image.getServerId()); + imageId = image.getId(); + blockUntilImageActive(imageId); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testCreateImage") + public void testRebuildServer() throws Exception { + client.rebuildServer(serverId, new RebuildServerOptions().withImage(imageId)); + blockUntilServerActive(serverId); + // issue Web Hosting #119580 imageId comes back incorrect after rebuild + // assertEquals(new Integer(imageId), client.getServer(serverId).getImageId()); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebuildServer") + public void testRebootHard() throws Exception { + client.rebootServer(serverId, RebootType.HARD); + blockUntilServerActive(serverId); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootHard") + public void testRebootSoft() throws Exception { + client.rebootServer(serverId, RebootType.SOFT); + blockUntilServerActive(serverId); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootSoft") + public void testRevertResize() throws Exception { + client.resizeServer(serverId, 2); + blockUntilServerVerifyResize(serverId); + client.revertResizeServer(serverId); + blockUntilServerActive(serverId); + assertEquals(new Integer(1), client.getServer(serverId).getFlavorId()); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testRebootSoft") + public void testConfirmResize() throws Exception { + client.resizeServer(serverId2, 2); + blockUntilServerVerifyResize(serverId2); + client.confirmResizeServer(serverId2); + blockUntilServerActive(serverId2); + assertEquals(new Integer(2), client.getServer(serverId2).getFlavorId()); + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = { "testRebootSoft", "testRevertResize", + "testConfirmResize" }) + void deleteServer2() { + if (serverId2 > 0) { + client.deleteServer(serverId2); + assert client.getServer(serverId2) == null; + } + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "deleteServer2") + void testDeleteImage() { + if (imageId > 0) { + client.deleteImage(imageId); + assert client.getImage(imageId) == null; + } + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = "testDeleteImage") + void deleteServer1() { + if (serverId > 0) { + client.deleteServer(serverId); + assert client.getServer(serverId) == null; + } + } + + @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = { "deleteServer1" }) + void testDeleteSharedIpGroup() { + if (sharedIpGroupId > 0) { + client.deleteSharedIpGroup(sharedIpGroupId); + assert client.getSharedIpGroup(sharedIpGroupId) == null; + } + } + + @AfterTest + void deleteServersOnEnd() { + if (serverId > 0) { + client.deleteServer(serverId); + } + if (serverId2 > 0) { + client.deleteServer(serverId2); + } + if (sharedIpGroupId > 0) { + client.deleteSharedIpGroup(sharedIpGroupId); + } + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/NovaComputeServiceLiveTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/NovaComputeServiceLiveTest.java new file mode 100644 index 0000000000..5d533d09cb --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/NovaComputeServiceLiveTest.java @@ -0,0 +1,89 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.openstack.nova.NovaAsyncClient; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.compute.BaseComputeServiceLiveTest; +import org.jclouds.compute.ComputeServiceContextFactory; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.domain.LocationScope; +import org.jclouds.rest.RestContext; +import org.jclouds.ssh.jsch.config.JschSshClientModule; +import org.testng.annotations.Test; + +/** + * + * Generally disabled, as it incurs higher fees. + * + * @author Adrian Cole + */ +@Test(groups = "live", enabled = true, sequential = true) +public class NovaComputeServiceLiveTest extends BaseComputeServiceLiveTest { + public NovaComputeServiceLiveTest() { + provider = "nova"; + } + + @Override + protected JschSshClientModule getSshModule() { + return new JschSshClientModule(); + } + + public void testAssignability() throws Exception { + @SuppressWarnings("unused") + RestContext tmContext = new ComputeServiceContextFactory() + .createContext(provider, identity, credential).getProviderSpecificContext(); + } + + @Override + protected void checkNodes(Iterable nodes, String tag) throws IOException { + super.checkNodes(nodes, tag); + for (NodeMetadata node : nodes) { + assertEquals(node.getLocation().getScope(), LocationScope.HOST); + } + } + + @Test(enabled = true, dependsOnMethods = "testReboot", expectedExceptions = UnsupportedOperationException.class) + public void testSuspendResume() throws Exception { + super.testSuspendResume(); + } + + @Test(enabled = true, dependsOnMethods = "testSuspendResume") + @Override + public void testGetNodesWithDetails() throws Exception { + super.testGetNodesWithDetails(); + } + + @Test(enabled = true, dependsOnMethods = "testSuspendResume") + @Override + public void testListNodes() throws Exception { + super.testListNodes(); + } + + @Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" }) + @Override + public void testDestroyNodes() { + super.testDestroyNodes(); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModuleTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModuleTest.java new file mode 100644 index 0000000000..fb7202503c --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/config/NovaComputeServiceContextModuleTest.java @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.config; + +import org.jclouds.openstack.nova.domain.ServerStatus; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit") +public class NovaComputeServiceContextModuleTest { + + public void testAllStatusCovered() { + + for (ServerStatus state : ServerStatus.values()) { + assert NovaComputeServiceDependenciesModule.serverToNodeState.containsKey(state) : state; + } + + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java new file mode 100644 index 0000000000..72088797a1 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java @@ -0,0 +1,62 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.functions; + +import static org.testng.Assert.assertEquals; + +import java.net.UnknownHostException; + +import org.jclouds.openstack.nova.domain.Flavor; +import org.jclouds.openstack.nova.functions.ParseFlavorFromJsonResponseTest; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.VolumeBuilder; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit") +public class FlavorToHardwareTest { + Location provider = new LocationBuilder().scope(LocationScope.ZONE).id("dallas").description("description").build(); + + @Test + public void test() throws UnknownHostException { + assertEquals(convertFlavor(), new HardwareBuilder().ids("1").name("256 MB Server").processors( + ImmutableList.of(new Processor(1.0, 1.0))).ram(256).volumes( + ImmutableList.of(new VolumeBuilder().type(Volume.Type.LOCAL).size(10.0f).durable(true).bootDevice(true) + .build())).build()); + } + + public static Hardware convertFlavor() { + Flavor flavor = ParseFlavorFromJsonResponseTest.parseFlavor(); + + FlavorToHardware parser = new FlavorToHardware(); + + return parser.apply(flavor); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImageTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImageTest.java new file mode 100644 index 0000000000..516db3270f --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/NovaImageToImageTest.java @@ -0,0 +1,67 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.functions; + +import static org.testng.Assert.assertEquals; + +import java.net.UnknownHostException; + +import org.jclouds.compute.config.BaseComputeServiceContextModule; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystemBuilder; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Credentials; +import org.jclouds.json.Json; +import org.jclouds.json.config.GsonModule; +import org.jclouds.openstack.nova.functions.ParseImageFromJsonResponseTest; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit") +public class NovaImageToImageTest { + + @Test + public void testApplyWhereImageNotFound() throws UnknownHostException { + assertEquals( + convertImage(), + new ImageBuilder() + .name("CentOS 5.2") + .operatingSystem( + new OperatingSystemBuilder().family(OsFamily.CENTOS).version("5.2").description("CentOS 5.2").is64Bit(true) + .build()).description("CentOS 5.2").defaultCredentials(new Credentials("root", null)) + .ids("2").version("1286712000000").build()); + } + + public static Image convertImage() { + org.jclouds.openstack.nova.domain.Image image = ParseImageFromJsonResponseTest.parseImage(); + + NovaImageToImage parser = new NovaImageToImage(new NovaImageToOperatingSystem(new BaseComputeServiceContextModule() { + }.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule()) + .getInstance(Json.class)))); + + return parser.apply(image); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadataTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadataTest.java new file mode 100644 index 0000000000..b6736c7f2b --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/ServerToNodeMetadataTest.java @@ -0,0 +1,157 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.compute.functions; + +import static org.testng.Assert.assertEquals; + +import java.net.UnknownHostException; +import java.util.Map; +import java.util.Set; + +import org.jclouds.openstack.nova.compute.config.NovaComputeServiceDependenciesModule; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; +import org.jclouds.openstack.nova.functions.ParseServerFromJsonResponseTest; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.domain.OperatingSystemBuilder; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.VolumeBuilder; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.testng.annotations.Test; + +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ServerToNodeMetadataTest { + Location provider = new LocationBuilder().scope(LocationScope.ZONE).id("dallas").description("description").build(); + + @Test + public void testApplyWhereImageAndHardwareNotFoundButCredentialsFound() throws UnknownHostException { + Credentials creds = new Credentials("root", "abdce"); + + Map serverStateToNodeState = NovaComputeServiceDependenciesModule.serverToNodeState; + Set images = ImmutableSet.of(); + Set hardwares = ImmutableSet.of(); + Server server = ParseServerFromJsonResponseTest.parseServer(); + + ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, ImmutableMap + . of("node#1234", creds), Suppliers.> ofInstance(images), + Suppliers.ofInstance(provider), Suppliers.> ofInstance(hardwares)); + + NodeMetadata metadata = parser.apply(server); + + assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses( + ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")) + .imageId("2").id("1234").providerId("1234").name("sample-server").credentials(creds).location( + new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0") + .description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build()) + .userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build()); + } + + @Test + public void testApplyWhereImageAndHardwareNotFound() throws UnknownHostException { + Map serverStateToNodeState = NovaComputeServiceDependenciesModule.serverToNodeState; + Set images = ImmutableSet.of(); + Set hardwares = ImmutableSet.of(); + Server server = ParseServerFromJsonResponseTest.parseServer(); + + ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, ImmutableMap + . of(), Suppliers.> ofInstance(images), Suppliers + .ofInstance(provider), Suppliers.> ofInstance(hardwares)); + + NodeMetadata metadata = parser.apply(server); + + assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses( + ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")) + .imageId("2").id("1234").providerId("1234").name("sample-server").location( + new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0") + .description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build()) + .userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build()); + + } + + @Test + public void testApplyWhereImageFoundAndHardwareNotFound() throws UnknownHostException { + Map serverStateToNodeState = NovaComputeServiceDependenciesModule.serverToNodeState; + org.jclouds.compute.domain.Image jcImage = NovaImageToImageTest.convertImage(); + Set images = ImmutableSet.of(jcImage); + Set hardwares = ImmutableSet.of(); + Server server = ParseServerFromJsonResponseTest.parseServer(); + + ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, ImmutableMap + . of(), Suppliers.> ofInstance(images), Suppliers + .ofInstance(provider), Suppliers.> ofInstance(hardwares)); + + NodeMetadata metadata = parser.apply(server); + + assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses( + ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")) + .imageId("2").operatingSystem( + new OperatingSystemBuilder().family(OsFamily.CENTOS).description("CentOS 5.2").version("5.2") + .is64Bit(true).build()).id("1234").providerId("1234").name("sample-server").location( + new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0") + .description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build()) + .userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build()); + + } + + @Test + public void testApplyWhereImageAndHardwareFound() throws UnknownHostException { + Map serverStateToNodeState = NovaComputeServiceDependenciesModule.serverToNodeState; + Set images = ImmutableSet.of(NovaImageToImageTest.convertImage()); + Set hardwares = ImmutableSet.of(FlavorToHardwareTest.convertFlavor()); + Server server = ParseServerFromJsonResponseTest.parseServer(); + + ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, ImmutableMap + . of(), Suppliers.> ofInstance(images), Suppliers + .ofInstance(provider), Suppliers.> ofInstance(hardwares)); + + NodeMetadata metadata = parser.apply(server); + + assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses( + ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")) + .imageId("2").hardware( + new HardwareBuilder().ids("1").name("256 MB Server").processors( + ImmutableList.of(new Processor(1.0, 1.0))).ram(256).volumes( + ImmutableList.of(new VolumeBuilder().type(Volume.Type.LOCAL).size(10.0f).durable(true) + .bootDevice(true).build())).build()).operatingSystem( + new OperatingSystemBuilder().family(OsFamily.CENTOS).description("CentOS 5.2").version("5.2") + .is64Bit(true).build()).id("1234").providerId("1234").name("sample-server").location( + new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0") + .description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build()) + .userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build()); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/domain/ServerTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/domain/ServerTest.java new file mode 100644 index 0000000000..0c93f0cb3b --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/domain/ServerTest.java @@ -0,0 +1,49 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.domain; + +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code CreateImageBinder} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ServerTest { + public void testStatusDoesntAffectEquals() { + Server server1 = new Server(1, "hello"); + server1.setStatus(ServerStatus.ACTIVE); + Server server2 = new Server(1, "hello"); + server2.setStatus(ServerStatus.BUILD); + assertEquals(server1, server2); + } + + public void testProgressDoesntAffectEquals() { + Server server1 = new Server(1, "hello"); + server1.setProgress(1); + Server server2 = new Server(1, "hello"); + server2.setProgress(2); + assertEquals(server1, server2); + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseAddressesFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseAddressesFromJsonResponseTest.java new file mode 100644 index 0000000000..a7eb137961 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseAddressesFromJsonResponseTest.java @@ -0,0 +1,63 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; +import java.util.List; + +import org.jclouds.openstack.nova.domain.Addresses; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseAddressesFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseAddressesFromJsonResponseTest { + Injector i = Guice.createInjector(new GsonModule()); + + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_addresses.json"); + + UnwrapOnlyJsonValue parser = i.getInstance(Key.get(new TypeLiteral>() { + })); + Addresses response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + List publicAddresses = ImmutableList.of("67.23.10.132", "67.23.10.131"); + + List privateAddresses = ImmutableList.of("10.176.42.16"); + + assertEquals(response.getPublicAddresses(), publicAddresses); + assertEquals(response.getPrivateAddresses(), privateAddresses); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseBackupScheduleFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseBackupScheduleFromJsonResponseTest.java new file mode 100644 index 0000000000..3ce29a32e1 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseBackupScheduleFromJsonResponseTest.java @@ -0,0 +1,69 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; + +import org.jclouds.openstack.nova.domain.BackupSchedule; +import org.jclouds.openstack.nova.domain.DailyBackup; +import org.jclouds.openstack.nova.domain.WeeklyBackup; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseBackupScheduleFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseBackupScheduleFromJsonResponseTest { + Injector i = Guice.createInjector(new GsonModule()); + + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_backupschedule.json"); + + UnwrapOnlyJsonValue parser = i.getInstance(Key + .get(new TypeLiteral>() { + })); + BackupSchedule response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + assertEquals(new BackupSchedule(WeeklyBackup.THURSDAY, DailyBackup.H_0400_0600, true), response); + } + + public void testNoSchedule() throws UnknownHostException { + + UnwrapOnlyJsonValue parser = i.getInstance(Key + .get(new TypeLiteral>() { + })); + BackupSchedule response = parser.apply(new HttpResponse(200, "ok", Payloads + .newStringPayload("{\"backupSchedule\":{\"enabled\" : false}}"))); + assertEquals(new BackupSchedule(), response); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java new file mode 100644 index 0000000000..a7cc0dd176 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java @@ -0,0 +1,65 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.openstack.nova.domain.Flavor; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.gson.Gson; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseFlavorFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseFlavorFromJsonResponseTest { + public void test() { + Flavor response = parseFlavor(); + + String json = new Gson().toJson(response); + + assertEquals(json, "{\"id\":1,\"name\":\"256 MB Server\",\"disk\":10,\"ram\":256}"); + } + + public static Flavor parseFlavor() { + Injector i = Guice.createInjector(new GsonModule()); + + InputStream is = ParseFlavorFromJsonResponseTest.class.getResourceAsStream("/test_get_flavor_details.json"); + + UnwrapOnlyJsonValue parser = i.getInstance(Key.get(new TypeLiteral>() { + })); + Flavor response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + return response; + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java new file mode 100644 index 0000000000..cf2bfbeb83 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java @@ -0,0 +1,82 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; +import java.util.List; + +import org.jclouds.openstack.nova.domain.Flavor; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseFlavorListFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseFlavorListFromJsonResponseTest { + + Injector i = Guice.createInjector(new GsonModule()); + + public void testApplyInputStream() { + InputStream is = getClass().getResourceAsStream("/test_list_flavors.json"); + + List expects = ImmutableList.of(new Flavor(1, "256 MB Server"), new Flavor(2, "512 MB Server")); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + assertEquals(response, expects); + } + + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_flavors_detail.json"); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + assertEquals(response.get(0).getId(), 1); + assertEquals(response.get(0).getName(), "256 MB Server"); + assertEquals(response.get(0).getDisk(), new Integer(10)); + assertEquals(response.get(0).getRam(), new Integer(256)); + + assertEquals(response.get(1).getId(), 2); + assertEquals(response.get(1).getName(), "512 MB Server"); + assertEquals(response.get(1).getDisk(), new Integer(20)); + assertEquals(response.get(1).getRam(), new Integer(512)); + + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageFromJsonResponseTest.java new file mode 100644 index 0000000000..0e9694af57 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageFromJsonResponseTest.java @@ -0,0 +1,93 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; + +import org.jclouds.openstack.nova.domain.Image; +import org.jclouds.openstack.nova.domain.ImageStatus; +import org.jclouds.date.DateService; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.jclouds.json.config.GsonModule.DateAdapter; +import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseImageFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseImageFromJsonResponseTest { + Injector i = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + } + + }, new GsonModule()); + + DateService dateService = i.getInstance(DateService.class); + + public void testApplyInputStreamDetails() throws UnknownHostException { + Image response = parseImage(); + + assertEquals(response.getId(), 2); + assertEquals(response.getName(), "CentOS 5.2"); + assertEquals(response.getCreated(), dateService.iso8601SecondsDateParse("2010-08-10T12:00:00Z")); + assertEquals(response.getProgress(), new Integer(80)); + assertEquals(response.getServerId(), new Integer(12)); + assertEquals(response.getStatus(), ImageStatus.SAVING); + assertEquals(response.getUpdated(), dateService.iso8601SecondsDateParse(("2010-10-10T12:00:00Z"))); + + } + + public static Image parseImage() { + Injector i = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + } + + }, new GsonModule()); + + InputStream is = ParseImageFromJsonResponseTest.class.getResourceAsStream("/test_get_image_details.json"); + + UnwrapOnlyJsonValue parser = i.getInstance(Key.get(new TypeLiteral>() { + })); + Image response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + return response; + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageListFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageListFromJsonResponseTest.java new file mode 100644 index 0000000000..2e28d9814d --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseImageListFromJsonResponseTest.java @@ -0,0 +1,102 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; +import java.util.List; + +import org.jclouds.openstack.nova.domain.Image; +import org.jclouds.openstack.nova.domain.ImageStatus; +import org.jclouds.date.DateService; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.jclouds.json.config.GsonModule.DateAdapter; +import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseImageListFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseImageListFromJsonResponseTest { + Injector i = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + } + + },new GsonModule()); + DateService dateService = i.getInstance(DateService.class); + + public void testApplyInputStream() { + InputStream is = getClass().getResourceAsStream("/test_list_images.json"); + + List expects = ImmutableList.of(new Image(2, "CentOS 5.2"), new Image(743, "My Server Backup")); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response, expects); + } + + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_images_detail.json"); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response.get(0).getId(), 2); + assertEquals(response.get(0).getName(), "CentOS 5.2"); + assertEquals(response.get(0).getCreated(), dateService.iso8601SecondsDateParse("2010-08-10T12:00:00Z")); + assertEquals(response.get(0).getProgress(), null); + assertEquals(response.get(0).getServerId(), null); + assertEquals(response.get(0).getStatus(), ImageStatus.ACTIVE); + assertEquals(response.get(0).getUpdated(), dateService.iso8601SecondsDateParse("2010-10-10T12:00:00Z")); + + assertEquals(response.get(1).getId(), 743); + assertEquals(response.get(1).getName(), "My Server Backup"); + assertEquals(response.get(1).getCreated(), dateService.iso8601SecondsDateParse("2009-07-07T09:56:16-05:00")); + ; + assertEquals(response.get(1).getProgress(), new Integer(80)); + assertEquals(response.get(1).getServerId(), new Integer(12)); + assertEquals(response.get(1).getStatus(), ImageStatus.SAVING); + assertEquals(response.get(1).getUpdated(), dateService.iso8601SecondsDateParse("2010-10-10T12:00:00Z")); + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseInetAddressListFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseInetAddressListFromJsonResponseTest.java new file mode 100644 index 0000000000..60f8c2c1f2 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseInetAddressListFromJsonResponseTest.java @@ -0,0 +1,71 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; +import java.util.List; + +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseInetAddressListFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseInetAddressListFromJsonResponseTest { + + Injector i = Guice.createInjector(new GsonModule()); + + public void testPublic() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_addresses_public.json"); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response, ImmutableList.of("67.23.10.132", "67.23.10.131")); + } + + public void testPrivate() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_addresses_private.json"); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response, ImmutableList.of("10.176.42.16")); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerFromJsonResponseTest.java new file mode 100644 index 0000000000..dd18cc9001 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerFromJsonResponseTest.java @@ -0,0 +1,83 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; +import java.util.List; + +import org.jclouds.openstack.nova.domain.Addresses; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseServerFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseServerFromJsonResponseTest { + + public void testApplyInputStreamDetails() throws UnknownHostException { + Server response = parseServer(); + + assertEquals(response.getId(), 1234); + assertEquals(response.getName(), "sample-server"); + assertEquals(response.getImageId(), new Integer(2)); + assertEquals(response.getFlavorId(), new Integer(1)); + assertEquals(response.getHostId(), "e4d909c290d0fb1ca068ffaddf22cbd0"); + assertEquals(response.getStatus(), ServerStatus.BUILD); + assertEquals(response.getProgress(), new Integer(60)); + List publicAddresses = Lists.newArrayList("67.23.10.132", "67.23.10.131"); + List privateAddresses = Lists.newArrayList("10.176.42.16"); + Addresses addresses1 = new Addresses(); + addresses1.getPrivateAddresses().addAll(privateAddresses); + addresses1.getPublicAddresses().addAll(publicAddresses); + assertEquals(response.getAddresses(), addresses1); + assertEquals(response.getMetadata(), ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")); + + } + + public static Server parseServer() { + Injector i = Guice.createInjector(new GsonModule()); + + InputStream is = ParseServerFromJsonResponseTest.class.getResourceAsStream("/test_get_server_detail.json"); + + UnwrapOnlyJsonValue parser = i.getInstance(Key.get(new TypeLiteral>() { + })); + Server response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + return response; + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerListFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerListFromJsonResponseTest.java new file mode 100644 index 0000000000..321dfd5a27 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseServerListFromJsonResponseTest.java @@ -0,0 +1,107 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; +import java.util.List; + +import org.jclouds.openstack.nova.domain.Addresses; +import org.jclouds.openstack.nova.domain.Server; +import org.jclouds.openstack.nova.domain.ServerStatus; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseServerListFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseServerListFromJsonResponseTest { + + Injector i = Guice.createInjector(new GsonModule()); + + public void testApplyInputStream() { + InputStream is = getClass().getResourceAsStream("/test_list_servers.json"); + + List expects = ImmutableList.of(new Server(1234, "sample-server"), new Server(5678, "sample-server2")); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response, expects); + } + + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_servers_detail.json"); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response.get(0).getId(), 1234); + assertEquals(response.get(0).getName(), "sample-server"); + assertEquals(response.get(0).getImageId(), new Integer(2)); + assertEquals(response.get(0).getFlavorId(), new Integer(1)); + assertEquals(response.get(0).getHostId(), "e4d909c290d0fb1ca068ffaddf22cbd0"); + assertEquals(response.get(0).getStatus(), ServerStatus.BUILD); + assertEquals(response.get(0).getProgress(), new Integer(60)); + List publicAddresses = Lists.newArrayList("67.23.10.132", "67.23.10.131"); + List privateAddresses = Lists.newArrayList("10.176.42.16"); + Addresses addresses1 = new Addresses(); + addresses1.getPrivateAddresses().addAll(privateAddresses); + addresses1.getPublicAddresses().addAll(publicAddresses); + assertEquals(response.get(0).getAddresses(), addresses1); + assertEquals(response.get(0).getMetadata(), ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")); + assertEquals(response.get(1).getId(), 5678); + assertEquals(response.get(1).getName(), "sample-server2"); + assertEquals(response.get(1).getImageId(), new Integer(2)); + assertEquals(response.get(1).getFlavorId(), new Integer(1)); + assertEquals(response.get(1).getHostId(), "9e107d9d372bb6826bd81d3542a419d6"); + assertEquals(response.get(1).getStatus(), ServerStatus.ACTIVE); + assertEquals(response.get(1).getProgress(), null); + List publicAddresses2 = Lists.newArrayList("67.23.10.133"); + List privateAddresses2 = Lists.newArrayList("10.176.42.17"); + Addresses addresses2 = new Addresses(); + addresses2.getPrivateAddresses().addAll(privateAddresses2); + addresses2.getPublicAddresses().addAll(publicAddresses2); + assertEquals(response.get(1).getAddresses(), addresses2); + assertEquals(response.get(1).getMetadata(), ImmutableMap.of("Server Label", "DB 1")); + + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupFromJsonResponseTest.java new file mode 100644 index 0000000000..9cddc31676 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupFromJsonResponseTest.java @@ -0,0 +1,62 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; + +import org.jclouds.openstack.nova.domain.SharedIpGroup; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseSharedIpGroupFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseSharedIpGroupFromJsonResponseTest { + + Injector i = Guice.createInjector(new GsonModule()); + + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_get_sharedipgroup_details.json"); + + UnwrapOnlyJsonValue parser = i.getInstance(Key + .get(new TypeLiteral>() { + })); + SharedIpGroup response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response.getId(), 1234); + assertEquals(response.getName(), "Shared IP Group 1"); + assertEquals(response.getServers(), ImmutableList.of(422)); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupListFromJsonResponseTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupListFromJsonResponseTest.java new file mode 100644 index 0000000000..8c3d189f82 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseSharedIpGroupListFromJsonResponseTest.java @@ -0,0 +1,84 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; +import java.util.List; + +import org.jclouds.openstack.nova.domain.SharedIpGroup; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.io.Payloads; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseSharedIpGroupListFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseSharedIpGroupListFromJsonResponseTest { + + Injector i = Guice.createInjector(new GsonModule()); + + public void testApplyInputStream() { + InputStream is = getClass().getResourceAsStream("/test_list_sharedipgroups.json"); + + List expects = ImmutableList.of(new SharedIpGroup(1234, "Shared IP Group 1"), new SharedIpGroup( + 5678, "Shared IP Group 2")); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response, expects); + + } + + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/test_list_sharedipgroups_detail.json"); + + UnwrapOnlyJsonValue> parser = i.getInstance(Key + .get(new TypeLiteral>>() { + })); + List response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + + assertEquals(response.get(0).getId(), 1234); + assertEquals(response.get(0).getName(), "Shared IP Group 1"); + assertEquals(response.get(0).getServers(), ImmutableList.of(422, 3445)); + + assertEquals(response.get(1).getId(), 5678); + assertEquals(response.get(1).getName(), "Shared IP Group 2"); + assertEquals(response.get(1).getServers(), ImmutableList.of(23203, 2456, 9891)); + + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateServerOptionsTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateServerOptionsTest.java new file mode 100644 index 0000000000..c3bd13cb53 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateServerOptionsTest.java @@ -0,0 +1,141 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withFile; +import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withSharedIp; +import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withSharedIpGroup; +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import javax.ws.rs.HttpMethod; + +import org.jclouds.http.HttpRequest; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseFlavorFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class CreateServerOptionsTest { + + Injector injector = Guice.createInjector(new GsonModule()); + + @Test + public void testAddPayloadToRequestMapOfStringStringHttpRequest() { + CreateServerOptions options = new CreateServerOptions(); + HttpRequest request = buildRequest(options); + assertEquals("{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2}}", request.getPayload().getRawContent()); + } + + private HttpRequest buildRequest(CreateServerOptions options) { + injector.injectMembers(options); + HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost")); + options.bindToRequest(request, ImmutableMap.of("name", "foo", "imageId", "1", "flavorId", "2")); + return request; + } + + @Test + public void testWithFile() { + CreateServerOptions options = new CreateServerOptions(); + options.withFile("/tmp/rhubarb", "foo".getBytes()); + HttpRequest request = buildRequest(options); + assertFile(request); + } + + @Test + public void testWithFileStatic() { + CreateServerOptions options = withFile("/tmp/rhubarb", "foo".getBytes()); + HttpRequest request = buildRequest(options); + assertFile(request); + } + + private void assertFile(HttpRequest request) { + assertEquals( + "{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2,\"personality\":[{\"path\":\"/tmp/rhubarb\",\"contents\":\"Zm9v\"}]}}", + request.getPayload().getRawContent()); + } + + @Test + public void testWithSharedIpGroup() { + CreateServerOptions options = new CreateServerOptions(); + options.withSharedIpGroup(3); + HttpRequest request = buildRequest(options); + assertSharedIpGroup(request); + } + + @Test + public void testWithSharedIpGroupStatic() { + CreateServerOptions options = withSharedIpGroup(3); + HttpRequest request = buildRequest(options); + assertSharedIpGroup(request); + } + + private void assertSharedIpGroup(HttpRequest request) { + assertEquals("{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2,\"sharedIpGroupId\":3}}", request + .getPayload().getRawContent()); + } + + @Test + public void testWithMetadata() { + } + + @Test + public void testWithSharedIp() { + CreateServerOptions options = new CreateServerOptions(); + options.withSharedIpGroup(3).withSharedIp("127.0.0.1"); + HttpRequest request = buildRequest(options); + assertSharedIp(request); + } + + @Test + public void testWithSharedIpStatic() { + CreateServerOptions options = withSharedIpGroup(3).withSharedIp("127.0.0.1"); + HttpRequest request = buildRequest(options); + assertSharedIp(request); + } + + private void assertSharedIp(HttpRequest request) { + assertEquals( + "{\"server\":{\"name\":\"foo\",\"imageId\":1,\"flavorId\":2,\"sharedIpGroupId\":3,\"addresses\":{\"public\":[\"127.0.0.1\"]}}}", + request.getPayload().getRawContent()); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWithSharedIpNoGroup() { + CreateServerOptions options = new CreateServerOptions(); + options.withSharedIp("127.0.0.1"); + buildRequest(options); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWithSharedIpNoGroupStatic() { + CreateServerOptions options = withSharedIp("127.0.0.1"); + buildRequest(options); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptionsTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptionsTest.java new file mode 100644 index 0000000000..87722806a0 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/CreateSharedIpGroupOptionsTest.java @@ -0,0 +1,80 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import static org.jclouds.openstack.nova.options.CreateSharedIpGroupOptions.Builder.withServer; +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import javax.ws.rs.HttpMethod; + +import org.jclouds.http.HttpRequest; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseFlavorFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class CreateSharedIpGroupOptionsTest { + + Injector injector = Guice.createInjector(new GsonModule()); + + @Test + public void testAddPayloadToRequestMapOfStringStringHttpRequest() { + CreateSharedIpGroupOptions options = new CreateSharedIpGroupOptions(); + HttpRequest request = buildRequest(options); + assertEquals("{\"sharedIpGroup\":{\"name\":\"foo\"}}", request.getPayload().getRawContent()); + } + + private HttpRequest buildRequest(CreateSharedIpGroupOptions options) { + injector.injectMembers(options); + HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost")); + options.bindToRequest(request, ImmutableMap.of("name", "foo")); + return request; + } + + @Test + public void testWithServer() { + CreateSharedIpGroupOptions options = new CreateSharedIpGroupOptions(); + options.withServer(3); + HttpRequest request = buildRequest(options); + assertSharedIpGroup(request); + } + + @Test + public void testWithServerStatic() { + CreateSharedIpGroupOptions options = withServer(3); + HttpRequest request = buildRequest(options); + assertSharedIpGroup(request); + } + + private void assertSharedIpGroup(HttpRequest request) { + assertEquals("{\"sharedIpGroup\":{\"name\":\"foo\",\"server\":3}}", request.getPayload().getRawContent()); + } + +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/ListOptionsTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/ListOptionsTest.java new file mode 100644 index 0000000000..f5f91b51a0 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/ListOptionsTest.java @@ -0,0 +1,89 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import static org.jclouds.openstack.nova.options.ListOptions.Builder.changesSince; +import static org.jclouds.openstack.nova.options.ListOptions.Builder.maxResults; +import static org.jclouds.openstack.nova.options.ListOptions.Builder.startAt; +import static org.jclouds.openstack.nova.options.ListOptions.Builder.withDetails; +import static org.testng.Assert.assertEquals; + +import java.util.Date; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +/** + * Tests behavior of {@code ListOptions} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ListOptionsTest { + + public void testWithDetails() { + ListOptions options = new ListOptions().withDetails(); + assertEquals(options.buildPathSuffix(), "/detail"); + } + + public void testWithDetailsStatic() { + ListOptions options = withDetails(); + assertEquals(options.buildPathSuffix(), "/detail"); + } + + public void testChangesSince() { + Date ifModifiedSince = new Date(); + ListOptions options = new ListOptions().changesSince(ifModifiedSince); + assertEquals(ImmutableList.of(ifModifiedSince.getTime() / 1000 + ""), options + .buildQueryParameters().get("changes-since")); + } + + public void testStartAt() { + long offset = 1; + ListOptions options = new ListOptions().startAt(offset); + assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("offset")); + } + + public void testMaxResults() { + int limit = 1; + ListOptions options = new ListOptions().maxResults(limit); + assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit")); + } + + public void testChangesSinceStatic() { + Date ifModifiedSince = new Date(); + ListOptions options = changesSince(ifModifiedSince); + assertEquals(ImmutableList.of(ifModifiedSince.getTime() / 1000 + ""), options + .buildQueryParameters().get("changes-since")); + } + + public void testStartAtStatic() { + long offset = 1; + ListOptions options = startAt(offset); + assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("offset")); + } + + public void testMaxResultsStatic() { + int limit = 1; + ListOptions options = maxResults(limit); + assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit")); + } +} diff --git a/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/RebuildServerOptionsTest.java b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/RebuildServerOptionsTest.java new file mode 100644 index 0000000000..963b2fb5c6 --- /dev/null +++ b/sandbox-apis/nova/src/test/java/org/jclouds/openstack/nova/options/RebuildServerOptionsTest.java @@ -0,0 +1,80 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.openstack.nova.options; + +import static org.jclouds.openstack.nova.options.RebuildServerOptions.Builder.withImage; +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.HashMap; + +import javax.ws.rs.HttpMethod; + +import org.jclouds.http.HttpRequest; +import org.jclouds.json.config.GsonModule; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseFlavorFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class RebuildServerOptionsTest { + + Injector injector = Guice.createInjector(new GsonModule()); + + @Test + public void testAddPayloadToRequestMapOfStringStringHttpRequest() { + RebuildServerOptions options = new RebuildServerOptions(); + HttpRequest request = buildRequest(options); + assertEquals("{\"rebuild\":{}}", request.getPayload().getRawContent()); + } + + private HttpRequest buildRequest(RebuildServerOptions options) { + injector.injectMembers(options); + HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost")); + options.bindToRequest(request, new HashMap()); + return request; + } + + @Test + public void testWithServer() { + RebuildServerOptions options = new RebuildServerOptions(); + options.withImage(3); + HttpRequest request = buildRequest(options); + assertRebuild(request); + } + + @Test + public void testWithServerStatic() { + RebuildServerOptions options = withImage(3); + HttpRequest request = buildRequest(options); + assertRebuild(request); + } + + private void assertRebuild(HttpRequest request) { + assertEquals("{\"rebuild\":{\"imageId\":3}}", request.getPayload().getRawContent()); + } + +} diff --git a/sandbox-apis/nova/src/test/resources/log4j.xml b/sandbox-apis/nova/src/test/resources/log4j.xml new file mode 100755 index 0000000000..5b548a0f48 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/log4j.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sandbox-apis/nova/src/test/resources/test_get_flavor_details.json b/sandbox-apis/nova/src/test/resources/test_get_flavor_details.json new file mode 100644 index 0000000000..28500d2d6b --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_get_flavor_details.json @@ -0,0 +1,8 @@ +{ + "flavor" : { + "id" : 1, + "name" : "256 MB Server", + "ram" : 256, + "disk" : 10 + } +} diff --git a/sandbox-apis/nova/src/test/resources/test_get_image_details.json b/sandbox-apis/nova/src/test/resources/test_get_image_details.json new file mode 100644 index 0000000000..e73095bb77 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_get_image_details.json @@ -0,0 +1,11 @@ +{ + "image" : { + "id" : 2, + "name" : "CentOS 5.2", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2010-08-10T12:00:00Z", + "status" : "SAVING", + "progress" : 80 + } +} \ No newline at end of file diff --git a/sandbox-apis/nova/src/test/resources/test_get_server_detail.json b/sandbox-apis/nova/src/test/resources/test_get_server_detail.json new file mode 100644 index 0000000000..c90bb0bc96 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_get_server_detail.json @@ -0,0 +1,25 @@ +{ + "server" : { + "id" : 1234, + "name" : "sample-server", + "imageId" : 2, + "flavorId" : 1, + "hostId" : "e4d909c290d0fb1ca068ffaddf22cbd0", + "status" : "BUILD", + "progress" : 60, + "addresses" : { + "public" : [ + "67.23.10.132", + "67.23.10.131" + ], + "private" : [ + "10.176.42.16" + ] + }, + "metadata" : { + "Server Label" : "Web Head 1", + "Image Version" : "2.1" + } + } + +} diff --git a/sandbox-apis/nova/src/test/resources/test_get_sharedipgroup_details.json b/sandbox-apis/nova/src/test/resources/test_get_sharedipgroup_details.json new file mode 100644 index 0000000000..d10f33d656 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_get_sharedipgroup_details.json @@ -0,0 +1,7 @@ +{ + "sharedIpGroup" : { + "id" : 1234, + "name" : "Shared IP Group 1", + "servers" : [422] + } +} \ No newline at end of file diff --git a/sandbox-apis/nova/src/test/resources/test_list_addresses.json b/sandbox-apis/nova/src/test/resources/test_list_addresses.json new file mode 100644 index 0000000000..24441b8fac --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_addresses.json @@ -0,0 +1,12 @@ +{ + "addresses" : { + "public" : [ + "67.23.10.132", + "67.23.10.131" + ], + "private" : [ + "10.176.42.16" + ] + } +} + diff --git a/sandbox-apis/nova/src/test/resources/test_list_addresses_private.json b/sandbox-apis/nova/src/test/resources/test_list_addresses_private.json new file mode 100644 index 0000000000..8c14cf3b93 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_addresses_private.json @@ -0,0 +1,8 @@ +{ + + "private" : [ + "10.176.42.16" + ] + +} + diff --git a/sandbox-apis/nova/src/test/resources/test_list_addresses_public.json b/sandbox-apis/nova/src/test/resources/test_list_addresses_public.json new file mode 100644 index 0000000000..22982ccb40 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_addresses_public.json @@ -0,0 +1,7 @@ +{ + "public" : [ + "67.23.10.132", + "67.23.10.131" + ] +} + diff --git a/sandbox-apis/nova/src/test/resources/test_list_backupschedule.json b/sandbox-apis/nova/src/test/resources/test_list_backupschedule.json new file mode 100644 index 0000000000..c2f893a506 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_backupschedule.json @@ -0,0 +1,7 @@ +{ + "backupSchedule" : { + "enabled" : true, + "weekly" : "THURSDAY", + "daily" : "H_0400_0600" + } +} \ No newline at end of file diff --git a/sandbox-apis/nova/src/test/resources/test_list_flavors.json b/sandbox-apis/nova/src/test/resources/test_list_flavors.json new file mode 100644 index 0000000000..d1cc9bee93 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_flavors.json @@ -0,0 +1,12 @@ +{ + "flavors" : [ + { + "id" : 1, + "name" : "256 MB Server" + }, + { + "id" : 2, + "name" : "512 MB Server" + } + ] +} diff --git a/sandbox-apis/nova/src/test/resources/test_list_flavors_detail.json b/sandbox-apis/nova/src/test/resources/test_list_flavors_detail.json new file mode 100644 index 0000000000..a274908f9b --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_flavors_detail.json @@ -0,0 +1,16 @@ +{ + "flavors" : [ + { + "id" : 1, + "name" : "256 MB Server", + "ram" : 256, + "disk" : 10 + }, + { + "id" : 2, + "name" : "512 MB Server", + "ram" : 512, + "disk" : 20 + } + ] +} diff --git a/sandbox-apis/nova/src/test/resources/test_list_images.json b/sandbox-apis/nova/src/test/resources/test_list_images.json new file mode 100644 index 0000000000..0c5cb251ad --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_images.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "id" : 2, + "name" : "CentOS 5.2" + }, + { + "id" : 743, + "name" : "My Server Backup" + } + ] +} diff --git a/sandbox-apis/nova/src/test/resources/test_list_images_detail.json b/sandbox-apis/nova/src/test/resources/test_list_images_detail.json new file mode 100644 index 0000000000..bdafc2ded3 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_images_detail.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "id" : 2, + "name" : "CentOS 5.2", + "updated" : "2010-10-10T12:00:00Z", + "created" : "2010-08-10T12:00:00Z", + "status" : "ACTIVE" + }, + { + "id" : 743, + "name" : "My Server Backup", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2009-07-07T09:56:16-05:00", + "status" : "SAVING", + "progress" : 80 + } + ] +} diff --git a/sandbox-apis/nova/src/test/resources/test_list_servers.json b/sandbox-apis/nova/src/test/resources/test_list_servers.json new file mode 100644 index 0000000000..3be518e566 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_servers.json @@ -0,0 +1,12 @@ +{ + "servers" : [ + { + "id" : 1234, + "name" : "sample-server" + }, + { + "id" : 5678, + "name" : "sample-server2" + } + ] +} diff --git a/sandbox-apis/nova/src/test/resources/test_list_servers_detail.json b/sandbox-apis/nova/src/test/resources/test_list_servers_detail.json new file mode 100644 index 0000000000..a9bc29aa1e --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_servers_detail.json @@ -0,0 +1,45 @@ +{ + "servers" : [ + { + "id" : 1234, + "name" : "sample-server", + "imageId" : 2, + "flavorId" : 1, + "hostId" : "e4d909c290d0fb1ca068ffaddf22cbd0", + "status" : "BUILD", + "progress" : 60, + "addresses" : { + "public" : [ + "67.23.10.132", + "67.23.10.131" + ], + "private" : [ + "10.176.42.16" + ] + }, + "metadata" : { + "Server Label" : "Web Head 1", + "Image Version" : "2.1" + } + }, + { + "id" : 5678, + "name" : "sample-server2", + "imageId" : 2, + "flavorId" : 1, + "hostId" : "9e107d9d372bb6826bd81d3542a419d6", + "status" : "ACTIVE", + "addresses" : { + "public" : [ + "67.23.10.133" + ], + "private" : [ + "10.176.42.17" + ] + }, + "metadata" : { + "Server Label" : "DB 1" + } + } + ] +} diff --git a/sandbox-apis/nova/src/test/resources/test_list_sharedipgroups.json b/sandbox-apis/nova/src/test/resources/test_list_sharedipgroups.json new file mode 100644 index 0000000000..73717c4a76 --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_sharedipgroups.json @@ -0,0 +1,12 @@ +{ + "sharedIpGroups" : [ + { + "id" : 1234, + "name" : "Shared IP Group 1" + }, + { + "id" : 5678, + "name" : "Shared IP Group 2" + } + ] +} \ No newline at end of file diff --git a/sandbox-apis/nova/src/test/resources/test_list_sharedipgroups_detail.json b/sandbox-apis/nova/src/test/resources/test_list_sharedipgroups_detail.json new file mode 100644 index 0000000000..de6e37336b --- /dev/null +++ b/sandbox-apis/nova/src/test/resources/test_list_sharedipgroups_detail.json @@ -0,0 +1,14 @@ +{ + "sharedIpGroups" : [ + { + "id" : 1234, + "name" : "Shared IP Group 1", + "servers" : [422, 3445] + }, + { + "id" : 5678, + "name" : "Shared IP Group 2", + "servers" : [23203, 2456, 9891] + } + ] +} \ No newline at end of file