Package org.jclouds.ec2.compute.functions

Source Code of org.jclouds.ec2.compute.functions.PasswordCredentialsFromWindowsInstance

/*
* 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.ec2.compute.functions;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.util.Predicates2.retry;

import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;

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

import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.PasswordData;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.features.WindowsApi;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.util.concurrent.Atomics;

/**
* @author Adrian Cole
*/
@Singleton
public class PasswordCredentialsFromWindowsInstance implements Function<RunningInstance, LoginCredentials> {

   @Resource
   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
   protected Logger logger = Logger.NULL;

   private final ConcurrentMap<RegionAndName, KeyPair> credentialsMap;
   private final EC2Client ec2Client;
   private final Function<PasswordDataAndPrivateKey, LoginCredentials> pwDataToLoginCredentials;

   @Inject
   protected PasswordCredentialsFromWindowsInstance(ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
            EC2Client ec2Client, Function<PasswordDataAndPrivateKey, LoginCredentials> pwDataToLoginCredentials) {
      this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
      this.ec2Client = checkNotNull(ec2Client, "ec2Client");
      this.pwDataToLoginCredentials = checkNotNull(pwDataToLoginCredentials, "pwDataToLoginCredentials");
   }

   @Override
   public LoginCredentials apply(final RunningInstance instance) {
      Optional<? extends WindowsApi> windowsOption = ec2Client.getWindowsApiForRegion(instance.getRegion());
      checkState(windowsOption.isPresent(), "windows feature not present in region %s", instance.getRegion());
     
      final WindowsApi windowsApi = windowsOption.get();
     
      LoginCredentials credentials = LoginCredentials.builder().user("Administrator").noPrivateKey().build();
      String privateKey = getPrivateKeyOrNull(instance);
      if (privateKey == null) {
         return credentials;
      }
      // The Administrator password will take some time before it is ready - Amazon says
      // sometimes
      // 15 minutes.
      // So we create a predicate that tests if the password is ready, and wrap it in a retryable
      // predicate.
      final AtomicReference<PasswordData> data = Atomics.newReference();
      Predicate<String> passwordReady = new Predicate<String>() {
         @Override
         public boolean apply(@Nullable String s) {
            if (Strings.isNullOrEmpty(s))
               return false;
            data.set(windowsApi.getPasswordDataForInstance(instance.getId()));
            if (data.get() == null)
               return false;
            return !Strings.isNullOrEmpty(data.get().getPasswordData());
         }
      };

      // TODO: parameterize
      Predicate<String> passwordReadyRetryable = retry(passwordReady, 600, 10, SECONDS);

      logger.debug(">> awaiting password data for instance(%s/%s)", instance.getRegion(), instance.getId());
      if (passwordReadyRetryable.apply(instance.getId())) {
         credentials = pwDataToLoginCredentials.apply(new PasswordDataAndPrivateKey(data.get(), privateKey));
         logger.debug("<< obtained password data for instance(%s/%s)", instance.getRegion(), instance.getId());
      } else {
         logger.debug("<< unable to get password data for instance(%s/%s)", instance.getRegion(), instance.getId());
      }
      return credentials;
   }

   @VisibleForTesting
   String getPrivateKeyOrNull(RunningInstance instance) {
      KeyPair keyPair = credentialsMap.get(new RegionAndName(instance.getRegion(), instance.getKeyName()));
      return keyPair != null ? keyPair.getKeyMaterial() : null;
   }

}
TOP

Related Classes of org.jclouds.ec2.compute.functions.PasswordCredentialsFromWindowsInstance

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.