blob: a64c3f75c5710a926b0e860a779bde72fa423d5e [file] [log] [blame]
/*
* 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.apache.jclouds.profitbricks.rest.compute.config;
import com.google.common.base.Function;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.jclouds.profitbricks.rest.ProfitBricksApi;
import org.apache.jclouds.profitbricks.rest.compute.ProfitBricksComputeServiceAdapter;
import org.apache.jclouds.profitbricks.rest.compute.concurrent.ProvisioningJob;
import org.apache.jclouds.profitbricks.rest.compute.concurrent.ProvisioningManager;
import org.apache.jclouds.profitbricks.rest.compute.extensions.ProfitBricksImageExtension;
import org.apache.jclouds.profitbricks.rest.compute.function.ProvisionableToImage;
import org.apache.jclouds.profitbricks.rest.compute.function.ServerInDataCenterToNodeMetadata;
import org.apache.jclouds.profitbricks.rest.compute.function.VolumeToVolume;
import org.apache.jclouds.profitbricks.rest.compute.strategy.AssignDataCenterToTemplate;
import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_MAX_PERIOD;
import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PERIOD;
import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PREDICATE_DATACENTER;
import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PREDICATE_NIC;
import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PREDICATE_SERVER;
import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PREDICATE_SNAPSHOT;
import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_TIMEOUT;
import org.apache.jclouds.profitbricks.rest.domain.DataCenter;
import org.apache.jclouds.profitbricks.rest.domain.Nic;
import org.apache.jclouds.profitbricks.rest.domain.Provisionable;
import org.apache.jclouds.profitbricks.rest.domain.Server;
import org.apache.jclouds.profitbricks.rest.domain.State;
import org.apache.jclouds.profitbricks.rest.domain.zonescoped.ServerInDataCenter;
import org.apache.jclouds.profitbricks.rest.ids.NicRef;
import org.apache.jclouds.profitbricks.rest.ids.ServerRef;
import org.apache.jclouds.profitbricks.rest.ids.VolumeRef;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl;
import org.jclouds.compute.domain.internal.TemplateBuilderImpl;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.lifecycle.Closer;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone;
import org.jclouds.util.PasswordGenerator;
import static org.jclouds.util.Predicates2.retry;
public class ProfitBricksComputeServiceContextModule extends
ComputeServiceAdapterContextModule<ServerInDataCenter, Hardware, Provisionable, Location> {
@SuppressWarnings("unchecked")
@Override
protected void configure() {
super.configure();
install(new FactoryModuleBuilder().build(ProvisioningJob.Factory.class));
bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstZone.class).in(Scopes.SINGLETON);
bind(CreateNodesInGroupThenAddToSet.class).to(AssignDataCenterToTemplate.class).in(Scopes.SINGLETON);
bind(new TypeLiteral<ComputeServiceAdapter<ServerInDataCenter, Hardware, Provisionable, Location>>() {
}).to(ProfitBricksComputeServiceAdapter.class);
bind(TemplateBuilderImpl.class).to(ArbitraryCpuRamTemplateBuilderImpl.class);
bind(new TypeLiteral<Function<ServerInDataCenter, NodeMetadata>>() {
}).to(ServerInDataCenterToNodeMetadata.class);
bind(new TypeLiteral<Function<Provisionable, Image>>() {
}).to(ProvisionableToImage.class);
bind(new TypeLiteral<Function<org.apache.jclouds.profitbricks.rest.domain.Volume, Volume>>() {
}).to(VolumeToVolume.class);
bind(new TypeLiteral<Function<Hardware, Hardware>>() {
}).to(Class.class.cast(IdentityFunction.class));
bind(new TypeLiteral<ImageExtension>() {
}).to(ProfitBricksImageExtension.class);
}
@Provides
@Singleton
protected PasswordGenerator.Config providePasswordGenerator() {
return new PasswordGenerator()
.lower().min(2).max(10).exclude("ilowyz".toCharArray())
.upper().min(2).max(10).exclude("IOWYZ".toCharArray())
.numbers().min(2).max(10).exclude("10".toCharArray())
.symbols().count(0);
}
@Provides
@Singleton
@Named(POLL_PREDICATE_DATACENTER)
Predicate<String> provideDataCenterAvailablePredicate(final ProfitBricksApi api, ComputeConstants constants) {
return retry(new DataCenterProvisioningStatePredicate(
api, State.AVAILABLE),
constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
}
@Provides
@Named(TIMEOUT_NODE_RUNNING)
Predicate<ServerRef> provideServerRunningPredicate(final ProfitBricksApi api, ComputeConstants constants) {
return retry(new ServerStatusPredicate(
api, Server.Status.RUNNING),
constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
}
@Provides
@Named(TIMEOUT_NODE_SUSPENDED)
Predicate<ServerRef> provideServerSuspendedPredicate(final ProfitBricksApi api, ComputeConstants constants) {
return retry(new ServerStatusPredicate(
api, Server.Status.SHUTOFF),
constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
}
@Provides
@Named(POLL_PREDICATE_SERVER)
Predicate<ServerRef> provideServerAvailablePredicate(final ProfitBricksApi api, ComputeConstants constants) {
return retry(new ServerAvaiblablePredicate(
api, State.AVAILABLE),
constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
}
@Provides
@Singleton
ProvisioningManager provideProvisioningManager(Closer closer) {
ProvisioningManager provisioningManager = new ProvisioningManager();
closer.addToClose(provisioningManager);
return provisioningManager;
}
@Provides
@Singleton
@Named(POLL_PREDICATE_SNAPSHOT)
Predicate<String> provideSnapshotAvailablePredicate(final ProfitBricksApi api, ComputeConstants constants) {
return retry(new SnapshotProvisioningStatePredicate(
api, State.AVAILABLE),
constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named(TIMEOUT_NODE_RUNNING)
Predicate<VolumeRef> provideVolumeAvailablePredicate(final ProfitBricksApi api, ComputeConstants constants) {
return retry(new VolumeProvisoningStatusPredicate(
api, State.AVAILABLE),
constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named(POLL_PREDICATE_NIC)
Predicate<NicRef> provideNicAvailablePredicate(final ProfitBricksApi api, ProfitBricksComputeServiceContextModule.ComputeConstants constants) {
return retry(new NicAvailable(
api, State.AVAILABLE),
constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
}
static class DataCenterProvisioningStatePredicate implements Predicate<String> {
private final ProfitBricksApi api;
private final State expectedState;
public DataCenterProvisioningStatePredicate(ProfitBricksApi api, State expectedState) {
this.api = checkNotNull(api, "api must not be null");
this.expectedState = checkNotNull(expectedState, "expectedState must not be null");
}
@Override
public boolean apply(String input) {
checkNotNull(input, "datacenter id");
DataCenter dataCenter = api.dataCenterApi().getDataCenter(input);
return dataCenter.metadata().state() == expectedState;
}
}
static class ServerAvaiblablePredicate implements Predicate<ServerRef> {
private final ProfitBricksApi api;
private final State expectedState;
public ServerAvaiblablePredicate(ProfitBricksApi api, State expectedState) {
this.api = checkNotNull(api, "api must not be null");
this.expectedState = checkNotNull(expectedState, "expectedState must not be null");
}
@Override
public boolean apply(ServerRef serverRef) {
checkNotNull(serverRef, "serverRef");
//give time for the operation to actually start
Uninterruptibles.sleepUninterruptibly(10, TimeUnit.SECONDS);
Server server = api.serverApi().getServer(serverRef.dataCenterId(), serverRef.serverId());
if (server == null || server.metadata() == null) {
return false;
}
return server.metadata().state().toString().equals(expectedState.toString());
}
}
static class ServerStatusPredicate implements Predicate<ServerRef> {
private final ProfitBricksApi api;
private final Server.Status expectedStatus;
public ServerStatusPredicate(ProfitBricksApi api, Server.Status expectedStatus) {
this.api = checkNotNull(api, "api must not be null");
this.expectedStatus = checkNotNull(expectedStatus, "expectedStatus must not be null");
}
@Override
public boolean apply(ServerRef serverRef) {
checkNotNull(serverRef, "serverRef");
//give time for the operation to actually start
Uninterruptibles.sleepUninterruptibly(10, TimeUnit.SECONDS);
Server server = api.serverApi().getServer(serverRef.dataCenterId(), serverRef.serverId());
if (server == null || server.properties().vmState() == null) {
return false;
}
return server.properties().vmState() == expectedStatus;
}
}
static class SnapshotProvisioningStatePredicate implements Predicate<String> {
private final ProfitBricksApi api;
private final State expectedState;
public SnapshotProvisioningStatePredicate(ProfitBricksApi api, State expectedState) {
this.api = checkNotNull(api, "api must not be null");
this.expectedState = checkNotNull(expectedState, "expectedState must not be null");
}
@Override
public boolean apply(String input) {
checkNotNull(input, "snapshot id");
return api.snapshotApi().get(input).metadata().state().toString().equals(expectedState.toString());
}
}
static class VolumeProvisoningStatusPredicate implements Predicate<VolumeRef> {
private final ProfitBricksApi api;
private final State expectedState;
public VolumeProvisoningStatusPredicate(ProfitBricksApi api, State expectedState) {
this.api = checkNotNull(api, "api must not be null");
this.expectedState = checkNotNull(expectedState, "expectedState must not be null");
}
@Override
public boolean apply(VolumeRef input) {
checkNotNull(input, "Volume REF");
org.apache.jclouds.profitbricks.rest.domain.Volume volume = api.volumeApi().getVolume(input.dataCenterId(), input.volumeId());
if (volume == null || volume.metadata() == null || volume.metadata().state() == null) {
return false;
}
return volume.metadata().state().toString().equals(expectedState.toString());
}
}
static class NicAvailable implements Predicate<NicRef> {
private final ProfitBricksApi api;
private final State expectedState;
public NicAvailable(ProfitBricksApi api, State expectedState) {
this.api = checkNotNull(api, "api must not be null");
this.expectedState = checkNotNull(expectedState, "expectedState must not be null");
}
@Override
public boolean apply(NicRef input) {
checkNotNull(input, "NicRef ");
Nic nice = api.nicApi().get(input.dataCenterId(), input.serverId(), input.nicId());
if (nice == null || nice.metadata() == null || nice.metadata().state() == null) {
return false;
}
return nice.metadata().state().toString().equals(expectedState.toString());
}
}
@Singleton
public static class ComputeConstants {
@Inject
@Named(POLL_TIMEOUT)
private String pollTimeout;
@Inject
@Named(POLL_PERIOD)
private String pollPeriod;
@Inject
@Named(POLL_MAX_PERIOD)
private String pollMaxPeriod;
public long pollTimeout() {
return Long.parseLong(pollTimeout);
}
public long pollPeriod() {
return Long.parseLong(pollPeriod);
}
public long pollMaxPeriod() {
return Long.parseLong(pollMaxPeriod);
}
}
}