
com.aoindustries.aoserv.master.cluster.OriginalClusterOptimizer Maven / Gradle / Ivy
/*
* aoserv-master - Master server for the AOServ Platform.
* Copyright (C) 2007-2013, 2019, 2020 AO Industries, Inc.
* [email protected]
* 7262 Bull Pen Cir
* Mobile, AL 36695
*
* This file is part of aoserv-master.
*
* aoserv-master is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* aoserv-master 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with aoserv-master. If not, see .
*/
package com.aoindustries.aoserv.master.cluster;
import com.aoindustries.lang.Strings;
import com.aoindustries.sql.SQLUtility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Finds the optimal mapping of virtual machines to physical resources to balance customer needs and redundant resources.
*
*
* - TODO: Provide separate control over secondary processor type, currently only secondary architecture and number of cores are considered.
* - TODO: Have separate core count and CPU weight. Cores<=count on box, sum of primary weight <= # of cores on box, each virtualServer adds cores*weight to overall weight.
* - TODO: Make sure can actually map extents and spindle counts to drives.
* - TODO: If two virtual servers are interchangeable, don't try both combinations - implications?
*
*
* @author AO Industries, Inc.
*/
public final class OriginalClusterOptimizer {
private static final int EXTENTS_SIZE = 33554432;
private enum Rack {
FC_9_07,
FC_9_14,
FC_9_17,
KC
}
private enum ProcessorType {
P4,
P4_XEON,
CORE,
CORE2,
XEON_LV
}
private enum ProcessorArchitecture {
I686,
X86_64
}
private enum DiskType {
RAID1_7200,
RAID1_10000,
RAID5_10000,
RAID1_15000
}
private enum SkipType {
PRIMARY_PROCESSOR_MISMATCH,
PRIMARY_CORES_EXCEEDED,
PRIMARY_RAM_EXCEEDED,
PRIMARY_PLUS_SECONDARY_RAM_EXCEEDED,
PRIMARY_PLUS_SECONDARY_DISK_EXTENTS_EXCEEDED,
PRIMARY_PLUS_SECONDARY_DISK_ARRAYS_EXCEEDED,
SECONDARY_PROCESSOR_MISMATCH,
SECONDARY_CORES_EXCEEDED,
SECONDARY_RAM_EXCEEDED,
SECONDARY_DISK_EXTENTS_EXCEEDED,
SECONDARY_DISK_ARRAYS_EXCEEDED
;
public long counter = 0;
}
private static final DiskType[] diskTypes = DiskType.values();
private static class Disk {
private final String device;
private final DiskType diskType;
private final int extents;
private Disk(String device, DiskType diskType, int extents) {
this.device = device;
this.diskType = diskType;
this.extents = extents;
}
}
private static class Host implements Comparable {
private final String hostname;
private final Rack rack;
private final int ram;
private final ProcessorType processorType;
private final ProcessorArchitecture processorArchitecture;
private final int processorSpeed;
private final int processorCores;
private final Disk[] disks;
private Host(String hostname, Rack rack, int ram, ProcessorType processorType, ProcessorArchitecture processorArchitecture, int processorSpeed, int processorCores, Disk[] disks) {
this.hostname = hostname;
this.rack = rack;
this.ram = ram;
this.processorType = processorType;
this.processorArchitecture = processorArchitecture;
this.processorSpeed = processorSpeed;
this.processorCores = processorCores;
this.disks = disks;
}
/**
* Sorts from smallest to biggest. The combination of sorting servers from smallest to biggest and virtual servers
* from biggest to smallest causes the tightest fit of big virtual servers into the smallest possible server. This
* results in the smallest skip/map ratio (and hopefully quicker finding of optimal layouts).
*/
@Override
public int compareTo(Host other) {
if(ramother.ram) return 1;
return processorCores-other.processorCores;
}
}
private static class VirtualDisk {
private final String device;
private final int extents;
private final DiskType primaryDiskType;
private final float primaryAllocation;
private final DiskType secondaryDiskType;
private final float secondaryAllocation;
private VirtualDisk(
String device,
int extents,
DiskType primaryDiskType,
float primaryAllocation,
DiskType secondaryDiskType,
float secondaryAllocation
) {
this.device = device;
this.extents = extents;
this.primaryDiskType = primaryDiskType;
this.primaryAllocation = primaryAllocation;
this.secondaryDiskType = secondaryDiskType;
this.secondaryAllocation = secondaryAllocation;
}
}
private static class VirtualServer implements Comparable {
private final String hostname;
private final int minimumPrimaryRam;
private final int minimumSecondaryRam;
private final ProcessorType minimumProcessorType;
private final ProcessorArchitecture requiredProcessorArchitecture;
private final int minimumProcessorSpeed;
private final float minimumProcessorCores;
private final VirtualDisk[] virtualDisks;
private VirtualServer(
String hostname,
int minimumPrimaryRam,
int minimumSecondaryRam,
ProcessorType minimumProcessorType,
ProcessorArchitecture requiredProcessorArchitecture,
int minimumProcessorSpeed,
float minimumProcessorCores,
VirtualDisk[] virtualDisks
) {
this.hostname = hostname;
this.minimumPrimaryRam = minimumPrimaryRam;
this.minimumSecondaryRam = minimumSecondaryRam;
this.minimumProcessorType = minimumProcessorType;
this.requiredProcessorArchitecture = requiredProcessorArchitecture;
this.minimumProcessorSpeed = minimumProcessorSpeed;
this.minimumProcessorCores = minimumProcessorCores;
this.virtualDisks = virtualDisks;
}
/**
* Sorts from biggest to smallest.
*/
@Override
public int compareTo(VirtualServer other) {
if(minimumPrimaryRamother.minimumPrimaryRam) return -1;
return Float.compare(other.minimumProcessorCores, minimumProcessorCores);
}
}
/**
* Need to load this directly from the servers.
*/
private static List getServers() {
List servers = new ArrayList<>();
servers.add(
new Host(
"gw1.fc.aoindustries.com",
Rack.FC_9_07,
2048,
ProcessorType.P4,
ProcessorArchitecture.I686,
2800,
2,
new Disk[] {
new Disk("/dev/md0", DiskType.RAID1_7200, 2044),
new Disk("/dev/md4", DiskType.RAID1_7200, 2044)
}
)
);
servers.add(
new Host(
"xen907-1.fc.aoindustries.com",
Rack.FC_9_07,
16384,
ProcessorType.XEON_LV,
ProcessorArchitecture.X86_64,
2000,
8,
new Disk[] {
new Disk("/dev/sde1", DiskType.RAID1_7200, 7450),
new Disk("/dev/sdf1", DiskType.RAID1_7200, 7450),
new Disk("/dev/sdg1", DiskType.RAID1_7200, 7450),
new Disk("/dev/sdh1", DiskType.RAID1_7200, 7450),
new Disk("/dev/sdi1", DiskType.RAID1_7200, 7450*2), // TODO: These are not purchased yet - estimated size
new Disk("/dev/md3", DiskType.RAID1_15000, 4375)
}
)
);
servers.add(
new Host(
"xen907-2.fc.aoindustries.com",
Rack.FC_9_07,
2048,
ProcessorType.P4,
ProcessorArchitecture.I686,
2600,
2,
new Disk[] {
new Disk("/dev/md1", DiskType.RAID1_7200, 7112),
new Disk("/dev/md2", DiskType.RAID1_7200, 7139),
new Disk("/dev/md5", DiskType.RAID1_7200, 4769)
}
)
);
servers.add(
new Host(
"xen907-5.fc.aoindustries.com",
Rack.FC_9_07,
4096,
ProcessorType.P4,
ProcessorArchitecture.X86_64,
3400,
2,
new Disk[] {
new Disk("/dev/md3", DiskType.RAID1_7200, 2102),
new Disk("/dev/md4", DiskType.RAID1_7200, 7112)
}
)
);
servers.add(
new Host(
"gw2.fc.aoindustries.com",
Rack.FC_9_14,
2048,
ProcessorType.P4,
ProcessorArchitecture.I686,
2800,
2,
new Disk[] {
new Disk("/dev/md1", DiskType.RAID1_7200, 3236),
new Disk("/dev/md2", DiskType.RAID1_7200, 1449)
}
)
);
servers.add(
new Host(
"xen914-1.fc.aoindustries.com",
Rack.FC_9_14,
2048,
ProcessorType.P4,
ProcessorArchitecture.I686,
2800,
2,
new Disk[] {
new Disk("/dev/md1", DiskType.RAID1_7200, 2044),
new Disk("/dev/md2", DiskType.RAID1_7200, 3340)
}
)
);
servers.add(
new Host(
"xen914-2.fc.aoindustries.com",
Rack.FC_9_14,
4096,
ProcessorType.P4_XEON,
ProcessorArchitecture.I686,
2400,
4,
new Disk[] {
new Disk("/dev/md3", DiskType.RAID1_7200, 7112),
new Disk("/dev/md4", DiskType.RAID1_7200, 7112),
new Disk("/dev/md5", DiskType.RAID5_10000, 1093)
}
)
);
servers.add(
new Host(
"xen914-5.fc.lnxhosting.ca",
Rack.FC_9_14,
16384,
ProcessorType.P4_XEON,
ProcessorArchitecture.X86_64,
3200,
8,
new Disk[] {
new Disk("/dev/md3", DiskType.RAID1_7200, 7450*4), // TODO: These are not purchased yet - estimated size
new Disk("/dev/md4", DiskType.RAID1_7200, 9198),
new Disk("/dev/md5", DiskType.RAID1_7200, 9198)
}
)
);
/* powered-down after installation of xen917-5.fc.aoindustries.com
servers.add(
new Server(
"xen917-1.fc.aoindustries.com",
Rack.FC_9_17,
2048,
ProcessorType.P4,
ProcessorArchitecture.I686,
3200,
2,
new Disk[] {
new Disk("/dev/md3", DiskType.RAID1_7200, 7112),
new Disk("/dev/md4", DiskType.RAID1_7200, 7112),
new Disk("/dev/md5", DiskType.RAID1_7200, 3236)
}
)
);
*/
servers.add(
new Host(
"xen917-2.fc.aoindustries.com",
Rack.FC_9_17,
2048,
ProcessorType.P4_XEON,
ProcessorArchitecture.I686,
2667,
4,
new Disk[] {
new Disk("/dev/md3", DiskType.RAID1_7200, 2044),
new Disk("/dev/md4", DiskType.RAID1_7200, 2044)
}
)
);
servers.add(
new Host(
"xen917-3.fc.aoindustries.com",
Rack.FC_9_17,
6144,
ProcessorType.P4_XEON,
ProcessorArchitecture.X86_64,
2800,
4,
new Disk[] {
new Disk("/dev/md3", DiskType.RAID1_7200, 7112),
new Disk("/dev/md4", DiskType.RAID1_7200, 7139)
}
)
);
servers.add(
new Host(
"xen917-4.fc.aoindustries.com",
Rack.FC_9_17,
4096,
ProcessorType.CORE2,
ProcessorArchitecture.X86_64,
2130,
2,
new Disk[] {
new Disk("/dev/md3", DiskType.RAID1_10000, 1851)
}
)
);
servers.add(
new Host(
"xen917-5.fc.aoindustries.com",
Rack.FC_9_17,
16384,
ProcessorType.XEON_LV,
ProcessorArchitecture.X86_64,
2333,
8,
new Disk[] {
new Disk("/dev/sdc1", DiskType.RAID1_7200, 7450*2), // TODO: These are not purchased yet. Estimated size for the 2x500 GB for CARR
new Disk("/dev/sdd1", DiskType.RAID1_7200, 8700) // These are the internal drives - Need separate hot-swap pair
}
)
);
Collections.sort(servers);
return servers;
}
/**
* TODO: Load this directly from the database.
*/
private static List getVirtualServers() {
List virtualServers = new ArrayList<>();
virtualServers.add(
new VirtualServer(
"ao1.kc.aoindustries.com",
512,
512,
null,
null,
-1,
.0625f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .03125f)
}
)
);
virtualServers.add(
new VirtualServer(
"centos5.aoindustries.com",
256,
256,
ProcessorType.XEON_LV,
null,
-1,
.0625f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .03125f)
}
)
);
virtualServers.add(
new VirtualServer(
"centos5-build64.aoindustries.com",
256,
256,
ProcessorType.XEON_LV,
null,
-1,
.0625f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .03125f)
}
)
);
virtualServers.add(
new VirtualServer(
"daissystems.com",
1024,
1024,
null,
null,
-1,
0.5f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 4480, DiskType.RAID1_7200, .5f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"ipharos.com",
4096,
4096,
ProcessorType.XEON_LV,
null,
-1,
1.0f, // 4 * .25
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_15000, .5f, DiskType.RAID1_7200, .5f)
}
)
);
virtualServers.add(
new VirtualServer(
"db1.fc.ipharos.com",
2048, // Need 4096
2048, // Need 4096
ProcessorType.XEON_LV,
null,
2000,
3.0f, // 4 * .75 - Need 4 * 1.0
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_15000, .5f, DiskType.RAID1_7200, 1.0f) // Need to be 1792, .5, .5 once ipharos.com is gone - and secondary on 15k
}
)
);
virtualServers.add(
new VirtualServer(
"www1.fc.ipharos.com",
2048, // Need 4096
2048, // Need 4096
ProcessorType.XEON_LV,
null,
2333,
1.0f, // 4 * .25 - Need 4 * 1.0
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .5f, DiskType.RAID1_7200, .5f) // Need to be 1792, .5, .5 once ipharos.com is gone
}
)
);
virtualServers.add(
new VirtualServer(
"master.aoindustries.com",
1024,
1024,
null,
null,
-1,
.0625f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"ns1.aoindustries.com",
256,
256,
null,
null,
-1,
.0625f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .03125f)
}
)
);
virtualServers.add(
new VirtualServer(
"ns4.aoindustries.com",
256,
256,
null,
null,
-1,
.0625f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .03125f)
}
)
);
virtualServers.add(
new VirtualServer(
"w1.fc.insightsys.com",
2048,
2048,
null,
null,
-1,
.5f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_7200, 1.0f, DiskType.RAID1_7200, 1.0f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.fc.enduraquest.com",
4096,
4096,
ProcessorType.CORE2,
null,
-1,
2.0f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_10000, 1.0f, DiskType.RAID1_7200, .25f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.fc.lnxhosting.ca",
4096,
4096,
ProcessorType.P4_XEON,
ProcessorArchitecture.X86_64,
3200,
2.0f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .125f)
// new VirtualDisk("/dev/xvdb", 8064, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .03125f) // Was
}
)
);
virtualServers.add(
new VirtualServer(
"backup1.lnxhosting.ca",
512,
512,
ProcessorType.P4_XEON,
ProcessorArchitecture.X86_64,
3200,
0.5f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .125f),
new VirtualDisk("/dev/xvdb", 8064+896*4, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.fc.newmediaworks.com",
4096,
4096,
null,
null,
-1,
2.0f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_7200, 1.0f, DiskType.RAID1_7200, .25f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.fc.objectevolution.com",
1024,
1024,
null,
null,
-1,
0.5f,
new VirtualDisk[] {
// TODO: More disk I/O here
new VirtualDisk("/dev/xvda", 896*2, DiskType.RAID1_7200, .5f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.fc.showsandshoots.com",
512, // Need 1024
512, // Need 1024
null,
null,
-1,
0.5f,
new VirtualDisk[] {
// TODO: More disk I/O here
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.fc.softwaremiracles.com",
512,
512,
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .125f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.kc.aoindustries.com",
2048,
2048,
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 3584+896, DiskType.RAID1_7200, .25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.kc.artizen.com",
1024,
1024,
null,
null,
-1,
0.5f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 896, DiskType.RAID1_7200, .25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www1.nl.pertinence.net",
2048,
2048,
null,
null,
-1,
1.0f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 4480+896*2, DiskType.RAID1_7200, .25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www2.fc.newmediaworks.com",
4096,
4096,
null,
null,
-1,
2.0f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_7200, 1.0f, DiskType.RAID1_7200, .25f)
}
)
);
virtualServers.add(
new VirtualServer(
"www2.kc.aoindustries.com",
1024,
0, // Need 1024
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 2688+896, DiskType.RAID1_7200, .25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www3.kc.aoindustries.com",
1024,
0, // Need 1024
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_7200, 0.25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www4.kc.aoindustries.com",
1024,
0, // Need 1024
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 2688, DiskType.RAID1_7200, 0.25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www5.kc.aoindustries.com",
1024,
0, // Need 1024
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 2688, DiskType.RAID1_7200, 0.25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www6.kc.aoindustries.com",
1024,
0, // Need 1024
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792, DiskType.RAID1_7200, 0.25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www7.fc.aoindustries.com",
1024,
0, // Need 1024
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 1792+896, DiskType.RAID1_7200, 0.25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www8.kc.aoindustries.com",
2048,
0, // Need 2048
null,
null,
-1,
.25f,
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 2688+896, DiskType.RAID1_7200, .25f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www9.fc.aoindustries.com",
1024,
1024,
null,
null,
-1,
.25f,
new VirtualDisk[] {
// TODO: More disk +896 here
new VirtualDisk("/dev/xvda", 1792+896, DiskType.RAID1_7200, 0.125f, DiskType.RAID1_7200, .125f)
}
)
);
virtualServers.add(
new VirtualServer(
"www.keepandshare.com",
8192,
4096, // Need 8192
ProcessorType.XEON_LV,
null,
2333,
6.0f, // 8 * .75 each - Need 8 * 1.0
new VirtualDisk[] {
new VirtualDisk("/dev/xvda", 7450*2, DiskType.RAID1_7200, 1.0f, DiskType.RAID1_7200, .5f) // TODO: Estimated size
}
)
);
virtualServers.add(
new VirtualServer(
"www.swimconnection.com",
1024,
1024,
null,
null,
-1, // TODO: If possible, make this 3200, had solution at -1
1.0f,
new VirtualDisk[] {
// TODO: More disk I/O here
new VirtualDisk("/dev/xvda", 2688, DiskType.RAID1_7200, .25f, DiskType.RAID1_7200, .0625f)
}
)
);
Collections.sort(virtualServers);
return virtualServers;
}
public static void main(String[] args) {
List servers = getServers();
long totalProcessorCores = 0;
long totalRam = 0;
long totalDisk = 0;
int totalDiskArrays = 0;
for(Host server : servers) {
totalProcessorCores += server.processorCores;
totalRam += server.ram;
for(Disk disk : server.disks) {
totalDisk += disk.extents;
totalDiskArrays++;
}
}
System.out.println("Servers:");
System.out.println(" Total Processor Cores........: " + totalProcessorCores);
System.out.println(" Total RAM....................: " + totalRam + " MB (" + Strings.getApproximateSize(totalRam*1048576)+")");
System.out.println(" Total Disk Space.............: " + totalDisk + " extents (" + Strings.getApproximateSize(totalDisk*EXTENTS_SIZE)+")");
System.out.println(" Total Disk Arrays............: " + totalDiskArrays);
List virtualServers = getVirtualServers();
float totalVirtualProcessorCores = 0;
long totalMinimumRam = 0;
long totalVirtualDisk = 0;
float totalVirtualDiskArrays = 0;
for(VirtualServer virtualServer : virtualServers) {
totalVirtualProcessorCores += virtualServer.minimumProcessorCores;
totalMinimumRam += virtualServer.minimumPrimaryRam;
for(VirtualDisk virtualDisk : virtualServer.virtualDisks) {
totalVirtualDisk += virtualDisk.extents;
totalVirtualDiskArrays += virtualDisk.primaryAllocation + virtualDisk.secondaryAllocation;
}
}
System.out.println("Virtual Servers:");
System.out.println(" Total Minimum Processor Cores: " + totalVirtualProcessorCores);
System.out.println(" Total Minimum RAM............: " + totalMinimumRam + " MB (" + Strings.getApproximateSize(totalMinimumRam*1048576)+")");
System.out.println(" Total Virtual Disk Space.....: " + totalVirtualDisk + " extents (" + Strings.getApproximateSize(totalVirtualDisk*2*EXTENTS_SIZE)+")");
System.out.println(" Total Virtual Disk Arrays....: " + totalVirtualDiskArrays);
/*
* Try all permutations of mappings from virtual server to physical servers, only continuing to the next allocation
* checks if the total CPU cores, RAM, number of disk arrays, and disk extents is <= what the physical hardware provides.
* Also only map the permutations when they match minimumProcessorType, requiredProcessorArchitecture, and minimumProcessorSpeed.
* These are the quick checks that don't need to worry about the actual mappings to specific primary and secondary disk
* arrays.
*/
//System.out.println(servers.size());
//System.out.println(virtualServers.size());
System.out.println("Worst-case permutations: " + (Math.pow(servers.size(), virtualServers.size()) * Math.pow(servers.size()-1, virtualServers.size())));
int[] selectedPrimaries = new int[virtualServers.size()];
int[] selectedSecondaries = new int[virtualServers.size()];
mapServers(servers, virtualServers, selectedPrimaries, selectedSecondaries, 0);
System.out.println("Done!!! Mapped "+mapped);
}
private static long mapped=0;
private static long skipped=0;
private static long lastMapDisplayedTime = -1;
private static long callCounter = 0;
/**
* TODO: How can we optimize further knowing that multiple virtual servers have exactly the same configuration (and therefore don't affect the overall results when switched positions)
*/
private static void mapServers(List hosts, List virtualServers, int[] selectedPrimaries, int[] selectedSecondaries, int currentVirtualServer) {
final int hostsSize = hosts.size();
final int virtualServersSize = virtualServers.size();
callCounter++;
long currentTime = System.currentTimeMillis();
long timeSince = currentTime-lastMapDisplayedTime;
if(lastMapDisplayedTime==-1 || timeSince<0 || timeSince>=30000) {
if(mapped!=0 || skipped!=0) {
for(int d=0;d0) System.out.print('/');
//if(selectedPrimaries[d]<10) System.out.print('0');
System.out.print(selectedPrimaries[d]);
System.out.print('.');
//if(selectedSecondaries[d]<10) System.out.print('0');
System.out.print(selectedSecondaries[d]);
}
System.out.print(" Mapped "+mapped+", skipped "+skipped);
if(mapped!=0) System.out.print(", skip/map ratio: "+SQLUtility.formatDecimal2(skipped*100/mapped));
if(timeSince>0) System.out.print(", "+(callCounter*1000/timeSince)+" calls/sec");
System.out.println();
/*
for(SkipType skipType : SkipType.values()) {
System.out.print(skipType.name());
System.out.print(' ');
for(int c=skipType.name().length(); c<44; c++) System.out.print(' ');
System.out.println(skipType.counter);
}
*/
}
lastMapDisplayedTime = currentTime;
callCounter = 0;
}
if(currentVirtualServer==virtualServersSize) {
// Verify mapping
// TODO: Make sure that each server has at least one possible mapping of virtual disk space to physical drives (both primary and secondary)
// TODO: that provides proper disk array isolation and space allocation.
// TODO: For each server, verify that all virtual primary and secondary (per single failure) servers match requirements.
mapped++;
/*
System.out.println("Mapping found with "+skipped+" skips");
for(int hostIndex=0;hostIndex=0
) && (
virtualServer.requiredProcessorArchitecture==null
|| primaryServer.processorArchitecture==virtualServer.requiredProcessorArchitecture
) && (
virtualServer.minimumProcessorSpeed==-1
|| primaryServer.processorSpeed>=virtualServer.minimumProcessorSpeed
)
) {
selectedPrimaries[currentVirtualServer]=primaryServerIndex;
// Stop processing if primaryServer past capacity on either processor cores or RAM
float totalPrimaryServerVirtualProcessorCores = 0;
long totalPrimaryServerMinimumRam = 0;
for(int d=0;d<=currentVirtualServer;d++) {
if(selectedPrimaries[d]==primaryServerIndex) {
VirtualServer mappedVirtualServer = virtualServers.get(d);
totalPrimaryServerVirtualProcessorCores += mappedVirtualServer.minimumProcessorCores;
totalPrimaryServerMinimumRam += mappedVirtualServer.minimumPrimaryRam;
}
}
if(primaryServer.processorCores>=totalPrimaryServerVirtualProcessorCores) {
if(primaryServer.ram>=totalPrimaryServerMinimumRam) {
// Make sure that the combined primary mappings plus secondary CPU cores and RAM do not exceed the total of this machine
// for any one primary failure. The loop represents the failure of each server, one at a time.
boolean needsSecondarySkip = false;
for(int failedPrimaryServerIndex=0;failedPrimaryServerIndex=virtualServer.minimumProcessorCores) {
// Make sure that the combined primary mapping plus secondary CPU cores and RAM do not exceed the total of this machine
// for any one primary failure. The loop represents the failure of each server, one at a time.
//float totalPrimaryVirtualProcessorCores = 0;
long totalPrimaryMinimumRam = 0;
for(int g=0;g<=currentVirtualServer;g++) {
if(selectedPrimaries[g]==secondaryServerIndex) {
VirtualServer mappedVirtualServer = virtualServers.get(g);
//totalPrimaryVirtualProcessorCores += mappedVirtualServer.minimumProcessorCores;
totalPrimaryMinimumRam += mappedVirtualServer.minimumPrimaryRam;
}
}
needsSecondarySkip = false;
for(int failedPrimaryIndex=0;failedPrimaryIndex
© 2015 - 2025 Weber Informatics LLC | Privacy Policy