Package com.elastisys.scale.cloudadapters.openstack.scalinggroup

Source Code of com.elastisys.scale.cloudadapters.openstack.scalinggroup.OpenStackScalingGroup

package com.elastisys.scale.cloudadapters.openstack.scalinggroup;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Lists.transform;
import static java.lang.String.format;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;

import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.elastisys.scale.cloudadapers.api.types.Machine;
import com.elastisys.scale.cloudadapters.commons.adapter.BaseCloudAdapter;
import com.elastisys.scale.cloudadapters.commons.adapter.BaseCloudAdapterConfig;
import com.elastisys.scale.cloudadapters.commons.adapter.BaseCloudAdapterConfig.ScaleUpConfig;
import com.elastisys.scale.cloudadapters.commons.adapter.BaseCloudAdapterConfig.ScalingGroupConfig;
import com.elastisys.scale.cloudadapters.commons.adapter.scalinggroup.ScalingGroup;
import com.elastisys.scale.cloudadapters.commons.adapter.scalinggroup.ScalingGroupException;
import com.elastisys.scale.cloudadapters.commons.adapter.scalinggroup.StartMachinesException;
import com.elastisys.scale.cloudadapters.openstack.functions.ServerToMachine;
import com.elastisys.scale.cloudadapters.openstack.scalinggroup.client.OpenstackClient;
import com.elastisys.scale.commons.json.JsonUtils;
import com.elastisys.scale.commons.json.schema.JsonValidator;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Atomics;
import com.google.gson.JsonObject;

/**
* A {@link ScalingGroup} implementation that operates against the OpenStack
* cloud API.
*
* @see BaseCloudAdapter
*
*
*
*/
public class OpenStackScalingGroup implements ScalingGroup {

  /**
   * JSON Schema describing valid {@link OpenStackScalingGroupConfig}
   * instances.
   */
  private static final JsonObject CONFIG_SCHEMA = JsonUtils
      .parseJsonResource("openstack-scaling-group-schema.json");

  static Logger LOG = LoggerFactory.getLogger(OpenStackScalingGroup.class);

  /** OpenStack client API configuration. */
  private final AtomicReference<OpenStackScalingGroupConfig> config;
  /** Name of the managed scaling group. */
  private final AtomicReference<String> scalingGroupName;

  /** Client used to communicate with the OpenStack API. */
  private final OpenstackClient client;

  /**
   * Creates a new {@link OpenStackScalingGroup}. Needs to be configured
   * before use.
   *
   * @param client
   *            The client to be used to communicate with the OpenStack API.
   */
  public OpenStackScalingGroup(OpenstackClient client) {
    this.config = Atomics.newReference();
    this.scalingGroupName = Atomics.newReference();
    this.client = client;
  }

  @Override
  public void configure(BaseCloudAdapterConfig configuration)
      throws ScalingGroupException {
    ScalingGroupConfig scalingGroupConfig = configuration.getScalingGroup();
    checkArgument(scalingGroupConfig != null, "missing scalingGroup config");

    try {
      // validate against client config schema
      JsonValidator.validate(CONFIG_SCHEMA,
          scalingGroupConfig.getConfig());
      // parse and validate cloud login configuration
      OpenStackScalingGroupConfig config = JsonUtils.toObject(
          scalingGroupConfig.getConfig(),
          OpenStackScalingGroupConfig.class);
      config.validate();
      this.config.set(config);
      this.scalingGroupName.set(scalingGroupConfig.getName());
      this.client.configure(config);
    } catch (Exception e) {
      Throwables.propagateIfInstanceOf(e, ScalingGroupException.class);
      throw new ScalingGroupException(String.format(
          "failed to apply configuration: %s", e.getMessage()), e);
    }
  }

  @Override
  public List<Machine> listMachines() throws ScalingGroupException {
    checkState(isConfigured(), "attempt to use unconfigured ScalingGroup");

    try {
      List<Server> servers = this.client.getServers(
          Constants.SCALING_GROUP_TAG, getScalingGroupName());
      return transform(servers, new ServerToMachine());
    } catch (Exception e) {
      throw new ScalingGroupException(format(
          "failed to retrieve machines in scaling group \"%s\": %s",
          this.scalingGroupName, e.getMessage()), e);
    }
  }

  @Override
  public List<Machine> startMachines(int count, ScaleUpConfig scaleUpConfig)
      throws StartMachinesException {
    checkState(isConfigured(), "attempt to use unconfigured ScalingGroup");

    List<Machine> startedMachines = Lists.newArrayList();
    try {
      for (int i = 0; i < count; i++) {
        // tag new server with scaling group membership
        Map<String, String> tags = ImmutableMap.of(
            Constants.SCALING_GROUP_TAG, getScalingGroupName());
        Server newServer = this.client.launchServer(uniqueServerName(),
            scaleUpConfig, tags);
        startedMachines.add(ServerToMachine.convert(newServer));

        if (config().isAssignFloatingIp()) {
          String serverId = newServer.getId();
          this.client.assignFloatingIp(serverId);
          // update meta data to include the public IP
          startedMachines.set(i, ServerToMachine.convert(this.client
              .getServer(serverId)));
        }
      }
    } catch (Exception e) {
      throw new StartMachinesException(count, startedMachines, e);
    }
    return startedMachines;
  }

  @Override
  public void terminateMachine(String machineId) throws ScalingGroupException {
    checkState(isConfigured(), "attempt to use unconfigured ScalingGroup");

    try {
      this.client.terminateServer(machineId);
    } catch (Exception e) {
      Throwables.propagateIfInstanceOf(e, ScalingGroupException.class);
      String message = format("failed to terminate server \"%s\": %s",
          machineId, e.getMessage());
      throw new ScalingGroupException(message, e);
    }
  }

  @Override
  public String getScalingGroupName() {
    checkState(isConfigured(), "attempt to use unconfigured ScalingGroup");

    return this.scalingGroupName.get();
  }

  /**
   * Create a unique server host name for a new server instance. This is
   * necessary to make sure that different hosts do not report monitoring
   * values using the same host name, which may confuse OpenTSDB.
   *
   * @return
   */
  private String uniqueServerName() {
    String prefix = getScalingGroupName();
    String suffix = UUID.randomUUID().toString();
    return String.format("%s-%s", prefix, suffix);
  }

  boolean isConfigured() {
    return config() != null;
  }

  OpenStackScalingGroupConfig config() {
    return this.config.get();
  }
}
TOP

Related Classes of com.elastisys.scale.cloudadapters.openstack.scalinggroup.OpenStackScalingGroup

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.