http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java new file mode 100644 index 0000000..73868fb --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java @@ -0,0 +1,497 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.compute.strategy; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.get; +import static org.jclouds.compute.util.ComputeServiceUtils.getCores; +import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue; +import static org.jclouds.util.Predicates2.retry; +import static org.jclouds.vcloud.compute.util.VCloudComputeUtils.getCredentialsFrom; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import org.jclouds.cim.ResourceAllocationSettingData; +import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.logging.Logger; +import org.jclouds.ovf.Network; +import org.jclouds.predicates.validators.DnsNameValidator; +import org.jclouds.rest.annotations.BuildVersion; +import org.jclouds.vcloud.TaskStillRunningException; +import org.jclouds.vcloud.VCloudApi; +import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; +import org.jclouds.vcloud.domain.*; +import org.jclouds.vcloud.domain.NetworkConnectionSection.Builder; +import org.jclouds.vcloud.domain.internal.VmImpl; +import org.jclouds.vcloud.domain.network.IpAddressAllocationMode; +import org.jclouds.vcloud.domain.network.NetworkConfig; +import org.jclouds.vcloud.domain.ovf.VCloudNetworkAdapter; +import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.base.Predicate; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import org.jclouds.vcloud.predicates.TaskSuccess; + +@Singleton +public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + protected final VCloudApi client; + protected final Predicate<URI> successTester; + protected final LoadingCache<URI, VAppTemplate> vAppTemplates; + protected final NetworkConfigurationForNetworkAndOptions networkConfigurationForNetworkAndOptions; + protected final String buildVersion; + + + @Inject + protected InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn(VCloudApi client, + Predicate<URI> successTester, LoadingCache<URI, VAppTemplate> vAppTemplates, NetworkConfigurationForNetworkAndOptions networkConfigurationForNetworkAndOptions, + @BuildVersion String buildVersion) { + this.client = client; + this.successTester = successTester; + this.vAppTemplates = vAppTemplates; + this.networkConfigurationForNetworkAndOptions = networkConfigurationForNetworkAndOptions; + this.buildVersion = buildVersion; + } + + /** + * per john ellis at bluelock, vCloud Director 1.5 is more strict than earlier versions. + * <p/> + * It appears to be 15 characters to match Windows' hostname limitation. Must be alphanumeric, at + * least one non-number character and hyphens and underscores are the only non-alpha character + * allowed. + */ + public static enum ComputerNameValidator { + INSTANCE; + + private DnsNameValidator validator; + + ComputerNameValidator() { + this.validator = new DnsNameValidator(3, 15); + } + + public void validate(@Nullable String t) throws IllegalArgumentException { + this.validator.validate(t); + } + + } + + public NodeAndInitialCredentials<VApp> createNodeWithGroupEncodedIntoName(String group, String name, Template template) { + // no sense waiting until failures occur later + ComputerNameValidator.INSTANCE.validate(name); + VApp vAppResponse = instantiateVAppFromTemplate(name, template); + waitForTask(vAppResponse.getTasks().get(0)); + logger.debug("<< instantiated VApp(%s)", vAppResponse.getName()); + + // vm data is available after instantiate completes + vAppResponse = client.getVAppApi().getVApp(vAppResponse.getHref()); + + // per above check, we know there is only a single VM + Vm vm = get(vAppResponse.getChildren(), 0); + + template.getOptions().userMetadata(ComputeServiceConstants.NODE_GROUP_KEY, group); + VCloudTemplateOptions vOptions = VCloudTemplateOptions.class.cast(template.getOptions()); + + // note we cannot do tasks in parallel or VCD will throw "is busy" errors + + // note we must do this before any other customizations as there is a dependency on + // valid naming conventions before you can perform commands such as updateCPUCount + logger.trace(">> updating customization vm(%s) name->(%s)", vm.getName(), name); + waitForTask(updateVmWithNameAndCustomizationScript(vm, name, vOptions.getCustomizationScript())); + logger.trace("<< updated customization vm(%s)", name); + + ensureVmHasDesiredNetworkConnectionSettings(vAppResponse, vOptions); + + int cpuCount = (int) getCores(template.getHardware()); + logger.trace(">> updating cpuCount(%d) vm(%s)", cpuCount, vm.getName()); + waitForTask(updateCPUCountOfVm(vm, cpuCount)); + logger.trace("<< updated cpuCount vm(%s)", vm.getName()); + int memoryMB = template.getHardware().getRam(); + logger.trace(">> updating memoryMB(%d) vm(%s)", memoryMB, vm.getName()); + waitForTask(updateMemoryMBOfVm(vm, memoryMB)); + logger.trace("<< updated memoryMB vm(%s)", vm.getName()); + logger.trace(">> deploying vApp(%s)", vAppResponse.getName()); + waitForTask(client.getVAppApi().deployVApp(vAppResponse.getHref())); + logger.trace("<< deployed vApp(%s)", vAppResponse.getName()); + + // only after deploy is the password valid + vAppResponse = client.getVAppApi().getVApp(vAppResponse.getHref()); + + logger.trace(">> powering on vApp(%s)", vAppResponse.getName()); + client.getVAppApi().powerOnVApp(vAppResponse.getHref()); + + return new NodeAndInitialCredentials<VApp>(vAppResponse, vAppResponse.getHref().toASCIIString(), + getCredentialsFrom(vAppResponse)); + + } + + @VisibleForTesting + protected VApp instantiateVAppFromTemplate(String name, Template template) { + VCloudTemplateOptions vOptions = VCloudTemplateOptions.class.cast(template.getOptions()); + + URI templateId = URI.create(template.getImage().getId()); + + VAppTemplate vAppTemplate = vAppTemplates.getUnchecked(templateId); + + if (vAppTemplate.getChildren().size() > 1) + throw new UnsupportedOperationException("we currently do not support multiple vms in a vAppTemplate " + + vAppTemplate); + + VmImpl vmTemplate = VmImpl.class.cast(vAppTemplate.getChildren().iterator().next()); + + String description = VCloudTemplateOptions.class.cast(template.getOptions()).getDescription(); + if (description == null) { + Map<String, String> md = metadataAndTagsAsCommaDelimitedValue(template.getOptions()); + description = Joiner.on('\n').withKeyValueSeparator("=").join(md); + } + + InstantiateVAppTemplateOptions options = InstantiateVAppTemplateOptions.Builder.description(description); + + /* + * Match up networks in the vApp template with the ones in the options we got passed in, so that + * the right ones can be wired together. + * Note that in the end the order of the network interfaces is what's important, not the names. The names + * might not match up. In the worst case, maybe someone called their vApp networks A and B, but really wants + * them cross-connected, i.e. wired up to B and A respectively. + * The only potential issue here is that the networks in the vOptions are stored as a Set, which makes little + * sense. While the API is what it is, we need to rely on people higher up using sensible underlying + * datastructures (that conform to the set interface), which preserve their order. + */ + + int vmTemplateNumNetworks = vmTemplate.getNetworkConnectionSection().getConnections().size(); + + /* + * Backwards-compatibility hack: we might get passed in a parent network URI and an empty vOptions.networks list. + * In that case, move the parent network URI into the vOptions.networks list, and remove the parent URI. + */ + if (vOptions.getNetworks().size() == 0 && vmTemplateNumNetworks == 1 && vOptions.getParentNetwork() != null) { + ArrayList<String> netlist = new ArrayList<String>(); + netlist.add(vOptions.getParentNetwork().toASCIIString()); + vOptions.networks(netlist); + vOptions.parentNetwork(null); + } + + URI[] vOptionsNetworkIdList = new URI[vOptions.getNetworks().size()]; + NetworkConnection[] vAppTemplateNetworkList = + new NetworkConnection[vmTemplateNumNetworks]; + + //hopefully this preserves the original order, assuming the original underlying datastructure was ordered. + int i = 0; + for (String network: vOptions.getNetworks()) { + try { + vOptionsNetworkIdList[i] = new URI(network); + } catch (URISyntaxException e) { + logger.error(e, "Failed to convert href '" + network + "' to URI. We expect a href to a network to be " + + "passed in, not a name for example."); + return null; + } + i++; + } + + //iterate over the NetworkConnectionSection, and put them in order of their connection indices + // into the vAppTemplateNetworkList. + for (NetworkConnection netCon: vmTemplate.getNetworkConnectionSection().getConnections()) { + vAppTemplateNetworkList[netCon.getNetworkConnectionIndex()] = netCon; + } + + for (i = 0; i < vOptionsNetworkIdList.length; i++) { + URI parentNetwork = vOptionsNetworkIdList[i]; + NetworkConnection networkConnectionParams = vAppTemplateNetworkList.length > i ? vAppTemplateNetworkList[i] : null; + //hook 'em up. + + //use network name from vAppTemplate if possible + String networkName; + if (networkConnectionParams != null) { + networkName = networkConnectionParams.getNetwork(); + } else { + networkName = "jclouds-net-" + String.valueOf(i); + } + + Network n = new Network(networkName, null); // ignore description, not needed here. + VCloudTemplateOptions networkTemplateOptions = vOptions.clone(); //we'll modify bits here + networkTemplateOptions.parentNetwork(parentNetwork); + + NetworkConfig config = networkConfigurationForNetworkAndOptions.apply(n, networkTemplateOptions); + // note that in VCD 1.5, the network name after instantiation will be the same as the parent + options.addNetworkConfig(config); + logger.debug("Connecting vApp network " + n.getName() + " to org network " + parentNetwork + "."); + } + + // TODO make disk size specifiable + // disk((long) ((template.getHardware().getVolumes().get(0).getSize()) * + // 1024 * 1024l)); + + + + options.deploy(false); + options.powerOn(false); + + URI VDC = URI.create(template.getLocation().getId()); + + logger.debug(">> instantiating vApp vDC(%s) template(%s) name(%s) options(%s) ", VDC, templateId, name, options); + + VApp vAppResponse = client.getVAppTemplateApi().createVAppInVDCByInstantiatingTemplate(name, VDC, templateId, + options); + return vAppResponse; + } + + // TODO: filtering on "none" is a hack until we can filter on + // vAppTemplate.getNetworkConfigSection().getNetworkConfigs() where + // name = getChildren().NetworkConnectionSection.connection where ipallocationmode == none + static Predicate<Network> networkWithNoIpAllocation = new Predicate<Network>() { + + @Override + public boolean apply(Network input) { + return "none".equals(input.getName()); + } + + }; + + public void waitForTask(Task task) { + if (!successTester.apply(task.getHref())) { + throw new TaskStillRunningException(task); + } + } + /** + * Naming constraints modifying a VM on a VApp in vCloud Director (at least v1.5) can be more + * strict than those in a vAppTemplate. For example, while it is possible to instantiate a + * vAppTemplate with a VM named (incorrectly) {@code Ubuntu_10.04}, you must change the name to a + * valid (alphanumeric underscore) name before you can update it. + */ + public Task updateVmWithNameAndCustomizationScript(Vm vm, String name, @Nullable String customizationScript) { + GuestCustomizationSection guestConfiguration = vm.getGuestCustomizationSection(); + guestConfiguration.setComputerName(name); + if (customizationScript != null) { + // In version 1.0.0, the api returns a script that loses newlines, so we cannot append to a + // customization script. + // TODO: parameterize whether to overwrite or append existing customization + if (!buildVersion.startsWith("1.0.0") && !"".endsWith(buildVersion) + && guestConfiguration.getCustomizationScript() != null) + customizationScript = guestConfiguration.getCustomizationScript() + "\n" + customizationScript; + + guestConfiguration.setCustomizationScript(customizationScript); + } + return client.getVmApi().updateGuestCustomizationOfVm(guestConfiguration, vm.getHref()); + } + + public void ensureVmHasDesiredNetworkConnectionSettings(VApp vApp, VCloudTemplateOptions vOptions) { + Network networkToConnect = find(vApp.getNetworkSection().getNetworks(), not(networkWithNoIpAllocation)); + + Vm vm = get(vApp.getChildren(), 0); + + NetworkConnectionSection nets = vm.getNetworkConnectionSection(); + checkArgument(nets.getConnections().size() > 0, "no connections on vm %s", vm); + + /* + * Here we want to build the NetworkConnectionSection. + * This is not required if: + * - the user didn't pass in any vCloud specific NetworkConnection settings, and + * - there exist enough NetworkConnectionSections to cover the networks we need to + * wire up to the VM + * + * In case of modifying the existing network connection, its important that + * those optional parameters whose value is not being changed needs to be returned + * with the existing values or vcloud puts default values for them. When mac address is not + * modified then it needs to be returned else vclouds changes the adapter type of the NIC to E1000. + * + * There are a couple of things that might require changes: + * - different parameters (e.g. ip address allocation mode) + * - insufficient NetworkConnection items (we need to add more to trigger the + * creation of more NICs) + * - if the user didn't pass in any vCloud specific NetworkConnections, we might need to + * create new ones here. + * It's easier to just unconditionally rewrite the network connection section, + * than to write some bug-prone code that checks all of the above conditions. + */ + + /* + * We also need to add NICs. If we don't do this, we'll get new NICs, but they'll all be E1000s. + * We really want to replicate the type of any existing adapters. + * + * We add the NICs only when it is needed. In case of vapp template having vm with multiple NICs + * and if we update only the existing NICs then vcloud throws error that primary NIC not found. + */ + Set<? extends ResourceAllocationSettingData> allVirtualHWItems = vm.getVirtualHardwareSection().getItems(); + Iterable<VCloudNetworkAdapter> existingNics = Iterables.filter(allVirtualHWItems, VCloudNetworkAdapter.class); + // we want to program all existing nics. + ArrayList<VCloudNetworkAdapter> nicsToProgram = Lists.newArrayList(existingNics); + + //the first adapter type will be used as default for newly added ones. + String firstAdapterType = "E1000"; + int nextInstanceID = 1; + if (nicsToProgram.size() >= 1) { + firstAdapterType = nicsToProgram.get(0).getResourceSubType(); + nextInstanceID = 1 + Integer.valueOf(nicsToProgram.get(nicsToProgram.size() - 1).getInstanceID()); + } + + int i = 0; + LinkedHashSet<NetworkConnection> connectionsToProgram = new LinkedHashSet<NetworkConnection>(); + for (String netUuid: vOptions.getNetworks()) { + NetworkConnection desiredNC = vOptions.getNetworkConnections().get(netUuid); + String netName; + String macAddr; + NetworkConnection vappNC = findNetworkConnectionByIndexOrNull(nets, i); + if (vappNC != null && vappNC.getNetwork() != null) { + netName = vappNC.getNetwork(); + } else { + netName = null; + } + + if (vappNC != null && vappNC.getMACAddress() != null) { + macAddr = vappNC.getMACAddress(); + } else { + macAddr = null; + } + + if (desiredNC != null + && desiredNC.getNetworkConnectionIndex() != i) { + logger.error("Data consistency error: the network '" + netUuid + "'s connection index has been specified " + + "in the vCloud specific NetworkConnection settings in VCloudTemplateOptions.networkConnections, but " + + "the connection index does not match the " + + "position of the network in the TemplateOptions.networks object. Ignoring vCloud specific options for this net."); + desiredNC = null; + } + /* + Its not yet clear why the mac address in desiredNC is null. This needs to be explored. + This special handling is needed as the mac address is null and if it is not set, it results in NIC + type as E1000 + */ + if (desiredNC != null && macAddr != null && desiredNC.getMACAddress() == null){ + NetworkConnection.Builder desiredNCBuilder = desiredNC.toBuilder(); + desiredNCBuilder.MACAddress(macAddr); + desiredNC = desiredNCBuilder.build(); + } + if (desiredNC != null && desiredNC.getIpAddressAllocationMode() == null + || desiredNC.getIpAddressAllocationMode() == IpAddressAllocationMode.NONE) { + logger.error("Data consistency error: the network '" + netUuid + "'s IP address allocation mode" + + "has been set to 'none' or null in the vCloud specific NetworkConnection settings in VCloudTemplateOptions.networkConnections. " + + "This is invalid. Ignoring vCloud specific options for this net."); + desiredNC = null; + } + + NetworkConnection ncToAdd = null; + if (desiredNC == null) { + // use default settings + ncToAdd = new NetworkConnection(netName, i, null, null, true, null, + IpAddressAllocationMode.POOL); + } else { + if (netName != null && !netName.equals(desiredNC.getNetwork())) { + //something's probably wrong. + logger.warn("vcloud overridden network name '" + desiredNC.getNetwork() + "' doesn't match the vApp's " + + " network with index " + i + " name '" + netName + "'"); + } + + if (netName == null && desiredNC.getNetwork() == null) { + //ok we need to come up with some network name. + netName = "jclouds-net-" + String.valueOf(i); + NetworkConnection.Builder ncBuilder = desiredNC.toBuilder(); + ncToAdd = ncBuilder.network(netName).connected(desiredNC.isConnected()) + .externalIpAddress(desiredNC.getExternalIpAddress()) + .ipAddress(desiredNC.getIpAddress()).ipAddressAllocationMode(desiredNC.getIpAddressAllocationMode()) + .MACAddress(desiredNC.getMACAddress()).networkConnectionIndex(desiredNC.getNetworkConnectionIndex()).build(); + } else { + ncToAdd = desiredNC; + } + } + connectionsToProgram.add(ncToAdd); + + //OK, we've now setup the network connection. Now we want to check if we need to add a new NIC for it. + if (nicsToProgram.size() < connectionsToProgram.size()) { + VCloudNetworkAdapter.Builder nicBuilder = VCloudNetworkAdapter.builder(); + //interesting values + nicBuilder.addressOnParent(String.valueOf(i)); + nicBuilder.automaticAllocation(true); + nicBuilder.connection(ncToAdd.getNetwork()); + nicBuilder.ipAddressingMode(ncToAdd.getIpAddressAllocationMode().toString()); + nicBuilder.elementName("Network adapter " + String.valueOf(i)); + nicBuilder.instanceID(String.valueOf(nextInstanceID)); + nextInstanceID += 1; + nicBuilder.resourceSubType(firstAdapterType); + nicBuilder.resourceType(ResourceAllocationSettingData.ResourceType.ETHERNET_ADAPTER); + + VCloudNetworkAdapter newNic = nicBuilder.build(); + nicsToProgram.add(newNic); + } + i++; + } + + // Add new nics only if they are needed + if (nicsToProgram.size() < connectionsToProgram.size()) { + logger.debug("Programming NICs: %s", nicsToProgram); + Task t = client.getVmApi().updateNetworkCardsOfVm(nicsToProgram, vm.getHref()); + waitForTask(t); + } + + // update the NetworkConnectionSection. + Builder builder = nets.toBuilder(); + builder.connections(connectionsToProgram); + logger.trace(">> updating networkConnection vm(%s)", vm.getName()); + logger.debug("New NetworkConnectionSection for VM %s: %s", vm.getName(), builder.build().toString()); + waitForTask(client.getVmApi().updateNetworkConnectionOfVm(builder.build(), vm.getHref())); + logger.trace("<< updated networkConnection vm(%s)", vm.getName()); + } + + private NetworkConnection findWithPoolAllocationOrFirst(NetworkConnectionSection net) { + return find(net.getConnections(), new Predicate<NetworkConnection>() { + + @Override + public boolean apply(NetworkConnection input) { + return input.getIpAddressAllocationMode() == IpAddressAllocationMode.POOL; + } + + }, get(net.getConnections(), 0)); + } + + private NetworkConnection findNetworkConnectionByIndexOrNull(NetworkConnectionSection net, final int index) { + return find(net.getConnections(), new Predicate<NetworkConnection>() { + + @Override + public boolean apply(NetworkConnection input) { + return input.getNetworkConnectionIndex() == index; + } + + }, null); + } + + public Task updateCPUCountOfVm(Vm vm, int cpuCount) { + return client.getVmApi().updateCPUCountOfVm(cpuCount, vm.getHref()); + } + + public Task updateMemoryMBOfVm(Vm vm, int memoryInMB) { + return client.getVmApi().updateMemoryMBOfVm(memoryInMB, vm.getHref()); + } +}
http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/NetworkConfigurationForNetworkAndOptions.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/NetworkConfigurationForNetworkAndOptions.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/NetworkConfigurationForNetworkAndOptions.java new file mode 100644 index 0000000..28c8a9b --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/NetworkConfigurationForNetworkAndOptions.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.compute.strategy; + +import java.net.URI; + +import javax.inject.Inject; + +import org.jclouds.ovf.Network; +import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; +import org.jclouds.vcloud.domain.network.FenceMode; +import org.jclouds.vcloud.domain.network.NetworkConfig; + +import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; + +@Beta +public class NetworkConfigurationForNetworkAndOptions { + protected final Supplier<NetworkConfig> defaultNetworkConfig; + protected final FenceMode defaultFenceMode; + + @Inject + protected NetworkConfigurationForNetworkAndOptions(Supplier<NetworkConfig> defaultNetworkConfig, + FenceMode defaultFenceMode) { + this.defaultNetworkConfig = defaultNetworkConfig; + this.defaultFenceMode = defaultFenceMode; + } + + /** + * + * returns a {@link NetworkConfig} used to instantiate a vAppTemplate to + * either the default parent (org) network, or one specified by options. + * + * @param networkToConnect + * network defined in the VAppTemplate you wish to connect to + * @param vOptions + * options to override defaults with + * @return + */ + public NetworkConfig apply(Network networkToConnect, VCloudTemplateOptions vOptions) { + NetworkConfig config; + URI userDefinedParentNetwork = vOptions.getParentNetwork(); + FenceMode fenceMode = vOptions.getFenceMode() != null ? vOptions.getFenceMode() : defaultFenceMode; + if (userDefinedParentNetwork != null) { + config = NetworkConfig.builder().networkName("jclouds").fenceMode(fenceMode) + .parentNetwork(userDefinedParentNetwork).build(); + } else { + config = defaultNetworkConfig.get().toBuilder().fenceMode(fenceMode).build(); + } + + // if we only have a disconnected network, we are adding a new section + // for the upstream + if (InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.networkWithNoIpAllocation + .apply(networkToConnect)) { + // TODO: remove the disconnected entry + } else { + config = config.toBuilder().networkName(networkToConnect.getName()).build(); + } + return config; + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java new file mode 100644 index 0000000..cd636df --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java @@ -0,0 +1,262 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.compute.strategy; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.contains; +import static com.google.common.collect.Iterables.filter; + +import java.net.URI; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Location; +import org.jclouds.logging.Logger; +import org.jclouds.ovf.Envelope; +import org.jclouds.util.Throwables2; +import org.jclouds.vcloud.TaskInErrorStateException; +import org.jclouds.vcloud.TaskStillRunningException; +import org.jclouds.vcloud.VCloudApi; +import org.jclouds.vcloud.VCloudMediaType; +import org.jclouds.vcloud.domain.Org; +import org.jclouds.vcloud.domain.ReferenceType; +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.suppliers.VAppTemplatesSupplier; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; + +/** + * defines the connection between the {@link org.jclouds.vcloud.VCloudApi} implementation and the jclouds + * {@link ComputeService} + */ +@Singleton +public class VCloudComputeServiceAdapter implements ComputeServiceAdapter<VApp, VAppTemplate, VAppTemplate, Location> { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + protected final VCloudApi client; + protected final Predicate<URI> successTester; + protected final InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn booter; + protected final Supplier<Map<String, Org>> nameToOrg; + protected final Supplier<Set<VAppTemplate>> templates; + protected final Function<VAppTemplate, Envelope> templateToEnvelope; + + @Inject + protected VCloudComputeServiceAdapter(VCloudApi client, Predicate<URI> successTester, + InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn booter, + Supplier<Map<String, Org>> nameToOrg, VAppTemplatesSupplier templates, + Function<VAppTemplate, Envelope> templateToEnvelope) { + this.client = checkNotNull(client, "client"); + this.successTester = checkNotNull(successTester, "successTester"); + this.booter = checkNotNull(booter, "booter"); + this.nameToOrg = checkNotNull(nameToOrg, "nameToOrg"); + this.templates = checkNotNull(templates, "templates"); + this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope"); + } + + @Override + public NodeAndInitialCredentials<VApp> createNodeWithGroupEncodedIntoName(String group, String name, + Template template) { + return booter.createNodeWithGroupEncodedIntoName(group, name, template); + } + + @Override + public Iterable<VAppTemplate> listHardwareProfiles() { + return supportedTemplates(); + } + + private Iterable<VAppTemplate> supportedTemplates() { + return filter(templates.get(), new Predicate<VAppTemplate>() { + + @Override + public boolean apply(VAppTemplate from) { + try { + templateToEnvelope.apply(from); + } catch (IllegalArgumentException e) { + logger.warn("Unsupported: " + e.getMessage()); + return false; + } catch (RuntimeException e) { + IllegalArgumentException e2 = Throwables2.getFirstThrowableOfType(e, IllegalArgumentException.class); + if (e2 != null) { + logger.warn("Unsupported: " + e2.getMessage()); + return false; + } else { + throw e; + } + } + return true; + } + + }); + } + + @Override + public Iterable<VAppTemplate> listImages() { + return supportedTemplates(); + } + + @Override + public Iterable<VApp> listNodes() { + // TODO: parallel or cache + Builder<VApp> nodes = ImmutableSet.builder(); + for (Org org : nameToOrg.get().values()) { + for (ReferenceType vdc : org.getVDCs().values()) { + for (ReferenceType resource : client.getVDCApi().getVDC(vdc.getHref()).getResourceEntities().values()) { + if (resource.getType().equals(VCloudMediaType.VAPP_XML)) { + addVAppToSetRetryingIfNotYetPresent(nodes, vdc, resource); + } + } + } + } + return nodes.build(); + } + + @Override + public Iterable<VApp> listNodesByIds(final Iterable<String> ids) { + return filter(listNodes(), new Predicate<VApp>() { + + @Override + public boolean apply(VApp vm) { + return contains(ids, vm.getHref().toASCIIString()); + } + }); + } + + @VisibleForTesting + void addVAppToSetRetryingIfNotYetPresent(Builder<VApp> nodes, ReferenceType vdc, ReferenceType resource) { + VApp node = null; + int i = 0; + while (node == null && i++ < 3) { + try { + node = client.getVAppApi().getVApp(resource.getHref()); + nodes.add(node); + } catch (NullPointerException e) { + logger.warn("vApp %s not yet present in vdc %s", resource.getName(), vdc.getName()); + } + } + } + + @Override + public Iterable<Location> listLocations() { + // Not using the adapter to determine locations + return ImmutableSet.<Location>of(); + } + + @Override + public VApp getNode(String in) { + URI id = URI.create(in); + return client.getVAppApi().getVApp(id); + } + + @Override + public VAppTemplate getImage(String in) { + URI id = URI.create(in); + return client.getVAppTemplateApi().getVAppTemplate(id); + } + + @Override + public void destroyNode(String id) { + URI vappId = URI.create(checkNotNull(id, "node.id")); + VApp vApp = cancelAnyRunningTasks(vappId); + if (vApp.getStatus() != Status.OFF) { + logger.debug(">> powering off VApp vApp(%s), current status: %s", vApp.getName(), vApp.getStatus()); + try { + waitForTask(client.getVAppApi().powerOffVApp(vApp.getHref())); + vApp = client.getVAppApi().getVApp(vApp.getHref()); + logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName()); + } catch (IllegalStateException e) { + logger.warn(e, "<< %s vApp(%s)", vApp.getStatus(), vApp.getName()); + } + logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), vApp.getStatus()); + try { + waitForTask(client.getVAppApi().undeployVApp(vApp.getHref())); + vApp = client.getVAppApi().getVApp(vApp.getHref()); + logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName()); + } catch (IllegalStateException e) { + logger.warn(e, "<< %s vApp(%s)", vApp.getStatus(), vApp.getName()); + } + } + logger.debug(">> deleting vApp(%s)", vApp.getHref()); + waitForTask(client.getVAppApi().deleteVApp(vApp.getHref())); + logger.debug("<< deleted vApp(%s)", vApp.getHref()); + } + + VApp waitForPendingTasksToComplete(URI vappId) { + VApp vApp = client.getVAppApi().getVApp(vappId); + if (vApp.getTasks().size() == 0) + return vApp; + for (Task task : vApp.getTasks()) + waitForTask(task); + return client.getVAppApi().getVApp(vappId); + } + + VApp cancelAnyRunningTasks(URI vappId) { + VApp vApp = client.getVAppApi().getVApp(vappId); + if (vApp.getTasks().size() == 0) + return vApp; + for (Task task : vApp.getTasks()) { + try { + client.getTaskApi().cancelTask(task.getHref()); + waitForTask(task); + } catch (TaskInErrorStateException e) { + } + } + return client.getVAppApi().getVApp(vappId); + + } + + public void waitForTask(Task task) { + if (!successTester.apply(task.getHref())) + throw new TaskStillRunningException(task); + } + + @Override + public void rebootNode(String in) { + URI id = URI.create(checkNotNull(in, "node.id")); + waitForTask(client.getVAppApi().resetVApp(id)); + } + + @Override + public void resumeNode(String in) { + URI id = URI.create(checkNotNull(in, "node.id")); + waitForTask(client.getVAppApi().powerOnVApp(id)); + } + + @Override + public void suspendNode(String in) { + URI id = URI.create(checkNotNull(in, "node.id")); + waitForTask(client.getVAppApi().powerOffVApp(id)); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java new file mode 100644 index 0000000..905565e --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/compute/util/VCloudComputeUtils.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.compute.util; + +import static com.google.common.collect.Iterables.filter; + +import java.util.Set; + +import org.jclouds.cim.CIMPredicates; +import org.jclouds.cim.ResourceAllocationSettingData; +import org.jclouds.cim.ResourceAllocationSettingData.ResourceType; +import org.jclouds.compute.domain.CIMOperatingSystem; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.vcloud.domain.NetworkConnection; +import org.jclouds.vcloud.domain.VApp; +import org.jclouds.vcloud.domain.VAppTemplate; +import org.jclouds.vcloud.domain.Vm; +import org.jclouds.vcloud.domain.ovf.VCloudNetworkAdapter; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Iterables; + +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().size() > 0 ? toComputeOs(Iterables.get(vApp.getChildren(), 0)) : null; + } + + public static CIMOperatingSystem toComputeOs(Vm vm) { + return CIMOperatingSystem.toComputeOs(vm.getOperatingSystemSection()); + } + + public static String getVirtualSystemIdentifierOfFirstVMIn(VApp vApp) { + return vApp.getChildren().size() > 0 ? getVirtualSystemIdentifierOf(Iterables.get(vApp.getChildren(), 0)) : null; + } + + public static String getVirtualSystemIdentifierOf(Vm vm) { + if (vm.getVirtualHardwareSection() != null && vm.getVirtualHardwareSection().getSystem() != null) + return vm.getVirtualHardwareSection().getSystem().getVirtualSystemIdentifier(); + return null; + } + + public static LoginCredentials getCredentialsFrom(VApp vApp) { + return vApp.getChildren().size() > 0 ? getCredentialsFrom(Iterables.get(vApp.getChildren(), 0)) : null; + } + + public static LoginCredentials getCredentialsFrom(VAppTemplate vApp) { + return vApp.getChildren().size() > 0 ? getCredentialsFrom(Iterables.get(vApp.getChildren(), 0)) : null; + } + + public static LoginCredentials getCredentialsFrom(Vm vm) { + LoginCredentials.Builder builder = LoginCredentials.builder(); + if (vm.getGuestCustomizationSection() != null) + builder.password(vm.getGuestCustomizationSection().getAdminPassword()); + return builder.build(); + } + + public static Set<String> getIpsFromVApp(VApp vApp) { + // TODO make this work with composite vApps + if (vApp.getChildren().size() == 0) + return ImmutableSet.of(); + Builder<String> ips = ImmutableSet.builder(); + Vm vm = Iterables.get(vApp.getChildren(), 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 + if (vm.getNetworkConnectionSection() != null) { + for (NetworkConnection connection : vm.getNetworkConnectionSection().getConnections()) { + if (connection.getIpAddress() != null) + ips.add(connection.getIpAddress()); + if (connection.getExternalIpAddress() != null) + ips.add(connection.getExternalIpAddress()); + } + } else { + for (ResourceAllocationSettingData net : filter(vm.getVirtualHardwareSection().getItems(), + CIMPredicates.resourceTypeIn(ResourceType.ETHERNET_ADAPTER))) { + if (net instanceof VCloudNetworkAdapter) { + VCloudNetworkAdapter vNet = VCloudNetworkAdapter.class.cast(net); + if (vNet.getIpAddress() != null) + ips.add(vNet.getIpAddress()); + } + } + } + return ips.build(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultCatalogForOrg.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultCatalogForOrg.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultCatalogForOrg.java new file mode 100644 index 0000000..eb700f3 --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultCatalogForOrg.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_CATALOG; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.vcloud.domain.Org; +import org.jclouds.vcloud.domain.ReferenceType; +import org.jclouds.vcloud.endpoints.Catalog; +import org.jclouds.vcloud.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; + +@Singleton +public class DefaultCatalogForOrg implements Function<ReferenceType, ReferenceType> { + private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector; + private final Supplier<Map<String, Org>> nameToOrg; + + @Inject + public DefaultCatalogForOrg(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, + @Catalog Predicate<ReferenceType> defaultSelector, Supplier<Map<String, Org>> nameToOrg) { + this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull( + valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_CATALOG, + checkNotNull(defaultSelector, "defaultSelector")); + this.nameToOrg = checkNotNull(nameToOrg, "nameToOrg"); + } + + @Override + public ReferenceType apply(ReferenceType defaultOrg) { + Org org = nameToOrg.get().get(defaultOrg.getName()); + checkState(org != null, "could not retrieve Org at %s", defaultOrg); + return selector.apply(org.getCatalogs().values()); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultNetworkForVDC.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultNetworkForVDC.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultNetworkForVDC.java new file mode 100644 index 0000000..e336b95 --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultNetworkForVDC.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_NETWORK; + +import java.net.URI; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.vcloud.domain.ReferenceType; +import org.jclouds.vcloud.domain.VDC; +import org.jclouds.vcloud.endpoints.Network; +import org.jclouds.vcloud.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; + +@Singleton +public class DefaultNetworkForVDC implements Function<ReferenceType, ReferenceType> { + + private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector; + private final Supplier<Map<URI, VDC>> uriToVDC; + + @Inject + public DefaultNetworkForVDC(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, + @Network Predicate<ReferenceType> defaultSelector, Supplier<Map<URI, VDC>> uriToVDC) { + this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull( + valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_NETWORK, + checkNotNull(defaultSelector, "defaultSelector")); + this.uriToVDC = checkNotNull(uriToVDC, "uriToVDC"); + } + + @Override + public ReferenceType apply(ReferenceType defaultVDC) { + org.jclouds.vcloud.domain.VDC vDC = uriToVDC.get().get(defaultVDC.getHref()); + checkState(vDC != null, "could not retrieve VDC at %s", defaultVDC); + return selector.apply(vDC.getAvailableNetworks().values()); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultOrgForUser.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultOrgForUser.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultOrgForUser.java new file mode 100644 index 0000000..8ed2eba --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultOrgForUser.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_ORG; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.vcloud.domain.ReferenceType; +import org.jclouds.vcloud.domain.VCloudSession; +import org.jclouds.vcloud.endpoints.Org; +import org.jclouds.vcloud.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; + +@Singleton +public class DefaultOrgForUser implements Supplier<ReferenceType> { + + private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector; + private final Supplier<VCloudSession> session; + + @Inject + public DefaultOrgForUser(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, + @Org Predicate<ReferenceType> defaultSelector, Supplier<VCloudSession> session) { + this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull( + valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_ORG, checkNotNull( + defaultSelector, "defaultSelector")); + this.session = checkNotNull(session, "session"); + } + + @Override + public ReferenceType get() { + return selector.apply(session.get().getOrgs().values()); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultTasksListForOrg.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultTasksListForOrg.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultTasksListForOrg.java new file mode 100644 index 0000000..c670161 --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultTasksListForOrg.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.vcloud.domain.Org; +import org.jclouds.vcloud.domain.ReferenceType; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +@Singleton +public class DefaultTasksListForOrg implements Function<ReferenceType, ReferenceType> { + private final Supplier<Map<String, Org>> nameToOrg; + + @Inject + public DefaultTasksListForOrg(Supplier<Map<String, Org>> nameToOrg) { + this.nameToOrg = checkNotNull(nameToOrg, "nameToOrg"); + } + + @Override + public ReferenceType apply(ReferenceType defaultOrg) { + org.jclouds.vcloud.domain.Org org = nameToOrg.get().get(defaultOrg.getName()); + checkState(org != null, "could not retrieve Org at %s", defaultOrg); + return org.getTasksList(); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVCloudReferencesModule.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVCloudReferencesModule.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVCloudReferencesModule.java new file mode 100644 index 0000000..5a0ba9d --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVCloudReferencesModule.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.config; + +import java.net.URI; +import java.util.Map; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.domain.Catalog; +import org.jclouds.vcloud.domain.ReferenceType; +import org.jclouds.vcloud.endpoints.Org; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import com.google.inject.AbstractModule; +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; + +public class DefaultVCloudReferencesModule extends AbstractModule { + + @Override + protected void configure() { + bind(new TypeLiteral<Supplier<ReferenceType>>() { + }).annotatedWith(Org.class).to(DefaultOrgForUser.class); + } + + @Provides + @Singleton + @org.jclouds.vcloud.endpoints.Org + protected Predicate<ReferenceType> provideDefaultOrgSelector(Injector i) { + return Predicates.alwaysTrue(); + } + + @Provides + @org.jclouds.vcloud.endpoints.TasksList + @Singleton + protected Supplier<ReferenceType> provideDefaultTasksList(DefaultTasksListForOrg defaultTasksListURIForOrg, + @org.jclouds.vcloud.endpoints.Org Supplier<ReferenceType> defaultOrg) { + return Suppliers.compose(defaultTasksListURIForOrg, defaultOrg); + } + + @Provides + @org.jclouds.vcloud.endpoints.Catalog + @Singleton + protected Supplier<ReferenceType> provideDefaultCatalog(DefaultCatalogForOrg defaultCatalogURIForOrg, + @org.jclouds.vcloud.endpoints.Org Supplier<ReferenceType> defaultOrg) { + return Suppliers.compose(defaultCatalogURIForOrg, defaultOrg); + } + + @Provides + @Singleton + @org.jclouds.vcloud.endpoints.Catalog + protected Predicate<ReferenceType> provideDefaultCatalogSelector(Injector i) { + return i.getInstance(WriteableCatalog.class); + } + + @Provides + @Singleton + protected Supplier<Map<URI, org.jclouds.vcloud.domain.Catalog>> provideCatalogsById( + Supplier<Map<String, Map<String, org.jclouds.vcloud.domain.Catalog>>> supplier) { + return Suppliers + .compose( + new Function<Map<String, Map<String, org.jclouds.vcloud.domain.Catalog>>, Map<URI, org.jclouds.vcloud.domain.Catalog>>() { + + @Override + public Map<URI, Catalog> apply(Map<String, Map<String, Catalog>> arg0) { + Builder<URI, Catalog> builder = ImmutableMap.builder(); + for (Map<String, Catalog> v1 : arg0.values()) { + for (Catalog v2 : v1.values()) { + builder.put(v2.getHref(), v2); + } + } + return builder.build(); + } + + }, supplier); + } + + @Singleton + public static class WriteableCatalog implements Predicate<ReferenceType> { + + @Resource + protected Logger logger = Logger.NULL; + + private final Supplier<Map<URI, org.jclouds.vcloud.domain.Catalog>> catalogsByIdSupplier; + + @Inject + public WriteableCatalog(Supplier<Map<URI, org.jclouds.vcloud.domain.Catalog>> catalogsByIdSupplier) { + this.catalogsByIdSupplier = catalogsByIdSupplier; + } + + @Override + public boolean apply(ReferenceType arg0) { + // TODO: this is inefficient, calculating the index each time, but + // shouldn't be added to constructor as the supplier is an expensive + // call + Map<URI, Catalog> index = catalogsByIdSupplier.get(); + Catalog catalog = index.get(arg0.getHref()); + if (catalog == null) { + if (logger.isTraceEnabled()) + logger.trace("didn't find catalog %s", arg0); + return false; + } else + return !catalog.isReadOnly(); + } + } + + @Provides + @org.jclouds.vcloud.endpoints.VDC + @Singleton + protected Supplier<ReferenceType> provideDefaultVDC(DefaultVDCForOrg defaultVDCURIForOrg, + @org.jclouds.vcloud.endpoints.Org Supplier<ReferenceType> defaultOrg) { + return Suppliers.compose(defaultVDCURIForOrg, defaultOrg); + } + + @Provides + @Singleton + @org.jclouds.vcloud.endpoints.VDC + protected Predicate<ReferenceType> provideDefaultVDCSelector(Injector i) { + return Predicates.alwaysTrue(); + } + + @Provides + @org.jclouds.vcloud.endpoints.Network + @Singleton + protected Supplier<ReferenceType> provideDefaultNetwork(DefaultNetworkForVDC defaultNetworkURIForVDC, + @org.jclouds.vcloud.endpoints.VDC Supplier<ReferenceType> defaultVDC) { + return Suppliers.compose(defaultNetworkURIForVDC, defaultVDC); + } + + @Provides + @Singleton + @org.jclouds.vcloud.endpoints.Network + protected Predicate<ReferenceType> provideDefaultNetworkSelector(Injector i) { + return Predicates.alwaysTrue(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVDCForOrg.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVDCForOrg.java b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVDCForOrg.java new file mode 100644 index 0000000..4eefd30 --- /dev/null +++ b/dependencies/jclouds/apis/vcloud/1.8.1-stratos/src/main/java/org/jclouds/vcloud/config/DefaultVDCForOrg.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.vcloud.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_VDC; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.vcloud.domain.Org; +import org.jclouds.vcloud.domain.ReferenceType; +import org.jclouds.vcloud.endpoints.VDC; +import org.jclouds.vcloud.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; + +@Singleton +public class DefaultVDCForOrg implements Function<ReferenceType, ReferenceType> { + private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector; + private final Supplier<Map<String, Org>> nameToOrg; + + @Inject + public DefaultVDCForOrg(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, + @VDC Predicate<ReferenceType> defaultSelector, Supplier<Map<String, Org>> nameToOrg) { + this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull( + valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_VDC, + checkNotNull(defaultSelector, "defaultSelector")); + this.nameToOrg = checkNotNull(nameToOrg, "nameToOrg"); + } + + @Override + public ReferenceType apply(ReferenceType defaultOrg) { + Org org = nameToOrg.get().get(defaultOrg.getName()); + checkState(org != null, "could not retrieve Org at %s", defaultOrg); + return selector.apply(org.getVDCs().values()); + } + +}
