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/CloudStackGlobalApi.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java new file mode 100644 index 0000000..0e77d84 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java @@ -0,0 +1,127 @@ +/* + * 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.cloudstack.features.GlobalAccountApi; +import org.jclouds.cloudstack.features.GlobalAlertApi; +import org.jclouds.cloudstack.features.GlobalCapacityApi; +import org.jclouds.cloudstack.features.GlobalConfigurationApi; +import org.jclouds.cloudstack.features.GlobalDomainApi; +import org.jclouds.cloudstack.features.GlobalHostApi; +import org.jclouds.cloudstack.features.GlobalOfferingApi; +import org.jclouds.cloudstack.features.GlobalPodApi; +import org.jclouds.cloudstack.features.GlobalStoragePoolApi; +import org.jclouds.cloudstack.features.GlobalUsageApi; +import org.jclouds.cloudstack.features.GlobalUserApi; +import org.jclouds.cloudstack.features.GlobalVlanApi; +import org.jclouds.cloudstack.features.GlobalZoneApi; +import org.jclouds.rest.annotations.Delegate; + +/** + * Provides synchronous access to CloudStack. + * <p/> + * + * @see <a href= + * "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html" + * /> + */ +public interface CloudStackGlobalApi extends CloudStackDomainApi { + + /** + * Provides synchronous access to Accounts + */ + @Delegate + @Override + GlobalAccountApi getAccountApi(); + + /** + * Provides synchronous access to Users + */ + @Delegate + @Override + GlobalUserApi getUserClient(); + + /** + * Provides synchronous access to Alerts + */ + @Delegate + GlobalAlertApi getAlertClient(); + + /** + * Provides synchronous access to Capacities + */ + @Delegate + GlobalCapacityApi getCapacityClient(); + + /** + * Provides synchronous access to Offerings + */ + @Delegate + @Override + GlobalOfferingApi getOfferingApi(); + + /** + * Provides synchronous access to Hosts + */ + @Delegate + GlobalHostApi getHostClient(); + + /** + * Provides synchronous access to Storage Pools + */ + @Delegate + GlobalStoragePoolApi getStoragePoolClient(); + + /** + * Provides synchronous access to Usage + */ + @Delegate + GlobalUsageApi getUsageClient(); + + /** + * Provides synchronous access to Configuration + */ + @Delegate + @Override + GlobalConfigurationApi getConfigurationApi(); + + /** + * Provides synchronous access to Domain + */ + @Delegate + @Override + GlobalDomainApi getDomainClient(); + + /** + * Provides synchronous access to Zone + */ + @Delegate + @Override + GlobalZoneApi getZoneApi(); + + /** + * Provides synchronous access to Pod + */ + @Delegate + GlobalPodApi getPodClient(); + + /** + * Provides synchronous access to Vlan + */ + @Delegate + GlobalVlanApi getVlanClient(); +}
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/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java new file mode 100644 index 0000000..b99e644 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java @@ -0,0 +1,55 @@ +/* + * 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.binders; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.http.Uris.uriBuilder; +import static org.jclouds.http.utils.Queries.queryParser; + +import java.net.URI; +import java.util.Map.Entry; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableMultimap.Builder; +import com.google.common.collect.Multimap; + +@Singleton +public class BindAccountSecurityGroupPairsToIndexedQueryParams implements Binder { + + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + checkArgument(input instanceof Multimap<?, ?>, "this binder is only valid for Multimaps!"); + Multimap<String, String> pairs = (Multimap<String, String>) checkNotNull(input, "account group pairs"); + checkArgument(!pairs.isEmpty(), "you must specify at least one account, group pair"); + + Multimap<String, String> existingParams = queryParser().apply(request.getEndpoint().getQuery()); + Builder<String, String> map = ImmutableMultimap.<String, String> builder().putAll(existingParams); + int i = 0; + for (Entry<String, String> entry : pairs.entries()) + map.put(String.format("usersecuritygrouplist[%d].account", i), entry.getKey()).put( + String.format("usersecuritygrouplist[%d].group", i++), entry.getValue()); + URI endpoint = uriBuilder(request.getEndpoint()).query(map.build()).build(); + return (R) request.toBuilder().endpoint(endpoint).build(); + } +} 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/binders/BindCIDRsToCommaDelimitedQueryParam.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.java new file mode 100644 index 0000000..28adf91 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.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.binders; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; + +@Singleton +public class BindCIDRsToCommaDelimitedQueryParam implements Binder { + + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + checkArgument(input instanceof Iterable<?>, "this binder is only valid for Iterables!"); + Iterable<String> cidrs = (Iterable<String>) checkNotNull(input, "cidr list"); + checkArgument(!Iterables.isEmpty(cidrs), "you must specify at least one cidr range"); + return (R) request.toBuilder().replaceQueryParam("cidrlist", Joiner.on(',').join(cidrs)).build(); + } +} 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/binders/BindIdListToCommaDelimitedQueryParam.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java new file mode 100644 index 0000000..f4b3813 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.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.binders; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; + +@Singleton +public class BindIdListToCommaDelimitedQueryParam implements Binder { + + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + checkArgument(input instanceof Iterable<?>, "this binder is only valid for Iterables!"); + Iterable<Long> numbers = (Iterable<Long>) checkNotNull(input, "list of Longs"); + checkArgument(!Iterables.isEmpty(numbers), "you must specify at least one element"); + return (R) request.toBuilder().replaceQueryParam("ids", Joiner.on(',').join(numbers)).build(); + } +} 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/binders/BindSnapshotPolicyScheduleToQueryParam.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java new file mode 100644 index 0000000..d80f4ba --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java @@ -0,0 +1,43 @@ +/* + * 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.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import javax.inject.Singleton; + +import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableMultimap.Builder; + +@Singleton +public class BindSnapshotPolicyScheduleToQueryParam implements Binder { + + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + checkArgument(input instanceof SnapshotPolicySchedule, "this binder is only valid for SnapshotPolicySchedule"); + SnapshotPolicySchedule schedule = SnapshotPolicySchedule.class.cast(input); + Builder<String, String> builder = ImmutableMultimap.<String, String> builder(); + builder.put("intervaltype", schedule.getInterval().toString()); + builder.put("schedule", schedule.getTime().toString()); + return (R) request.toBuilder().replaceQueryParams(builder.build()).build(); + } +} 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/binders/BindTemplateMetadataToQueryParams.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java new file mode 100644 index 0000000..e61990c --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java @@ -0,0 +1,53 @@ +/* + * 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.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import org.jclouds.cloudstack.domain.TemplateMetadata; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableMultimap.Builder; + +public class BindTemplateMetadataToQueryParams implements Binder { + + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + checkArgument(input instanceof TemplateMetadata, "this binder is only valid for TemplateMetadata"); + TemplateMetadata metadata = (TemplateMetadata) input; + Builder<String, String> builder = ImmutableMultimap.<String, String>builder(); + builder.put("name", metadata.getName()); + builder.put("ostypeid", metadata.getOsTypeId()); + builder.put("displaytext", metadata.getDisplayText()); + if (metadata.getSnapshotId() != null) { + builder.put("snapshotid", metadata.getSnapshotId()); + } + if (metadata.getVolumeId() != null) { + builder.put("volumeid", metadata.getVolumeId()); + } + if (metadata.getVirtualMachineId() != null) { + builder.put("virtualmachineid", metadata.getVirtualMachineId()); + } + if (metadata.isPasswordEnabled() != null) { + builder.put("passwordenabled", metadata.isPasswordEnabled().toString()); + } + return (R) request.toBuilder().replaceQueryParams(builder.build()).build(); + } +} 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/binders/ResourceLimitToQueryParams.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java new file mode 100644 index 0000000..847fea5 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java @@ -0,0 +1,48 @@ +/* + * 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.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import org.jclouds.cloudstack.domain.ResourceLimit; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableMultimap.Builder; + +/** + * + * @see <a href= + * "http://download.cloud.com/releases/2.2.0/api_2.2.12/domain_admin/updateResourceLimit.html" + * /> + */ +public class ResourceLimitToQueryParams implements Binder { + + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + checkArgument(input instanceof ResourceLimit, "this binder is only valid for ResourceLimit"); + ResourceLimit limit = (ResourceLimit) input; + Builder<String, String> builder = ImmutableMultimap.<String, String> builder(); + builder.put("resourcetype", limit.getResourceType().getCode() + ""); + builder.put("account", limit.getAccount()); + builder.put("domainid", limit.getDomainId()); + builder.put("max", limit.getMax() + ""); + return (R) request.toBuilder().replaceQueryParams(builder.build()).build(); + } +} 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/compute/CloudStackComputeService.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java new file mode 100644 index 0000000..1109cbb --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java @@ -0,0 +1,180 @@ +/* + * 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.base.Preconditions.checkNotNull; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; +import static org.jclouds.cloudstack.predicates.SshKeyPairPredicates.nameMatches; +import static org.jclouds.cloudstack.predicates.ZonePredicates.supportsSecurityGroups; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.jclouds.Constants; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.callables.RunScriptOnNode; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.extensions.SecurityGroupExtension; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.compute.internal.BaseComputeService; +import org.jclouds.compute.internal.PersistNodeCredentials; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; +import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; +import org.jclouds.compute.strategy.DestroyNodeStrategy; +import org.jclouds.compute.strategy.GetImageStrategy; +import org.jclouds.compute.strategy.GetNodeMetadataStrategy; +import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap; +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.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; +import org.jclouds.cloudstack.domain.SecurityGroup; +import org.jclouds.cloudstack.domain.SshKeyPair; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.domain.ZoneAndName; +import org.jclouds.cloudstack.predicates.SecurityGroupPredicates; +import org.jclouds.scriptbuilder.functions.InitAdminAccess; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; +import com.google.common.util.concurrent.ListeningExecutorService; + +@Singleton +public class CloudStackComputeService extends BaseComputeService { + protected final CloudStackApi client; + protected final LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap; + protected final LoadingCache<String, SshKeyPair> keyPairCache; + protected final Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId; + protected final GroupNamingConvention.Factory namingConvention; + protected final Supplier<LoadingCache<String, Zone>> zoneIdToZone; + + @Inject + protected CloudStackComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore, + @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes, + @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy, + GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy, + CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy, + DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy, + SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider, + @Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider, + @Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning, + @Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated, + @Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended, + InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, + RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess, + PersistNodeCredentials persistNodeCredentials, Timeouts timeouts, + @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CloudStackApi client, + LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap, + LoadingCache<String, SshKeyPair> keyPairCache, + Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId, + GroupNamingConvention.Factory namingConvention, + Supplier<LoadingCache<String, Zone>> zoneIdToZone, + Optional<ImageExtension> imageExtension, + Optional<SecurityGroupExtension> securityGroupExtension) { + super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy, + getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, + startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, + nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, + persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension); + this.zoneIdToZone = checkNotNull(zoneIdToZone, "zoneIdToZone"); + this.client = checkNotNull(client, "client"); + this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap"); + this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache"); + this.orphanedGroupsByZoneId = checkNotNull(orphanedGroupsByZoneId, "orphanedGroupsByZoneId"); + this.namingConvention = checkNotNull(namingConvention, "namingConvention"); + } + + @Override + protected void cleanUpIncidentalResourcesOfDeadNodes(Set<? extends NodeMetadata> deadNodes) { + Multimap<String, String> zoneToZoneAndGroupNames = orphanedGroupsByZoneId.apply(deadNodes); + for (String zoneId : zoneToZoneAndGroupNames.keySet()) { + cleanOrphanedGroupsInZone(ImmutableSet.copyOf(zoneToZoneAndGroupNames.get(zoneId)), zoneId); + } + } + + protected void cleanOrphanedGroupsInZone(Set<String> groups, String zoneId) { + cleanupOrphanedSecurityGroupsInZone(groups, zoneId); + cleanupOrphanedKeyPairsInZone(groups, zoneId); + } + + private void cleanupOrphanedSecurityGroupsInZone(Set<String> groups, String zoneId) { + Zone zone = zoneIdToZone.get().getUnchecked(zoneId); + + if (supportsSecurityGroups().apply(zone)) { + for (String group : groups) { + for (SecurityGroup securityGroup : Iterables.filter(client.getSecurityGroupApi().listSecurityGroups(), + SecurityGroupPredicates.nameMatches(namingConvention.create().containsGroup(group)))) { + ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, securityGroup.getName()); + logger.debug(">> deleting securityGroup(%s)", zoneAndName); + client.getSecurityGroupApi().deleteSecurityGroup(securityGroup.getId()); + // TODO: test this clear happens + securityGroupMap.invalidate(zoneAndName); + logger.debug("<< deleted securityGroup(%s)", zoneAndName); + } + } + } + } + + private void cleanupOrphanedKeyPairsInZone(Set<String> groups, String zoneId) { + for (String group : groups) { + for (SshKeyPair pair : Iterables.filter(client.getSSHKeyPairApi().listSSHKeyPairs(), + nameMatches(namingConvention.create().containsGroup(group)))) { + logger.debug(">> deleting keypair(%s)", pair.getName()); + client.getSSHKeyPairApi().deleteSSHKeyPair(pair.getName()); + // TODO: test this clear happens + keyPairCache.invalidate(pair.getName()); + logger.debug("<< deleted keypair(%s)", pair.getName()); + } + keyPairCache.invalidate(namingConvention.create().sharedNameForGroup(group)); + } + } + + /** + * returns template options, as {@link CloudStackTemplateOptions}. + */ + @Override + public CloudStackTemplateOptions templateOptions() { + return CloudStackTemplateOptions.class.cast(super.templateOptions()); + } + + + +} 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/compute/config/CloudStackComputeServiceContextModule.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java new file mode 100644 index 0000000..b2c02ad --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java @@ -0,0 +1,291 @@ +/* + * 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.config; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; +import static org.jclouds.cloudstack.config.CloudStackProperties.AUTO_GENERATE_KEYPAIRS; +import static org.jclouds.util.Predicates2.retry; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.compute.extensions.CloudStackImageExtension; +import org.jclouds.cloudstack.compute.extensions.CloudStackSecurityGroupExtension; +import org.jclouds.cloudstack.compute.functions.CloudStackSecurityGroupToSecurityGroup; +import org.jclouds.cloudstack.compute.functions.IngressRuleToIpPermission; +import org.jclouds.cloudstack.compute.functions.OrphanedGroupsByZoneId; +import org.jclouds.cloudstack.compute.functions.ServiceOfferingToHardware; +import org.jclouds.cloudstack.compute.functions.TemplateToImage; +import org.jclouds.cloudstack.compute.functions.TemplateToOperatingSystem; +import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata; +import org.jclouds.cloudstack.compute.functions.ZoneToLocation; +import org.jclouds.cloudstack.compute.loaders.CreateUniqueKeyPair; +import org.jclouds.cloudstack.compute.loaders.FindSecurityGroupOrCreate; +import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; +import org.jclouds.cloudstack.compute.strategy.AdvancedNetworkOptionsConverter; +import org.jclouds.cloudstack.compute.strategy.BasicNetworkOptionsConverter; +import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter; +import org.jclouds.cloudstack.compute.strategy.OptionsConverter; +import org.jclouds.cloudstack.domain.FirewallRule; +import org.jclouds.cloudstack.domain.IPForwardingRule; +import org.jclouds.cloudstack.domain.IngressRule; +import org.jclouds.cloudstack.domain.Network; +import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.OSType; +import org.jclouds.cloudstack.domain.Project; +import org.jclouds.cloudstack.domain.SecurityGroup; +import org.jclouds.cloudstack.domain.ServiceOffering; +import org.jclouds.cloudstack.domain.SshKeyPair; +import org.jclouds.cloudstack.domain.Template; +import org.jclouds.cloudstack.domain.User; +import org.jclouds.cloudstack.domain.VirtualMachine; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.domain.ZoneAndName; +import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs; +import org.jclouds.cloudstack.features.GuestOSApi; +import org.jclouds.cloudstack.functions.CreateSecurityGroupIfNeeded; +import org.jclouds.cloudstack.functions.GetFirewallRulesByVirtualMachine; +import org.jclouds.cloudstack.functions.GetIPForwardingRulesByVirtualMachine; +import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork; +import org.jclouds.cloudstack.functions.ZoneIdToZone; +import org.jclouds.cloudstack.predicates.JobComplete; +import org.jclouds.cloudstack.suppliers.GetCurrentUser; +import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser; +import org.jclouds.cloudstack.suppliers.ProjectsForCurrentUser; +import org.jclouds.cloudstack.suppliers.ZoneIdToZoneSupplier; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.extensions.SecurityGroupExtension; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.Location; +import org.jclouds.net.domain.IpPermission; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; + +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; +import com.google.inject.name.Names; + +public class CloudStackComputeServiceContextModule extends + ComputeServiceAdapterContextModule<VirtualMachine, ServiceOffering, Template, Zone> { + + @Override + protected void configure() { + super.configure(); + bind(new TypeLiteral<ComputeServiceAdapter<VirtualMachine, ServiceOffering, Template, Zone>>() { + }).to(CloudStackComputeServiceAdapter.class); + bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() { + }).to(VirtualMachineToNodeMetadata.class); + bind(new TypeLiteral<Function<SecurityGroup, org.jclouds.compute.domain.SecurityGroup>>() { + }).to(CloudStackSecurityGroupToSecurityGroup.class); + bind(new TypeLiteral<Function<IngressRule, IpPermission>>() { + }).to(IngressRuleToIpPermission.class); + bind(new TypeLiteral<Function<Template, org.jclouds.compute.domain.Image>>() { + }).to(TemplateToImage.class); + bind(new TypeLiteral<Function<ServiceOffering, org.jclouds.compute.domain.Hardware>>() { + }).to(ServiceOfferingToHardware.class); + bind(new TypeLiteral<Function<Zone, Location>>() { + }).to(ZoneToLocation.class); + bind(TemplateOptions.class).to(CloudStackTemplateOptions.class); + bind(new TypeLiteral<Function<Template, OperatingSystem>>() { + }).to(TemplateToOperatingSystem.class); + install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class)); + bind(new TypeLiteral<CacheLoader<String, Set<IPForwardingRule>>>() { + }).to(GetIPForwardingRulesByVirtualMachine.class); + bind(new TypeLiteral<CacheLoader<String, Set<FirewallRule>>>() { + }).to(GetFirewallRulesByVirtualMachine.class); + bind(new TypeLiteral<CacheLoader<String, Zone>>() { + }).to(ZoneIdToZone.class); + bind(new TypeLiteral<CacheLoader<String, SshKeyPair>>() { + }).to(CreateUniqueKeyPair.class); + bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() { + }).to(ZoneIdToZoneSupplier.class); + bind(new TypeLiteral<Function<ZoneSecurityGroupNamePortsCidrs, SecurityGroup>>() { + }).to(CreateSecurityGroupIfNeeded.class); + bind(new TypeLiteral<CacheLoader<ZoneAndName, SecurityGroup>>() { + }).to(FindSecurityGroupOrCreate.class); + bind(new TypeLiteral<Function<Set<? extends NodeMetadata>, Multimap<String, String>>>() { + }).to(OrphanedGroupsByZoneId.class); + + bind(new TypeLiteral<ImageExtension>() { + }).to(CloudStackImageExtension.class); + + bind(new TypeLiteral<SecurityGroupExtension>() { + }).to(CloudStackSecurityGroupExtension.class); + + // to have the compute service adapter override default locations + install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, ServiceOffering, Template, Zone>() { + }); + } + + + @Override + protected TemplateOptions provideTemplateOptions(Injector injector, TemplateOptions options) { + return options.as(CloudStackTemplateOptions.class) + .generateKeyPair(injector.getInstance( + Key.get(boolean.class, Names.named(AUTO_GENERATE_KEYPAIRS)))); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<String, String>> listOSCategories(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, + final CloudStackApi client) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, + new Supplier<Map<String, String>>() { + @Override + public Map<String, String> get() { + GuestOSApi guestOSClient = client.getGuestOSApi(); + return guestOSClient.listOSCategories(); + } + @Override + public String toString() { + return MoreObjects.toStringHelper(client.getGuestOSApi()).add("method", "listOSCategories").toString(); + } + }, seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<String, OSType>> listOSTypes(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, + final CloudStackApi client) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, + new Supplier<Map<String, OSType>>() { + @Override + public Map<String, OSType> get() { + GuestOSApi guestOSClient = client.getGuestOSApi(); + return Maps.uniqueIndex(guestOSClient.listOSTypes(), new Function<OSType, String>() { + + @Override + public String apply(OSType arg0) { + return arg0.getId(); + } + }); + } + @Override + public String toString() { + return MoreObjects.toStringHelper(client.getGuestOSApi()).add("method", "listOSTypes").toString(); + } + }, seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<String, Network>> listNetworks(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, + final NetworksForCurrentUser networksForCurrentUser) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, networksForCurrentUser, + seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<String, Project>> listProjects(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, + final ProjectsForCurrentUser projectsForCurrentUser) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, projectsForCurrentUser, + seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + @Memoized + public Supplier<User> getCurrentUser(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, + final GetCurrentUser getCurrentUser) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, getCurrentUser, + seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + protected Predicate<String> jobComplete(JobComplete jobComplete) { + return retry(jobComplete, 1200, 1, 5, SECONDS); + } + + @Provides + @Singleton + protected LoadingCache<String, SshKeyPair> keyPairMap( + CacheLoader<String, SshKeyPair> in) { + return CacheBuilder.newBuilder().build(in); + } + + @Provides + @Singleton + protected LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap( + CacheLoader<ZoneAndName, SecurityGroup> in) { + return CacheBuilder.newBuilder().build(in); + } + + @Provides + @Singleton + protected LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine( + CacheLoader<String, Set<IPForwardingRule>> in) { + return CacheBuilder.newBuilder().build(in); + } + + + @Provides + @Singleton + protected LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine( + CacheLoader<String, Set<FirewallRule>> getFirewallRules) { + return CacheBuilder.newBuilder().build(getFirewallRules); + } + + @Provides + @Singleton + public Map<NetworkType, ? extends OptionsConverter> optionsConverters() { + return ImmutableMap.of( + NetworkType.ADVANCED, new AdvancedNetworkOptionsConverter(), + NetworkType.BASIC, new BasicNetworkOptionsConverter()); + } + + @Override + protected Optional<ImageExtension> provideImageExtension(Injector i) { + return Optional.of(i.getInstance(ImageExtension.class)); + } + + @Override + protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) { + return Optional.of(i.getInstance(SecurityGroupExtension.class)); + } +} 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/compute/extensions/CloudStackImageExtension.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java new file mode 100644 index 0000000..2009e6d --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java @@ -0,0 +1,160 @@ +/* + * 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 com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.Iterables.find; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; +import static org.jclouds.location.predicates.LocationPredicates.idEquals; + +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicReference; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.Constants; +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.domain.Template; +import org.jclouds.cloudstack.domain.TemplateMetadata; +import org.jclouds.cloudstack.domain.VirtualMachine; +import org.jclouds.cloudstack.domain.Volume; +import org.jclouds.cloudstack.options.CreateTemplateOptions; +import org.jclouds.cloudstack.options.ListVolumesOptions; +import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.CloneImageTemplate; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.ImageTemplate; +import org.jclouds.compute.domain.ImageTemplateBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Location; +import org.jclouds.logging.Logger; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.Atomics; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.UncheckedTimeoutException; + +/** + * CloudStack implementation of {@link ImageExtension} + */ +@Singleton +public class CloudStackImageExtension implements ImageExtension { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final CloudStackApi client; + private final ListeningExecutorService userExecutor; + private final Supplier<Set<? extends Location>> locations; + private final Predicate<AtomicReference<Image>> imageAvailablePredicate; + private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult; + private final Predicate<String> jobComplete; + + @Inject + public CloudStackImageExtension(CloudStackApi client, + @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, + @Memoized Supplier<Set<? extends Location>> locations, + @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<AtomicReference<Image>> imageAvailablePredicate, + BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult, + Predicate<String> jobComplete) { + this.client = checkNotNull(client, "client"); + this.userExecutor = checkNotNull(userExecutor, "userExecutor"); + this.locations = checkNotNull(locations, "locations"); + this.imageAvailablePredicate = checkNotNull(imageAvailablePredicate, "imageAvailablePredicate"); + this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult, + "blockUntilJobCompletesAndReturnResult"); + this.jobComplete = checkNotNull(jobComplete, "jobComplete"); + } + + @Override + public ImageTemplate buildImageTemplateFromNode(String name, String id) { + VirtualMachine vm = client.getVirtualMachineApi().getVirtualMachine(id); + if (vm == null) + throw new NoSuchElementException("Cannot find vm with id: " + id); + CloneImageTemplate template = new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name).build(); + return template; + } + + @Override + public ListenableFuture<Image> createImage(ImageTemplate template) { + checkState(template instanceof CloneImageTemplate, + " cloudstack only currently supports creating images through cloning."); + CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; + + VirtualMachine vm = client.getVirtualMachineApi().getVirtualMachine(cloneTemplate.getSourceNodeId()); + String stopJob = client.getVirtualMachineApi().stopVirtualMachine(vm.getId()); + jobComplete.apply(stopJob); + + Set<Volume> volumes = client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.virtualMachineId(vm.getId())); + Volume volume = Iterables.getOnlyElement(volumes); + + CreateTemplateOptions options = CreateTemplateOptions.Builder.volumeId(volume.getId()); + AsyncCreateResponse templateJob = client.getTemplateApi().createTemplate(TemplateMetadata.builder() + .name(cloneTemplate.getName()) + .osTypeId(vm.getGuestOSId()) + .displayText(cloneTemplate.getName()) + .build(), options); + Template newTemplate = blockUntilJobCompletesAndReturnResult.<Template>apply(templateJob); + + logger.info(">> Registered new template %s, waiting for it to become available.", newTemplate.getId()); + + final AtomicReference<Image> image = Atomics.newReference(new ImageBuilder() + .location(find(locations.get(), idEquals(vm.getZoneId()))) + .id(newTemplate.getId()) + .providerId(newTemplate.getId()) + .description(cloneTemplate.getName()) + .operatingSystem(OperatingSystem.builder().description(cloneTemplate.getName()).build()) + .status(Image.Status.PENDING).build()); + + return userExecutor.submit(new Callable<Image>() { + @Override + public Image call() throws Exception { + if (imageAvailablePredicate.apply(image)) + return image.get(); + // TODO: get rid of the expectation that the image will be available, as it is very brittle + throw new UncheckedTimeoutException("Image was not created within the time limit: " + image.get()); + } + }); + } + + @Override + public boolean deleteImage(String id) { + try { + AsyncCreateResponse deleteJob = client.getTemplateApi().deleteTemplate(id); + jobComplete.apply(deleteJob.getJobId()); + return true; + } catch (Exception e) { + return false; + } + } + +} 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/compute/extensions/CloudStackSecurityGroupExtension.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtension.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtension.java new file mode 100644 index 0000000..70f7728 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtension.java @@ -0,0 +1,282 @@ +/* + * 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 com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.transform; +import static org.jclouds.cloudstack.predicates.SecurityGroupPredicates.ruleCidrMatches; +import static org.jclouds.cloudstack.predicates.SecurityGroupPredicates.ruleGroupMatches; + +import java.util.Set; + +import javax.inject.Inject; + +import org.jclouds.cloudstack.CloudStackApi; +import org.jclouds.cloudstack.domain.IngressRule; +import org.jclouds.cloudstack.domain.ZoneAndName; +import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs; +import org.jclouds.cloudstack.options.ListSecurityGroupsOptions; +import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.SecurityGroup; +import org.jclouds.compute.extensions.SecurityGroupExtension; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.domain.Location; +import org.jclouds.net.domain.IpPermission; +import org.jclouds.net.domain.IpProtocol; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; + +/** + * An extension to compute service to allow for the manipulation of {@link org.jclouds.compute.domain.SecurityGroup}s. Implementation + * is optional by providers. + */ +public class CloudStackSecurityGroupExtension implements SecurityGroupExtension { + protected final CloudStackApi api; + protected final Function<org.jclouds.cloudstack.domain.SecurityGroup, SecurityGroup> groupConverter; + protected final LoadingCache<ZoneAndName, org.jclouds.cloudstack.domain.SecurityGroup> groupCreator; + protected final GroupNamingConvention.Factory namingConvention; + protected final Supplier<Set<? extends Location>> locations; + protected final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult; + protected final Predicate<String> jobComplete; + + @Inject + public CloudStackSecurityGroupExtension(CloudStackApi api, + Function<org.jclouds.cloudstack.domain.SecurityGroup, SecurityGroup> groupConverter, + LoadingCache<ZoneAndName, org.jclouds.cloudstack.domain.SecurityGroup> groupCreator, + GroupNamingConvention.Factory namingConvention, + @Memoized Supplier<Set<? extends Location>> locations, + BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult, + Predicate<String> jobComplete) { + this.api = checkNotNull(api, "api"); + this.groupConverter = checkNotNull(groupConverter, "groupConverter"); + this.groupCreator = checkNotNull(groupCreator, "groupCreator"); + this.namingConvention = checkNotNull(namingConvention, "namingConvention"); + this.locations = checkNotNull(locations, "locations"); + this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult, + "blockUntilJobCompletesAndReturnResult"); + this.jobComplete = checkNotNull(jobComplete, "jobComplete"); + } + + @Override + public Set<SecurityGroup> listSecurityGroups() { + Iterable<? extends org.jclouds.cloudstack.domain.SecurityGroup> rawGroups = + api.getSecurityGroupApi().listSecurityGroups(); + Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()), + groupConverter); + return ImmutableSet.copyOf(groups); + } + + /** + * Note that for the time being, security groups are not scoped by location in + * CloudStack, so this will simply return listSecurityGroups(). + * + * @param location + * @return security groups + */ + @Override + public Set<SecurityGroup> listSecurityGroupsInLocation(final Location location) { + return listSecurityGroups(); + } + + @Override + public Set<SecurityGroup> listSecurityGroupsForNode(String id) { + checkNotNull(id, "id"); + + Iterable<? extends org.jclouds.cloudstack.domain.SecurityGroup> rawGroups = + api.getSecurityGroupApi().listSecurityGroups(ListSecurityGroupsOptions.Builder + .virtualMachineId(id)); + + Iterable<SecurityGroup> groups = transform(filter(rawGroups, notNull()), + groupConverter); + return ImmutableSet.copyOf(groups); + } + + @Override + public SecurityGroup getSecurityGroupById(String id) { + checkNotNull(id, "id"); + + org.jclouds.cloudstack.domain.SecurityGroup rawGroup + = api.getSecurityGroupApi().getSecurityGroup(id); + + if (rawGroup == null) { + return null; + } + + return groupConverter.apply(rawGroup); + } + + @Override + public SecurityGroup createSecurityGroup(String name, Location location) { + checkNotNull(name, "name"); + checkNotNull(location, "location"); + + String markerGroup = namingConvention.create().sharedNameForGroup(name); + + ZoneSecurityGroupNamePortsCidrs zoneAndName = ZoneSecurityGroupNamePortsCidrs.builder() + .zone(location.getId()) + .name(markerGroup) + .build(); + + return groupConverter.apply(groupCreator.getUnchecked(zoneAndName)); + } + + @Override + public boolean removeSecurityGroup(String id) { + checkNotNull(id, "id"); + + org.jclouds.cloudstack.domain.SecurityGroup group = + api.getSecurityGroupApi().getSecurityGroup(id); + + if (group == null) { + return false; + } + + for (IngressRule rule : group.getIngressRules()) { + jobComplete.apply(api.getSecurityGroupApi().revokeIngressRule(rule.getId())); + } + + api.getSecurityGroupApi().deleteSecurityGroup(id); + + // TODO find something better here maybe - hard to map zones to groups + for (Location location : locations.get()) { + groupCreator.invalidate(ZoneSecurityGroupNamePortsCidrs.builder() + .zone(location.getId()) + .name(group.getName()) + .build()); + } + + return true; + } + + @Override + public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) { + checkNotNull(group, "group"); + checkNotNull(ipPermission, "ipPermission"); + String id = checkNotNull(group.getId(), "group.getId()"); + + if (!ipPermission.getCidrBlocks().isEmpty()) { + jobComplete.apply(api.getSecurityGroupApi().authorizeIngressPortsToCIDRs(id, + ipPermission.getIpProtocol().toString().toUpperCase(), + ipPermission.getFromPort(), + ipPermission.getToPort(), + ipPermission.getCidrBlocks())); + } + + if (!ipPermission.getTenantIdGroupNamePairs().isEmpty()) { + jobComplete.apply(api.getSecurityGroupApi().authorizeIngressPortsToSecurityGroups(id, + ipPermission.getIpProtocol().toString().toUpperCase(), + ipPermission.getFromPort(), + ipPermission.getToPort(), + ipPermission.getTenantIdGroupNamePairs())); + } + + return getSecurityGroupById(id); + } + + @Override + public SecurityGroup addIpPermission(IpProtocol protocol, int startPort, int endPort, + Multimap<String, String> tenantIdGroupNamePairs, + Iterable<String> ipRanges, + Iterable<String> groupIds, SecurityGroup group) { + IpPermission.Builder permBuilder = IpPermission.builder(); + permBuilder.ipProtocol(protocol); + permBuilder.fromPort(startPort); + permBuilder.toPort(endPort); + permBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs); + permBuilder.cidrBlocks(ipRanges); + permBuilder.groupIds(groupIds); + + return addIpPermission(permBuilder.build(), group); + } + + @Override + public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) { + checkNotNull(group, "group"); + checkNotNull(ipPermission, "ipPermission"); + String id = checkNotNull(group.getId(), "group.getId()"); + + org.jclouds.cloudstack.domain.SecurityGroup rawGroup = api.getSecurityGroupApi() + .getSecurityGroup(id); + + if (!ipPermission.getCidrBlocks().isEmpty()) { + for (IngressRule rule : filter(rawGroup.getIngressRules(), + ruleCidrMatches(ipPermission.getIpProtocol().toString(), + ipPermission.getFromPort(), + ipPermission.getToPort(), + ipPermission.getCidrBlocks()))) { + jobComplete.apply(api.getSecurityGroupApi().revokeIngressRule(rule.getId())); + } + } + + if (!ipPermission.getTenantIdGroupNamePairs().isEmpty()) { + for (IngressRule rule : filter(rawGroup.getIngressRules(), + ruleGroupMatches(ipPermission.getIpProtocol().toString(), + ipPermission.getFromPort(), + ipPermission.getToPort(), + ipPermission.getTenantIdGroupNamePairs()))) { + jobComplete.apply(api.getSecurityGroupApi().revokeIngressRule(rule.getId())); + } + } + + return getSecurityGroupById(id); + } + + @Override + public SecurityGroup removeIpPermission(IpProtocol protocol, int startPort, int endPort, + Multimap<String, String> tenantIdGroupNamePairs, + Iterable<String> ipRanges, + Iterable<String> groupIds, SecurityGroup group) { + IpPermission.Builder permBuilder = IpPermission.builder(); + permBuilder.ipProtocol(protocol); + permBuilder.fromPort(startPort); + permBuilder.toPort(endPort); + permBuilder.tenantIdGroupNamePairs(tenantIdGroupNamePairs); + permBuilder.cidrBlocks(ipRanges); + permBuilder.groupIds(groupIds); + + return removeIpPermission(permBuilder.build(), group); + } + + @Override + public boolean supportsTenantIdGroupNamePairs() { + return true; + } + + @Override + public boolean supportsTenantIdGroupIdPairs() { + return false; + } + + @Override + public boolean supportsGroupIds() { + return false; + } + + @Override + public boolean supportsPortRangesForGroups() { + return false; + } + +} 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/compute/functions/CloudStackSecurityGroupToSecurityGroup.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/CloudStackSecurityGroupToSecurityGroup.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/CloudStackSecurityGroupToSecurityGroup.java new file mode 100644 index 0000000..0d17317 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/CloudStackSecurityGroupToSecurityGroup.java @@ -0,0 +1,66 @@ +/* + * 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.functions; + +import static com.google.common.collect.Iterables.transform; + + +import javax.annotation.Resource; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.SecurityGroup; +import org.jclouds.compute.domain.SecurityGroupBuilder; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.net.domain.IpPermission; +import org.jclouds.cloudstack.domain.IngressRule; + +import com.google.common.base.Function; +import com.google.inject.Inject; + + +/** + * A function for transforming a CloudStack-specific SecurityGroup into a generic + * SecurityGroup object. + */ +@Singleton +public class CloudStackSecurityGroupToSecurityGroup implements Function<org.jclouds.cloudstack.domain.SecurityGroup, SecurityGroup> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + protected final Function<IngressRule, IpPermission> ruleToPermission; + + @Inject + public CloudStackSecurityGroupToSecurityGroup(Function<IngressRule, IpPermission> ruleToPermission) { + this.ruleToPermission = ruleToPermission; + } + + @Override + public SecurityGroup apply(org.jclouds.cloudstack.domain.SecurityGroup group) { + SecurityGroupBuilder builder = new SecurityGroupBuilder(); + + builder.id(group.getId()); + builder.providerId(group.getId()); + builder.name(group.getName()); + builder.ownerId(group.getAccount()); + builder.ipPermissions(transform(group.getIngressRules(), ruleToPermission)); + + return builder.build(); + } +} 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/compute/functions/IngressRuleToIpPermission.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/IngressRuleToIpPermission.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/IngressRuleToIpPermission.java new file mode 100644 index 0000000..fbcdc18 --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/IngressRuleToIpPermission.java @@ -0,0 +1,58 @@ +/* + * 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.functions; + +import javax.annotation.Resource; +import javax.inject.Named; + +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.cloudstack.domain.IngressRule; +import org.jclouds.logging.Logger; +import org.jclouds.net.domain.IpPermission; +import org.jclouds.net.domain.IpProtocol; + +import com.google.common.base.Function; + + +/** + * A function for transforming a CloudStack-specific IngressRule into a generic + * IpPermission object. + */ +public class IngressRuleToIpPermission implements Function<IngressRule, IpPermission> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + public IngressRuleToIpPermission() { + } + + @Override + public IpPermission apply(IngressRule rule) { + IpPermission.Builder builder = IpPermission.builder(); + builder.ipProtocol(IpProtocol.fromValue(rule.getProtocol())); + builder.fromPort(rule.getStartPort()); + builder.toPort(rule.getEndPort()); + if (rule.getCIDR() != null) { + builder.cidrBlock(rule.getCIDR()); + } + if (rule.getSecurityGroupName() != null + && rule.getAccount() != null) { + builder.tenantIdGroupNamePair(rule.getAccount(), rule.getSecurityGroupName()); + } + return builder.build(); + } +} 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/compute/functions/OrphanedGroupsByZoneId.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/OrphanedGroupsByZoneId.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/OrphanedGroupsByZoneId.java new file mode 100644 index 0000000..d7a187d --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/OrphanedGroupsByZoneId.java @@ -0,0 +1,73 @@ +/* + * 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.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Sets.filter; + +import java.util.Set; + +import javax.inject.Inject; + +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.predicates.NodePredicates; +import org.jclouds.domain.LocationScope; +import org.jclouds.cloudstack.compute.predicates.AllNodesInGroupTerminated; +import org.jclouds.cloudstack.domain.ZoneAndName; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; + +public class OrphanedGroupsByZoneId implements Function<Set<? extends NodeMetadata>, Multimap<String, String>> { + private final Predicate<ZoneAndName> allNodesInGroupTerminated; + + @Inject + protected OrphanedGroupsByZoneId(ComputeService computeService) { + this(new AllNodesInGroupTerminated(checkNotNull(computeService, "computeService"))); + } + + @VisibleForTesting + OrphanedGroupsByZoneId(Predicate<ZoneAndName> allNodesInGroupTerminated) { + this.allNodesInGroupTerminated = checkNotNull(allNodesInGroupTerminated, "allNodesInGroupTerminated"); + } + + public Multimap<String, String> apply(Set<? extends NodeMetadata> deadNodes) { + Iterable<? extends NodeMetadata> nodesWithGroup = filter(deadNodes, NodePredicates.hasGroup()); + Set<ZoneAndName> zoneAndGroupNames = ImmutableSet.copyOf(filter(transform(nodesWithGroup, + new Function<NodeMetadata, ZoneAndName>() { + + @Override + public ZoneAndName apply(NodeMetadata input) { + String zoneId = input.getLocation().getScope() == LocationScope.HOST ? input.getLocation() + .getParent().getId() : input.getLocation().getId(); + return ZoneAndName.fromZoneAndName(zoneId, input.getGroup()); + } + + }), allNodesInGroupTerminated)); + Multimap<String, String> zoneToZoneAndGroupNames = Multimaps.transformValues(Multimaps.index(zoneAndGroupNames, + ZoneAndName.ZONE_FUNCTION), ZoneAndName.NAME_FUNCTION); + return zoneToZoneAndGroupNames; + } + +} 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/compute/functions/ServiceOfferingToHardware.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/ServiceOfferingToHardware.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/ServiceOfferingToHardware.java new file mode 100644 index 0000000..ab85c3a --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/ServiceOfferingToHardware.java @@ -0,0 +1,50 @@ +/* + * 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.functions; + +import javax.inject.Singleton; + +import org.jclouds.cloudstack.domain.ServiceOffering; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; + +@Singleton +public class ServiceOfferingToHardware implements Function<ServiceOffering, Hardware> { + + @Override + public Hardware apply(ServiceOffering offering) { + return new HardwareBuilder() + .ids(offering.getId() + "") + .name(offering.getName()) + .tags(offering.getTags()) + .processors(ImmutableList.of(new Processor(offering.getCpuNumber(), offering.getCpuSpeed()))) + .ram(offering.getMemory())// + // TODO: hypervisor probably from zone? + // TODO .volumes() + // displayText + // created + // haSupport + // storageType + // TODO where's the location of this? + .build(); + } + +} 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/compute/functions/TemplateToImage.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToImage.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToImage.java new file mode 100644 index 0000000..86ab66e --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToImage.java @@ -0,0 +1,67 @@ +/* + * 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.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.location.predicates.LocationPredicates.idEquals; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudstack.domain.Template; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Image.Status; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.domain.Location; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.FluentIterable; + +@Singleton +public class TemplateToImage implements Function<Template, Image> { + private final Supplier<Set<? extends Location>> locations; + private final Function<Template, OperatingSystem> templateToOperatingSystem; + + @Inject + public TemplateToImage(@Memoized Supplier<Set<? extends Location>> locations, + Function<Template, OperatingSystem> templateToOperatingSystem) { + this.locations = checkNotNull(locations, "locations"); + this.templateToOperatingSystem = checkNotNull(templateToOperatingSystem, "templateToOperatingSystem"); + } + + @Override + public Image apply(Template template) { + checkNotNull(template, "template"); + + OperatingSystem os = templateToOperatingSystem.apply(template); + + ImageBuilder builder = new ImageBuilder().ids(template.getId() + "").name(template.getName()) + .description(template.getDisplayText()).operatingSystem(os); + + if (!template.isCrossZones()) + builder.location(FluentIterable.from(locations.get()).firstMatch(idEquals(template.getZoneId())).orNull()); + + //TODO: implement status mapping!!! + builder.status(Status.AVAILABLE); + return builder.build(); + } +} 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/compute/functions/TemplateToOperatingSystem.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToOperatingSystem.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToOperatingSystem.java new file mode 100644 index 0000000..9abb7da --- /dev/null +++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/compute/functions/TemplateToOperatingSystem.java @@ -0,0 +1,88 @@ +/* + * 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.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +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.cloudstack.domain.OSType; +import org.jclouds.cloudstack.domain.Template; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.OperatingSystem.Builder; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.compute.util.ComputeServiceUtils; +import org.jclouds.logging.Logger; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +@Singleton +public class TemplateToOperatingSystem implements Function<Template, OperatingSystem> { + // CentOS 5.2 (32-bit) + public static final Pattern DEFAULT_PATTERN = Pattern.compile(".* ([0-9.]+) ?\\(.*"); + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final Supplier<Map<String, OSType>> osTypes; + private final Supplier<Map<String, String>> osCategories; + private final Map<OsFamily, Map<String, String>> osVersionMap; + + @Inject + public TemplateToOperatingSystem(@Memoized Supplier<Map<String, OSType>> osTypes, + @Memoized Supplier<Map<String, String>> osCategories, Map<OsFamily, Map<String, String>> osVersionMap) { + this.osTypes = checkNotNull(osTypes, "osTypes"); + this.osCategories = checkNotNull(osCategories, "osCategories"); + this.osVersionMap = checkNotNull(osVersionMap, "osVersionMap"); + } + + public OperatingSystem apply(Template from) { + Builder builder = OperatingSystem.builder().description(from.getOSType()); + + OSType type = osTypes.get().get(from.getOSTypeId()); + if (type == null) { + logger.warn("Template refers to OS type ID %s but this does not exist. Template=%s Known OS types=%s", from.getOSTypeId(), from, osTypes.get()); + return builder.build(); + } + builder.description(type.getDescription()); + builder.is64Bit(type.getDescription().indexOf("64-bit") != -1); + String osCategory = osCategories.get().get(type.getOSCategoryId()); + if (osCategory == null) { + logger.warn("OS type refers to OS category ID %s but this does not exist. OS type=%s Known OS categories=%s", type.getOSCategoryId(), type, osCategories.get()); + return builder.build(); + } + builder.name(osCategory); + OsFamily family = OsFamily.fromValue(osCategory.toLowerCase()); + builder.family(family); + Matcher matcher = DEFAULT_PATTERN.matcher(type.getDescription()); + if (matcher.find()) { + builder.version(ComputeServiceUtils.parseVersionOrReturnEmptyString(family, matcher.group(1), osVersionMap)); + } + return builder.build(); + } +}
