Issue 158: Added retryable predicate to check that login information is available.

This commit is contained in:
Adrian Cole 2011-09-30 22:35:54 -07:00
commit b599b30f99
6 changed files with 133 additions and 15 deletions

View File

@ -39,7 +39,7 @@ public class SoftLayerPropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_ENDPOINT, "https://api.softlayer.com/rest");
properties.setProperty(PROPERTY_API_VERSION, "3");
properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME, "Cloud Server");
properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_ORDER_DELAY, "5000");
properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY, "3000000");
properties.setProperty(PROPERTY_ISO3166_CODES, "SG,US-CA,US-TX,US-VA,US-WA,US-TX");
return properties;
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.softlayer.compute.strategy;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
@ -28,6 +29,7 @@ import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.ProductItems;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
@ -44,6 +46,7 @@ import java.util.Set;
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 static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
@ -61,12 +64,21 @@ public class SoftLayerComputeServiceAdapter implements
private final SoftLayerClient client;
private final String virtualGuestPackageName;
private final RetryablePredicate<VirtualGuest> loginDetailsTester;
private final long guestLoginDelay;
@Inject
public SoftLayerComputeServiceAdapter(SoftLayerClient client,
@Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName) {
@Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName,
VirtualGuestHasLoginDetailsPresent virtualGuestHasLoginDetailsPresent,
@Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY) long guestLoginDelay) {
this.client = checkNotNull(client, "client");
this.virtualGuestPackageName = checkNotNull(virtualGuestPackageName, "virtualGuestPackageName");
checkArgument(guestLoginDelay > 500, "guestOrderDelay must be in milliseconds and greater than 500");
this.guestLoginDelay =guestLoginDelay;
this.loginDetailsTester = new RetryablePredicate<VirtualGuest>(virtualGuestHasLoginDetailsPresent,
guestLoginDelay);
}
@Override
@ -89,18 +101,13 @@ public class SoftLayerComputeServiceAdapter implements
ProductOrderReceipt productOrderReceipt = client.getVirtualGuestClient().orderVirtualGuest(order);
VirtualGuest result = Iterables.get(productOrderReceipt.getOrderDetails().getVirtualGuests(), 0);
boolean orderInSystem = loginDetailsTester.apply(result);
Credentials credentials = new Credentials(null, null);
checkState(orderInSystem, "order for guest %s doesn't have login details within %sms", result, Long.toString(guestLoginDelay));
result = client.getVirtualGuestClient().getVirtualGuest(result.getId());
// This information is not always available.
OperatingSystem os = result.getOperatingSystem();
if (os != null) {
Set<Password> passwords = os.getPasswords();
if (passwords.size() > 0) {
Password pw = Iterables.get(passwords, 0);
credentials = new Credentials(pw.getUsername(), pw.getPassword());
}
}
Password pw = Iterables.get(result.getOperatingSystem().getPasswords(),0);
Credentials credentials = new Credentials(pw.getUsername(), pw.getPassword());
credentialStore.put("node#" + result.getId(), credentials);
return result;
}
@ -210,4 +217,25 @@ public class SoftLayerComputeServiceAdapter implements
public void suspendNode(String id) {
client.getVirtualGuestClient().pauseVirtualGuest(Long.parseLong(id));
}
public static class VirtualGuestHasLoginDetailsPresent implements Predicate<VirtualGuest> {
private final SoftLayerClient client;
@Inject
public VirtualGuestHasLoginDetailsPresent(SoftLayerClient client) {
this.client = checkNotNull(client, "client was null");
}
@Override
public boolean apply(VirtualGuest guest) {
checkNotNull(guest, "virtual guest was null");
VirtualGuest newGuest = client.getVirtualGuestClient().getVirtualGuest(guest.getId());
boolean hasBackendIp = newGuest.getPrimaryBackendIpAddress() != null;
boolean hasPrimaryIp = newGuest.getPrimaryIpAddress() != null;
boolean hasPasswords = newGuest.getOperatingSystem()!=null && newGuest.getOperatingSystem().getPasswords().size() > 0;
return hasBackendIp && hasPrimaryIp && hasPasswords;
}
}
}

View File

@ -38,7 +38,7 @@ public interface SoftLayerConstants {
/**
* number of milliseconds to wait for an order to arrive on the api.
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_ORDER_DELAY = "jclouds.softlayer.virtualguest.order-delay";
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY = "jclouds.softlayer.virtualguest.order-delay";
public static final Set<ProductItemPrice> DEFAULT_VIRTUAL_GUEST_PRICES = ImmutableSet.<ProductItemPrice>builder()
.add(ProductItemPrice.builder().id(1639).build()) // 100 GB (SAN)

View File

@ -56,7 +56,8 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
public void setupClient() {
super.setupClient();
adapter = new SoftLayerComputeServiceAdapter(context.getApi(),
ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME);
ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME,
new SoftLayerComputeServiceAdapter.VirtualGuestHasLoginDetailsPresent(context.getApi()),300000);
}
@Test

View File

@ -0,0 +1,89 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.softlayer.compute;
import com.google.inject.Module;
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.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import java.io.IOException;
import static org.testng.Assert.assertEquals;
/**
*
* Generally disabled, as it incurs higher fees.
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true)
public class SoftLayerComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public SoftLayerComputeServiceLiveTest() {
provider = "softlayer";
}
@Override
protected Module getSshModule() {
return new SshjSshClientModule();
}
public void testAssignability() throws Exception {
@SuppressWarnings("unused")
RestContext<SoftLayerClient, SoftLayerAsyncClient> tmContext = new ComputeServiceContextFactory()
.createContext(provider, identity, credential).getProviderSpecificContext();
}
@Override
protected void checkNodes(Iterable<? extends NodeMetadata> 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();
}
}