You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by im...@apache.org on 2014/11/26 12:54:57 UTC
[27/41] stratos git commit: adding cloudstack dependancy
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/VolumeApi.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/VolumeApi.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/VolumeApi.java
new file mode 100644
index 0000000..2f601e9
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/VolumeApi.java
@@ -0,0 +1,170 @@
+/*
+ * 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.features;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.Volume;
+import org.jclouds.cloudstack.filters.AuthenticationFilter;
+import org.jclouds.cloudstack.options.ListVolumesOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Unwrap;
+
+/**
+ * Provides synchronous access to cloudstack via their REST API.
+ * <p/>
+ *
+ * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
+ */
+@RequestFilters(AuthenticationFilter.class)
+@QueryParams(keys = "response", values = "json")
+public interface VolumeApi {
+ /**
+ * Create a volume with given name and diskOfferingId
+ *
+ * @param name name of the volume
+ * @param diskOfferingId the ID of the disk offering.
+ * @param zoneId the ID of the availability zone
+ * @return AsyncCreateResponse job response used to track creation
+ */
+ @Named("listVolumes")
+ @GET
+ @QueryParams(keys = { "command", "listAll" }, values = { "listVolumes", "true" })
+ @SelectJson("volume")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<Volume> listVolumes(ListVolumesOptions... options);
+
+ /**
+ * Create a volume with given name, size and diskOfferingId
+ *
+ * @param name name of the volume
+ * @param diskOfferingId the ID of the disk offering (the offering should have the custom disk size flag set)
+ * @param zoneId the ID of the availability zone
+ * @param size the size of volume required (in GB)
+ * @return AsyncCreateResponse job response used to track creation
+ */
+ @Named("listVolumes")
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = { "command", "listAll" }, values = { "listVolumes", "true" })
+ @SelectJson("volume")
+ @OnlyElement
+ @Fallback(NullOnNotFoundOr404.class)
+ Volume getVolume(@QueryParam("id") String id);
+
+
+ /**
+ * Create a volume with given name and snapshotId
+ *
+ * @param name name of the volume
+ * @param snapshotId Snapshot id to be used while creating the volume
+ * @param zoneId the ID of the availability zone
+ * @return AsyncCreateResponse job response used to track creation
+ */
+ @Named("createVolume")
+ @GET
+ @QueryParams(keys = "command", values = "createVolume")
+ @Unwrap
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCreateResponse createVolumeFromDiskOfferingInZone(@QueryParam("name") String name,
+ @QueryParam("diskofferingid") String diskOfferingId,
+ @QueryParam("zoneid") String zoneId);
+
+ /**
+ * List volumes
+ *
+ * @return volume list, empty if not found
+ */
+ @GET
+ @QueryParams(keys = "command", values = "createVolume")
+ @Unwrap
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCreateResponse createVolumeFromCustomDiskOfferingInZone(@QueryParam("name") String name,
+ @QueryParam("diskofferingid") String diskOfferingId,
+ @QueryParam("zoneid") String zoneId,
+ @QueryParam("size") int size);
+
+ /**
+ * Get volume by id
+ *
+ * @param id the volume id to retrieve
+ * @return volume or null if not found
+ */
+ @Named("createVolume")
+ @GET
+ @QueryParams(keys = "command", values = "createVolume")
+ @Unwrap
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCreateResponse createVolumeFromSnapshotInZone(@QueryParam("name") String name,
+ @QueryParam("snapshotid") String snapshotId,
+ @QueryParam("zoneid") String zoneId);
+
+ /**
+ * Deletes a attached disk volume
+ *
+ * @param id id of the volume
+ */
+ @Named("attachVolume")
+ @GET
+ @QueryParams(keys = "command", values = "attachVolume")
+ @Unwrap
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCreateResponse attachVolume(@QueryParam("id") String volumeId,
+ @QueryParam("virtualmachineid") String virtualMachineId);
+
+ /**
+ * Attaches a disk volume to a virtual machine.
+ *
+ * @param volumeId the ID of the disk volume
+ * @param virtualMachineId the ID of the virtual machine
+ * @return AsyncCreateResponse job response used to track creation
+ */
+ @Named("detachVolume")
+ @GET
+ @QueryParams(keys = "command", values = "detachVolume")
+ @Unwrap
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCreateResponse detachVolume(@QueryParam("id") String volumeId);
+
+ /**
+ * Detaches a disk volume to a virtual machine.
+ *
+ * @param volumeId the ID of the disk volume
+ * @return AsyncCreateResponse job response used to track creation
+ */
+ @Named("deleteVolume")
+ @GET
+ @QueryParams(keys = "command", values = "deleteVolume")
+ @Fallback(VoidOnNotFoundOr404.class)
+ void deleteVolume(@QueryParam("id") String id);
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/ZoneApi.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/ZoneApi.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/ZoneApi.java
new file mode 100644
index 0000000..d7e8ff3
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/features/ZoneApi.java
@@ -0,0 +1,79 @@
+/*
+ * 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.features;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.filters.AuthenticationFilter;
+import org.jclouds.cloudstack.options.ListZonesOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+/**
+ * Provides synchronous access to cloudstack via their REST API.
+ * <p/>
+ *
+ * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
+ */
+@RequestFilters(AuthenticationFilter.class)
+@QueryParams(keys = "response", values = "json")
+public interface ZoneApi {
+
+ /**
+ * Lists zones
+ *
+ * @param options
+ * if present, how to constrain the list.
+ * @return zones matching query, or empty set, if no zones are found
+ */
+ @Named("listZones")
+ @GET
+ @QueryParams(keys = { "command", "listAll" }, values = { "listZones", "true" })
+ @SelectJson("zone")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(EmptySetOnNotFoundOr404.class)
+ Set<Zone> listZones(ListZonesOptions... options);
+
+ /**
+ * get a specific zone by id
+ *
+ * @param id
+ * zone to get
+ * @return zone or null if not found
+ */
+ @Named("listZones")
+ @GET
+ @QueryParams(keys = { "command", "listAll" }, values = { "listZones", "true" })
+ @SelectJson("zone")
+ @OnlyElement
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(NullOnNotFoundOr404.class)
+ Zone getZone(@QueryParam("id") String id);
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AddSessionKeyAndJSessionIdToRequest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AddSessionKeyAndJSessionIdToRequest.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AddSessionKeyAndJSessionIdToRequest.java
new file mode 100644
index 0000000..f08c0e8
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AddSessionKeyAndJSessionIdToRequest.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.filters;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.LoginResponse;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequest.Builder;
+
+import com.google.common.base.Supplier;
+import com.google.common.net.HttpHeaders;
+
+/**
+ *
+ * @see <a href="http://docs.cloud.com/CloudStack_Documentation/Customizing_the_CloudStack_UI#Cross_Site_Request_Forgery_%28CSRF%29"
+ * />
+ */
+@Singleton
+public class AddSessionKeyAndJSessionIdToRequest implements AuthenticationFilter {
+
+ private final Supplier<LoginResponse> loginResponseSupplier;
+
+ @Inject
+ public AddSessionKeyAndJSessionIdToRequest(Supplier<LoginResponse> loginResponseSupplier) {
+ this.loginResponseSupplier = loginResponseSupplier;
+ }
+
+ @Override
+ public HttpRequest filter(HttpRequest request) throws HttpException {
+ LoginResponse loginResponse = loginResponseSupplier.get();
+ Builder<?> builder = request.toBuilder();
+ builder.replaceHeader(HttpHeaders.COOKIE, "JSESSIONID=" + loginResponse.getJSessionId());
+ builder.replaceQueryParam("sessionkey", loginResponse.getSessionKey());
+ return builder.build();
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AuthenticationFilter.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AuthenticationFilter.java
new file mode 100644
index 0000000..1e567a6
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/AuthenticationFilter.java
@@ -0,0 +1,30 @@
+/*
+ * 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.filters;
+
+import org.jclouds.http.HttpRequestFilter;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ * Marker interface that determines how we authenticate http requests in cloudstack. default to sign
+ * requests as opposed to login.
+ */
+@ImplementedBy(QuerySigner.class)
+public interface AuthenticationFilter extends HttpRequestFilter {
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java
new file mode 100644
index 0000000..04610cc
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java
@@ -0,0 +1,141 @@
+/*
+ * 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.filters;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.io.BaseEncoding.base64;
+import static com.google.common.io.ByteStreams.readBytes;
+import static org.jclouds.Constants.LOGGER_SIGNATURE;
+import static org.jclouds.crypto.Macs.asByteProcessor;
+import static org.jclouds.http.Uris.uriBuilder;
+import static org.jclouds.http.utils.Queries.queryParser;
+import static org.jclouds.util.Strings2.toInputStream;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import com.google.common.base.Joiner;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.domain.Credentials;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.internal.SignatureWire;
+import org.jclouds.location.Provider;
+import org.jclouds.logging.Logger;
+import org.jclouds.rest.RequestSigner;
+import org.jclouds.util.Strings2;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Multimap;
+import com.google.common.io.ByteProcessor;
+
+/**
+ *
+ * @see <a href= "http://download.cloud.com/releases/2.2.0/api/user/2.2api_security_details.html" />
+ */
+@Singleton
+public class QuerySigner implements AuthenticationFilter, RequestSigner {
+
+ private final SignatureWire signatureWire;
+ private final Supplier<Credentials> creds;
+ private final Crypto crypto;
+ private final HttpUtils utils;
+
+ @Resource
+ @Named(LOGGER_SIGNATURE)
+ private Logger signatureLog = Logger.NULL;
+
+ @Inject
+ public QuerySigner(SignatureWire signatureWire, @Provider Supplier<Credentials> creds, Crypto crypto, HttpUtils utils) {
+ this.signatureWire = signatureWire;
+ this.creds = creds;
+ this.crypto = crypto;
+ this.utils = utils;
+ }
+
+ public HttpRequest filter(HttpRequest request) throws HttpException {
+ checkNotNull(request, "request must be present");
+ Multimap<String, String> decodedParams = queryParser().apply(request.getEndpoint().getRawQuery());
+ addSigningParams(decodedParams);
+ String stringToSign = createStringToSign(request, decodedParams);
+ String signature = sign(stringToSign);
+ addSignature(decodedParams, signature);
+ request = request.toBuilder().endpoint(uriBuilder(request.getEndpoint()).query(decodedParams).build()).build();
+ utils.logRequest(signatureLog, request, "<<");
+ return request;
+ }
+
+ @VisibleForTesting
+ void addSignature(Multimap<String, String> params, String signature) {
+ params.replaceValues("signature", ImmutableList.of(signature));
+ }
+
+ @VisibleForTesting
+ public String sign(String toSign) {
+ String signature;
+ try {
+ ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(creds.get().credential.getBytes()));
+ signature = base64().encode(readBytes(toInputStream(toSign), hmacSHA1));
+ if (signatureWire.enabled())
+ signatureWire.input(toInputStream(signature));
+ return signature;
+ } catch (InvalidKeyException e) {
+ throw propagate(e);
+ } catch (IOException e) {
+ throw propagate(e);
+ }
+ }
+
+ @VisibleForTesting
+ public String createStringToSign(HttpRequest request, Multimap<String, String> decodedParams) {
+ utils.logRequest(signatureLog, request, ">>");
+ // encode each parameter value first,
+ ImmutableSortedSet.Builder<String> builder = ImmutableSortedSet.naturalOrder();
+ for (Map.Entry<String, String> entry : decodedParams.entries())
+ builder.add(entry.getKey() + "=" + Strings2.urlEncode(entry.getValue()));
+ // then, lower case the entire query string
+ String stringToSign = Joiner.on('&').join(builder.build()).toLowerCase();
+ if (signatureWire.enabled())
+ signatureWire.output(stringToSign);
+
+ return stringToSign;
+ }
+
+ @VisibleForTesting
+ void addSigningParams(Multimap<String, String> params) {
+ params.replaceValues("apiKey", ImmutableList.of(creds.get().identity));
+ params.removeAll("signature");
+ }
+
+ public String createStringToSign(HttpRequest input) {
+ Multimap<String, String> decodedParams = queryParser().apply(input.getEndpoint().getQuery());
+ addSigningParams(decodedParams);
+ return createStringToSign(input, decodedParams);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CloudStackFallbacks.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CloudStackFallbacks.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CloudStackFallbacks.java
new file mode 100644
index 0000000..50185ed
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CloudStackFallbacks.java
@@ -0,0 +1,52 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static org.jclouds.Fallbacks.valOnNotFoundOr404;
+import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
+
+import org.jclouds.Fallback;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public final class CloudStackFallbacks {
+ private CloudStackFallbacks() {
+ }
+
+ /**
+ * CloudStack is currently sending 431 errors with the text "Unable to find account owner for ip ". In this case, we
+ * have to ignore as there's no means for us to avoid the problem, or action to take.
+ */
+ public static final class VoidOnNotFoundOr404OrUnableToFindAccountOwner implements Fallback<Void> {
+ @Override
+ public ListenableFuture<Void> create(Throwable t) throws Exception {
+ return immediateFuture(createOrPropagate(t));
+ }
+
+ @Override
+ public Void createOrPropagate(Throwable t) throws Exception {
+ IllegalStateException e = getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class);
+ if (e != null && e.getMessage().indexOf("Unable to find account owner for") != -1) {
+ return null;
+ } else {
+ return valOnNotFoundOr404(null, t);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateFirewallRulesForIP.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateFirewallRulesForIP.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateFirewallRulesForIP.java
new file mode 100644
index 0000000..dd15e19
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateFirewallRulesForIP.java
@@ -0,0 +1,90 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.FirewallRule;
+import org.jclouds.cloudstack.domain.PublicIPAddress;
+import org.jclouds.cloudstack.options.CreateFirewallRuleOptions;
+import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ImmutableSet.Builder;
+
+@Singleton
+public class CreateFirewallRulesForIP {
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final CloudStackApi client;
+ private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult;
+ private final LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine;
+
+ @Inject
+ public CreateFirewallRulesForIP(CloudStackApi client,
+ BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
+ LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine) {
+ this.client = checkNotNull(client, "client");
+ this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult,
+ "blockUntilJobCompletesAndReturnResult");
+ this.getFirewallRulesByVirtualMachine = checkNotNull(getFirewallRulesByVirtualMachine,
+ "getFirewallRulesByVirtualMachine");
+ }
+
+ public Set<FirewallRule> apply(PublicIPAddress ip, Iterable<Integer> ports) {
+ return apply(ip, "tcp", ports);
+ }
+
+ public Set<FirewallRule> apply(PublicIPAddress ip, String protocol, Iterable<Integer> ports) {
+ checkState(ip.getVirtualMachineId() != null,
+ "ip %s should be static NATed to a virtual machine before applying rules", ip);
+ if (Iterables.isEmpty(ports))
+ return ImmutableSet.<FirewallRule> of();
+ Builder<AsyncCreateResponse> responses = ImmutableSet.builder();
+ for (int port : ports) {
+ AsyncCreateResponse response = client.getFirewallApi().createFirewallRuleForIpAndProtocol(ip.getId(), FirewallRule.Protocol.fromValue(protocol),
+ CreateFirewallRuleOptions.Builder.startPort(port).endPort(port));
+ logger.debug(">> creating firewall rule IPAddress(%s) for protocol(%s), port(%s); response(%s)",
+ ip.getId(), protocol, port, response);
+ responses.add(response);
+ }
+ Builder<FirewallRule> rules = ImmutableSet.builder();
+ for (AsyncCreateResponse response : responses.build()) {
+ FirewallRule rule = blockUntilJobCompletesAndReturnResult.<FirewallRule> apply(response);
+ rules.add(rule);
+ getFirewallRulesByVirtualMachine.asMap().put(ip.getVirtualMachineId(), ImmutableSet.of(rule));
+ }
+ return rules.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreatePortForwardingRulesForIP.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreatePortForwardingRulesForIP.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreatePortForwardingRulesForIP.java
new file mode 100644
index 0000000..dd09f77
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreatePortForwardingRulesForIP.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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.IPForwardingRule;
+import org.jclouds.cloudstack.domain.PublicIPAddress;
+import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ImmutableSet.Builder;
+
+@Singleton
+public class CreatePortForwardingRulesForIP {
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final CloudStackApi client;
+ private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult;
+ private final LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine;
+
+ @Inject
+ public CreatePortForwardingRulesForIP(CloudStackApi client,
+ BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult,
+ LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine) {
+ this.client = checkNotNull(client, "client");
+ this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult,
+ "blockUntilJobCompletesAndReturnResult");
+ this.getIPForwardingRulesByVirtualMachine = checkNotNull(getIPForwardingRulesByVirtualMachine,
+ "getIPForwardingRulesByVirtualMachine");
+ }
+
+ public Set<IPForwardingRule> apply(PublicIPAddress ip, Iterable<Integer> ports) {
+ return apply(ip, "tcp", ports);
+ }
+
+ public Set<IPForwardingRule> apply(PublicIPAddress ip, String protocol, Iterable<Integer> ports) {
+ checkState(ip.getVirtualMachineId() != null,
+ "ip %s should be static NATed to a virtual machine before applying rules", ip);
+ if (Iterables.isEmpty(ports))
+ return ImmutableSet.<IPForwardingRule> of();
+ Builder<AsyncCreateResponse> responses = ImmutableSet.builder();
+ for (int port : ports) {
+ AsyncCreateResponse response = client.getNATApi().createIPForwardingRule(ip.getId(), protocol, port);
+ logger.debug(">> creating IP forwarding rule IPAddress(%s) for protocol(%s), port(%s); response(%s)",
+ ip.getId(), protocol, port, response);
+ responses.add(response);
+ }
+ Builder<IPForwardingRule> rules = ImmutableSet.builder();
+ for (AsyncCreateResponse response : responses.build()) {
+ IPForwardingRule rule = blockUntilJobCompletesAndReturnResult.<IPForwardingRule> apply(response);
+ rules.add(rule);
+ getIPForwardingRulesByVirtualMachine.asMap().put(ip.getVirtualMachineId(), ImmutableSet.of(rule));
+ }
+ return rules.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeeded.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeeded.java
new file mode 100644
index 0000000..8360977
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/CreateSecurityGroupIfNeeded.java
@@ -0,0 +1,111 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.cloudstack.predicates.SecurityGroupPredicates.portInRangeForCidr;
+import static org.jclouds.cloudstack.predicates.ZonePredicates.supportsSecurityGroups;
+
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.SecurityGroup;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs;
+
+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;
+
+@Singleton
+public class CreateSecurityGroupIfNeeded implements Function<ZoneSecurityGroupNamePortsCidrs, SecurityGroup> {
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+ protected final CloudStackApi client;
+ protected final Supplier<LoadingCache<String, Zone>> zoneIdToZone;
+ protected final Predicate<String> jobComplete;
+
+ @Inject
+ public CreateSecurityGroupIfNeeded(CloudStackApi client,
+ Predicate<String> jobComplete,
+ Supplier<LoadingCache<String, Zone>> zoneIdToZone) {
+ this.client = checkNotNull(client, "client");
+ this.jobComplete = checkNotNull(jobComplete, "jobComplete");
+ this.zoneIdToZone = zoneIdToZone;
+ }
+
+ @Override
+ public SecurityGroup apply(ZoneSecurityGroupNamePortsCidrs input) {
+ checkNotNull(input, "input");
+
+ String zoneId = input.getZone();
+ Zone zone = zoneIdToZone.get().getUnchecked(zoneId);
+
+ checkArgument(supportsSecurityGroups().apply(zone),
+ "Security groups are required, but the zone %s does not support security groups", zoneId);
+ logger.debug(">> creating securityGroup %s", input);
+ try {
+
+ SecurityGroup securityGroup = client.getSecurityGroupApi().createSecurityGroup(input.getName());
+
+ logger.debug("<< created securityGroup(%s)", securityGroup);
+ ImmutableSet<String> cidrs;
+ if (!input.getCidrs().isEmpty()) {
+ cidrs = ImmutableSet.copyOf(input.getCidrs());
+ } else {
+ cidrs = ImmutableSet.of("0.0.0.0/0");
+ }
+ for (int port : input.getPorts()) {
+ authorizeGroupToItselfAndToTCPPortAndCidr(client, securityGroup, port, cidrs);
+ }
+ return securityGroup;
+ } catch (IllegalStateException e) {
+ logger.trace("<< trying to find securityGroup(%s): %s", input, e.getMessage());
+ SecurityGroup group = client.getSecurityGroupApi().getSecurityGroupByName(input.getName());
+ logger.debug("<< reused securityGroup(%s)", group.getId());
+ return group;
+ }
+ }
+
+ private void authorizeGroupToItselfAndToTCPPortAndCidr(CloudStackApi client,
+ SecurityGroup securityGroup,
+ int port,
+ Set<String> cidrs) {
+ for (String cidr : cidrs) {
+ logger.debug(">> authorizing securityGroup(%s) permission to %s on port %d", securityGroup, cidr, port);
+ if (!portInRangeForCidr(port, cidr).apply(securityGroup)) {
+ jobComplete.apply(client.getSecurityGroupApi().authorizeIngressPortsToCIDRs(securityGroup.getId(),
+ "TCP",
+ port,
+ port,
+ ImmutableSet.of(cidr)));
+ logger.debug("<< authorized securityGroup(%s) permission to %s on port %d", securityGroup, cidr, port);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/DateToYyyyMmDd.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/DateToYyyyMmDd.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/DateToYyyyMmDd.java
new file mode 100644
index 0000000..cddb19d
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/DateToYyyyMmDd.java
@@ -0,0 +1,39 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.google.common.base.Function;
+
+/**
+ * Convert a Date object into a "yyyy-MM-dd" String
+ */
+public class DateToYyyyMmDd implements Function<Object, String> {
+
+ public String apply(Object input) {
+ checkNotNull(input, "input cannot be null");
+ checkArgument(input instanceof Date, "input must be a Date");
+
+ return new SimpleDateFormat("yyyy-MM-dd").format((Date)input);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetFirewallRulesByVirtualMachine.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetFirewallRulesByVirtualMachine.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetFirewallRulesByVirtualMachine.java
new file mode 100644
index 0000000..3fc73ab
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetFirewallRulesByVirtualMachine.java
@@ -0,0 +1,49 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.cache.CacheLoader;
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.FirewallRule;
+import org.jclouds.cloudstack.options.ListFirewallRulesOptions;
+
+@Singleton
+public class GetFirewallRulesByVirtualMachine extends CacheLoader<String, Set<FirewallRule>> {
+ private final CloudStackApi client;
+
+ @Inject
+ public GetFirewallRulesByVirtualMachine(CloudStackApi client) {
+ this.client = checkNotNull(client, "client");
+ }
+
+ /**
+ * @throws org.jclouds.rest.ResourceNotFoundException
+ * when there is no ip forwarding rule available for the VM
+ */
+ @Override
+ public Set<FirewallRule> load(String input) {
+ String publicIPId = client.getVirtualMachineApi().getVirtualMachine(input).getPublicIPId();
+ Set<FirewallRule> rules = client.getFirewallApi()
+ .listFirewallRules(ListFirewallRulesOptions.Builder.ipAddressId(publicIPId));
+ return rules != null ? rules : ImmutableSet.<FirewallRule>of();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetIPForwardingRulesByVirtualMachine.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetIPForwardingRulesByVirtualMachine.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetIPForwardingRulesByVirtualMachine.java
new file mode 100644
index 0000000..02e6fa1
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/GetIPForwardingRulesByVirtualMachine.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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.IPForwardingRule;
+
+import com.google.common.cache.CacheLoader;
+
+@Singleton
+public class GetIPForwardingRulesByVirtualMachine extends CacheLoader<String, Set<IPForwardingRule>> {
+ private final CloudStackApi client;
+
+ @Inject
+ public GetIPForwardingRulesByVirtualMachine(CloudStackApi client) {
+ this.client = checkNotNull(client, "client");
+ }
+
+ /**
+ * @throws org.jclouds.rest.ResourceNotFoundException
+ * when there is no ip forwarding rule available for the VM
+ */
+ @Override
+ public Set<IPForwardingRule> load(String input) {
+ return client.getNATApi().getIPForwardingRulesForVirtualMachine(input);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponse.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponse.java
new file mode 100644
index 0000000..3095729
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobFromHttpResponse.java
@@ -0,0 +1,51 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.AsyncJob;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.UnwrapOnlyJsonValue;
+
+import com.google.common.base.Function;
+import com.google.inject.Inject;
+
+@Singleton
+public class ParseAsyncJobFromHttpResponse implements Function<HttpResponse, AsyncJob<?>> {
+ private final UnwrapOnlyJsonValue<AsyncJob<Map<String, JsonBall>>> parser;
+ private final ParseTypedAsyncJob parseTyped;
+
+ @Inject
+ public ParseAsyncJobFromHttpResponse(ParseTypedAsyncJob parseTyped,
+ UnwrapOnlyJsonValue<AsyncJob<Map<String, JsonBall>>> parser) {
+ this.parseTyped = checkNotNull(parseTyped, "parseTyped");
+ this.parser = checkNotNull(parser, "parser");
+ }
+
+ public AsyncJob<?> apply(HttpResponse response) {
+ checkNotNull(response, "response");
+ AsyncJob<Map<String, JsonBall>> toParse = parser.apply(response);
+ checkNotNull(toParse, "parsed result from %s", response);
+ return parseTyped.apply(toParse);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponse.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponse.java
new file mode 100644
index 0000000..59f479f
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseAsyncJobsFromHttpResponse.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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.AsyncJob;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.json.internal.GsonWrapper;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+@Singleton
+public class ParseAsyncJobsFromHttpResponse implements Function<HttpResponse, Set<AsyncJob<?>>> {
+ private final ParseFirstJsonValueNamed<Set<AsyncJob<Map<String, JsonBall>>>> parser;
+ private final ParseTypedAsyncJob parseTyped;
+
+ @Inject
+ public ParseAsyncJobsFromHttpResponse(ParseTypedAsyncJob parseTyped, GsonWrapper gsonView) {
+ this.parseTyped = checkNotNull(parseTyped, "parseTyped");
+ this.parser = new ParseFirstJsonValueNamed<Set<AsyncJob<Map<String, JsonBall>>>>(
+ checkNotNull(gsonView, "gsonView"),
+ new TypeLiteral<Set<AsyncJob<Map<String, JsonBall>>>>() { },
+ "asyncjobs");
+ }
+
+ public Set<AsyncJob<?>> apply(HttpResponse response) {
+ checkNotNull(response, "response");
+ Set<AsyncJob<Map<String, JsonBall>>> toParse = parser.apply(response);
+ checkNotNull(toParse, "parsed result from %s", response);
+ return ImmutableSet.copyOf(Iterables.transform(toParse, parseTyped));
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseEventTypesFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseEventTypesFromHttpResponse.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseEventTypesFromHttpResponse.java
new file mode 100644
index 0000000..552a6e8
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseEventTypesFromHttpResponse.java
@@ -0,0 +1,79 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.json.internal.GsonWrapper;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+@Singleton
+public class ParseEventTypesFromHttpResponse implements Function<HttpResponse, Set<String>> {
+ private final ParseFirstJsonValueNamed<Set<EventType>> parser;
+
+ private static class EventType {
+ private String name;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ EventType that = (EventType) o;
+
+ if (!Objects.equal(name, that.name)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+ }
+
+ @Inject
+ public ParseEventTypesFromHttpResponse(GsonWrapper gsonView) {
+ this.parser = new ParseFirstJsonValueNamed<Set<EventType>>(checkNotNull(gsonView, "gsonView"),
+ new TypeLiteral<Set<EventType>>() {
+ }, "eventtype");
+ }
+
+ public Set<String> apply(HttpResponse response) {
+ checkNotNull(response, "response");
+ Set<EventType> toParse = parser.apply(response);
+ checkNotNull(toParse, "parsed result from %s", response);
+ Builder<String> builder = ImmutableSet.builder();
+ for (EventType entry : toParse)
+ builder.add(entry.name);
+ return builder.build();
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameEntryFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameEntryFromHttpResponse.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameEntryFromHttpResponse.java
new file mode 100644
index 0000000..936e5aa
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameEntryFromHttpResponse.java
@@ -0,0 +1,46 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpResponse;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+
+@Singleton
+public class ParseIdToNameEntryFromHttpResponse implements Function<HttpResponse, Map.Entry<String, String>> {
+ private final ParseIdToNameFromHttpResponse parser;
+
+ @Inject
+ public ParseIdToNameEntryFromHttpResponse(ParseIdToNameFromHttpResponse parser) {
+ this.parser = checkNotNull(parser, "parser");
+ }
+
+ public Map.Entry<String, String> apply(HttpResponse response) {
+ checkNotNull(response, "response");
+ Map<String, String> toParse = parser.apply(response);
+ checkNotNull(toParse, "parsed result from %s", response);
+ return Iterables.getFirst(toParse.entrySet(), null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameFromHttpResponse.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameFromHttpResponse.java
new file mode 100644
index 0000000..d2ba0a7
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseIdToNameFromHttpResponse.java
@@ -0,0 +1,80 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.json.internal.GsonWrapper;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSortedMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+@Singleton
+public class ParseIdToNameFromHttpResponse implements Function<HttpResponse, Map<String, String>> {
+ private final ParseFirstJsonValueNamed<Set<IdName>> parser;
+
+ private static class IdName {
+ private String id;
+ private String name;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ IdName that = (IdName) o;
+
+ if (!Objects.equal(id, that.id)) return false;
+ if (!Objects.equal(name, that.name)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, name);
+ }
+ }
+
+ @Inject
+ public ParseIdToNameFromHttpResponse(GsonWrapper gsonView) {
+ this.parser = new ParseFirstJsonValueNamed<Set<IdName>>(checkNotNull(gsonView, "gsonView"),
+ new TypeLiteral<Set<IdName>>() {
+ }, "oscategory");
+ }
+
+ public Map<String, String> apply(HttpResponse response) {
+ checkNotNull(response, "response");
+ Set<IdName> toParse = parser.apply(response);
+ checkNotNull(toParse, "parsed result from %s", response);
+ Builder<String, String> builder = ImmutableSortedMap.naturalOrder();
+ for (IdName entry : toParse)
+ builder.put(entry.id, entry.name);
+ return builder.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.java
new file mode 100644
index 0000000..317aa28
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseLoginResponseFromHttpResponse.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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.get;
+import static com.google.common.collect.Iterables.getOnlyElement;
+
+import org.jclouds.cloudstack.domain.LoginResponse;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.json.internal.GsonWrapper;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+public class ParseLoginResponseFromHttpResponse implements Function<HttpResponse, LoginResponse> {
+
+ private ParseFirstJsonValueNamed<LoginResponse> parser;
+
+ @Inject
+ ParseLoginResponseFromHttpResponse(GsonWrapper gson) {
+ this.parser = new ParseFirstJsonValueNamed<LoginResponse>(checkNotNull(gson, "gsonView"),
+ new TypeLiteral<LoginResponse>(){}, "loginresponse");
+ }
+
+ @Override
+ public LoginResponse apply(HttpResponse response) {
+ checkNotNull(response, "response");
+
+ LoginResponse login = parser.apply(response);
+ checkNotNull(login, "loginResponse");
+
+ String jSessionId = get(Splitter.on("=").split(get(Splitter.on(";").trimResults().split(
+ getOnlyElement(response.getHeaders().get("Set-Cookie"))), 0)), 1);
+
+ return LoginResponse.builder().fromLoginResponse(login).jSessionId(jSessionId).build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseNamesFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseNamesFromHttpResponse.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseNamesFromHttpResponse.java
new file mode 100644
index 0000000..f30c6a4
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseNamesFromHttpResponse.java
@@ -0,0 +1,77 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.json.internal.GsonWrapper;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+@Singleton
+public class ParseNamesFromHttpResponse implements Function<HttpResponse, Set<String>> {
+ private final ParseFirstJsonValueNamed<Set<Name>> parser;
+
+ private static class Name {
+ private String name;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Name that = (Name) o;
+
+ if (!Objects.equal(name, that.name)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+ }
+
+ @Inject
+ public ParseNamesFromHttpResponse(GsonWrapper gsonView) {
+ this.parser = new ParseFirstJsonValueNamed<Set<Name>>(checkNotNull(gsonView, "gsonView"),
+ new TypeLiteral<Set<Name>>() {
+ }, "hypervisor");
+ }
+
+ public Set<String> apply(HttpResponse response) {
+ checkNotNull(response, "response");
+ Set<Name> toParse = parser.apply(response);
+ checkNotNull(toParse, "parsed result from %s", response);
+ Builder<String> builder = ImmutableSet.builder();
+ for (Name entry : toParse)
+ builder.add(entry.name);
+ return builder.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseTypedAsyncJob.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseTypedAsyncJob.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseTypedAsyncJob.java
new file mode 100644
index 0000000..0082ea8
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ParseTypedAsyncJob.java
@@ -0,0 +1,129 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.domain.Account;
+import org.jclouds.cloudstack.domain.AsyncJob;
+import org.jclouds.cloudstack.domain.AsyncJobError;
+import org.jclouds.cloudstack.domain.FirewallRule;
+import org.jclouds.cloudstack.domain.IPForwardingRule;
+import org.jclouds.cloudstack.domain.LoadBalancerRule;
+import org.jclouds.cloudstack.domain.Network;
+import org.jclouds.cloudstack.domain.PortForwardingRule;
+import org.jclouds.cloudstack.domain.PublicIPAddress;
+import org.jclouds.cloudstack.domain.SecurityGroup;
+import org.jclouds.cloudstack.domain.Snapshot;
+import org.jclouds.cloudstack.domain.Template;
+import org.jclouds.cloudstack.domain.TemplateExtraction;
+import org.jclouds.cloudstack.domain.User;
+import org.jclouds.cloudstack.domain.VirtualMachine;
+import org.jclouds.cloudstack.domain.Volume;
+import org.jclouds.cloudstack.domain.AsyncJob.Builder;
+import org.jclouds.cloudstack.domain.AsyncJobError.ErrorCode;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.json.Json;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+
+@Singleton
+public class ParseTypedAsyncJob implements Function<AsyncJob<Map<String, JsonBall>>, AsyncJob<?>> {
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ @Inject(optional = true)
+ @VisibleForTesting
+ @Named("jclouds.cloudstack.jobresult-type-map")
+ Map<String, Class<?>> typeMap = ImmutableMap.<String, Class<?>>builder()
+ .put("user", User.class)
+ .put("account", Account.class)
+ .put("securitygroup", SecurityGroup.class)
+ .put("portforwardingrule", PortForwardingRule.class)
+ .put("ipforwardingrule", IPForwardingRule.class)
+ .put("firewallrule", FirewallRule.class)
+ .put("network", Network.class)
+ .put("ipaddress", PublicIPAddress.class)
+ .put("virtualmachine", VirtualMachine.class)
+ .put("loadbalancer", LoadBalancerRule.class)
+ .put("snapshot", Snapshot.class)
+ .put("template", Template.class)
+ .put("volume", Volume.class).build();
+ private final Json json;
+
+ @Inject
+ public ParseTypedAsyncJob(Json json) {
+ this.json = checkNotNull(json, "json");
+ }
+
+ public AsyncJob<?> apply(AsyncJob<Map<String, JsonBall>> toParse) {
+ AsyncJob<?> result = toParse;
+ if (toParse.getResult() != null) {
+ if (toParse.getResult().size() == 1) {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ Builder<?, Object> builder = AsyncJob.Builder.fromAsyncJobUntyped((AsyncJob) toParse);
+ if (toParse.getResult().containsKey("success")) {
+ builder.result(null);
+ } else {
+ Entry<String, JsonBall> entry = Iterables.get(toParse.getResult().entrySet(), 0);
+ if ("template".equals(entry.getKey())) {
+ // Sometimes Cloudstack will say 'template' and the payload is a Template object.
+ // Sometimes Cloudstack will say 'template' and the payload is a TemplateExtraction object.
+ // The 'state' field only exists on TemplateExtraction, so we can test this to work out what we have actually been given.
+ Template template = json.fromJson(entry.getValue().toString(), Template.class);
+ TemplateExtraction templateExtraction = json.fromJson(entry.getValue().toString(), TemplateExtraction.class);
+ boolean isTemplate = Strings.isNullOrEmpty(templateExtraction.getState());
+ builder.result(isTemplate ? template : templateExtraction);
+ } else if (typeMap.containsKey(entry.getKey())) {
+ builder.result(json.fromJson(entry.getValue().toString(), typeMap.get(entry.getKey())));
+ } else {
+ logger.warn(
+ "type key %s not configured. please override default for Map<String, Class<?>> bound to name jclouds.cloudstack.jobresult-type-map",
+ entry.getKey());
+ builder.result(entry.getValue().toString());
+ }
+ }
+ result = builder.build();
+ } else if (toParse.getResult().containsKey("errorcode")) {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ Builder<?, Object> builder = AsyncJob.Builder.fromAsyncJobUntyped((AsyncJob) toParse);
+ builder.result(null); // avoid classcastexceptions
+ builder.error(AsyncJobError.builder().errorCode(ErrorCode.fromValue(toParse.getResult().get("errorcode").toString()))
+ .errorText(toParse.getResult().containsKey("errortext") ? toParse.getResult().get("errortext").toString().replace("\"", "") : null)
+ .build());
+ result = builder.build();
+ } else if (toParse.getResult().size() > 1) {
+ logger.warn("unexpected size of async job result; expecting a map with a single element",
+ toParse.getResult());
+ }
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddress.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddress.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddress.java
new file mode 100644
index 0000000..7ea19b2
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/ReuseOrAssociateNewPublicIPAddress.java
@@ -0,0 +1,101 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.and;
+import static com.google.common.collect.Iterables.find;
+import static org.jclouds.cloudstack.options.AssociateIPAddressOptions.Builder.networkId;
+import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.allocatedOnly;
+import static org.jclouds.cloudstack.predicates.PublicIPAddressPredicates.associatedWithNetwork;
+import static org.jclouds.cloudstack.predicates.PublicIPAddressPredicates.available;
+import static org.jclouds.compute.reference.ComputeServiceConstants.COMPUTE_LOGGER;
+
+import java.util.NoSuchElementException;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.Network;
+import org.jclouds.cloudstack.domain.PublicIPAddress;
+import org.jclouds.cloudstack.features.AddressApi;
+import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+
+@Singleton
+public class ReuseOrAssociateNewPublicIPAddress implements Function<Network, PublicIPAddress> {
+ private final CloudStackApi client;
+ private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult;
+ @Resource
+ @Named(COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ public ReuseOrAssociateNewPublicIPAddress(CloudStackApi client,
+ BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult) {
+ this.client = checkNotNull(client, "client");
+ this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult,
+ "blockUntilJobCompletesAndReturnResult");
+ }
+
+ /**
+ * Finds existing addresses who are ready for use and not assigned to a
+ * machine.
+ *
+ * @param networkId
+ * network id to search
+ * @param client
+ * address client
+ * @return address to use
+ * @throws NoSuchElementException
+ * if there's no existing ip address that is free for use
+ */
+ public static PublicIPAddress findAvailableAndAssociatedWithNetwork(String networkId, AddressApi client) {
+ return find(client.listPublicIPAddresses(allocatedOnly(true).networkId(networkId)),
+ and(associatedWithNetwork(networkId), available()));
+ }
+
+ public static PublicIPAddress associateIPAddressInNetwork(Network network, CloudStackApi client,
+ BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult) {
+ AsyncCreateResponse job = client.getAddressApi().associateIPAddressInZone(network.getZoneId(),
+ networkId(network.getId()));
+ PublicIPAddress ip = blockUntilJobCompletesAndReturnResult.<PublicIPAddress> apply(job);
+ assert ip.getZoneId().equals(network.getZoneId());
+ return ip;
+ }
+
+ @Override
+ public PublicIPAddress apply(Network input) {
+ try {
+ logger.debug(">> looking for existing address in network(%s)", input.getId());
+ PublicIPAddress returnVal = findAvailableAndAssociatedWithNetwork(input.getId(), client.getAddressApi());
+ logger.debug("<< reused address(%s)", returnVal.getId());
+ return returnVal;
+ } catch (NoSuchElementException e) {
+ logger.debug(">> associating new address in network(%s)", input.getId());
+ PublicIPAddress returnVal = associateIPAddressInNetwork(input, client, blockUntilJobCompletesAndReturnResult);
+ logger.debug("<< associated address(%s)", returnVal.getId());
+ return returnVal;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/a4a03688/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetwork.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetwork.java b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetwork.java
new file mode 100644
index 0000000..87fc128
--- /dev/null
+++ b/dependencies/jclouds/apis/cloudstack/1.8.0-stratos/src/main/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetwork.java
@@ -0,0 +1,78 @@
+/*
+ * 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.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.Network;
+import org.jclouds.cloudstack.domain.PublicIPAddress;
+import org.jclouds.cloudstack.domain.VirtualMachine;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.inject.assistedinject.Assisted;
+
+@Singleton
+public class StaticNATVirtualMachineInNetwork implements Function<VirtualMachine, PublicIPAddress> {
+ public interface Factory {
+ StaticNATVirtualMachineInNetwork create(Network in);
+ }
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final CloudStackApi client;
+ private final ReuseOrAssociateNewPublicIPAddress reuseOrAssociate;
+ private final Network network;
+
+ @Inject
+ public StaticNATVirtualMachineInNetwork(CloudStackApi client,
+ ReuseOrAssociateNewPublicIPAddress reuseOrAssociate, @Assisted Network network) {
+ this.client = checkNotNull(client, "client");
+ this.reuseOrAssociate = checkNotNull(reuseOrAssociate, "reuseOrAssociate");
+ this.network = checkNotNull(network, "network");
+ }
+
+ public PublicIPAddress apply(VirtualMachine vm) {
+ PublicIPAddress ip;
+ for (ip = reuseOrAssociate.apply(network); !ip.isStaticNAT() || ip.getVirtualMachineId() != vm.getId(); ip = reuseOrAssociate
+ .apply(network)) {
+ // check to see if someone already grabbed this ip
+ if (ip.getVirtualMachineId() != null && ip.getVirtualMachineId() != vm.getId())
+ continue;
+ try {
+ logger.debug(">> static NATing IPAddress(%s) to virtualMachine(%s)", ip.getId(), vm.getId());
+ client.getNATApi().enableStaticNATForVirtualMachine(vm.getId(), ip.getId());
+ ip = client.getAddressApi().getPublicIPAddress(ip.getId());
+ if (ip.isStaticNAT() && ip.getVirtualMachineId().equals(vm.getId()))
+ break;
+ } catch (IllegalStateException e) {
+ // very likely an ip conflict, so retry;
+ }
+ return ip;
+ }
+ return ip;
+ }
+}