Package com.abiquo.hypervisor.model.builder

Source Code of com.abiquo.hypervisor.model.builder.DiskSequenceToBusAndUnitNumber$DiskAddress

/**
* Copyright (C) 2008 - Abiquo Holdings S.L. All rights reserved.
*
* Please see /opt/abiquo/tomcat/webapps/legal/ on Abiquo server
* or contact contact@abiquo.com for licensing information.
*/
package com.abiquo.hypervisor.model.builder;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.abiquo.hypervisor.model.DiskDescription.DiskControllerType;
import com.abiquo.hypervisor.model.SecondaryDiskStandard;
import com.abiquo.hypervisor.model.SecondaryDiskStateful;
import com.abiquo.hypervisor.model.VirtualMachineDefinition;
import com.abiquo.hypervisor.model.VirtualMachineDefinition.SecondaryDisks;
import com.abiquo.hypervisor.model.builder.BuilderException.VirtualMachineDescriptionBuilderError;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;

public class DiskSequenceToBusAndUnitNumber
{
    private final static Logger LOG = LoggerFactory.getLogger(DiskSequenceToBusAndUnitNumber.class);

    /**
     * Set the bus and unit number for all the Disks in the virtual machine definition. Including
     * PrimaryDisk, SecondaryStandardDisk, SecondaryStatefulDisk and CDRom.
     * <ul>
     * <li>Primary disk always sequence = 0 => (0:0) (other secondaries disk also uses 0)</li>
     * <li>CD-ROM always IDE and with higher priority of other secondary disks</li>
     * <li>Sequence numbers no need to be consecutive. Then need all the sequences to select the
     * unit numbers, by ordering the sequence numbers in groups of controller types (one ordered
     * list for IDE and other for SCSI), then enumerate following the controller type rules (SCSI :
     * 0:x and IDE only 2 bus with 2 units each)</li>
     * <li>HD and volumes CAN NOT share sequences</li>
     * </ul>
     */
    public static VirtualMachineDefinition numerateBusAndUnitBasedOnSequences(
        final VirtualMachineDefinition vmdef)
    {

        final List<SequenceAndController> sequences = getSequencesWithControllerType(vmdef);

        for (DiskAddress address : numerateBusAndUnitBasedOnSequence(sequences,
            DiskControllerType.IDE == vmdef.getPrimaryDisk().getDiskControllerType(),
            vmdef.isCdromSet()))
        {
            if (-1 == address.sequence) // has cdrom set
            {
                LOG.debug("CD-ROM will use {}:{}", address.busNumber, address.unitNumber);

                vmdef.getCdrom().setBusNumber(address.busNumber);
                vmdef.getCdrom().setUnitNumber(address.unitNumber);
            }
            else
            {
                LOG.debug("Secondary Disk with sequence {} will use {} ", address.sequence,
                    String.format("%d:%d", address.busNumber, address.unitNumber));

                vmdef.getSecondaryDiskBySequence(address.sequence).//
                    setBusAndUnitNumber(address.busNumber, address.unitNumber);
            }
        }

        if (vmdef.getPrimaryDisk().isStandard())
        {
            vmdef.getPrimaryDisk().getDiskStandard().setBusAndUnitNumber(0, 0);
        }
        else
        {
            vmdef.getPrimaryDisk().getDiskStateful().setBusAndUnitNumber(0, 0);
        }

        // Make sure the definition has the disk lists sorted by sequence
        // XXX: There are separate lists for the standard and the stateful disks although they share
        // the sequence. This is something the hypervisor plugins must take into account to respect
        // the attachment order.
        sortSecondaryStandardDisksBySequence(vmdef);
        sortSecondaryStatefulDisksBySequence(vmdef);

        return vmdef;
    }

    private static List<SequenceAndController> getSequencesWithControllerType(
        final VirtualMachineDefinition vmdef)
    {
        final List<SequenceAndController> sequences = new LinkedList<SequenceAndController>();

        final SecondaryDisks secondaries = vmdef.getSecondaryDisks();

        for (SecondaryDiskStandard standard : secondaries.getStandardDisks())
        {
            sequences.add(new SequenceAndController(standard.getSequence(), standard
                .getDiskControllerType()));
        }
        for (SecondaryDiskStateful stateful : secondaries.getStatefulDisks())
        {
            sequences.add(new SequenceAndController(stateful.getSequence(), stateful
                .getDiskControllerType()));
        }

        checkNoSequenceRepetition(sequences);

        return sequences;
    }

    private static List<DiskAddress> numerateBusAndUnitBasedOnSequence(
        final List<SequenceAndController> sequences, final boolean primaryIde, final boolean isCdrom)
    {
        if (isCdrom)
        {
            // setting CD-ROM with sequence -1
            // used by primary disk, convention done in #numerateBusAndUnitBasedOnSequences)
            sequences.add(new SequenceAndController(-1, DiskControllerType.IDE));
        }

        ImmutableList<SequenceAndController> sortedIdes =
            ImmutableList.copyOf(Ordering.natural().onResultOf(sequenceOrdering)
                .sortedCopy(Iterables.filter(sequences, new Predicate<SequenceAndController>()
                {
                    @Override
                    public boolean apply(final SequenceAndController input)
                    {
                        return DiskControllerType.IDE == input.controller;
                    }
                })));

        ImmutableList<SequenceAndController> sortedScsi =
            ImmutableList.copyOf(Ordering.natural().onResultOf(sequenceOrdering)
                .sortedCopy(Iterables.filter(sequences, new Predicate<SequenceAndController>()
                {
                    @Override
                    public boolean apply(final SequenceAndController input)
                    {
                        return DiskControllerType.SCSI == input.controller;
                    }
                })));

        List<DiskAddress> addresses = new LinkedList<DiskAddress>();

        Integer regularSequence = primaryIde ? 1 : 0;
        for (SequenceAndController seq : sortedIdes)
        {
            // FIXME now is controlled in tarantino in order to avoid a transaction mess in
            // TarantinoService
            // if (regularSequence > 3)
            // {
            // throw new BuilderException(VirtualMachineDescriptionBuilderError.IDE_FULL);
            // }

            addresses.add(new DiskAddress(seq.sequence, //
                regularSequence / 2,
                regularSequence % 2));
            regularSequence++;
        }

        //

        regularSequence = primaryIde ? 0 : 1;
        for (SequenceAndController seq : sortedScsi)
        {
            addresses.add(new DiskAddress(seq.sequence, 0, regularSequence));
            regularSequence++;
        }

        return addresses;
    }

    private static final Function<SequenceAndController, Integer> sequenceOrdering =
        new Function<SequenceAndController, Integer>()
        {
            @Override
            public Integer apply(final SequenceAndController from)
            {
                return from.sequence;
            }
        };

    private static void checkNoSequenceRepetition(final List<SequenceAndController> sequences)
    {
        HashSet<Integer> setseq = new HashSet<Integer>();
        for (SequenceAndController s : sequences)
        {
            if (!setseq.add(s.sequence))
            {
                throw new BuilderException(VirtualMachineDescriptionBuilderError.SEQUENCE_REPETITION);
            }
        }
    }

    private static void sortSecondaryStandardDisksBySequence(final VirtualMachineDefinition vmdef)
    {
        Collections.sort(vmdef.getSecondaryDisks().getStandardDisks(),
            new Comparator<SecondaryDiskStandard>()
            {
                @Override
                public int compare(final SecondaryDiskStandard disk1,
                    final SecondaryDiskStandard disk2)
                {
                    return disk1.getSequence() - disk2.getSequence();
                }
            });
    }

    private static void sortSecondaryStatefulDisksBySequence(final VirtualMachineDefinition vmdef)
    {
        Collections.sort(vmdef.getSecondaryDisks().getStatefulDisks(),
            new Comparator<SecondaryDiskStateful>()
            {
                @Override
                public int compare(final SecondaryDiskStateful disk1,
                    final SecondaryDiskStateful disk2)
                {
                    return disk1.getSequence() - disk2.getSequence();
                }
            });
    }

    /**
     * Holder classes
     */

    public static class SequenceAndController
    {
        public final Integer sequence;

        public final DiskControllerType controller;

        public SequenceAndController(final Integer sequence, final DiskControllerType controller)
        {
            super();
            this.sequence = sequence;
            this.controller = controller;
        }
    }

    public static class DiskAddress
    {
        public final Integer sequence;

        public final Integer busNumber;

        public final Integer unitNumber;

        public DiskAddress(final Integer sequence, final Integer busNumber, final Integer unitNumber)
        {
            super();
            this.sequence = sequence;
            this.busNumber = busNumber;
            this.unitNumber = unitNumber;
        }
    }
}
TOP

Related Classes of com.abiquo.hypervisor.model.builder.DiskSequenceToBusAndUnitNumber$DiskAddress

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.