/** * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. jclouds licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.jclouds.compute.util; import static com.google.common.base.Predicates.equalTo; import static com.google.common.base.Predicates.not; import static com.google.common.base.Throwables.getStackTraceAsString; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Maps.filterKeys; import static com.google.common.collect.Maps.filterValues; import static org.jclouds.scriptbuilder.domain.Statements.pipeHttpResponseToBash; import java.net.URI; import java.util.Formatter; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.regex.Pattern; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadataIncludingStatus; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Volume; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.http.HttpRequest; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statements; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.Iterables; /** * * @author Adrian Cole */ public class ComputeServiceUtils { /** * status as a string which optionally includes the backend status */ public static String formatStatus(ComputeMetadataIncludingStatus<?> resource) { if (resource.getBackendStatus() == null) return resource.getStatus().toString(); return String.format("%s[%s]", resource.getStatus(), resource.getBackendStatus()); } public static final Pattern DELIMITED_BY_HYPHEN_ENDING_IN_HYPHEN_HEX = Pattern.compile("(.+)-[0-9a-f]+"); /** * build a shell script that invokes the contents of the http request in bash. * * @return a shell script that will invoke the http request */ public static Statement execHttpResponse(HttpRequest request) { return pipeHttpResponseToBash(request.getMethod(), request.getEndpoint(), request.getHeaders()); } public static Statement execHttpResponse(URI location) { return execHttpResponse(HttpRequest.builder().method("GET").endpoint(location).build()); } /** * build a shell script that invokes the contents of the http request in bash. * * @return a shell script that will invoke the http request */ public static Statement extractTargzIntoDirectory(HttpRequest targz, String directory) { return Statements .extractTargzIntoDirectory(targz.getMethod(), targz.getEndpoint(), targz.getHeaders(), directory); } public static Statement extractTargzIntoDirectory(URI targz, String directory) { return extractTargzIntoDirectory(HttpRequest.builder().method("GET").endpoint(targz).build(), directory); } /** * build a shell script that invokes the contents of the http request in bash. * * @return a shell script that will invoke the http request */ public static Statement extractZipIntoDirectory(HttpRequest zip, String directory) { return Statements.extractZipIntoDirectory(zip.getMethod(), zip.getEndpoint(), zip.getHeaders(), directory); } public static Statement extractZipIntoDirectory(URI zip, String directory) { return extractZipIntoDirectory(HttpRequest.builder().method("GET").endpoint(zip).build(), directory); } public static double getCores(Hardware input) { double cores = 0; for (Processor processor : input.getProcessors()) cores += processor.getCores(); return cores; } public static double getCoresAndSpeed(Hardware input) { double total = 0; for (Processor processor : input.getProcessors()) total += processor.getCores() * processor.getSpeed(); return total; } public static double getSpace(Hardware input) { double total = 0; for (Volume volume : input.getVolumes()) { Float size = volume.getSize(); if (size != null) { total += size; } } return total; } public static org.jclouds.compute.domain.OsFamily parseOsFamilyOrUnrecognized(String in) { org.jclouds.compute.domain.OsFamily myOs = null; for (org.jclouds.compute.domain.OsFamily os : org.jclouds.compute.domain.OsFamily.values()) { if (in.toLowerCase().replaceAll("\\s", "").indexOf(os.toString()) != -1) { myOs = os; } } return myOs != null ? myOs : OsFamily.UNRECOGNIZED; } public static String createExecutionErrorMessage(Map<?, Exception> executionExceptions) { Formatter fmt = new Formatter().format("Execution failures:%n%n"); int index = 1; for (Entry<?, Exception> errorMessage : executionExceptions.entrySet()) { fmt.format("%s) %s on %s:%n%s%n%n", index++, errorMessage.getValue().getClass().getSimpleName(), errorMessage .getKey(), getStackTraceAsString(errorMessage.getValue())); } return fmt.format("%s error[s]", executionExceptions.size()).toString(); } public static String createNodeErrorMessage(Map<? extends NodeMetadata, ? extends Throwable> failedNodes) { Formatter fmt = new Formatter().format("Node failures:%n%n"); int index = 1; for (Entry<? extends NodeMetadata, ? extends Throwable> errorMessage : failedNodes.entrySet()) { fmt.format("%s) %s on node %s:%n%s%n%n", index++, errorMessage.getValue().getClass().getSimpleName(), errorMessage.getKey().getId(), getStackTraceAsString(errorMessage.getValue())); } return fmt.format("%s error[s]", failedNodes.size()).toString(); } public static Iterable<? extends ComputeMetadata> filterByName(Iterable<? extends ComputeMetadata> nodes, final String name) { return filter(nodes, new Predicate<ComputeMetadata>() { @Override public boolean apply(ComputeMetadata input) { return input.getName().equalsIgnoreCase(name); } }); } /** * For cloud apis that have a pattern of using empty strings as tags, return a map that contains * that. */ public static Map<String, String> metadataAndTagsAsValuesOfEmptyString(TemplateOptions options) { Builder<String, String> builder = ImmutableMap.<String, String> builder(); builder.putAll(options.getUserMetadata()); for (String tag : options.getTags()) builder.put(tag, ""); return builder.build(); } /** * @see #metadataAndTagsAsValuesOfEmptyString */ public static NodeMetadataBuilder addMetadataAndParseTagsFromValuesOfEmptyString(NodeMetadataBuilder builder, Map<String, String> map) { return builder.tags(filterValues(map, equalTo("")).keySet()).userMetadata(filterValues(map, not(equalTo("")))); } /** * For cloud apis that need to namespace tags as the value of the key {@code jclouds.tags} */ public static Map<String, String> metadataAndTagsAsCommaDelimitedValue(TemplateOptions options) { Builder<String, String> builder = ImmutableMap.<String, String> builder(); builder.putAll(options.getUserMetadata()); if (options.getTags().size() > 0) builder.put("jclouds_tags", Joiner.on(',').join(options.getTags())); return builder.build(); } /** * @see #metadataAndTagsAsCommaDelimitedValue */ public static NodeMetadataBuilder addMetadataAndParseTagsFromCommaDelimitedValue(NodeMetadataBuilder builder, Map<String, String> map) { String tagString = map.get("jclouds_tags"); if (tagString != null) builder.tags(Splitter.on(',').split(tagString)); builder.userMetadata(filterKeys(map, not(equalTo("jclouds_tags")))); return builder; } public static String parseVersionOrReturnEmptyString(org.jclouds.compute.domain.OsFamily family, String in, Map<OsFamily, Map<String, String>> osVersionMap) { if (osVersionMap.containsKey(family)) { if (osVersionMap.get(family).containsKey(in)) return osVersionMap.get(family).get(in); if (osVersionMap.get(family).containsValue(in)) return in; CONTAINS_SUBSTRING contains = new CONTAINS_SUBSTRING(in.replace('-', '.')); try { String key = Iterables.find(osVersionMap.get(family).keySet(), contains); return osVersionMap.get(family).get(key); } catch (NoSuchElementException e) { try { return Iterables.find(osVersionMap.get(family).values(), contains); } catch (NoSuchElementException e1) { } } } return ""; } static final class CONTAINS_SUBSTRING implements Predicate<String> { private final String in; CONTAINS_SUBSTRING(String in) { this.in = in; } @Override public boolean apply(String input) { if ("".equals(input)) return false; return in.indexOf(input) != -1; } @Override public String toString() { return String.format("containsSubString(%s)", in); } } }