/*
* Copyright (c) Fabien Hermenier
*
* This file is part of Entropy.
*
* Entropy 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.
*
* Entropy 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 Entropy. If not, see <http://www.gnu.org/licenses/>.
*/
package gipad.configuration.configuration;
import gipad.tools.ManagedElementList;
import gipad.tools.SimpleManagedElementList;
/**
* Common tools related to Configuration
*
* @author Fabien Hermenier
*/
public final class ConfigurationUtils {
public static enum State {
/**
* Specify running virtual machines.
*/
Runnings,
/**
* Specify sleeping virtual machines.
*/
Sleepings
}
/**
* Utility class. No instantiation.
*/
private ConfigurationUtils() {
}
/**
* Return the subset of online nodes that host at least one virtual machines
*
* @param cfg
* the configuration to browse
* @param wrt
* the hosting type to consider
* @return subset of node that may be empty
*/
/*public static ManagedElementList<Node> usedNodes(Configuration cfg, EnumSet<State> wrt) {
ManagedElementList<Node> ns = new SimpleManagedElementList<Node>();
if (wrt.contains(State.Runnings)) {
for (VirtualMachine vm : cfg.getRunnings()) {
ns.add(cfg.getLocation(vm));
}
}
if (wrt.contains(State.Sleepings)) {
for (VirtualMachine vm : cfg.getSleepings()) {
ns.add(cfg.getLocation(vm));
}
}
return ns;
}*/
/**
* Return the subset of online nodes that does not host virtual machines.
*
* @param cfg
* the configuration to browse
* @param wrt
* the hosting type to consider
* @return a subset of node that may be empty
*/
/*public static ManagedElementList<Node> unusedNodes(Configuration cfg, State wrt) {
ManagedElementList<Node> ns = new SimpleManagedElementList<Node>();
for (Node n : cfg.getOnlines()) {
if (wrt == State.Runnings && cfg.getRunnings(n).size() == 0) {
ns.add(n);
}
if (wrt == State.Sleepings && cfg.getSleepings(n).size() == 0) {
ns.add(n);
}
}
return ns;
}*/
/**
* Return the subset of nodes that are currently overloaded. A node is
* considered as overloaded if the total memory or CPU currently consumed by
* the virtual machines it hosts is greater than its memory or CPU capacity.
*
* @return a subset of nodes, may be empty.
*/
public static ManagedElementList<Node> getOverloadedNodes(Configuration cfg) {
ManagedElementList<Node> nodes = new SimpleManagedElementList<Node>();
for (Node n : cfg.getOnlines()) {
if(isOverloaded(cfg, n)){
nodes.add(n);
break;
}
}
return nodes;
}
public static boolean isOverloaded(Configuration cfg, Node n){
long[] coreCapa = n.getCoresCapacities();
long[] memCapa = n.getMemCapacities();
long[] networkInCapa = n.getNetworkInCapacities();
long[] networkOutCapa = n.getNetworkOutCapacities();
for (VirtualMachine vm : cfg.getRunnings(n)) {
coreCapa = computeFreeUsage(coreCapa, vm.getCoreUsage());
memCapa = computeFreeUsage(memCapa, vm.getCoreUsage());
networkInCapa = computeFreeUsage(networkInCapa, vm.getCoreUsage());
networkOutCapa = computeFreeUsage(networkOutCapa, vm.getCoreUsage());
if (isResourceViolated(coreCapa) || isResourceViolated(memCapa) ||
isResourceViolated(networkInCapa) || isResourceViolated(networkOutCapa)) {
return true;
}
}
return true;
}
public static long[] computeFreeUsage(long[] capacities, long[] consumption){
long[] freeUsageLeft = capacities.clone();
for(int i=0; i<capacities.length && i<consumption.length; i++){
freeUsageLeft[i] -= consumption[i];
}
return freeUsageLeft;
}
public static boolean isResourceViolated(long[] resource){
for (int i = 0; i < resource.length; i++) {
if(resource[i] < 0)
return false;
}
return true;
}
/**
* Return the subset of nodes that can not satisfy the resource demand of
* the VMs. A node is considered as overloaded if the total memory or CPU
* demand of the virtual machines it hosts is greater than its memory or CPU
* capacity.
*
* @return a subset of nodes, may be empty.
*/
/*
* public static ManagedElementList<Node>
* futureOverloadedNodes(Configuration cfg) { ManagedElementList<Node> nodes
* = new SimpleManagedElementList<Node>(); for (Node n : cfg.getOnlines()) {
* int sumCpuCapa = 0; for(Cpu cpu : n.hardwareSpecification().cpus()){
* sumCpuCapa += cpu.getCpuCapacity(); } double memCapa =
* n.hardwareSpecification().memory().capacity(); int networkCapa = 0;
* for(NetworkInterface network :
* n.networkSpecification().networkInterfaces()){ networkCapa +=
* network.maxBandwidth(); } for (VirtualMachine vm : cfg.getRunnings(n)) {
* sumCpuCapa -= vm.hardwareSpecification().cpus().get(0); memCapa -=
* vm.getMemoryDemand(); networkCapa -= vm; vm. if (cpuCapa < 0 || memCapa <
* 0) { nodes.add(n); break; } } } return nodes; }
*/
/**
* Check whether the current configuration is overloaded or not.
*
* @return true if at least one node is overloaded
*/
/*
* public static boolean isCurrentlyViable(Configuration cfg) { for (Node n
* : cfg.getOnlines()) { int cpuCapa = n.getCPUCapacity(); int memCapa =
* n.getMemoryCapacity(); for (VirtualMachine vm : cfg.getRunnings(n)) {
* cpuCapa -= vm.getCPUConsumption(); memCapa -= vm.getMemoryConsumption();
* if (cpuCapa < 0 || memCapa < 0) { return false; } } } return true; }
*/
/**
* Check whether the current configuration will be overloaded once all the
* virtual machines will want to uses their demanded resources.
*
* @return true if at least one node is overloaded
*/
/*
* public static boolean isFutureViable(Configuration cfg) { for (Node n :
* cfg.getOnlines()) { int cpuCapa = n.getCPUCapacity(); int memCapa =
* n.getMemoryCapacity(); for (VirtualMachine vm : cfg.getRunnings(n)) {
* cpuCapa -= vm.getCPUDemand(); memCapa -= vm.getMemoryDemand(); if
* (cpuCapa < 0 || memCapa < 0) { return false; } } } return true; }
*/
/**
* Compute a sub configuration that only consider a subset of nodes and
* virtual machines All the virtual machines must be hosted on the subset of
* nodes or be in a waiting state
*
* @param vms
* the subset of virtual machines
* @param nodes
* the subset of nodes
* @return a new configuration is the operation succeed, {@code null}
* otherwise
*/
/*public static Configuration subConfiguration(Configuration cfg,
ManagedElementList<VirtualMachine> vms, ManagedElementList<Node> nodes)
throws ConfigurationsException {
Configuration sub = new SimpleConfiguration();
ManagedElementList<VirtualMachine> cpy = vms.clone();
for (Node n : nodes) {
if (cfg.isOffline(n)) {
sub.addOffline(n);
} else if (cfg.isOnline(n)) {
sub.addOnline(n);
ManagedElementList<VirtualMachine> runs = cfg.getRunnings(n);
ManagedElementList<VirtualMachine> sleeps = cfg.getSleepings(n);
if (!cpy.containsAll(runs)) {
throw new ConfigurationsException(cfg, "VMs on node " + n.name() + "(" + runs
+ ") does not only contains VMs in " + cpy);
}
if (!cpy.containsAll(sleeps)) {
throw new ConfigurationsException(cfg, "VMs on node " + n.name() + "(" + sleeps
+ ") does not only contains VMs in " + cpy);
}
cpy.removeAll(runs);
cpy.removeAll(sleeps);
for (VirtualMachine vm : runs) {
sub.setRunOn(vm, n);
}
for (VirtualMachine vm : sleeps) {
sub.setSleepOn(vm, n);
}
} else {
throw new ConfigurationsException(cfg, "Unknown node " + n.getName());
}
}
if (!cfg.getWaitings().isEmpty() && !cfg.getWaitings().containsAll(cpy)) {
throw new ConfigurationsException(cfg, "Waiting VMs (" + cfg.getWaitings()
+ ") does not only contains VMs in " + cpy);
}
for (VirtualMachine vm : cpy) {
sub.addWaiting(vm);
}
return sub;
}*/
/**
* Merge a list of Configurations. The set of virtual machines in the
* configuration is supposed to be disjoint while if some nodes are presents
* in different configurations, there state have to be the same
*
* @param cfgs
* the list of configurations to merge
* @return the resulting configuration
* @throws ConfigurationsException
* if configurations are conflicting between each other
*/
/*public static Configuration merge(List<Configuration> cfgs) throws ConfigurationsException {
return merge(cfgs.toArray(new Configuration[cfgs.size()]));
}*/
/**
* Merge a list of Configurations. The set of virtual machines in the
* configuration is supposed to be disjoint while if some nodes are presents
* in different configurations, there state have to be the same
*
* @param cfgs
* the list of configurations to merge
* @return the resulting configuration
* @throws ConfigurationsException
* if configurations are conflicting between each other
*/
/*public static Configuration merge(Configuration... cfgs) throws ConfigurationsException {
Configuration res = new SimpleConfiguration();
for (Configuration c : cfgs) {
if (!Collections.disjoint(c.getAllVirtualMachines(), res.getAllVirtualMachines())) {
throw new ConfigurationsException(c,
"Set of virtual machines are not disjoint with already merged configurations");
}
for (Node n : c.getOfflines()) {
if (res.isOnline(n)) {
throw new ConfigurationsException(c, "Conflicting state for node '" + n.name() + "'");
}
if (!res.isOffline(n)) {
res.addOffline(n);
}
}
for (Node n : c.getOnlines()) {
if (res.isOffline(n)) {
throw new ConfigurationsException(c, "Conflicting state for node '" + n.name() + "'");
}
if (!res.isOnline(n)) {
res.addOnline(n);
}
for (VirtualMachine vm : c.getRunnings(n)) {
if (!res.setRunOn(vm, n)) {
throw new ConfigurationsException(c, "Unable to place running '" + vm.name()
+ "' on '" + n.name() + "'");
}
}
for (VirtualMachine vm : c.getSleepings(n)) {
if (!res.setSleepOn(vm, n)) {
throw new ConfigurationsException(c, "Unable to place sleeping '" + vm.name()
+ "' on '" + n.name() + "'");
}
}
}
for (VirtualMachine vm : c.getWaitings()) {
res.addWaiting(vm);
}
}
return res;
}*/
}