http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/ApiKeyPairs.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/ApiKeyPairs.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/ApiKeyPairs.java new file mode 100644 index 0000000..4b702b0 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/ApiKeyPairs.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.util; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.Set; + +import org.jclouds.Constants; +import org.jclouds.ContextBuilder; +import org.jclouds.cloudstack.CloudStackApiMetadata; +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.Account; +import org.jclouds.cloudstack.domain.ApiKeyPair; +import org.jclouds.cloudstack.domain.User; + +public class ApiKeyPairs { + + /** + * Retrieve the API key pair for a given CloudStack user + * + * @param endpoint + * CloudStack API endpoint (e.g. http://72.52.126.25/client/api/) + * @param username + * User account name + * @param password + * User password + * @param domain + * Domain name. If empty defaults to ROOT + * @throws NoSuchElementException, AuthorizationException + * @return + */ + public static ApiKeyPair loginToEndpointAsUsernameInDomainWithPasswordAndReturnApiKeyPair( + URI endpoint, String username, String password, String domain) { + CloudStackContext context = null; + try { + Properties overrides = new Properties(); + overrides.put(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.put(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.put("jclouds.cloudstack.credential-type", "passwordCredentials"); + + context = ContextBuilder.newBuilder(new CloudStackApiMetadata()) + .endpoint(checkNotNull(endpoint, "endpoint").toASCIIString()) + .credentials(String.format("%s/%s", checkNotNull(domain, "domain"), checkNotNull(username, "username")), password) + .overrides(overrides).build(CloudStackContext.class); + + CloudStackApi client = context.getApi(); + Set<Account> listOfAccounts = client.getAccountApi().listAccounts(); + + domain = (domain.equals("") || domain.equals("/")) ? "ROOT" : domain; + for (Account account : listOfAccounts) { + for (User user : account.getUsers()) { + if (user.getName().equals(username) && user.getDomain().equals(domain)) { + return ApiKeyPair.builder().apiKey(user.getApiKey()) + .secretKey(user.getSecretKey()).build(); + } + } + } + throw new NoSuchElementException("Unable to find API keypair for user " + username); + + } finally { + if (context != null) + context.close(); + } + } + +}
http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java new file mode 100644 index 0000000..5cf7790 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.util; + +import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; + +/** + * Methods to create SnapshotPolicySchedule objects in the format required by Cloudstack. + */ +public class SnapshotPolicySchedules { + public static SnapshotPolicySchedule hourly(int minute) { + return SnapshotPolicySchedule.builder().interval(Snapshot.Interval.HOURLY).time(String.format("%02d", minute)).build(); + } + + public static SnapshotPolicySchedule daily(int hour, int minute) { + return SnapshotPolicySchedule.builder().interval(Snapshot.Interval.DAILY).time(String.format("%02d:%02d", minute, hour)).build(); + } + + public static SnapshotPolicySchedule weekly(int day, int hour, int minute) { + return SnapshotPolicySchedule.builder().interval(Snapshot.Interval.WEEKLY).time(String.format("%02d:%02d:%02d", minute, hour, day)).build(); + } + + public static SnapshotPolicySchedule monthly(int day, int hour, int minute) { + return SnapshotPolicySchedule.builder().interval(Snapshot.Interval.MONTHLY).time(String.format("%02d:%02d:%02d", minute, hour, day)).build(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata new file mode 100644 index 0000000..ad45dce --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata @@ -0,0 +1 @@ +org.jclouds.cloudstack.CloudStackApiMetadata \ No newline at end of file http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackApiMetadataTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackApiMetadataTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackApiMetadataTest.java new file mode 100644 index 0000000..ad2f376 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackApiMetadataTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack; + +import org.jclouds.compute.internal.BaseComputeServiceApiMetadataTest; +import org.testng.annotations.Test; + +@Test(groups = "unit", testName = "CloudStackApiMetadataTest") +public class CloudStackApiMetadataTest extends BaseComputeServiceApiMetadataTest { + + public CloudStackApiMetadataTest() { + super(new CloudStackApiMetadata()); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackContextBuilderTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackContextBuilderTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackContextBuilderTest.java new file mode 100644 index 0000000..04999aa --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/CloudStackContextBuilderTest.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack; + +import static org.jclouds.reflect.Reflection2.typeToken; + +import org.jclouds.ContextBuilder; +import org.jclouds.View; +import org.jclouds.compute.ComputeServiceContext; +import org.testng.annotations.Test; + +@Test(groups = "unit", testName = "CloudStackContextBuilderTest") +public class CloudStackContextBuilderTest { + + public void testAssignability() { + View view = ContextBuilder.newBuilder(new CloudStackApiMetadata()).credentials("foo", "bar") + .buildView(typeToken(ComputeServiceContext.class)); + view.unwrapApi(CloudStackApi.class); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java new file mode 100644 index 0000000..d669ebd --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack; + +import static org.testng.Assert.assertNotNull; + +import java.util.Properties; + +import org.jclouds.cloudstack.features.AccountApi; +import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +import com.google.common.net.HttpHeaders; + +/** + * + * @see CloudStackProperties#CREDENTIAL_TYPE + */ +@Test(groups = "unit", testName = "PasswordAuthenticationExpectTest") +public class PasswordAuthenticationExpectTest extends BaseCloudStackExpectTest<AccountApi> { + + /** + * this reflects the properties that a user would pass to createContext + */ + @Override + protected Properties setupProperties() { + Properties contextProperties = super.setupProperties(); + contextProperties.setProperty("jclouds.cloudstack.credential-type", "passwordCredentials"); + return contextProperties; + } + + public void testLoginWithPasswordSetsSessionKeyAndCookie() { + + AccountApi client = requestsSendResponses( + login, loginResponse, + HttpRequest.builder() + .method("GET") + .endpoint("http://localhost:8080/client/api?response=json&command=listAccounts&listAll=true&sessionkey=" + Strings2.urlEncode(sessionKey, '/')) + .addHeader("Accept", "application/json") + .addHeader(HttpHeaders.COOKIE, "JSESSIONID=" + jSessionId) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/listaccountsresponse.json")) + .build(), + logout, logoutResponse); + + assertNotNull(client.listAccounts()); + } + + @Override + protected AccountApi clientFrom(CloudStackContext context) { + return context.getApi().getAccountApi(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java new file mode 100644 index 0000000..877b0fe --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java @@ -0,0 +1,455 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.compute; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.io.IOException; +import java.util.Map; + +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; +import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter; +import org.jclouds.cloudstack.domain.VirtualMachine; +import org.jclouds.cloudstack.internal.BaseCloudStackComputeServiceContextExpectTest; +import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Injector; + +/** + * Tests the compute service abstraction of the cloudstack api. + */ +@Test(groups = "unit") +public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackComputeServiceContextExpectTest<Injector> { + HttpResponse deployVMResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/deployvirtualmachineresponse.json")) + .build(); + + HttpRequest queryAsyncJobResult = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "queryAsyncJobResult") + .addQueryParam("jobid", "50006") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "v8BWKMxd%2BIzHIuTaZ9sNSzCWqFI%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse queryAsyncJobResultResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/queryasyncjobresultresponse-virtualmachine.json")) + .build(); + + HttpResponse queryAsyncJobResultSecurityGroupResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/queryasyncjobresultresponse-virtualmachine-securitygroup.json")) + .build(); + + HttpRequest queryAsyncJobResultAuthorizeIngress = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "queryAsyncJobResult") + .addQueryParam("jobid", "13330fc9-8b3e-4582-aa3e-90883c041010") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "y4gk3ckWAMPDNZM26LUK0gAhfiE%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse queryAsyncJobResultAuthorizeIngressResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/queryasyncjobresultresponse-authorizeingress.json")) + .build(); + + HttpRequest listCapabilitiesNotListAll = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "listCapabilities") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "l3PVoJnKK2G2gHk3HPHtpwWjlW4%3D") + .addHeader("Accept", "application/json") + .build(); + + public void testCreateNodeWithGroupEncodedIntoName() { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "1") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "4") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("networkids", "204") + .addQueryParam("group", "test") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "M2Wx0CgOeH9vYHhbcbblwziqpwI%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listProjects, listProjectsResponse) + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksResponse) + .put(getZone, getZoneResponse) + .put(deployVM, deployVMResponse) + .put(queryAsyncJobResult, queryAsyncJobResultResponse) + .build(); + + Injector forNode = requestsSendResponses(requestResponseMap); + + Template template = forNode.getInstance(TemplateBuilder.class).osFamily(OsFamily.CENTOS).build(); + template.getOptions().as(CloudStackTemplateOptions.class).setupStaticNat(false); + + CloudStackComputeServiceAdapter adapter = forNode.getInstance(CloudStackComputeServiceAdapter.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertEquals(server.getCredentials(), LoginCredentials.builder().password("dD7jwajkh").build()); + } + + public void testCreateNodeWithGroupEncodedIntoNameWithKeyPair() throws IOException { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "1") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "4") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("networkids", "204") + .addQueryParam("group", "test") + .addQueryParam("keypair", "mykeypair") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "D3qQlTNjxrBXeG82C7YPrwU1jMc%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listProjects, listProjectsResponse) + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksResponse) + .put(getZone, getZoneResponse) + .put(deployVM, deployVMResponse) + .put(queryAsyncJobResult, queryAsyncJobResultResponse) + .build(); + + Injector forKeyPair = requestsSendResponses(requestResponseMap); + + String privKey = Strings2.toStringAndClose(getClass().getResourceAsStream("/test")); + Template template = forKeyPair.getInstance(TemplateBuilder.class).osFamily(OsFamily.CENTOS).build(); + template.getOptions().as(CloudStackTemplateOptions.class).keyPair("mykeypair") + .setupStaticNat(false) + .overrideLoginPrivateKey(privKey); + + CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertEquals(server.getCredentials().getOptionalPrivateKey().get(), privKey); + } + + public void testCreateNodeWithGroupEncodedIntoNameWithGenerateKeyPair() throws IOException { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "1") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "4") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("networkids", "204") + .addQueryParam("group", "test") + .addQueryParam("keypair", "jclouds-test") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "kfU/J/REa4DdYj0b/pSjuB3h3Qc%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listProjects, listProjectsResponse) + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksResponse) + .put(getZone, getZoneResponse) + .put(deployVM, deployVMResponse) + .put(createSSHKeyPair, createSSHKeyPairResponse) + .put(queryAsyncJobResult, queryAsyncJobResultResponse) + .build(); + + Injector forKeyPair = requestsSendResponses(requestResponseMap); + + Template template = forKeyPair.getInstance(TemplateBuilder.class).osFamily(OsFamily.CENTOS).build(); + template.getOptions().as(CloudStackTemplateOptions.class).generateKeyPair(true) + .setupStaticNat(false); + + CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertTrue(server.getCredentials().getOptionalPrivateKey().isPresent()); + } + + public void testCreateNodeWithGroupEncodedIntoNameWithKeyPairDefaultSecurityGroup() throws IOException { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "2") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "241") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("networkids", "204") + .addQueryParam("group", "test") + .addQueryParam("keypair", "mykeypair") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "5qkUSGh0y%2BP/t04/j3%2BEN9PAeFI%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listProjects, listProjectsResponse) + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksWithSecurityGroupsResponse) + .put(getZoneWithSecurityGroups, getZoneWithSecurityGroupsResponse) + .put(deployVM, deployVMResponse) + .put(queryAsyncJobResult, queryAsyncJobResultResponse) + .build(); + + Injector forKeyPair = requestsSendResponses(requestResponseMap); + + String privKey = Strings2.toStringAndClose(getClass().getResourceAsStream("/test")); + Template template = forKeyPair.getInstance(TemplateBuilder.class) + .osFamily(OsFamily.CENTOS) + .locationId("2") + .build(); + template.getOptions().as(CloudStackTemplateOptions.class).keyPair("mykeypair") + .setupStaticNat(false) + .overrideLoginPrivateKey(privKey); + + CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertEquals(server.getCredentials().getOptionalPrivateKey().get(), privKey); + } + + public void testCreateNodeWithGroupEncodedIntoNameWithKeyPairDefaultSecurityGroupAndDisk() throws IOException { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "2") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "241") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("networkids", "204") + .addQueryParam("group", "test") + .addQueryParam("keypair", "mykeypair") + .addQueryParam("diskofferingid", "5678") + .addQueryParam("size", "10") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "lDzBXtVKCktueskyI/haID9ohJU%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listProjects, listProjectsResponse) + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksWithSecurityGroupsResponse) + .put(getZoneWithSecurityGroups, getZoneWithSecurityGroupsResponse) + .put(deployVM, deployVMResponse) + .put(queryAsyncJobResult, queryAsyncJobResultResponse) + .build(); + + Injector forKeyPair = requestsSendResponses(requestResponseMap); + + String privKey = Strings2.toStringAndClose(getClass().getResourceAsStream("/test")); + Template template = forKeyPair.getInstance(TemplateBuilder.class) + .osFamily(OsFamily.CENTOS) + .locationId("2") + .build(); + template.getOptions().as(CloudStackTemplateOptions.class).keyPair("mykeypair") + .diskOfferingId("5678") + .dataDiskSize(10) + .setupStaticNat(false) + .overrideLoginPrivateKey(privKey); + + + CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertEquals(server.getCredentials().getOptionalPrivateKey().get(), privKey); + } + + public void testCreateNodeWithGroupEncodedIntoNameWithKeyPairGenerateSecurityGroup() throws IOException { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "2") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "241") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("networkids", "204") + .addQueryParam("group", "test") + .addQueryParam("keypair", "mykeypair") + .addQueryParam("securitygroupids", "30") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "rz8V/tMk/UbxUhNqp7Bq3CrSg/k%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listProjects, listProjectsResponse) + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksWithSecurityGroupsResponse) + .put(getZoneWithSecurityGroups, getZoneWithSecurityGroupsResponse) + .put(deployVM, deployVMResponse) + .put(queryAsyncJobResult, queryAsyncJobResultSecurityGroupResponse) + .put(queryAsyncJobResultAuthorizeIngress, queryAsyncJobResultAuthorizeIngressResponse) + .put(getSecurityGroup, getSecurityGroupResponse) + .put(createSecurityGroup, createSecurityGroupResponse) + .put(authorizeIngress, authorizeIngressResponse) + .build(); + + Injector forKeyPair = requestsSendResponses(requestResponseMap); + + String privKey = Strings2.toStringAndClose(getClass().getResourceAsStream("/test")); + Template template = forKeyPair.getInstance(TemplateBuilder.class) + .osFamily(OsFamily.CENTOS) + .locationId("2") + .build(); + template.getOptions().as(CloudStackTemplateOptions.class).keyPair("mykeypair") + .setupStaticNat(false) + .generateSecurityGroup(true) + .overrideLoginPrivateKey(privKey); + + CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + CloudStackContext context = forKeyPair.getInstance(CloudStackContext.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertEquals(server.getCredentials().getOptionalPrivateKey().get(), privKey); + } + + public void testCreateNodeWithGroupEncodedIntoNameWithKeyPairAssignedToAccountAndDomain() throws IOException { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "1") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "4") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("account", "account") // + .addQueryParam("domainid", "domainId") // + .addQueryParam("networkids", "204") + .addQueryParam("group", "test") + .addQueryParam("keypair", "mykeypair") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "hGV6gZZakwvNKhTJurkm48%2Bzgso%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listProjects, listProjectsResponse) + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksResponse) + .put(getZone, getZoneResponse) + .put(deployVM, deployVMResponse) + .put(queryAsyncJobResult, queryAsyncJobResultResponse) + .build(); + + Injector forKeyPair = requestsSendResponses(requestResponseMap); + + String privKey = Strings2.toStringAndClose(getClass().getResourceAsStream("/test")); + Template template = forKeyPair.getInstance(TemplateBuilder.class).osFamily(OsFamily.CENTOS).build(); + template.getOptions().as(CloudStackTemplateOptions.class).keyPair("mykeypair") + .account("account") + .domainId("domainId") + .setupStaticNat(false) + .overrideLoginPrivateKey(privKey); + + CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + CloudStackContext context = forKeyPair.getInstance(CloudStackContext.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertEquals(server.getCredentials().getOptionalPrivateKey().get(), privKey); + } + + @Override + protected Injector clientFrom(CloudStackContext context) { + return context.utils().injector(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java new file mode 100644 index 0000000..6f926c1 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.compute; +import static com.google.common.collect.Iterables.getFirst; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.util.Map; +import java.util.Random; + + +import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; +import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter; +import org.jclouds.cloudstack.domain.IPForwardingRule; +import org.jclouds.cloudstack.domain.ServiceOffering; +import org.jclouds.cloudstack.domain.VirtualMachine; +import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest; +import org.jclouds.cloudstack.predicates.TemplatePredicates; +import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials; +import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; +import org.jclouds.domain.Credentials; +import org.jclouds.ssh.SshKeys; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.net.HostAndPort; +import com.google.common.net.InetAddresses; + +@Test(groups = "live", singleThreaded = true, testName = "CloudStackComputeServiceAdapterLiveTest") +public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackApiLiveTest { + + private CloudStackComputeServiceAdapter adapter; + private NodeAndInitialCredentials<VirtualMachine> vm; + + private String keyPairName; + private Map<String, String> keyPair; + Map<String, Credentials> credentialStore = Maps.newLinkedHashMap(); + + @BeforeGroups(groups = { "live" }) + public void setupContext() { + super.setupContext(); + + adapter = context.utils().injector().getInstance( + CloudStackComputeServiceAdapter.class); + + keyPairName = prefix + "-adapter-test-keypair"; + keyPair = SshKeys.generate(); + + client.getSSHKeyPairApi().deleteSSHKeyPair(keyPairName); + client.getSSHKeyPairApi().registerSSHKeyPair(keyPairName, keyPair.get("public")); + } + + @Test + public void testListLocations() { + assertFalse(Iterables.isEmpty(adapter.listLocations())); + } + + private static final PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate = new PrioritizeCredentialsFromTemplate( + new DefaultCredentialsFromImageOrOverridingCredentials()); + + @Test + public void testCreateNodeWithGroupEncodedIntoName() { + String group = prefix + "-foo"; + String name = group + "-node-" + new Random().nextInt(); + Template template = view.getComputeService().templateBuilder().build(); + + if (!client + .getTemplateApi() + .getTemplateInZone(template.getImage().getId(), + template.getLocation().getId()).isPasswordEnabled()) { + + // TODO: look at SecurityGroupApiLiveTest for how to do this + template.getOptions().as(CloudStackTemplateOptions.class).keyPair(keyPairName); + } + vm = adapter.createNodeWithGroupEncodedIntoName(group, name, template); + + assertEquals(vm.getNode().getDisplayName(), name); + // check to see if we setup a NAT rule (conceding we could check this from + // cache) + IPForwardingRule rule = getFirst( + client.getNATApi().getIPForwardingRulesForVirtualMachine(vm.getNode().getId()), null); + + String address = rule != null ? rule.getIPAddress() : vm.getNode().getIPAddress(); + + loginCredentials = prioritizeCredentialsFromTemplate.apply(template, vm.getCredentials()); + + assert InetAddresses.isInetAddress(address) : vm; + HostAndPort socket = HostAndPort.fromParts(address, 22); + checkSSH(socket); + } + + @Test + public void testListHardwareProfiles() { + Iterable<ServiceOffering> profiles = adapter.listHardwareProfiles(); + assertFalse(Iterables.isEmpty(profiles)); + + for (ServiceOffering profile : profiles) { + // TODO: check that the results are valid + } + } + + @Test + public void testListImages() { + Iterable<org.jclouds.cloudstack.domain.Template> templates = adapter.listImages(); + assertFalse(Iterables.isEmpty(templates)); + + for (org.jclouds.cloudstack.domain.Template template : templates) { + assert TemplatePredicates.isReady().apply(template) : template; + } + } + + @AfterGroups(groups = "live") + @Override + protected void tearDownContext() { + if (vm != null) + adapter.destroyNode(vm.getNodeId()); + super.tearDownContext(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceLiveTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceLiveTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceLiveTest.java new file mode 100644 index 0000000..7cc6d40 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceLiveTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.compute; + +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.internal.BaseComputeServiceLiveTest; +import org.jclouds.sshj.config.SshjSshClientModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Module; + +/** + * + * Generally disabled, as it incurs higher fees. + */ +@Test(groups = "live", enabled = true, singleThreaded = true) +public class CloudStackComputeServiceLiveTest extends BaseComputeServiceLiveTest { + public CloudStackComputeServiceLiveTest() { + provider = "cloudstack"; + } + + @Override + protected Module getSshModule() { + return new SshjSshClientModule(); + } + + // cloudstack does not support metadata + @Override + protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) { + assert node.getUserMetadata().equals(ImmutableMap.<String, String> of()) : String.format( + "node userMetadata did not match %s %s", userMetadata, node); + } + + @Override + public void testOptionToNotBlock() { + // start call blocks until we static nat, which is long enough to reach + // running state + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackExperimentLiveTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackExperimentLiveTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackExperimentLiveTest.java new file mode 100644 index 0000000..7affab0 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/CloudStackExperimentLiveTest.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.compute; + +import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; +import org.jclouds.cloudstack.domain.Network; +import org.jclouds.cloudstack.domain.TrafficType; +import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest; +import org.jclouds.cloudstack.options.ListNetworksOptions; +import org.jclouds.compute.RunNodesException; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.predicates.NodePredicates; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.get; +import static com.google.common.collect.Sets.newTreeSet; +import static org.jclouds.cloudstack.options.CreateNetworkOptions.Builder.vlan; +import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder.specifyVLAN; + +@Test(groups = "live", testName = "CloudStackExperimentLiveTest") +public class CloudStackExperimentLiveTest extends BaseCloudStackApiLiveTest { + + public CloudStackExperimentLiveTest() { + provider = "cloudstack"; + } + + protected void deleteNetworksInZoneWithVlanId(String zoneId, String vlanId) { + Set<Network> networks = domainAdminClient.getNetworkApi().listNetworks( + ListNetworksOptions.Builder + .isDefault(false) + .isSystem(false) + .zoneId(zoneId) + .trafficType(TrafficType.GUEST) + ); + + // Warning: the vlan id is not set in the response - using an workaround + URI broadcastUri = URI.create("vlan://" + vlanId); + for (Network net : networks) { + if (broadcastUri.equals(net.getBroadcastURI())) { + String jobId = domainAdminClient.getNetworkApi().deleteNetwork(net.getId()); + adminJobComplete.apply(jobId); + } + } + } + + @Test + public void testAndExperiment() { + if (!domainAdminEnabled) { + Logger.getAnonymousLogger().log(Level.SEVERE, "domainAdmin credentials not present, skipping test"); + return; + } + + String group = prefix + "-vlan"; + String vlanId = "2"; + Network network = null; + Set<? extends NodeMetadata> nodes = null; + try { + assert !view.getComputeService().listAssignableLocations().isEmpty(); + + Template template = view.getComputeService().templateBuilder().build(); + + // get the zone we are launching into + String zoneId = template.getLocation().getId(); + + // cleanup before running the test + deleteNetworksInZoneWithVlanId(zoneId, vlanId); + + // find a network offering that supports vlans in our zone + String offeringId = get( + cloudStackContext.getApi().getOfferingApi().listNetworkOfferings(specifyVLAN(true).zoneId(zoneId)), 0).getId(); + + // create an arbitrary network + network = domainAdminClient + .getNetworkApi() + // startIP/endIP/netmask/gateway must be specified together + .createNetworkInZone(zoneId, offeringId, group, group, + vlan(vlanId).startIP("192.168.1.2").netmask("255.255.255.0").gateway("192.168.1.1")); + + // set options to specify this network id + template.getOptions().as(CloudStackTemplateOptions.class).networks(network.getId()); + + // launch the VM + nodes = view.getComputeService().createNodesInGroup(group, 1, template); + + assert !nodes.isEmpty(); + + } catch (RunNodesException e) { + Logger.getAnonymousLogger().log(Level.SEVERE, "error creating nodes", e); + nodes = newTreeSet(concat(e.getSuccessfulNodes(), e.getNodeErrors().keySet())); + } finally { + if (nodes != null) + view.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group)); + if (network != null) + domainAdminClient.getNetworkApi().deleteNetwork(network.getId()); + } + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java new file mode 100644 index 0000000..8b1db02 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.compute.extensions; + +import static org.testng.Assert.assertEquals; + +import java.util.Map; +import java.util.Properties; + +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.internal.BaseCloudStackComputeServiceContextExpectTest; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageTemplate; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Futures; +import com.google.inject.Module; + +@Test(groups = "unit", testName = "CloudStackImageExtensionExpectTest") +public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeServiceContextExpectTest<ComputeService> { + + @Override + protected Properties setupProperties() { + Properties overrides = super.setupProperties(); + overrides.setProperty("jclouds.zones", "MTV-Zone1"); + return overrides; + } + + public void testCreateImage() { + HttpRequest listVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "listVirtualMachines") + .addQueryParam("listAll", "true") + .addQueryParam("id", "3239ade9-fd25-405c-8eda-59f0313a3fb0") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "Qq7Br3qNsyr5ifWZHIrLAslhwm0%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse listVMResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/listvirtualmachinesresponse-imageextension.json")) + .build(); + + HttpRequest stopVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "stopVirtualMachine") + .addQueryParam("id", "3239ade9-fd25-405c-8eda-59f0313a3fb0") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "y9vxRK61K8sDoWtvSJHIx5WO9AE%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse stopVMResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/stopvirtualmachineresponse-imageextension.json")) + .build(); + + HttpRequest stopAsyncJobResult = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "queryAsyncJobResult") + .addQueryParam("jobid", "a7d5127b-24a2-4a44-a4a7-25a6d057b453") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "CVpnN%2FSbx%2FMCOOyj%2FoVAt3bn684%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse stopAsyncJobResultResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/queryasyncjobresultresponse-stopvirtualmachine-imageextension.json")) + .build(); + + HttpRequest listVolumes = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "listVolumes") + .addQueryParam("listAll", "true") + .addQueryParam("virtualmachineid", "3239ade9-fd25-405c-8eda-59f0313a3fb0") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "drLPf9NE9ROZPOfeDkASiKa50t8%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse listVolumesResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/listvolumesresponse-imageextension.json")) + .build(); + + + HttpRequest createTemplate = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "createTemplate") + .addQueryParam("volumeid", "fe1ada16-57a0-40ae-b577-01a153690fb4") + .addQueryParam("name", "temp-template-ignore") + .addQueryParam("ostypeid", "45de18f1-87c6-4646-8099-95c61f2a300a") + .addQueryParam("displaytext", "temp-template-ignore") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "madHsBgxjYbM6JnZKYWajOlfPlY%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse createTemplateResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/createtemplateresponse-imageextension.json")) + .build(); + + HttpRequest createAsyncJobResult = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "queryAsyncJobResult") + .addQueryParam("jobid", "4e345230-8fcc-48a3-8a37-c5fe960df671") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "6mTKL9fjz7bn6C7tOaZBzKdZwHs%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse createAsyncJobResultResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/queryasyncjobresultresponse-createtemplate-imageextension.json")) + .build(); + + HttpRequest getTemplate = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "listTemplates") + .addQueryParam("listAll", "true") + .addQueryParam("templatefilter", "executable") + .addQueryParam("id", "3dc6ce25-a6cf-4d60-a664-3499993b511b") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "dXv%2Bl04EDd7hmrWv5CdW8v298RE%3D") + .addHeader("Accept", "application/json") + .build(); + + HttpResponse getTemplateResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/listtemplatesresponse-imageextension.json")) + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksResponse) + .put(getZone, getZoneResponse) + .put(listVM, listVMResponse) + .put(stopVM, stopVMResponse) + .put(stopAsyncJobResult, stopAsyncJobResultResponse) + .put(listVolumes, listVolumesResponse) + .put(createTemplate, createTemplateResponse) + .put(createAsyncJobResult, createAsyncJobResultResponse) + .put(getTemplate, getTemplateResponse) + .build(); + + ImageExtension apiThatCreatesImage = requestsSendResponses(requestResponseMap).getImageExtension().get(); + + ImageTemplate newImageTemplate = apiThatCreatesImage.buildImageTemplateFromNode("temp-template-ignore", "3239ade9-fd25-405c-8eda-59f0313a3fb0"); + + Image image = Futures.getUnchecked(apiThatCreatesImage.createImage(newImageTemplate)); + assertEquals(image.getId(), "3dc6ce25-a6cf-4d60-a664-3499993b511b"); + } + + @Override + public ComputeService createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) { + return clientFrom(createInjector(fn, module, props).getInstance(CloudStackContext.class)); + } + + @Override + protected ComputeService clientFrom(CloudStackContext context) { + return context.getComputeService(); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/86fd5cf2/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionLiveTest.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionLiveTest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionLiveTest.java new file mode 100644 index 0000000..9eff8e6 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionLiveTest.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.cloudstack.compute.extensions; + +import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest; +import org.jclouds.sshj.config.SshjSshClientModule; +import org.testng.annotations.Test; + +import com.google.inject.Module; + +/** + * Live test for CloudStack {@link ImageExtension} implementation. + */ +@Test(groups = "live", singleThreaded = true, testName = "CloudStackImageExtensionLiveTest") +public class CloudStackImageExtensionLiveTest extends BaseImageExtensionLiveTest { + + public CloudStackImageExtensionLiveTest() { + provider = "cloudstack"; + } + + @Override + protected Module getSshModule() { + return new SshjSshClientModule(); + } + +}
