From 401d2f675f4f48e947d4a4c0b5262a37101fb276 Mon Sep 17 00:00:00 2001 From: danikov Date: Mon, 23 Apr 2012 11:31:12 +0100 Subject: [PATCH] cloud director compute functions and predicates --- .../java/org/jclouds/dmtf/CIMPredicates.java | 59 ++++++++ ...ardwareBuilderFromResourceAllocations.java | 75 +++++++++ .../functions/FindLocationForResource.java | 71 +++++++++ .../compute/functions/HardwareForVApp.java | 83 ++++++++++ .../functions/HardwareForVAppTemplate.java | 90 +++++++++++ .../functions/ImageForVAppTemplate.java | 82 ++++++++++ .../compute/functions/VAppToNodeMetadata.java | 99 ++++++++++++ ...ardwareBuilderFromResourceAllocations.java | 44 ++++++ ...velopeOrThrowIllegalArgumentException.java | 84 ++++++++++ .../v1_5/compute/util/VCloudComputeUtils.java | 143 ++++++++++++++++++ .../VCloudDirectorRestClientModule.java | 3 + .../v1_5/functions/SectionForVApp.java | 52 +++++++ .../functions/SectionForVAppTemplate.java | 4 - 13 files changed, 885 insertions(+), 4 deletions(-) create mode 100644 labs/dmtf/src/main/java/org/jclouds/dmtf/CIMPredicates.java create mode 100644 labs/dmtf/src/main/java/org/jclouds/dmtf/cim/functions/HardwareBuilderFromResourceAllocations.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/FindLocationForResource.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVApp.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVAppTemplate.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ImageForVAppTemplate.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VAppToNodeMetadata.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VCloudHardwareBuilderFromResourceAllocations.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/util/VCloudComputeUtils.java create mode 100644 labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVApp.java diff --git a/labs/dmtf/src/main/java/org/jclouds/dmtf/CIMPredicates.java b/labs/dmtf/src/main/java/org/jclouds/dmtf/CIMPredicates.java new file mode 100644 index 0000000000..485877b765 --- /dev/null +++ b/labs/dmtf/src/main/java/org/jclouds/dmtf/CIMPredicates.java @@ -0,0 +1,59 @@ +/** + * 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.dmtf; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author danikov + */ +public class CIMPredicates { + + /** + * Return resource allocations of the specific type. + * + * @param type + * type to match the items + * @return predicate + */ + public static Predicate resourceTypeIn(final ResourceType... types) { + checkNotNull(types, "resourceTypes"); + final Set resourceTypes = ImmutableSet.copyOf(types); + return new Predicate() { + @Override + public boolean apply(ResourceAllocationSettingData in) { + return resourceTypes.contains(in.getResourceType()); + } + + @Override + public String toString() { + return "resourceTypeIn(" + resourceTypes + ")"; + } + }; + } +} diff --git a/labs/dmtf/src/main/java/org/jclouds/dmtf/cim/functions/HardwareBuilderFromResourceAllocations.java b/labs/dmtf/src/main/java/org/jclouds/dmtf/cim/functions/HardwareBuilderFromResourceAllocations.java new file mode 100644 index 0000000000..f881fa8343 --- /dev/null +++ b/labs/dmtf/src/main/java/org/jclouds/dmtf/cim/functions/HardwareBuilderFromResourceAllocations.java @@ -0,0 +1,75 @@ +/** + * 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.dmtf.cim.functions; + +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.transform; + +import javax.inject.Singleton; + +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.dmtf.CIMPredicates; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType; + +import com.google.common.base.Function; + +/** + * @author Adrian Cole + */ +@Singleton +public class HardwareBuilderFromResourceAllocations implements + Function, HardwareBuilder> { + @Override + public HardwareBuilder apply(Iterable from) { + HardwareBuilder builder = new HardwareBuilder(); + builder.volumes(transform(filter(from, CIMPredicates.resourceTypeIn(ResourceType.DISK_DRIVE, + ResourceType.BASE_PARTITIONABLE_UNIT, ResourceType.PARTITIONABLE_UNIT)), + new Function() { + + @Override + public Volume apply(ResourceAllocationSettingData from) { + return HardwareBuilderFromResourceAllocations.this.apply(from); + } + + })); + + builder.ram((int) find(from, CIMPredicates.resourceTypeIn(ResourceType.MEMORY)).getVirtualQuantity().longValue()); + + builder.processors(transform(filter(from, CIMPredicates.resourceTypeIn(ResourceType.PROCESSOR)), + new Function() { + + @Override + public Processor apply(ResourceAllocationSettingData arg0) { + return new Processor(arg0.getVirtualQuantity().longValue(), 1); + } + })); + return builder; + } + + public Volume apply(ResourceAllocationSettingData from) { + return new VolumeImpl(from.getAddressOnParent() + "", Volume.Type.LOCAL, from.getVirtualQuantity() == null ? null + : from.getVirtualQuantity().longValue() / 1024 / 1024f, null, "0".equals(from.getAddressOnParent()) + || ResourceType.BASE_PARTITIONABLE_UNIT.equals(from.getResourceType()), true); + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/FindLocationForResource.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/FindLocationForResource.java new file mode 100644 index 0000000000..b123469a01 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/FindLocationForResource.java @@ -0,0 +1,71 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import java.net.URI; +import java.util.NoSuchElementException; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.collect.Memoized; +import org.jclouds.domain.Location; +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.director.v1_5.domain.Reference; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +/** + * @author danikov + */ +@Singleton +public class FindLocationForResource implements Function { + + @Resource + protected Logger logger = Logger.NULL; + + final Supplier> locations; + + @Inject + public FindLocationForResource(@Memoized Supplier> locations) { + this.locations = locations; + } + + /** + * searches for a location associated with this resource. + * + * @throws NoSuchElementException + * if not found + */ + public Location apply(Reference resource) { + for (Location input : locations.get()) { + do { + // The "name" isn't always present, ex inside a vApp we have a rel + // link that only includes href and type. + if (URI.create(input.getId()).equals(resource.getHref())) + return input; + } while ((input = input.getParent()) != null); + } + throw new NoSuchElementException(String.format("resource: %s not found in locations: %s", resource, + locations.get())); + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVApp.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVApp.java new file mode 100644 index 0000000000..8df5e4d1af --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVApp.java @@ -0,0 +1,83 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.predicates.ImagePredicates; +import org.jclouds.domain.Location; +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Link; +import org.jclouds.vcloud.director.v1_5.domain.Reference; +import org.jclouds.vcloud.director.v1_5.domain.VApp; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; +import org.jclouds.vcloud.director.v1_5.functions.SectionForVApp; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.inject.name.Named; + +/** + * @author Adrian Cole + */ +public class HardwareForVApp implements Function { + + @Resource + protected Logger logger = Logger.NULL; + + private final Function findLocationForResource; + private final VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder; + private final SectionForVApp findVirtualHardwareSectionForVm; + + @Inject + protected HardwareForVApp(Function findLocationForResource, + VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder, + SectionForVApp findVirtualHardwareSectionForVm) { + this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource"); + this.rasdToHardwareBuilder = checkNotNull(rasdToHardwareBuilder, "rasdToHardwareBuilder"); + this.findVirtualHardwareSectionForVm = checkNotNull(findVirtualHardwareSectionForVm, "findVirtualHardwareSectionForVm"); + } + + @Override + public Hardware apply(VApp from) { + checkNotNull(from, "VApp"); + // TODO make this work with composite vApps + Vm vm = from.getChildren().getVms().size() == 0 ? null : Iterables.get(from.getChildren().getVms(), 0); + if (vm == null) + return null; + + VirtualHardwareSection hardware = findVirtualHardwareSectionForVm.apply(vm); + HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getItems()); + builder.location(findLocationForResource.apply(Iterables.find(checkNotNull(from, "from").getLinks(), + LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)))); + builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage( + ImagePredicates.idEquals(from.getHref().toASCIIString())); + builder.hypervisor("VMware"); + return builder.build(); + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVAppTemplate.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVAppTemplate.java new file mode 100644 index 0000000000..d1bef8b89c --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVAppTemplate.java @@ -0,0 +1,90 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.predicates.ImagePredicates; +import org.jclouds.dmtf.ovf.VirtualHardwareSection; +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Link; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.domain.dmtf.Envelope; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class HardwareForVAppTemplate implements Function { + + @Resource + protected Logger logger = Logger.NULL; + + private final Function templateToEnvelope; + private final FindLocationForResource findLocationForResource; + private final VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder; + + @Inject + protected HardwareForVAppTemplate(Function templateToEnvelope, + FindLocationForResource findLocationForResource, + VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder) { + this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope"); + this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource"); + this.rasdToHardwareBuilder = checkNotNull(rasdToHardwareBuilder, "rasdToHardwareBuilder"); + } + + @Override + public Hardware apply(VAppTemplate from) { + checkNotNull(from, "VAppTemplate"); + + Envelope ovf = templateToEnvelope.apply(from); + + if (ovf.getVirtualSystem().getVirtualHardwareSections().size() > 1) { + logger.warn("multiple hardware choices found. using first", ovf); + } + VirtualHardwareSection hardware = Iterables.get(ovf.getVirtualSystem().getVirtualHardwareSections(), 0); + HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getItems()); + Link vdc = Iterables.find(checkNotNull(from, "from").getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)); + if (vdc != null) { + builder.location(findLocationForResource.apply(vdc)); + } else { + // otherwise, it could be in a public catalog, which is not assigned to a VDC + } + builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage( + ImagePredicates.idEquals(from.getHref().toASCIIString())); + builder.hypervisor("VMware"); + return builder.build(); + + } + + protected String getName(String name) { + return name; + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ImageForVAppTemplate.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ImageForVAppTemplate.java new file mode 100644 index 0000000000..18c934ebc1 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ImageForVAppTemplate.java @@ -0,0 +1,82 @@ +/** + * 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.vcloud.director.v1_5.compute.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.compute.domain.CIMOperatingSystem; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.ovf.Envelope; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Link; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class ImageForVAppTemplate implements Function { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + public Logger logger = Logger.NULL; + + private final Function templateToEnvelope; + private final FindLocationForResource findLocationForResource; + + @Inject + protected ImageForVAppTemplate(Function templateToEnvelope, + FindLocationForResource findLocationForResource) { + this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope"); + this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource"); + } + + @Override + public Image apply(VAppTemplate from) { + checkNotNull(from, "VAppTemplate"); + Envelope ovf = templateToEnvelope.apply(from); + + ImageBuilder builder = new ImageBuilder(); + builder.ids(from.getHref().toASCIIString()); + builder.uri(from.getHref()); + builder.name(from.getName()); + Link vdc = Iterables.find(checkNotNull(from, "from").getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)); + if (vdc != null) { + builder.location(findLocationForResource.apply(vdc)); + } else { + // otherwise, it could be in a public catalog, which is not assigned to a VDC + } + builder.description(from.getDescription() != null ? from.getDescription() : from.getName()); + builder.operatingSystem(CIMOperatingSystem.toComputeOs(ovf)); + return builder.build(); + } + +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VAppToNodeMetadata.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VAppToNodeMetadata.java new file mode 100644 index 0000000000..4f90d7da39 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VAppToNodeMetadata.java @@ -0,0 +1,99 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Iterables.filter; +import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudComputeUtils.getCredentialsFrom; +import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudComputeUtils.getIpsFromVApp; +import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudComputeUtils.toComputeOs; + +import java.util.Map; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.domain.Credentials; +import org.jclouds.logging.Logger; +import org.jclouds.util.InetAddresses2.IsPrivateIPAddress; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status; +import org.jclouds.vcloud.director.v1_5.domain.VApp; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class VAppToNodeMetadata implements Function { + @Resource + protected static Logger logger = Logger.NULL; + + protected final FindLocationForResource findLocationForResourceInVDC; + protected final Function hardwareForVApp; + protected final Map vAppStatusToNodeState; + protected final Map credentialStore; + protected final GroupNamingConvention nodeNamingConvention; + + @Inject + protected VAppToNodeMetadata(Map vAppStatusToNodeState, Map credentialStore, + FindLocationForResource findLocationForResourceInVDC, Function hardwareForVApp, + GroupNamingConvention.Factory namingConvention) { + this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix(); + this.hardwareForVApp = checkNotNull(hardwareForVApp, "hardwareForVApp"); + this.findLocationForResourceInVDC = checkNotNull(findLocationForResourceInVDC, "findLocationForResourceInVDC"); + this.credentialStore = checkNotNull(credentialStore, "credentialStore"); + this.vAppStatusToNodeState = checkNotNull(vAppStatusToNodeState, "vAppStatusToNodeState"); + } + + public NodeMetadata apply(VApp from) { + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + builder.ids(from.getHref().toASCIIString()); + builder.uri(from.getHref()); + builder.name(from.getName()); + builder.hostname(from.getName()); + builder.location(findLocationForResourceInVDC.apply( + Iterables.find(from.getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)))); + builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName())); + builder.operatingSystem(toComputeOs(from, null)); + builder.hardware(hardwareForVApp.apply(from)); + builder.state(vAppStatusToNodeState.get(from.getStatus())); + Set addresses = getIpsFromVApp(from); + builder.publicAddresses(filter(addresses, not(IsPrivateIPAddress.INSTANCE))); + builder.privateAddresses(filter(addresses, IsPrivateIPAddress.INSTANCE)); + + // normally, we don't affect the credential store when reading vApps. + // However, login user, etc, is actually in the metadata, so lets see + Credentials fromApi = getCredentialsFrom(from); + if (fromApi != null && !credentialStore.containsKey("node#" + from.getHref().toASCIIString())) + credentialStore.put("node#" + from.getHref().toASCIIString(), fromApi); + return builder.build(); + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VCloudHardwareBuilderFromResourceAllocations.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VCloudHardwareBuilderFromResourceAllocations.java new file mode 100644 index 0000000000..8bbd8179c5 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VCloudHardwareBuilderFromResourceAllocations.java @@ -0,0 +1,44 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Volume; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.functions.HardwareBuilderFromResourceAllocations; + +/** + * @author Adrian Cole + */ +@Singleton +public class VCloudHardwareBuilderFromResourceAllocations extends HardwareBuilderFromResourceAllocations { + @Override + public Volume apply(ResourceAllocationSettingData from) { + // FIXME: not yet implemented +// if (from instanceof VCloudHardDisk) { +// VCloudHardDisk vDisk = VCloudHardDisk.class.cast(from); +// return new VolumeImpl(from.getAddressOnParent() + "", Volume.Type.LOCAL, vDisk.getCapacity() / 1024f, null, +// "0".equals(from.getAddressOnParent()), true); +// } else { +// return super.apply(from); +// } + return null; + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException.java new file mode 100644 index 0000000000..7e36aefa33 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException.java @@ -0,0 +1,84 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.concurrent.ExecutionException; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.dmtf.ovf.NetworkSection; +import org.jclouds.logging.Logger; +import org.jclouds.ovf.Envelope; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.functions.SectionForVAppTemplate; + +import com.google.common.base.Function; +import com.google.common.cache.LoadingCache; + +/** + * @author Adrian Cole + */ +@Singleton +public class ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException implements + Function { + + @Resource + protected Logger logger = Logger.NULL; + + private final LoadingCache envelopes; + private final SectionForVAppTemplate findNetworkSectionForVAppTemplate; + + @Inject + protected ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException(LoadingCache envelopes, + SectionForVAppTemplate findNetworkSectionForVAppTemplate) { + this.envelopes = checkNotNull(envelopes, "envelopes"); + this.findNetworkSectionForVAppTemplate = checkNotNull(findNetworkSectionForVAppTemplate, "findNetworkSectionForVAppTemplate"); + } + + @Override + public Envelope apply(VAppTemplate from) { + checkArgument(from.getChildren().size() == 1, "multiple vms are not supported: %s", from); + + checkArgument(findNetworkSectionForVAppTemplate.apply(from).getNetworks().size() == 1, + "multiple network connections are not supported: %s", from); + + checkArgument(from.isOvfDescriptorUploaded(), "ovf descriptor is not uploaded: %s", from); + Envelope ovf = getOVFForVAppTemplateAndValidate(from); + return ovf; + } + + private Envelope getOVFForVAppTemplateAndValidate(VAppTemplate from) throws IllegalArgumentException { + Envelope ovf; + try { + ovf = envelopes.get(from.getHref()); + checkArgument(ovf.getVirtualSystem().getVirtualHardwareSections().size() > 0, + "no hardware sections exist in ovf %s", ovf); + } catch (ExecutionException e) { + throw new IllegalArgumentException("no ovf envelope found for: " + from, e); + } + return ovf; + } +} + diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/util/VCloudComputeUtils.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/util/VCloudComputeUtils.java new file mode 100644 index 0000000000..e94cef2fc3 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/util/VCloudComputeUtils.java @@ -0,0 +1,143 @@ +/** + * 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.vcloud.director.v1_5.compute.util; + +import static com.google.common.collect.Iterables.filter; + +import java.util.Set; + +import org.jclouds.cim.OSType; +import org.jclouds.compute.domain.CIMOperatingSystem; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.dmtf.CIMPredicates; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.vcloud.director.v1_5.domain.VApp; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection; +import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; +import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; +import org.jclouds.vcloud.director.v1_5.functions.SectionForVApp; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Iterables; +import com.google.inject.Inject; + +/** + * + * @author danikov + */ +public class VCloudComputeUtils { + + public static OperatingSystem toComputeOs(VApp vApp, OperatingSystem defaultOs) { + CIMOperatingSystem cimOs = toComputeOs(vApp); + return cimOs != null ? cimOs : defaultOs; + } + + public static CIMOperatingSystem toComputeOs(VApp vApp) { + // TODO we need to change the design so that it doesn't assume single-vms + return vApp.getChildren().getVms().size() > 0 ? toComputeOs(Iterables.get(vApp.getChildren().getVms(), 0)) : null; + } + + @Inject private static SectionForVApp findOperatingSystemSectionForVApp; + + public static CIMOperatingSystem toComputeOs(Vm vm) { + return toComputeOs(findOperatingSystemSectionForVApp.apply(vm)); + } + + public static CIMOperatingSystem toComputeOs(OperatingSystemSection os) { + return new CIMOperatingSystem(OSType.fromValue(os.getId()), "", null, os.getDescription()); + } + + public static String getVirtualSystemIdentifierOfFirstVMIn(VApp vApp) { + return vApp.getChildren().getVms().size() > 0 ? + getVirtualSystemIdentifierOf(Iterables.get(vApp.getChildren().getVms(), 0)) : null; + } + + @Inject private static SectionForVApp findVirtualHardwareSectionForVApp; + + public static String getVirtualSystemIdentifierOf(Vm vm) { + VirtualHardwareSection virtualHardwareSection = findVirtualHardwareSectionForVApp.apply(vm); + if (virtualHardwareSection != null && virtualHardwareSection != null) + return virtualHardwareSection.getSystem().getVirtualSystemIdentifier(); + return null; + } + + public static LoginCredentials getCredentialsFrom(VApp vApp) { + return vApp.getChildren().getVms().size() > 0 ? + getCredentialsFrom(Iterables.get(vApp.getChildren().getVms(), 0)) : null; + } + + public static LoginCredentials getCredentialsFrom(VAppTemplate vApp) { + return vApp.getChildren().size() > 0 ? getCredentialsFrom(Iterables.get(vApp.getChildren(), 0)) : null; + } + + @Inject private static SectionForVApp findGuestCustomizationSectionForVApp; + + public static LoginCredentials getCredentialsFrom(Vm vm) { + LoginCredentials.Builder builder = LoginCredentials.builder(); + GuestCustomizationSection guestCustomizationSection = findGuestCustomizationSectionForVApp.apply(vm); + if (guestCustomizationSection != null) + builder.password(guestCustomizationSection.getAdminPassword()); + return builder.build(); + } + + @Inject private static SectionForVApp findNetworkConnectionSectionForVApp; + + public static Set getIpsFromVApp(VApp vApp) { + // TODO make this work with composite vApps + if (vApp.getChildren().getVms().size() == 0) + return ImmutableSet.of(); + Builder ips = ImmutableSet.builder(); + Vm vm = Iterables.get(vApp.getChildren().getVms(), 0); + // TODO: figure out how to differentiate public from private ip addresses + // assumption is that we'll do this from the network object, which may + // have + // enough data to tell whether or not it is a public network without + // string + // parsing. At worst, we could have properties set per cloud provider to + // declare the networks which are public, then check against these in + // networkconnection.getNetwork + NetworkConnectionSection networkConnectionSection = findNetworkConnectionSectionForVApp.apply(vApp); + if (networkConnectionSection != null) { + for (NetworkConnection connection : networkConnectionSection.getNetworkConnections()) { + if (connection.getIpAddress() != null) + ips.add(connection.getIpAddress()); + if (connection.getExternalIpAddress() != null) + ips.add(connection.getExternalIpAddress()); + } + } else { + for (ResourceAllocationSettingData net : filter(findVirtualHardwareSectionForVApp.apply(vApp).getItems(), + CIMPredicates.resourceTypeIn(ResourceType.ETHERNET_ADAPTER))) { + // FIXME: not yet implemented +// if (net instanceof VCloudNetworkAdapter) { +// VCloudNetworkAdapter vNet = VCloudNetworkAdapter.class.cast(net); +// if (vNet.getIpAddress() != null) +// ips.add(vNet.getIpAddress()); +// } + } + } + return ips.build(); + } +} diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java index d8af02ac6e..650736396b 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java @@ -43,6 +43,7 @@ import org.jclouds.rest.internal.RestContextImpl; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminAsyncClient; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminClient; import org.jclouds.vcloud.director.v1_5.annotations.Login; +import org.jclouds.vcloud.director.v1_5.compute.util.VCloudComputeUtils; import org.jclouds.vcloud.director.v1_5.domain.Session; import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken; import org.jclouds.vcloud.director.v1_5.features.CatalogAsyncClient; @@ -173,6 +174,8 @@ public class VCloudDirectorRestClientModule extends RestClientModule implements Function { + + private final Class sectionType; + + @Inject + SectionForVApp(Class sectionType) { + this.sectionType = sectionType; + } + + @SuppressWarnings("unchecked") + @Override + public S apply(AbstractVAppType from) { + for (SectionType section : from.getSections()) { + if (sectionType.isAssignableFrom(section.getClass())) { + return (S)section; + } + } + return null; + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java index 2efcd27ee4..e33051b65f 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java @@ -18,8 +18,6 @@ */ package org.jclouds.vcloud.director.v1_5.functions; -import java.util.Set; - import javax.inject.Inject; import javax.inject.Singleton; @@ -27,7 +25,6 @@ import org.jclouds.dmtf.ovf.SectionType; import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; import com.google.common.base.Function; -import com.google.common.collect.Sets; /** * @author danikov @@ -45,7 +42,6 @@ public class SectionForVAppTemplate implements Function sections = Sets.newLinkedHashSet(); for (SectionType section : from.getSections()) { if (sectionType.isAssignableFrom(section.getClass())) { return (S)section;