com.eucalyptus.cluster.service.fake.FakeNodeService.java Source code

Java tutorial

Introduction

Here is the source code for com.eucalyptus.cluster.service.fake.FakeNodeService.java

Source

/*************************************************************************
 * (c) Copyright 2017 Hewlett Packard Enterprise Development Company LP
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 ************************************************************************/
package com.eucalyptus.cluster.service.fake;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.hibernate.criterion.Restrictions;
import com.eucalyptus.cluster.common.msgs.InstanceType;
import com.eucalyptus.cluster.common.msgs.MetricCounterType;
import com.eucalyptus.cluster.common.msgs.MetricDimensionsType;
import com.eucalyptus.cluster.common.msgs.MetricDimensionsValuesType;
import com.eucalyptus.cluster.common.msgs.MetricsResourceType;
import com.eucalyptus.cluster.common.msgs.NcAssignAddressResponseType;
import com.eucalyptus.cluster.common.msgs.NcAssignAddressType;
import com.eucalyptus.cluster.common.msgs.NcAttachNetworkInterfaceResponseType;
import com.eucalyptus.cluster.common.msgs.NcAttachNetworkInterfaceType;
import com.eucalyptus.cluster.common.msgs.NcAttachVolumeResponseType;
import com.eucalyptus.cluster.common.msgs.NcAttachVolumeType;
import com.eucalyptus.cluster.common.msgs.NcBroadcastNetworkInfoResponseType;
import com.eucalyptus.cluster.common.msgs.NcBroadcastNetworkInfoType;
import com.eucalyptus.cluster.common.msgs.NcBundleInstanceResponseType;
import com.eucalyptus.cluster.common.msgs.NcBundleInstanceType;
import com.eucalyptus.cluster.common.msgs.NcBundleRestartInstanceResponseType;
import com.eucalyptus.cluster.common.msgs.NcBundleRestartInstanceType;
import com.eucalyptus.cluster.common.msgs.NcCancelBundleTaskResponseType;
import com.eucalyptus.cluster.common.msgs.NcCancelBundleTaskType;
import com.eucalyptus.cluster.common.msgs.NcCreateImageResponseType;
import com.eucalyptus.cluster.common.msgs.NcCreateImageType;
import com.eucalyptus.cluster.common.msgs.NcDescribeInstancesResponseType;
import com.eucalyptus.cluster.common.msgs.NcDescribeInstancesType;
import com.eucalyptus.cluster.common.msgs.NcDescribeResourceResponseType;
import com.eucalyptus.cluster.common.msgs.NcDescribeResourceType;
import com.eucalyptus.cluster.common.msgs.NcDescribeSensorsResponseType;
import com.eucalyptus.cluster.common.msgs.NcDescribeSensorsType;
import com.eucalyptus.cluster.common.msgs.NcDetachNetworkInterfaceResponseType;
import com.eucalyptus.cluster.common.msgs.NcDetachNetworkInterfaceType;
import com.eucalyptus.cluster.common.msgs.NcDetachVolumeResponseType;
import com.eucalyptus.cluster.common.msgs.NcDetachVolumeType;
import com.eucalyptus.cluster.common.msgs.NcGetConsoleOutputResponseType;
import com.eucalyptus.cluster.common.msgs.NcGetConsoleOutputType;
import com.eucalyptus.cluster.common.msgs.NcMigrateInstancesResponseType;
import com.eucalyptus.cluster.common.msgs.NcMigrateInstancesType;
import com.eucalyptus.cluster.common.msgs.NcModifyNodeResponseType;
import com.eucalyptus.cluster.common.msgs.NcModifyNodeType;
import com.eucalyptus.cluster.common.msgs.NcPowerDownResponseType;
import com.eucalyptus.cluster.common.msgs.NcPowerDownType;
import com.eucalyptus.cluster.common.msgs.NcRebootInstanceResponseType;
import com.eucalyptus.cluster.common.msgs.NcRebootInstanceType;
import com.eucalyptus.cluster.common.msgs.NcRunInstanceResponseType;
import com.eucalyptus.cluster.common.msgs.NcRunInstanceType;
import com.eucalyptus.cluster.common.msgs.NcStartInstanceResponseType;
import com.eucalyptus.cluster.common.msgs.NcStartInstanceType;
import com.eucalyptus.cluster.common.msgs.NcStartNetworkResponseType;
import com.eucalyptus.cluster.common.msgs.NcStartNetworkType;
import com.eucalyptus.cluster.common.msgs.NcStopInstanceResponseType;
import com.eucalyptus.cluster.common.msgs.NcStopInstanceType;
import com.eucalyptus.cluster.common.msgs.NcTerminateInstanceResponseType;
import com.eucalyptus.cluster.common.msgs.NcTerminateInstanceType;
import com.eucalyptus.cluster.common.msgs.NetConfigType;
import com.eucalyptus.cluster.common.msgs.SensorsResourceType;
import com.eucalyptus.cluster.common.msgs.VirtualBootRecordType;
import com.eucalyptus.cluster.common.msgs.VirtualMachineType;
import com.eucalyptus.cluster.common.msgs.VolumeType;
import com.eucalyptus.cluster.service.NodeService;
import com.eucalyptus.cluster.service.node.ClusterNode;
import com.eucalyptus.cluster.service.vm.VmInfo;
import com.eucalyptus.cluster.service.vm.VmInterface;
import com.eucalyptus.cluster.service.vm.VmVolumeAttachment;
import com.eucalyptus.compute.common.internal.vm.VmInstance;
import com.eucalyptus.compute.common.internal.vm.VmInstances;
import com.eucalyptus.compute.common.internal.vpc.NetworkInterface;
import com.eucalyptus.compute.common.internal.vpc.NetworkInterfaceAssociation;
import com.eucalyptus.compute.common.internal.vpc.NetworkInterfaceAttachment;
import com.eucalyptus.entities.Entities;
import com.eucalyptus.entities.TransactionResource;
import com.eucalyptus.util.FUtils;
import com.eucalyptus.util.async.CheckedListenableFuture;
import com.eucalyptus.util.async.Futures;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.BaseEncoding;
import javaslang.collection.Stream;
import javaslang.control.Option;

/**
 *
 */
public class FakeNodeService implements NodeService {

    private final ClusterNode node;
    private final FakeNodeState state;

    public FakeNodeService(final ClusterNode node, final boolean allowReload) {
        this.node = node;
        this.state = new FakeNodeState();
        if (allowReload && node.getVms().isEmpty()) {
            reload();
        }
        node.getVms().forEach(state::extant);
    }

    @Override
    public NcAssignAddressResponseType assignAddress(final NcAssignAddressType request) {
        state.assignAddress(request.getInstanceId(), request.getPublicIp());
        return request.getReply();
    }

    @Override
    public NcAttachNetworkInterfaceResponseType attachNetworkInterface(final NcAttachNetworkInterfaceType request) {
        return request.getReply();
    }

    @Override
    public NcAttachVolumeResponseType attachVolume(final NcAttachVolumeType request) {
        final NcAttachVolumeResponseType reply = request.getReply();
        state.vm(request.getInstanceId()).forEach(vm -> {
            final VmVolumeAttachment fakeVolumeAttachment = new VmVolumeAttachment(System.currentTimeMillis(),
                    request.getVolumeId(), request.getLocalDev(), request.getRemoteDev(), "attached");
            vm.getVolumeAttachments().put(request.getVolumeId(), fakeVolumeAttachment);
        });
        return reply;
    }

    @Override
    public NcBroadcastNetworkInfoResponseType broadcastNetworkInfo(final NcBroadcastNetworkInfoType request) {
        return request.getReply();
    }

    @Override
    public NcBundleInstanceResponseType bundleInstance(final NcBundleInstanceType request) {
        return request.getReply();
    }

    @Override
    public NcBundleRestartInstanceResponseType bundleRestartInstance(final NcBundleRestartInstanceType request) {
        return request.getReply();
    }

    @Override
    public NcCancelBundleTaskResponseType cancelBundleTask(final NcCancelBundleTaskType request) {
        return request.getReply();
    }

    @Override
    public NcCreateImageResponseType createImage(final NcCreateImageType request) {
        return request.getReply();
    }

    @Override
    public NcDescribeInstancesResponseType describeInstances(final NcDescribeInstancesType request) {
        final NcDescribeInstancesResponseType reply = request.getReply();
        final ArrayList<InstanceType> instances = Lists.newArrayList();
        state.cleanup();
        node.getVms().forEach(vm -> {
            final Option<FakeNodeVmInfo> nodeVm = state.vm(vm.getId());
            if (nodeVm.isEmpty())
                return;

            final VirtualMachineType vmType = new VirtualMachineType();
            vmType.setName(vm.getInstanceTypeName());
            vmType.setCores(vm.getInstanceTypeCores());
            vmType.setDisk(vm.getInstanceTypeDisk());
            vmType.setMemory(vm.getInstanceTypeMemory());
            nodeVm.get().getVolumeAttachments().values().forEach(attachment -> {
                final VirtualBootRecordType virtualBootRecord = new VirtualBootRecordType();
                virtualBootRecord.setType("machine");
                virtualBootRecord.setFormat("none");
                virtualBootRecord.setGuestDeviceName(attachment.getDevice());
                virtualBootRecord.setSize(41126400L);
                virtualBootRecord.setId(attachment.getVolumeId());
                virtualBootRecord.setResourceLocation(attachment.getRemoteDevice());
                vmType.getVirtualBootRecord().add(virtualBootRecord);
            });

            final NetConfigType netConfig = new NetConfigType();
            netConfig.setInterfaceId(vm.getId());
            netConfig.setDevice(0);
            netConfig.setPrivateIp(vm.getPrimaryInterface().getPrivateAddress());
            netConfig.setPublicIp(
                    nodeVm.map(FakeNodeVmInfo::getPublicIp).getOrElse(vm.getPrimaryInterface().getPublicAddress()));
            netConfig.setVlan(-1);
            netConfig.setNetworkIndex(-1);

            final InstanceType instance = new InstanceType();
            instance.setReservationId(vm.getReservationId());
            instance.setInstanceId(vm.getId());
            instance.setUuid(vm.getUuid());
            instance.setUserId(vm.getOwnerId());
            instance.setOwnerId(vm.getOwnerId());
            instance.setAccountId(vm.getAccountId());
            instance.setKeyName(vm.getSshKeyValue());
            instance.setInstanceType(vmType);
            instance.setNetParams(netConfig);
            instance.setStateName(nodeVm.map(FakeNodeVmInfo::getStateName).getOrElse(vm.getState()));
            instance.setBundleTaskStateName("none");
            instance.setBundleTaskProgress(0D);
            //      instance.setExpiryTime(  );
            instance.setLaunchTime(new Date(vm.getLaunchtime()));
            instance.setLaunchIndex(String.valueOf(vm.getLaunchIndex()));
            instance.setBlkbytes(0);
            instance.setNetbytes(0);
            instance.setGuestStateName("poweredOn");
            instance.setMigrationStateName("none");
            //      instance.setMigrationSource(  );
            //      instance.setMigrationDestination(  );
            //      instance.setUserData(  );
            instance.setPlatform(vm.getPlatform());
            //      instance.setGroupNames(  );
            //      instance.setGroupIds(  );
            instance.setHasFloopy(0);
            for (VmVolumeAttachment attachment : nodeVm.get().getVolumeAttachments().values()) {
                final VolumeType volume = new VolumeType();
                volume.setVolumeId(attachment.getVolumeId());
                volume.setLocalDev(attachment.getDevice());
                volume.setRemoteDev(attachment.getRemoteDevice());
                volume.setState(attachment.getState());
                instance.getVolumes().add(volume);
            }

            instances.add(instance);
        });
        reply.setInstances(instances);
        return reply;
    }

    @Override
    public NcDescribeResourceResponseType describeResource(final NcDescribeResourceType request) {
        final NcDescribeResourceResponseType reply = request.getReply();
        reply.setIqn("iqn.1994-05.com.redhat:c7ec6fad289");
        reply.setHypervisor("KVM");
        reply.setNumberOfCoresMax(100_000);
        reply.setNumberOfCoresAvailable(100_000 - (node.getVms().size()));
        reply.setDiskSizeMax(500_000);
        reply.setDiskSizeAvailable(500_000 - (node.getVms().size()) * 5);
        reply.setMemorySizeMax(25_600_000);
        reply.setMemorySizeAvailable(25_600_000 - (node.getVms().size()));
        return reply;
    }

    @Override
    public NcDescribeSensorsResponseType describeSensors(final NcDescribeSensorsType request) {
        final NcDescribeSensorsResponseType reply = request.getReply();
        final Iterable<String> instanceIds = request.getInstanceIds();
        final int history = request.getHistorySize();
        final long interval = request.getCollectionIntervalTimeMs().longValue();

        final long currentTime = System.currentTimeMillis();
        final long mostRecentTimestamp = currentTime - (currentTime % interval);

        for (final String instanceId : instanceIds) {
            VmInfo vmInfo = null;
            for (final VmInfo fakeVmInfo : node.getVms()) {
                if (fakeVmInfo.getId().equals(instanceId)) {
                    vmInfo = fakeVmInfo;
                    break;
                }
            }
            if (vmInfo == null) {
                continue;
            }

            final long sequenceNumber = (mostRecentTimestamp - vmInfo.getLaunchtime()) / interval;
            final SensorsResourceType sensorsResource = new SensorsResourceType();
            sensorsResource.setResourceName(instanceId);
            sensorsResource.setResourceType("instance");
            sensorsResource.setResourceUuid(vmInfo.getUuid());
            for (final MetricsToFake metric : MetricsToFake.values()) {
                final MetricsResourceType metricsResource = new MetricsResourceType();
                metricsResource.setMetricName(metric.name());
                final MetricCounterType metricCounter = new MetricCounterType();
                metricCounter.setCollectionIntervalMs(interval);
                metricCounter.setType(metric.isSummation() ? "summation" : "latest");
                for (final String dimension : metric.getDimensions()) {
                    final MetricDimensionsType metricDimensions = new MetricDimensionsType();
                    metricDimensions.setDimensionName(dimension);
                    metricDimensions.setSequenceNum(sequenceNumber);
                    for (long i = Math.max(0, sequenceNumber - history); i < sequenceNumber; i++) {
                        final MetricDimensionsValuesType metricDimensionsValues = new MetricDimensionsValuesType();
                        metricDimensionsValues.setTimestamp(
                                new Date(mostRecentTimestamp - ((sequenceNumber - (i + 1)) * interval)));
                        metricDimensionsValues.setValue((i * interval) * metric.getMultipler());
                        metricDimensions.getValues().add(metricDimensionsValues);
                    }
                    metricCounter.getDimensions().add(metricDimensions);
                }
                metricsResource.getCounters().add(metricCounter);
                sensorsResource.getMetrics().add(metricsResource);
            }
            reply.getSensorsResources().add(sensorsResource);
        }
        return reply;
    }

    @Override
    public NcDetachNetworkInterfaceResponseType detachNetworkInterface(final NcDetachNetworkInterfaceType request) {
        return request.getReply();
    }

    @Override
    public NcDetachVolumeResponseType detachVolume(final NcDetachVolumeType request) {
        final NcDetachVolumeResponseType reply = request.getReply();
        state.vm(request.getInstanceId()).forEach(vm -> {
            final VmVolumeAttachment existingFakeVolumeAttachment = vm.getVolumeAttachments()
                    .get(request.getVolumeId());
            if (existingFakeVolumeAttachment != null) {
                final VmVolumeAttachment newFakeVolumeAttachment = new VmVolumeAttachment(
                        existingFakeVolumeAttachment.getAttachmentTimestamp(),
                        existingFakeVolumeAttachment.getVolumeId(), existingFakeVolumeAttachment.getDevice(),
                        existingFakeVolumeAttachment.getRemoteDevice(), "detached");
                vm.getVolumeAttachments().replace(request.getVolumeId(), existingFakeVolumeAttachment,
                        newFakeVolumeAttachment);
            }
        });
        return reply;
    }

    @Override
    public NcGetConsoleOutputResponseType getConsoleOutput(final NcGetConsoleOutputType request) {
        final NcGetConsoleOutputResponseType reply = request.getReply();
        final Option<VmInfo> vm = vm(request.getInstanceId());
        final Option<FakeNodeVmInfo> fakeVm = state.vm(request.getInstanceId());
        reply.setConsoleOutput(BaseEncoding.base64()
                .encode(("\nConsole output for fake instance " + request.getInstanceId() + "\n"
                        + vm.map(Object::toString).getOrElse("") + "\n" + fakeVm.map(Object::toString).getOrElse("")
                        + "\n").getBytes(StandardCharsets.UTF_8)));
        return reply;
    }

    @Override
    public NcMigrateInstancesResponseType migrateInstances(final NcMigrateInstancesType request) {
        return request.getReply();
    }

    @Override
    public NcModifyNodeResponseType modifyNode(final NcModifyNodeType request) {
        return request.getReply();
    }

    @Override
    public NcPowerDownResponseType powerDown(final NcPowerDownType request) {
        return request.getReply();
    }

    @Override
    public NcRebootInstanceResponseType rebootInstance(final NcRebootInstanceType request) {
        final NcRebootInstanceResponseType reply = request.getReply();
        reply.setStatus(true);
        return reply;
    }

    @Override
    public NcRunInstanceResponseType runInstance(final NcRunInstanceType request) {
        final NcRunInstanceResponseType reply = request.getReply();
        vm(request.getInstanceId()).forEach(state::extant);
        final InstanceType instanceType = new InstanceType();
        instanceType.setReservationId(request.getReservationId());
        instanceType.setInstanceId(request.getInstanceId());
        instanceType.setUuid(request.getUuid());
        instanceType.setImageId(request.getImageId());
        reply.setInstance(instanceType);
        return reply;
    }

    @Override
    public NcStartInstanceResponseType startInstance(final NcStartInstanceType request) {
        return request.getReply();
    }

    @Override
    public NcStartNetworkResponseType startNetwork(final NcStartNetworkType request) {
        return request.getReply();
    }

    @Override
    public NcStopInstanceResponseType stopInstance(final NcStopInstanceType request) {
        return request.getReply();
    }

    @Override
    public NcTerminateInstanceResponseType terminateInstance(final NcTerminateInstanceType request) {
        final NcTerminateInstanceResponseType reply = request.getReply();
        state.terminate(request.getInstanceId());
        reply.setInstanceId(request.getInstanceId());
        return reply;
    }

    @Override
    public CheckedListenableFuture<NcBroadcastNetworkInfoResponseType> broadcastNetworkInfoAsync(
            final NcBroadcastNetworkInfoType request) {
        return Futures.predestinedFuture(broadcastNetworkInfo(request));
    }

    @Override
    public CheckedListenableFuture<NcDescribeInstancesResponseType> describeInstancesAsync(
            final NcDescribeInstancesType request) {
        return Futures.predestinedFuture(describeInstances(request));
    }

    @Override
    public CheckedListenableFuture<NcDescribeResourceResponseType> describeResourceAsync(
            final NcDescribeResourceType request) {
        return Futures.predestinedFuture(describeResource(request));
    }

    @Override
    public CheckedListenableFuture<NcDescribeSensorsResponseType> describeSensorsAsync(
            final NcDescribeSensorsType request) {
        return Futures.predestinedFuture(describeSensors(request));
    }

    private Option<VmInfo> vm(final String id) {
        return Stream.ofAll(node.getVms()).find(vm -> vm.getId().equals(id));
    }

    private void reload() {
        try (final TransactionResource tx = Entities.readOnlyDistinctTransactionFor(VmInstance.class)) {
            for (final VmInstance instance : VmInstances.list(null,
                    Restrictions.and(VmInstance.criterion(VmInstance.VmStateSet.RUN.array()),
                            VmInstance.serviceTagCriterion(node.getServiceTag())),
                    Collections.emptyMap(), VmInstance.VmStateSet.RUN, false)) {

                final VmInfo fakeVmInfo = new VmInfo(instance.getInstanceId(), instance.getInstanceUuid(),
                        instance.getReservationId(), instance.getLaunchIndex(), instance.getVmType().getName(),
                        instance.getVmType().getCpu(), instance.getVmType().getDisk(),
                        instance.getVmType().getMemory(), instance.getPlatform(),
                        instance.getKeyPair().getPublicKey(), instance.getCreationTimestamp().getTime(), "Extant",
                        instance.getLastUpdateTimestamp().getTime(),
                        instance.getNetworkInterfaces().stream().findFirst().map(NetworkInterface::getDisplayName)
                                .<String>orElse(null),
                        instance.getNetworkInterfaces().stream().findFirst()
                                .map(ni -> ni.getAttachment().getAttachmentId()).orElse(null),
                        instance.getMacAddress(), instance.getPrivateAddress(), null, instance.getOwnerUserId(),
                        instance.getOwnerAccountNumber(), instance.getVpcId());

                instance.getNetworkInterfaces().stream().skip(1).collect(Collectors.toMap(
                        FUtils.chain(NetworkInterface::getAttachment, NetworkInterfaceAttachment::getDeviceIndex),
                        ni -> new VmInterface(ni.getDisplayName(), ni.getAttachment().getAttachmentId(),
                                ni.getAttachment().getDeviceIndex(), ni.getMacAddress(), ni.getPrivateIpAddress(),
                                Optional.ofNullable(ni.getAssociation())
                                        .map(NetworkInterfaceAssociation::getPublicIp).<String>orElse(null)),
                        (v1, v2) -> v1, fakeVmInfo::getSecondaryInterfaceAttachments));

                for (com.eucalyptus.compute.common.internal.vm.VmVolumeAttachment attachment : Iterables.concat(
                        instance.getBootRecord().getPersistentVolumes(),
                        instance.getTransientVolumeState().getAttachments())) {
                    fakeVmInfo.getVolumeAttachments().put(attachment.getVolumeId(),
                            new VmVolumeAttachment(attachment.getAttachTime().getTime(), attachment.getVolumeId(),
                                    attachment.getDevice(), attachment.getRemoteDevice(), "attached"));
                }
                node.vm(fakeVmInfo);
            }
        }
    }

    private enum MetricsToFake {
        CPUUtilization(0.25, "default"), DiskReadBytes(1, "ephemeral0", "vda"), DiskReadOps(0.2, "ephemeral0",
                "vda"), DiskWriteBytes(0.5, "ephemeral0", "vda"), DiskWriteOps(0.1, "ephemeral0",
                        "vda"), NetworkIn(2, "total"), NetworkInExternal(1, "default"), NetworkOut(4,
                                "total"), NetworkOutExternal(3, "default"), NetworkPacketsIn(1,
                                        "total"), NetworkPacketsOut(2, "total"), VolumeQueueLength(0, false,
                                                "ephemeral0", "vda"), VolumeTotalReadTime(0.0001, "ephemeral0",
                                                        "vda"), VolumeTotalWriteTime(0.0002, "ephemeral0", "vda"),;

        private final double multipler;
        private final boolean summation;
        private final List<String> dimensions;

        MetricsToFake(double multiplier, boolean summation, String... dimensions) {
            this.multipler = multiplier;
            this.summation = summation;
            this.dimensions = ImmutableList.copyOf(dimensions);
        }

        MetricsToFake(double multiplier, String... dimensions) {
            this(multiplier, true, dimensions);
        }

        public double getMultipler() {
            return multipler;
        }

        public boolean isSummation() {
            return summation;
        }

        public List<String> getDimensions() {
            return dimensions;
        }
    }
}