From 00387336461fa00862b19270f5123aa03112542d Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Wed, 25 Aug 2010 00:12:33 -0700 Subject: [PATCH] Issue 280: added operating system and started parsing ip addresses from api --- .../domain/internal/TemplateBuilderImpl.java | 4 +- .../src/main/java/org/jclouds/util/Utils.java | 2 +- ...udDirectorComputeServiceContextModule.java | 22 +-- ...efaultLoginCredentialsFromBlueLockFAQ.java | 5 +- ...kVCloudDirectorComputeServiceLiveTest.java | 5 +- .../compute/functions/GetExtraFromVApp.java | 51 +++--- .../vcloud/compute/functions/ImagesInOrg.java | 3 +- .../vcloud/compute/functions/ImagesInVDC.java | 58 ------- .../internal/VCloudComputeClientImpl.java | 28 +++- .../VCloudGetNodeMetadataStrategy.java | 12 +- .../vcloud/domain/OperatingSystem.java | 149 ++++++++++++++++++ .../java/org/jclouds/vcloud/domain/Vm.java | 8 + .../vcloud/domain/internal/VmImpl.java | 21 ++- .../VAppTemplatesForCatalogItems.java | 27 +++- .../VAppTemplatesForResourceEntities.java | 84 ---------- .../vcloud/xml/OperatingSystemHandler.java | 87 ++++++++++ .../vcloud/xml/VirtualHardwareHandler.java | 8 +- .../org/jclouds/vcloud/xml/VmHandler.java | 21 ++- .../xml/OperatingSystemHandlerTest.java | 63 ++++++++ .../org/jclouds/vcloud/xml/VmHandlerTest.java | 1 + vcloud/core/src/test/resources/os.xml | 11 ++ 21 files changed, 461 insertions(+), 209 deletions(-) delete mode 100644 vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInVDC.java create mode 100644 vcloud/core/src/main/java/org/jclouds/vcloud/domain/OperatingSystem.java delete mode 100644 vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForResourceEntities.java create mode 100644 vcloud/core/src/main/java/org/jclouds/vcloud/xml/OperatingSystemHandler.java create mode 100644 vcloud/core/src/test/java/org/jclouds/vcloud/xml/OperatingSystemHandlerTest.java create mode 100644 vcloud/core/src/test/resources/os.xml diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java index 06d1b8d7c5..66f7b39867 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java @@ -669,7 +669,9 @@ public class TemplateBuilderImpl implements TemplateBuilder { predicates.add(imageDescriptionPredicate); } - Predicate imagePredicate = predicates.size() == 1 ? Iterables.get(predicates, 0) : and(predicates); + // looks verbose, but explicit type needed for this to compile properly + Predicate imagePredicate = predicates.size() == 1 ? Iterables.> get(predicates, 0) + : Predicates. and(predicates); return imagePredicate; } diff --git a/core/src/main/java/org/jclouds/util/Utils.java b/core/src/main/java/org/jclouds/util/Utils.java index a56a27bdca..8c4d3527cf 100644 --- a/core/src/main/java/org/jclouds/util/Utils.java +++ b/core/src/main/java/org/jclouds/util/Utils.java @@ -149,7 +149,7 @@ public class Utils { return ImmutableSet. of(in); } - public static Object propagateOrNull(Exception from) { + public static T propagateOrNull(Exception from) { propagate(from); assert false : "exception should have propogated"; return null; diff --git a/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/config/BlueLockVCloudDirectorComputeServiceContextModule.java b/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/config/BlueLockVCloudDirectorComputeServiceContextModule.java index 0a2b234ec0..f3f033120f 100644 --- a/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/config/BlueLockVCloudDirectorComputeServiceContextModule.java +++ b/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/config/BlueLockVCloudDirectorComputeServiceContextModule.java @@ -19,24 +19,14 @@ package org.jclouds.vcloud.bluelock.compute.config; -import java.util.Set; - -import org.jclouds.compute.domain.Size; -import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; +import org.jclouds.compute.ComputeServiceContext; import org.jclouds.vcloud.bluelock.compute.BlueLockVCloudDirectorComputeClient; -import org.jclouds.vcloud.bluelock.compute.config.suppliers.ParseSizeFromImageSupplier; -import org.jclouds.vcloud.bluelock.compute.functions.BlueLockVCloudImageForVAppTemplate; -import org.jclouds.vcloud.bluelock.compute.strategy.DefaultLoginCredentialsFromBlueLockFAQ; import org.jclouds.vcloud.compute.VCloudComputeClient; import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule; -import org.jclouds.vcloud.compute.functions.ImageForVCloudExpressVAppTemplate; - -import com.google.common.base.Supplier; -import com.google.inject.Injector; /** - * Configures the {@link BlueLockVCloudComputeServiceContext}; requires - * {@link BlueLockVCloudComputeClient} bound. + * Configures the {@link ComputeServiceContext}; requires + * {@link BlueLockVCloudDirectorComputeClient} bound. * * @author Adrian Cole */ @@ -45,13 +35,7 @@ public class BlueLockVCloudDirectorComputeServiceContextModule extends VCloudCom @Override protected void configure() { super.configure(); - bind(ImageForVCloudExpressVAppTemplate.class).to(BlueLockVCloudImageForVAppTemplate.class); bind(VCloudComputeClient.class).to(BlueLockVCloudDirectorComputeClient.class); - bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(DefaultLoginCredentialsFromBlueLockFAQ.class); } - @Override - protected Supplier> getSourceSizeSupplier(Injector injector) { - return injector.getInstance(ParseSizeFromImageSupplier.class); - } } diff --git a/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/strategy/DefaultLoginCredentialsFromBlueLockFAQ.java b/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/strategy/DefaultLoginCredentialsFromBlueLockFAQ.java index 66d27947b9..4c60e0f867 100644 --- a/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/strategy/DefaultLoginCredentialsFromBlueLockFAQ.java +++ b/vcloud/bluelock/src/main/java/org/jclouds/vcloud/bluelock/compute/strategy/DefaultLoginCredentialsFromBlueLockFAQ.java @@ -36,14 +36,13 @@ import org.jclouds.vcloud.domain.VCloudExpressVAppTemplate; * */ @Singleton -public class DefaultLoginCredentialsFromBlueLockFAQ implements - PopulateDefaultLoginCredentialsForImageStrategy { +public class DefaultLoginCredentialsFromBlueLockFAQ implements PopulateDefaultLoginCredentialsForImageStrategy { @Override public Credentials execute(Object resourceToAuthenticate) { checkNotNull(resourceToAuthenticate); checkArgument(resourceToAuthenticate instanceof VCloudExpressVAppTemplate, - "Resource must be an VAppTemplate (for Terremark)"); + "Resource must be an VCloudExpressVAppTemplate (for Bluelock vCloud Express)"); VCloudExpressVAppTemplate template = (VCloudExpressVAppTemplate) resourceToAuthenticate; if (template.getDescription().indexOf("Windows") >= 0) { return new Credentials("expressuser", "ExpressPassword#1"); diff --git a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java index aba4db23fd..baee4d9c5f 100644 --- a/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java +++ b/vcloud/bluelock/src/test/java/org/jclouds/vcloud/bluelock/compute/BlueLockVCloudDirectorComputeServiceLiveTest.java @@ -26,6 +26,7 @@ import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.predicates.OperatingSystemPredicates; import org.jclouds.vcloud.compute.VCloudComputeServiceLiveTest; import org.testng.annotations.Test; @@ -53,8 +54,10 @@ public class BlueLockVCloudDirectorComputeServiceLiveTest extends VCloudComputeS @Test public void testTemplateBuilder() { Template defaultTemplate = client.templateBuilder().build(); - assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true); + assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), false); + assert OperatingSystemPredicates.supportsApt().apply(defaultTemplate.getImage().getOperatingSystem()); assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU); + assertEquals(defaultTemplate.getImage().getOperatingSystem().getDescription(), "Ubuntu Template"); assert defaultTemplate.getLocation().getId() != null : defaultTemplate.getLocation(); assertEquals(defaultTemplate.getSize().getCores(), 1.0d); } diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/GetExtraFromVApp.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/GetExtraFromVApp.java index 2fcd398eda..8728b8ca67 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/GetExtraFromVApp.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/GetExtraFromVApp.java @@ -19,7 +19,10 @@ package org.jclouds.vcloud.compute.functions; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Maps.newHashMap; +import static org.jclouds.vcloud.predicates.VCloudPredicates.resourceType; import java.util.Map; @@ -28,9 +31,15 @@ import javax.inject.Singleton; import org.jclouds.logging.Logger; import org.jclouds.vcloud.compute.internal.VCloudExpressComputeClientImpl; +import org.jclouds.vcloud.domain.ResourceAllocation; +import org.jclouds.vcloud.domain.ResourceType; import org.jclouds.vcloud.domain.VApp; +import org.jclouds.vcloud.domain.VCloudHardDisk; +import org.jclouds.vcloud.domain.VCloudNetworkAdapter; +import org.jclouds.vcloud.domain.Vm; import com.google.common.base.Function; +import com.google.common.collect.Iterables; /** * Configures the {@link VCloudComputeServiceContext}; requires @@ -47,24 +56,30 @@ public class GetExtraFromVApp implements Function> { public Map apply(VApp vApp) { Map extra = newHashMap(); try { - // TODO - // extra.put("memory/mb", find(vApp.getResourceAllocations(), - // resourceType(ResourceType.MEMORY)) - // .getVirtualQuantity() - // + ""); - // extra.put("processor/count", find(vApp.getResourceAllocations(), - // resourceType(ResourceType.PROCESSOR)) - // .getVirtualQuantity() - // + ""); - // for (ResourceAllocation disk : filter(vApp.getResourceAllocations(), - // resourceType(ResourceType.DISK_DRIVE))) { - // extra.put(String.format("disk_drive/%s/kb", disk.getAddressOnParent()), - // disk.getVirtualQuantity() + ""); - // } - // - // for (Entry net : vApp.getNetworkToAddresses().entries()) { - // extra.put(String.format("network/%s/ip", net.getKey()), net.getValue()); - // } + // TODO make this work with composite vApps + Vm vm = Iterables.get(vApp.getChildren(), 0); + extra.put("memory/mb", find(vm.getHardware().getResourceAllocations(), resourceType(ResourceType.MEMORY)) + .getVirtualQuantity() + + ""); + extra.put("processor/count", find(vm.getHardware().getResourceAllocations(), + resourceType(ResourceType.PROCESSOR)).getVirtualQuantity() + + ""); + for (ResourceAllocation disk : filter(vm.getHardware().getResourceAllocations(), + resourceType(ResourceType.DISK_DRIVE))) { + if (disk instanceof VCloudHardDisk) { + VCloudHardDisk vDisk = VCloudHardDisk.class.cast(disk); + extra.put(String.format("disk_drive/%s/kb", disk.getAddressOnParent()), vDisk.getCapacity() + ""); + } else { + extra.put(String.format("disk_drive/%s/kb", disk.getAddressOnParent()), disk.getVirtualQuantity() + ""); + } + } + for (ResourceAllocation net : filter(vm.getHardware().getResourceAllocations(), + resourceType(ResourceType.ETHERNET_ADAPTER))) { + if (net instanceof VCloudNetworkAdapter) { + VCloudNetworkAdapter vNet = VCloudNetworkAdapter.class.cast(net); + extra.put(String.format("network/%s/ip", net.getAddressOnParent()), vNet.getIpAddress()); + } + } } catch (Exception e) { logger.error(e, "error getting extra data for vApp: %s", vApp); } diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInOrg.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInOrg.java index 82afba6ffc..b69a010237 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInOrg.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInOrg.java @@ -30,6 +30,7 @@ import org.jclouds.vcloud.domain.VAppTemplate; import org.jclouds.vcloud.functions.AllCatalogItemsInOrg; import com.google.common.base.Function; +import com.google.common.base.Predicates; import com.google.common.collect.Iterables; /** @@ -55,7 +56,7 @@ public class ImagesInOrg implements Function> { public Iterable apply(Org from) { Iterable catalogs = allCatalogItemsInOrg.apply(from); Iterable vAppTemplates = vAppTemplatesForCatalogItems.apply(catalogs); - return Iterables.transform(vAppTemplates, imageForVAppTemplateProvider.get().withParent(from)); + return Iterables.transform(Iterables.filter(vAppTemplates, Predicates.notNull()), imageForVAppTemplateProvider.get().withParent(from)); } } \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInVDC.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInVDC.java deleted file mode 100644 index 166bd69774..0000000000 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/functions/ImagesInVDC.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * Licensed 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.compute.functions; - -import static com.google.common.base.Preconditions.checkNotNull; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import org.jclouds.compute.domain.Image; -import org.jclouds.vcloud.domain.VAppTemplate; -import org.jclouds.vcloud.domain.VDC; -import org.jclouds.vcloud.functions.VAppTemplatesForResourceEntities; - -import com.google.common.base.Function; -import com.google.common.collect.Iterables; - -/** - * @author Adrian Cole - */ -@Singleton -public class ImagesInVDC implements Function> { - private final VAppTemplatesForResourceEntities vAppTemplatesForResourceEntities; - private final ImageForVAppTemplate imageForVAppTemplateProvider; - - @Inject - public ImagesInVDC(VAppTemplatesForResourceEntities vAppTemplatesForResourceEntities, - ImageForVAppTemplate imageForVAppTemplateProvider) { - this.vAppTemplatesForResourceEntities = checkNotNull(vAppTemplatesForResourceEntities, - "vAppTemplatesForResourceEntities"); - this.imageForVAppTemplateProvider = checkNotNull(imageForVAppTemplateProvider, "imageForVAppTemplateProvider"); - } - - @Override - public Iterable apply(VDC from) { - Iterable vAppTemplates = vAppTemplatesForResourceEntities.apply(checkNotNull(from, "vdc") - .getResourceEntities().values()); - return Iterables.transform(vAppTemplates, imageForVAppTemplateProvider.withParent(from)); - } - -} \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/internal/VCloudComputeClientImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/internal/VCloudComputeClientImpl.java index c31800f190..6eb72f687c 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/internal/VCloudComputeClientImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/internal/VCloudComputeClientImpl.java @@ -20,6 +20,8 @@ package org.jclouds.vcloud.compute.internal; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.filter; +import static org.jclouds.vcloud.predicates.VCloudPredicates.resourceType; import java.net.URI; import java.util.Map; @@ -31,16 +33,22 @@ import javax.inject.Singleton; import org.jclouds.compute.domain.NodeState; import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.compute.VCloudComputeClient; +import org.jclouds.vcloud.domain.ResourceAllocation; +import org.jclouds.vcloud.domain.ResourceType; import org.jclouds.vcloud.domain.Status; import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VAppTemplate; +import org.jclouds.vcloud.domain.VCloudNetworkAdapter; import org.jclouds.vcloud.domain.VDC; +import org.jclouds.vcloud.domain.Vm; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.inject.Inject; +import com.google.inject.internal.util.Sets; /** * @author Adrian Cole @@ -67,8 +75,8 @@ public class VCloudComputeClientImpl extends CommonVCloudComputeClientImpl> deploying vApp(%s)", vAppResponse.getName()); @@ -91,10 +99,18 @@ public class VCloudComputeClientImpl extends CommonVCloudComputeClientImpl getPublicAddresses(URI id) { - return ImmutableSet.of(); - // TODO - // VApp vApp = refreshVApp(id); - // return Sets.newHashSet(vApp.getNetworkToAddresses().values()); + Set ips = Sets.newLinkedHashSet(); + VApp vApp = refreshVApp(id); + // TODO make this work with composite vApps + Vm vm = Iterables.get(vApp.getChildren(), 0); + for (ResourceAllocation net : filter(vm.getHardware().getResourceAllocations(), + resourceType(ResourceType.ETHERNET_ADAPTER))) { + if (net instanceof VCloudNetworkAdapter) { + VCloudNetworkAdapter vNet = VCloudNetworkAdapter.class.cast(net); + ips.add(vNet.getIpAddress()); + } + } + return ips; } @Override diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudGetNodeMetadataStrategy.java b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudGetNodeMetadataStrategy.java index cf4d012e6c..e58848876b 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudGetNodeMetadataStrategy.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudGetNodeMetadataStrategy.java @@ -47,9 +47,11 @@ import org.jclouds.vcloud.compute.functions.FindLocationForResource; import org.jclouds.vcloud.compute.functions.GetExtraFromVApp; import org.jclouds.vcloud.domain.Status; import org.jclouds.vcloud.domain.VApp; +import org.jclouds.vcloud.domain.Vm; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; /** * @author Adrian Cole @@ -92,11 +94,11 @@ public class VCloudGetNodeMetadataStrategy implements GetNodeMetadataStrategy { } private OperatingSystem getOperatingSystemForVAppOrDefaultTo(VApp vApp, OperatingSystem operatingSystem) { - // TODO - return new CIMOperatingSystem(CIMOperatingSystem.OSType.UBUNTU_64, null, null, vApp.getDescription()); - // return vApp.getOsType() != null ? new - // CIMOperatingSystem(CIMOperatingSystem.OSType.fromValue(vApp.getOsType()), - // null, null, vApp.getOperatingSystemDescription()) : operatingSystem; + // TODO we need to change the design so that it doesn't assume single-vms + Vm vm = Iterables.get(vApp.getChildren(), 0); + return vm.getOperatingSystem() != null && vm.getOperatingSystem().getId() != null ? new CIMOperatingSystem( + CIMOperatingSystem.OSType.fromValue(vm.getOperatingSystem().getId()), null, null, vm + .getOperatingSystem().getDescription()) : operatingSystem; } } \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/OperatingSystem.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/OperatingSystem.java new file mode 100644 index 0000000000..d797561aff --- /dev/null +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/OperatingSystem.java @@ -0,0 +1,149 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed 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.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; + +import javax.annotation.Nullable; + +import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl; + +/** + * A description of the operating system supported by a virtual machine. + */ +public class OperatingSystem extends ReferenceTypeImpl { + + @Nullable + private final Integer id; + @Nullable + private final String info; + @Nullable + private final String vmwOsType; + @Nullable + private final String description; + private final ReferenceType edit; + + public OperatingSystem(@Nullable String name, String type, URI href, @Nullable Integer id, @Nullable String info, + @Nullable String vmwOsType, @Nullable String description, ReferenceType edit) { + super(name, type, href); + this.id = id; + this.info = info; + this.vmwOsType = vmwOsType; + this.description = description; + this.edit = checkNotNull(edit, "edit"); + } + + /** + * + * @return ovf id + */ + public Integer getId() { + return id; + } + + /** + * + * @return ovf info + */ + public String getInfo() { + return info; + } + + /** + * + * @return VMware osType, if running on VMware + */ + public String getVmwOsType() { + return vmwOsType; + } + + /** + * + * @return description or null + */ + public String getDescription() { + return description; + } + + /** + * + * @return edit link + */ + public ReferenceType getEdit() { + return edit; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((edit == null) ? 0 : edit.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((info == null) ? 0 : info.hashCode()); + result = prime * result + ((vmwOsType == null) ? 0 : vmwOsType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + OperatingSystem other = (OperatingSystem) obj; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (edit == null) { + if (other.edit != null) + return false; + } else if (!edit.equals(other.edit)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (info == null) { + if (other.info != null) + return false; + } else if (!info.equals(other.info)) + return false; + if (vmwOsType == null) { + if (other.vmwOsType != null) + return false; + } else if (!vmwOsType.equals(other.vmwOsType)) + return false; + return true; + } + + @Override + public String toString() { + return "[href=" + getHref() + ", name=" + getName() + ", type=" + getType() + ", id=" + getId() + ", vmwOsType=" + + getVmwOsType() + ", description=" + getDescription() + "]"; + } +} \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Vm.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Vm.java index eed9cba6e9..cd58ada04a 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Vm.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/Vm.java @@ -75,6 +75,14 @@ public interface Vm extends ReferenceType { */ @Nullable VirtualHardware getHardware(); + + /** + * @return operating system on this VM, or null, if part of a vApp template + * + * @since vcloud api 1.0 + */ + @Nullable + OperatingSystem getOperatingSystem(); /** * read-only identifier created on import diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/VmImpl.java b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/VmImpl.java index c4a2872b40..1c91f86271 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/VmImpl.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/domain/internal/VmImpl.java @@ -26,6 +26,7 @@ import java.util.List; import javax.annotation.Nullable; +import org.jclouds.vcloud.domain.OperatingSystem; import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.Status; import org.jclouds.vcloud.domain.Task; @@ -52,16 +53,18 @@ public class VmImpl extends ReferenceTypeImpl implements Vm { @Nullable private final VirtualHardware hardware; private final String vAppScopedLocalId; + private final OperatingSystem os; public VmImpl(String name, String type, URI id, @Nullable Status status, ReferenceType vApp, @Nullable String description, Iterable tasks, @Nullable VirtualHardware hardware, - @Nullable String vAppScopedLocalId) { + @Nullable OperatingSystem os, @Nullable String vAppScopedLocalId) { super(name, type, id); this.status = status; this.vApp = vApp;// TODO: once <1.0 is killed check not null this.description = description; Iterables.addAll(this.tasks, checkNotNull(tasks, "tasks")); this.hardware = hardware; + this.os = os; this.vAppScopedLocalId = vAppScopedLocalId; } @@ -106,6 +109,14 @@ public class VmImpl extends ReferenceTypeImpl implements Vm { return hardware; } + /** + * {@inheritDoc} + */ + @Override + public OperatingSystem getOperatingSystem() { + return os; + } + /** * {@inheritDoc} */ @@ -120,6 +131,7 @@ public class VmImpl extends ReferenceTypeImpl implements Vm { int result = super.hashCode(); result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((hardware == null) ? 0 : hardware.hashCode()); + result = prime * result + ((os == null) ? 0 : os.hashCode()); result = prime * result + ((status == null) ? 0 : status.hashCode()); result = prime * result + ((tasks == null) ? 0 : tasks.hashCode()); result = prime * result + ((vApp == null) ? 0 : vApp.hashCode()); @@ -146,6 +158,11 @@ public class VmImpl extends ReferenceTypeImpl implements Vm { return false; } else if (!hardware.equals(other.hardware)) return false; + if (os == null) { + if (other.os != null) + return false; + } else if (!os.equals(other.os)) + return false; if (status == null) { if (other.status != null) return false; @@ -172,7 +189,7 @@ public class VmImpl extends ReferenceTypeImpl implements Vm { @Override public String toString() { return "[href=" + getHref() + ", name=" + getName() + ", type=" + getType() + ", description=" + description - + ", status=" + status + ", tasks=" + tasks + ", vApp=" + vApp + ", hardware=" + hardware + + ", status=" + status + ", tasks=" + tasks + ", vApp=" + vApp + ", hardware=" + hardware + ", os=" + os + ", vAppScopedLocalId=" + vAppScopedLocalId + "]"; } diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForCatalogItems.java b/vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForCatalogItems.java index da0d624ab3..54ea703f13 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForCatalogItems.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForCatalogItems.java @@ -21,6 +21,7 @@ package org.jclouds.vcloud.functions; import static com.google.common.collect.Iterables.filter; import static org.jclouds.concurrent.FutureIterables.transformParallel; +import static org.jclouds.util.Utils.propagateOrNull; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -32,7 +33,10 @@ import javax.inject.Singleton; import org.jclouds.Constants; import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.concurrent.ExceptionParsingListenableFuture; +import org.jclouds.concurrent.Futures; import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; import org.jclouds.vcloud.CommonVCloudAsyncClient; import org.jclouds.vcloud.VCloudAsyncClient; import org.jclouds.vcloud.VCloudMediaType; @@ -47,18 +51,32 @@ import com.google.common.base.Predicate; */ @Singleton public class VAppTemplatesForCatalogItems implements - Function, Iterable> { + Function, Iterable> { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) public Logger logger = Logger.NULL; private final CommonVCloudAsyncClient aclient; private final ExecutorService executor; + private final ReturnNullOnAuthorizationException returnNullOnAuthorizationException; + + @Singleton + static class ReturnNullOnAuthorizationException implements Function { + + public VAppTemplate apply(Exception from) { + if (from instanceof AuthorizationException) { + return null; + } + return propagateOrNull(from); + } + } @Inject VAppTemplatesForCatalogItems(CommonVCloudAsyncClient aclient, - @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { + @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, + ReturnNullOnAuthorizationException returnNullOnAuthorizationException) { this.aclient = aclient; this.executor = executor; + this.returnNullOnAuthorizationException = returnNullOnAuthorizationException; } @Override @@ -75,8 +93,9 @@ public class VAppTemplatesForCatalogItems implements @SuppressWarnings("unchecked") @Override public Future apply(CatalogItem from) { - return (Future) VCloudAsyncClient.class.cast(aclient).getVAppTemplate( - from.getEntity().getHref()); + return new ExceptionParsingListenableFuture(Futures.makeListenable( + (Future) VCloudAsyncClient.class.cast(aclient).getVAppTemplate( + from.getEntity().getHref()), executor), returnNullOnAuthorizationException); } }, executor, null, logger, "vappTemplates in"); diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForResourceEntities.java b/vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForResourceEntities.java deleted file mode 100644 index 534a7e0441..0000000000 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/functions/VAppTemplatesForResourceEntities.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * Licensed 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.functions; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Iterables.filter; -import static org.jclouds.concurrent.FutureIterables.transformParallel; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - -import javax.annotation.Resource; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.jclouds.Constants; -import org.jclouds.compute.reference.ComputeServiceConstants; -import org.jclouds.logging.Logger; -import org.jclouds.vcloud.VCloudAsyncClient; -import org.jclouds.vcloud.VCloudMediaType; -import org.jclouds.vcloud.domain.ReferenceType; -import org.jclouds.vcloud.domain.VAppTemplate; - -import com.google.common.base.Function; -import com.google.common.base.Predicate; - -/** - * @author Adrian Cole - */ -@Singleton -public class VAppTemplatesForResourceEntities implements - Function, Iterable> { - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - public Logger logger = Logger.NULL; - private final VCloudAsyncClient aclient; - private final ExecutorService executor; - - @Inject - VAppTemplatesForResourceEntities(VCloudAsyncClient aclient, - @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { - this.aclient = aclient; - this.executor = executor; - } - - @Override - public Iterable apply(Iterable from) { - return transformParallel(filter(checkNotNull(from, "named resources"), new Predicate() { - - @Override - public boolean apply(ReferenceType input) { - return input.getType().equals(VCloudMediaType.VAPPTEMPLATE_XML); - } - - }), new Function>() { - - @SuppressWarnings("unchecked") - @Override - public Future apply(ReferenceType from) { - return (Future) aclient.getVAppTemplate(from.getHref()); - } - - }, executor, null, logger, "vappTemplates in"); - } - -} \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/xml/OperatingSystemHandler.java b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/OperatingSystemHandler.java new file mode 100644 index 0000000000..5c3e10dafe --- /dev/null +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/OperatingSystemHandler.java @@ -0,0 +1,87 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed 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.xml; + +import static org.jclouds.vcloud.util.Utils.newReferenceType; + +import java.util.Map; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.vcloud.domain.OperatingSystem; +import org.jclouds.vcloud.domain.ReferenceType; +import org.jclouds.vcloud.util.Utils; +import org.xml.sax.Attributes; + +/** + * @author Adrian Cole + */ +public class OperatingSystemHandler extends ParseSax.HandlerWithResult { + private StringBuilder currentText = new StringBuilder(); + + protected ReferenceType os; + protected Integer id; + protected String info; + protected String vmwOsType; + protected String description; + protected ReferenceType edit; + + public OperatingSystem getResult() { + OperatingSystem system = new OperatingSystem(os.getName(), os.getType(), os.getHref(), id, info, vmwOsType, + description, edit); + os = null; + id = null; + info = null; + vmwOsType = null; + description = null; + edit = null; + return system; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attrs) { + Map attributes = Utils.cleanseAttributes(attrs); + if (qName.endsWith("Link")) { + this.edit = Utils.newReferenceType(attributes); + } else if (qName.endsWith("OperatingSystemSection")) { + if (attributes.containsKey("href") && attributes.get("href").endsWith("/")) { + String href = attributes.get("href"); + attributes.put("href", href.substring(0, href.lastIndexOf('/'))); + } + os = newReferenceType(attributes); + vmwOsType = attributes.get("osType"); + if (attributes.containsKey("id")) + this.id = Integer.parseInt(attributes.get("id")); + } + } + + @Override + public void endElement(String uri, String localName, String qName) { + if (qName.endsWith("Info")) { + this.info = currentText.toString().trim(); + } else if (qName.endsWith("Description")) { + this.description = currentText.toString().trim(); + } + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} \ No newline at end of file diff --git a/vcloud/core/src/main/java/org/jclouds/vcloud/xml/VirtualHardwareHandler.java b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/VirtualHardwareHandler.java index 6e0e4b0485..5ef40280e3 100644 --- a/vcloud/core/src/main/java/org/jclouds/vcloud/xml/VirtualHardwareHandler.java +++ b/vcloud/core/src/main/java/org/jclouds/vcloud/xml/VirtualHardwareHandler.java @@ -65,6 +65,10 @@ public class VirtualHardwareHandler extends ParseSax.HandlerWithResult attributes = cleanseAttributes(attrs); + if (attributes.containsKey("href") && attributes.get("href").endsWith("/")) { + String href = attributes.get("href"); + attributes.put("href", href.substring(0, href.lastIndexOf('/'))); + } if (qName.endsWith("System")) { inSystem = true; } else if (!inSystem && qName.endsWith("Item")) { @@ -75,10 +79,6 @@ public class VirtualHardwareHandler extends ParseSax.HandlerWithResult { protected final TaskHandler taskHandler; protected final VirtualHardwareHandler virtualHardwareHandler; + protected final OperatingSystemHandler operatingSystemHandler; @Inject - public VmHandler(TaskHandler taskHandler, VirtualHardwareHandler virtualHardwareHandler) { + public VmHandler(TaskHandler taskHandler, VirtualHardwareHandler virtualHardwareHandler, + OperatingSystemHandler operatingSystemHandler) { this.taskHandler = taskHandler; this.virtualHardwareHandler = virtualHardwareHandler; + this.operatingSystemHandler = operatingSystemHandler; } protected StringBuilder currentText = new StringBuilder(); @@ -61,13 +65,15 @@ public class VmHandler extends ParseSax.HandlerWithResult { protected String description; protected List tasks = Lists.newArrayList(); protected VirtualHardware hardware; + protected OperatingSystem os; protected String vAppScopedLocalId; private boolean inTasks; private boolean inHardware; + private boolean inOs; public Vm getResult() { - return new VmImpl(vm.getName(), vm.getType(), vm.getHref(), status, vdc, description, tasks, hardware, + return new VmImpl(vm.getName(), vm.getType(), vm.getHref(), status, vdc, description, tasks, hardware, os, vAppScopedLocalId); } @@ -76,11 +82,15 @@ public class VmHandler extends ParseSax.HandlerWithResult { Map attributes = cleanseAttributes(attrs); if (qName.endsWith("VirtualHardwareSection")) { inHardware = true; + } else if (qName.endsWith("OperatingSystemSection")) { + inOs = true; } else if (qName.endsWith("Tasks")) { inTasks = true; } if (inHardware) { virtualHardwareHandler.startElement(uri, localName, qName, attrs); + } else if (inOs) { + operatingSystemHandler.startElement(uri, localName, qName, attrs); } else if (inTasks) { taskHandler.startElement(uri, localName, qName, attrs); } else if (qName.equals("Vm")) { @@ -97,12 +107,17 @@ public class VmHandler extends ParseSax.HandlerWithResult { if (qName.endsWith("VirtualHardwareSection")) { inHardware = false; this.hardware = virtualHardwareHandler.getResult(); + } else if (qName.endsWith("OperatingSystemSection")) { + inOs = false; + os = operatingSystemHandler.getResult(); } else if (qName.endsWith("Tasks")) { inTasks = false; this.tasks.add(taskHandler.getResult()); } if (inHardware) { virtualHardwareHandler.endElement(uri, name, qName); + } else if (inOs) { + operatingSystemHandler.endElement(uri, name, qName); } else if (inTasks) { taskHandler.endElement(uri, name, qName); } else if (qName.equals("Description")) { @@ -118,6 +133,8 @@ public class VmHandler extends ParseSax.HandlerWithResult { taskHandler.characters(ch, start, length); if (inHardware) virtualHardwareHandler.characters(ch, start, length); + if (inOs) + operatingSystemHandler.characters(ch, start, length); currentText.append(ch, start, length); } diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/xml/OperatingSystemHandlerTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/xml/OperatingSystemHandlerTest.java new file mode 100644 index 0000000000..8a36f4f979 --- /dev/null +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/xml/OperatingSystemHandlerTest.java @@ -0,0 +1,63 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed 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.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; +import java.net.UnknownHostException; + +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.vcloud.domain.OperatingSystem; +import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code OperatingSystemHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "vcloud.OperatingSystemHandlerTest") +public class OperatingSystemHandlerTest extends BaseHandlerTest { + + public void testDefault() throws UnknownHostException { + InputStream is = getClass().getResourceAsStream("/os.xml"); + + OperatingSystem result = factory.create(injector.getInstance(OperatingSystemHandler.class)).parse(is); + + checkOs(result); + + } + + static void checkOs(OperatingSystem result) { + assertEquals(result.getHref(), URI + .create("https://vcenterprise.bluelock.com/api/v1.0/vApp/vm-2087535248/operatingSystemSection")); + assertEquals(result.getDescription(), "Red Hat Enterprise Linux 5 (64-bit)"); + assertEquals(result.getEdit(), new ReferenceTypeImpl(null, + "application/vnd.vmware.vcloud.operatingSystemSection+xml", + URI.create("https://vcenterprise.bluelock.com/api/v1.0/vApp/vm-2087535248/operatingSystemSection/"))); + assertEquals(result.getId(), new Integer(80)); + assertEquals(result.getVmwOsType(), "rhel5_64Guest"); + assertEquals(result.getName(), null); + assertEquals(result.getType(), "application/vnd.vmware.vcloud.operatingSystemSection+xml"); + assertEquals(result.getInfo(), "Specifies the operating system installed"); + } +} diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/xml/VmHandlerTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/xml/VmHandlerTest.java index 118ae84239..6d87c7e5f7 100644 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/xml/VmHandlerTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/xml/VmHandlerTest.java @@ -63,6 +63,7 @@ public class VmHandlerTest { assertEquals(result.getTasks(), ImmutableList.of()); assertEquals(result.getVAppScopedLocalId(), "10_rhel_template"); VirtualHardwareHandlerTest.checkHardware(result.getHardware()); + OperatingSystemHandlerTest.checkOs(result.getOperatingSystem()); } } diff --git a/vcloud/core/src/test/resources/os.xml b/vcloud/core/src/test/resources/os.xml new file mode 100644 index 0000000000..3196a272f6 --- /dev/null +++ b/vcloud/core/src/test/resources/os.xml @@ -0,0 +1,11 @@ + + Specifies the operating system installed + Red Hat Enterprise Linux 5 (64-bit) + + \ No newline at end of file