org.jclouds.openstack.nova.v2_0.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java Source code

Java tutorial

Introduction

Here is the source code for org.jclouds.openstack.nova.v2_0.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java

Source

/*
 * 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.openstack.nova.v2_0.compute.strategy;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import org.jclouds.Constants;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.compute.functions.AllocateAndAddFloatingIpToNode;
import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;

import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Multimap;
import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;

/**
 * 
 * @author Adrian Cole
 */
@Singleton
public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet
        extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {

    private final AllocateAndAddFloatingIpToNode createAndAddFloatingIpToNode;
    private final LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache;
    private final LoadingCache<ZoneAndName, KeyPair> keyPairCache;
    private final NovaApi novaApi;

    @Inject
    protected ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet(
            CreateNodeWithGroupEncodedIntoName addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy,
            GroupNamingConvention.Factory namingConvention,
            CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
            @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
            AllocateAndAddFloatingIpToNode createAndAddFloatingIpToNode,
            LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache,
            LoadingCache<ZoneAndName, KeyPair> keyPairCache, NovaApi novaApi) {
        super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, userExecutor,
                customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
        this.securityGroupCache = checkNotNull(securityGroupCache, "securityGroupCache");
        this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
        this.createAndAddFloatingIpToNode = checkNotNull(createAndAddFloatingIpToNode,
                "createAndAddFloatingIpToNode");
        this.novaApi = checkNotNull(novaApi, "novaApi");
    }

    @Override
    public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
            Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
            Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {

        Template mutableTemplate = template.clone();

        NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(mutableTemplate.getOptions());

        assert template.getOptions().equals(templateOptions) : "options didn't clone properly";

        String zone = mutableTemplate.getLocation().getId();

        if (templateOptions.shouldAutoAssignFloatingIp()) {
            checkArgument(novaApi.getFloatingIPExtensionForZone(zone).isPresent(),
                    "Floating IPs are required by options, but the extension is not available! options: %s",
                    templateOptions);
        }

        boolean keyPairExtensionPresent = novaApi.getKeyPairExtensionForZone(zone).isPresent();
        if (templateOptions.shouldGenerateKeyPair()) {
            checkArgument(keyPairExtensionPresent,
                    "Key Pairs are required by options, but the extension is not available! options: %s",
                    templateOptions);
            KeyPair keyPair = keyPairCache.getUnchecked(
                    ZoneAndName.fromZoneAndName(zone, namingConvention.create().sharedNameForGroup(group)));
            keyPairCache.asMap().put(ZoneAndName.fromZoneAndName(zone, keyPair.getName()), keyPair);
            templateOptions.keyPairName(keyPair.getName());
        } else if (templateOptions.getKeyPairName() != null) {
            checkArgument(keyPairExtensionPresent,
                    "Key Pairs are required by options, but the extension is not available! options: %s",
                    templateOptions);
            if (templateOptions.getLoginPrivateKey() != null) {
                String pem = templateOptions.getLoginPrivateKey();
                KeyPair keyPair = KeyPair.builder().name(templateOptions.getKeyPairName())
                        .fingerprint(fingerprintPrivateKey(pem)).privateKey(pem).build();
                keyPairCache.asMap().put(ZoneAndName.fromZoneAndName(zone, keyPair.getName()), keyPair);
            }
        }

        boolean securityGroupExtensionPresent = novaApi.getSecurityGroupExtensionForZone(zone).isPresent();
        List<Integer> inboundPorts = Ints.asList(templateOptions.getInboundPorts());
        if (templateOptions.getSecurityGroupNames().isPresent()
                && templateOptions.getSecurityGroupNames().get().size() > 0) {
            checkArgument(securityGroupExtensionPresent,
                    "Security groups are required by options, but the extension is not available! options: %s",
                    templateOptions);
        } else if (securityGroupExtensionPresent) {
            if (!templateOptions.getSecurityGroupNames().isPresent() && inboundPorts.size() > 0) {
                String securityGroupName = namingConvention.create().sharedNameForGroup(group);
                try {
                    securityGroupCache
                            .get(new ZoneSecurityGroupNameAndPorts(zone, securityGroupName, inboundPorts));
                } catch (ExecutionException e) {
                    throw Throwables.propagate(e.getCause());
                }
                templateOptions.securityGroupNames(securityGroupName);
            }
        }
        templateOptions.userMetadata(ComputeServiceConstants.NODE_GROUP_KEY, group);

        return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses);
    }

    @Override
    protected ListenableFuture<AtomicReference<NodeMetadata>> createNodeInGroupWithNameAndTemplate(String group,
            final String name, Template template) {

        ListenableFuture<AtomicReference<NodeMetadata>> future = super.createNodeInGroupWithNameAndTemplate(group,
                name, template);
        NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());

        if (templateOptions.shouldAutoAssignFloatingIp()) {
            return Futures.transform(future, createAndAddFloatingIpToNode, userExecutor);
        } else {
            return future;
        }
    }

}