init
This commit is contained in:
19
src/org/cloudbus/cloudsim/sdn/Activity.java
Normal file
19
src/org/cloudbus/cloudsim/sdn/Activity.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
/**
|
||||
* Activities that can be performed by VM. (Transmission or Compute)
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public interface Activity {
|
||||
}
|
||||
24
src/org/cloudbus/cloudsim/sdn/AggregationSwitch.java
Normal file
24
src/org/cloudbus/cloudsim/sdn/AggregationSwitch.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
/**
|
||||
* Represent aggregation switch
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class AggregationSwitch extends Switch {
|
||||
|
||||
public AggregationSwitch(String name,int bw, long iops, int upports, int downports, NetworkOperatingSystem nos) {
|
||||
super(name, bw, iops, upports, downports, nos);
|
||||
}
|
||||
|
||||
}
|
||||
53
src/org/cloudbus/cloudsim/sdn/Arc.java
Normal file
53
src/org/cloudbus/cloudsim/sdn/Arc.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
/**
|
||||
* Traffic requirements between two VMs
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Arc {
|
||||
|
||||
int srcId;
|
||||
int dstId;
|
||||
int flowId;
|
||||
long requiredBandwidth;
|
||||
double requiredLatency;
|
||||
|
||||
public Arc(int srcId, int dstId, int flowId, long reqBW, double reqLatency) {
|
||||
super();
|
||||
this.srcId = srcId;
|
||||
this.dstId = dstId;
|
||||
this.flowId = flowId;
|
||||
this.requiredBandwidth = reqBW;
|
||||
this.requiredLatency = reqLatency;
|
||||
}
|
||||
|
||||
public int getSrcId() {
|
||||
return srcId;
|
||||
}
|
||||
|
||||
public int getDstId() {
|
||||
return dstId;
|
||||
}
|
||||
public int getFlowId() {
|
||||
return flowId;
|
||||
}
|
||||
|
||||
public long getBw() {
|
||||
return requiredBandwidth;
|
||||
}
|
||||
|
||||
public double getLatency() {
|
||||
return requiredLatency;
|
||||
}
|
||||
}
|
||||
341
src/org/cloudbus/cloudsim/sdn/Channel.java
Normal file
341
src/org/cloudbus/cloudsim/sdn/Channel.java
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
|
||||
/**
|
||||
* This class represents a channel for transmission of data between switches.
|
||||
* It controls sharing of available bandwidth. Relation between
|
||||
* Transmission and Channel is the same as Cloudlet and CloudletScheduler,
|
||||
* but here we consider only the time shared case, representing a shared
|
||||
* channel among different simultaneous package transmissions.
|
||||
*
|
||||
* This is logical channel. One physical link (class Link) can hold more than one logical channels (class Channel).
|
||||
* Channel is directional. It is one way.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Channel {
|
||||
private List<Node> nodes;
|
||||
private List<Link> links;
|
||||
|
||||
private double allocatedBandwidth; // Actual bandwidth allocated to the channel
|
||||
private double previousTime;
|
||||
|
||||
private LinkedList<Transmission> inTransmission;
|
||||
private LinkedList<Transmission> completed;
|
||||
|
||||
private final int srcId;
|
||||
private final int dstId;
|
||||
private final int chId;
|
||||
private final double requestedBandwidth; // Requested by user
|
||||
|
||||
public Channel(int chId, int srcId, int dstId, List<Node> nodes, List<Link> links, double bandwidth) {
|
||||
this.chId = chId;
|
||||
this.srcId = srcId;
|
||||
this.dstId = dstId;
|
||||
this.nodes = nodes;
|
||||
this.links = links;
|
||||
this.allocatedBandwidth = bandwidth;
|
||||
this.requestedBandwidth = bandwidth;
|
||||
this.inTransmission = new LinkedList<Transmission>();
|
||||
this.completed = new LinkedList<Transmission>();
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
// Assign BW to all links
|
||||
for(int i=0; i<nodes.size()-1; i++) {
|
||||
Node from = nodes.get(i);
|
||||
Link link = links.get(i);
|
||||
|
||||
link.addChannel(from, this);
|
||||
|
||||
from.updateNetworkUtilization();
|
||||
}
|
||||
nodes.get(nodes.size()-1).updateNetworkUtilization();
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
// Assign BW to all links
|
||||
for(int i=0; i<nodes.size()-1; i++) {
|
||||
Link link = links.get(i);
|
||||
|
||||
link.removeChannel(this);
|
||||
|
||||
Node node = nodes.get(i);
|
||||
node.updateNetworkUtilization();
|
||||
}
|
||||
nodes.get(nodes.size()-1).updateNetworkUtilization();
|
||||
}
|
||||
|
||||
private double getLowestSharedBandwidth() {
|
||||
// Get the lowest bandwidth along links in the channel
|
||||
double lowestSharedBw = Double.POSITIVE_INFINITY;
|
||||
|
||||
for(int i=0; i<nodes.size()-1; i++) {
|
||||
Node from = nodes.get(i);
|
||||
Node to = nodes.get(i+1);
|
||||
Link link = links.get(i);
|
||||
|
||||
if(lowestSharedBw > link.getSharedBandwidthPerChannel(from, to))
|
||||
lowestSharedBw = link.getSharedBandwidthPerChannel(from, to);
|
||||
}
|
||||
return lowestSharedBw;
|
||||
|
||||
}
|
||||
|
||||
public double getAdjustedRequestedBandwidth() {
|
||||
double lowest_factor = 1.0;
|
||||
|
||||
// Find the slowest link (low bw) among all links where this channel is passing through
|
||||
for(int i=0; i<nodes.size()-1; i++) {
|
||||
Node from = nodes.get(i);
|
||||
Link link = links.get(i);
|
||||
|
||||
double factor = link.getDedicatedChannelAdjustFactor(from);
|
||||
if(lowest_factor > factor)
|
||||
lowest_factor = factor;
|
||||
}
|
||||
|
||||
return lowest_factor;
|
||||
|
||||
}
|
||||
public boolean adjustDedicatedBandwidthAlongLink() {
|
||||
if(chId == -1)
|
||||
return false;
|
||||
|
||||
double lowestLinkBwShared = Double.POSITIVE_INFINITY;
|
||||
double factor = this.getAdjustedRequestedBandwidth();
|
||||
double adjustedBandwidth = this.getRequestedBandwidth() * factor;
|
||||
if(factor < 1.0) {
|
||||
Log.printLine("Link.adjustDedicatedBandwidthAlongLink(): Cannot allocate requested amount of BW"
|
||||
+adjustedBandwidth+"/"+this.getRequestedBandwidth());
|
||||
}
|
||||
|
||||
// Find the slowest link (low bw) among all links where this channel is passing through
|
||||
for(int i=0; i<nodes.size()-1; i++) {
|
||||
Node from = nodes.get(i);
|
||||
Link link = links.get(i);
|
||||
|
||||
double link_bw = link.getBw();
|
||||
int numChannels = link.getChannelCount(from);
|
||||
|
||||
double link_bw_per_channel = link_bw / numChannels;
|
||||
|
||||
if(lowestLinkBwShared > link_bw_per_channel)
|
||||
lowestLinkBwShared = link_bw_per_channel;
|
||||
}
|
||||
|
||||
// Dedicated channel.
|
||||
if(adjustedBandwidth < lowestLinkBwShared) {
|
||||
changeBandwidth(lowestLinkBwShared);
|
||||
return true;
|
||||
}
|
||||
else if(this.allocatedBandwidth != adjustedBandwidth) {
|
||||
changeBandwidth(adjustedBandwidth);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public boolean adjustSharedBandwidthAlongLink() {
|
||||
if(chId != -1)
|
||||
return false;
|
||||
|
||||
// Get the lowest bandwidth along links in the channel
|
||||
double lowestLinkBw = getLowestSharedBandwidth();
|
||||
|
||||
if(this.allocatedBandwidth != lowestLinkBw) {
|
||||
changeBandwidth(lowestLinkBw);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean changeBandwidth(double newBandwidth){
|
||||
if (newBandwidth == allocatedBandwidth)
|
||||
return false; //nothing changed
|
||||
|
||||
boolean isChanged = this.updatePackageProcessing();
|
||||
this.allocatedBandwidth=newBandwidth;
|
||||
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
public double getAllocatedBandwidth() {
|
||||
return allocatedBandwidth;
|
||||
}
|
||||
|
||||
private double getAllocatedBandwidthPerTransmission() {
|
||||
// If this channel shares a link with another channel, this channel might not get the full BW from link.
|
||||
if(inTransmission.size() == 0) {
|
||||
return getAllocatedBandwidth();
|
||||
}
|
||||
|
||||
return getAllocatedBandwidth()/inTransmission.size();
|
||||
}
|
||||
|
||||
public int getActiveTransmissionNum() {
|
||||
return inTransmission.size();
|
||||
}
|
||||
/**
|
||||
* Updates processing of transmissions taking place in this Channel.
|
||||
* @param currentTime current simulation time (in seconds)
|
||||
* @return delay to next transmission completion or
|
||||
* Double.POSITIVE_INFINITY if there is no pending transmissions
|
||||
*/
|
||||
public boolean updatePackageProcessing(){
|
||||
double currentTime = CloudSim.clock();
|
||||
double timeSpent = NetworkOperatingSystem.round(currentTime - this.previousTime);
|
||||
|
||||
if(timeSpent <= 0 || inTransmission.size() == 0)
|
||||
return false; // Nothing changed
|
||||
|
||||
//update the amount of transmission
|
||||
long processedThisRound = Math.round(timeSpent*getAllocatedBandwidthPerTransmission());
|
||||
|
||||
//update transmission table; remove finished transmission
|
||||
LinkedList<Transmission> completedTransmissions = new LinkedList<Transmission>();
|
||||
for(Transmission transmission: inTransmission){
|
||||
transmission.addCompletedLength(processedThisRound);
|
||||
|
||||
if (transmission.isCompleted()){
|
||||
completedTransmissions.add(transmission);
|
||||
this.completed.add(transmission);
|
||||
}
|
||||
}
|
||||
|
||||
this.inTransmission.removeAll(completedTransmissions);
|
||||
previousTime=currentTime;
|
||||
|
||||
Log.printLine(CloudSim.clock() + ": Channel.updatePackageProcessing() ("+this.toString()+"):Time spent:"+timeSpent+
|
||||
", BW/host:"+getAllocatedBandwidthPerTransmission()+", Processed:"+processedThisRound);
|
||||
|
||||
if(completedTransmissions.isEmpty())
|
||||
return false; // Nothing changed
|
||||
return true;
|
||||
}
|
||||
|
||||
// Estimated finish time of one transmission
|
||||
private double estimateFinishTime(Transmission t) {
|
||||
double bw = getAllocatedBandwidthPerTransmission();
|
||||
|
||||
if(bw == 0) {
|
||||
return Double.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
double eft= (double)t.getSize()/bw;
|
||||
return eft;
|
||||
}
|
||||
|
||||
// The earliest finish time among all transmissions in this channel
|
||||
public double nextFinishTime() {
|
||||
//now, predicts delay to next transmission completion
|
||||
double delay = Double.POSITIVE_INFINITY;
|
||||
|
||||
for (Transmission transmission:this.inTransmission){
|
||||
double eft = estimateFinishTime(transmission);
|
||||
if (eft<delay)
|
||||
delay = eft;
|
||||
}
|
||||
|
||||
if(delay == Double.POSITIVE_INFINITY) {
|
||||
return delay;
|
||||
}
|
||||
else if(delay < 0) {
|
||||
throw new IllegalArgumentException("Channel.nextFinishTime: delay"+delay);
|
||||
}
|
||||
|
||||
delay=NetworkOperatingSystem.round(delay);
|
||||
|
||||
if (delay < NetworkOperatingSystem.getMinTimeBetweenNetworkEvents()) {
|
||||
//Log.printLine(CloudSim.clock() + ":Channel: delay is too short: "+ delay);
|
||||
delay = NetworkOperatingSystem.getMinTimeBetweenNetworkEvents();
|
||||
}
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new Transmission to be submitted via this Channel
|
||||
* @param transmission transmission initiating
|
||||
* @return estimated delay to complete this transmission
|
||||
*
|
||||
*/
|
||||
public double addTransmission(Transmission transmission){
|
||||
if (this.inTransmission.isEmpty())
|
||||
previousTime=CloudSim.clock();
|
||||
|
||||
this.inTransmission.add(transmission);
|
||||
double eft = estimateFinishTime(transmission);
|
||||
|
||||
return eft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a transmission submitted to this Channel
|
||||
* @param transmission to be removed
|
||||
*
|
||||
*/
|
||||
public void removeTransmission(Transmission transmission){
|
||||
inTransmission.remove(transmission);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of Packages whose transmission finished, or empty
|
||||
* list if no package arrived.
|
||||
*/
|
||||
public LinkedList<Transmission> getArrivedPackages(){
|
||||
LinkedList<Transmission> returnList = new LinkedList<Transmission>();
|
||||
|
||||
if (!completed.isEmpty()){
|
||||
returnList.addAll(completed);
|
||||
}
|
||||
completed.removeAll(returnList);
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public int getChId() {
|
||||
return chId;
|
||||
}
|
||||
|
||||
public double getLastUpdateTime(){
|
||||
return previousTime;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Channel("+this.srcId+"->"+this.dstId+"|"+this.chId
|
||||
+"): BW:"+allocatedBandwidth+", Transmissions:"+inTransmission.size();
|
||||
}
|
||||
|
||||
public Node getLastNode() {
|
||||
Node node = this.nodes.get(this.nodes.size()-1);
|
||||
return node;
|
||||
}
|
||||
|
||||
public int getSrcId() {
|
||||
return srcId;
|
||||
}
|
||||
|
||||
public int getDstId() {
|
||||
return dstId;
|
||||
}
|
||||
|
||||
public double getRequestedBandwidth() {
|
||||
return requestedBandwidth;
|
||||
}
|
||||
}
|
||||
28
src/org/cloudbus/cloudsim/sdn/Constants.java
Normal file
28
src/org/cloudbus/cloudsim/sdn/Constants.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
/**
|
||||
* Constant variables to use
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
private static final int SDN_BASE = 89000000;
|
||||
|
||||
public static final int SDN_PACKAGE = SDN_BASE + 1;
|
||||
public static final int SDN_INTERNAL_PACKAGE_PROCESS = SDN_BASE + 2;
|
||||
public static final int REQUEST_SUBMIT = SDN_BASE + 10;
|
||||
public static final int REQUEST_COMPLETED = SDN_BASE + 11;
|
||||
public static final int APPLICATION_SUBMIT = SDN_BASE + 20; // Broker -> Datacenter.
|
||||
public static final int APPLICATION_SUBMIT_ACK = SDN_BASE + 21;
|
||||
}
|
||||
25
src/org/cloudbus/cloudsim/sdn/CoreSwitch.java
Normal file
25
src/org/cloudbus/cloudsim/sdn/CoreSwitch.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
/**
|
||||
* Represent core switch
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class CoreSwitch extends Switch {
|
||||
|
||||
public CoreSwitch(String name,int bw, long iops, int upports, int downports, NetworkOperatingSystem nos) {
|
||||
super(name, bw, iops, upports, downports, nos);
|
||||
//if (upports>0) throw new IllegalArgumentException("Core switches cannot have uplinks.");
|
||||
}
|
||||
|
||||
}
|
||||
24
src/org/cloudbus/cloudsim/sdn/EdgeSwitch.java
Normal file
24
src/org/cloudbus/cloudsim/sdn/EdgeSwitch.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
/**
|
||||
* Represent edge switch
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class EdgeSwitch extends Switch {
|
||||
|
||||
public EdgeSwitch(String name,int bw, long iops, int upports, int downports, NetworkOperatingSystem nos) {
|
||||
super(name, bw, iops, upports, downports, nos);
|
||||
}
|
||||
|
||||
}
|
||||
95
src/org/cloudbus/cloudsim/sdn/ForwardingRule.java
Normal file
95
src/org/cloudbus/cloudsim/sdn/ForwardingRule.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
|
||||
|
||||
/**
|
||||
* ForwardingRule class is to represent a forwarding table in each switch.
|
||||
* This is for VM routing, not host routing. Addresses used here are the addresses of VM.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class ForwardingRule {
|
||||
|
||||
Table<Integer, Integer, Map<Integer,Node>> table;
|
||||
|
||||
public ForwardingRule(){
|
||||
this.table = HashBasedTable.create();
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
table.clear();
|
||||
}
|
||||
|
||||
public void addRule(int src, int dest, int flowId, Node to){
|
||||
Map<Integer, Node> map = table.get(src, dest);
|
||||
if(map == null)
|
||||
map = new HashMap<Integer, Node>();
|
||||
map.put(flowId, to);
|
||||
table.put(src, dest, map);
|
||||
}
|
||||
|
||||
public void removeRule(int src, int dest, int flowId){
|
||||
Map<Integer, Node> map = table.get(src, dest);
|
||||
map.remove(flowId);
|
||||
if(map.isEmpty())
|
||||
table.remove(src, dest);
|
||||
else
|
||||
table.put(src, dest, map);
|
||||
}
|
||||
|
||||
public Node getRoute(int src, int dest, int flowId) {
|
||||
Map<Integer, Node> map = table.get(src, dest);
|
||||
if(map==null)
|
||||
return null;
|
||||
|
||||
return map.get(flowId);
|
||||
}
|
||||
|
||||
public void printForwardingTable(String thisNode) {
|
||||
for(Integer rowK:table.rowKeySet()) {
|
||||
Map<Integer, Map<Integer,Node>> row = table.row(rowK);
|
||||
for(Integer colK: row.keySet()) {
|
||||
Map<Integer, Node> nodes = row.get(colK);
|
||||
|
||||
for(Integer flowId:nodes.keySet()) {
|
||||
Node node = nodes.get(flowId);
|
||||
if(node instanceof SDNHost) {
|
||||
Log.printLine(thisNode + ": "+
|
||||
NetworkOperatingSystem.debugVmIdName.get(rowK) + "->" +
|
||||
NetworkOperatingSystem.debugVmIdName.get(colK) + "->"+"(flow:"+flowId+")" +
|
||||
((SDNHost) node).getName());
|
||||
}
|
||||
else if(node instanceof Switch) {
|
||||
Log.printLine(thisNode + ": "+
|
||||
NetworkOperatingSystem.debugVmIdName.get(rowK) + "->" +
|
||||
NetworkOperatingSystem.debugVmIdName.get(colK) + "->"+"(flow:"+flowId+")" +
|
||||
((Switch) node).getName());
|
||||
}
|
||||
else {
|
||||
Log.printLine(thisNode + ": "+
|
||||
NetworkOperatingSystem.debugVmIdName.get(rowK) + "->" +
|
||||
NetworkOperatingSystem.debugVmIdName.get(colK) + "->"+"(flow:"+flowId+")" +
|
||||
node.getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
211
src/org/cloudbus/cloudsim/sdn/Link.java
Normal file
211
src/org/cloudbus/cloudsim/sdn/Link.java
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
|
||||
/**
|
||||
* This is physical link between hosts and switches to build physical topology.
|
||||
* Links have latency and bandwidth.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Link {
|
||||
// bi-directional link (one link = both ways)
|
||||
Node highOrder;
|
||||
Node lowOrder;
|
||||
double upBW; // low -> high
|
||||
double downBW; // high -> low
|
||||
double latency;
|
||||
|
||||
private List<Channel> upChannels;
|
||||
private List<Channel> downChannels;
|
||||
|
||||
public Link(Node highOrder, Node lowOrder, double latency, double bw) {
|
||||
this.highOrder = highOrder;
|
||||
this.lowOrder = lowOrder;
|
||||
this.upBW = this.downBW = bw;
|
||||
this.latency = latency;
|
||||
|
||||
this.upChannels = new ArrayList<Channel>();
|
||||
this.downChannels = new ArrayList<Channel>();
|
||||
}
|
||||
|
||||
public Link(Node highOrder, Node lowOrder, double latency, double upBW, double downBW) {
|
||||
this(highOrder, lowOrder, latency, upBW);
|
||||
this.downBW = downBW;
|
||||
}
|
||||
|
||||
public Node getHighOrder() {
|
||||
return highOrder;
|
||||
}
|
||||
|
||||
public Node getLowOrder() {
|
||||
return lowOrder;
|
||||
}
|
||||
|
||||
public Node getOtherNode(Node from) {
|
||||
if(highOrder.equals(from))
|
||||
return lowOrder;
|
||||
|
||||
return highOrder;
|
||||
}
|
||||
|
||||
private boolean isUplink(Node from) {
|
||||
if(from.equals(lowOrder)) {
|
||||
return true;
|
||||
}
|
||||
else if(from.equals(highOrder)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Link.isUplink(): from("+from+") Node is wrong!!");
|
||||
}
|
||||
}
|
||||
|
||||
public double getBw(Node from) {
|
||||
if(isUplink(from)) {
|
||||
return upBW;
|
||||
}
|
||||
else {
|
||||
return downBW;
|
||||
}
|
||||
}
|
||||
|
||||
public double getBw() {
|
||||
if(upBW != downBW) {
|
||||
throw new IllegalArgumentException("Downlink/Uplink BW are different!");
|
||||
}
|
||||
return upBW;
|
||||
}
|
||||
|
||||
public double getLatency() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
private List<Channel> getChannels(Node from) {
|
||||
List<Channel> channels;
|
||||
if(isUplink(from)) {
|
||||
channels = this.upChannels;
|
||||
}
|
||||
else {
|
||||
channels = this.downChannels;
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
public double getDedicatedChannelAdjustFactor(Node from) {
|
||||
double factor = 1.0;
|
||||
double totalRequested = getRequestedBandwidthForDedicatedChannels(from);
|
||||
|
||||
if(totalRequested > this.getBw()) {
|
||||
Log.printLine("Link.getDedicatedChannelAdjustFactor() Exceeds link bandwidth. Reduce requested bandwidth");
|
||||
factor = this.getBw() / totalRequested;
|
||||
}
|
||||
return factor;
|
||||
}
|
||||
|
||||
public boolean addChannel(Node from, Channel ch) {
|
||||
getChannels(from).add(ch);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean removeChannel(Channel ch) {
|
||||
boolean ret = this.upChannels.remove(ch);
|
||||
if(!ret) {
|
||||
// the channel is down link
|
||||
ret = this.downChannels.remove(ch);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public double getAllocatedBandwidthForDedicatedChannels(Node from) {
|
||||
|
||||
double bw=0;
|
||||
for(Channel ch: getChannels(from)) {
|
||||
if(ch.getChId() != -1) {
|
||||
// chId == -1 : default channel
|
||||
bw += ch.getAllocatedBandwidth();
|
||||
}
|
||||
}
|
||||
return bw;
|
||||
}
|
||||
|
||||
public double getRequestedBandwidthForDedicatedChannels(Node from) {
|
||||
|
||||
double bw=0;
|
||||
for(Channel ch: getChannels(from)) {
|
||||
if(ch.getChId() != -1) {
|
||||
// chId == -1 : default channel
|
||||
bw += ch.getRequestedBandwidth();
|
||||
}
|
||||
}
|
||||
return bw;
|
||||
}
|
||||
|
||||
public int getChannelCount(Node from) {
|
||||
List<Channel> channels = getChannels(from);
|
||||
return channels.size();
|
||||
}
|
||||
|
||||
public int getDedicatedChannelCount(Node from) {
|
||||
int num=0;
|
||||
for(Channel ch: getChannels(from)) {
|
||||
if(ch.getChId() != -1) {
|
||||
// chId == -1 : default channel
|
||||
num ++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public int getSharedChannelCount(Node from) {
|
||||
int num = getChannels(from).size() - getDedicatedChannelCount(from);
|
||||
return num;
|
||||
}
|
||||
|
||||
public double getFreeBandwidth(Node from) {
|
||||
double bw = this.getBw(from);
|
||||
double dedicatedBw = getAllocatedBandwidthForDedicatedChannels(from);
|
||||
|
||||
return bw-dedicatedBw;
|
||||
}
|
||||
|
||||
public double getFreeBandwidthForDedicatedChannel(Node from) {
|
||||
double bw = this.getBw(from);
|
||||
double dedicatedBw = getRequestedBandwidthForDedicatedChannels(from);
|
||||
|
||||
return bw-dedicatedBw;
|
||||
}
|
||||
|
||||
public double getSharedBandwidthPerChannel(Node from, Node to) {
|
||||
double freeBw = getFreeBandwidth(from);
|
||||
double sharedBwEachChannel = freeBw / getSharedChannelCount(from);
|
||||
|
||||
return sharedBwEachChannel;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Link:"+this.highOrder.toString() + " <-> "+this.lowOrder.toString() + ", upBW:" + upBW + ", Latency:"+ latency;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
if(this.upChannels.size() >0 || this.downChannels.size() >0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
56
src/org/cloudbus/cloudsim/sdn/Middlebox.java
Normal file
56
src/org/cloudbus/cloudsim/sdn/Middlebox.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.UtilizationModelFull;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.core.CloudSimTags;
|
||||
|
||||
/**
|
||||
* Middlebox represent specific VM that acts as a middle box
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public abstract class Middlebox {
|
||||
|
||||
Vm vm;
|
||||
int mipsPerOp;
|
||||
SDNHost host;
|
||||
static int id=0;
|
||||
|
||||
public Middlebox(Vm vm, int misPerOperation){
|
||||
this.vm=vm;
|
||||
this.mipsPerOp=misPerOperation;
|
||||
}
|
||||
|
||||
public abstract void editRequest(Request req);
|
||||
|
||||
public int getId(){
|
||||
return vm.getId();
|
||||
}
|
||||
|
||||
public Vm getVm(){
|
||||
return vm;
|
||||
}
|
||||
|
||||
public void setHost(SDNHost host){
|
||||
this.host=host;
|
||||
}
|
||||
|
||||
public void submitRequest(Request req){
|
||||
Cloudlet cl = new Cloudlet(id++,mipsPerOp,1,0,0,new UtilizationModelFull(),new UtilizationModelFull(),new UtilizationModelFull());
|
||||
cl.setVmId(vm.getId());
|
||||
|
||||
host.schedule(host.getHost().getDatacenter().getId(), 0.0, CloudSimTags.CLOUDLET_SUBMIT, cl);
|
||||
}
|
||||
|
||||
}
|
||||
687
src/org/cloudbus/cloudsim/sdn/NetworkOperatingSystem.java
Normal file
687
src/org/cloudbus/cloudsim/sdn/NetworkOperatingSystem.java
Normal file
@@ -0,0 +1,687 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.CloudletSchedulerTimeShared;
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Pe;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.VmScheduler;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.core.CloudSimTags;
|
||||
import org.cloudbus.cloudsim.core.SimEntity;
|
||||
import org.cloudbus.cloudsim.core.SimEvent;
|
||||
import org.cloudbus.cloudsim.core.predicates.PredicateType;
|
||||
import org.cloudbus.cloudsim.provisioners.BwProvisioner;
|
||||
import org.cloudbus.cloudsim.provisioners.BwProvisionerSimple;
|
||||
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
|
||||
import org.cloudbus.cloudsim.provisioners.RamProvisioner;
|
||||
import org.cloudbus.cloudsim.provisioners.RamProvisionerSimple;
|
||||
import org.cloudbus.cloudsim.sdn.example.policies.VmSchedulerTimeSharedEnergy;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
/**
|
||||
* NOS calculates and estimates network behaviour. It also mimics SDN Controller functions.
|
||||
* It manages channels between switches, and assigns packages to channels and control their completion
|
||||
* Once the transmission is completed, forward the packet to the destination.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public abstract class NetworkOperatingSystem extends SimEntity {
|
||||
|
||||
String physicalTopologyFileName;
|
||||
protected PhysicalTopology topology;
|
||||
//Hashtable<Integer,SDNHost> vmHostTable;
|
||||
Hashtable<Package,Node> pkgTable;
|
||||
|
||||
Hashtable<String, Channel> channelTable;
|
||||
|
||||
List<Host> hosts;
|
||||
protected List<SDNHost> sdnhosts;
|
||||
protected List<Switch> switches= new ArrayList<Switch>();
|
||||
int vmId=0;
|
||||
protected SDNDatacenter datacenter;
|
||||
protected LinkedList<Vm> vmList;
|
||||
protected LinkedList<Arc> arcList;
|
||||
Map<Integer, Arc> flowIdArcTable;
|
||||
Map<String, Integer> vmNameIdTable;
|
||||
Map<String, Integer> flowNameIdTable;
|
||||
|
||||
public static Map<Integer, String> debugVmIdName = new HashMap<Integer, String>();
|
||||
public static Map<Integer, String> debugFlowIdName = new HashMap<Integer, String>();
|
||||
|
||||
boolean isApplicationDeployed = false;
|
||||
|
||||
// Resolution of the result.
|
||||
public static double minTimeBetweenEvents = 0.001; // in sec
|
||||
public static int resolutionPlaces = 5;
|
||||
public static int timeUnit = 1; // 1: sec, 1000: msec
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 1. map VMs and middleboxes to hosts, add the new vm/mb to the vmHostTable, advise host, advise dc
|
||||
* 2. set channels and bws
|
||||
* 3. set routing tables to restrict hops to meet latency
|
||||
*/
|
||||
protected abstract boolean deployApplication(List<Vm> vms, List<Middlebox> middleboxes, List<Arc> links);
|
||||
protected abstract Middlebox deployMiddlebox(String type, Vm vm);
|
||||
|
||||
public NetworkOperatingSystem(String fileName) {
|
||||
super("NOS");
|
||||
|
||||
this.physicalTopologyFileName = fileName;
|
||||
|
||||
this.pkgTable = new Hashtable<Package, Node>();
|
||||
this.channelTable = new Hashtable<String, Channel>();
|
||||
|
||||
initPhysicalTopology();
|
||||
}
|
||||
|
||||
public static double getMinTimeBetweenNetworkEvents() {
|
||||
return minTimeBetweenEvents* timeUnit;
|
||||
}
|
||||
public static double round(double value) {
|
||||
int places = resolutionPlaces;
|
||||
if (places < 0) throw new IllegalArgumentException();
|
||||
|
||||
if(timeUnit >= 1000) value = Math.floor(value*timeUnit);
|
||||
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(places, RoundingMode.CEILING);
|
||||
return bd.doubleValue();
|
||||
//return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void startEntity() {}
|
||||
|
||||
@Override
|
||||
public void shutdownEntity() {}
|
||||
|
||||
@Override
|
||||
public void processEvent(SimEvent ev) {
|
||||
int tag = ev.getTag();
|
||||
|
||||
switch(tag){
|
||||
case Constants.SDN_INTERNAL_PACKAGE_PROCESS:
|
||||
internalPackageProcess();
|
||||
break;
|
||||
case CloudSimTags.VM_CREATE_ACK:
|
||||
processVmCreateAck(ev);
|
||||
break;
|
||||
case CloudSimTags.VM_DESTROY:
|
||||
processVmDestroyAck(ev);
|
||||
break;
|
||||
default: System.out.println("Unknown event received by "+super.getName()+". Tag:"+ev.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
public void processVmCreateAck(SimEvent ev) {
|
||||
}
|
||||
protected void processVmDestroyAck(SimEvent ev) {
|
||||
Vm destroyedVm = (Vm) ev.getData();
|
||||
// remove all channels transferring data from or to this vm.
|
||||
for(Vm vm:this.vmList) {
|
||||
Channel ch = this.findChannel(vm.getId(), destroyedVm.getId(), -1);
|
||||
if(ch != null) {
|
||||
this.removeChannel(getKey(vm.getId(), destroyedVm.getId(), -1));
|
||||
}
|
||||
|
||||
ch = this.findChannel(destroyedVm.getId(), vm.getId(), -1);
|
||||
if(ch != null) {
|
||||
this.removeChannel(getKey(destroyedVm.getId(), vm.getId(), -1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sendInternalEvent();
|
||||
|
||||
}
|
||||
|
||||
public void addPackageToChannel(Node sender, Package pkg) {
|
||||
int src = pkg.getOrigin();
|
||||
int dst = pkg.getDestination();
|
||||
int flowId = pkg.getFlowId();
|
||||
|
||||
if(sender.equals(sender.getVMRoute(src, dst, flowId))) {
|
||||
// For loopback packet (when src and dst is on the same host)
|
||||
//Log.printLine(CloudSim.clock() + ": " + getName() + ".addPackageToChannel: Loopback package: "+pkg +". Send to destination:"+dst);
|
||||
sendNow(sender.getAddress(),Constants.SDN_PACKAGE,pkg);
|
||||
return;
|
||||
}
|
||||
|
||||
updatePackageProcessing();
|
||||
|
||||
pkgTable.put(pkg,sender);
|
||||
|
||||
Channel channel=findChannel(src, dst, flowId);
|
||||
if(channel == null) {
|
||||
//No channel establisihed. Add a channel.
|
||||
channel = createChannel(src, dst, flowId, sender);
|
||||
|
||||
if(channel == null) {
|
||||
// failed to create channel
|
||||
return;
|
||||
}
|
||||
addChannel(src, dst, flowId, channel);
|
||||
}
|
||||
|
||||
double eft = channel.addTransmission(new Transmission(pkg));
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ".addPackageToChannel ("+channel
|
||||
+"): Transmission added:" +
|
||||
NetworkOperatingSystem.debugVmIdName.get(src) + "->"+
|
||||
NetworkOperatingSystem.debugVmIdName.get(dst) + ", flow ="+flowId + " / eft="+eft);
|
||||
|
||||
sendInternalEvent();
|
||||
}
|
||||
|
||||
|
||||
private void internalPackageProcess() {
|
||||
if(updatePackageProcessing()) {
|
||||
sendInternalEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendInternalEvent() {
|
||||
CloudSim.cancelAll(getId(), new PredicateType(Constants.SDN_INTERNAL_PACKAGE_PROCESS));
|
||||
|
||||
if(channelTable.size() != 0) {
|
||||
// More to process. Send event again
|
||||
double delay = this.nextFinishTime();
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ".sendInternalEvent(): next finish time: "+ delay);
|
||||
|
||||
send(this.getId(), delay, Constants.SDN_INTERNAL_PACKAGE_PROCESS);
|
||||
}
|
||||
}
|
||||
|
||||
private double nextFinishTime() {
|
||||
double earliestEft = Double.POSITIVE_INFINITY;
|
||||
for(Channel ch:channelTable.values()){
|
||||
|
||||
double eft = ch.nextFinishTime();
|
||||
if (eft<earliestEft){
|
||||
earliestEft=eft;
|
||||
}
|
||||
}
|
||||
|
||||
if(earliestEft == Double.POSITIVE_INFINITY) {
|
||||
throw new IllegalArgumentException("NOS.nextFinishTime(): next finish time is infinite!");
|
||||
}
|
||||
return earliestEft;
|
||||
|
||||
}
|
||||
|
||||
private boolean updatePackageProcessing() {
|
||||
boolean needSendEvent = false;
|
||||
|
||||
LinkedList<Channel> completeChannels = new LinkedList<Channel>();
|
||||
|
||||
for(Channel ch:channelTable.values()){
|
||||
boolean isCompleted = ch.updatePackageProcessing();
|
||||
needSendEvent = needSendEvent || isCompleted;
|
||||
//completeChannels.add(ch.getArrivedPackages());
|
||||
completeChannels.add(ch);
|
||||
}
|
||||
|
||||
if(completeChannels.size() != 0) {
|
||||
processCompletePackages(completeChannels);
|
||||
updateChannel();
|
||||
}
|
||||
|
||||
return needSendEvent;
|
||||
}
|
||||
|
||||
private void processCompletePackages(List<Channel> channels){
|
||||
for(Channel ch:channels) {
|
||||
|
||||
Node dest = ch.getLastNode();
|
||||
|
||||
for (Transmission tr:ch.getArrivedPackages()){
|
||||
Package pkg = tr.getPackage();
|
||||
//Node sender = pkgTable.remove(pkg);
|
||||
//Node nextHop = sender.getRoute(pkg.getOrigin(),pkg.getDestination(),pkg.getFlowId());
|
||||
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Package completed: "+pkg +". Send to destination:"+dest);
|
||||
sendNow(dest.getAddress(),Constants.SDN_PACKAGE,pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Integer> getVmNameIdTable() {
|
||||
return this.vmNameIdTable;
|
||||
}
|
||||
public Map<String, Integer> getFlowNameIdTable() {
|
||||
return this.flowNameIdTable;
|
||||
}
|
||||
|
||||
private Channel findChannel(int from, int to, int channelId) {
|
||||
// check if there is a pre-configured channel for this application
|
||||
Channel channel=channelTable.get(getKey(from,to, channelId));
|
||||
|
||||
if (channel == null) {
|
||||
//there is no channel for specific flow, find the default channel for this link
|
||||
channel=channelTable.get(getKey(from,to));
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
private void addChannel(int src, int dst, int chId, Channel ch) {
|
||||
//System.err.println("NOS.addChannel:"+getKey(src, dst, chId));
|
||||
this.channelTable.put(getKey(src, dst, chId), ch);
|
||||
ch.initialize();
|
||||
adjustAllChannels();
|
||||
}
|
||||
|
||||
private Channel removeChannel(String key) {
|
||||
//System.err.println("NOS.removeChannel:"+key);
|
||||
Channel ch = this.channelTable.remove(key);
|
||||
ch.terminate();
|
||||
adjustAllChannels();
|
||||
return ch;
|
||||
}
|
||||
|
||||
private void adjustAllChannels() {
|
||||
for(Channel ch:this.channelTable.values()) {
|
||||
if(ch.adjustDedicatedBandwidthAlongLink()) {
|
||||
// Channel BW is changed. send event.
|
||||
}
|
||||
}
|
||||
|
||||
for(Channel ch:this.channelTable.values()) {
|
||||
if(ch.adjustSharedBandwidthAlongLink()) {
|
||||
// Channel BW is changed. send event.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Channel createChannel(int src, int dst, int flowId, Node srcNode) {
|
||||
List<Node> nodes = new ArrayList<Node>();
|
||||
List<Link> links = new ArrayList<Link>();
|
||||
|
||||
Node origin = srcNode;
|
||||
Node dest = origin.getVMRoute(src, dst, flowId);
|
||||
|
||||
if(dest==null)
|
||||
return null;
|
||||
|
||||
Link link;
|
||||
double lowestBw = Double.POSITIVE_INFINITY;
|
||||
double reqBw = 0;
|
||||
if(flowId != -1) {
|
||||
Arc flow = this.flowIdArcTable.get(flowId);
|
||||
reqBw = flow.getBw();
|
||||
}
|
||||
|
||||
nodes.add(origin);
|
||||
|
||||
while(true) {
|
||||
link = this.topology.getLink(origin.getAddress(), dest.getAddress());
|
||||
links.add(link);
|
||||
nodes.add(dest);
|
||||
|
||||
if(lowestBw > link.getFreeBandwidth(origin)) {
|
||||
lowestBw = link.getFreeBandwidth(origin);
|
||||
}
|
||||
|
||||
if(dest instanceof SDNHost)
|
||||
break;
|
||||
|
||||
origin = dest;
|
||||
dest = origin.getVMRoute(src, dst, flowId);
|
||||
}
|
||||
|
||||
if(flowId != -1 && lowestBw < reqBw) {
|
||||
// free bandwidth is less than required one.
|
||||
// Cannot make channel.
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Free bandwidth is less than required.("+getKey(src,dst,flowId)+"): ReqBW="+ reqBw + "/ Free="+lowestBw);
|
||||
//return null;
|
||||
}
|
||||
|
||||
Channel channel=new Channel(flowId, src, dst, nodes, links, reqBw);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
private void updateChannel() {
|
||||
List<String> removeCh = new ArrayList<String>();
|
||||
for(String key:this.channelTable.keySet()) {
|
||||
Channel ch = this.channelTable.get(key);
|
||||
if(ch.getActiveTransmissionNum() == 0) {
|
||||
// No more job in channel. Delete
|
||||
removeCh.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
for(String key:removeCh) {
|
||||
removeChannel(key);
|
||||
}
|
||||
}
|
||||
|
||||
private String getKey(int origin, int destination) {
|
||||
return origin+"-"+destination;
|
||||
}
|
||||
|
||||
private String getKey(int origin, int destination, int appId) {
|
||||
return getKey(origin,destination)+"-"+appId;
|
||||
}
|
||||
|
||||
|
||||
public void setDatacenter(SDNDatacenter dc) {
|
||||
this.datacenter = dc;
|
||||
}
|
||||
|
||||
public List<Host> getHostList() {
|
||||
return this.hosts;
|
||||
}
|
||||
|
||||
public List<Switch> getSwitchList() {
|
||||
return this.switches;
|
||||
}
|
||||
|
||||
public boolean isApplicationDeployed() {
|
||||
return isApplicationDeployed;
|
||||
}
|
||||
|
||||
protected Vm findVm(int vmId) {
|
||||
for(Vm vm:vmList) {
|
||||
if(vm.getId() == vmId)
|
||||
return vm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
protected SDNHost findSDNHost(Host host) {
|
||||
for(SDNHost sdnhost:sdnhosts) {
|
||||
if(sdnhost.getHost().equals(host)) {
|
||||
return sdnhost;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
protected SDNHost findSDNHost(int vmId) {
|
||||
Vm vm = findVm(vmId);
|
||||
if(vm == null)
|
||||
return null;
|
||||
|
||||
for(SDNHost sdnhost:sdnhosts) {
|
||||
if(sdnhost.getHost().equals(vm.getHost())) {
|
||||
return sdnhost;
|
||||
}
|
||||
}
|
||||
//System.err.println("NOS.findSDNHost: Host is not found for VM:"+ vmId);
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getHostAddressByVmId(int vmId) {
|
||||
Vm vm = findVm(vmId);
|
||||
if(vm == null) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Cannot find VM with vmId = "+ vmId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Host host = vm.getHost();
|
||||
SDNHost sdnhost = findSDNHost(host);
|
||||
if(sdnhost == null) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Cannot find SDN Host with vmId = "+ vmId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sdnhost.getAddress();
|
||||
}
|
||||
|
||||
protected Host createHost(int hostId, int ram, long bw, long storage, long pes, double mips) {
|
||||
LinkedList<Pe> peList = new LinkedList<Pe>();
|
||||
int peId=0;
|
||||
for(int i=0;i<pes;i++) peList.add(new Pe(peId++,new PeProvisionerSimple(mips)));
|
||||
|
||||
RamProvisioner ramPro = new RamProvisionerSimple(ram);
|
||||
BwProvisioner bwPro = new BwProvisionerSimple(bw);
|
||||
VmScheduler vmScheduler = new VmSchedulerTimeSharedEnergy(peList);
|
||||
Host newHost = new Host(hostId, ramPro, bwPro, storage, peList, vmScheduler);
|
||||
|
||||
return newHost;
|
||||
}
|
||||
|
||||
protected void initPhysicalTopology() {
|
||||
this.topology = new PhysicalTopology();
|
||||
this.hosts = new ArrayList<Host>();
|
||||
this.sdnhosts = new ArrayList<SDNHost>();
|
||||
|
||||
int hostId=0;
|
||||
Hashtable<String,Integer> nameIdTable = new Hashtable<String, Integer>();
|
||||
try {
|
||||
JSONObject doc = (JSONObject) JSONValue.parse(new FileReader(this.physicalTopologyFileName));
|
||||
|
||||
JSONArray nodes = (JSONArray) doc.get("nodes");
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> iter =nodes.iterator();
|
||||
while(iter.hasNext()){
|
||||
JSONObject node = iter.next();
|
||||
String nodeType = (String) node.get("type");
|
||||
String nodeName = (String) node.get("name");
|
||||
|
||||
if(nodeType.equalsIgnoreCase("host")){
|
||||
long pes = (Long) node.get("pes");
|
||||
long mips = (Long) node.get("mips");
|
||||
int ram = new BigDecimal((Long)node.get("ram")).intValueExact();
|
||||
long storage = (Long) node.get("storage");
|
||||
long bw = new BigDecimal((Long)node.get("bw")).intValueExact();
|
||||
|
||||
int num = 1;
|
||||
if (node.get("nums")!= null)
|
||||
num = new BigDecimal((Long)node.get("nums")).intValueExact();
|
||||
|
||||
for(int n = 0; n< num; n++) {
|
||||
String nodeName2 = nodeName;
|
||||
if(num >1) nodeName2 = nodeName + n;
|
||||
|
||||
Host host = createHost(hostId, ram, bw, storage, pes, mips);
|
||||
SDNHost sdnHost = new SDNHost(host, this);
|
||||
nameIdTable.put(nodeName2, sdnHost.getAddress());
|
||||
hostId++;
|
||||
|
||||
topology.addNode(sdnHost);
|
||||
this.hosts.add(host);
|
||||
this.sdnhosts.add(sdnHost);
|
||||
}
|
||||
|
||||
} else {
|
||||
int MAX_PORTS = 256;
|
||||
|
||||
int bw = new BigDecimal((Long)node.get("bw")).intValueExact();
|
||||
long iops = (Long) node.get("iops");
|
||||
int upports = MAX_PORTS;
|
||||
int downports = MAX_PORTS;
|
||||
if (node.get("upports")!= null)
|
||||
upports = new BigDecimal((Long)node.get("upports")).intValueExact();
|
||||
if (node.get("downports")!= null)
|
||||
downports = new BigDecimal((Long)node.get("downports")).intValueExact();
|
||||
Switch sw = null;
|
||||
|
||||
if(nodeType.equalsIgnoreCase("core")) {
|
||||
sw = new CoreSwitch(nodeName, bw, iops, upports, downports, this);
|
||||
} else if (nodeType.equalsIgnoreCase("aggregate")){
|
||||
sw = new AggregationSwitch(nodeName, bw, iops, upports, downports, this);
|
||||
} else if (nodeType.equalsIgnoreCase("edge")){
|
||||
sw = new EdgeSwitch(nodeName, bw, iops, upports, downports, this);
|
||||
} else {
|
||||
throw new IllegalArgumentException("No switch found!");
|
||||
}
|
||||
|
||||
if(sw != null) {
|
||||
nameIdTable.put(nodeName, sw.getAddress());
|
||||
topology.addNode(sw);
|
||||
this.switches.add(sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray links = (JSONArray) doc.get("links");
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> linksIter =links.iterator();
|
||||
while(linksIter.hasNext()){
|
||||
JSONObject link = linksIter.next();
|
||||
String src = (String) link.get("source");
|
||||
String dst = (String) link.get("destination");
|
||||
double lat = (Double) link.get("latency");
|
||||
|
||||
int srcAddress = nameIdTable.get(src);
|
||||
int dstAddress = nameIdTable.get(dst);
|
||||
topology.addLink(srcAddress, dstAddress, lat);
|
||||
}
|
||||
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
topology.buildDefaultRouting();
|
||||
}
|
||||
|
||||
private static int flowNumbers=0;
|
||||
public boolean deployApplication(int userId, String vmsFileName){
|
||||
|
||||
vmNameIdTable = new HashMap<String, Integer>();
|
||||
vmList = new LinkedList<Vm>();
|
||||
LinkedList<Middlebox> mbList = new LinkedList<Middlebox>();
|
||||
arcList = new LinkedList<Arc>();
|
||||
flowIdArcTable = new HashMap<Integer, Arc>();
|
||||
flowNameIdTable = new HashMap<String, Integer>();
|
||||
flowNameIdTable.put("default", -1);
|
||||
|
||||
try {
|
||||
JSONObject doc = (JSONObject) JSONValue.parse(new FileReader(vmsFileName));
|
||||
JSONArray nodes = (JSONArray) doc.get("nodes");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> iter = nodes.iterator();
|
||||
while(iter.hasNext()){
|
||||
JSONObject node = iter.next();
|
||||
|
||||
String nodeType = (String) node.get("type");
|
||||
String nodeName = (String) node.get("name");
|
||||
int pes = new BigDecimal((Long)node.get("pes")).intValueExact();
|
||||
long mips = (Long) node.get("mips");
|
||||
int ram = new BigDecimal((Long)node.get("ram")).intValueExact();
|
||||
long size = (Long) node.get("size");
|
||||
long bw = 1000;
|
||||
if(node.get("bw") != null)
|
||||
bw = (Long) node.get("bw");
|
||||
|
||||
double starttime = 0;
|
||||
double endtime = Double.POSITIVE_INFINITY;
|
||||
if(node.get("starttime") != null)
|
||||
starttime = (Double) node.get("starttime");
|
||||
if(node.get("endtime") != null)
|
||||
endtime = (Double) node.get("endtime");
|
||||
|
||||
long nums =1;
|
||||
if(node.get("nums") != null)
|
||||
nums = (Long) node.get("nums");
|
||||
|
||||
for(int n=0; n<nums; n++) {
|
||||
String nodeName2 = nodeName;
|
||||
if(nums > 1) {
|
||||
// Nodename should be numbered.
|
||||
nodeName2 = nodeName + n;
|
||||
}
|
||||
if(nodeType.equalsIgnoreCase("vm")){
|
||||
// VM
|
||||
Vm vm = new TimedVm(vmId,userId,mips,pes,ram,bw,size,"VMM",new CloudletSchedulerTimeShared(), starttime, endtime);
|
||||
vmNameIdTable.put(nodeName2, vmId);
|
||||
NetworkOperatingSystem.debugVmIdName.put(vmId, nodeName2);
|
||||
|
||||
vmList.add(vm);
|
||||
vmId++;
|
||||
} else {
|
||||
// Middle box
|
||||
Vm vm = new Vm(vmId,userId,mips,pes,ram,bw,size,"VMM",new CloudletSchedulerTimeShared());
|
||||
Middlebox m = deployMiddlebox(nodeType,vm);
|
||||
vmNameIdTable.put(nodeName2, vmId);
|
||||
mbList.add(m);
|
||||
vmId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray links = (JSONArray) doc.get("links");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> linksIter = links.iterator();
|
||||
while(linksIter.hasNext()){
|
||||
JSONObject link = linksIter.next();
|
||||
String name = (String) link.get("name");
|
||||
String src = (String) link.get("source");
|
||||
String dst = (String) link.get("destination");
|
||||
|
||||
Object reqLat = link.get("latency");
|
||||
Object reqBw = link.get("bandwidth");
|
||||
|
||||
double lat = 0.0;
|
||||
long bw = 0;
|
||||
|
||||
if(reqLat != null)
|
||||
lat = (Double) reqLat;
|
||||
if(reqBw != null)
|
||||
bw = (Long) reqBw;
|
||||
|
||||
int srcId = vmNameIdTable.get(src);
|
||||
int dstId = vmNameIdTable.get(dst);
|
||||
|
||||
int flowId = -1;
|
||||
|
||||
if(name == null || "default".equalsIgnoreCase(name)) {
|
||||
// default flow.
|
||||
flowId = -1;
|
||||
}
|
||||
else {
|
||||
flowId = flowNumbers++;
|
||||
flowNameIdTable.put(name, flowId);
|
||||
}
|
||||
|
||||
Arc arc = new Arc(srcId, dstId, flowId, bw, lat);
|
||||
arcList.add(arc);
|
||||
if(flowId != -1) {
|
||||
flowIdArcTable.put(flowId, arc);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
boolean result = deployApplication(vmList, mbList, arcList);
|
||||
if (result){
|
||||
isApplicationDeployed = true;
|
||||
return true;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
40
src/org/cloudbus/cloudsim/sdn/Node.java
Normal file
40
src/org/cloudbus/cloudsim/sdn/Node.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Node represents network node (host or switch)
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public interface Node {
|
||||
|
||||
int getAddress();
|
||||
public long getBandwidth();
|
||||
public void setRank(int rank);
|
||||
public int getRank();
|
||||
|
||||
public void clearVMRoutingTable();
|
||||
public void addVMRoute(int srcVM, int destVM, int flowId, Node to);
|
||||
public Node getVMRoute(int srcVM, int destVM, int flowId);
|
||||
public void removeVMRoute(int srcVM, int destVM, int flowId);
|
||||
public void printVMRoute();
|
||||
|
||||
public void addRoute(Node destHost, Link to);
|
||||
public List<Link> getRoute(Node destHost);
|
||||
|
||||
public RoutingTable getRoutingTable();
|
||||
|
||||
public void addLink(Link l);
|
||||
public void updateNetworkUtilization();
|
||||
}
|
||||
76
src/org/cloudbus/cloudsim/sdn/Package.java
Normal file
76
src/org/cloudbus/cloudsim/sdn/Package.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
|
||||
/**
|
||||
* Network data packet to transfer from source to destination.
|
||||
* Payload of Package will have a list of activities.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Package {
|
||||
|
||||
int origin;
|
||||
int destination;
|
||||
long size;
|
||||
int flowId;
|
||||
Request payload;
|
||||
|
||||
private double startTime=-1;
|
||||
private double finishTime=-1;
|
||||
|
||||
public Package(int origin, int destination, long size, int flowId, Request payload) {
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
this.size = size;
|
||||
this.flowId = flowId;
|
||||
this.payload = payload;
|
||||
|
||||
}
|
||||
|
||||
public int getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public int getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public Request getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public int getFlowId() {
|
||||
return flowId;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "PKG:"+origin + "->" + destination + " - " + payload.toString();
|
||||
}
|
||||
|
||||
public void setStartTime(double time) {
|
||||
this.startTime = time;
|
||||
}
|
||||
public void setFinishTime(double time) {
|
||||
this.finishTime = time;
|
||||
}
|
||||
public double getStartTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
public double getFinishTime() {
|
||||
return this.finishTime;
|
||||
}
|
||||
}
|
||||
192
src/org/cloudbus/cloudsim/sdn/PhysicalTopology.java
Normal file
192
src/org/cloudbus/cloudsim/sdn/PhysicalTopology.java
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.cloudbus.cloudsim.network.datacenter.AggregateSwitch;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Table;
|
||||
|
||||
|
||||
/**
|
||||
* Network connection maps including switches, hosts, and links between them
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class PhysicalTopology {
|
||||
|
||||
Hashtable<Integer,Node> nodesTable; // Address -> Node
|
||||
Table<Integer, Integer, Link> links; // From : To -> Link
|
||||
Multimap<Node,Link> nodeLinks; // Node -> all Links
|
||||
|
||||
public PhysicalTopology() {
|
||||
nodesTable = new Hashtable<Integer,Node>();
|
||||
nodeLinks = HashMultimap.create();
|
||||
links = HashBasedTable.create();
|
||||
}
|
||||
|
||||
public Link getLink(int from, int to) {
|
||||
return links.get(from, to);
|
||||
}
|
||||
public Node getNode(int id) {
|
||||
return nodesTable.get(id);
|
||||
}
|
||||
public double getLinkBandwidth(int from, int to){
|
||||
return getLink(from, to).getBw(getNode(from));
|
||||
}
|
||||
|
||||
public double getLinkLatency(int from, int to){
|
||||
return getLink(from, to).getLatency();
|
||||
}
|
||||
|
||||
public void addNode(Node node){
|
||||
nodesTable.put(node.getAddress(), node);
|
||||
if (node instanceof CoreSwitch){//coreSwitch is rank 0 (root)
|
||||
node.setRank(0);
|
||||
} else if (node instanceof AggregateSwitch){//Hosts are on the bottom of hierarchy (leaf)
|
||||
node.setRank(1);
|
||||
} else if (node instanceof EdgeSwitch){//Edge switches are just before hosts in the hierarchy
|
||||
node.setRank(2);
|
||||
} else if (node instanceof SDNHost){//Hosts are on the bottom of hierarchy (leaf)
|
||||
node.setRank(3);
|
||||
}
|
||||
}
|
||||
public void buildDefaultRouting() {
|
||||
Collection<Node> nodes = getAllNodes();
|
||||
|
||||
// For SDNHost: build path to edge switch
|
||||
// For Edge: build path to SDN Host
|
||||
for(Node sdnhost:nodes) {
|
||||
if(sdnhost.getRank() == 3) { // Rank3 = SDN Host
|
||||
Collection<Link> links = getAdjacentLinks(sdnhost);
|
||||
for(Link l:links) {
|
||||
if(l.getLowOrder().equals(sdnhost)) {
|
||||
sdnhost.addRoute(null, l);
|
||||
Node edge = l.getHighOrder();
|
||||
edge.addRoute(sdnhost, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For Edge: build path to aggregate switch
|
||||
// For Aggregate: build path to edge switch
|
||||
for(Node lowerNode:nodes) {
|
||||
if(lowerNode.getRank() == 2) { // Rank2 = Edge switch
|
||||
Collection<Link> links = getAdjacentLinks(lowerNode);
|
||||
for(Link l:links) {
|
||||
if(l.getLowOrder().equals(lowerNode)) {
|
||||
// Link is between Edge and Aggregate
|
||||
lowerNode.addRoute(null, l);
|
||||
Node higherNode = l.getHighOrder();
|
||||
|
||||
// Add all children hosts to
|
||||
for(Node destination: lowerNode.getRoutingTable().getKnownDestination()) {
|
||||
if(destination != null)
|
||||
higherNode.addRoute(destination, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For Agg: build path to core switch
|
||||
// For Core: build path to aggregate switch
|
||||
for(Node agg:nodes) {
|
||||
if(agg.getRank() == 1) { // Rank1 = Agg switch
|
||||
Collection<Link> links = getAdjacentLinks(agg);
|
||||
for(Link l:links) {
|
||||
if(l.getLowOrder().equals(agg)) {
|
||||
// Link is between Edge and Aggregate
|
||||
agg.addRoute(null, l);
|
||||
Node core = l.getHighOrder();
|
||||
|
||||
// Add all children hosts to
|
||||
for(Node destination: agg.getRoutingTable().getKnownDestination()) {
|
||||
if(destination != null)
|
||||
core.addRoute(destination, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(Node n:nodes) {
|
||||
System.out.println("============================================");
|
||||
System.out.println("Node: "+n);
|
||||
n.getRoutingTable().printRoutingTable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void addLink(int from, int to, double latency){
|
||||
Node fromNode = nodesTable.get(from);
|
||||
Node toNode = nodesTable.get(to);
|
||||
|
||||
long bw = (fromNode.getBandwidth()<toNode.getBandwidth())? fromNode.getBandwidth():toNode.getBandwidth();
|
||||
|
||||
if(!nodesTable.containsKey(from)||!nodesTable.containsKey(to)){
|
||||
throw new IllegalArgumentException("Unknown node on link:"+nodesTable.get(from).getAddress()+"->"+nodesTable.get(to).getAddress());
|
||||
}
|
||||
|
||||
if (links.contains(fromNode.getAddress(), toNode.getAddress())){
|
||||
throw new IllegalArgumentException("Link added twice:"+fromNode.getAddress()+"->"+toNode.getAddress());
|
||||
}
|
||||
|
||||
if(fromNode.getRank()==-1&&toNode.getRank()==-1){
|
||||
throw new IllegalArgumentException("Unable to establish orders for nodes on link:"+nodesTable.get(from).getAddress()+"->"+nodesTable.get(to).getAddress());
|
||||
}
|
||||
|
||||
if (fromNode.getRank()>=0 && toNode.getRank()>=0){
|
||||
//we know the rank of both nodes; easy to establish topology
|
||||
if ((toNode.getRank()-fromNode.getRank())!=1) {
|
||||
//throw new IllegalArgumentException("Nodes need to be parent and child:"+nodesTable.get(from).getAddress()+"->"+nodesTable.get(to).getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
if(fromNode.getRank()>=0&&toNode.getRank()==-1){
|
||||
//now we now B is children of A
|
||||
toNode.setRank(fromNode.getRank()+1);
|
||||
}
|
||||
|
||||
if(fromNode.getRank()==-1&&toNode.getRank()>=1){
|
||||
//now we now A is parent of B
|
||||
fromNode.setRank(toNode.getRank()-1);
|
||||
}
|
||||
Link l = new Link(fromNode, toNode, latency, bw);
|
||||
|
||||
// Two way links (From -> to, To -> from)
|
||||
links.put(from, to, l);
|
||||
links.put(to, from, l);
|
||||
|
||||
nodeLinks.put(fromNode, l);
|
||||
nodeLinks.put(toNode, l);
|
||||
|
||||
fromNode.addLink(l);
|
||||
toNode.addLink(l);
|
||||
}
|
||||
|
||||
public Collection<Link> getAdjacentLinks(Node node) {
|
||||
return nodeLinks.get(node);
|
||||
}
|
||||
|
||||
public Collection<Node> getAllNodes() {
|
||||
return nodesTable.values();
|
||||
}
|
||||
|
||||
public Collection<Link> getAllLinks() {
|
||||
return nodeLinks.values();
|
||||
}
|
||||
|
||||
}
|
||||
31
src/org/cloudbus/cloudsim/sdn/Processing.java
Normal file
31
src/org/cloudbus/cloudsim/sdn/Processing.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
|
||||
/**
|
||||
* Processing activity to compute in VM. Basically a wrapper of Cloudlet.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Processing implements Activity {
|
||||
|
||||
long requestId;
|
||||
Cloudlet cl;
|
||||
|
||||
public Processing(Cloudlet cl){
|
||||
this.cl=cl;
|
||||
}
|
||||
|
||||
public Cloudlet getCloudlet(){
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
83
src/org/cloudbus/cloudsim/sdn/Request.java
Normal file
83
src/org/cloudbus/cloudsim/sdn/Request.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Request class represents a message submitted to VM. Each request has a list of activities
|
||||
* that should be performed at the VM. (Processing and Transmission)
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Request {
|
||||
|
||||
long requestId;
|
||||
int userId;
|
||||
LinkedList<Activity> activities;
|
||||
|
||||
private LinkedList<Activity> removedActivites; //Logging purpose only
|
||||
|
||||
public Request(long requestId, int userId){
|
||||
this.requestId=requestId;
|
||||
this.userId=userId;
|
||||
this.activities = new LinkedList<Activity>();
|
||||
|
||||
this.removedActivites = new LinkedList<Activity>();
|
||||
|
||||
}
|
||||
|
||||
public long getRequestId(){
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public int getUserId(){
|
||||
return userId;
|
||||
}
|
||||
|
||||
public boolean isFinished(){
|
||||
return activities.size()==0;
|
||||
}
|
||||
|
||||
public void addActivity(Activity act){
|
||||
activities.add(act);
|
||||
}
|
||||
|
||||
public Activity getNextActivity(){
|
||||
Activity act = activities.get(0);
|
||||
return act;
|
||||
}
|
||||
|
||||
public Transmission getNextTransmission() {
|
||||
for(Activity act:activities) {
|
||||
if(act instanceof Transmission)
|
||||
return (Transmission) act;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Activity removeNextActivity(){
|
||||
Activity act = activities.remove(0);
|
||||
|
||||
this.removedActivites.add(act);
|
||||
|
||||
return act;
|
||||
}
|
||||
public String toString() {
|
||||
return "Request. UserID:"+ this.userId + ",Req ID:"+this.requestId;
|
||||
}
|
||||
|
||||
public List<Activity> getRemovedActivities() {
|
||||
return this.removedActivites;
|
||||
}
|
||||
}
|
||||
69
src/org/cloudbus/cloudsim/sdn/RoutingTable.java
Normal file
69
src/org/cloudbus/cloudsim/sdn/RoutingTable.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Routing table for hosts and switches. This has information about the next hop.
|
||||
* When physical topology is set up, RoutingTable is created with the information
|
||||
* about next hop
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class RoutingTable {
|
||||
|
||||
Map<Node, List<Link>> table;
|
||||
|
||||
public RoutingTable(){
|
||||
this.table = new HashMap<Node, List<Link>>();
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
table.clear();
|
||||
}
|
||||
|
||||
public void addRoute(Node destHost, Link to){
|
||||
List<Link> links = table.get(destHost);
|
||||
if(links == null)
|
||||
{
|
||||
links = new ArrayList<Link>();
|
||||
}
|
||||
links.add(to);
|
||||
table.put(destHost, links);
|
||||
}
|
||||
|
||||
public void removeRoute(Node destHost){
|
||||
table.remove(destHost);
|
||||
}
|
||||
|
||||
public List<Link> getRoute(Node destHost) {
|
||||
List<Link> links = table.get(destHost);
|
||||
if(links == null)
|
||||
links = table.get(null);
|
||||
return links;
|
||||
}
|
||||
|
||||
public Set<Node> getKnownDestination() {
|
||||
return table.keySet();
|
||||
}
|
||||
|
||||
public void printRoutingTable() {
|
||||
for(Node key:table.keySet()) {
|
||||
for(Link l: table.get(key)) {
|
||||
System.out.println("dst:"+key+" : "+l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
src/org/cloudbus/cloudsim/sdn/SDNDatacenter.java
Normal file
117
src/org/cloudbus/cloudsim/sdn/SDNDatacenter.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.Datacenter;
|
||||
import org.cloudbus.cloudsim.DatacenterCharacteristics;
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Storage;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.VmAllocationPolicy;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.core.CloudSimTags;
|
||||
import org.cloudbus.cloudsim.core.SimEvent;
|
||||
|
||||
/**
|
||||
* Extended class of Datacenter that supports processing SDN-specific events.
|
||||
* In addtion to the default Datacenter, it processes Request submission to VM,
|
||||
* and application deployment request.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class SDNDatacenter extends Datacenter {
|
||||
|
||||
NetworkOperatingSystem nos;
|
||||
|
||||
public SDNDatacenter(String name, DatacenterCharacteristics characteristics, VmAllocationPolicy vmAllocationPolicy, List<Storage> storageList, double schedulingInterval, NetworkOperatingSystem nos) throws Exception {
|
||||
super(name, characteristics, vmAllocationPolicy, storageList, schedulingInterval);
|
||||
|
||||
this.nos=nos;
|
||||
//nos.init();
|
||||
}
|
||||
|
||||
public void addVm(Vm vm){
|
||||
getVmList().add(vm);
|
||||
if (vm.isBeingInstantiated()) vm.setBeingInstantiated(false);
|
||||
vm.updateVmProcessing(CloudSim.clock(), getVmAllocationPolicy().getHost(vm).getVmScheduler().getAllocatedMipsForVm(vm));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processVmCreate(SimEvent ev, boolean ack) {
|
||||
super.processVmCreate(ev, ack);
|
||||
if(ack) {
|
||||
send(nos.getId(), CloudSim.getMinTimeBetweenEvents(), CloudSimTags.VM_CREATE_ACK, ev.getData());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOtherEvent(SimEvent ev){
|
||||
switch(ev.getTag()){
|
||||
case Constants.REQUEST_SUBMIT: processRequest((Request) ev.getData()); break;
|
||||
case Constants.APPLICATION_SUBMIT: processApplication(ev.getSource(),(String) ev.getData()); break;
|
||||
default: System.out.println("Unknown event recevied by SdnDatacenter. Tag:"+ev.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkCloudletCompletion() {
|
||||
if(!nos.isApplicationDeployed())
|
||||
{
|
||||
super.checkCloudletCompletion();
|
||||
return;
|
||||
}
|
||||
|
||||
List<? extends Host> list = getVmAllocationPolicy().getHostList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Host host = list.get(i);
|
||||
for (Vm vm : host.getVmList()) {
|
||||
while (vm.getCloudletScheduler().isFinishedCloudlets()) {
|
||||
Cloudlet cl = vm.getCloudletScheduler().getNextFinishedCloudlet();
|
||||
if (cl != null) {
|
||||
int hostAddress = nos.getHostAddressByVmId(cl.getVmId());
|
||||
sendNow(hostAddress, CloudSimTags.CLOUDLET_RETURN, cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processRequest(Request req) {//Request received from user. Send to SdnHost
|
||||
Activity ac = req.getNextActivity();
|
||||
if(ac instanceof Processing) {
|
||||
Cloudlet cl = ((Processing) ac).getCloudlet();
|
||||
int hostAddress = nos.getHostAddressByVmId(cl.getVmId());
|
||||
|
||||
//for this first package, size doesn't matter
|
||||
Package pkg = new Package(super.getId(), cl.getVmId(), -1, -1, req);
|
||||
sendNow(hostAddress, Constants.SDN_PACKAGE, pkg);
|
||||
}
|
||||
else {
|
||||
System.err.println("Request should start with Processing!!");
|
||||
}
|
||||
}
|
||||
|
||||
private void processApplication(int userId, String filename) {
|
||||
nos.deployApplication(userId,filename);
|
||||
send(userId, CloudSim.getMinTimeBetweenEvents(), Constants.APPLICATION_SUBMIT_ACK, filename);
|
||||
}
|
||||
|
||||
public Map<String, Integer> getVmNameIdTable() {
|
||||
return this.nos.getVmNameIdTable();
|
||||
}
|
||||
public Map<String, Integer> getFlowNameIdTable() {
|
||||
return this.nos.getFlowNameIdTable();
|
||||
}
|
||||
}
|
||||
240
src/org/cloudbus/cloudsim/sdn/SDNHost.java
Normal file
240
src/org/cloudbus/cloudsim/sdn/SDNHost.java
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.core.CloudSimTags;
|
||||
import org.cloudbus.cloudsim.core.SimEntity;
|
||||
import org.cloudbus.cloudsim.core.SimEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Extended class of Host to support SDN.
|
||||
* Added function includes data transmission after completion of Cloudlet compute processing.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class SDNHost extends SimEntity implements Node {
|
||||
private static final double PROCESSING_DELAY= 0.1;
|
||||
|
||||
Host host;
|
||||
EdgeSwitch sw;
|
||||
//Hashtable<Integer,Vm> vms;
|
||||
Hashtable<Integer,Middlebox> middleboxes;
|
||||
Hashtable<Cloudlet,Request> requestsTable;
|
||||
ForwardingRule forwardingTable;
|
||||
RoutingTable routingTable;
|
||||
int rank = -1;
|
||||
NetworkOperatingSystem nos;
|
||||
|
||||
SDNHost(Host host, NetworkOperatingSystem nos){
|
||||
super("Host"+host.getId());
|
||||
this.host=host;
|
||||
this.nos = nos;
|
||||
|
||||
//this.vms = new Hashtable<Integer,Vm>();
|
||||
this.middleboxes = new Hashtable<Integer, Middlebox>();
|
||||
this.requestsTable = new Hashtable<Cloudlet, Request>();
|
||||
this.forwardingTable = new ForwardingRule();
|
||||
this.routingTable = new RoutingTable();
|
||||
}
|
||||
|
||||
public Host getHost(){
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setEdgeSwitch(EdgeSwitch sw){
|
||||
this.sw=sw;
|
||||
}
|
||||
/*
|
||||
public void addVm(Vm vm){
|
||||
vms.put(vm.getId(), vm);
|
||||
host.vmCreate(vm);
|
||||
}
|
||||
*/
|
||||
public void addMiddlebox(Middlebox m){
|
||||
middleboxes.put(m.getId(), m);
|
||||
host.vmCreate(m.getVm());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEntity(){}
|
||||
|
||||
@Override
|
||||
public void shutdownEntity(){}
|
||||
|
||||
@Override
|
||||
public void processEvent(SimEvent ev) {
|
||||
int tag = ev.getTag();
|
||||
|
||||
switch(tag){
|
||||
case Constants.SDN_PACKAGE: processPackage((Package) ev.getData()); break;
|
||||
case CloudSimTags.CLOUDLET_RETURN: processCloudletReturn((Cloudlet) ev.getData()); break;
|
||||
default: System.out.println("Unknown event received by "+super.getName()+". Tag:"+ev.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
private Vm findVm(int vmId) {
|
||||
List<Vm> vms = host.getVmList();
|
||||
for(Vm vm:vms) {
|
||||
if(vm.getId() == vmId) {
|
||||
return vm;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void processPackage(Package data) {
|
||||
int vmId = data.getDestination();
|
||||
Vm dstVm = findVm(vmId);
|
||||
|
||||
if (dstVm != null){//Try to deliver package to a hosted VM
|
||||
//Log.printLine(CloudSim.clock() + ": " + getName() + ".processPackage(): Deliver the request to dest VM: "+ dstVm);
|
||||
|
||||
data.setFinishTime(CloudSim.clock());
|
||||
|
||||
Request req = data.getPayload();
|
||||
Activity ac = req.removeNextActivity();
|
||||
processActivity(ac, req, vmId);
|
||||
} else if (middleboxes.containsKey(vmId)){//Try to deliver package to a hosted middlebox
|
||||
Request req = data.getPayload();
|
||||
Middlebox m = middleboxes.get(vmId);
|
||||
m.submitRequest(req);
|
||||
} else {//Something wrong - package doesn't come from/goes to a VM from this Host
|
||||
System.out.println("Warning package sent to wrong host. Host ID="+host.getId()+" DST VM ID="+vmId+", SRC VM ID="+data.getDestination());
|
||||
}
|
||||
}
|
||||
|
||||
private void processCloudletReturn(Cloudlet data) {
|
||||
Request req = requestsTable.remove(data);
|
||||
if (req.isFinished()){//return to user
|
||||
send(req.getUserId(),PROCESSING_DELAY,Constants.REQUEST_COMPLETED,req);
|
||||
} else {//consume next activity from request. It should be a transmission
|
||||
Activity ac = req.removeNextActivity();
|
||||
processActivity(ac, req, data.getVmId());
|
||||
}
|
||||
}
|
||||
|
||||
private void processActivity(Activity ac, Request req, int vmId) {
|
||||
if(ac instanceof Transmission) {
|
||||
Transmission tr = (Transmission)ac;
|
||||
|
||||
Package pkg = tr.getPackage();
|
||||
//send package to router via channel (NOS)
|
||||
nos.addPackageToChannel(this, pkg);
|
||||
|
||||
pkg.setStartTime(CloudSim.clock());
|
||||
}
|
||||
else if(ac instanceof Processing) {
|
||||
Cloudlet cl = ((Processing) ac).getCloudlet();
|
||||
cl.setVmId(vmId);
|
||||
|
||||
requestsTable.put(cl, req);
|
||||
sendNow(host.getDatacenter().getId(),CloudSimTags.CLOUDLET_SUBMIT,cl);
|
||||
} else {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Activity is unknown..");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/******* Routeable interface implementation methods ******/
|
||||
|
||||
@Override
|
||||
public int getAddress() {
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBandwidth() {
|
||||
return host.getBw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVMRoutingTable(){
|
||||
this.forwardingTable.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVMRoute(int src, int dest, int flowId, Node to){
|
||||
forwardingTable.addRule(src, dest, flowId, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getVMRoute(int src, int dest, int flowId){
|
||||
Node route= this.forwardingTable.getRoute(src, dest, flowId);
|
||||
if(route == null) {
|
||||
this.printVMRoute();
|
||||
System.err.println("SDNHost: ERROR: Cannot find route:" + src + "->"+dest + ", flow ="+flowId);
|
||||
}
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVMRoute(int src, int dest, int flowId){
|
||||
forwardingTable.removeRule(src, dest, flowId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRank(int rank) {
|
||||
this.rank=rank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRank() {
|
||||
return rank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printVMRoute() {
|
||||
forwardingTable.printForwardingTable(getName());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "SDNHost: "+this.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLink(Link l) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNetworkUtilization() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRoute(Node destHost, Link to) {
|
||||
this.routingTable.addRoute(destHost, to);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Link> getRoute(Node destHost) {
|
||||
return this.routingTable.getRoute(destHost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoutingTable getRoutingTable() {
|
||||
return this.routingTable;
|
||||
}
|
||||
}
|
||||
349
src/org/cloudbus/cloudsim/sdn/Switch.java
Normal file
349
src/org/cloudbus/cloudsim/sdn/Switch.java
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.core.SimEntity;
|
||||
import org.cloudbus.cloudsim.core.SimEvent;
|
||||
|
||||
|
||||
/**
|
||||
* This represents switches that maintain routing information.
|
||||
* Note that all traffic estimation is calculated within NOS class, not in Switch class.
|
||||
* Energy consumption of Switch is calculated in this class by utilization history.
|
||||
*
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Switch extends SimEntity implements Node{
|
||||
|
||||
//private static long cont=0;
|
||||
//private static long MULTI = 1;
|
||||
|
||||
private static double POWER_CONSUMPTION_IDLE = 66.7;
|
||||
private static double POWER_CONSUMPTION_PER_ACTIVE_PORT = 1;
|
||||
/* based on CARPO: Correlation-Aware Power Optimization in Data Center Networks by Xiaodong Wang et al. */
|
||||
|
||||
int bw;
|
||||
long iops;
|
||||
double previousTime;
|
||||
int rank = -1;
|
||||
int currentupports=0;
|
||||
int currentdownports=0;
|
||||
NetworkOperatingSystem nos;
|
||||
|
||||
Node[] upports;
|
||||
Node[] downports;
|
||||
|
||||
ArrayList<Link> links = new ArrayList<Link>();
|
||||
|
||||
ForwardingRule forwardingTable;
|
||||
RoutingTable routingTable;
|
||||
Hashtable<Package,Long> processingTable;
|
||||
|
||||
public Switch(String name, int bw, long iops, int upports, int downports, NetworkOperatingSystem nos) {
|
||||
super(name);
|
||||
this.bw = bw;
|
||||
this.iops = iops;
|
||||
this.previousTime = 0.0;
|
||||
this.nos=nos;
|
||||
|
||||
if (upports>0) this.upports = new Node[upports];
|
||||
this.downports = new Node[downports];
|
||||
|
||||
this.forwardingTable = new ForwardingRule();
|
||||
this.processingTable = new Hashtable<Package,Long>();
|
||||
this.routingTable = new RoutingTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEntity() {}
|
||||
|
||||
@Override
|
||||
public void shutdownEntity() {}
|
||||
|
||||
@Override
|
||||
public void processEvent(SimEvent ev) {
|
||||
int tag = ev.getTag();
|
||||
|
||||
switch(tag){
|
||||
//case Constants.SDN_INTERNAL_PACKAGE_PROCESS: internalPackageProcessing(); break;
|
||||
//case Constants.SDN_PACKAGE: sendToBuffer((Package) ev.getData()); break;
|
||||
default: System.out.println("Unknown event received by "+super.getName()+". Tag:"+ev.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
public void addLink(Link l){
|
||||
this.links.add(l);
|
||||
}
|
||||
|
||||
|
||||
/************************************************
|
||||
* Calculate Utilization history
|
||||
************************************************/
|
||||
private List<HistoryEntry> utilizationHistories = null;
|
||||
private static double powerOffDuration = 0; //if switch was idle for 1 hours, it's turned off.
|
||||
|
||||
public class HistoryEntry {
|
||||
public double startTime;
|
||||
public int numActivePorts;
|
||||
HistoryEntry(double t, int n) { startTime=t; numActivePorts=n;}
|
||||
}
|
||||
public List<HistoryEntry> getUtilizationHisotry() {
|
||||
return utilizationHistories;
|
||||
}
|
||||
|
||||
public double getUtilizationEnergyConsumption() {
|
||||
|
||||
double total=0;
|
||||
double lastTime=0;
|
||||
int lastPort=0;
|
||||
if(this.utilizationHistories == null)
|
||||
return 0;
|
||||
|
||||
for(HistoryEntry h:this.utilizationHistories) {
|
||||
double duration = h.startTime - lastTime;
|
||||
double power = calculatePower(lastPort);
|
||||
double energyConsumption = power * duration;
|
||||
|
||||
// Assume that the host is turned off when duration is long enough
|
||||
if(duration > powerOffDuration && lastPort == 0)
|
||||
energyConsumption = 0;
|
||||
|
||||
total += energyConsumption;
|
||||
lastTime = h.startTime;
|
||||
lastPort = h.numActivePorts;
|
||||
}
|
||||
return total/3600; // transform to Whatt*hour from What*seconds
|
||||
}
|
||||
public void updateNetworkUtilization() {
|
||||
this.addUtilizationEntry();
|
||||
}
|
||||
|
||||
public void addUtilizationEntryTermination(double finishTime) {
|
||||
if(this.utilizationHistories != null)
|
||||
this.utilizationHistories.add(new HistoryEntry(finishTime, 0));
|
||||
}
|
||||
|
||||
private void addUtilizationEntry() {
|
||||
double time = CloudSim.clock();
|
||||
int totalActivePorts = getTotalActivePorts();
|
||||
if(utilizationHistories == null)
|
||||
utilizationHistories = new ArrayList<HistoryEntry>();
|
||||
else {
|
||||
HistoryEntry hist = this.utilizationHistories.get(this.utilizationHistories.size()-1);
|
||||
if(hist.numActivePorts == totalActivePorts) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.utilizationHistories.add(new HistoryEntry(time, totalActivePorts));
|
||||
}
|
||||
private double calculatePower(int numActivePort) {
|
||||
double power = POWER_CONSUMPTION_IDLE + POWER_CONSUMPTION_PER_ACTIVE_PORT * numActivePort;
|
||||
return power;
|
||||
}
|
||||
private int getTotalActivePorts() {
|
||||
int num = 0;
|
||||
for(Link l:this.links) {
|
||||
if(l.isActive())
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
/*
|
||||
private void updateTime(double now) {
|
||||
this.previousTime = now;
|
||||
}
|
||||
private void internalPackageProcessing() {
|
||||
if(updatePackageProcessing()) {
|
||||
sendInternalEvent();
|
||||
}
|
||||
else {
|
||||
System.err.println(CloudSim.clock() + ": " + getName() +": Nothing changed! omg");
|
||||
sendInternalEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendInternalEvent() {
|
||||
CloudSim.cancelAll(getId(), new PredicateType(Constants.SDN_INTERNAL_PACKAGE_PROCESS));
|
||||
if(processingTable.size() != 0) {
|
||||
// More to process. Send event again
|
||||
double delay = this.nextFinishTime();
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ".sendInternalEvent(): next finish time: "+ delay);
|
||||
send(this.getId(), delay, Constants.SDN_INTERNAL_PACKAGE_PROCESS);
|
||||
}
|
||||
}
|
||||
|
||||
// Return if anything removed?
|
||||
private boolean updatePackageProcessing() {
|
||||
double currentTime = CloudSim.clock();
|
||||
double timeSpent = CloudSim.round(currentTime - this.previousTime);
|
||||
|
||||
if(timeSpent <= 0 || processingTable.size() == 0)
|
||||
return false; // Nothing changed
|
||||
|
||||
//update the amount of iops processed this round
|
||||
long processedThisRound= Math.round(timeSpent * iops * MULTI / processingTable.size())+1;
|
||||
|
||||
//update processing table; remove finished packs
|
||||
List<Package> toRemove = new ArrayList<Package>();
|
||||
for (Package key: processingTable.keySet()) {
|
||||
|
||||
//DEBUG ONLY
|
||||
if(key.payload.requestId == 309) {
|
||||
System.out.println("ID:309 HERE:rem_len="+processingTable.get(key)+","+key.size);
|
||||
}
|
||||
|
||||
long remainingLength = processingTable.get(key);
|
||||
remainingLength-=processedThisRound;
|
||||
|
||||
if (remainingLength <= 0) {// finished: remove from the list
|
||||
toRemove.add(key);
|
||||
} else { //not finished:update table, check if it is the smaller to be processed
|
||||
processingTable.put(key, remainingLength);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all packages that is done.
|
||||
for (Package pkg:toRemove){
|
||||
processingTable.remove(pkg);
|
||||
this.processPackageFinish(pkg);
|
||||
}
|
||||
updateTime(currentTime);
|
||||
|
||||
|
||||
System.err.println(CloudSim.clock()+": Switch.updatePackageProcessing("+getName()+ ") #("+this.processingTable.size()+"):Time spent:"+timeSpent+
|
||||
", Processed:"+processedThisRound);
|
||||
|
||||
if(toRemove.isEmpty())
|
||||
return false; // Nothing changed
|
||||
return true;
|
||||
}
|
||||
|
||||
private void processPackageFinish(Package pkg) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": finished processing a package:" + pkg);
|
||||
nos.sendPackageToNextHop(this, pkg);
|
||||
}
|
||||
|
||||
private void sendToBuffer(Package pkg) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Package received from Network:" + pkg);
|
||||
updatePackageProcessing();
|
||||
this.processingTable.put(pkg, pkg.getSize()*MULTI);
|
||||
sendInternalEvent();
|
||||
}
|
||||
|
||||
private double nextFinishTime() {
|
||||
// Calculate the latest finish time among all jobs in the queue.
|
||||
long smallerPkg = Long.MAX_VALUE;
|
||||
|
||||
for (Package key: processingTable.keySet()) {
|
||||
|
||||
// DEBUG
|
||||
if(key.getPayload().requestId > 30 && key.getPayload().requestId < 35) {
|
||||
System.out.println("Here!");
|
||||
}
|
||||
|
||||
if(key.getPayload().requestId > 530 && key.getPayload().requestId < 535) {
|
||||
System.out.println("Here!");
|
||||
}
|
||||
|
||||
|
||||
long remainingLength = processingTable.get(key);
|
||||
if (remainingLength<smallerPkg) smallerPkg=remainingLength;
|
||||
}
|
||||
|
||||
double delay = (double)smallerPkg/ iops / MULTI * processingTable.size();//smallerPkg*processingTable.size()/(iops*MULTI);
|
||||
delay=CloudSim.round(delay);
|
||||
|
||||
if (delay < CloudSim.getMinTimeBetweenEvents()) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": delay is too short: "+ delay);
|
||||
delay = CloudSim.getMinTimeBetweenEvents();
|
||||
}
|
||||
|
||||
return delay;
|
||||
}
|
||||
*/
|
||||
|
||||
/******* Routeable interface implementation methods ******/
|
||||
|
||||
@Override
|
||||
public int getAddress() {
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBandwidth() {
|
||||
return bw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVMRoutingTable(){
|
||||
this.forwardingTable.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVMRoute(int src, int dest, int flowId, Node to){
|
||||
this.forwardingTable.addRule(src, dest, flowId, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getVMRoute(int src, int dest, int flowId){
|
||||
Node route= this.forwardingTable.getRoute(src, dest, flowId);
|
||||
if(route == null) {
|
||||
this.printVMRoute();
|
||||
System.err.println("SDNSwitch.getRoute() ERROR: Cannot find route:" +
|
||||
NetworkOperatingSystem.debugVmIdName.get(src) + "->"+
|
||||
NetworkOperatingSystem.debugVmIdName.get(dest) + ", flow ="+flowId);
|
||||
}
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVMRoute(int src, int dest, int flowId){
|
||||
forwardingTable.removeRule(src, dest, flowId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRank(int rank) {
|
||||
this.rank = rank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRank() {
|
||||
return rank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printVMRoute() {
|
||||
forwardingTable.printForwardingTable(getName());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Switch: "+this.getName();
|
||||
}
|
||||
@Override
|
||||
public void addRoute(Node destHost, Link to) {
|
||||
this.routingTable.addRoute(destHost, to);
|
||||
|
||||
}
|
||||
@Override
|
||||
public List<Link> getRoute(Node destHost) {
|
||||
return this.routingTable.getRoute(destHost);
|
||||
}
|
||||
@Override
|
||||
public RoutingTable getRoutingTable() {
|
||||
return this.routingTable;
|
||||
}
|
||||
}
|
||||
48
src/org/cloudbus/cloudsim/sdn/TimedVm.java
Normal file
48
src/org/cloudbus/cloudsim/sdn/TimedVm.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
import org.cloudbus.cloudsim.CloudletScheduler;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
|
||||
/**
|
||||
* Extension of VM that supports to set start and terminate time of VM in VM creation request.
|
||||
* If start time and finish time is set up, specific CloudSim Event is triggered
|
||||
* in datacenter to create and terminate the VM.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class TimedVm extends Vm {
|
||||
|
||||
private double startTime;
|
||||
private double finishTime;
|
||||
|
||||
public TimedVm(int id, int userId, double mips, int numberOfPes, int ram,
|
||||
long bw, long size, String vmm, CloudletScheduler cloudletScheduler) {
|
||||
super(id, userId, mips, numberOfPes, ram, bw, size, vmm, cloudletScheduler);
|
||||
}
|
||||
|
||||
public TimedVm(int id, int userId, double mips, int numberOfPes, int ram,
|
||||
long bw, long size, String vmm, CloudletScheduler cloudletScheduler, double startTime, double finishTime) {
|
||||
super(id, userId, mips, numberOfPes, ram, bw, size, vmm, cloudletScheduler);
|
||||
|
||||
this.startTime = startTime;
|
||||
this.finishTime = finishTime;
|
||||
}
|
||||
|
||||
public double getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public double getFinishTime() {
|
||||
return finishTime;
|
||||
}
|
||||
|
||||
}
|
||||
65
src/org/cloudbus/cloudsim/sdn/Transmission.java
Normal file
65
src/org/cloudbus/cloudsim/sdn/Transmission.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn;
|
||||
|
||||
/**
|
||||
* This class represents transmission of a package. It controls
|
||||
* amount of data transmitted in a shared data medium. Relation between
|
||||
* Transmission and Channel is the same as Cloudlet and CloudletScheduler,
|
||||
* but here we consider only the time shared case, representing a shared
|
||||
* channel among different simultaneous package transmissions.
|
||||
* Note that estimated transmission time is calculated in NOS.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Transmission implements Activity {
|
||||
Package pkg;
|
||||
long amountToBeProcessed;
|
||||
|
||||
public Transmission(int origin, int destination, long size, int flowId, Request payload) {
|
||||
this.pkg = new Package(origin, destination, size, flowId, payload);
|
||||
this.amountToBeProcessed=pkg.getSize();
|
||||
}
|
||||
|
||||
public Transmission(Package pkg){
|
||||
this.pkg = pkg;
|
||||
this.amountToBeProcessed=pkg.getSize();
|
||||
}
|
||||
|
||||
public long getSize(){
|
||||
return amountToBeProcessed;
|
||||
}
|
||||
|
||||
public Package getPackage(){
|
||||
return pkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums some amount of data to the already transmitted data
|
||||
* @param completed amount of data completed since last update
|
||||
*/
|
||||
public void addCompletedLength(long completed){
|
||||
amountToBeProcessed-=completed;
|
||||
if (amountToBeProcessed<=0) amountToBeProcessed = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Say if the Package transmission finished or not.
|
||||
* @return true if transmission finished; false otherwise
|
||||
*/
|
||||
public boolean isCompleted(){
|
||||
return amountToBeProcessed==0;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Transmission:"+this.pkg.toString();
|
||||
}
|
||||
}
|
||||
260
src/org/cloudbus/cloudsim/sdn/example/LogPrinter.java
Normal file
260
src/org/cloudbus/cloudsim/sdn/example/LogPrinter.java
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.sdn.Activity;
|
||||
import org.cloudbus.cloudsim.sdn.Processing;
|
||||
import org.cloudbus.cloudsim.sdn.Request;
|
||||
import org.cloudbus.cloudsim.sdn.Switch;
|
||||
import org.cloudbus.cloudsim.sdn.Transmission;
|
||||
import org.cloudbus.cloudsim.sdn.Switch.HistoryEntry;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationHistoryEntry;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationInterface;
|
||||
|
||||
/**
|
||||
* This class is to print out logs into console.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class LogPrinter {
|
||||
public static void printEnergyConsumption(List<Host> hostList, List<Switch> switchList, double finishTime) {
|
||||
double hostEnergyConsumption = 0, switchEnergyConsumption = 0;
|
||||
|
||||
Log.printLine("========== HOST POWER CONSUMPTION AND DETAILED UTILIZATION ===========");
|
||||
for(Host host:hostList) {
|
||||
PowerUtilizationInterface scheduler = (PowerUtilizationInterface) host.getVmScheduler();
|
||||
scheduler.addUtilizationEntryTermination(finishTime);
|
||||
|
||||
double energy = scheduler.getUtilizationEnergyConsumption();
|
||||
Log.printLine("Host #"+host.getId()+": "+energy);
|
||||
hostEnergyConsumption+= energy;
|
||||
|
||||
printHostUtilizationHistory(scheduler.getUtilizationHisotry());
|
||||
|
||||
}
|
||||
|
||||
Log.printLine("========== SWITCH POWER CONSUMPTION AND DETAILED UTILIZATION ===========");
|
||||
for(Switch sw:switchList) {
|
||||
sw.addUtilizationEntryTermination(finishTime);
|
||||
double energy = sw.getUtilizationEnergyConsumption();
|
||||
Log.printLine("Switch #"+sw.getId()+": "+energy);
|
||||
switchEnergyConsumption+= energy;
|
||||
|
||||
printSwitchUtilizationHistory(sw.getUtilizationHisotry());
|
||||
|
||||
}
|
||||
Log.printLine("========== TOTAL POWER CONSUMPTION ===========");
|
||||
Log.printLine("Host energy consumed: "+hostEnergyConsumption);
|
||||
Log.printLine("Switch energy consumed: "+switchEnergyConsumption);
|
||||
Log.printLine("Total energy consumed: "+(hostEnergyConsumption+switchEnergyConsumption));
|
||||
|
||||
}
|
||||
|
||||
private static void printHostUtilizationHistory(
|
||||
List<PowerUtilizationHistoryEntry> utilizationHisotry) {
|
||||
if(utilizationHisotry != null)
|
||||
for(PowerUtilizationHistoryEntry h:utilizationHisotry) {
|
||||
Log.printLine(h.startTime+", "+h.usedMips);
|
||||
}
|
||||
}
|
||||
private static void printSwitchUtilizationHistory(List<HistoryEntry> utilizationHisotry) {
|
||||
if(utilizationHisotry != null)
|
||||
for(HistoryEntry h:utilizationHisotry) {
|
||||
Log.printLine(h.startTime+", "+h.numActivePorts);
|
||||
}
|
||||
}
|
||||
|
||||
static public String indent = ",";
|
||||
static public String tabSize = "10";
|
||||
static public String fString = "%"+tabSize+"s"+indent;
|
||||
static public String fInt = "%"+tabSize+"d"+indent;
|
||||
static public String fFloat = "%"+tabSize+".3f"+indent;
|
||||
|
||||
public static void printCloudletList(List<Cloudlet> list) {
|
||||
int size = list.size();
|
||||
Cloudlet cloudlet;
|
||||
|
||||
Log.printLine();
|
||||
Log.printLine("========== OUTPUT ==========");
|
||||
|
||||
Log.print(String.format(fString, "Cloudlet_ID"));
|
||||
Log.print(String.format(fString, "STATUS" ));
|
||||
Log.print(String.format(fString, "DataCenter_ID"));
|
||||
Log.print(String.format(fString, "VM_ID"));
|
||||
Log.print(String.format(fString, "Length"));
|
||||
Log.print(String.format(fString, "Time"));
|
||||
Log.print(String.format(fString, "Start Time"));
|
||||
Log.print(String.format(fString, "Finish Time"));
|
||||
Log.print("\n");
|
||||
|
||||
//DecimalFormat dft = new DecimalFormat("######.##");
|
||||
for (int i = 0; i < size; i++) {
|
||||
cloudlet = list.get(i);
|
||||
printCloudlet(cloudlet);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printCloudlet(Cloudlet cloudlet) {
|
||||
Log.print(String.format(fInt, cloudlet.getCloudletId()));
|
||||
|
||||
if (cloudlet.getCloudletStatus() == Cloudlet.SUCCESS) {
|
||||
Log.print(String.format(fString, "SUCCESS"));
|
||||
Log.print(String.format(fInt, cloudlet.getResourceId()));
|
||||
Log.print(String.format(fInt, cloudlet.getVmId()));
|
||||
Log.print(String.format(fInt, cloudlet.getCloudletLength()));
|
||||
Log.print(String.format(fFloat, cloudlet.getActualCPUTime()));
|
||||
Log.print(String.format(fFloat, cloudlet.getExecStartTime()));
|
||||
Log.print(String.format(fFloat, cloudlet.getFinishTime()));
|
||||
Log.print("\n");
|
||||
}
|
||||
else {
|
||||
Log.printLine("FAILED");
|
||||
}
|
||||
}
|
||||
|
||||
private static double startTime, finishTime;
|
||||
public static void printWorkloadList(List<Workload> wls) {
|
||||
int[] appIdNum = new int[SDNBroker.appId];
|
||||
double[] appIdTime = new double[SDNBroker.appId];
|
||||
double[] appIdStartTime = new double[SDNBroker.appId];
|
||||
double[] appIdFinishTime = new double[SDNBroker.appId];
|
||||
|
||||
double serveTime, totalTime = 0;
|
||||
|
||||
Log.printLine();
|
||||
Log.printLine("========== DETAILED RESPONSE TIME OF WORKLOADS ===========");
|
||||
|
||||
if(wls.size() == 0) return;
|
||||
|
||||
Log.print(String.format(fString, "App_ID"));
|
||||
printRequestTitle(wls.get(0).request);
|
||||
Log.print(String.format(fString, "ResponseTime"));
|
||||
Log.printLine();
|
||||
|
||||
for(Workload wl:wls) {
|
||||
Log.print(String.format(fInt, wl.appId));
|
||||
|
||||
startTime = finishTime = -1;
|
||||
printRequest(wl.request);
|
||||
|
||||
serveTime= (finishTime - startTime);
|
||||
Log.print(String.format(fFloat, serveTime));
|
||||
totalTime += serveTime;
|
||||
|
||||
appIdNum[wl.appId] ++; //How many workloads in this app.
|
||||
appIdTime[wl.appId] += serveTime;
|
||||
if(appIdStartTime[wl.appId] <=0) {
|
||||
appIdStartTime[wl.appId] = wl.time;
|
||||
}
|
||||
appIdFinishTime[wl.appId] = wl.time;
|
||||
Log.printLine();
|
||||
}
|
||||
|
||||
Log.printLine("========== AVERAGE RESULT OF WORKLOADS ===========");
|
||||
for(int i=0; i<SDNBroker.appId; i++) {
|
||||
Log.printLine("App Id ("+i+"): "+appIdNum[i]+" requests, Start=" + appIdStartTime[i]+
|
||||
", Finish="+appIdFinishTime[i]+", Rate="+(double)appIdNum[i]/(appIdFinishTime[i] - appIdStartTime[i])+
|
||||
" req/sec, Response time=" + appIdTime[i]/appIdNum[i]);
|
||||
}
|
||||
|
||||
//printGroupStatistics(WORKLOAD_GROUP_PRIORITY, appIdNum, appIdTime);
|
||||
|
||||
Log.printLine("Average Response Time:"+(totalTime / wls.size()));
|
||||
|
||||
}
|
||||
|
||||
private static void printRequestTitle(Request req) {
|
||||
//Log.print(String.format(fString, "Req_ID"));
|
||||
//Log.print(String.format(fFloat, req.getStartTime()));
|
||||
//Log.print(String.format(fFloat, req.getFinishTime()));
|
||||
|
||||
List<Activity> acts = req.getRemovedActivities();
|
||||
for(Activity act:acts) {
|
||||
if(act instanceof Transmission) {
|
||||
Transmission tr=(Transmission)act;
|
||||
Log.print(String.format(fString, "Tr:Size"));
|
||||
Log.print(String.format(fString, "Tr:Channel"));
|
||||
|
||||
Log.print(String.format(fString, "Tr:time"));
|
||||
Log.print(String.format(fString, "Tr:Start"));
|
||||
Log.print(String.format(fString, "Tr:End"));
|
||||
|
||||
printRequestTitle(tr.getPackage().getPayload());
|
||||
}
|
||||
else {
|
||||
Log.print(String.format(fString, "Pr:Size"));
|
||||
|
||||
Log.print(String.format(fString, "Pr:time"));
|
||||
Log.print(String.format(fString, "Pr:Start"));
|
||||
Log.print(String.format(fString, "Pr:End"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void printRequest(Request req) {
|
||||
//Log.print(String.format(fInt, req.getRequestId()));
|
||||
//Log.print(String.format(fFloat, req.getStartTime()));
|
||||
//Log.print(String.format(fFloat, req.getFinishTime()));
|
||||
|
||||
List<Activity> acts = req.getRemovedActivities();
|
||||
for(Activity act:acts) {
|
||||
if(act instanceof Transmission) {
|
||||
Transmission tr=(Transmission)act;
|
||||
Log.print(String.format(fInt, tr.getPackage().getSize()));
|
||||
Log.print(String.format(fInt, tr.getPackage().getFlowId()));
|
||||
|
||||
Log.print(String.format(fFloat, tr.getPackage().getFinishTime() - tr.getPackage().getStartTime()));
|
||||
Log.print(String.format(fFloat, tr.getPackage().getStartTime()));
|
||||
Log.print(String.format(fFloat, tr.getPackage().getFinishTime()));
|
||||
|
||||
printRequest(tr.getPackage().getPayload());
|
||||
}
|
||||
else {
|
||||
Processing pr=(Processing)act;
|
||||
Log.print(String.format(fInt, pr.getCloudlet().getCloudletLength()));
|
||||
|
||||
Log.print(String.format(fFloat, pr.getCloudlet().getActualCPUTime()));
|
||||
Log.print(String.format(fFloat, pr.getCloudlet().getExecStartTime()));
|
||||
Log.print(String.format(fFloat, pr.getCloudlet().getFinishTime()));
|
||||
|
||||
if(startTime == -1) startTime = pr.getCloudlet().getExecStartTime();
|
||||
finishTime=pr.getCloudlet().getFinishTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void printGroupStatistics(int groupSeperateNum, int[] appIdNum, double[] appIdTime) {
|
||||
|
||||
double prioritySum = 0, standardSum = 0;
|
||||
int priorityReqNum = 0, standardReqNum =0;
|
||||
|
||||
for(int i=0; i<SDNBroker.appId; i++) {
|
||||
double avgResponseTime = appIdTime[i]/appIdNum[i];
|
||||
if(i<groupSeperateNum) {
|
||||
prioritySum += avgResponseTime;
|
||||
priorityReqNum += appIdNum[i];
|
||||
}
|
||||
else {
|
||||
standardSum += avgResponseTime;
|
||||
standardReqNum += appIdNum[i];
|
||||
}
|
||||
}
|
||||
|
||||
Log.printLine("Average Response Time(Priority):"+(prioritySum / priorityReqNum));
|
||||
Log.printLine("Average Response Time(Standard):"+(standardSum / standardReqNum));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
175
src/org/cloudbus/cloudsim/sdn/example/SDNBroker.java
Normal file
175
src/org/cloudbus/cloudsim/sdn/example/SDNBroker.java
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.UtilizationModelFull;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.core.CloudSimTags;
|
||||
import org.cloudbus.cloudsim.core.SimEntity;
|
||||
import org.cloudbus.cloudsim.core.SimEvent;
|
||||
import org.cloudbus.cloudsim.sdn.Constants;
|
||||
import org.cloudbus.cloudsim.sdn.SDNDatacenter;
|
||||
|
||||
/**
|
||||
* Broker class for CloudSimSDN example. This class represents a broker (Service Provider)
|
||||
* who uses the Cloud data center.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class SDNBroker extends SimEntity {
|
||||
|
||||
private SDNDatacenter datacenter = null;
|
||||
private String applicationFileName = null;
|
||||
private List<String> workloadFileNames=null;
|
||||
|
||||
private List<Cloudlet> cloudletList;
|
||||
private List<Workload> workloads;
|
||||
|
||||
public SDNBroker(String name) throws Exception {
|
||||
super(name);
|
||||
this.workloadFileNames = new ArrayList<String>();
|
||||
this.cloudletList = new ArrayList<Cloudlet>();
|
||||
this.workloads = new ArrayList<Workload>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEntity() {
|
||||
sendNow(this.datacenter.getId(), Constants.APPLICATION_SUBMIT, this.applicationFileName);
|
||||
}
|
||||
@Override
|
||||
public void shutdownEntity() {
|
||||
List<Vm> vmList = this.datacenter.getVmList();
|
||||
for(Vm vm:vmList) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Shuttingdown.. VM:" + vm.getId());
|
||||
}
|
||||
}
|
||||
public void submitDeployApplication(SDNDatacenter dc, String filename) {
|
||||
this.datacenter = dc;
|
||||
this.applicationFileName = filename;
|
||||
}
|
||||
|
||||
public void submitRequests(String filename) {
|
||||
this.workloadFileNames.add(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEvent(SimEvent ev) {
|
||||
int tag = ev.getTag();
|
||||
|
||||
switch(tag){
|
||||
case CloudSimTags.VM_CREATE_ACK: processVmCreate(ev); break;
|
||||
case Constants.APPLICATION_SUBMIT_ACK: applicationSubmitCompleted(ev); break;
|
||||
case Constants.REQUEST_COMPLETED: requestCompleted(ev); break;
|
||||
default: System.out.println("Unknown event received by "+super.getName()+". Tag:"+ev.getTag());
|
||||
}
|
||||
}
|
||||
private void processVmCreate(SimEvent ev) {
|
||||
|
||||
}
|
||||
|
||||
private void requestCompleted(SimEvent ev) {
|
||||
|
||||
}
|
||||
|
||||
public List<Cloudlet> getCloudletReceivedList() {
|
||||
return cloudletList;
|
||||
}
|
||||
|
||||
public static int appId = 0;
|
||||
|
||||
private void applicationSubmitCompleted(SimEvent ev) {
|
||||
for(String workloadFileName:this.workloadFileNames) {
|
||||
scheduleRequest(workloadFileName);
|
||||
SDNBroker.appId++;
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleRequest(String workloadFile) {
|
||||
WorkloadParser rp = new WorkloadParser(workloadFile, this.getId(), new UtilizationModelFull(),
|
||||
this.datacenter.getVmNameIdTable(), this.datacenter.getFlowNameIdTable());
|
||||
|
||||
for(Workload wl: rp.getWorkloads()) {
|
||||
send(this.datacenter.getId(), wl.time, Constants.REQUEST_SUBMIT, wl.request);
|
||||
wl.appId = SDNBroker.appId;
|
||||
}
|
||||
|
||||
this.cloudletList.addAll(rp.getAllCloudlets());
|
||||
this.workloads.addAll(rp.getWorkloads());
|
||||
}
|
||||
|
||||
public List<Workload> getWorkloads() {
|
||||
return this.workloads;
|
||||
}
|
||||
/*
|
||||
private static int reqId=0;
|
||||
private void scheduleRequestTest() {
|
||||
|
||||
cloudletList = new ArrayList<Cloudlet>();
|
||||
int cloudletId = 0;
|
||||
|
||||
List<Vm> vmList = this.datacenter.getVmList();
|
||||
|
||||
Vm vm1 = vmList.get(0);
|
||||
Vm vm2 = vmList.get(1);
|
||||
Vm vm3 = vmList.get(2);
|
||||
|
||||
///////////////////////////////////////
|
||||
// req = vm1:p1 -> tr1 -> vm2:p2 -> tr2 -> vm3:p3 -> tr3 -> vm1:p4
|
||||
// req r1 r2 r3
|
||||
long fileSize = 300;
|
||||
long outputSize = 300;
|
||||
UtilizationModel utilizationModel = new UtilizationModelFull();
|
||||
|
||||
Cloudlet cloudlet1 = new Cloudlet(cloudletId++, 4000, 1, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
|
||||
Cloudlet cloudlet2 = new Cloudlet(cloudletId++, 30000, 1, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
|
||||
Cloudlet cloudlet3 = new Cloudlet(cloudletId++, 6000, 1, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
|
||||
Cloudlet cloudlet4 = new Cloudlet(cloudletId++, 10000, 1, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
|
||||
cloudlet1.setUserId(getId());
|
||||
cloudlet2.setUserId(getId());
|
||||
cloudlet3.setUserId(getId());
|
||||
cloudlet4.setUserId(getId());
|
||||
cloudlet1.setVmId(vm1.getId());
|
||||
cloudletList.add(cloudlet1);
|
||||
cloudletList.add(cloudlet2);
|
||||
cloudletList.add(cloudlet3);
|
||||
cloudletList.add(cloudlet4);
|
||||
Processing p1 = new Processing(cloudlet1);
|
||||
Processing p2 = new Processing(cloudlet2);
|
||||
Processing p3 = new Processing(cloudlet3);
|
||||
Processing p4 = new Processing(cloudlet4);
|
||||
|
||||
Request req = new Request(reqId++, getId(), getId());
|
||||
Request r1 = new Request(reqId++, getId(), getId());
|
||||
Request r2 = new Request(reqId++, getId(), getId());
|
||||
Request r3 = new Request(reqId++, getId(), getId());
|
||||
|
||||
r3.addActivity(p4);
|
||||
|
||||
Transmission tr3 = new Transmission(vm3.getId(), vm1.getId(), 30000, r3);
|
||||
r2.addActivity(p3);
|
||||
r2.addActivity(tr3);
|
||||
|
||||
Transmission tr2 = new Transmission(vm2.getId(), vm3.getId(), 7000, r2);
|
||||
r1.addActivity(p2);
|
||||
r1.addActivity(tr2);
|
||||
|
||||
Transmission tr1 = new Transmission(vm1.getId(), vm2.getId(), 3000, r1);
|
||||
req.addActivity(p1);
|
||||
req.addActivity(tr1);
|
||||
sendNow(this.datacenter.getId(), Constants.REQUEST_SUBMIT, req);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
332
src/org/cloudbus/cloudsim/sdn/example/SDNExample.java
Normal file
332
src/org/cloudbus/cloudsim/sdn/example/SDNExample.java
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.DatacenterCharacteristics;
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Storage;
|
||||
import org.cloudbus.cloudsim.VmAllocationPolicy;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.sdn.NetworkOperatingSystem;
|
||||
import org.cloudbus.cloudsim.sdn.SDNDatacenter;
|
||||
import org.cloudbus.cloudsim.sdn.Switch;
|
||||
import org.cloudbus.cloudsim.sdn.example.policies.VmAllocationPolicyCombinedLeastFullFirst;
|
||||
import org.cloudbus.cloudsim.sdn.example.policies.VmAllocationPolicyCombinedMostFullFirst;
|
||||
import org.cloudbus.cloudsim.sdn.example.policies.VmAllocationPolicyMipsLeastFullFirst;
|
||||
import org.cloudbus.cloudsim.sdn.example.policies.VmAllocationPolicyMipsMostFullFirst;
|
||||
import org.cloudbus.cloudsim.sdn.overbooking.OverbookingNetworkOperatingSystem;
|
||||
import org.cloudbus.cloudsim.sdn.overbooking.VmAllocationPolicyOverbooking;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationMaxHostInterface;
|
||||
|
||||
/**
|
||||
* CloudSimSDN example main program. It loads physical topology file, application
|
||||
* deployment configuration file and workload files, and run simulation.
|
||||
* Simulation result will be shown on the console
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class SDNExample {
|
||||
protected static String physicalTopologyFile = "dataset-energy/energy-physical.json";
|
||||
protected static String deploymentFile = "dataset-energy/energy-virtual.json";
|
||||
protected static String [] workload_files = {
|
||||
"dataset-energy/energy-workload.csv",
|
||||
//"sdn-example-workload-normal-user.csv",
|
||||
//"sdn-example-workload-prio-user-prio-ch.csv",
|
||||
//"sdn-example-workload-prio-user-normal-ch.csv",
|
||||
};
|
||||
|
||||
protected static List<String> workloads;
|
||||
|
||||
private static boolean logEnabled = true;
|
||||
|
||||
public interface VmAllocationPolicyFactory {
|
||||
public VmAllocationPolicy create(List<? extends Host> list);
|
||||
}
|
||||
enum VmAllocationPolicyEnum{ CombLFF, CombMFF, MipLFF, MipMFF, OverLFF, OverMFF, LFF, MFF, Overbooking}
|
||||
|
||||
private static void printUsage() {
|
||||
String runCmd = "java SDNExample";
|
||||
System.out.format("Usage: %s <LFF|MFF> [physical.json] [virtual.json] [workload1.csv] [workload2.csv] [...]\n", runCmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates main() to run this example.
|
||||
*
|
||||
* @param args the args
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void main(String[] args) {
|
||||
|
||||
workloads = new ArrayList<String>();
|
||||
|
||||
// Parse system arguments
|
||||
if(args.length < 1) {
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
VmAllocationPolicyEnum vmAllocPolicy = VmAllocationPolicyEnum.valueOf(args[0]);
|
||||
if(args.length > 1)
|
||||
physicalTopologyFile = args[1];
|
||||
if(args.length > 2)
|
||||
deploymentFile = args[2];
|
||||
if(args.length > 3)
|
||||
for(int i=3; i<args.length; i++) {
|
||||
workloads.add(args[i]);
|
||||
}
|
||||
else
|
||||
workloads = (List<String>) Arrays.asList(workload_files);
|
||||
|
||||
printArguments(physicalTopologyFile, deploymentFile, workloads);
|
||||
Log.printLine("Starting CloudSim SDN...");
|
||||
|
||||
try {
|
||||
// Initialize
|
||||
int num_user = 1; // number of cloud users
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
boolean trace_flag = false; // mean trace events
|
||||
CloudSim.init(num_user, calendar, trace_flag);
|
||||
|
||||
VmAllocationPolicyFactory vmAllocationFac = null;
|
||||
NetworkOperatingSystem snos = null;
|
||||
switch(vmAllocPolicy) {
|
||||
case CombMFF:
|
||||
case MFF:
|
||||
vmAllocationFac = new VmAllocationPolicyFactory() {
|
||||
public VmAllocationPolicy create(List<? extends Host> hostList) { return new VmAllocationPolicyCombinedMostFullFirst(hostList); }
|
||||
};
|
||||
snos = new SimpleNetworkOperatingSystem(physicalTopologyFile);
|
||||
break;
|
||||
case CombLFF:
|
||||
case LFF:
|
||||
vmAllocationFac = new VmAllocationPolicyFactory() {
|
||||
public VmAllocationPolicy create(List<? extends Host> hostList) { return new VmAllocationPolicyCombinedLeastFullFirst(hostList); }
|
||||
};
|
||||
snos = new SimpleNetworkOperatingSystem(physicalTopologyFile);
|
||||
break;
|
||||
case MipMFF:
|
||||
vmAllocationFac = new VmAllocationPolicyFactory() {
|
||||
public VmAllocationPolicy create(List<? extends Host> hostList) { return new VmAllocationPolicyMipsMostFullFirst(hostList); }
|
||||
};
|
||||
snos = new SimpleNetworkOperatingSystem(physicalTopologyFile);
|
||||
break;
|
||||
case MipLFF:
|
||||
vmAllocationFac = new VmAllocationPolicyFactory() {
|
||||
public VmAllocationPolicy create(List<? extends Host> hostList) { return new VmAllocationPolicyMipsLeastFullFirst(hostList); }
|
||||
};
|
||||
snos = new SimpleNetworkOperatingSystem(physicalTopologyFile);
|
||||
break;
|
||||
case Overbooking:
|
||||
vmAllocationFac = new VmAllocationPolicyFactory() {
|
||||
public VmAllocationPolicy create(List<? extends Host> hostList) { return new VmAllocationPolicyOverbooking(hostList); }
|
||||
};
|
||||
snos = new OverbookingNetworkOperatingSystem(physicalTopologyFile);
|
||||
break;
|
||||
default:
|
||||
System.err.println("Choose proper VM placement polilcy!");
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Create a Datacenter
|
||||
SDNDatacenter datacenter = createSDNDatacenter("Datacenter_0", physicalTopologyFile, snos, vmAllocationFac);
|
||||
|
||||
// Broker
|
||||
SDNBroker broker = createBroker();
|
||||
int brokerId = broker.getId();
|
||||
|
||||
// Submit virtual topology
|
||||
broker.submitDeployApplication(datacenter, deploymentFile);
|
||||
|
||||
// Submit individual workloads
|
||||
submitWorkloads(broker);
|
||||
|
||||
// Sixth step: Starts the simulation
|
||||
if(!SDNExample.logEnabled)
|
||||
Log.disable();
|
||||
|
||||
double finishTime = CloudSim.startSimulation();
|
||||
CloudSim.stopSimulation();
|
||||
Log.enable();
|
||||
|
||||
Log.printLine(finishTime+": ========== EXPERIMENT FINISHED ===========");
|
||||
|
||||
// Print results when simulation is over
|
||||
//*
|
||||
List<Cloudlet> newList = broker.getCloudletReceivedList();
|
||||
|
||||
if(SDNExample.logEnabled)
|
||||
LogPrinter.printCloudletList(newList);
|
||||
|
||||
List<Workload> wls = broker.getWorkloads();
|
||||
LogPrinter.printWorkloadList(wls);
|
||||
//*/
|
||||
|
||||
// Print hosts' and switches' total utilization.
|
||||
List<Host> hostList = nos.getHostList();
|
||||
List<Switch> switchList = nos.getSwitchList();
|
||||
LogPrinter.printEnergyConsumption(hostList, switchList, finishTime);
|
||||
|
||||
Log.printLine("Simultanously used hosts:"+maxHostHandler.getMaxNumHostsUsed());
|
||||
Log.printLine("CloudSim SDN finished!");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.printLine("Unwanted errors happen");
|
||||
}
|
||||
}
|
||||
|
||||
public static void submitWorkloads(SDNBroker broker) {
|
||||
// Submit workload files individually
|
||||
if(workloads != null) {
|
||||
for(String workload:workloads)
|
||||
broker.submitRequests(workload);
|
||||
}
|
||||
|
||||
// Or, Submit groups of workloads
|
||||
//submitGroupWorkloads(broker, WORKLOAD_GROUP_NUM, WORKLOAD_GROUP_PRIORITY, WORKLOAD_GROUP_FILENAME, WORKLOAD_GROUP_FILENAME_BG);
|
||||
}
|
||||
|
||||
public static void printArguments(String physical, String virtual, List<String> workloads) {
|
||||
System.out.println("Data center infrastructure (Physical Topology) : "+ physical);
|
||||
System.out.println("Virtual Machine and Network requests (Virtual Topology) : "+ virtual);
|
||||
System.out.println("Workloads: ");
|
||||
for(String work:workloads)
|
||||
System.out.println(" "+work);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the datacenter.
|
||||
*
|
||||
* @param name the name
|
||||
*
|
||||
* @return the datacenter
|
||||
*/
|
||||
protected static NetworkOperatingSystem nos;
|
||||
protected static PowerUtilizationMaxHostInterface maxHostHandler = null;
|
||||
protected static SDNDatacenter createSDNDatacenter(String name, String physicalTopology, NetworkOperatingSystem snos, VmAllocationPolicyFactory vmAllocationFactory) {
|
||||
// In order to get Host information, pre-create NOS.
|
||||
nos=snos;
|
||||
List<Host> hostList = nos.getHostList();
|
||||
|
||||
String arch = "x86"; // system architecture
|
||||
String os = "Linux"; // operating system
|
||||
String vmm = "Xen";
|
||||
|
||||
double time_zone = 10.0; // time zone this resource located
|
||||
double cost = 3.0; // the cost of using processing in this resource
|
||||
double costPerMem = 0.05; // the cost of using memory in this resource
|
||||
double costPerStorage = 0.001; // the cost of using storage in this
|
||||
// resource
|
||||
double costPerBw = 0.0; // the cost of using bw in this resource
|
||||
LinkedList<Storage> storageList = new LinkedList<Storage>(); // we are not adding SAN
|
||||
// devices by now
|
||||
|
||||
DatacenterCharacteristics characteristics = new DatacenterCharacteristics(
|
||||
arch, os, vmm, hostList, time_zone, cost, costPerMem,
|
||||
costPerStorage, costPerBw);
|
||||
|
||||
// Create Datacenter with previously set parameters
|
||||
SDNDatacenter datacenter = null;
|
||||
try {
|
||||
VmAllocationPolicy vmPolicy = vmAllocationFactory.create(hostList);
|
||||
maxHostHandler = (PowerUtilizationMaxHostInterface)vmPolicy;
|
||||
datacenter = new SDNDatacenter(name, characteristics, vmPolicy, storageList, 0, nos);
|
||||
|
||||
|
||||
nos.setDatacenter(datacenter);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return datacenter;
|
||||
}
|
||||
|
||||
// We strongly encourage users to develop their own broker policies, to
|
||||
// submit vms and cloudlets according
|
||||
// to the specific rules of the simulated scenario
|
||||
/**
|
||||
* Creates the broker.
|
||||
*
|
||||
* @return the datacenter broker
|
||||
*/
|
||||
protected static SDNBroker createBroker() {
|
||||
SDNBroker broker = null;
|
||||
try {
|
||||
broker = new SDNBroker("Broker");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return broker;
|
||||
}
|
||||
|
||||
|
||||
static String WORKLOAD_GROUP_FILENAME = "workload_10sec_100_default.csv"; // group 0~9
|
||||
static String WORKLOAD_GROUP_FILENAME_BG = "workload_10sec_100.csv"; // group 10~29
|
||||
static int WORKLOAD_GROUP_NUM = 50;
|
||||
static int WORKLOAD_GROUP_PRIORITY = 1;
|
||||
|
||||
public static void submitGroupWorkloads(SDNBroker broker, int workloadsNum, int groupSeperateNum, String filename_suffix_group1, String filename_suffix_group2) {
|
||||
for(int set=0; set<workloadsNum; set++) {
|
||||
String filename = filename_suffix_group1;
|
||||
if(set>=groupSeperateNum)
|
||||
filename = filename_suffix_group2;
|
||||
|
||||
filename = set+"_"+filename;
|
||||
broker.submitRequests(filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Under development
|
||||
/*
|
||||
static class WorkloadGroup {
|
||||
static int autoIdGenerator = 0;
|
||||
final int groupId;
|
||||
|
||||
String groupFilenamePrefix;
|
||||
int groupFilenameStart;
|
||||
int groupFileNum;
|
||||
|
||||
WorkloadGroup(int id, String groupFilenamePrefix, int groupFileNum, int groupFilenameStart) {
|
||||
this.groupId = id;
|
||||
this.groupFilenamePrefix = groupFilenamePrefix;
|
||||
this.groupFileNum = groupFileNum;
|
||||
}
|
||||
|
||||
List<String> getFileList() {
|
||||
List<String> filenames = new LinkedList<String>();
|
||||
|
||||
for(int fileId=groupFilenameStart; fileId< this.groupFilenameStart+this.groupFileNum; fileId++) {
|
||||
String filename = groupFilenamePrefix + fileId;
|
||||
filenames.add(filename);
|
||||
}
|
||||
return filenames;
|
||||
}
|
||||
|
||||
public static WorkloadGroup createWorkloadGroup(String groupFilenamePrefix, int groupFileNum) {
|
||||
return new WorkloadGroup(autoIdGenerator++, groupFilenamePrefix, groupFileNum, 0);
|
||||
}
|
||||
public static WorkloadGroup createWorkloadGroup(String groupFilenamePrefix, int groupFileNum, int groupFilenameStart) {
|
||||
return new WorkloadGroup(autoIdGenerator++, groupFilenamePrefix, groupFileNum, groupFilenameStart);
|
||||
}
|
||||
}
|
||||
|
||||
static LinkedList<WorkloadGroup> workloadGroups = new LinkedList<WorkloadGroup>();
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.core.CloudSimTags;
|
||||
import org.cloudbus.cloudsim.core.SimEvent;
|
||||
import org.cloudbus.cloudsim.sdn.Arc;
|
||||
import org.cloudbus.cloudsim.sdn.Link;
|
||||
import org.cloudbus.cloudsim.sdn.Middlebox;
|
||||
import org.cloudbus.cloudsim.sdn.NetworkOperatingSystem;
|
||||
import org.cloudbus.cloudsim.sdn.Node;
|
||||
import org.cloudbus.cloudsim.sdn.SDNHost;
|
||||
import org.cloudbus.cloudsim.sdn.TimedVm;
|
||||
|
||||
/**
|
||||
* Simple network operating system class for the example.
|
||||
* In this example, network operating system (aka SDN controller) finds shortest path
|
||||
* when deploying the application onto the cloud.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class SimpleNetworkOperatingSystem extends NetworkOperatingSystem {
|
||||
|
||||
public SimpleNetworkOperatingSystem(String fileName) {
|
||||
super(fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deployApplication(List<Vm> vms, List<Middlebox> middleboxes, List<Arc> links) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Starting deploying application..");
|
||||
|
||||
for(Vm vm:vms)
|
||||
{
|
||||
TimedVm tvm = (TimedVm) vm;
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Trying to Create VM #" + vm.getId()
|
||||
+ " in " + datacenter.getName() + ", (" + tvm.getStartTime() + "~" +tvm.getFinishTime() + ")");
|
||||
send(datacenter.getId(), tvm.getStartTime(), CloudSimTags.VM_CREATE_ACK, vm);
|
||||
|
||||
if(tvm.getFinishTime() != Double.POSITIVE_INFINITY) {
|
||||
//System.err.println("VM will be terminated at: "+tvm.getFinishTime());
|
||||
send(datacenter.getId(), tvm.getFinishTime(), CloudSimTags.VM_DESTROY, vm);
|
||||
send(this.getId(), tvm.getFinishTime(), CloudSimTags.VM_DESTROY, vm);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean deployFlow(List<Arc> links) {
|
||||
for(Arc link:links) {
|
||||
int srcVm = link.getSrcId();
|
||||
int dstVm = link.getDstId();
|
||||
int flowId = link.getFlowId();
|
||||
|
||||
SDNHost srchost = findSDNHost(srcVm);
|
||||
SDNHost dsthost = findSDNHost(dstVm);
|
||||
if(srchost == null || dsthost == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(srchost.equals(dsthost)) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Source SDN Host is same as Destination. Go loopback");
|
||||
srchost.addVMRoute(srcVm, dstVm, flowId, dsthost);
|
||||
}
|
||||
else {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": VMs are in different hosts. Create entire routing table (hosts, switches)");
|
||||
boolean findRoute = buildForwardingTables(srchost, srcVm, dstVm, flowId, null);
|
||||
|
||||
if(!findRoute) {
|
||||
System.err.println("SimpleNetworkOperatingSystem.deployFlow: Could not find route!!" +
|
||||
NetworkOperatingSystem.debugVmIdName.get(srcVm) + "->"+NetworkOperatingSystem.debugVmIdName.get(dstVm));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Print all routing tables.
|
||||
for(Node node:this.topology.getAllNodes()) {
|
||||
node.printVMRoute();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Link selectLinkFirst(List<Link> links) {
|
||||
return links.get(0);
|
||||
}
|
||||
|
||||
int i=0;
|
||||
private Link selectLinkRandom(List<Link> links) {
|
||||
return links.get(i++ % links.size());
|
||||
}
|
||||
|
||||
private Link selectLinkByFlow(List<Link> links, int flowId) {
|
||||
if(flowId == -1)
|
||||
return links.get(0);
|
||||
else
|
||||
return links.get(1 % links.size());
|
||||
|
||||
}
|
||||
|
||||
private Link selectLinkByChannelCount(Node from, List<Link> links) {
|
||||
Link lighter = links.get(0);
|
||||
for(Link l:links) {
|
||||
if(l.getChannelCount(from) < lighter.getChannelCount(from)) {
|
||||
// Less traffic flows using this link
|
||||
lighter = l;
|
||||
}
|
||||
}
|
||||
return lighter;
|
||||
}
|
||||
|
||||
private Link selectLinkByDestination(List<Link> links, SDNHost destHost) {
|
||||
int numLinks = links.size();
|
||||
int linkid = destHost.getAddress() % numLinks;
|
||||
Link link = links.get(linkid);
|
||||
return link;
|
||||
}
|
||||
|
||||
private boolean buildForwardingTables(Node node, int srcVm, int dstVm, int flowId, Node prevNode) {
|
||||
// There are many links. Determine which hop to go.
|
||||
SDNHost desthost = findSDNHost(dstVm);
|
||||
if(node.equals(desthost))
|
||||
return true;
|
||||
|
||||
List<Link> nextLinks = node.getRoute(desthost);
|
||||
|
||||
// Let's choose the first link. make simple
|
||||
Link nextLink = selectLinkByFlow(nextLinks, flowId);
|
||||
//Link nextLink = selectLinkRandom(nextLinks);
|
||||
//Link nextLink = selectBestLink(node, nextLinks);
|
||||
//Link nextLink = selectRandomTreeLink(nextLinks, desthost);
|
||||
Node nextHop = nextLink.getOtherNode(node);
|
||||
|
||||
node.addVMRoute(srcVm, dstVm, flowId, nextHop);
|
||||
buildForwardingTables(nextHop, srcVm, dstVm, flowId, null);
|
||||
|
||||
return true;
|
||||
|
||||
/*
|
||||
Collection<Link> links = this.topology.getAdjacentLinks(node);
|
||||
if(links.size() == 0) {
|
||||
// No link. Do nothing
|
||||
}
|
||||
else if(links.size() == 1) {
|
||||
// Only one way, no other choice (for Host to Edge switch)
|
||||
for(Link l:links) {
|
||||
Node nextHop= l.getHighOrder();
|
||||
if(nextHop.equals(node))
|
||||
nextHop= l.getLowOrder();
|
||||
|
||||
node.addVMRoute(srcVm, dstVm, flowId, nextHop);
|
||||
buildForwardingTables(nextHop, srcVm, dstVm, flowId, node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// There are many links. Determine which hop to go.
|
||||
SDNHost dsthost = findSDNHost(dstVm);
|
||||
|
||||
for(Link l:links) {
|
||||
Node nextHop= l.getOtherNode(node);
|
||||
|
||||
if(nextHop.equals(prevNode)) {
|
||||
// NextHop is going back to prev node
|
||||
continue;
|
||||
}
|
||||
else if(nextHop.equals(dsthost)) {
|
||||
// NextHop is the destination. Just add. No further route finding.
|
||||
node.addVMRoute(srcVm, dstVm, flowId, nextHop);
|
||||
return true;
|
||||
}
|
||||
else if(nextHop instanceof SDNHost) {
|
||||
// NextHop is host but no destination. Can't forward
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// Nexthop is switch
|
||||
if(buildForwardingTables(nextHop, srcVm, dstVm, flowId, node)) {
|
||||
// If the route is right.
|
||||
node.addVMRoute(srcVm, dstVm, flowId, nextHop);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Middlebox deployMiddlebox(String type,Vm vm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processVmCreateAck(SimEvent ev) {
|
||||
// print the created VM info
|
||||
TimedVm vm = (TimedVm) ev.getData();
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": VM Created: " + vm.getId() + " in " + this.findSDNHost(vm.getId()));
|
||||
deployFlow(this.arcList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
|
||||
public class VmAllocationPolicyCombinedLeastFullFirst extends VmAllocationPolicyCombinedMostFullFirst{
|
||||
|
||||
public VmAllocationPolicyCombinedLeastFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / hostTotalMips;
|
||||
double bwFreePercent = (double)getFreeBw().get(i) / hostTotalBw;
|
||||
|
||||
freeResources[i] = convertWeightedMetric(mipsFreePercent, bwFreePercent);
|
||||
}
|
||||
|
||||
for(int tries = 0; tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double moreFree = Double.NEGATIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] > moreFree) {
|
||||
moreFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(idx==-1) {
|
||||
System.err.println("Cannot assign the VM to any host:"+tries+"/"+numHosts);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeResources[idx] = Double.NEGATIVE_INFINITY;
|
||||
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if(getFreeMips().get(idx) < requiredMips ||
|
||||
getFreeBw().get(idx) < requiredBw ||
|
||||
getFreePes().get(idx) < requiredPes) {
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
break;
|
||||
}
|
||||
}
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.VmAllocationPolicy;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
|
||||
public class VmAllocationPolicyCombinedMostFullFirst extends VmAllocationPolicy {
|
||||
|
||||
protected final double hostTotalMips;
|
||||
protected final double hostTotalBw;
|
||||
protected final int hostTotalPes;
|
||||
|
||||
/** The vm table. */
|
||||
private Map<String, Host> vmTable;
|
||||
|
||||
/** The used pes. */
|
||||
private Map<String, Integer> usedPes;
|
||||
|
||||
/** The free pes. */
|
||||
private List<Integer> freePes;
|
||||
|
||||
private Map<String, Long> usedMips;
|
||||
private List<Long> freeMips;
|
||||
private Map<String, Long> usedBw;
|
||||
private List<Long> freeBw;
|
||||
|
||||
/**
|
||||
* Creates the new VmAllocationPolicySimple object.
|
||||
*
|
||||
* @param list the list
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
public VmAllocationPolicyCombinedMostFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
|
||||
setFreePes(new ArrayList<Integer>());
|
||||
setFreeMips(new ArrayList<Long>());
|
||||
setFreeBw(new ArrayList<Long>());
|
||||
|
||||
for (Host host : getHostList()) {
|
||||
getFreePes().add(host.getNumberOfPes());
|
||||
getFreeMips().add((long) host.getTotalMips());
|
||||
getFreeBw().add(host.getBw());
|
||||
}
|
||||
hostTotalMips = getHostList().get(0).getTotalMips();
|
||||
hostTotalBw = getHostList().get(0).getBw();
|
||||
hostTotalPes = getHostList().get(0).getNumberOfPes();
|
||||
|
||||
setVmTable(new HashMap<String, Host>());
|
||||
setUsedPes(new HashMap<String, Integer>());
|
||||
setUsedMips(new HashMap<String, Long>());
|
||||
setUsedBw(new HashMap<String, Long>());
|
||||
}
|
||||
|
||||
protected double convertWeightedMetric(double mipsPercent, double bwPercent) {
|
||||
double ret = mipsPercent * bwPercent;
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / this.hostTotalMips;
|
||||
double bwFreePercent = (double)getFreeBw().get(i) / this.hostTotalBw;
|
||||
|
||||
freeResources[i] = this.convertWeightedMetric(mipsFreePercent, bwFreePercent);
|
||||
}
|
||||
|
||||
for(int tries = 0; result == false && tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double lessFree = Double.POSITIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] < lessFree) {
|
||||
lessFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
freeResources[idx] = Double.POSITIVE_INFINITY;
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if(getFreeMips().get(idx) < requiredMips ||
|
||||
getFreeBw().get(idx) < requiredBw ||
|
||||
getFreePes().get(idx) < requiredPes) {
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected int maxNumHostsUsed=0;
|
||||
protected void logMaxNumHostsUsed() {
|
||||
// Get how many are used
|
||||
int numHostsUsed=0;
|
||||
for(int freePes:getFreePes()) {
|
||||
if(freePes < hostTotalPes) {
|
||||
numHostsUsed++;
|
||||
}
|
||||
}
|
||||
if(maxNumHostsUsed < numHostsUsed)
|
||||
maxNumHostsUsed = numHostsUsed;
|
||||
System.err.println("Number of online hosts:"+numHostsUsed + ", max was ="+maxNumHostsUsed);
|
||||
|
||||
|
||||
}
|
||||
public int getMaxNumHostsUsed() { return maxNumHostsUsed;}
|
||||
|
||||
/**
|
||||
* Releases the host used by a VM.
|
||||
*
|
||||
* @param vm the vm
|
||||
* @pre $none
|
||||
* @post none
|
||||
*/
|
||||
@Override
|
||||
public void deallocateHostForVm(Vm vm) {
|
||||
Host host = getVmTable().remove(vm.getUid());
|
||||
if (host != null) {
|
||||
int idx = getHostList().indexOf(host);
|
||||
host.vmDestroy(vm);
|
||||
|
||||
Integer pes = getUsedPes().remove(vm.getUid());
|
||||
getFreePes().set(idx, getFreePes().get(idx) + pes);
|
||||
|
||||
Long mips = getUsedMips().remove(vm.getUid());
|
||||
getFreeMips().set(idx, getFreeMips().get(idx) + mips);
|
||||
|
||||
Long bw = getUsedBw().remove(vm.getUid());
|
||||
getFreeBw().set(idx, getFreeBw().get(idx) + bw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host that is executing the given VM belonging to the given user.
|
||||
*
|
||||
* @param vm the vm
|
||||
* @return the Host with the given vmID and userID; $null if not found
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public Host getHost(Vm vm) {
|
||||
return getVmTable().get(vm.getUid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host that is executing the given VM belonging to the given user.
|
||||
*
|
||||
* @param vmId the vm id
|
||||
* @param userId the user id
|
||||
* @return the Host with the given vmID and userID; $null if not found
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public Host getHost(int vmId, int userId) {
|
||||
return getVmTable().get(Vm.getUid(userId, vmId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the vm table.
|
||||
*
|
||||
* @return the vm table
|
||||
*/
|
||||
public Map<String, Host> getVmTable() {
|
||||
return vmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vm table.
|
||||
*
|
||||
* @param vmTable the vm table
|
||||
*/
|
||||
protected void setVmTable(Map<String, Host> vmTable) {
|
||||
this.vmTable = vmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the used pes.
|
||||
*
|
||||
* @return the used pes
|
||||
*/
|
||||
protected Map<String, Integer> getUsedPes() {
|
||||
return usedPes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the used pes.
|
||||
*
|
||||
* @param usedPes the used pes
|
||||
*/
|
||||
protected void setUsedPes(Map<String, Integer> usedPes) {
|
||||
this.usedPes = usedPes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the free pes.
|
||||
*
|
||||
* @return the free pes
|
||||
*/
|
||||
protected List<Integer> getFreePes() {
|
||||
return freePes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the free pes.
|
||||
*
|
||||
* @param freePes the new free pes
|
||||
*/
|
||||
protected void setFreePes(List<Integer> freePes) {
|
||||
this.freePes = freePes;
|
||||
}
|
||||
|
||||
protected Map<String, Long> getUsedMips() {
|
||||
return usedMips;
|
||||
}
|
||||
protected void setUsedMips(Map<String, Long> usedMips) {
|
||||
this.usedMips = usedMips;
|
||||
}
|
||||
protected Map<String, Long> getUsedBw() {
|
||||
return usedBw;
|
||||
}
|
||||
protected void setUsedBw(Map<String, Long> usedBw) {
|
||||
this.usedBw = usedBw;
|
||||
}
|
||||
protected List<Long> getFreeMips() {
|
||||
return this.freeMips;
|
||||
}
|
||||
protected void setFreeMips(List<Long> freeMips) {
|
||||
this.freeMips = freeMips;
|
||||
}
|
||||
|
||||
protected List<Long> getFreeBw() {
|
||||
return this.freeBw;
|
||||
}
|
||||
protected void setFreeBw(List<Long> freeBw) {
|
||||
this.freeBw = freeBw;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.VmAllocationPolicy#optimizeAllocation(double, cloudsim.VmList, double)
|
||||
*/
|
||||
@Override
|
||||
public List<Map<String, Object>> optimizeAllocation(List<? extends Vm> vmList) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.cloudbus.cloudsim.VmAllocationPolicy#allocateHostForVm(org.cloudbus.cloudsim.Vm,
|
||||
* org.cloudbus.cloudsim.Host)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm, Host host) {
|
||||
if (host.vmCreate(vm)) { // if vm has been succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
int idx = getHostList().indexOf(host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
Log.formatLine(
|
||||
"%.2f: VM #" + vm.getId() + " has been allocated to the host #" + host.getId(),
|
||||
CloudSim.clock());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
|
||||
public class VmAllocationPolicyMipsLeastFullFirst extends VmAllocationPolicyCombinedMostFullFirst{
|
||||
|
||||
public VmAllocationPolicyMipsLeastFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / hostTotalMips;
|
||||
//double bwFreePercent = (double)getFreeBw().get(i) / hostTotalBw;
|
||||
|
||||
freeResources[i] = mipsFreePercent;
|
||||
}
|
||||
|
||||
for(int tries = 0; tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double moreFree = Double.NEGATIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] > moreFree) {
|
||||
moreFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(idx==-1) {
|
||||
System.err.println("Cannot assign the VM to any host:"+tries+"/"+numHosts);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeResources[idx] = Double.NEGATIVE_INFINITY;
|
||||
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if(getFreeMips().get(idx) < requiredMips ||
|
||||
getFreeBw().get(idx) < requiredBw ||
|
||||
getFreePes().get(idx) < requiredPes) {
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
break;
|
||||
}
|
||||
}
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
|
||||
public class VmAllocationPolicyMipsMostFullFirst extends VmAllocationPolicyCombinedMostFullFirst{
|
||||
|
||||
public VmAllocationPolicyMipsMostFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / this.hostTotalMips;
|
||||
|
||||
freeResources[i] = mipsFreePercent;
|
||||
}
|
||||
|
||||
for(int tries = 0; result == false && tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double lessFree = Double.POSITIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] < lessFree) {
|
||||
lessFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
freeResources[idx] = Double.POSITIVE_INFINITY;
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if(getFreeMips().get(idx) < requiredMips ||
|
||||
getFreeBw().get(idx) < requiredBw ||
|
||||
getFreePes().get(idx) < requiredPes) {
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Title: CloudSim Toolkit
|
||||
* Description: CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2009-2012, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Pe;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.VmScheduler;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
|
||||
/**
|
||||
* VmSchedulerSpaceShared is a VMM allocation policy that allocates one or more Pe to a VM, and
|
||||
* doesn't allow sharing of PEs. If there is no free PEs to the VM, allocation fails. Free PEs are
|
||||
* not allocated to VMs
|
||||
*
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @author Anton Beloglazov
|
||||
* @since CloudSim Toolkit 1.0
|
||||
*/
|
||||
public class VmSchedulerSpaceSharedEnergy extends VmScheduler {
|
||||
|
||||
/** Map containing VM ID and a vector of PEs allocated to this VM. */
|
||||
private Map<String, List<Pe>> peAllocationMap;
|
||||
|
||||
/** The free pes vector. */
|
||||
private List<Pe> freePes;
|
||||
|
||||
/**
|
||||
* Instantiates a new vm scheduler space shared.
|
||||
*
|
||||
* @param pelist the pelist
|
||||
*/
|
||||
public VmSchedulerSpaceSharedEnergy(List<? extends Pe> pelist) {
|
||||
super(pelist);
|
||||
setPeAllocationMap(new HashMap<String, List<Pe>>());
|
||||
setFreePes(new ArrayList<Pe>());
|
||||
getFreePes().addAll(pelist);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.cloudbus.cloudsim.VmScheduler#allocatePesForVm(org.cloudbus.cloudsim.Vm,
|
||||
* java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocatePesForVm(Vm vm, List<Double> mipsShare) {
|
||||
// if there is no enough free PEs, fails
|
||||
if (getFreePes().size() < mipsShare.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Pe> selectedPes = new ArrayList<Pe>();
|
||||
Iterator<Pe> peIterator = getFreePes().iterator();
|
||||
Pe pe = peIterator.next();
|
||||
double totalMips = 0;
|
||||
for (Double mips : mipsShare) {
|
||||
if (mips <= pe.getMips()) {
|
||||
selectedPes.add(pe);
|
||||
totalMips += mips;
|
||||
if (!peIterator.hasNext()) {
|
||||
break;
|
||||
}
|
||||
pe = peIterator.next();
|
||||
}
|
||||
}
|
||||
if (mipsShare.size() > selectedPes.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
getFreePes().removeAll(selectedPes);
|
||||
|
||||
getPeAllocationMap().put(vm.getUid(), selectedPes);
|
||||
getMipsMap().put(vm.getUid(), mipsShare);
|
||||
setAvailableMips(getAvailableMips() - totalMips);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.cloudbus.cloudsim.VmScheduler#deallocatePesForVm(org.cloudbus.cloudsim.Vm)
|
||||
*/
|
||||
@Override
|
||||
public void deallocatePesForVm(Vm vm) {
|
||||
getFreePes().addAll(getPeAllocationMap().get(vm.getUid()));
|
||||
getPeAllocationMap().remove(vm.getUid());
|
||||
|
||||
double totalMips = 0;
|
||||
for (double mips : getMipsMap().get(vm.getUid())) {
|
||||
totalMips += mips;
|
||||
}
|
||||
setAvailableMips(getAvailableMips() + totalMips);
|
||||
|
||||
getMipsMap().remove(vm.getUid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pe allocation map.
|
||||
*
|
||||
* @param peAllocationMap the pe allocation map
|
||||
*/
|
||||
protected void setPeAllocationMap(Map<String, List<Pe>> peAllocationMap) {
|
||||
this.peAllocationMap = peAllocationMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pe allocation map.
|
||||
*
|
||||
* @return the pe allocation map
|
||||
*/
|
||||
protected Map<String, List<Pe>> getPeAllocationMap() {
|
||||
return peAllocationMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the free pes vector.
|
||||
*
|
||||
* @param freePes the new free pes vector
|
||||
*/
|
||||
protected void setFreePes(List<Pe> freePes) {
|
||||
this.freePes = freePes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the free pes vector.
|
||||
*
|
||||
* @return the free pes vector
|
||||
*/
|
||||
protected List<Pe> getFreePes() {
|
||||
return freePes;
|
||||
}
|
||||
|
||||
|
||||
/************************************************
|
||||
* Calculate Utilization history
|
||||
************************************************/
|
||||
public class HistoryEntry {
|
||||
public double startTime;
|
||||
public double usedMips;
|
||||
HistoryEntry(double t, double m) { startTime=t; usedMips=m;}
|
||||
}
|
||||
private List<HistoryEntry> utilizationHistories = null;
|
||||
public List<HistoryEntry> getUtilizationHisotry() {
|
||||
return utilizationHistories;
|
||||
}
|
||||
public double getUtilizationTotalMips() {
|
||||
double total=0;
|
||||
double lastTime=0;
|
||||
double lastMips=0;
|
||||
for(HistoryEntry h:this.utilizationHistories) {
|
||||
total += lastMips * (h.startTime - lastTime);
|
||||
lastTime = h.startTime;
|
||||
lastMips = h.usedMips;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
private static double powerOffDuration = 1*3600; //if host is idle for 1 hours, it's turned off.
|
||||
|
||||
public double getUtilizationEnergyConsumption() {
|
||||
|
||||
double total=0;
|
||||
double lastTime=0;
|
||||
double lastMips=0;
|
||||
for(HistoryEntry h:this.utilizationHistories) {
|
||||
double duration = h.startTime - lastTime;
|
||||
double utilPercentage = lastMips/ getTotalMips();
|
||||
double power = calculatePower(utilPercentage);
|
||||
double energyConsumption = power * duration;
|
||||
|
||||
// Assume that the host is turned off when duration is long enough
|
||||
if(duration > powerOffDuration && lastMips == 0)
|
||||
energyConsumption = 0;
|
||||
|
||||
total += energyConsumption;
|
||||
lastTime = h.startTime;
|
||||
lastMips = h.usedMips;
|
||||
}
|
||||
return total/3600; // transform to Whatt*hour from What*seconds
|
||||
}
|
||||
private void addUtilizationEntry() {
|
||||
double time = CloudSim.clock();
|
||||
double totalMips = getTotalMips();
|
||||
double usingMips = totalMips - this.getAvailableMips();
|
||||
if(usingMips < 0) {
|
||||
System.err.println("No way!");
|
||||
}
|
||||
if(utilizationHistories == null)
|
||||
utilizationHistories = new ArrayList<HistoryEntry>();
|
||||
this.utilizationHistories.add(new HistoryEntry(time, usingMips));
|
||||
}
|
||||
private double calculatePower(double u) {
|
||||
double power = 120 + 154 * u;
|
||||
return power;
|
||||
}
|
||||
private double getTotalMips() {
|
||||
return this.getPeList().size() * this.getPeCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAvailableMips(double availableMips) {
|
||||
super.setAvailableMips(availableMips);
|
||||
addUtilizationEntry();
|
||||
}
|
||||
}
|
||||
25
src/org/cloudbus/cloudsim/sdn/example/Workload.java
Normal file
25
src/org/cloudbus/cloudsim/sdn/example/Workload.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.Request;
|
||||
|
||||
/**
|
||||
* Class to keep workload information parsed from files.
|
||||
* This class is used in WorkloadParser
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class Workload {
|
||||
public int appId;
|
||||
public double time;
|
||||
public int submitVmId;
|
||||
public int submitPktSize;
|
||||
public Request request;
|
||||
}
|
||||
187
src/org/cloudbus/cloudsim/sdn/example/WorkloadParser.java
Normal file
187
src/org/cloudbus/cloudsim/sdn/example/WorkloadParser.java
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.example;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.UtilizationModel;
|
||||
import org.cloudbus.cloudsim.sdn.Processing;
|
||||
import org.cloudbus.cloudsim.sdn.Request;
|
||||
import org.cloudbus.cloudsim.sdn.Transmission;
|
||||
|
||||
/**
|
||||
* Parse [request].csv file.
|
||||
*
|
||||
* File format : req_time, vm_name(1), pkt_size(1), cloudlet_len(1),
|
||||
* vm_name(2), pkt_size(2), cloudlet_len(2),
|
||||
* ...
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
|
||||
public class WorkloadParser {
|
||||
private final Map<String, Integer> vmNames;
|
||||
private final Map<String, Integer> flowNames;
|
||||
private String file;
|
||||
private static int reqId = 0;
|
||||
private static int cloudletId = 0;
|
||||
private int userId;
|
||||
private UtilizationModel utilizationModel;
|
||||
private List<Workload> workloads;
|
||||
private List<Cloudlet> lastCloudlets;
|
||||
private List<Cloudlet> allCloudlets;
|
||||
|
||||
public WorkloadParser(String file, int userId, UtilizationModel cloudletUtilModel,
|
||||
Map<String, Integer> vmNameIdMap, Map<String, Integer> flowNameIdMap) {
|
||||
this.file = file;
|
||||
this.userId = userId;
|
||||
this.utilizationModel = cloudletUtilModel;
|
||||
this.vmNames = vmNameIdMap;
|
||||
this.flowNames = flowNameIdMap;
|
||||
|
||||
startParsing();
|
||||
}
|
||||
|
||||
public List<Workload> getWorkloads() {
|
||||
return this.workloads;
|
||||
}
|
||||
|
||||
public List<Cloudlet> getLastCloudlets() {
|
||||
// Returns cloudlets that is done at last for each workload
|
||||
return this.lastCloudlets;
|
||||
}
|
||||
|
||||
public List<Cloudlet> getAllCloudlets() {
|
||||
// Returns cloudlets that is done at last for each workload
|
||||
return this.allCloudlets;
|
||||
}
|
||||
|
||||
|
||||
private int getVmId(String vmName) {
|
||||
Integer vmId = this.vmNames.get(vmName);
|
||||
if(vmId == null) {
|
||||
System.err.println("Cannot find VM name:"+vmName);
|
||||
return -1;
|
||||
}
|
||||
return vmId;
|
||||
}
|
||||
|
||||
private Cloudlet generateCloudlet(int vmId, int length) {
|
||||
int peNum=1;
|
||||
long fileSize = 300;
|
||||
long outputSize = 300;
|
||||
Cloudlet cloudlet= new Cloudlet(cloudletId++, length, peNum, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
|
||||
cloudlet.setUserId(userId);
|
||||
cloudlet.setVmId(vmId);
|
||||
|
||||
return cloudlet;
|
||||
}
|
||||
|
||||
// Cloud_Len -> /FlowId/ -> ToVmId -> PktSize
|
||||
private Request parseRequest(int fromVmId, Queue<String> lineitems) {
|
||||
if(lineitems.size() <= 0)
|
||||
{
|
||||
System.err.println("No REQUEST! ERROR");
|
||||
return null;
|
||||
}
|
||||
|
||||
long cloudletLen = Long.parseLong(lineitems.poll());
|
||||
|
||||
Request req = new Request(reqId++, userId);
|
||||
Cloudlet cl = generateCloudlet(fromVmId, (int) cloudletLen);
|
||||
this.allCloudlets.add(cl);
|
||||
|
||||
Processing proc = new Processing(cl);
|
||||
req.addActivity(proc);
|
||||
|
||||
if(lineitems.size() != 0) {
|
||||
// Has more requests after this. Create a transmission and add
|
||||
String linkName = lineitems.poll();
|
||||
Integer flowId = this.flowNames.get(linkName);
|
||||
|
||||
if(flowId == null) {
|
||||
throw new IllegalArgumentException("No such link name in virtual.json:"+linkName);
|
||||
}
|
||||
|
||||
String vmName = lineitems.poll();
|
||||
int toVmId = getVmId(vmName);
|
||||
|
||||
long pktSize = Long.parseLong(lineitems.poll());
|
||||
|
||||
Request nextReq = parseRequest(toVmId, lineitems);
|
||||
|
||||
Transmission trans = new Transmission(fromVmId, toVmId, pktSize, flowId, nextReq);
|
||||
req.addActivity(trans);
|
||||
} else {
|
||||
// this is the last request.
|
||||
this.lastCloudlets.add(cl);
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
private void startParsing() {
|
||||
this.workloads = new ArrayList<Workload>();
|
||||
this.lastCloudlets = new ArrayList<Cloudlet>();
|
||||
this.allCloudlets = new ArrayList<Cloudlet>();
|
||||
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String line;
|
||||
try {
|
||||
@SuppressWarnings("unused")
|
||||
String head=br.readLine();
|
||||
//System.out.println("Headline: "+ head);
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
//System.out.println("parsing:"+line);
|
||||
|
||||
Workload tr = new Workload();
|
||||
|
||||
String[] splitLine = line.split(",");
|
||||
Queue<String> lineitems = new LinkedList<String>(Arrays.asList(splitLine));
|
||||
|
||||
tr.time = Double.parseDouble(lineitems.poll());
|
||||
|
||||
String vmName = lineitems.poll();
|
||||
tr.submitVmId = getVmId(vmName);
|
||||
|
||||
tr.submitPktSize = Integer.parseInt(lineitems.poll());
|
||||
|
||||
tr.request = parseRequest(tr.submitVmId, lineitems);
|
||||
|
||||
workloads.add(tr);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example.policies;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
|
||||
/**
|
||||
* VM Allocation Policy - BW and Compute combined, LFF.
|
||||
* When select a host to create a new VM, this policy chooses
|
||||
* the least full host in terms of both compute power and network bandwidth.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class VmAllocationPolicyCombinedLeastFullFirst extends VmAllocationPolicyCombinedMostFullFirst{
|
||||
|
||||
public VmAllocationPolicyCombinedLeastFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / hostTotalMips;
|
||||
double bwFreePercent = (double)getFreeBw().get(i) / hostTotalBw;
|
||||
|
||||
freeResources[i] = convertWeightedMetric(mipsFreePercent, bwFreePercent);
|
||||
}
|
||||
|
||||
for(int tries = 0; tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double moreFree = Double.NEGATIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] > moreFree) {
|
||||
moreFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(idx==-1) {
|
||||
System.err.println("Cannot assign the VM to any host:"+tries+"/"+numHosts);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeResources[idx] = Double.NEGATIVE_INFINITY;
|
||||
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if( getFreeMips().get(idx) < requiredMips) {
|
||||
//System.err.println("not enough MIPS");
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
if( getFreeBw().get(idx) < requiredBw) {
|
||||
//System.err.println("not enough BW");
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!result) {
|
||||
System.err.println("Cannot assign the VM to any host:"+"/"+numHosts);
|
||||
}
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.example.policies;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.VmAllocationPolicy;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationMaxHostInterface;
|
||||
|
||||
/**
|
||||
* VM Allocation Policy - BW and Compute combined, MFF.
|
||||
* When select a host to create a new VM, this policy chooses
|
||||
* the most full host in terms of both compute power and network bandwidth.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class VmAllocationPolicyCombinedMostFullFirst extends VmAllocationPolicy implements PowerUtilizationMaxHostInterface {
|
||||
|
||||
protected final double hostTotalMips;
|
||||
protected final double hostTotalBw;
|
||||
protected final int hostTotalPes;
|
||||
|
||||
/** The vm table. */
|
||||
private Map<String, Host> vmTable;
|
||||
|
||||
/** The used pes. */
|
||||
private Map<String, Integer> usedPes;
|
||||
|
||||
/** The free pes. */
|
||||
private List<Integer> freePes;
|
||||
|
||||
private Map<String, Long> usedMips;
|
||||
private List<Long> freeMips;
|
||||
private Map<String, Long> usedBw;
|
||||
private List<Long> freeBw;
|
||||
|
||||
/**
|
||||
* Creates the new VmAllocationPolicySimple object.
|
||||
*
|
||||
* @param list the list
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
public VmAllocationPolicyCombinedMostFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
|
||||
setFreePes(new ArrayList<Integer>());
|
||||
setFreeMips(new ArrayList<Long>());
|
||||
setFreeBw(new ArrayList<Long>());
|
||||
|
||||
for (Host host : getHostList()) {
|
||||
getFreePes().add(host.getNumberOfPes());
|
||||
getFreeMips().add((long)host.getTotalMips());
|
||||
getFreeBw().add(host.getBw());
|
||||
}
|
||||
hostTotalMips = getHostList().get(0).getTotalMips();
|
||||
hostTotalBw = getHostList().get(0).getBw();
|
||||
hostTotalPes = getHostList().get(0).getNumberOfPes();
|
||||
|
||||
setVmTable(new HashMap<String, Host>());
|
||||
setUsedPes(new HashMap<String, Integer>());
|
||||
setUsedMips(new HashMap<String, Long>());
|
||||
setUsedBw(new HashMap<String, Long>());
|
||||
}
|
||||
|
||||
protected double convertWeightedMetric(double mipsPercent, double bwPercent) {
|
||||
double ret = mipsPercent * bwPercent;
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / this.hostTotalMips;
|
||||
double bwFreePercent = (double)getFreeBw().get(i) / this.hostTotalBw;
|
||||
|
||||
freeResources[i] = this.convertWeightedMetric(mipsFreePercent, bwFreePercent);
|
||||
}
|
||||
|
||||
for(int tries = 0; result == false && tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double lessFree = Double.POSITIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] < lessFree) {
|
||||
lessFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
freeResources[idx] = Double.POSITIVE_INFINITY;
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if( getFreeMips().get(idx) < requiredMips) {
|
||||
//System.err.println("not enough MIPS");
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
if( getFreeBw().get(idx) < requiredBw) {
|
||||
//System.err.println("not enough BW");
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
System.err.println("VmAllocationPolicy: WARNING:: Cannot create VM!!!!");
|
||||
}
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected int maxNumHostsUsed=0;
|
||||
public void logMaxNumHostsUsed() {
|
||||
// Get how many are used
|
||||
int numHostsUsed=0;
|
||||
for(int freePes:getFreePes()) {
|
||||
if(freePes < hostTotalPes) {
|
||||
numHostsUsed++;
|
||||
}
|
||||
}
|
||||
if(maxNumHostsUsed < numHostsUsed)
|
||||
maxNumHostsUsed = numHostsUsed;
|
||||
Log.printLine("Number of online hosts:"+numHostsUsed + ", max was ="+maxNumHostsUsed);
|
||||
}
|
||||
public int getMaxNumHostsUsed() { return maxNumHostsUsed;}
|
||||
|
||||
/**
|
||||
* Releases the host used by a VM.
|
||||
*
|
||||
* @param vm the vm
|
||||
* @pre $none
|
||||
* @post none
|
||||
*/
|
||||
@Override
|
||||
public void deallocateHostForVm(Vm vm) {
|
||||
Host host = getVmTable().remove(vm.getUid());
|
||||
if (host != null) {
|
||||
int idx = getHostList().indexOf(host);
|
||||
host.vmDestroy(vm);
|
||||
|
||||
Integer pes = getUsedPes().remove(vm.getUid());
|
||||
getFreePes().set(idx, getFreePes().get(idx) + pes);
|
||||
|
||||
Long mips = getUsedMips().remove(vm.getUid());
|
||||
getFreeMips().set(idx, getFreeMips().get(idx) + mips);
|
||||
|
||||
Long bw = getUsedBw().remove(vm.getUid());
|
||||
getFreeBw().set(idx, getFreeBw().get(idx) + bw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host that is executing the given VM belonging to the given user.
|
||||
*
|
||||
* @param vm the vm
|
||||
* @return the Host with the given vmID and userID; $null if not found
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public Host getHost(Vm vm) {
|
||||
return getVmTable().get(vm.getUid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host that is executing the given VM belonging to the given user.
|
||||
*
|
||||
* @param vmId the vm id
|
||||
* @param userId the user id
|
||||
* @return the Host with the given vmID and userID; $null if not found
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public Host getHost(int vmId, int userId) {
|
||||
return getVmTable().get(Vm.getUid(userId, vmId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the vm table.
|
||||
*
|
||||
* @return the vm table
|
||||
*/
|
||||
public Map<String, Host> getVmTable() {
|
||||
return vmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vm table.
|
||||
*
|
||||
* @param vmTable the vm table
|
||||
*/
|
||||
protected void setVmTable(Map<String, Host> vmTable) {
|
||||
this.vmTable = vmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the used pes.
|
||||
*
|
||||
* @return the used pes
|
||||
*/
|
||||
protected Map<String, Integer> getUsedPes() {
|
||||
return usedPes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the used pes.
|
||||
*
|
||||
* @param usedPes the used pes
|
||||
*/
|
||||
protected void setUsedPes(Map<String, Integer> usedPes) {
|
||||
this.usedPes = usedPes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the free pes.
|
||||
*
|
||||
* @return the free pes
|
||||
*/
|
||||
protected List<Integer> getFreePes() {
|
||||
return freePes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the free pes.
|
||||
*
|
||||
* @param freePes the new free pes
|
||||
*/
|
||||
protected void setFreePes(List<Integer> freePes) {
|
||||
this.freePes = freePes;
|
||||
}
|
||||
|
||||
protected Map<String, Long> getUsedMips() {
|
||||
return usedMips;
|
||||
}
|
||||
protected void setUsedMips(Map<String, Long> usedMips) {
|
||||
this.usedMips = usedMips;
|
||||
}
|
||||
protected Map<String, Long> getUsedBw() {
|
||||
return usedBw;
|
||||
}
|
||||
protected void setUsedBw(Map<String, Long> usedBw) {
|
||||
this.usedBw = usedBw;
|
||||
}
|
||||
protected List<Long> getFreeMips() {
|
||||
return this.freeMips;
|
||||
}
|
||||
protected void setFreeMips(List<Long> freeMips) {
|
||||
this.freeMips = freeMips;
|
||||
}
|
||||
|
||||
protected List<Long> getFreeBw() {
|
||||
return this.freeBw;
|
||||
}
|
||||
protected void setFreeBw(List<Long> freeBw) {
|
||||
this.freeBw = freeBw;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.VmAllocationPolicy#optimizeAllocation(double, cloudsim.VmList, double)
|
||||
*/
|
||||
@Override
|
||||
public List<Map<String, Object>> optimizeAllocation(List<? extends Vm> vmList) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.cloudbus.cloudsim.VmAllocationPolicy#allocateHostForVm(org.cloudbus.cloudsim.Vm,
|
||||
* org.cloudbus.cloudsim.Host)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm, Host host) {
|
||||
if (host.vmCreate(vm)) { // if vm has been succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
int idx = getHostList().indexOf(host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
Log.formatLine(
|
||||
"%.2f: VM #" + vm.getId() + " has been allocated to the host #" + host.getId(),
|
||||
CloudSim.clock());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example.policies;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
|
||||
/**
|
||||
* VM Allocation Policy - Only compute power, LFF.
|
||||
* When select a host to create a new VM, this policy chooses
|
||||
* the least full host in terms of compute power (MIPS) only.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class VmAllocationPolicyMipsLeastFullFirst extends VmAllocationPolicyCombinedMostFullFirst{
|
||||
|
||||
public VmAllocationPolicyMipsLeastFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / hostTotalMips;
|
||||
//double bwFreePercent = (double)getFreeBw().get(i) / hostTotalBw;
|
||||
|
||||
freeResources[i] = mipsFreePercent;
|
||||
}
|
||||
|
||||
for(int tries = 0; tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double moreFree = Double.NEGATIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] > moreFree) {
|
||||
moreFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(idx==-1) {
|
||||
System.err.println("Cannot assign the VM to any host:"+tries+"/"+numHosts);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeResources[idx] = Double.NEGATIVE_INFINITY;
|
||||
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if(getFreeMips().get(idx) < requiredMips ||
|
||||
getFreeBw().get(idx) < requiredBw ||
|
||||
getFreePes().get(idx) < requiredPes) {
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
break;
|
||||
}
|
||||
}
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example.policies;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
|
||||
/**
|
||||
* VM Allocation Policy - Only compute power, MFF.
|
||||
* When select a host to create a new VM, this policy chooses
|
||||
* the most full host in terms of compute power (MIPS) only.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class VmAllocationPolicyMipsMostFullFirst extends VmAllocationPolicyCombinedMostFullFirst{
|
||||
|
||||
public VmAllocationPolicyMipsMostFullFirst(List<? extends Host> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / this.hostTotalMips;
|
||||
|
||||
freeResources[i] = mipsFreePercent;
|
||||
}
|
||||
|
||||
for(int tries = 0; result == false && tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double lessFree = Double.POSITIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// we want the host with less pes in use
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] < lessFree) {
|
||||
lessFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
freeResources[idx] = Double.POSITIVE_INFINITY;
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if(getFreeMips().get(idx) < requiredMips ||
|
||||
getFreeBw().get(idx) < requiredBw ||
|
||||
getFreePes().get(idx) < requiredPes) {
|
||||
//Cannot host the VM
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example.policies;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Pe;
|
||||
import org.cloudbus.cloudsim.VmSchedulerTimeShared;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationHistoryEntry;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationInterface;
|
||||
|
||||
/**
|
||||
* VmSchedulerTimeSharedEnergy is a VMM allocation policy that allocates one or more Pe to a VM, and
|
||||
* allows sharing of PEs by time. If there is no free PEs to the VM, allocation fails. Free PEs are
|
||||
* not allocated to VMs
|
||||
*
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @author Anton Beloglazov
|
||||
* @author Jungmin Son
|
||||
* * @since CloudSim Toolkit 1.0
|
||||
*/
|
||||
public class VmSchedulerTimeSharedEnergy extends VmSchedulerTimeShared implements PowerUtilizationInterface{
|
||||
|
||||
|
||||
public VmSchedulerTimeSharedEnergy(List<? extends Pe> pelist) {
|
||||
super(pelist);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAvailableMips(double availableMips) {
|
||||
super.setAvailableMips(availableMips);
|
||||
addUtilizationEntry();
|
||||
}
|
||||
|
||||
private List<PowerUtilizationHistoryEntry> utilizationHistories = null;
|
||||
private static double powerOffDuration = 0; //if host is idle for 1 hours, it's turned off.
|
||||
|
||||
public void addUtilizationEntryTermination(double terminatedTime) {
|
||||
if(this.utilizationHistories != null)
|
||||
this.utilizationHistories.add(new PowerUtilizationHistoryEntry(terminatedTime, 0));
|
||||
}
|
||||
|
||||
public List<PowerUtilizationHistoryEntry> getUtilizationHisotry() {
|
||||
return utilizationHistories;
|
||||
}
|
||||
|
||||
public double getUtilizationEnergyConsumption() {
|
||||
|
||||
double total=0;
|
||||
double lastTime=0;
|
||||
double lastMips=0;
|
||||
if(this.utilizationHistories == null)
|
||||
return 0;
|
||||
|
||||
for(PowerUtilizationHistoryEntry h:this.utilizationHistories) {
|
||||
double duration = h.startTime - lastTime;
|
||||
double utilPercentage = lastMips/ getTotalMips();
|
||||
double power = calculatePower(utilPercentage);
|
||||
double energyConsumption = power * duration;
|
||||
|
||||
// Assume that the host is turned off when duration is long enough
|
||||
if(duration > powerOffDuration && lastMips == 0)
|
||||
energyConsumption = 0;
|
||||
|
||||
total += energyConsumption;
|
||||
lastTime = h.startTime;
|
||||
lastMips = h.usedMips;
|
||||
}
|
||||
return total/3600; // transform to Whatt*hour from What*seconds
|
||||
}
|
||||
|
||||
private double calculatePower(double u) {
|
||||
double power = 120 + 154 * u;
|
||||
return power;
|
||||
}
|
||||
|
||||
private void addUtilizationEntry() {
|
||||
double time = CloudSim.clock();
|
||||
double totalMips = getTotalMips();
|
||||
double usingMips = totalMips - this.getAvailableMips();
|
||||
if(usingMips < 0) {
|
||||
System.err.println("addUtilizationEntry : using mips is negative, No way!");
|
||||
}
|
||||
if(utilizationHistories == null)
|
||||
utilizationHistories = new ArrayList<PowerUtilizationHistoryEntry>();
|
||||
this.utilizationHistories.add(new PowerUtilizationHistoryEntry(time, usingMips));
|
||||
}
|
||||
|
||||
private double getTotalMips() {
|
||||
return this.getPeList().size() * this.getPeCapacity();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.example.topogenerators;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
/**
|
||||
* Generate Physical topology Json file, for example:
|
||||
{
|
||||
"nodes" : [
|
||||
{
|
||||
"name": "core",
|
||||
"type" : "core",
|
||||
"iops" : 1000000000,
|
||||
"bw" : 1000000000,
|
||||
},
|
||||
{
|
||||
"name": "edge1",
|
||||
"type" : "edge",
|
||||
"iops" : 1000000000,
|
||||
"bw" : 1000000000,
|
||||
},
|
||||
{
|
||||
"name": "host01",
|
||||
"type" : "host",
|
||||
"pes" : 1,
|
||||
"mips" : 30000000,
|
||||
"ram" : 10240,
|
||||
"storage" : 10000000,
|
||||
"bw" : 200000000,
|
||||
},
|
||||
{
|
||||
"name": "host02",
|
||||
"type" : "host",
|
||||
"pes" : 1,
|
||||
"mips" : 30000000,
|
||||
"ram" : 10240,
|
||||
"storage" : 10000000,
|
||||
"bw" : 200000000,
|
||||
},
|
||||
],
|
||||
"links" : [
|
||||
{ "source" : "core" , "destination" : "edge1" , "latency" : 0.5 },
|
||||
{ "source" : "edge1" , "destination" : "host01" , "latency" : 0.5 },
|
||||
{ "source" : "edge1" , "destination" : "host02" , "latency" : 0.5 },
|
||||
]
|
||||
}
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class PhysicalTopologyGenerator {
|
||||
|
||||
public static void main(String [] argv) {
|
||||
|
||||
String jsonFileName = "very_simple_physical.json";
|
||||
|
||||
int fanout = 2;
|
||||
double latency = 0.1;
|
||||
|
||||
long iops = 1000000000L;
|
||||
|
||||
int pe = 8;
|
||||
long mips = 4000;
|
||||
int ram = 10240;
|
||||
long storage = 10000000;
|
||||
//long bw = 125000000;
|
||||
long bw = 1000000000;
|
||||
|
||||
PhysicalTopologyGenerator reqg = new PhysicalTopologyGenerator();
|
||||
HostSpec hostSpec = reqg.createHostSpec(pe, mips, ram, storage, bw);
|
||||
reqg.createTopology(hostSpec, iops, bw, fanout, latency);
|
||||
reqg.wrtieJSON(jsonFileName);
|
||||
}
|
||||
|
||||
public void createTopology(HostSpec hostSpec, long swIops, long swBw, int fanout, double latency) {
|
||||
// core, aggregation, edge
|
||||
// Core switch
|
||||
SwitchSpec c = addSwitch("c", "core", swBw, swIops);
|
||||
|
||||
for(int i=0; i<fanout; i++) {
|
||||
SwitchSpec e = addSwitch("e"+i, "edge", swBw, swIops);
|
||||
addLink(c, e, latency);
|
||||
|
||||
for(int j=0; j<fanout; j++) {
|
||||
String hostname = "h_" + i + "_" + j;
|
||||
HostSpec h = addHost(hostname, hostSpec);
|
||||
addLink(e, h, latency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<HostSpec> hosts = new ArrayList<HostSpec>();
|
||||
private List<SwitchSpec> switches = new ArrayList<SwitchSpec>();
|
||||
private List<LinkSpec> links = new ArrayList<LinkSpec>();
|
||||
|
||||
public HostSpec addHost(String name, HostSpec spec) {
|
||||
HostSpec host = new HostSpec(spec.pe, spec.mips, spec.ram, spec.storage, spec.bw);
|
||||
|
||||
host.name = name;
|
||||
host.type = "host";
|
||||
|
||||
hosts.add(host);
|
||||
return host;
|
||||
}
|
||||
public HostSpec addHost(String name, int pes, long mips, int ram, long storage, long bw) {
|
||||
HostSpec host = new HostSpec(pes, mips, ram, storage, bw);
|
||||
return addHost(name, host);
|
||||
}
|
||||
|
||||
public SwitchSpec addSwitch(String name, String type, long bw, long iops) {
|
||||
SwitchSpec sw = new SwitchSpec();
|
||||
|
||||
sw.name = name;
|
||||
sw.type = type; // core, aggregation, edge
|
||||
sw.bw = bw;
|
||||
sw.iops = iops;
|
||||
|
||||
switches.add(sw);
|
||||
return sw;
|
||||
}
|
||||
|
||||
|
||||
private void addLink(NodeSpec source, NodeSpec dest, double latency) {
|
||||
links.add(new LinkSpec(source.name,dest.name, latency));
|
||||
}
|
||||
|
||||
public HostSpec createHostSpec(int pe, long mips, int ram, long storage, long bw) {
|
||||
return new HostSpec(pe, mips, ram, storage, bw);
|
||||
}
|
||||
|
||||
class NodeSpec {
|
||||
String name;
|
||||
String type;
|
||||
long bw;
|
||||
}
|
||||
class HostSpec extends NodeSpec {
|
||||
int pe;
|
||||
long mips;
|
||||
int ram;
|
||||
long storage;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
JSONObject toJSON() {
|
||||
HostSpec o = this;
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("name", o.name);
|
||||
obj.put("type", o.type);
|
||||
obj.put("storage", o.storage);
|
||||
obj.put("pes", o.pe);
|
||||
obj.put("mips", o.mips);
|
||||
obj.put("ram", new Integer(o.ram));
|
||||
obj.put("bw", o.bw);
|
||||
return obj;
|
||||
}
|
||||
public HostSpec(int pe, long mips, int ram, long storage, long bw) {
|
||||
this.pe = pe;
|
||||
this.mips = mips;
|
||||
this.ram = ram;
|
||||
this.storage = storage;
|
||||
this.bw = bw;
|
||||
this.type = "host";
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchSpec extends NodeSpec {
|
||||
long iops;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
JSONObject toJSON() {
|
||||
SwitchSpec o = this;
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("name", o.name);
|
||||
obj.put("type", o.type);
|
||||
obj.put("iops", o.iops);
|
||||
obj.put("bw", o.bw);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
class LinkSpec {
|
||||
String source;
|
||||
String destination;
|
||||
double latency;
|
||||
|
||||
public LinkSpec(String source,String destination,double latency2) {
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.latency = latency2;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
JSONObject toJSON() {
|
||||
LinkSpec link = this;
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("source", link.source);
|
||||
obj.put("destination", link.destination);
|
||||
obj.put("latency", link.latency);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
int vmId = 0;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void wrtieJSON(String jsonFileName) {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
JSONArray nodeList = new JSONArray();
|
||||
JSONArray linkList = new JSONArray();
|
||||
|
||||
for(HostSpec o:hosts) {
|
||||
nodeList.add(o.toJSON());
|
||||
}
|
||||
for(SwitchSpec o:switches) {
|
||||
nodeList.add(o.toJSON());
|
||||
}
|
||||
|
||||
for(LinkSpec link:links) {
|
||||
linkList.add(link.toJSON());
|
||||
}
|
||||
|
||||
obj.put("nodes", nodeList);
|
||||
obj.put("links", linkList);
|
||||
|
||||
try {
|
||||
|
||||
FileWriter file = new FileWriter(jsonFileName);
|
||||
file.write(obj.toJSONString().replaceAll(",", ",\n"));
|
||||
file.flush();
|
||||
file.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println(obj);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example.topogenerators;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.math3.distribution.ExponentialDistribution;
|
||||
import org.apache.commons.math3.distribution.ParetoDistribution;
|
||||
import org.apache.commons.math3.random.Well19937c;
|
||||
|
||||
/**
|
||||
* Generate VM requests, for example:
|
||||
{
|
||||
"nodes" : [
|
||||
{
|
||||
"name" : "vm01",
|
||||
"type" : "vm",
|
||||
"size" : 1000,
|
||||
"pes": 1,
|
||||
"mips" : 30000000,
|
||||
"ram" : 512,
|
||||
"bw" : 100000,
|
||||
"starttime": 1.3,
|
||||
"endtime" : 20.5,
|
||||
},
|
||||
],
|
||||
"links" : [
|
||||
{
|
||||
"name": "l32",
|
||||
"source" : "vm03" ,
|
||||
"destination" : "vm02" ,
|
||||
"bandwidth" : 66000000
|
||||
},
|
||||
],
|
||||
}
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
|
||||
public class VMRequestRandomGenerator {
|
||||
|
||||
public static void main(String [] argv) {
|
||||
int numVms = 5;
|
||||
String jsonFileName = "very_simple_virtual.json";
|
||||
|
||||
VirtualTopologyGeneratorVmTypes vmGenerator = new VirtualTopologyGeneratorVmTypes();
|
||||
VMRequestRandomGenerator reqg = new VMRequestRandomGenerator(vmGenerator, numVms, jsonFileName);
|
||||
reqg.start();
|
||||
}
|
||||
|
||||
private static long seed = 10;
|
||||
int numVms = 0;
|
||||
String jsonFileName = null;
|
||||
VirtualTopologyGeneratorVmTypes vmGenerator = null;
|
||||
|
||||
public VMRequestRandomGenerator(VirtualTopologyGeneratorVmTypes vmGenerator, int numVms, String jsonFileName) {
|
||||
this.vmGenerator = vmGenerator;
|
||||
this.numVms = numVms;
|
||||
this.jsonFileName = jsonFileName;
|
||||
|
||||
}
|
||||
public void start() {
|
||||
generateVMsRandom(numVms);
|
||||
vmGenerator.wrtieJSON(jsonFileName);
|
||||
}
|
||||
|
||||
public void generateVMsRandom(int totalVmNum) {
|
||||
int vmCount = 0;
|
||||
double lastStartTime = 0;
|
||||
|
||||
double startMean = 1800; // sec = 30min
|
||||
double durScale=14400; // sec = 4 hours
|
||||
double durShape=1.2;
|
||||
|
||||
Random rVmNum = new Random(seed);
|
||||
ExponentialDistribution rStartTime = new ExponentialDistribution(new Well19937c(seed), startMean, ExponentialDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
|
||||
ParetoDistribution rDuration = new ParetoDistribution(new Well19937c(seed), durScale, durShape);
|
||||
|
||||
while(vmCount < totalVmNum) {
|
||||
int vmsInGroup = rVmNum.nextInt(4)+2;
|
||||
double duration = Math.floor(rDuration.sample());
|
||||
|
||||
vmGenerator.generateVMGroup(vmsInGroup, lastStartTime, lastStartTime+duration, null);
|
||||
lastStartTime += Math.floor(rStartTime.sample());
|
||||
|
||||
vmCount += vmsInGroup;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example.topogenerators;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
/**
|
||||
* Generate virtual topology Json file from pre-configured VM type sets.
|
||||
* VM types are defined in another class - VirtualTopologyGeneratorVmTypes.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class VirtualTopologyGenerator {
|
||||
private List<VMSpec> vms = new ArrayList<VMSpec>();
|
||||
private List<LinkSpec> links = new ArrayList<LinkSpec>();
|
||||
private List<DummyWorkloadSpec> dummyWorkload = new ArrayList<DummyWorkloadSpec>();
|
||||
|
||||
public VMSpec addVM(String name, VMSpec spec) {
|
||||
return addVM(name, spec.pe, spec.mips, spec.ram, spec.size, spec.bw, spec.starttime, spec.endtime);
|
||||
}
|
||||
public VMSpec addVM(String name, int pes, long mips, int ram, long storage, long bw, double starttime, double endtime) {
|
||||
VMSpec vm = new VMSpec(pes, mips, ram, storage, bw, starttime, endtime);
|
||||
vm.name = name;
|
||||
|
||||
vms.add(vm);
|
||||
return vm;
|
||||
}
|
||||
|
||||
|
||||
public LinkSpec addLink(String linkname, VMSpec source, VMSpec dest, Long bw) {
|
||||
LinkSpec link = new LinkSpec(linkname, source.name,dest.name, bw);
|
||||
links.add(link);
|
||||
|
||||
addWorkload(linkname, source, dest);
|
||||
return link;
|
||||
}
|
||||
|
||||
public void addWorkload(String linkname, VMSpec source, VMSpec dest) {
|
||||
DummyWorkloadSpec wl = new DummyWorkloadSpec(source.starttime, source.name,dest.name, linkname);
|
||||
this.dummyWorkload.add(wl);
|
||||
}
|
||||
|
||||
public VMSpec createVmSpec(int pe, long mips, int ram, long storage, long bw, double starttime, double endtime) {
|
||||
return new VMSpec(pe, mips, ram, storage, bw, starttime, endtime);
|
||||
}
|
||||
|
||||
class VMSpec {
|
||||
String name;
|
||||
String type;
|
||||
long size;
|
||||
int pe;
|
||||
long mips;
|
||||
int ram;
|
||||
long bw;
|
||||
double starttime = -1;
|
||||
double endtime = -1;
|
||||
|
||||
public VMSpec(int pe, long mips, int ram, long storage, long bw,double starttime,double endtime) {
|
||||
this.pe = pe;
|
||||
this.mips = mips;
|
||||
this.ram = ram;
|
||||
this.size = storage;
|
||||
this.bw = bw;
|
||||
this.type = "vm";
|
||||
this.starttime = starttime;
|
||||
this.endtime = endtime;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
JSONObject toJSON() {
|
||||
VMSpec vm = this;
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("name", vm.name);
|
||||
obj.put("type", vm.type);
|
||||
obj.put("size", vm.size);
|
||||
obj.put("pes", vm.pe);
|
||||
obj.put("mips", vm.mips);
|
||||
obj.put("ram", new Integer(vm.ram));
|
||||
obj.put("bw", vm.bw);
|
||||
if(vm.starttime != -1)
|
||||
obj.put("starttime", vm.starttime);
|
||||
if(vm.endtime != -1)
|
||||
obj.put("endtime", vm.endtime);
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
class DummyWorkloadSpec {
|
||||
double startTime;
|
||||
String source;
|
||||
String linkname;
|
||||
String destination;
|
||||
|
||||
public DummyWorkloadSpec(double startTime, String source,String destination,String linkname) {
|
||||
this.linkname = linkname;
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.startTime = startTime;
|
||||
}
|
||||
public String toString() {
|
||||
String st = startTime+ ","+ source + ",0,1,"+linkname+","+destination + ",1000000000000000,1";
|
||||
return st;
|
||||
}
|
||||
}
|
||||
class LinkSpec {
|
||||
String name;
|
||||
String source;
|
||||
String destination;
|
||||
Long bw;
|
||||
|
||||
public LinkSpec(String name,String source,String destination,Long bw) {
|
||||
this.name = name;
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.bw = bw;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
JSONObject toJSON() {
|
||||
LinkSpec link = this;
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("name", link.name);
|
||||
obj.put("source", link.source);
|
||||
obj.put("destination", link.destination);
|
||||
if(link.bw != null)
|
||||
obj.put("bandwidth", link.bw);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
int vmId = 0;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void wrtieJSON(String jsonFileName) {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
JSONArray vmList = new JSONArray();
|
||||
JSONArray linkList = new JSONArray();
|
||||
|
||||
for(VMSpec vm:vms) {
|
||||
vmList.add(vm.toJSON());
|
||||
}
|
||||
|
||||
for(LinkSpec link:links) {
|
||||
linkList.add(link.toJSON());
|
||||
}
|
||||
|
||||
obj.put("nodes", vmList);
|
||||
obj.put("links", linkList);
|
||||
|
||||
try {
|
||||
|
||||
FileWriter file = new FileWriter(jsonFileName);
|
||||
file.write(obj.toJSONString().replaceAll(",", ",\n"));
|
||||
file.flush();
|
||||
file.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println(obj);
|
||||
|
||||
System.out.println("===============WORKLOAD=============");
|
||||
System.out.println("start, source, z, w1, link, dest, psize, w2");
|
||||
for(DummyWorkloadSpec wl:this.dummyWorkload) {
|
||||
System.out.println(wl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.example.topogenerators;
|
||||
|
||||
/**
|
||||
* This class specifies different type of VMs that will be generated from VirtualTopoGenerator.
|
||||
* Please change the configurations of VMs (MIPs, bandwidth, etc) here.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class VirtualTopologyGeneratorVmTypes extends VirtualTopologyGenerator{
|
||||
|
||||
public static void main(String [] argv) {
|
||||
int numVms = 10;
|
||||
String jsonFileName = "virtual_ccgrid.json";
|
||||
|
||||
VirtualTopologyGeneratorVmTypes vmGenerator = new VirtualTopologyGeneratorVmTypes();
|
||||
vmGenerator.generate3TierTopology(numVms, jsonFileName);
|
||||
}
|
||||
|
||||
public void generate3TierTopology(int num, String jsonFileName) {
|
||||
final int TIER = 3;
|
||||
final Long linkBW = (long) (125000000/3);
|
||||
for(int i = 0;i < num; i++) {
|
||||
generateVMGroup(TIER, -1, -1, linkBW); // Priority VMs
|
||||
}
|
||||
for(int i = 0;i < num*4; i++) {
|
||||
generateVMGroup(TIER, -1, -1, null);
|
||||
}
|
||||
wrtieJSON(jsonFileName);
|
||||
}
|
||||
|
||||
int vmGroupId = 0;
|
||||
int vmNum = 0;
|
||||
|
||||
enum VMtype {
|
||||
WebServer,
|
||||
AppServer,
|
||||
DBServer,
|
||||
Proxy,
|
||||
Firewall
|
||||
}
|
||||
|
||||
|
||||
public VMSpec createVM(VMtype vmtype, double startTime, double endTime) {
|
||||
String name = "vm";
|
||||
int pes = 1;
|
||||
long vmSize = 1000;
|
||||
long mips=1000;
|
||||
int vmRam = 512;
|
||||
long vmBW=100000000;
|
||||
|
||||
switch(vmtype) {
|
||||
case WebServer:
|
||||
//m1.large
|
||||
mips=mips*2;
|
||||
pes=2;
|
||||
name="web";
|
||||
break;
|
||||
case AppServer:
|
||||
//m2.xlarge
|
||||
mips=(long) (mips*1.5);
|
||||
pes=8;
|
||||
name="app";
|
||||
break;
|
||||
case DBServer:
|
||||
//c1.xlarge
|
||||
mips=(long) (mips*2.4);
|
||||
pes=8;
|
||||
name="db";
|
||||
break;
|
||||
case Proxy:
|
||||
mips=mips*2;
|
||||
pes=8;
|
||||
vmBW=500000000;
|
||||
name="proxy";
|
||||
break;
|
||||
case Firewall:
|
||||
mips=mips*3;
|
||||
pes=8;
|
||||
vmBW=500000000;
|
||||
name="firewall";
|
||||
break;
|
||||
}
|
||||
name += vmGroupId;
|
||||
vmNum++;
|
||||
|
||||
VMSpec vm = addVM(name, pes, mips, vmRam, vmSize, vmBW, startTime, endTime);
|
||||
return vm;
|
||||
}
|
||||
/*
|
||||
public VMSpec createVM(VMtype vmtype, double startTime, double endTime) {
|
||||
String name = "vm";
|
||||
int pes = 1;
|
||||
long vmSize = 1000;
|
||||
long mips=10000000;
|
||||
int vmRam = 512;
|
||||
long vmBW=100000;
|
||||
|
||||
switch(vmtype) {
|
||||
case WebServer:
|
||||
//m1.large
|
||||
mips=mips*2;
|
||||
pes=2;
|
||||
name="web";
|
||||
break;
|
||||
case AppServer:
|
||||
//m2.xlarge
|
||||
mips=(long) ( *1.5);
|
||||
pes=8;
|
||||
name="app";
|
||||
break;
|
||||
case DBServer:
|
||||
//c1.xlarge
|
||||
mips=(long) (mips*2.4);
|
||||
pes=8;
|
||||
name="db";
|
||||
break;
|
||||
case Proxy:
|
||||
mips=mips*2;
|
||||
pes=8;
|
||||
vmBW=vmBW*5;
|
||||
name="proxy";
|
||||
break;
|
||||
case Firewall:
|
||||
mips=mips*3;
|
||||
pes=8;
|
||||
vmBW=vmBW*5;
|
||||
name="firewall";
|
||||
break;
|
||||
}
|
||||
name += vmGroupId;
|
||||
vmNum++;
|
||||
|
||||
VMSpec vm = addVM(name, pes, mips, vmRam, vmSize, vmBW, startTime, endTime);
|
||||
return vm;
|
||||
}
|
||||
*/
|
||||
private void addLinkAutoName(VMSpec src, VMSpec dest, Long bw) {
|
||||
String linkName = "default";
|
||||
addLink(linkName, src, dest, bw);
|
||||
|
||||
if(bw != null) {
|
||||
linkName = src.name + dest.name;
|
||||
addLink(linkName, src, dest, bw);
|
||||
}
|
||||
}
|
||||
private void addLinkAutoNameBoth(VMSpec vm1, VMSpec vm2, Long linkBw) {
|
||||
addLinkAutoName(vm1, vm2, linkBw);
|
||||
addLinkAutoName(vm2, vm1, linkBw);
|
||||
}
|
||||
|
||||
|
||||
public void generateVMGroup(int numVMsInGroup, double startTime, double endTime, Long linkBw) {
|
||||
System.out.printf("Generating VM Group(%d): %f - %f\n", numVMsInGroup, startTime, endTime);
|
||||
|
||||
switch(numVMsInGroup) {
|
||||
case 2:
|
||||
{
|
||||
VMSpec web = this.createVM(VMtype.WebServer, startTime, endTime);
|
||||
VMSpec app = this.createVM(VMtype.AppServer, startTime, endTime);
|
||||
addLinkAutoNameBoth(web, app, linkBw);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
VMSpec web = this.createVM(VMtype.WebServer, startTime, endTime);
|
||||
VMSpec app = this.createVM(VMtype.AppServer, startTime, endTime);
|
||||
VMSpec db = this.createVM(VMtype.DBServer, startTime, endTime);
|
||||
addLinkAutoNameBoth(web, app, linkBw);
|
||||
addLinkAutoNameBoth(app, db, linkBw);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
VMSpec web = this.createVM(VMtype.WebServer, startTime, endTime);
|
||||
VMSpec app = this.createVM(VMtype.AppServer, startTime, endTime);
|
||||
VMSpec db = this.createVM(VMtype.DBServer, startTime, endTime);
|
||||
VMSpec proxy = this.createVM(VMtype.Proxy, startTime, endTime);
|
||||
addLinkAutoNameBoth(web, app, linkBw);
|
||||
addLinkAutoNameBoth(app, db, linkBw);
|
||||
addLinkAutoNameBoth(web, proxy, linkBw);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
VMSpec web = this.createVM(VMtype.WebServer, startTime, endTime);
|
||||
VMSpec app = this.createVM(VMtype.AppServer, startTime, endTime);
|
||||
VMSpec db = this.createVM(VMtype.DBServer, startTime, endTime);
|
||||
VMSpec proxy = this.createVM(VMtype.Proxy, startTime, endTime);
|
||||
this.createVM(VMtype.Firewall, startTime, endTime);
|
||||
addLinkAutoNameBoth(web, app, linkBw);
|
||||
addLinkAutoNameBoth(app, db, linkBw);
|
||||
addLinkAutoNameBoth(web, proxy, linkBw);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
System.err.println("Unknown group number"+numVMsInGroup);
|
||||
break;
|
||||
}
|
||||
vmGroupId ++;
|
||||
}
|
||||
|
||||
}
|
||||
248
src/org/cloudbus/cloudsim/sdn/graph/core/Bridge.java
Normal file
248
src/org/cloudbus/cloudsim/sdn/graph/core/Bridge.java
Normal file
@@ -0,0 +1,248 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
public class Bridge {
|
||||
|
||||
private static Node getNode(Graph graph, String name){
|
||||
for(Node node : graph.getAdjacencyList().keySet()){
|
||||
if(node!=null){
|
||||
if(node.getName().equals(name)){
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// convert from JSON object to Graph object
|
||||
public static Graph jsonToGraph(String fileName, int type){
|
||||
|
||||
Graph graph = new Graph();
|
||||
|
||||
// type 0->physical topology 1->virtual topology
|
||||
if(0 == type){
|
||||
try {
|
||||
JSONObject doc = (JSONObject) JSONValue.parse(new FileReader(fileName));
|
||||
JSONArray nodes = (JSONArray) doc.get("nodes");
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> iter =nodes.iterator();
|
||||
while(iter.hasNext()){
|
||||
JSONObject node = iter.next();
|
||||
String nodeType = (String) node.get("type");
|
||||
String nodeName = (String) node.get("name");
|
||||
|
||||
if(nodeType.equalsIgnoreCase("host")){ //host
|
||||
long pes = (Long) node.get("pes");
|
||||
long mips = (Long) node.get("mips");
|
||||
int ram = new BigDecimal((Long)node.get("ram")).intValueExact();
|
||||
long storage = (Long) node.get("storage");
|
||||
long bw = new BigDecimal((Long)node.get("bw")).intValueExact();
|
||||
|
||||
int num = 1;
|
||||
if (node.get("nums")!= null)
|
||||
num = new BigDecimal((Long)node.get("nums")).intValueExact();
|
||||
|
||||
for(int n = 0; n< num; n++) {
|
||||
Node hNode = new HostNode(nodeName, nodeType, pes, mips, ram, storage, bw);
|
||||
graph.addNode(hNode);
|
||||
}
|
||||
|
||||
} else { //switch
|
||||
int bw = new BigDecimal((Long)node.get("bw")).intValueExact();
|
||||
long iops = (Long) node.get("iops");
|
||||
int upports = new BigDecimal((Long)node.get("upports")).intValueExact();
|
||||
int downports = new BigDecimal((Long)node.get("downports")).intValueExact();
|
||||
|
||||
Node sNode = new SwitchNode(nodeName, nodeType, iops, upports, downports, bw);
|
||||
graph.addNode(sNode);
|
||||
}
|
||||
}
|
||||
|
||||
JSONArray links = (JSONArray) doc.get("links");
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> linksIter =links.iterator();
|
||||
while(linksIter.hasNext()){
|
||||
JSONObject link = linksIter.next();
|
||||
String src = (String) link.get("source");
|
||||
String dst = (String) link.get("destination");
|
||||
double lat = (Double) link.get("latency");
|
||||
|
||||
Node source = (Node) getNode(graph, src);
|
||||
Node target = (Node) getNode(graph, dst);
|
||||
|
||||
|
||||
if(source!=null && target!=null){
|
||||
Edge edge = new Edge(target, lat);
|
||||
graph.addEdge(source, edge);
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}else if(1 == type){
|
||||
try {
|
||||
JSONObject doc = (JSONObject) JSONValue.parse(new FileReader(fileName));
|
||||
JSONArray nodes = (JSONArray) doc.get("nodes");
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> iter = nodes.iterator();
|
||||
while(iter.hasNext()){
|
||||
JSONObject node = iter.next();
|
||||
|
||||
String nodeType = (String) node.get("type");
|
||||
String nodeName = (String) node.get("name");
|
||||
int pes = new BigDecimal((Long)node.get("pes")).intValueExact();
|
||||
long mips = (Long) node.get("mips");
|
||||
int ram = new BigDecimal((Long)node.get("ram")).intValueExact();
|
||||
long size = (Long) node.get("size");
|
||||
|
||||
Node vmNode = new VmNode(nodeName, nodeType, size, pes, mips, ram);
|
||||
graph.addNode(vmNode);
|
||||
}
|
||||
|
||||
JSONArray links = (JSONArray) doc.get("links");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<JSONObject> linksIter = links.iterator();
|
||||
while(linksIter.hasNext()){
|
||||
JSONObject link = linksIter.next();
|
||||
String name = (String) link.get("name");
|
||||
String src = (String) link.get("source");
|
||||
String dst = (String) link.get("destination");
|
||||
|
||||
Object reqBw = link.get("bandwidth");
|
||||
|
||||
long bw = 0;
|
||||
if(reqBw != null)
|
||||
bw = (Long) reqBw;
|
||||
|
||||
Node source = getNode(graph, src);
|
||||
Node target = getNode(graph, dst);
|
||||
|
||||
Edge edge = new Edge(target, name, bw);
|
||||
graph.addEdge(source, edge);
|
||||
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
// convert from Graph object to JSON object
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String graphToJson(Graph graph){
|
||||
if(graph.getAdjacencyList().size() < 1){
|
||||
return "Graph is Empty";
|
||||
}
|
||||
Map<Node, List<Node>> edgeList = new HashMap<Node, List<Node>>();
|
||||
|
||||
JSONObject topo = new JSONObject();
|
||||
JSONArray nodes = new JSONArray();
|
||||
JSONArray links = new JSONArray();
|
||||
|
||||
for (Entry<Node, List<Edge>> entry : graph.getAdjacencyList().entrySet()) {
|
||||
Node srcNode = entry.getKey();
|
||||
|
||||
// add node
|
||||
JSONObject jobj = new JSONObject();
|
||||
switch(srcNode.getType()){
|
||||
case "host":
|
||||
HostNode hNode = (HostNode)srcNode;
|
||||
jobj.put("name", hNode.getName());
|
||||
jobj.put("type", hNode.getType());
|
||||
jobj.put("pes", hNode.getPes());
|
||||
jobj.put("mips", hNode.getMips());
|
||||
jobj.put("ram", hNode.getRam());
|
||||
jobj.put("storage", hNode.getStorage());
|
||||
jobj.put("bw", hNode.getBw());
|
||||
break;
|
||||
case "core":
|
||||
case "edge":
|
||||
SwitchNode sNode = (SwitchNode)srcNode;
|
||||
jobj.put("name", sNode.getName());
|
||||
jobj.put("type", sNode.getType());
|
||||
jobj.put("iops", sNode.getIops());
|
||||
jobj.put("upports", sNode.getDownports());
|
||||
jobj.put("downports", sNode.getDownports());
|
||||
jobj.put("bw", sNode.getBw());
|
||||
break;
|
||||
case "vm":
|
||||
VmNode vNode = (VmNode)srcNode;
|
||||
jobj.put("name", vNode.getName());
|
||||
jobj.put("type", vNode.getType());
|
||||
jobj.put("size", vNode.getSize());
|
||||
jobj.put("pes", vNode.getPes());
|
||||
jobj.put("mips", vNode.getMips());
|
||||
jobj.put("ram", vNode.getRam());
|
||||
break;
|
||||
}
|
||||
nodes.add(jobj);
|
||||
|
||||
// add edge
|
||||
for (Edge edge : entry.getValue()) {
|
||||
Node destNode = edge.getNode();
|
||||
|
||||
// check if edge exist (dest->src)
|
||||
if (edgeList.containsKey(destNode) && edgeList.get(destNode).contains(srcNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject jobj2 = new JSONObject();
|
||||
jobj2.put("source", srcNode.getName());
|
||||
jobj2.put("destination", destNode.getName());
|
||||
if("host"==destNode.getType() || "core"==destNode.getType() || "edge"==destNode.getType()){
|
||||
jobj2.put("latency", edge.getLatency());
|
||||
}else if("vm"==destNode.getName()){
|
||||
if(edge.getBandwidth()>0){
|
||||
jobj2.put("bandwidth", edge.getBandwidth());
|
||||
}
|
||||
}
|
||||
links.add(jobj2);
|
||||
|
||||
// add exist edge to the edgeList
|
||||
if (edgeList.containsKey(entry.getKey())) {
|
||||
edgeList.get(entry.getKey()).add(edge.getNode());
|
||||
} else {
|
||||
List<Node> ns = new ArrayList<Node>();
|
||||
ns.add(edge.getNode());
|
||||
edgeList.put(entry.getKey(), ns);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
topo.put("nodes", nodes);
|
||||
topo.put("links", links);
|
||||
|
||||
StringWriter out = new StringWriter();
|
||||
String jsonText = "";
|
||||
try {
|
||||
topo.writeJSONString(out);
|
||||
jsonText = out.toString();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//System.out.println(jsonText);
|
||||
return jsonText;
|
||||
}
|
||||
|
||||
}
|
||||
36
src/org/cloudbus/cloudsim/sdn/graph/core/Coordinates.java
Normal file
36
src/org/cloudbus/cloudsim/sdn/graph/core/Coordinates.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
public class Coordinates {
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
public Coordinates() {
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
}
|
||||
public Coordinates(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Coordinates [abscissa=" + x + ", ordinate=" + y + "]";
|
||||
}
|
||||
|
||||
}
|
||||
93
src/org/cloudbus/cloudsim/sdn/graph/core/Edge.java
Normal file
93
src/org/cloudbus/cloudsim/sdn/graph/core/Edge.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The model that represents an edge with two vertexes, for physical link and virtual edge.
|
||||
*
|
||||
*/
|
||||
public class Edge implements Serializable {
|
||||
private static final long serialVersionUID = -356975278987708987L;
|
||||
|
||||
private Node dest = null;
|
||||
|
||||
private double latency = 0.0;
|
||||
private String name = "";
|
||||
private long bandwidth = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param node the node that belongs to the edge.
|
||||
*/
|
||||
public Edge(Node to) {
|
||||
this.dest = to;
|
||||
}
|
||||
|
||||
/** physical topology link */
|
||||
public Edge(Node to, double latency) {
|
||||
this.dest = to;
|
||||
this.latency = latency;
|
||||
}
|
||||
|
||||
/** virtual virtual edge */
|
||||
public Edge(Node to, String name, long bw) {
|
||||
this.dest = to;
|
||||
this.name = name;
|
||||
this.bandwidth = bw;
|
||||
}
|
||||
|
||||
/** copy edge */
|
||||
public Edge(Node to, Map<String, Object> info){
|
||||
this.dest = to;
|
||||
if(info.get("name")!=null){
|
||||
this.name = (String) info.get("name");
|
||||
}
|
||||
if(info.get("bandwidth")!=null){
|
||||
this.bandwidth = (long) info.get("bandwidth");
|
||||
}
|
||||
if(info.get("latency")!=null){
|
||||
this.latency = (double) info.get("latency");
|
||||
}
|
||||
}
|
||||
|
||||
public Node getNode() {
|
||||
return dest;
|
||||
}
|
||||
|
||||
public long getBandwidth() {
|
||||
return bandwidth;
|
||||
}
|
||||
|
||||
public double getLatency() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
public Map<String, Object> getInfo() {
|
||||
Map<String, Object> info = new HashMap<String, Object>();
|
||||
info.put("name", this.name);
|
||||
info.put("bandwidth",this.bandwidth);
|
||||
info.put("latency", this.latency);
|
||||
return info;
|
||||
}
|
||||
|
||||
public void setInfo(Map<String, Object> info){
|
||||
if(info.get("name")!=null){
|
||||
this.name = (String) info.get("name");
|
||||
}
|
||||
if(info.get("bandwidth")!=null){
|
||||
this.bandwidth = (long) info.get("bandwidth");
|
||||
}
|
||||
if(info.get("latency")!=null){
|
||||
this.latency = (double) info.get("latency");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Edge [dest=" + dest + "]";
|
||||
}
|
||||
|
||||
}
|
||||
153
src/org/cloudbus/cloudsim/sdn/graph/core/Graph.java
Normal file
153
src/org/cloudbus/cloudsim/sdn/graph/core/Graph.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* A graph model. Normally a model should not have any logic, but in this case we implement logic to manipulate the
|
||||
* adjacencyList like reorganizing, adding nodes, removing nodes, e.g
|
||||
*
|
||||
*/
|
||||
public class Graph implements Serializable {
|
||||
private static final long serialVersionUID = 745864022429447529L;
|
||||
|
||||
private Map<Node, List<Edge>> adjacencyList;
|
||||
|
||||
|
||||
public Graph() {
|
||||
// when creating a new graph ensure that a new adjacencyList is created
|
||||
adjacencyList = new HashMap<Node, List<Edge>>();
|
||||
}
|
||||
|
||||
public Graph(Map<Node, List<Edge>> adjacencyList) {
|
||||
this.adjacencyList = adjacencyList;
|
||||
}
|
||||
|
||||
public void setAdjacencyList(Map<Node, List<Edge>> adjacencyList) {
|
||||
this.adjacencyList = adjacencyList;
|
||||
}
|
||||
|
||||
public Map<Node, List<Edge>> getAdjacencyList() {
|
||||
return adjacencyList;
|
||||
}
|
||||
|
||||
/** Adds a given edge to the adjacency list. If the base node is not yet part of the adjacency list a new entry is added */
|
||||
public void addEdge(Node key, Edge value) {
|
||||
|
||||
if (adjacencyList.containsKey(key)) {
|
||||
if (adjacencyList.get(key) == null) {
|
||||
adjacencyList.put(key, new ArrayList<Edge>());
|
||||
}
|
||||
// TODO: perhaps check if a value may not be added twice.
|
||||
// add edge if not null
|
||||
if (value != null) {
|
||||
adjacencyList.get(key).add(value);
|
||||
}
|
||||
} else {
|
||||
List<Edge> edges = new ArrayList<Edge>();
|
||||
// add edge if not null
|
||||
if (value != null) {
|
||||
edges.add(value);
|
||||
}
|
||||
|
||||
adjacencyList.put(key, edges);
|
||||
}
|
||||
|
||||
// do bidirectional adding. Ugly duplicated code.
|
||||
// only execute when there is an edge defined.
|
||||
if (value != null) {
|
||||
Edge reverseEdge = new Edge(key, value.getInfo());
|
||||
|
||||
if (adjacencyList.containsKey(value.getNode())) {
|
||||
if (adjacencyList.get(value.getNode()) == null) {
|
||||
adjacencyList.put(value.getNode(), new ArrayList<Edge>());
|
||||
}
|
||||
// TODO: perhaps check if a value may not be added twice.
|
||||
// add edge if not null
|
||||
if (reverseEdge != null) {
|
||||
adjacencyList.get(value.getNode()).add(reverseEdge);
|
||||
}
|
||||
} else {
|
||||
List<Edge> edges = new ArrayList<Edge>();
|
||||
// add edge if not null
|
||||
if (reverseEdge != null) {
|
||||
edges.add(reverseEdge);
|
||||
}
|
||||
|
||||
adjacencyList.put(value.getNode(), edges);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Simply adds a new node, without setting any edges */
|
||||
public void addNode(Node node) {
|
||||
addEdge(node, null);
|
||||
}
|
||||
|
||||
public void removeEdge(Node key, Edge value) {
|
||||
|
||||
if (!adjacencyList.containsKey(key)) {
|
||||
throw new IllegalArgumentException("The adjacency list does not contain a node for the given key: " + key);
|
||||
}
|
||||
List<Edge> edges = adjacencyList.get(key);
|
||||
|
||||
if (!edges.contains(value)) {
|
||||
throw new IllegalArgumentException("The list of edges does not contain the given edge to remove: " + value);
|
||||
}
|
||||
|
||||
edges.remove(value);
|
||||
// remove bidirectional
|
||||
List<Edge> reverseEdges = adjacencyList.get(value.getNode());
|
||||
List<Edge> toRemove = new ArrayList<Edge>();
|
||||
for (Edge edge : reverseEdges) {
|
||||
if (edge.getNode().equals(key)) {
|
||||
toRemove.add(edge);
|
||||
}
|
||||
}
|
||||
//normally only one element
|
||||
reverseEdges.removeAll(toRemove);
|
||||
}
|
||||
|
||||
/** Deletes a node */
|
||||
public void removeNode(Node key) {
|
||||
|
||||
if (!adjacencyList.containsKey(key)) {
|
||||
throw new IllegalArgumentException("The adjacency list does not contain a node for the given key: " + key);
|
||||
}
|
||||
|
||||
adjacencyList.remove(key);
|
||||
|
||||
// clean up all edges
|
||||
for (Entry<Node, List<Edge>> entry : adjacencyList.entrySet()) {
|
||||
|
||||
List<Edge> toRemove = new ArrayList<Edge>();
|
||||
|
||||
for (Edge edge : entry.getValue()) {
|
||||
if (edge.getNode().equals(key)) {
|
||||
toRemove.add(edge);
|
||||
}
|
||||
}
|
||||
entry.getValue().removeAll(toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearGraph(){
|
||||
adjacencyList.clear();
|
||||
}
|
||||
|
||||
public String toJsonString(){
|
||||
String jsonText = Bridge.graphToJson(this);
|
||||
return jsonText;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Graph [adjacencyList=" + adjacencyList + "]";
|
||||
}
|
||||
|
||||
}
|
||||
222
src/org/cloudbus/cloudsim/sdn/graph/core/GraphView.java
Normal file
222
src/org/cloudbus/cloudsim/sdn/graph/core/GraphView.java
Normal file
@@ -0,0 +1,222 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Coordinates;
|
||||
|
||||
/** Panel that displays a graph */
|
||||
public class GraphView extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JPanel canvas;
|
||||
private Graph graph;
|
||||
private final int ARR_SIZE = 4;
|
||||
|
||||
private Image imgDefault;
|
||||
private Image imgHost;
|
||||
private Image imgSwitch;
|
||||
private Image imgVm;
|
||||
|
||||
public GraphView(final Graph graph) {
|
||||
|
||||
this.graph = graph;
|
||||
|
||||
imgHost = Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/src/host.png"));
|
||||
imgSwitch = Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/src/disk.png"));
|
||||
imgVm = Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/src/vm2.png"));
|
||||
initComponents();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
|
||||
canvas = new JPanel() {
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
|
||||
if (graph.getAdjacencyList() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Node, Coordinates> coordForNodes = new HashMap<Node, Coordinates>();
|
||||
|
||||
int offsetX = canvas.getWidth() / 2;
|
||||
int offsetY = canvas.getHeight() / 2;
|
||||
//System.out.println("sys:"+canvas.getWidth() + ":" + canvas.getHeight());
|
||||
|
||||
int height = 40;
|
||||
int width = 40;
|
||||
double angle = 2 * Math.PI / graph.getAdjacencyList().keySet().size();
|
||||
int radius = offsetY / 2 - 20;
|
||||
FontMetrics f = g.getFontMetrics();
|
||||
int nodeHeight = Math.max(height, f.getHeight());
|
||||
int nodeWidth = nodeHeight;
|
||||
|
||||
int i = 0;
|
||||
for (Node node : graph.getAdjacencyList().keySet()) {
|
||||
// calculate coordinates
|
||||
int x = Double.valueOf(offsetX + Math.cos(i * angle) * radius).intValue();
|
||||
int y = Double.valueOf(offsetY + Math.sin(i * angle) * radius).intValue();
|
||||
//System.out.println(i+":"+x+"-"+y);
|
||||
|
||||
coordForNodes.put(node, new Coordinates(x, y));
|
||||
node.setCoordinate(new Coordinates(x, y));
|
||||
i++;
|
||||
}
|
||||
|
||||
Map<Node, List<Node>> drawnList = new HashMap<Node, List<Node>>();
|
||||
// draw edges first
|
||||
// TODO: we draw one edge two times at the moment because we have an undirected graph. But this
|
||||
// shouldn`t matter because we have the same edge costs and no one will see in. Perhaps refactor later.
|
||||
for (Entry<Node, List<Edge>> entry : graph.getAdjacencyList().entrySet()) {
|
||||
|
||||
Coordinates startNode = coordForNodes.get(entry.getKey());
|
||||
|
||||
for (Edge edge : entry.getValue()) {
|
||||
|
||||
// if other direction was drawn already continue
|
||||
if (drawnList.containsKey(edge.getNode()) && drawnList.get(edge.getNode()).contains(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Coordinates targetNode = coordForNodes.get(edge.getNode());
|
||||
g.setColor(Color.RED);
|
||||
g.drawLine(startNode.getX(), startNode.getY(), targetNode.getX(), targetNode.getY());
|
||||
|
||||
// add drawn edges to the drawnList
|
||||
if (drawnList.containsKey(entry.getKey())) {
|
||||
drawnList.get(entry.getKey()).add(edge.getNode());
|
||||
} else {
|
||||
List<Node> nodes = new ArrayList<Node>();
|
||||
nodes.add(edge.getNode());
|
||||
drawnList.put(entry.getKey(), nodes);
|
||||
}
|
||||
|
||||
// if (startNode.getX() - targetNode.getX() < 0) {
|
||||
|
||||
// int tx = 0;
|
||||
// int ty = 0;
|
||||
// double gradient = (targetNode.getY() - startNode.getY()) /
|
||||
// (targetNode.getX() - startNode.getX());
|
||||
// LOGGER.log(Level.INFO, "Gradient: " + gradient);
|
||||
|
||||
// if (startNode.getX() == targetNode.getX()) {
|
||||
// tx = targetNode.getX();
|
||||
// } else {
|
||||
// if ((startNode.getX() - targetNode.getX()) < 0) {
|
||||
// tx = targetNode.getX() - Double.valueOf((nodeHeight / 2)).intValue();
|
||||
// } else {
|
||||
// tx = targetNode.getX() + Double.valueOf((nodeHeight / 2)).intValue();
|
||||
// }
|
||||
// }
|
||||
// if (startNode.getY() == targetNode.getY()) {
|
||||
// ty = targetNode.getY();
|
||||
// } else {
|
||||
// if ((startNode.getY() - targetNode.getY()) < 0) {
|
||||
// ty = targetNode.getY() - Double.valueOf((nodeHeight / 2)).intValue();
|
||||
// } else {
|
||||
// ty = targetNode.getY() + Double.valueOf((nodeHeight / 2)).intValue();
|
||||
// }
|
||||
// }
|
||||
|
||||
// drawArrow(g, startNode.getX(), startNode.getY(), tx, ty);
|
||||
|
||||
// draw edge costs
|
||||
int labelX = (startNode.getX() - targetNode.getX()) / 2;
|
||||
int labelY = (startNode.getY() - targetNode.getY()) / 2;
|
||||
|
||||
labelX *= -1;
|
||||
labelY *= -1;
|
||||
|
||||
labelX += startNode.getX();
|
||||
labelY += startNode.getY();
|
||||
|
||||
//g.setColor(Color.BLACK);
|
||||
//g.drawString(String.valueOf(edge.getInfo()), labelX - f.stringWidth(String.valueOf(edge.getInfo())) / 2, labelY + f.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<Node, Coordinates> entry : coordForNodes.entrySet()) {
|
||||
// first paint a single node for testing.
|
||||
g.setColor(Color.black);
|
||||
// int nodeWidth = Math.max(width, f.stringWidth(entry.getKey().getNodeText()) + width / 2);
|
||||
|
||||
Coordinates wrapper = entry.getValue();
|
||||
switch(entry.getKey().getType()){
|
||||
case "host":
|
||||
g.drawImage(imgHost, wrapper.getX() - nodeWidth / 2, wrapper.getY() - nodeHeight / 2, nodeWidth, nodeHeight, this);
|
||||
break;
|
||||
case "vm":
|
||||
g.drawImage(imgVm, wrapper.getX() - nodeWidth / 2, wrapper.getY() - nodeHeight / 2, nodeWidth, nodeHeight, this);
|
||||
break;
|
||||
case "core":
|
||||
case "edge":
|
||||
g.drawImage(imgSwitch, wrapper.getX() - nodeWidth / 2, wrapper.getY() - nodeHeight / 2, nodeWidth, nodeHeight, this);
|
||||
break;
|
||||
}
|
||||
|
||||
//g.setColor(Color.white);
|
||||
//g.fillOval(wrapper.getX() - nodeWidth / 2, wrapper.getY() - nodeHeight / 2, nodeWidth, nodeHeight);
|
||||
//g.setColor(Color.black);
|
||||
//g.drawOval(wrapper.getX() - nodeWidth / 2, wrapper.getY() - nodeHeight / 2, nodeWidth, nodeHeight);
|
||||
//System.out.println((wrapper.getX())+" "+(wrapper.getY()));
|
||||
|
||||
//g.drawString(entry.getKey().getName(), wrapper.getX() - f.stringWidth(entry.getKey().getName()) / 2, wrapper.getY() + f.getHeight() / 2);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
JScrollPane scrollPane = new JScrollPane(canvas);
|
||||
|
||||
// canvas.setBorder(BorderFactory.createLineBorder(Color.GREEN));
|
||||
// scrollPane.setBorder(BorderFactory.createLineBorder(Color.BLUE));
|
||||
// scrollPane.setPreferredSize(new Dimension(200, 200));
|
||||
|
||||
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
|
||||
add(scrollPane);
|
||||
}
|
||||
|
||||
private void drawArrow(Graphics g1, int x1, int y1, int x2, int y2) {
|
||||
Graphics2D g = (Graphics2D) g1.create();
|
||||
|
||||
double dx = x2 - x1, dy = y2 - y1;
|
||||
double angle = Math.atan2(dy, dx);
|
||||
int len = (int) Math.sqrt(dx * dx + dy * dy);
|
||||
AffineTransform at = AffineTransform.getTranslateInstance(x1, y1);
|
||||
at.concatenate(AffineTransform.getRotateInstance(angle));
|
||||
g.transform(at);
|
||||
|
||||
// Draw horizontal arrow starting in (0, 0)
|
||||
// g.drawLine(0, 0, len, 0);
|
||||
g.fillPolygon(new int[] { len, len - ARR_SIZE, len - ARR_SIZE, len }, new int[] { 0, -ARR_SIZE, ARR_SIZE, 0 }, 4);
|
||||
}
|
||||
|
||||
public void setGraph(Graph newGraph){
|
||||
this.graph = newGraph;
|
||||
/*this.graph.clearGraph();
|
||||
for (Entry<Node, List<Edge>> entry : newGraph.getAdjacencyList().entrySet()) {
|
||||
graph.addNode(entry.getKey());
|
||||
for (Edge edge : entry.getValue()) {
|
||||
graph.addEdge(entry.getKey(), edge);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
74
src/org/cloudbus/cloudsim/sdn/graph/core/HostNode.java
Normal file
74
src/org/cloudbus/cloudsim/sdn/graph/core/HostNode.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
/**
|
||||
* The model that represents virtual machine node for the graph.
|
||||
*
|
||||
*/
|
||||
public class HostNode extends Node {
|
||||
private static final long serialVersionUID = -8635044061126993668L;
|
||||
|
||||
private long pes;
|
||||
private long mips;
|
||||
private int ram;
|
||||
private long storage;
|
||||
private long bw;
|
||||
|
||||
|
||||
public HostNode() {
|
||||
}
|
||||
|
||||
public HostNode(String name, String type, long pes, long mips, int ram, long storage, long bw) {
|
||||
super(name, type);
|
||||
this.pes = pes;
|
||||
this.mips = mips;
|
||||
this.ram = ram;
|
||||
this.storage = storage;
|
||||
this.bw = bw;
|
||||
}
|
||||
|
||||
public void setPes(long pes) {
|
||||
this.pes = pes;
|
||||
}
|
||||
|
||||
public long getPes() {
|
||||
return pes;
|
||||
}
|
||||
|
||||
public void setMips(long mips) {
|
||||
this.mips = mips;
|
||||
}
|
||||
|
||||
public long getMips() {
|
||||
return mips;
|
||||
}
|
||||
|
||||
public void setRam(int ram) {
|
||||
this.ram = ram;
|
||||
}
|
||||
|
||||
public int getRam() {
|
||||
return ram;
|
||||
}
|
||||
|
||||
public void setStorage(long storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
public long getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public void setBw(long bw) {
|
||||
this.bw = bw;
|
||||
}
|
||||
|
||||
public long getBw() {
|
||||
return bw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node [pes=" + pes + " mips=" + mips + " ram=" + ram + " storage=" + storage + " bw=" + bw + "]";
|
||||
}
|
||||
|
||||
}
|
||||
82
src/org/cloudbus/cloudsim/sdn/graph/core/Node.java
Normal file
82
src/org/cloudbus/cloudsim/sdn/graph/core/Node.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Coordinates;
|
||||
|
||||
/**
|
||||
* The model that represents node (host or vm) for the graph.
|
||||
*
|
||||
*/
|
||||
public class Node implements Serializable {
|
||||
private static final long serialVersionUID = 823544330517091616L;
|
||||
|
||||
private Coordinates coord;
|
||||
private String name;
|
||||
private String type;
|
||||
|
||||
public Node() {
|
||||
}
|
||||
|
||||
public Node(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
coord = new Coordinates();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setCoordinate(Coordinates coord) {
|
||||
this.coord.setX(coord.getX());
|
||||
this.coord.setY(coord.getY());
|
||||
}
|
||||
|
||||
public Coordinates getCoordinate() {
|
||||
return coord;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Node other = (Node) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node [name=" + name + " type=" + type + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListCellRenderer;
|
||||
|
||||
/** A cell renderer for the JComboBox when displaying a node object */
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class NodeCellRenderer extends JLabel implements ListCellRenderer {
|
||||
private static final long serialVersionUID = 6021697923766790099L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
Node node = (Node) value;
|
||||
JLabel label = new JLabel();
|
||||
|
||||
if (node != null && node.getName() != null) {
|
||||
label.setText(node.getName());
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
194
src/org/cloudbus/cloudsim/sdn/graph/core/SpringUtilities.java
Normal file
194
src/org/cloudbus/cloudsim/sdn/graph/core/SpringUtilities.java
Normal file
@@ -0,0 +1,194 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.SpringLayout;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* A 1.4 file that provides utility methods for
|
||||
* creating form- or grid-style layouts with SpringLayout.
|
||||
* These utilities are used by several programs, such as
|
||||
* SpringBox and SpringCompactGrid.
|
||||
*/
|
||||
public class SpringUtilities {
|
||||
/**
|
||||
* A debugging utility that prints to stdout the component's
|
||||
* minimum, preferred, and maximum sizes.
|
||||
*/
|
||||
public static void printSizes(Component c) {
|
||||
System.out.println("minimumSize = " + c.getMinimumSize());
|
||||
System.out.println("preferredSize = " + c.getPreferredSize());
|
||||
System.out.println("maximumSize = " + c.getMaximumSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Aligns the first <code>rows</code> * <code>cols</code>
|
||||
* components of <code>parent</code> in
|
||||
* a grid. Each component is as big as the maximum
|
||||
* preferred width and height of the components.
|
||||
* The parent is made just big enough to fit them all.
|
||||
*
|
||||
* @param rows number of rows
|
||||
* @param cols number of columns
|
||||
* @param initialX x location to start the grid at
|
||||
* @param initialY y location to start the grid at
|
||||
* @param xPad x padding between cells
|
||||
* @param yPad y padding between cells
|
||||
*/
|
||||
public static void makeGrid(Container parent,
|
||||
int rows, int cols,
|
||||
int initialX, int initialY,
|
||||
int xPad, int yPad) {
|
||||
SpringLayout layout;
|
||||
try {
|
||||
layout = (SpringLayout)parent.getLayout();
|
||||
} catch (ClassCastException exc) {
|
||||
System.err.println("The first argument to makeGrid must use SpringLayout.");
|
||||
return;
|
||||
}
|
||||
|
||||
Spring xPadSpring = Spring.constant(xPad);
|
||||
Spring yPadSpring = Spring.constant(yPad);
|
||||
Spring initialXSpring = Spring.constant(initialX);
|
||||
Spring initialYSpring = Spring.constant(initialY);
|
||||
int max = rows * cols;
|
||||
|
||||
//Calculate Springs that are the max of the width/height so that all
|
||||
//cells have the same size.
|
||||
Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)).
|
||||
getWidth();
|
||||
Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)).
|
||||
getHeight();
|
||||
for (int i = 1; i < max; i++) {
|
||||
SpringLayout.Constraints cons = layout.getConstraints(
|
||||
parent.getComponent(i));
|
||||
|
||||
maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth());
|
||||
maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight());
|
||||
}
|
||||
|
||||
//Apply the new width/height Spring. This forces all the
|
||||
//components to have the same size.
|
||||
for (int i = 0; i < max; i++) {
|
||||
SpringLayout.Constraints cons = layout.getConstraints(
|
||||
parent.getComponent(i));
|
||||
|
||||
cons.setWidth(maxWidthSpring);
|
||||
cons.setHeight(maxHeightSpring);
|
||||
}
|
||||
|
||||
//Then adjust the x/y constraints of all the cells so that they
|
||||
//are aligned in a grid.
|
||||
SpringLayout.Constraints lastCons = null;
|
||||
SpringLayout.Constraints lastRowCons = null;
|
||||
for (int i = 0; i < max; i++) {
|
||||
SpringLayout.Constraints cons = layout.getConstraints(
|
||||
parent.getComponent(i));
|
||||
if (i % cols == 0) { //start of new row
|
||||
lastRowCons = lastCons;
|
||||
cons.setX(initialXSpring);
|
||||
} else { //x position depends on previous component
|
||||
cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST),
|
||||
xPadSpring));
|
||||
}
|
||||
|
||||
if (i / cols == 0) { //first row
|
||||
cons.setY(initialYSpring);
|
||||
} else { //y position depends on previous row
|
||||
cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH),
|
||||
yPadSpring));
|
||||
}
|
||||
lastCons = cons;
|
||||
}
|
||||
|
||||
//Set the parent's size.
|
||||
SpringLayout.Constraints pCons = layout.getConstraints(parent);
|
||||
pCons.setConstraint(SpringLayout.SOUTH,
|
||||
Spring.sum(
|
||||
Spring.constant(yPad),
|
||||
lastCons.getConstraint(SpringLayout.SOUTH)));
|
||||
pCons.setConstraint(SpringLayout.EAST,
|
||||
Spring.sum(
|
||||
Spring.constant(xPad),
|
||||
lastCons.getConstraint(SpringLayout.EAST)));
|
||||
}
|
||||
|
||||
/* Used by makeCompactGrid. */
|
||||
private static SpringLayout.Constraints getConstraintsForCell(
|
||||
int row, int col,
|
||||
Container parent,
|
||||
int cols) {
|
||||
SpringLayout layout = (SpringLayout) parent.getLayout();
|
||||
Component c = parent.getComponent(row * cols + col);
|
||||
return layout.getConstraints(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aligns the first <code>rows</code> * <code>cols</code>
|
||||
* components of <code>parent</code> in
|
||||
* a grid. Each component in a column is as wide as the maximum
|
||||
* preferred width of the components in that column;
|
||||
* height is similarly determined for each row.
|
||||
* The parent is made just big enough to fit them all.
|
||||
*
|
||||
* @param rows number of rows
|
||||
* @param cols number of columns
|
||||
* @param initialX x location to start the grid at
|
||||
* @param initialY y location to start the grid at
|
||||
* @param xPad x padding between cells
|
||||
* @param yPad y padding between cells
|
||||
*/
|
||||
public static void makeCompactGrid(Container parent,
|
||||
int rows, int cols,
|
||||
int initialX, int initialY,
|
||||
int xPad, int yPad) {
|
||||
SpringLayout layout;
|
||||
try {
|
||||
layout = (SpringLayout)parent.getLayout();
|
||||
} catch (ClassCastException exc) {
|
||||
System.err.println("The first argument to makeCompactGrid must use SpringLayout.");
|
||||
return;
|
||||
}
|
||||
|
||||
//Align all cells in each column and make them the same width.
|
||||
Spring x = Spring.constant(initialX);
|
||||
for (int c = 0; c < cols; c++) {
|
||||
Spring width = Spring.constant(0);
|
||||
for (int r = 0; r < rows; r++) {
|
||||
width = Spring.max(width,
|
||||
getConstraintsForCell(r, c, parent, cols).
|
||||
getWidth());
|
||||
}
|
||||
for (int r = 0; r < rows; r++) {
|
||||
SpringLayout.Constraints constraints =
|
||||
getConstraintsForCell(r, c, parent, cols);
|
||||
constraints.setX(x);
|
||||
constraints.setWidth(width);
|
||||
}
|
||||
x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad)));
|
||||
}
|
||||
|
||||
//Align all cells in each row and make them the same height.
|
||||
Spring y = Spring.constant(initialY);
|
||||
for (int r = 0; r < rows; r++) {
|
||||
Spring height = Spring.constant(0);
|
||||
for (int c = 0; c < cols; c++) {
|
||||
height = Spring.max(height,
|
||||
getConstraintsForCell(r, c, parent, cols).
|
||||
getHeight());
|
||||
}
|
||||
for (int c = 0; c < cols; c++) {
|
||||
SpringLayout.Constraints constraints =
|
||||
getConstraintsForCell(r, c, parent, cols);
|
||||
constraints.setY(y);
|
||||
constraints.setHeight(height);
|
||||
}
|
||||
y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad)));
|
||||
}
|
||||
|
||||
//Set the parent's size.
|
||||
SpringLayout.Constraints pCons = layout.getConstraints(parent);
|
||||
pCons.setConstraint(SpringLayout.SOUTH, y);
|
||||
pCons.setConstraint(SpringLayout.EAST, x);
|
||||
}
|
||||
}
|
||||
62
src/org/cloudbus/cloudsim/sdn/graph/core/SwitchNode.java
Normal file
62
src/org/cloudbus/cloudsim/sdn/graph/core/SwitchNode.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
/**
|
||||
* The model that represents virtual machine node for the graph.
|
||||
*
|
||||
*/
|
||||
public class SwitchNode extends Node {
|
||||
private static final long serialVersionUID = 804858850147477656L;
|
||||
|
||||
private long iops;
|
||||
private int upports;
|
||||
private int downports;
|
||||
private long bw;
|
||||
|
||||
|
||||
public SwitchNode() {
|
||||
}
|
||||
|
||||
public SwitchNode(String name, String type, long iops, int upports, int downports, long bw) {
|
||||
super(name, type);
|
||||
this.iops = iops;
|
||||
this.upports = upports;
|
||||
this.downports = downports;
|
||||
this.bw = bw;
|
||||
}
|
||||
|
||||
public void setIops(long iops) {
|
||||
this.iops = iops;
|
||||
}
|
||||
|
||||
public long getIops() {
|
||||
return iops;
|
||||
}
|
||||
|
||||
public void setUpports(int upports) {
|
||||
this.upports = upports;
|
||||
}
|
||||
|
||||
public int getUpports() {
|
||||
return upports;
|
||||
}
|
||||
public void setDownports(int downports) {
|
||||
this.downports = downports;
|
||||
}
|
||||
|
||||
public int getDownports() {
|
||||
return downports;
|
||||
}
|
||||
public void setBw(long bw) {
|
||||
this.bw = bw;
|
||||
}
|
||||
|
||||
public long getBw() {
|
||||
return bw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node [iops=" + iops + " upports=" + upports + " downports=" + downports + " bw=" + bw + "]";
|
||||
}
|
||||
|
||||
}
|
||||
62
src/org/cloudbus/cloudsim/sdn/graph/core/VmNode.java
Normal file
62
src/org/cloudbus/cloudsim/sdn/graph/core/VmNode.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.core;
|
||||
|
||||
/**
|
||||
* The model that represents virtual machine node for the graph.
|
||||
*
|
||||
*/
|
||||
public class VmNode extends Node {
|
||||
private static final long serialVersionUID = 804858850147477656L;
|
||||
|
||||
private long size;
|
||||
private int pes;
|
||||
private long mips;
|
||||
private int ram;
|
||||
|
||||
|
||||
public VmNode() {
|
||||
}
|
||||
|
||||
public VmNode(String name, String type, long size, int pes, long mips, int ram) {
|
||||
super(name, type);
|
||||
this.size = size;
|
||||
this.pes = pes;
|
||||
this.mips = mips;
|
||||
this.ram = ram;
|
||||
}
|
||||
|
||||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setPes(int pes) {
|
||||
this.pes = pes;
|
||||
}
|
||||
|
||||
public int getPes() {
|
||||
return pes;
|
||||
}
|
||||
public void setMips(long mips) {
|
||||
this.mips = mips;
|
||||
}
|
||||
|
||||
public long getMips() {
|
||||
return mips;
|
||||
}
|
||||
public void setRam(int ram) {
|
||||
this.ram = ram;
|
||||
}
|
||||
|
||||
public int getRam() {
|
||||
return ram;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node [size=" + size + " pes=" + pes + " mips=" + mips + " ram=" + ram + "]";
|
||||
}
|
||||
|
||||
}
|
||||
59
src/org/cloudbus/cloudsim/sdn/graph/dialog/About.java
Normal file
59
src/org/cloudbus/cloudsim/sdn/graph/dialog/About.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.dialog;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class About extends JDialog {
|
||||
|
||||
public About() {
|
||||
initUI();
|
||||
}
|
||||
|
||||
public final void initUI() {
|
||||
|
||||
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
|
||||
|
||||
add(Box.createRigidArea(new Dimension(0, 10)));
|
||||
|
||||
ImageIcon icon = new ImageIcon("src/logo.png");
|
||||
JLabel label = new JLabel(icon);
|
||||
label.setAlignmentX(0.5f);
|
||||
add(label);
|
||||
|
||||
add(Box.createRigidArea(new Dimension(0, 10)));
|
||||
|
||||
JLabel name = new JLabel("CloudSim SDN, 1.00");
|
||||
name.setFont(new Font("Serif", Font.BOLD, 15));
|
||||
name.setAlignmentX(0.5f);
|
||||
add(name);
|
||||
|
||||
add(Box.createRigidArea(new Dimension(0, 50)));
|
||||
|
||||
JButton close = new JButton("Close");
|
||||
close.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
|
||||
close.setAlignmentX(0.5f);
|
||||
add(close);
|
||||
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
|
||||
setTitle("About CloudSim");
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
setLocationRelativeTo(null);
|
||||
setSize(350, 300);
|
||||
}
|
||||
}
|
||||
217
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddPhysicalEdge.java
Normal file
217
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddPhysicalEdge.java
Normal file
@@ -0,0 +1,217 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.dialog;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Label;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Edge;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Graph;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Node;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.NodeCellRenderer;
|
||||
|
||||
/** A dialog to add a new edge */
|
||||
public class AddPhysicalEdge extends JDialog {
|
||||
private static final long serialVersionUID = 4794808969864918000L;
|
||||
|
||||
private final Graph graph;
|
||||
private JComboBox sourceNode;
|
||||
private JComboBox targetNode;
|
||||
private JTextField tfLatency;
|
||||
|
||||
|
||||
public AddPhysicalEdge(final Graph graph, final JFrame frame) {
|
||||
|
||||
this.graph = graph;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(createInputPanel(), BorderLayout.CENTER);
|
||||
add(createButtonPanel(), BorderLayout.PAGE_END);
|
||||
// show dialog
|
||||
setTitle("Add Physical Topology edge");
|
||||
setModal(true);
|
||||
setPreferredSize(new Dimension(400, 200));
|
||||
setResizable(false);
|
||||
pack();
|
||||
setLocationRelativeTo(frame); // must be called between pack and setVisible to work properly
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private JPanel createInputPanel() {
|
||||
|
||||
Component rigid = Box.createRigidArea(new Dimension(10, 0));
|
||||
|
||||
JPanel inputPanelWrapper = new JPanel();
|
||||
inputPanelWrapper.setLayout(new BoxLayout(inputPanelWrapper, BoxLayout.PAGE_AXIS));
|
||||
|
||||
JPanel inputPanel = new JPanel();
|
||||
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
JPanel textAreaPanel = new JPanel();
|
||||
textAreaPanel.setLayout(new BoxLayout(textAreaPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
ComboBoxModel sourceNodeModel = new DefaultComboBoxModel(graph.getAdjacencyList().keySet().toArray());
|
||||
|
||||
sourceNodeModel.setSelectedItem(null);
|
||||
|
||||
sourceNode = new JComboBox(sourceNodeModel);
|
||||
targetNode = new JComboBox();
|
||||
sourceNode.setMaximumSize(sourceNode.getPreferredSize());
|
||||
sourceNode.setMinimumSize(new Dimension(150, sourceNode.getPreferredSize().height));
|
||||
sourceNode.setPreferredSize(new Dimension(150, sourceNode.getPreferredSize().height));
|
||||
targetNode.setMaximumSize(targetNode.getPreferredSize());
|
||||
targetNode.setMinimumSize(new Dimension(150, targetNode.getPreferredSize().height));
|
||||
targetNode.setPreferredSize(new Dimension(150, targetNode.getPreferredSize().height));
|
||||
|
||||
NodeCellRenderer renderer = new NodeCellRenderer();
|
||||
|
||||
sourceNode.setRenderer(renderer);
|
||||
targetNode.setRenderer(renderer);
|
||||
|
||||
sourceNode.addItemListener(new ItemListener() {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
// only display nodes which do not have already an edge
|
||||
|
||||
targetNode.removeAllItems();
|
||||
Node selectedNode = (Node) sourceNode.getSelectedItem();
|
||||
|
||||
if (selectedNode != null) {
|
||||
|
||||
List<Node> nodesToDisplay = new ArrayList<Node>();
|
||||
Set<Node> allNodes = graph.getAdjacencyList().keySet();
|
||||
|
||||
// get edged for selected node and throw out all target nodes where already an edge exists
|
||||
List<Edge> edgesForSelectedNode = graph.getAdjacencyList().get(selectedNode);
|
||||
Set<Node> nodesInEdges = new HashSet<Node>();
|
||||
for (Edge edge : edgesForSelectedNode) {
|
||||
nodesInEdges.add(edge.getNode());
|
||||
}
|
||||
|
||||
for (Node node : allNodes) {
|
||||
if (!node.equals(selectedNode) && !nodesInEdges.contains(node)) {
|
||||
nodesToDisplay.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
ComboBoxModel targetNodeModel = new DefaultComboBoxModel(nodesToDisplay.toArray());
|
||||
targetNode.setModel(targetNodeModel);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
inputPanel.add(sourceNode);
|
||||
inputPanel.add(new Label(" ¡ª"));
|
||||
inputPanel.add(targetNode);
|
||||
inputPanel.add(Box.createHorizontalGlue());
|
||||
inputPanelWrapper.add(inputPanel);
|
||||
|
||||
textAreaPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
textAreaPanel.add(new JLabel("Latency: "));
|
||||
tfLatency = new JTextField();
|
||||
tfLatency.setMaximumSize(tfLatency.getPreferredSize());
|
||||
tfLatency.setMinimumSize(new Dimension(150, tfLatency.getPreferredSize().height));
|
||||
tfLatency.setPreferredSize(new Dimension(150, tfLatency.getPreferredSize().height));
|
||||
|
||||
textAreaPanel.add(tfLatency);
|
||||
textAreaPanel.add(Box.createHorizontalGlue());
|
||||
|
||||
inputPanelWrapper.add(textAreaPanel);
|
||||
inputPanelWrapper.add(Box.createVerticalGlue());
|
||||
|
||||
inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
return inputPanelWrapper;
|
||||
}
|
||||
|
||||
private JPanel createButtonPanel() {
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
JButton okBtn = new JButton("Ok");
|
||||
JButton cancelBtn = new JButton("Cancel");
|
||||
|
||||
cancelBtn.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
okBtn.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
double latency = 0;
|
||||
boolean catchedError = false;
|
||||
|
||||
if (tfLatency.getText() == null || tfLatency.getText().isEmpty()) {
|
||||
catchedError = true;
|
||||
prompt("Please type latency", "Error");
|
||||
}else {
|
||||
try {
|
||||
latency = Double.valueOf(tfLatency.getText());
|
||||
} catch (NumberFormatException e1) {
|
||||
catchedError = true;
|
||||
prompt("Latency should be double type", "Error");
|
||||
}
|
||||
}
|
||||
|
||||
if (!catchedError) {
|
||||
if (sourceNode.getSelectedItem() == null || targetNode.getSelectedItem() == null) {
|
||||
prompt("Please select node", "Error");
|
||||
} else {
|
||||
|
||||
Node source = (Node) sourceNode.getSelectedItem();
|
||||
Node target = (Node) targetNode.getSelectedItem();
|
||||
|
||||
Edge edge = new Edge(target, latency);
|
||||
graph.addEdge(source, edge);
|
||||
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
buttonPanel.add(Box.createHorizontalGlue());
|
||||
buttonPanel.add(okBtn);
|
||||
buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
buttonPanel.add(cancelBtn);
|
||||
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private void prompt(String msg, String type){
|
||||
JOptionPane.showMessageDialog(AddPhysicalEdge.this, msg, type, JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
}
|
||||
290
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddPhysicalNode.java
Normal file
290
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddPhysicalNode.java
Normal file
@@ -0,0 +1,290 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.dialog;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpringLayout;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Graph;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Node;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.SpringUtilities;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.SwitchNode;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.HostNode;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class AddPhysicalNode extends JDialog {
|
||||
private static final long serialVersionUID = -5116677861770319577L;
|
||||
|
||||
private final Graph graph;
|
||||
|
||||
private JLabel lName;
|
||||
private JLabel lType;
|
||||
private JLabel lBw;
|
||||
private JLabel lop1;
|
||||
private JLabel lop2;
|
||||
private JLabel lop3;
|
||||
private JLabel lop4;
|
||||
|
||||
private JTextField tfName;
|
||||
private JComboBox cType;
|
||||
private JTextField tfBw;
|
||||
private JTextField top1;
|
||||
private JTextField top2;
|
||||
private JTextField top3;
|
||||
private JTextField top4;
|
||||
|
||||
|
||||
public AddPhysicalNode(final Graph graph, final JFrame frame) {
|
||||
this.graph = graph;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(createInputPanelArea(), BorderLayout.CENTER);
|
||||
add(createButtonPanel(), BorderLayout.PAGE_END);
|
||||
// show dialog
|
||||
setTitle("Add Physical Node");
|
||||
setModal(true);
|
||||
setPreferredSize(new Dimension(350, 380));
|
||||
setResizable(false);
|
||||
pack();
|
||||
setLocationRelativeTo(frame);
|
||||
setVisible(true);
|
||||
|
||||
}
|
||||
|
||||
private JPanel createButtonPanel() {
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
JButton okBtn = new JButton("Ok");
|
||||
JButton cancelBtn = new JButton("Cancel");
|
||||
|
||||
cancelBtn.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
okBtn.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
boolean catchedError = false;
|
||||
if (tfName.getText() == null || tfName.getText().length() < 1) {
|
||||
prompt("Please type VM name", "Error");
|
||||
} else if (tfBw.getText() == null || tfBw.getText().length() < 1) {
|
||||
prompt("Please type VM Bw", "Error");
|
||||
} else if(cType.getSelectedIndex() < 0) {
|
||||
prompt("Please type VM Type", "Error");
|
||||
}else{
|
||||
String type = (String)cType.getSelectedItem();
|
||||
if("host"==getType(type)){
|
||||
if (top1.getText() == null || top1.getText().length() < 1) {
|
||||
prompt("Please type pes", "Error");
|
||||
} else if (top2.getText() == null || top2.getText().length() < 1) {
|
||||
prompt("Please type VM mips", "Error");
|
||||
} else if (top3.getText() == null || top3.getText().length() < 1) {
|
||||
prompt("Please type VM RAM", "Error");
|
||||
} else if (top4.getText() == null || top4.getText().length() < 1) {
|
||||
prompt("Please type VM Storage", "Error");
|
||||
} else {
|
||||
long t1 = 0;
|
||||
long t2 = 0;
|
||||
int t3 = 0;
|
||||
long t4 = 0;
|
||||
long t5 = 0;
|
||||
try {
|
||||
t1 = Long.parseLong(top1.getText());
|
||||
t2 = Long.parseLong(top2.getText());
|
||||
t3 = Integer.parseInt(top3.getText());
|
||||
t4 = Long.parseLong(top4.getText());
|
||||
t5 = Long.parseLong(tfBw.getText());
|
||||
catchedError = false;
|
||||
} catch (NumberFormatException e1) {
|
||||
catchedError = true;
|
||||
prompt("Input should be numerical character", "Error");
|
||||
}
|
||||
if(!catchedError){
|
||||
Node node = new HostNode(tfName.getText().toString(), type, t1, t2, t3, t4, t5);
|
||||
graph.addNode(node);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
}else if("switch"==getType(type)){
|
||||
if (top1.getText() == null || top1.getText().length() < 1) {
|
||||
prompt("Please type Iops", "Error");
|
||||
} else if (top2.getText() == null || top2.getText().length() < 1) {
|
||||
prompt("Please type upports", "Error");
|
||||
} else if (top3.getText() == null || top3.getText().length() < 1) {
|
||||
prompt("Please type VM downports", "Error");
|
||||
} else {
|
||||
long t1 = 0;
|
||||
int t2 = 0;
|
||||
int t3 = 0;
|
||||
long t4 = 0;
|
||||
try {
|
||||
t1 = Long.parseLong(top1.getText());
|
||||
t2 = Integer.parseInt(top2.getText());
|
||||
t3 = Integer.parseInt(top3.getText());
|
||||
t4 = Long.parseLong(tfBw.getText());
|
||||
catchedError = false;
|
||||
} catch (NumberFormatException e1) {
|
||||
catchedError = true;
|
||||
prompt("Input should be numerical character", "Error");
|
||||
}
|
||||
if(!catchedError){
|
||||
Node node = new SwitchNode(tfName.getText().toString(), type, t1, t2, t3, t4);
|
||||
graph.addNode(node);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
buttonPanel.add(Box.createHorizontalGlue());
|
||||
buttonPanel.add(okBtn);
|
||||
buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
buttonPanel.add(cancelBtn);
|
||||
buttonPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private void updatePanel(String type){
|
||||
switch(type){
|
||||
case "core":
|
||||
case "edge":
|
||||
lop1.setText("Iops: ");
|
||||
lop2.setText("Upports: ");
|
||||
lop3.setText("Downports: ");
|
||||
lop4.setVisible(false);
|
||||
|
||||
top1.setText("");
|
||||
top2.setText("");
|
||||
top3.setText("");
|
||||
top4.setVisible(false);
|
||||
break;
|
||||
|
||||
case "host":
|
||||
lop1.setText("Pes: ");
|
||||
lop2.setText("Mips: ");
|
||||
lop3.setText("Ram: ");
|
||||
lop4.setVisible(true);
|
||||
lop4.setText("Storage: ");
|
||||
|
||||
top1.setText("");
|
||||
top2.setText("");
|
||||
top3.setText("");
|
||||
top4.setVisible(true);
|
||||
top4.setText("");
|
||||
break;
|
||||
}
|
||||
}
|
||||
private String getType(String type){
|
||||
if("core"==type || "edge"==type){
|
||||
return "switch";
|
||||
} else if("host"==type){
|
||||
return "host";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
private JPanel createInputPanelArea() {
|
||||
String[] vmType = {"core","edge","host"};
|
||||
|
||||
//Create and populate the panel.
|
||||
JPanel springPanel = new JPanel(new SpringLayout());
|
||||
springPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
lName = new JLabel("Name: ");
|
||||
springPanel.add(lName);
|
||||
tfName = new JTextField();
|
||||
lName.setLabelFor(tfName);
|
||||
springPanel.add(tfName);
|
||||
|
||||
lType = new JLabel("Type: "); //, JLabel.TRAILING);
|
||||
springPanel.add(lType);
|
||||
cType = new JComboBox(vmType);
|
||||
lType.setLabelFor(cType);
|
||||
cType.setSelectedIndex(0);
|
||||
cType.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
JComboBox ctype = (JComboBox)e.getSource();
|
||||
String item = (String)ctype.getSelectedItem();
|
||||
updatePanel(item);
|
||||
}
|
||||
});
|
||||
springPanel.add(cType);
|
||||
|
||||
lBw = new JLabel("Bw: ");
|
||||
springPanel.add(lBw);
|
||||
tfBw = new JTextField();
|
||||
lBw.setLabelFor(tfBw);
|
||||
springPanel.add(tfBw);
|
||||
|
||||
/** switch and host */
|
||||
lop1 = new JLabel("Pes: ");
|
||||
springPanel.add(lop1);
|
||||
top1 = new JTextField();
|
||||
lop1.setLabelFor(top1);
|
||||
springPanel.add(top1);
|
||||
|
||||
lop2 = new JLabel("Mips: ");
|
||||
springPanel.add(lop2);
|
||||
top2 = new JTextField();
|
||||
lop2.setLabelFor(top2);
|
||||
springPanel.add(top2);
|
||||
|
||||
lop3 = new JLabel("Ram: ");
|
||||
springPanel.add(lop3);
|
||||
top3 = new JTextField();
|
||||
lop3.setLabelFor(top3);
|
||||
springPanel.add(top3);
|
||||
|
||||
lop4 = new JLabel("Storage: ");
|
||||
springPanel.add(lop4);
|
||||
top4 = new JTextField();
|
||||
lop4.setLabelFor(top4);
|
||||
springPanel.add(top4);
|
||||
|
||||
|
||||
//Lay out the panel.
|
||||
SpringUtilities.makeCompactGrid(springPanel,
|
||||
7, 2, //rows, cols
|
||||
6, 6, //initX, initY
|
||||
6, 6); //xPad, yPad
|
||||
updatePanel("core");
|
||||
return springPanel;
|
||||
}
|
||||
|
||||
public static void setUIFont (javax.swing.plaf.FontUIResource f){
|
||||
java.util.Enumeration keys = UIManager.getDefaults().keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
Object key = keys.nextElement();
|
||||
Object value = UIManager.get (key);
|
||||
if (value != null && value instanceof javax.swing.plaf.FontUIResource)
|
||||
UIManager.put (key, f);
|
||||
}
|
||||
}
|
||||
|
||||
private void prompt(String msg, String type){
|
||||
JOptionPane.showMessageDialog(AddPhysicalNode.this, msg, type, JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
239
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddVirtualEdge.java
Normal file
239
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddVirtualEdge.java
Normal file
@@ -0,0 +1,239 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.dialog;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Label;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Edge;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Graph;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Node;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.NodeCellRenderer;
|
||||
|
||||
/** A dialog to add a new edge */
|
||||
public class AddVirtualEdge extends JDialog {
|
||||
private static final long serialVersionUID = 4794808969864918000L;
|
||||
|
||||
private final Graph graph;
|
||||
private JComboBox sourceNode;
|
||||
private JComboBox targetNode;
|
||||
private JTextField tfName;
|
||||
private JTextField tfBandwidth;
|
||||
|
||||
|
||||
public AddVirtualEdge(final Graph graph, final JFrame frame) {
|
||||
|
||||
this.graph = graph;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(createInputPanel(), BorderLayout.CENTER);
|
||||
add(createButtonPanel(), BorderLayout.PAGE_END);
|
||||
// show dialog
|
||||
setTitle("Add Virtual Topology edge");
|
||||
setModal(true);
|
||||
setPreferredSize(new Dimension(400, 250));
|
||||
setResizable(false);
|
||||
pack();
|
||||
setLocationRelativeTo(frame); // must be called between pack and setVisible to work properly
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private JPanel createInputPanel() {
|
||||
|
||||
Component rigid = Box.createRigidArea(new Dimension(10, 0));
|
||||
|
||||
JPanel inputPanelWrapper = new JPanel();
|
||||
inputPanelWrapper.setLayout(new BoxLayout(inputPanelWrapper, BoxLayout.PAGE_AXIS));
|
||||
|
||||
JPanel inputPanel = new JPanel();
|
||||
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
JPanel textAreaPanel = new JPanel();
|
||||
textAreaPanel.setLayout(new BoxLayout(textAreaPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
JPanel textAreaPanel2 = new JPanel();
|
||||
textAreaPanel2.setLayout(new BoxLayout(textAreaPanel2, BoxLayout.LINE_AXIS));
|
||||
|
||||
ComboBoxModel sourceNodeModel = new DefaultComboBoxModel(graph.getAdjacencyList().keySet().toArray());
|
||||
|
||||
sourceNodeModel.setSelectedItem(null);
|
||||
|
||||
sourceNode = new JComboBox(sourceNodeModel);
|
||||
targetNode = new JComboBox();
|
||||
sourceNode.setMaximumSize(sourceNode.getPreferredSize());
|
||||
sourceNode.setMinimumSize(new Dimension(150, sourceNode.getPreferredSize().height));
|
||||
sourceNode.setPreferredSize(new Dimension(150, sourceNode.getPreferredSize().height));
|
||||
targetNode.setMaximumSize(targetNode.getPreferredSize());
|
||||
targetNode.setMinimumSize(new Dimension(150, targetNode.getPreferredSize().height));
|
||||
targetNode.setPreferredSize(new Dimension(150, targetNode.getPreferredSize().height));
|
||||
|
||||
NodeCellRenderer renderer = new NodeCellRenderer();
|
||||
|
||||
sourceNode.setRenderer(renderer);
|
||||
targetNode.setRenderer(renderer);
|
||||
|
||||
sourceNode.addItemListener(new ItemListener() {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
// only display nodes which do not have already an edge
|
||||
|
||||
targetNode.removeAllItems();
|
||||
Node selectedNode = (Node) sourceNode.getSelectedItem();
|
||||
|
||||
if (selectedNode != null) {
|
||||
|
||||
List<Node> nodesToDisplay = new ArrayList<Node>();
|
||||
Set<Node> allNodes = graph.getAdjacencyList().keySet();
|
||||
|
||||
// get edged for selected node and throw out all target nodes where already an edge exists
|
||||
List<Edge> edgesForSelectedNode = graph.getAdjacencyList().get(selectedNode);
|
||||
Set<Node> nodesInEdges = new HashSet<Node>();
|
||||
for (Edge edge : edgesForSelectedNode) {
|
||||
nodesInEdges.add(edge.getNode());
|
||||
}
|
||||
|
||||
for (Node node : allNodes) {
|
||||
if (!node.equals(selectedNode) && !nodesInEdges.contains(node)) {
|
||||
nodesToDisplay.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
ComboBoxModel targetNodeModel = new DefaultComboBoxModel(nodesToDisplay.toArray());
|
||||
targetNode.setModel(targetNodeModel);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
inputPanel.add(sourceNode);
|
||||
// inputPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
inputPanel.add(new Label(" ¡ª"));
|
||||
inputPanel.add(targetNode);
|
||||
inputPanel.add(Box.createHorizontalGlue());
|
||||
inputPanelWrapper.add(inputPanel);
|
||||
|
||||
textAreaPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
textAreaPanel.add(new JLabel("Edge Name: "));
|
||||
tfName = new JTextField();
|
||||
tfName.setMaximumSize(tfName.getPreferredSize());
|
||||
tfName.setMinimumSize(new Dimension(180, tfName.getPreferredSize().height));
|
||||
tfName.setPreferredSize(new Dimension(180, tfName.getPreferredSize().height));
|
||||
textAreaPanel.add(tfName);
|
||||
textAreaPanel.add(Box.createHorizontalGlue());
|
||||
inputPanelWrapper.add(textAreaPanel);
|
||||
inputPanelWrapper.add(Box.createVerticalGlue());
|
||||
|
||||
textAreaPanel2.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
textAreaPanel2.add(new JLabel("Bandwidth: "));
|
||||
tfBandwidth = new JTextField();
|
||||
tfBandwidth.setMaximumSize(tfBandwidth.getPreferredSize());
|
||||
tfBandwidth.setMinimumSize(new Dimension(180, tfBandwidth.getPreferredSize().height));
|
||||
tfBandwidth.setPreferredSize(new Dimension(180, tfBandwidth.getPreferredSize().height));
|
||||
textAreaPanel2.add(tfBandwidth);
|
||||
textAreaPanel2.add(Box.createHorizontalGlue());
|
||||
inputPanelWrapper.add(textAreaPanel2);
|
||||
inputPanelWrapper.add(Box.createVerticalGlue());
|
||||
|
||||
inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
return inputPanelWrapper;
|
||||
}
|
||||
|
||||
private JPanel createButtonPanel() {
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
JButton okBtn = new JButton("Ok");
|
||||
JButton cancelBtn = new JButton("Cancel");
|
||||
|
||||
cancelBtn.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
okBtn.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
String name = "default";
|
||||
long bandwidth = 0;
|
||||
boolean catchedError = false;
|
||||
|
||||
if (tfName.getText() == null || tfName.getText().isEmpty()) {
|
||||
catchedError = true;
|
||||
prompt("Please type Edge Name", "Error");
|
||||
}else {
|
||||
name = (String)tfName.getText();
|
||||
}
|
||||
|
||||
if (tfBandwidth.getText() == null || tfBandwidth.getText().isEmpty()) {
|
||||
catchedError = true;
|
||||
prompt("Please type Bandwidth", "Error");
|
||||
}else {
|
||||
try {
|
||||
bandwidth = Long.valueOf(tfBandwidth.getText());
|
||||
} catch (NumberFormatException e1) {
|
||||
catchedError = true;
|
||||
prompt("Bandwidth should be long type", "Error");
|
||||
}
|
||||
}
|
||||
|
||||
if (!catchedError) {
|
||||
if (sourceNode.getSelectedItem() == null || targetNode.getSelectedItem() == null) {
|
||||
prompt("Please select node", "Error");
|
||||
} else {
|
||||
|
||||
Node source = (Node) sourceNode.getSelectedItem();
|
||||
Node target = (Node) targetNode.getSelectedItem();
|
||||
|
||||
Edge edge = new Edge(target, name, bandwidth);
|
||||
graph.addEdge(source, edge);
|
||||
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
buttonPanel.add(Box.createHorizontalGlue());
|
||||
buttonPanel.add(okBtn);
|
||||
buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
buttonPanel.add(cancelBtn);
|
||||
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private void prompt(String msg, String type){
|
||||
JOptionPane.showMessageDialog(AddVirtualEdge.this, msg, type, JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
}
|
||||
198
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddVirtualNode.java
Normal file
198
src/org/cloudbus/cloudsim/sdn/graph/dialog/AddVirtualNode.java
Normal file
@@ -0,0 +1,198 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.dialog;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpringLayout;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Graph;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.SpringUtilities;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.VmNode;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Node;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class AddVirtualNode extends JDialog {
|
||||
private static final long serialVersionUID = -5116677861770319577L;
|
||||
|
||||
private final Graph graph;
|
||||
|
||||
private JTextField tfName;
|
||||
private JComboBox cType;
|
||||
private JTextField tfSize;
|
||||
private JTextField tfPes;
|
||||
private JTextField tfMips;
|
||||
private JTextField tfRam;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param frame the parent frame
|
||||
*/
|
||||
public AddVirtualNode(final Graph graph, final JFrame frame) {
|
||||
this.graph = graph;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(createInputPanelArea(), BorderLayout.CENTER);
|
||||
add(createButtonPanel(), BorderLayout.PAGE_END);
|
||||
// show dialog
|
||||
setTitle("Add Virtual Node");
|
||||
setModal(true);
|
||||
setPreferredSize(new Dimension(350, 400));
|
||||
setResizable(false);
|
||||
pack();
|
||||
setLocationRelativeTo(frame);
|
||||
setVisible(true);
|
||||
|
||||
}
|
||||
|
||||
private JPanel createButtonPanel() {
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
|
||||
|
||||
JButton okBtn = new JButton("Ok");
|
||||
JButton cancelBtn = new JButton("Cancel");
|
||||
|
||||
cancelBtn.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
okBtn.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
boolean catchedError = false;
|
||||
if (tfName.getText() == null || tfName.getText().length() < 1) {
|
||||
prompt("Please type VM name", "Error");
|
||||
} else if (cType.getSelectedIndex() < 0) {
|
||||
prompt("Please select VM type", "Error");
|
||||
} else if (tfSize.getText() == null || tfSize.getText().length() < 1) {
|
||||
prompt("Please type VM size", "Error");
|
||||
} else if (tfPes.getText() == null || tfPes.getText().length() < 1) {
|
||||
prompt("Please type pes", "Error");
|
||||
} else if (tfMips.getText() == null || tfMips.getText().length() < 1) {
|
||||
prompt("Please type VM mips", "Error");
|
||||
} else if (tfRam.getText() == null || tfRam.getText().length() < 1) {
|
||||
prompt("Please type VM RAM", "Error");
|
||||
} else {
|
||||
long t1 = 0;
|
||||
int t2 = 0;
|
||||
long t3 = 0;
|
||||
int t4 = 0;
|
||||
try {
|
||||
t1 = Long.parseLong(tfSize.getText());
|
||||
t2 = Integer.parseInt(tfPes.getText());
|
||||
t3 = Long.parseLong(tfMips.getText());
|
||||
t4 = Integer.parseInt(tfRam.getText());
|
||||
} catch (NumberFormatException e1) {
|
||||
catchedError = true;
|
||||
prompt("Input should be numerical character", "Error");
|
||||
}
|
||||
if(!catchedError){
|
||||
Node node = new VmNode(tfName.getText().toString(), (String)cType.getSelectedItem(),
|
||||
t1, t2, t3, t4);
|
||||
graph.addNode(node);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
buttonPanel.add(Box.createHorizontalGlue());
|
||||
buttonPanel.add(okBtn);
|
||||
buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
buttonPanel.add(cancelBtn);
|
||||
buttonPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private JPanel createInputPanelArea() {
|
||||
String[] vmType = {"vm"};
|
||||
|
||||
//Create and populate the panel.
|
||||
JPanel springPanel = new JPanel(new SpringLayout());
|
||||
springPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
JLabel lName = new JLabel("Name: ");
|
||||
springPanel.add(lName);
|
||||
tfName = new JTextField();
|
||||
lName.setLabelFor(tfName);
|
||||
springPanel.add(tfName);
|
||||
|
||||
JLabel lType = new JLabel("Type: ", JLabel.TRAILING);
|
||||
springPanel.add(lType);
|
||||
cType = new JComboBox(vmType);
|
||||
lType.setLabelFor(cType);
|
||||
cType.setSelectedIndex(-1);
|
||||
cType.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
|
||||
}
|
||||
});
|
||||
springPanel.add(cType);
|
||||
|
||||
JLabel lSize = new JLabel("Size: ");
|
||||
springPanel.add(lSize);
|
||||
tfSize = new JTextField();
|
||||
lSize.setLabelFor(tfSize);
|
||||
springPanel.add(tfSize);
|
||||
|
||||
JLabel lPes = new JLabel("Pes: ");
|
||||
springPanel.add(lPes);
|
||||
tfPes = new JTextField();
|
||||
lPes.setLabelFor(tfPes);
|
||||
springPanel.add(tfPes);
|
||||
|
||||
JLabel lMips = new JLabel("Mips: ");
|
||||
springPanel.add(lMips);
|
||||
tfMips = new JTextField();
|
||||
lMips.setLabelFor(tfMips);
|
||||
springPanel.add(tfMips);
|
||||
|
||||
JLabel lRam = new JLabel("Ram: ");
|
||||
springPanel.add(lRam);
|
||||
tfRam = new JTextField();
|
||||
lRam.setLabelFor(tfRam);
|
||||
springPanel.add(tfRam);
|
||||
|
||||
//Lay out the panel.
|
||||
SpringUtilities.makeCompactGrid(springPanel,
|
||||
6, 2, //rows, columns
|
||||
6, 6, //initX, initY
|
||||
6, 6); //xPad, yPad
|
||||
return springPanel;
|
||||
}
|
||||
|
||||
public static void setUIFont (javax.swing.plaf.FontUIResource f){
|
||||
java.util.Enumeration keys = UIManager.getDefaults().keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
Object key = keys.nextElement();
|
||||
Object value = UIManager.get (key);
|
||||
if (value != null && value instanceof javax.swing.plaf.FontUIResource)
|
||||
UIManager.put (key, f);
|
||||
}
|
||||
}
|
||||
|
||||
private void prompt(String msg, String type){
|
||||
JOptionPane.showMessageDialog(AddVirtualNode.this, msg, type, JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
174
src/org/cloudbus/cloudsim/sdn/graph/dialog/SDNRun.java
Normal file
174
src/org/cloudbus/cloudsim/sdn/graph/dialog/SDNRun.java
Normal file
@@ -0,0 +1,174 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.dialog;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.Timer;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.example.GraphicSDNExample;
|
||||
|
||||
public class SDNRun extends JDialog {
|
||||
private static final long serialVersionUID = -8313194085507492462L;
|
||||
|
||||
private String physicalTopologyFile = ""; //physical
|
||||
private String deploymentFile = ""; //virtual
|
||||
private String workloads_background = ""; //workload
|
||||
private String workloads = ""; //workload
|
||||
|
||||
private JPanel panel;
|
||||
private JScrollPane pane;
|
||||
private JTextArea outputArea;
|
||||
private JLabel imageLabel;
|
||||
private JLabel msgLabel;
|
||||
private JComponent space;
|
||||
private int counter = 0;
|
||||
private Timer timer;
|
||||
|
||||
private GraphicSDNExample sdn;
|
||||
|
||||
public SDNRun(final String phy, final String vir, final String wlbk, final String wl, final JFrame frame){
|
||||
physicalTopologyFile = phy;
|
||||
deploymentFile = vir;
|
||||
workloads_background = wlbk;
|
||||
workloads = wl;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
panel = new JPanel();
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
|
||||
|
||||
initUI();
|
||||
run();
|
||||
add(panel, BorderLayout.CENTER);
|
||||
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE );
|
||||
setTitle("Run Simulation");
|
||||
setModal(true);
|
||||
setPreferredSize(new Dimension(900, 600));
|
||||
setResizable(false);
|
||||
pack();
|
||||
setLocationRelativeTo(frame); // must be called between pack and setVisible to work properly
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void initUI(){
|
||||
ImageIcon ii = new ImageIcon(this.getClass().getResource("/src/1.gif"));
|
||||
imageLabel = new JLabel(ii);
|
||||
imageLabel.setAlignmentX(CENTER_ALIGNMENT);
|
||||
msgLabel = new JLabel("Simulation is executing");
|
||||
msgLabel.setAlignmentX(CENTER_ALIGNMENT);
|
||||
space = (JComponent)Box.createRigidArea(new Dimension(0, 200));
|
||||
panel.add(space);
|
||||
panel.add(msgLabel);
|
||||
panel.add(imageLabel);
|
||||
|
||||
pane = new JScrollPane();
|
||||
outputArea = new JTextArea();
|
||||
|
||||
outputArea.setLineWrap(true);
|
||||
outputArea.setWrapStyleWord(true);
|
||||
outputArea.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||
outputArea.setEditable(false);
|
||||
//outputArea.setText("wo ai bei jin tian an men");
|
||||
//readFile(physicalTopologyFile, outputArea);
|
||||
|
||||
pane.getViewport().add(outputArea);
|
||||
panel.add(pane);
|
||||
pane.setVisible(false);
|
||||
}
|
||||
|
||||
private void run(){
|
||||
|
||||
sdn = new GraphicSDNExample(physicalTopologyFile, deploymentFile, workloads_background, workloads, outputArea);
|
||||
|
||||
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
|
||||
protected Boolean doInBackground() throws Exception {
|
||||
boolean success = false;
|
||||
success = sdn.simulate();
|
||||
if(success){
|
||||
sdn.output();
|
||||
append("<<<<<<<<<< Simulation completed >>>>>>>>>");
|
||||
}else{
|
||||
append("<<<<<<<<<< Running Error >>>>>>>>>>");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
protected void done() {
|
||||
boolean status;
|
||||
try {
|
||||
status = get();
|
||||
panel.remove(space);
|
||||
panel.remove(imageLabel);
|
||||
panel.remove(msgLabel);
|
||||
pane.setVisible(true);
|
||||
panel.revalidate();
|
||||
panel.repaint();
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
private void append(String content){
|
||||
outputArea.append(content+"\n");
|
||||
}
|
||||
|
||||
/** below only used for testing reading file to textarea */
|
||||
private void startTest(){
|
||||
ActionListener updateProBar = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
if(counter>=100){
|
||||
timer.stop();
|
||||
panel.remove(space);
|
||||
panel.remove(imageLabel);
|
||||
panel.remove(msgLabel);
|
||||
pane.setVisible(true);
|
||||
panel.revalidate();
|
||||
panel.repaint();
|
||||
|
||||
}else{
|
||||
counter +=2;
|
||||
}
|
||||
}
|
||||
};
|
||||
timer = new Timer(50, updateProBar);
|
||||
timer.start();
|
||||
}
|
||||
private void readFile(String path, JTextArea area) {
|
||||
|
||||
try{
|
||||
FileReader reader = new FileReader(path);
|
||||
BufferedReader br = new BufferedReader(reader);
|
||||
area.read( br, null );
|
||||
br.close();
|
||||
area.requestFocus();
|
||||
}catch(Exception e2) {
|
||||
System.out.println(e2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
632
src/org/cloudbus/cloudsim/sdn/graph/example/GraphicSDN.java
Normal file
632
src/org/cloudbus/cloudsim/sdn/graph/example/GraphicSDN.java
Normal file
@@ -0,0 +1,632 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.example;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButtonMenuItem;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Bridge;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Edge;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Graph;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.GraphView;
|
||||
import org.cloudbus.cloudsim.sdn.graph.core.Node;
|
||||
import org.cloudbus.cloudsim.sdn.graph.dialog.*;
|
||||
|
||||
public class GraphicSDN extends JFrame {
|
||||
private static final long serialVersionUID = -2238414769964738933L;
|
||||
|
||||
private JPanel contentPane;
|
||||
|
||||
/** Import file names */
|
||||
private String physicalTopologyFile = ""; //physical
|
||||
private String deploymentFile = ""; //virtual
|
||||
private String workloads_background = ""; //workload
|
||||
private String workloads = ""; //workload
|
||||
|
||||
private JPanel panel;
|
||||
private JPanel graph;
|
||||
|
||||
private Graph physicalGraph;
|
||||
private Graph virtualGraph;
|
||||
private GraphView physicalCanvas;
|
||||
private GraphView virtualCanvas;
|
||||
|
||||
private JButton btnRun;
|
||||
|
||||
private String mode; //'m':manual; 'i':import
|
||||
|
||||
public GraphicSDN() {
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setPreferredSize(new Dimension(1280, 800));
|
||||
setLocationRelativeTo(null);
|
||||
//setResizable(false);
|
||||
|
||||
setTitle("CloudSim SDN");
|
||||
contentPane = new JPanel();
|
||||
setContentPane(contentPane);
|
||||
contentPane.setLayout(new BorderLayout());
|
||||
|
||||
initUI();
|
||||
initGraph();
|
||||
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
public final void initUI() {
|
||||
setUIFont (new javax.swing.plaf.FontUIResource("Serif",Font.BOLD,18));
|
||||
|
||||
panel = new JPanel();
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
|
||||
graph = new JPanel(new java.awt.GridLayout(1, 2));
|
||||
|
||||
initBar();
|
||||
doPosition();
|
||||
}
|
||||
|
||||
/** position window */
|
||||
private void doPosition() {
|
||||
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int height = screenSize.height;
|
||||
int width = screenSize.width;
|
||||
|
||||
int x = (width / 2 - 1280 / 2);
|
||||
int y = (height / 2 - 800 / 2);
|
||||
// One could use the dimension of the frame. But when doing so, one have to call this method !BETWEEN! pack and
|
||||
// setVisible. Otherwise the calculation will go wrong.
|
||||
|
||||
this.setLocation(x, y);
|
||||
}
|
||||
|
||||
/** Initialize project menu and tool bar */
|
||||
private final void initBar() {
|
||||
//---------- Start ActionListener ----------
|
||||
ActionListener readPhyTopoListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
physicalTopologyFile = importFile("josn");
|
||||
checkImportStatus();
|
||||
}
|
||||
};
|
||||
ActionListener readVirTopoListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
deploymentFile = importFile("json");
|
||||
checkImportStatus();
|
||||
}
|
||||
};
|
||||
ActionListener readWorkloadBkListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
workloads_background = importFile("cvs");
|
||||
checkImportStatus();
|
||||
}
|
||||
};
|
||||
ActionListener readWorkloadListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
workloads = importFile("cvs");
|
||||
checkImportStatus();
|
||||
}
|
||||
};
|
||||
ActionListener addPhysicalNodeListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
openAddPhysicalNodeDialog();
|
||||
}
|
||||
};
|
||||
ActionListener addVirtualNodeListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
openAddVirtualNodeDialog();
|
||||
}
|
||||
};
|
||||
ActionListener addPhysicalEdgeListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
openAddPhysicalEdgeDialog();
|
||||
}
|
||||
};
|
||||
ActionListener addVirtualEdgeListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
openAddVirtualEdgeDialog();
|
||||
}
|
||||
};
|
||||
ActionListener importPhyTopoListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String fileName = importFile("josn");
|
||||
Graph phyGraph= Bridge.jsonToGraph(fileName, 0);
|
||||
/* System.out.println(phyGraph.getAdjacencyList().size());
|
||||
for (Entry<Node, List<Edge>> entry : phyGraph.getAdjacencyList().entrySet()) {
|
||||
System.out.println(entry.getKey().getName()+entry.getKey().getType());
|
||||
}*/
|
||||
physicalCanvas.setGraph(phyGraph);
|
||||
}
|
||||
};
|
||||
ActionListener importVirTopoListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String fileName = importFile("josn");
|
||||
Graph virGraph= Bridge.jsonToGraph(fileName, 1);
|
||||
virtualCanvas.setGraph(virGraph);
|
||||
}
|
||||
};
|
||||
ActionListener savePhyTopoListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
saveFile("json", physicalGraph);
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
ActionListener saveVirTopoListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
saveFile("json", virtualGraph);
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//---------- End ActionListener ----------
|
||||
|
||||
//---------- Start Creating project tool bar ----------
|
||||
JToolBar toolbar = new JToolBar();
|
||||
|
||||
ImageIcon iHost = new ImageIcon(
|
||||
getClass().getResource("/src/dc.png"));
|
||||
ImageIcon iHline = new ImageIcon(
|
||||
getClass().getResource("/src/hline2.png"));
|
||||
ImageIcon iHOpen = new ImageIcon(
|
||||
getClass().getResource("/src/openPhyTop.png"));
|
||||
ImageIcon iHSave = new ImageIcon(
|
||||
getClass().getResource("/src/savePhyTop.png"));
|
||||
ImageIcon iVM = new ImageIcon(
|
||||
getClass().getResource("/src/vm2.png"));
|
||||
ImageIcon iVline = new ImageIcon(
|
||||
getClass().getResource("/src/vline2.png"));
|
||||
ImageIcon iVOpen = new ImageIcon(
|
||||
getClass().getResource("/src/openVirTop.png"));
|
||||
ImageIcon iVSave = new ImageIcon(
|
||||
getClass().getResource("/src/saveVirTop.png"));
|
||||
ImageIcon iPhy = new ImageIcon(
|
||||
getClass().getResource("/src/upload1.png"));
|
||||
ImageIcon iVir = new ImageIcon(
|
||||
getClass().getResource("/src/upload2.png"));
|
||||
ImageIcon iWl1 = new ImageIcon(
|
||||
getClass().getResource("/src/upload3.png"));
|
||||
ImageIcon iWl2 = new ImageIcon(
|
||||
getClass().getResource("/src/upload4.png"));
|
||||
ImageIcon run = new ImageIcon(
|
||||
getClass().getResource("/src/play.png"));
|
||||
ImageIcon exit = new ImageIcon(
|
||||
getClass().getResource("/src/exit.png"));
|
||||
|
||||
final JButton btnHost = new JButton(iHost);
|
||||
btnHost.setToolTipText("Add Host Node");
|
||||
final JButton btnVm = new JButton(iVM);
|
||||
btnVm.setToolTipText("Add virtual Machine");
|
||||
final JButton btnHedge = new JButton(iHline);
|
||||
btnHedge.setToolTipText("Add Host Edge");
|
||||
final JButton btnVedge = new JButton(iVline);
|
||||
btnVedge.setToolTipText("Add VM Edge");
|
||||
final JButton btnHopen = new JButton(iHOpen);
|
||||
btnHopen.setToolTipText("Open Physical Topology");
|
||||
final JButton btnVopen = new JButton(iVOpen);
|
||||
btnVopen.setToolTipText("Open virtual Topology");
|
||||
final JButton btnHsave = new JButton(iHSave);
|
||||
btnHsave.setToolTipText("Save Physical Topology");
|
||||
final JButton btnVsave = new JButton(iVSave);
|
||||
btnVsave.setToolTipText("Save virtual Topology");
|
||||
|
||||
final JButton btnPhy = new JButton(iPhy);
|
||||
btnPhy.setToolTipText("Import topology network");
|
||||
final JButton btnVir = new JButton(iVir);
|
||||
btnVir.setToolTipText("Import virtual network");
|
||||
final JButton btnWl1 = new JButton(iWl1);
|
||||
btnWl1.setToolTipText("Import workload background");
|
||||
final JButton btnWl2 = new JButton(iWl2);
|
||||
btnWl2.setToolTipText("Import workload");
|
||||
|
||||
btnRun = new JButton(run);
|
||||
btnRun.setToolTipText("Start simulation");
|
||||
JButton btnExit = new JButton(exit);
|
||||
btnExit.setToolTipText("Exit CloudSim");
|
||||
toolbar.setAlignmentX(0);
|
||||
|
||||
btnHost.addActionListener(addPhysicalNodeListener);
|
||||
btnHedge.addActionListener(addPhysicalEdgeListener);
|
||||
btnHopen.addActionListener(importPhyTopoListener);
|
||||
btnHsave.addActionListener(savePhyTopoListener);
|
||||
btnVm.addActionListener(addVirtualNodeListener);
|
||||
btnVedge.addActionListener(addVirtualEdgeListener);
|
||||
btnVopen.addActionListener(importVirTopoListener);
|
||||
btnVsave.addActionListener(saveVirTopoListener);
|
||||
|
||||
btnPhy.addActionListener(readPhyTopoListener);
|
||||
btnVir.addActionListener(readVirTopoListener);
|
||||
btnWl1.addActionListener(readWorkloadBkListener);
|
||||
btnWl2.addActionListener(readWorkloadListener);
|
||||
btnRun.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
if("i"==mode){
|
||||
if(physicalTopologyFile==null || physicalTopologyFile.isEmpty()){
|
||||
JOptionPane.showMessageDialog(panel, "Please select physicalTopologyFile", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
if(deploymentFile==null || deploymentFile.isEmpty()){
|
||||
JOptionPane.showMessageDialog(panel, "Please select deploymentFile", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
if(workloads_background==null || workloads_background.isEmpty()){
|
||||
JOptionPane.showMessageDialog(panel, "Please select workloads_background", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
if(workloads==null || workloads.isEmpty()){
|
||||
JOptionPane.showMessageDialog(panel, "Please select workloads", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
// run simulation
|
||||
SDNRun run = new SDNRun(physicalTopologyFile, deploymentFile,
|
||||
workloads_background, workloads, GraphicSDN.this);
|
||||
|
||||
|
||||
}else if("m"==mode){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
btnExit.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
toolbar.add(btnHost);
|
||||
toolbar.add(btnHedge);
|
||||
toolbar.add(btnHopen);
|
||||
toolbar.add(btnHsave);
|
||||
toolbar.addSeparator();
|
||||
toolbar.add(btnVm);
|
||||
toolbar.add(btnVedge);
|
||||
toolbar.add(btnVopen);
|
||||
toolbar.add(btnVsave);
|
||||
|
||||
toolbar.add(btnPhy);
|
||||
toolbar.add(btnVir);
|
||||
toolbar.add(btnWl1);
|
||||
toolbar.add(btnWl2);
|
||||
toolbar.addSeparator();
|
||||
|
||||
toolbar.add(btnRun);
|
||||
toolbar.add(btnExit);
|
||||
|
||||
panel.add(toolbar);
|
||||
|
||||
contentPane.add(panel, BorderLayout.NORTH);
|
||||
//---------- End Creating project tool bar ----------
|
||||
|
||||
|
||||
|
||||
//---------- Start Creating project menu bar ----------
|
||||
//1-1
|
||||
JMenuBar menubar = new JMenuBar();
|
||||
//ImageIcon iconNew = new ImageIcon(getClass().getResource("/src/new.png"));
|
||||
|
||||
//2-1
|
||||
JMenu graph = new JMenu("Graph");
|
||||
graph.setMnemonic(KeyEvent.VK_G);
|
||||
|
||||
//Graph by importing json and cvs files
|
||||
final JMenuItem MiPhy = new JMenuItem("Physical Topology");
|
||||
final JMenuItem MiVir = new JMenuItem("Virtual Topology");
|
||||
final JMenuItem MiWl1 = new JMenuItem("Workload Background");
|
||||
final JMenuItem MiWl2 = new JMenuItem("Workload");
|
||||
//Graph drawing elements
|
||||
final JMenu MuPhy = new JMenu("Physical");
|
||||
JMenuItem MiPhyNode = new JMenuItem("Add Node");
|
||||
JMenuItem MiPhyEdge = new JMenuItem("Add Edge");
|
||||
JMenuItem MiPhyOpen = new JMenuItem("Import Physical Topology");
|
||||
JMenuItem MiPhySave = new JMenuItem("Save Physical Topology");
|
||||
MuPhy.add(MiPhyNode);
|
||||
MuPhy.add(MiPhyEdge);
|
||||
MuPhy.add(MiPhyOpen);
|
||||
MuPhy.add(MiPhySave);
|
||||
final JMenu MuVir = new JMenu("Virtual");
|
||||
JMenuItem MiVirNode = new JMenuItem("Add Node");
|
||||
JMenuItem MiVirEdge = new JMenuItem("Add Edge");
|
||||
JMenuItem MiVirOpen = new JMenuItem("Import Virtual Topology");
|
||||
JMenuItem MiVirSave = new JMenuItem("Save Virtual Topology");
|
||||
MuVir.add(MiVirNode);
|
||||
MuVir.add(MiVirEdge);
|
||||
MuVir.add(MiVirOpen);
|
||||
MuVir.add(MiVirSave);
|
||||
|
||||
|
||||
MiPhy.addActionListener(readPhyTopoListener);
|
||||
MiVir.addActionListener(readVirTopoListener);
|
||||
MiWl1.addActionListener(readWorkloadBkListener);
|
||||
MiWl2.addActionListener(readWorkloadListener);
|
||||
|
||||
MiPhyNode.addActionListener(addPhysicalNodeListener);
|
||||
MiPhyEdge.addActionListener(addPhysicalEdgeListener);
|
||||
MiPhyOpen.addActionListener(importPhyTopoListener);
|
||||
MiPhySave.addActionListener(savePhyTopoListener);
|
||||
MiVirNode.addActionListener(addVirtualNodeListener);
|
||||
MiVirEdge.addActionListener(addVirtualEdgeListener);
|
||||
MiVirOpen.addActionListener(importVirTopoListener);
|
||||
MiVirSave.addActionListener(saveVirTopoListener);
|
||||
|
||||
graph.add(MuPhy);
|
||||
graph.add(MuVir);
|
||||
graph.add(MiPhy);
|
||||
graph.add(MiVir);
|
||||
graph.add(MiWl1);
|
||||
graph.add(MiWl2);
|
||||
|
||||
//2-2
|
||||
JMenu view = new JMenu("View");
|
||||
view.setMnemonic(KeyEvent.VK_F);
|
||||
|
||||
//switch mode between manual mode (to create graph by hand) and import mode (to create graph from file)
|
||||
ActionListener actionSwitcher = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
String cmd = e.getActionCommand();
|
||||
if("Canvas" == cmd){
|
||||
btnHost.setVisible(true);
|
||||
btnHedge.setVisible(true);
|
||||
btnHopen.setVisible(true);
|
||||
btnHsave.setVisible(true);
|
||||
btnVm.setVisible(true);
|
||||
btnVedge.setVisible(true);
|
||||
btnVopen.setVisible(true);
|
||||
btnVsave.setVisible(true);
|
||||
btnPhy.setVisible(false);
|
||||
btnVir.setVisible(false);
|
||||
btnWl1.setVisible(false);
|
||||
btnWl2.setVisible(false);
|
||||
|
||||
MiPhy.setVisible(false);
|
||||
MiVir.setVisible(false);
|
||||
MiWl1.setVisible(false);
|
||||
MiWl2.setVisible(false);
|
||||
MuPhy.setVisible(true);
|
||||
MuVir.setVisible(true);
|
||||
|
||||
btnRun.setVisible(false);
|
||||
btnRun.setEnabled(false);
|
||||
|
||||
mode = "m";
|
||||
|
||||
}else if("Execution" == cmd){
|
||||
btnHost.setVisible(false);
|
||||
btnHedge.setVisible(false);
|
||||
btnHopen.setVisible(false);
|
||||
btnHsave.setVisible(false);
|
||||
btnVm.setVisible(false);
|
||||
btnVedge.setVisible(false);
|
||||
btnVopen.setVisible(false);
|
||||
btnVsave.setVisible(false);
|
||||
btnPhy.setVisible(true);
|
||||
btnVir.setVisible(true);
|
||||
btnWl1.setVisible(true);
|
||||
btnWl2.setVisible(true);
|
||||
|
||||
MiPhy.setVisible(true);
|
||||
MiVir.setVisible(true);
|
||||
MiWl1.setVisible(true);
|
||||
MiWl2.setVisible(true);
|
||||
MuPhy.setVisible(false);
|
||||
MuVir.setVisible(false);
|
||||
|
||||
btnRun.setVisible(true);
|
||||
btnRun.setEnabled(false);
|
||||
|
||||
mode = "i";
|
||||
}
|
||||
//System.out.println(e.getActionCommand());
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
JRadioButtonMenuItem manualMode = new JRadioButtonMenuItem("Canvas");
|
||||
manualMode.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, ActionEvent.CTRL_MASK));
|
||||
manualMode.addActionListener(actionSwitcher);
|
||||
JRadioButtonMenuItem importMode = new JRadioButtonMenuItem("Execution");
|
||||
importMode.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, ActionEvent.CTRL_MASK));
|
||||
importMode.addActionListener(actionSwitcher);
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
group.add(manualMode);
|
||||
group.add(importMode);
|
||||
|
||||
JMenuItem fileExit = new JMenuItem("Exit");
|
||||
fileExit.setMnemonic(KeyEvent.VK_C);
|
||||
fileExit.setToolTipText("Exit CloudSim");
|
||||
fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
|
||||
ActionEvent.CTRL_MASK));
|
||||
|
||||
fileExit.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
view.add(manualMode);
|
||||
view.add(importMode);
|
||||
view.addSeparator();
|
||||
view.add(fileExit);
|
||||
|
||||
|
||||
//3-1
|
||||
menubar.add(view);
|
||||
menubar.add(graph);
|
||||
|
||||
//4-1
|
||||
setJMenuBar(menubar);
|
||||
//----- End Creating project menu bar -----
|
||||
|
||||
|
||||
|
||||
//----- Start Initialize menu and tool bar -----
|
||||
manualMode.setSelected(true);
|
||||
mode = "m";
|
||||
|
||||
btnHost.setVisible(true);
|
||||
btnHedge.setVisible(true);
|
||||
btnHopen.setVisible(true);
|
||||
btnHsave.setVisible(true);
|
||||
btnVm.setVisible(true);
|
||||
btnVedge.setVisible(true);
|
||||
btnVopen.setVisible(true);
|
||||
btnVsave.setVisible(true);
|
||||
btnPhy.setVisible(false);
|
||||
btnVir.setVisible(false);
|
||||
btnWl1.setVisible(false);
|
||||
btnWl2.setVisible(false);
|
||||
|
||||
MiPhy.setVisible(false);
|
||||
MiVir.setVisible(false);
|
||||
MiWl1.setVisible(false);
|
||||
MiWl2.setVisible(false);
|
||||
MuPhy.setVisible(true);
|
||||
MuVir.setVisible(true);
|
||||
|
||||
btnRun.setVisible(false);
|
||||
btnRun.setEnabled(false);
|
||||
//----- End Initialize menu and tool bar -----
|
||||
|
||||
}
|
||||
|
||||
/** initialize Canvas */
|
||||
private void initGraph(){
|
||||
physicalGraph = new Graph();
|
||||
virtualGraph = new Graph();
|
||||
|
||||
physicalCanvas = new GraphView(physicalGraph);
|
||||
virtualCanvas = new GraphView(virtualGraph);
|
||||
|
||||
graph.add(physicalCanvas);
|
||||
graph.add(virtualCanvas);
|
||||
contentPane.add(graph, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
|
||||
/** dialog opening */
|
||||
private void openAddPhysicalNodeDialog(){
|
||||
AddPhysicalNode phyNode = new AddPhysicalNode(physicalGraph, GraphicSDN.this);
|
||||
physicalCanvas.repaint();
|
||||
}
|
||||
private void openAddPhysicalEdgeDialog(){
|
||||
AddPhysicalEdge phyEdge = new AddPhysicalEdge(physicalGraph, GraphicSDN.this);
|
||||
physicalCanvas.repaint();
|
||||
}
|
||||
private void openAddVirtualNodeDialog(){
|
||||
AddVirtualNode vmNode = new AddVirtualNode(virtualGraph, GraphicSDN.this);
|
||||
virtualCanvas.repaint();
|
||||
}
|
||||
private void openAddVirtualEdgeDialog(){
|
||||
AddVirtualEdge phyNode = new AddVirtualEdge(virtualGraph, GraphicSDN.this);
|
||||
virtualCanvas.repaint();
|
||||
}
|
||||
|
||||
/** common utility */
|
||||
private String importFile(String type){
|
||||
JFileChooser fileopen = new JFileChooser();
|
||||
FileFilter filter = new FileNameExtensionFilter(type.toUpperCase()+" Files", type);
|
||||
fileopen.addChoosableFileFilter(filter);
|
||||
|
||||
int ret = fileopen.showDialog(panel, "Import file");
|
||||
|
||||
if (ret == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fileopen.getSelectedFile();
|
||||
//System.out.println(file.getPath());
|
||||
return file.getPath();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/** save network topology */
|
||||
private void saveFile(String type, Graph graph) throws IOException{
|
||||
JFileChooser fileopen = new JFileChooser();
|
||||
FileFilter filter = new FileNameExtensionFilter(type.toUpperCase()+" Files", type);
|
||||
fileopen.addChoosableFileFilter(filter);
|
||||
|
||||
int ret = fileopen.showSaveDialog(panel);
|
||||
|
||||
if (ret == JFileChooser.APPROVE_OPTION) {
|
||||
String jsonText = graph.toJsonString();
|
||||
System.out.println(jsonText);
|
||||
String path = fileopen.getSelectedFile().toString();
|
||||
File file = new File(path);
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
out.write(jsonText.getBytes());
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void setUIFont(javax.swing.plaf.FontUIResource f){
|
||||
java.util.Enumeration keys = UIManager.getDefaults().keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
Object key = keys.nextElement();
|
||||
Object value = UIManager.get (key);
|
||||
if (value != null && value instanceof javax.swing.plaf.FontUIResource)
|
||||
UIManager.put (key, f);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkImportStatus(){
|
||||
if((physicalTopologyFile!=null && !physicalTopologyFile.isEmpty()) &&
|
||||
(deploymentFile!=null && !deploymentFile.isEmpty()) &&
|
||||
(workloads_background!=null && !workloads_background.isEmpty()) &&
|
||||
(workloads!=null && !workloads.isEmpty())){
|
||||
btnRun.setEnabled(true);
|
||||
}else{
|
||||
btnRun.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Application entry point */
|
||||
public static void main(String args[]) throws InterruptedException {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
GraphicSDN sdn = new GraphicSDN();
|
||||
sdn.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
package org.cloudbus.cloudsim.sdn.graph.example;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
import org.cloudbus.cloudsim.Cloudlet;
|
||||
import org.cloudbus.cloudsim.DatacenterCharacteristics;
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Storage;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.sdn.Activity;
|
||||
import org.cloudbus.cloudsim.sdn.Processing;
|
||||
import org.cloudbus.cloudsim.sdn.Request;
|
||||
import org.cloudbus.cloudsim.sdn.SDNDatacenter;
|
||||
import org.cloudbus.cloudsim.sdn.Transmission;
|
||||
import org.cloudbus.cloudsim.sdn.example.SDNBroker;
|
||||
import org.cloudbus.cloudsim.sdn.example.SimpleNetworkOperatingSystem;
|
||||
import org.cloudbus.cloudsim.sdn.example.VmAllocationPolicyCombinedLeastFullFirst;
|
||||
import org.cloudbus.cloudsim.sdn.example.Workload;
|
||||
import org.cloudbus.cloudsim.sdn.example.VmSchedulerSpaceSharedEnergy;
|
||||
|
||||
/** A simple example showing how to create a datacenter with one host and run one cloudlet on it */
|
||||
public class GraphicSDNExample {
|
||||
|
||||
private String physicalTopologyFile = "";
|
||||
private String deploymentFile = "";
|
||||
private String workloads_background = "";
|
||||
private String workloads = "";
|
||||
|
||||
private JTextArea outputArea;
|
||||
|
||||
private SDNBroker broker;
|
||||
|
||||
public GraphicSDNExample(String phy, String vir, String wlbk, String wl, JTextArea area){
|
||||
physicalTopologyFile = phy;
|
||||
deploymentFile = vir;
|
||||
workloads_background = wlbk;
|
||||
workloads = wl;
|
||||
outputArea = area;
|
||||
}
|
||||
|
||||
public boolean simulate() {
|
||||
|
||||
//append("Starting CloudSim SDN...");
|
||||
|
||||
try {
|
||||
// Initialize
|
||||
int num_user = 1; // number of cloud users
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
boolean trace_flag = false; // mean trace events
|
||||
CloudSim.init(num_user, calendar, trace_flag);
|
||||
|
||||
// Create a Datacenter
|
||||
SDNDatacenter datacenter = createSDNDatacenter("Datacenter_0", physicalTopologyFile);
|
||||
|
||||
// Broker
|
||||
broker = createBroker();
|
||||
int brokerId = broker.getId();
|
||||
|
||||
broker.submitDeployApplication(datacenter, deploymentFile);
|
||||
broker.submitRequests(workloads_background);
|
||||
broker.submitRequests(workloads);
|
||||
|
||||
// Sixth step: Starts the simulation
|
||||
CloudSim.startSimulation();
|
||||
CloudSim.stopSimulation();
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//append("====== RUNNING ERROR ======");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void output(){
|
||||
try {
|
||||
// Final step: Print hosts' total utilization.
|
||||
List<Host> hostList = nos.getHostList();
|
||||
|
||||
printEnergyConsumption(hostList);
|
||||
|
||||
//Final step: Print results when simulation is over
|
||||
List<Cloudlet> newList = broker.getCloudletReceivedList();
|
||||
printCloudletList(newList);
|
||||
|
||||
List<Workload> wls = broker.getWorkloads();
|
||||
printWorkloadList(wls);
|
||||
|
||||
append("CloudSim SDN finished!");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
append("====== OUTPUT ERROR ======");
|
||||
}
|
||||
}
|
||||
|
||||
private void printEnergyConsumption(List<Host> hostList) {
|
||||
double totalEnergyConsumption = 0;
|
||||
for(Host host:hostList) {
|
||||
double energy = ((VmSchedulerSpaceSharedEnergy) host.getVmScheduler()).getUtilizationEnergyConsumption();
|
||||
append("Host #"+host.getId()+": "+energy);
|
||||
totalEnergyConsumption+= energy;
|
||||
|
||||
printHostUtilizationHistory(((VmSchedulerSpaceSharedEnergy) host.getVmScheduler()).getUtilizationHisotry());
|
||||
|
||||
}
|
||||
append("Total energy consumed: "+totalEnergyConsumption);
|
||||
|
||||
}
|
||||
|
||||
private void printHostUtilizationHistory(
|
||||
List<org.cloudbus.cloudsim.sdn.example.VmSchedulerSpaceSharedEnergy.HistoryEntry> utilizationHisotry) {
|
||||
for(org.cloudbus.cloudsim.sdn.example.VmSchedulerSpaceSharedEnergy.HistoryEntry h:utilizationHisotry) {
|
||||
append(h.startTime+", "+h.usedMips);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the datacenter.
|
||||
*
|
||||
* @param name the name
|
||||
*
|
||||
* @return the datacenter
|
||||
*/
|
||||
private SimpleNetworkOperatingSystem nos;
|
||||
private SDNDatacenter createSDNDatacenter(String name, String physicalTopology) {
|
||||
|
||||
// In order to get Host information, pre-create NOS.
|
||||
|
||||
nos = new SimpleNetworkOperatingSystem(physicalTopology);
|
||||
List<Host> hostList = nos.getHostList();
|
||||
|
||||
String arch = "x86"; // system architecture
|
||||
String os = "Linux"; // operating system
|
||||
String vmm = "Xen";
|
||||
|
||||
double time_zone = 10.0; // time zone this resource located
|
||||
double cost = 3.0; // the cost of using processing in this resource
|
||||
double costPerMem = 0.05; // the cost of using memory in this resource
|
||||
double costPerStorage = 0.001; // the cost of using storage in this
|
||||
// resource
|
||||
double costPerBw = 0.0; // the cost of using bw in this resource
|
||||
LinkedList<Storage> storageList = new LinkedList<Storage>(); // we are not adding SAN
|
||||
// devices by now
|
||||
|
||||
DatacenterCharacteristics characteristics = new DatacenterCharacteristics(
|
||||
arch, os, vmm, hostList, time_zone, cost, costPerMem,
|
||||
costPerStorage, costPerBw);
|
||||
|
||||
// Create Datacenter with previously set parameters
|
||||
SDNDatacenter datacenter = null;
|
||||
try {
|
||||
datacenter = new SDNDatacenter(name, characteristics, new VmAllocationPolicyCombinedLeastFullFirst(hostList), storageList, 0, nos);
|
||||
//datacenter = new SDNDatacenter(name, characteristics, new VmAllocationPolicyCombinedMostFullFirst(hostList), storageList, 0, nos);
|
||||
//datacenter = new SDNDatacenter(name, characteristics, new VmAllocationPolicyMipsLeastFullFirst(hostList), storageList, 0, nos);
|
||||
|
||||
nos.setDatacenter(datacenter);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return datacenter;
|
||||
}
|
||||
|
||||
// We strongly encourage users to develop their own broker policies, to
|
||||
// submit vms and cloudlets according
|
||||
// to the specific rules of the simulated scenario
|
||||
/**
|
||||
* Creates the broker.
|
||||
*
|
||||
* @return the datacenter broker
|
||||
*/
|
||||
private SDNBroker createBroker() {
|
||||
SDNBroker broker = null;
|
||||
try {
|
||||
broker = new SDNBroker("Broker");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return broker;
|
||||
}
|
||||
|
||||
public String indent = ",";
|
||||
public String tabSize = "10";
|
||||
public String fString = "%"+tabSize+"s"+indent;
|
||||
public String fInt = "%"+tabSize+"d"+indent;
|
||||
public String fFloat = "%"+tabSize+".2f"+indent;
|
||||
|
||||
private void printCloudletList(List<Cloudlet> list) {
|
||||
int size = list.size();
|
||||
String content = "";
|
||||
Cloudlet cloudlet;
|
||||
|
||||
append("");
|
||||
append("========== OUTPUT ==========");
|
||||
|
||||
content = String.format(fString, "Cloudlet_ID") +
|
||||
String.format(fString, "STATUS" ) +
|
||||
String.format(fString, "DataCenter_ID") +
|
||||
String.format(fString, "VM_ID") +
|
||||
String.format(fString, "Length") +
|
||||
String.format(fString, "Time") +
|
||||
String.format(fString, "Start Time") +
|
||||
String.format(fString, "Finish Time");
|
||||
append(content);
|
||||
|
||||
//DecimalFormat dft = new DecimalFormat("######.##");
|
||||
for (int i = 0; i < size; i++) {
|
||||
cloudlet = list.get(i);
|
||||
printCloudlet(cloudlet);
|
||||
}
|
||||
}
|
||||
|
||||
private void printCloudlet(Cloudlet cloudlet) {
|
||||
String content = String.format(fInt, cloudlet.getCloudletId());
|
||||
|
||||
if (cloudlet.getCloudletStatus() == Cloudlet.SUCCESS) {
|
||||
content = content +
|
||||
String.format(fString, "SUCCESS") +
|
||||
String.format(fInt, cloudlet.getResourceId()) +
|
||||
String.format(fInt, cloudlet.getVmId()) +
|
||||
String.format(fInt, cloudlet.getCloudletLength()) +
|
||||
String.format(fFloat, cloudlet.getActualCPUTime()) +
|
||||
String.format(fFloat, cloudlet.getExecStartTime()) +
|
||||
String.format(fFloat, cloudlet.getFinishTime());
|
||||
}
|
||||
else {
|
||||
content += "FAILED";
|
||||
}
|
||||
append(content);
|
||||
}
|
||||
|
||||
private double startTime, finishTime;
|
||||
private void printWorkloadList(List<Workload> wls) {
|
||||
int[] appIdNum = new int[SDNBroker.appId];
|
||||
double[] appIdTime = new double[SDNBroker.appId];
|
||||
double[] appIdStartTime = new double[SDNBroker.appId];
|
||||
double[] appIdFinishTime = new double[SDNBroker.appId];
|
||||
|
||||
double serveTime, totalTime = 0;
|
||||
|
||||
append(" ");
|
||||
append("========== OUTPUT ==========");
|
||||
|
||||
printRequestTitle(wls.get(0).request);
|
||||
append(" ");
|
||||
|
||||
for(Workload wl:wls) {
|
||||
startTime = finishTime = -1;
|
||||
printRequest(wl.request);
|
||||
|
||||
serveTime= (finishTime - startTime);
|
||||
append(String.format(fFloat, serveTime));
|
||||
totalTime += serveTime;
|
||||
|
||||
appIdNum[wl.appId] ++;
|
||||
appIdTime[wl.appId] += serveTime;
|
||||
if(appIdStartTime[wl.appId] <=0) {
|
||||
appIdStartTime[wl.appId] = wl.time;
|
||||
}
|
||||
appIdFinishTime[wl.appId] = wl.time;
|
||||
append(" ");
|
||||
}
|
||||
for(int i=0; i<SDNBroker.appId; i++) {
|
||||
append("App Id ("+i+"): "+appIdNum[i]+" requests, Start=" + appIdStartTime[i]+
|
||||
", Finish="+appIdFinishTime[i]+", Rate="+(double)appIdNum[i]/(appIdFinishTime[i] - appIdStartTime[i])+
|
||||
" req/sec, Response time=" + appIdTime[i]/appIdNum[i]);
|
||||
|
||||
}
|
||||
append("Average Response Time:"+(totalTime / wls.size()));
|
||||
|
||||
}
|
||||
|
||||
private void printRequestTitle(Request req) {
|
||||
String content = String.format(fString, "Req_ID");
|
||||
//Log.print(String.format(fFloat, req.getStartTime()));
|
||||
//Log.print(String.format(fFloat, req.getFinishTime()));
|
||||
|
||||
List<Activity> acts = req.getRemovedActivities();
|
||||
for(Activity act:acts) {
|
||||
if(act instanceof Transmission) {
|
||||
Transmission tr=(Transmission)act;
|
||||
content +=
|
||||
String.format(fString, "Tr:Size") +
|
||||
String.format(fString, "Tr:Channel") +
|
||||
String.format(fString, "Tr:time") +
|
||||
String.format(fString, "Tr:Start") +
|
||||
String.format(fString, "Tr:End");
|
||||
|
||||
printRequestTitle(tr.getPackage().getPayload());
|
||||
}
|
||||
else {
|
||||
content +=
|
||||
String.format(fString, "Pr:Size") +
|
||||
String.format(fString, "Pr:time") +
|
||||
String.format(fString, "Pr:Start") +
|
||||
String.format(fString, "Pr:End");
|
||||
}
|
||||
}
|
||||
append(content);
|
||||
}
|
||||
|
||||
private void printRequest(Request req) {
|
||||
String content = String.format(fInt, req.getRequestId());
|
||||
//Log.print(String.format(fFloat, req.getStartTime()));
|
||||
//Log.print(String.format(fFloat, req.getFinishTime()));
|
||||
|
||||
List<Activity> acts = req.getRemovedActivities();
|
||||
for(Activity act:acts) {
|
||||
if(act instanceof Transmission) {
|
||||
Transmission tr=(Transmission)act;
|
||||
content +=
|
||||
String.format(fInt, tr.getPackage().getSize()) +
|
||||
String.format(fInt, tr.getPackage().getFlowId()) +
|
||||
|
||||
String.format(fFloat, tr.getPackage().getFinishTime() - tr.getPackage().getStartTime()) +
|
||||
String.format(fFloat, tr.getPackage().getStartTime()) +
|
||||
String.format(fFloat, tr.getPackage().getFinishTime());
|
||||
|
||||
printRequest(tr.getPackage().getPayload());
|
||||
}
|
||||
else {
|
||||
Processing pr=(Processing)act;
|
||||
content +=
|
||||
String.format(fInt, pr.getCloudlet().getCloudletLength()) +
|
||||
|
||||
String.format(fFloat, pr.getCloudlet().getActualCPUTime()) +
|
||||
String.format(fFloat, pr.getCloudlet().getExecStartTime()) +
|
||||
String.format(fFloat, pr.getCloudlet().getFinishTime());
|
||||
|
||||
if(startTime == -1) startTime = pr.getCloudlet().getExecStartTime();
|
||||
finishTime=pr.getCloudlet().getFinishTime();
|
||||
}
|
||||
}
|
||||
append(content);
|
||||
}
|
||||
|
||||
private void append(String content){
|
||||
outputArea.append(content+"\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Title: CloudSim Toolkit
|
||||
* Description: CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2009-2012, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.overbooking;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.provisioners.BwProvisioner;
|
||||
|
||||
/**
|
||||
* BwProvisionerSimple is a class that implements a simple best effort allocation policy: if there
|
||||
* is bw available to request, it allocates; otherwise, it fails.
|
||||
*
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @author Anton Beloglazov
|
||||
* @since CloudSim Toolkit 1.0
|
||||
*/
|
||||
public class BwProvisionerOverbooking extends BwProvisioner {
|
||||
|
||||
/** The bw table. */
|
||||
private Map<String, Long> bwTable;
|
||||
public static final double overbookingRatioBw = 1.0; // 20% overbooking allowed for BW
|
||||
|
||||
/**
|
||||
* Instantiates a new bw provisioner simple.
|
||||
*
|
||||
* @param bw the bw
|
||||
*/
|
||||
public BwProvisionerOverbooking(long bw) {
|
||||
super(bw);
|
||||
setAvailableBw((long) getOverbookedBw(bw)); //overwrite available BW to overbookable BW
|
||||
|
||||
setBwTable(new HashMap<String, Long>());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.BwProvisioner#allocateBwForVm(cloudsim.Vm, long)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateBwForVm(Vm vm, long bw) {
|
||||
deallocateBwForVm(vm);
|
||||
|
||||
if (getAvailableBw() >= bw) {
|
||||
setAvailableBw(getAvailableBw() - bw);
|
||||
getBwTable().put(vm.getUid(), bw);
|
||||
vm.setCurrentAllocatedBw(getAllocatedBwForVm(vm));
|
||||
return true;
|
||||
}
|
||||
|
||||
vm.setCurrentAllocatedBw(getAllocatedBwForVm(vm));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.BwProvisioner#getAllocatedBwForVm(cloudsim.Vm)
|
||||
*/
|
||||
@Override
|
||||
public long getAllocatedBwForVm(Vm vm) {
|
||||
if (getBwTable().containsKey(vm.getUid())) {
|
||||
return getBwTable().get(vm.getUid());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.BwProvisioner#deallocateBwForVm(cloudsim.Vm)
|
||||
*/
|
||||
@Override
|
||||
public void deallocateBwForVm(Vm vm) {
|
||||
if (getBwTable().containsKey(vm.getUid())) {
|
||||
long amountFreed = getBwTable().remove(vm.getUid());
|
||||
setAvailableBw(getAvailableBw() + amountFreed);
|
||||
vm.setCurrentAllocatedBw(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.BwProvisioner#deallocateBwForVm(cloudsim.Vm)
|
||||
*/
|
||||
@Override
|
||||
public void deallocateBwForAllVms() {
|
||||
super.deallocateBwForAllVms();
|
||||
|
||||
setAvailableBw((long) getOverbookedBw(getBw())); //Overbooking
|
||||
getBwTable().clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see
|
||||
* gridsim.virtualization.power.provisioners.BWProvisioner#isSuitableForVm(gridsim.virtualization
|
||||
* .power.VM, long)
|
||||
*/
|
||||
@Override
|
||||
public boolean isSuitableForVm(Vm vm, long bw) {
|
||||
long allocatedBw = getAllocatedBwForVm(vm);
|
||||
boolean result = allocateBwForVm(vm, bw);
|
||||
deallocateBwForVm(vm);
|
||||
if (allocatedBw > 0) {
|
||||
allocateBwForVm(vm, allocatedBw);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bw table.
|
||||
*
|
||||
* @return the bw table
|
||||
*/
|
||||
protected Map<String, Long> getBwTable() {
|
||||
return bwTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bw table.
|
||||
*
|
||||
* @param bwTable the bw table
|
||||
*/
|
||||
protected void setBwTable(Map<String, Long> bwTable) {
|
||||
this.bwTable = bwTable;
|
||||
}
|
||||
|
||||
public static double getOverbookedBw(long capacity) {
|
||||
double overbookedBw = capacity * BwProvisionerOverbooking.overbookingRatioBw;
|
||||
return overbookedBw;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package org.cloudbus.cloudsim.sdn.overbooking;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Pe;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.VmScheduler;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.core.CloudSimTags;
|
||||
import org.cloudbus.cloudsim.core.SimEvent;
|
||||
import org.cloudbus.cloudsim.provisioners.BwProvisioner;
|
||||
import org.cloudbus.cloudsim.provisioners.RamProvisioner;
|
||||
import org.cloudbus.cloudsim.provisioners.RamProvisionerSimple;
|
||||
import org.cloudbus.cloudsim.sdn.Arc;
|
||||
import org.cloudbus.cloudsim.sdn.Link;
|
||||
import org.cloudbus.cloudsim.sdn.Middlebox;
|
||||
import org.cloudbus.cloudsim.sdn.NetworkOperatingSystem;
|
||||
import org.cloudbus.cloudsim.sdn.Node;
|
||||
import org.cloudbus.cloudsim.sdn.SDNHost;
|
||||
import org.cloudbus.cloudsim.sdn.TimedVm;
|
||||
|
||||
public class OverbookingNetworkOperatingSystem extends NetworkOperatingSystem {
|
||||
|
||||
public OverbookingNetworkOperatingSystem(String fileName) {
|
||||
super(fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deployApplication(List<Vm> vms, List<Middlebox> middleboxes, List<Arc> links) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Starting deploying application..");
|
||||
|
||||
for(Vm vm:vms)
|
||||
{
|
||||
TimedVm tvm = (TimedVm) vm;
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Trying to Create VM #" + vm.getId()
|
||||
+ " in " + datacenter.getName() + ", (" + tvm.getStartTime() + "~" +tvm.getFinishTime() + ")");
|
||||
send(datacenter.getId(), tvm.getStartTime(), CloudSimTags.VM_CREATE_ACK, vm);
|
||||
|
||||
if(tvm.getFinishTime() != Double.POSITIVE_INFINITY) {
|
||||
send(datacenter.getId(), tvm.getFinishTime(), CloudSimTags.VM_DESTROY, vm);
|
||||
send(this.getId(), tvm.getFinishTime(), CloudSimTags.VM_DESTROY, vm);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean deployFlow(List<Arc> links) {
|
||||
for(Arc link:links) {
|
||||
int srcVm = link.getSrcId();
|
||||
int dstVm = link.getDstId();
|
||||
int flowId = link.getFlowId();
|
||||
|
||||
SDNHost srchost = findSDNHost(srcVm);
|
||||
SDNHost dsthost = findSDNHost(dstVm);
|
||||
if(srchost == null || dsthost == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(srchost.equals(dsthost)) {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": Source SDN Host is same as Destination. Go loopback");
|
||||
srchost.addVMRoute(srcVm, dstVm, flowId, dsthost);
|
||||
}
|
||||
else {
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": VMs are in different hosts. Create entire routing table (hosts, switches)");
|
||||
boolean findRoute = buildRoutingTables(srchost, srcVm, dstVm, flowId, null);
|
||||
|
||||
if(!findRoute) {
|
||||
System.err.println("SimpleNetworkOperatingSystem.deployFlow: Could not find route!!" +
|
||||
NetworkOperatingSystem.debugVmIdName.get(srcVm) + "->"+NetworkOperatingSystem.debugVmIdName.get(dstVm));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Print all routing tables.
|
||||
for(Node node:this.topology.getAllNodes()) {
|
||||
node.printVMRoute();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean buildRoutingTables(Node node, int srcVm, int dstVm, int flowId, Node prevNode) {
|
||||
Collection<Link> links = this.topology.getAdjacentLinks(node);
|
||||
if(links.size() == 0) {
|
||||
// No link. Do nothing
|
||||
}
|
||||
else if(links.size() == 1) {
|
||||
// Only one way, no other choice (for Host)
|
||||
for(Link l:links) {
|
||||
Node nextHop= l.getHighOrder();
|
||||
if(nextHop.equals(node))
|
||||
nextHop= l.getLowOrder();
|
||||
|
||||
node.addVMRoute(srcVm, dstVm, flowId, nextHop);
|
||||
buildRoutingTables(nextHop, srcVm, dstVm, flowId, node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// There are many links. Determine which hop to go.
|
||||
SDNHost dsthost = findSDNHost(dstVm);
|
||||
|
||||
for(Link l:links) {
|
||||
Node nextHop= l.getHighOrder();
|
||||
if(nextHop.equals(node))
|
||||
nextHop= l.getLowOrder();
|
||||
|
||||
if(nextHop.equals(prevNode)) {
|
||||
// NextHop is going back to prev node
|
||||
continue;
|
||||
}
|
||||
else if(nextHop.equals(dsthost)) {
|
||||
// NextHop is the destination. Just add. No further route finding.
|
||||
node.addVMRoute(srcVm, dstVm, flowId, nextHop);
|
||||
return true;
|
||||
}
|
||||
else if(nextHop instanceof SDNHost) {
|
||||
// NextHop is host but no destination. Can't forward
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// Nexthop is switch
|
||||
if(buildRoutingTables(nextHop, srcVm, dstVm, flowId, node)) {
|
||||
// If the route is right.
|
||||
node.addVMRoute(srcVm, dstVm, flowId, nextHop);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Middlebox deployMiddlebox(String type,Vm vm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processVmCreateAck(SimEvent ev) {
|
||||
// print the created VM info
|
||||
TimedVm vm = (TimedVm) ev.getData();
|
||||
Log.printLine(CloudSim.clock() + ": " + getName() + ": VM Created: " + vm.getId() + " in " + this.findSDNHost(vm.getId()));
|
||||
deployFlow(this.arcList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Host createHost(int hostId, int ram, long bw, long storage, long pes, double mips) {
|
||||
LinkedList<Pe> peList = new LinkedList<Pe>();
|
||||
int peId=0;
|
||||
for(int i=0;i<pes;i++) peList.add(new Pe(peId++,new PeProvisionerOverbooking(mips)));
|
||||
|
||||
RamProvisioner ramPro = new RamProvisionerSimple(ram);
|
||||
BwProvisioner bwPro = new BwProvisionerOverbooking(bw);
|
||||
VmScheduler vmScheduler = new VmSchedulerTimeSharedOverbookingEnergy(peList);
|
||||
Host newHost = new Host(hostId, ramPro, bwPro, storage, peList, vmScheduler);
|
||||
|
||||
return newHost;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Title: CloudSim Toolkit
|
||||
* Description: CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2009-2012, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.overbooking;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.provisioners.PeProvisioner;
|
||||
|
||||
/**
|
||||
* The Class PeProvisionerSimple.
|
||||
*
|
||||
* @author Anton Beloglazov
|
||||
* @since CloudSim Toolkit 2.0
|
||||
*/
|
||||
public class PeProvisionerOverbooking extends PeProvisioner {
|
||||
|
||||
/** The pe table. */
|
||||
private Map<String, List<Double>> peTable;
|
||||
public static final double overbookingRatioMips = 4.0; // 10% overbooking allowed for MIPS
|
||||
|
||||
/**
|
||||
* Creates the PeProvisionerSimple object.
|
||||
*
|
||||
* @param availableMips the available mips
|
||||
*
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
public PeProvisionerOverbooking(double availableMips) {
|
||||
super(availableMips);
|
||||
|
||||
setAvailableMips(PeProvisionerOverbooking.getOverbookedMips(availableMips));
|
||||
|
||||
setPeTable(new HashMap<String, ArrayList<Double>>());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.PeProvisioner#allocateMipsForVM(cloudsim.power.VM, int)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateMipsForVm(Vm vm, double mips) {
|
||||
return allocateMipsForVm(vm.getUid(), mips);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.PeProvisioner#allocateMipsForVm(java.lang.String, double)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateMipsForVm(String vmUid, double mips) {
|
||||
if (getAvailableMips() < mips) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Double> allocatedMips;
|
||||
|
||||
if (getPeTable().containsKey(vmUid)) {
|
||||
allocatedMips = getPeTable().get(vmUid);
|
||||
} else {
|
||||
allocatedMips = new ArrayList<Double>();
|
||||
}
|
||||
|
||||
allocatedMips.add(mips);
|
||||
|
||||
setAvailableMips(getAvailableMips() - mips);
|
||||
getPeTable().put(vmUid, allocatedMips);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.PeProvisioner#allocateMipsForVM(cloudsim.power.VM,
|
||||
* java.util.ArrayList)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateMipsForVm(Vm vm, List<Double> mips) {
|
||||
int totalMipsToAllocate = 0;
|
||||
for (double _mips : mips) {
|
||||
totalMipsToAllocate += _mips;
|
||||
}
|
||||
|
||||
if (getAvailableMips() + getTotalAllocatedMipsForVm(vm) < totalMipsToAllocate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setAvailableMips(getAvailableMips() + getTotalAllocatedMipsForVm(vm) - totalMipsToAllocate);
|
||||
|
||||
getPeTable().put(vm.getUid(), mips);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.PeProvisioner#deallocateMipsForAllVms()
|
||||
*/
|
||||
@Override
|
||||
public void deallocateMipsForAllVms() {
|
||||
super.deallocateMipsForAllVms();
|
||||
|
||||
setAvailableMips(PeProvisionerOverbooking.getOverbookedMips(getMips())); //Overbooking
|
||||
|
||||
getPeTable().clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see
|
||||
* cloudsim.provisioners.PeProvisioner#getAllocatedMipsForVMByVirtualPeId(cloudsim.power.VM,
|
||||
* int)
|
||||
*/
|
||||
@Override
|
||||
public double getAllocatedMipsForVmByVirtualPeId(Vm vm, int peId) {
|
||||
if (getPeTable().containsKey(vm.getUid())) {
|
||||
try {
|
||||
return getPeTable().get(vm.getUid()).get(peId);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.PeProvisioner#getAllocatedMipsForVM(cloudsim.power.VM)
|
||||
*/
|
||||
@Override
|
||||
public List<Double> getAllocatedMipsForVm(Vm vm) {
|
||||
if (getPeTable().containsKey(vm.getUid())) {
|
||||
return getPeTable().get(vm.getUid());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.PeProvisioner#getTotalAllocatedMipsForVM(cloudsim.power.VM)
|
||||
*/
|
||||
@Override
|
||||
public double getTotalAllocatedMipsForVm(Vm vm) {
|
||||
if (getPeTable().containsKey(vm.getUid())) {
|
||||
double totalAllocatedMips = 0.0;
|
||||
for (double mips : getPeTable().get(vm.getUid())) {
|
||||
totalAllocatedMips += mips;
|
||||
}
|
||||
return totalAllocatedMips;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.provisioners.PeProvisioner#deallocateMipsForVM(cloudsim.power.VM)
|
||||
*/
|
||||
@Override
|
||||
public void deallocateMipsForVm(Vm vm) {
|
||||
if (getPeTable().containsKey(vm.getUid())) {
|
||||
for (double mips : getPeTable().get(vm.getUid())) {
|
||||
setAvailableMips(getAvailableMips() + mips);
|
||||
}
|
||||
getPeTable().remove(vm.getUid());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pe table.
|
||||
*
|
||||
* @return the peTable
|
||||
*/
|
||||
protected Map<String, List<Double>> getPeTable() {
|
||||
return peTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pe table.
|
||||
*
|
||||
* @param peTable the peTable to set
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void setPeTable(Map<String, ? extends List<Double>> peTable) {
|
||||
this.peTable = (Map<String, List<Double>>) peTable;
|
||||
}
|
||||
|
||||
public static double getOverbookedMips(double availableMips) {
|
||||
double overbookedMips = availableMips * PeProvisionerOverbooking.overbookingRatioMips;
|
||||
return overbookedMips;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
package org.cloudbus.cloudsim.sdn.overbooking;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudbus.cloudsim.Host;
|
||||
import org.cloudbus.cloudsim.Log;
|
||||
import org.cloudbus.cloudsim.Vm;
|
||||
import org.cloudbus.cloudsim.VmAllocationPolicy;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationMaxHostInterface;
|
||||
|
||||
public class VmAllocationPolicyOverbooking extends VmAllocationPolicy implements PowerUtilizationMaxHostInterface {
|
||||
|
||||
protected final double hostTotalMips;
|
||||
protected final double hostTotalBw;
|
||||
protected final int hostTotalPes;
|
||||
|
||||
/** The vm table. */
|
||||
private Map<String, Host> vmTable;
|
||||
|
||||
/** The used pes. */
|
||||
private Map<String, Integer> usedPes;
|
||||
|
||||
/** The free pes. */
|
||||
private List<Integer> freePes;
|
||||
|
||||
private Map<String, Long> usedMips;
|
||||
private List<Long> freeMips;
|
||||
private Map<String, Long> usedBw;
|
||||
private List<Long> freeBw;
|
||||
|
||||
/**
|
||||
* Creates the new VmAllocationPolicySimple object.
|
||||
*
|
||||
* @param list the list
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
public VmAllocationPolicyOverbooking(List<? extends Host> list) {
|
||||
super(list);
|
||||
|
||||
setFreePes(new ArrayList<Integer>());
|
||||
setFreeMips(new ArrayList<Long>());
|
||||
setFreeBw(new ArrayList<Long>());
|
||||
|
||||
for (Host host : getHostList()) {
|
||||
getFreePes().add(host.getNumberOfPes());
|
||||
getFreeMips().add((long) PeProvisionerOverbooking.getOverbookedMips((host.getTotalMips())));
|
||||
getFreeBw().add((long) BwProvisionerOverbooking.getOverbookedBw(host.getBw()));
|
||||
}
|
||||
hostTotalMips = getHostList().get(0).getTotalMips();
|
||||
hostTotalBw = getHostList().get(0).getBw();
|
||||
hostTotalPes = getHostList().get(0).getNumberOfPes();
|
||||
|
||||
setVmTable(new HashMap<String, Host>());
|
||||
setUsedPes(new HashMap<String, Integer>());
|
||||
setUsedMips(new HashMap<String, Long>());
|
||||
setUsedBw(new HashMap<String, Long>());
|
||||
}
|
||||
|
||||
protected double convertWeightedMetric(double mipsPercent, double bwPercent) {
|
||||
double ret = mipsPercent * bwPercent;
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* Allocates a host for a given VM.
|
||||
*
|
||||
* @param vm VM specification
|
||||
* @return $true if the host could be allocated; $false otherwise
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm) {
|
||||
if (getVmTable().containsKey(vm.getUid())) { // if this vm was not created
|
||||
return false;
|
||||
}
|
||||
|
||||
int numHosts = getHostList().size();
|
||||
|
||||
// 1. Find/Order the best host for this VM by comparing a metric
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
double requiredMips = vm.getCurrentRequestedTotalMips();
|
||||
long requiredBw = vm.getCurrentRequestedBw();
|
||||
|
||||
boolean result = false;
|
||||
|
||||
// freeReousrces : Weighted-calculated free resource percentage in each host
|
||||
double[] freeResources = new double[numHosts];
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
double mipsFreePercent = (double)getFreeMips().get(i) / this.hostTotalMips;
|
||||
double bwFreePercent = (double)getFreeBw().get(i) / this.hostTotalBw;
|
||||
|
||||
freeResources[i] = this.convertWeightedMetric(mipsFreePercent, bwFreePercent);
|
||||
}
|
||||
|
||||
// Find the most full host, with available resource.
|
||||
for(int tries = 0; result == false && tries < numHosts; tries++) {// we still trying until we find a host or until we try all of them
|
||||
double lessFree = Double.POSITIVE_INFINITY;
|
||||
int idx = -1;
|
||||
|
||||
// Find the most full host
|
||||
for (int i = 0; i < numHosts; i++) {
|
||||
if (freeResources[i] < lessFree) {
|
||||
lessFree = freeResources[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
freeResources[idx] = Double.POSITIVE_INFINITY; // Mark visited
|
||||
|
||||
Host host = getHostList().get(idx);
|
||||
|
||||
// Check whether the host can hold this VM or not.
|
||||
if( getFreeMips().get(idx) < requiredMips) {
|
||||
System.err.format("not enough MIPS. MIPS %d(%.2f) / BW %d (%.2f)\n",
|
||||
getFreeMips().get(idx),
|
||||
(double)getFreeMips().get(idx)/requiredMips,
|
||||
getFreeBw().get(idx),
|
||||
(double)getFreeBw().get(idx) / requiredBw);
|
||||
continue;
|
||||
}
|
||||
if( getFreeBw().get(idx) < requiredBw) {
|
||||
System.err.format("not enough BW. MIPS %d(%.2f) / BW %d (%.2f)\n",
|
||||
getFreeMips().get(idx),
|
||||
(double)getFreeMips().get(idx)/requiredMips,
|
||||
getFreeBw().get(idx),
|
||||
(double)getFreeBw().get(idx) / requiredBw);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = host.vmCreate(vm);
|
||||
|
||||
if (result) { // if vm were succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
getUsedMips().put(vm.getUid(), (long) requiredMips);
|
||||
getFreeMips().set(idx, (long) (getFreeMips().get(idx) - requiredMips));
|
||||
|
||||
getUsedBw().put(vm.getUid(), (long) requiredBw);
|
||||
getFreeBw().set(idx, (long) (getFreeBw().get(idx) - requiredBw));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
System.err.println("VmAllocationPolicy: WARNING:: Cannot create VM!!!!");
|
||||
}
|
||||
logMaxNumHostsUsed();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected int maxNumHostsUsed=0;
|
||||
public void logMaxNumHostsUsed() {
|
||||
// Get how many are used
|
||||
int numHostsUsed=0;
|
||||
for(int freePes:getFreePes()) {
|
||||
if(freePes < hostTotalPes) {
|
||||
numHostsUsed++;
|
||||
}
|
||||
}
|
||||
if(maxNumHostsUsed < numHostsUsed)
|
||||
maxNumHostsUsed = numHostsUsed;
|
||||
Log.printLine("Number of online hosts:"+numHostsUsed + ", max was ="+maxNumHostsUsed);
|
||||
}
|
||||
public int getMaxNumHostsUsed() { return maxNumHostsUsed;}
|
||||
|
||||
/**
|
||||
* Releases the host used by a VM.
|
||||
*
|
||||
* @param vm the vm
|
||||
* @pre $none
|
||||
* @post none
|
||||
*/
|
||||
@Override
|
||||
public void deallocateHostForVm(Vm vm) {
|
||||
Host host = getVmTable().remove(vm.getUid());
|
||||
if (host != null) {
|
||||
int idx = getHostList().indexOf(host);
|
||||
host.vmDestroy(vm);
|
||||
|
||||
Integer pes = getUsedPes().remove(vm.getUid());
|
||||
getFreePes().set(idx, getFreePes().get(idx) + pes);
|
||||
|
||||
Long mips = getUsedMips().remove(vm.getUid());
|
||||
getFreeMips().set(idx, getFreeMips().get(idx) + mips);
|
||||
|
||||
Long bw = getUsedBw().remove(vm.getUid());
|
||||
getFreeBw().set(idx, getFreeBw().get(idx) + bw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host that is executing the given VM belonging to the given user.
|
||||
*
|
||||
* @param vm the vm
|
||||
* @return the Host with the given vmID and userID; $null if not found
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public Host getHost(Vm vm) {
|
||||
return getVmTable().get(vm.getUid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host that is executing the given VM belonging to the given user.
|
||||
*
|
||||
* @param vmId the vm id
|
||||
* @param userId the user id
|
||||
* @return the Host with the given vmID and userID; $null if not found
|
||||
* @pre $none
|
||||
* @post $none
|
||||
*/
|
||||
@Override
|
||||
public Host getHost(int vmId, int userId) {
|
||||
return getVmTable().get(Vm.getUid(userId, vmId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the vm table.
|
||||
*
|
||||
* @return the vm table
|
||||
*/
|
||||
public Map<String, Host> getVmTable() {
|
||||
return vmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vm table.
|
||||
*
|
||||
* @param vmTable the vm table
|
||||
*/
|
||||
protected void setVmTable(Map<String, Host> vmTable) {
|
||||
this.vmTable = vmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the used pes.
|
||||
*
|
||||
* @return the used pes
|
||||
*/
|
||||
protected Map<String, Integer> getUsedPes() {
|
||||
return usedPes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the used pes.
|
||||
*
|
||||
* @param usedPes the used pes
|
||||
*/
|
||||
protected void setUsedPes(Map<String, Integer> usedPes) {
|
||||
this.usedPes = usedPes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the free pes.
|
||||
*
|
||||
* @return the free pes
|
||||
*/
|
||||
protected List<Integer> getFreePes() {
|
||||
return freePes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the free pes.
|
||||
*
|
||||
* @param freePes the new free pes
|
||||
*/
|
||||
protected void setFreePes(List<Integer> freePes) {
|
||||
this.freePes = freePes;
|
||||
}
|
||||
|
||||
protected Map<String, Long> getUsedMips() {
|
||||
return usedMips;
|
||||
}
|
||||
protected void setUsedMips(Map<String, Long> usedMips) {
|
||||
this.usedMips = usedMips;
|
||||
}
|
||||
protected Map<String, Long> getUsedBw() {
|
||||
return usedBw;
|
||||
}
|
||||
protected void setUsedBw(Map<String, Long> usedBw) {
|
||||
this.usedBw = usedBw;
|
||||
}
|
||||
protected List<Long> getFreeMips() {
|
||||
return this.freeMips;
|
||||
}
|
||||
protected void setFreeMips(List<Long> freeMips) {
|
||||
this.freeMips = freeMips;
|
||||
}
|
||||
|
||||
protected List<Long> getFreeBw() {
|
||||
return this.freeBw;
|
||||
}
|
||||
protected void setFreeBw(List<Long> freeBw) {
|
||||
this.freeBw = freeBw;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see cloudsim.VmAllocationPolicy#optimizeAllocation(double, cloudsim.VmList, double)
|
||||
*/
|
||||
@Override
|
||||
public List<Map<String, Object>> optimizeAllocation(List<? extends Vm> vmList) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.cloudbus.cloudsim.VmAllocationPolicy#allocateHostForVm(org.cloudbus.cloudsim.Vm,
|
||||
* org.cloudbus.cloudsim.Host)
|
||||
*/
|
||||
@Override
|
||||
public boolean allocateHostForVm(Vm vm, Host host) {
|
||||
if (host.vmCreate(vm)) { // if vm has been succesfully created in the host
|
||||
getVmTable().put(vm.getUid(), host);
|
||||
|
||||
int requiredPes = vm.getNumberOfPes();
|
||||
int idx = getHostList().indexOf(host);
|
||||
getUsedPes().put(vm.getUid(), requiredPes);
|
||||
getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
|
||||
|
||||
Log.formatLine(
|
||||
"%.2f: VM #" + vm.getId() + " has been allocated to the host #" + host.getId(),
|
||||
CloudSim.clock());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Title: CloudSim Toolkit
|
||||
* Description: CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2009-2012, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.overbooking;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudbus.cloudsim.Pe;
|
||||
import org.cloudbus.cloudsim.VmSchedulerTimeSharedOverSubscription;
|
||||
import org.cloudbus.cloudsim.core.CloudSim;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationHistoryEntry;
|
||||
import org.cloudbus.cloudsim.sdn.power.PowerUtilizationInterface;
|
||||
|
||||
/**
|
||||
* VmSchedulerSpaceShared is a VMM allocation policy that allocates one or more Pe to a VM, and
|
||||
* doesn't allow sharing of PEs. If there is no free PEs to the VM, allocation fails. Free PEs are
|
||||
* not allocated to VMs
|
||||
*
|
||||
* @author Rodrigo N. Calheiros
|
||||
* @author Anton Beloglazov
|
||||
* @since CloudSim Toolkit 1.0
|
||||
*/
|
||||
public class VmSchedulerTimeSharedOverbookingEnergy extends VmSchedulerTimeSharedOverSubscription implements PowerUtilizationInterface{
|
||||
|
||||
|
||||
public VmSchedulerTimeSharedOverbookingEnergy(List<? extends Pe> pelist) {
|
||||
super(pelist);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAvailableMips(double availableMips) {
|
||||
super.setAvailableMips(availableMips);
|
||||
addUtilizationEntry();
|
||||
}
|
||||
|
||||
private List<PowerUtilizationHistoryEntry> utilizationHistories = null;
|
||||
private static double powerOffDuration = 0; //if host is idle for 1 hours, it's turned off.
|
||||
|
||||
public void addUtilizationEntryTermination(double terminatedTime) {
|
||||
if(this.utilizationHistories != null)
|
||||
this.utilizationHistories.add(new PowerUtilizationHistoryEntry(terminatedTime, 0));
|
||||
}
|
||||
|
||||
public List<PowerUtilizationHistoryEntry> getUtilizationHisotry() {
|
||||
return utilizationHistories;
|
||||
}
|
||||
|
||||
public double getUtilizationEnergyConsumption() {
|
||||
|
||||
double total=0;
|
||||
double lastTime=0;
|
||||
double lastMips=0;
|
||||
if(this.utilizationHistories == null)
|
||||
return 0;
|
||||
|
||||
for(PowerUtilizationHistoryEntry h:this.utilizationHistories) {
|
||||
double duration = h.startTime - lastTime;
|
||||
double utilPercentage = lastMips/ getTotalMips();
|
||||
double power = calculatePower(utilPercentage);
|
||||
double energyConsumption = power * duration;
|
||||
|
||||
// Assume that the host is turned off when duration is long enough
|
||||
if(duration > powerOffDuration && lastMips == 0)
|
||||
energyConsumption = 0;
|
||||
|
||||
total += energyConsumption;
|
||||
lastTime = h.startTime;
|
||||
lastMips = h.usedMips;
|
||||
}
|
||||
return total/3600; // transform to Whatt*hour from What*seconds
|
||||
}
|
||||
|
||||
private double calculatePower(double u) {
|
||||
double power = 120 + 154 * u;
|
||||
return power;
|
||||
}
|
||||
|
||||
private void addUtilizationEntry() {
|
||||
double time = CloudSim.clock();
|
||||
double totalMips = getTotalMips();
|
||||
double usingMips = totalMips - this.getAvailableMips();
|
||||
if(usingMips < 0) {
|
||||
System.err.println("addUtilizationEntry : using mips is negative, No way!");
|
||||
}
|
||||
if(utilizationHistories == null)
|
||||
utilizationHistories = new ArrayList<PowerUtilizationHistoryEntry>();
|
||||
this.utilizationHistories.add(new PowerUtilizationHistoryEntry(time, usingMips));
|
||||
}
|
||||
|
||||
private double getTotalMips() {
|
||||
return this.getPeList().size() * this.getPeCapacity();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.power;
|
||||
|
||||
/**
|
||||
* To log utilization history, this class holds power utilization information
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public class PowerUtilizationHistoryEntry {
|
||||
public double startTime;
|
||||
public double usedMips;
|
||||
public PowerUtilizationHistoryEntry(double t, double m) { startTime=t; usedMips=m;}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
|
||||
package org.cloudbus.cloudsim.sdn.power;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to manage utilization history.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public interface PowerUtilizationInterface {
|
||||
public void addUtilizationEntryTermination(double terminatedTime);
|
||||
public List<PowerUtilizationHistoryEntry> getUtilizationHisotry();
|
||||
public double getUtilizationEnergyConsumption();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Title: CloudSimSDN
|
||||
* Description: SDN extension for CloudSim
|
||||
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Copyright (c) 2015, The University of Melbourne, Australia
|
||||
*/
|
||||
package org.cloudbus.cloudsim.sdn.power;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to manage host history.
|
||||
*
|
||||
* @author Jungmin Son
|
||||
* @since CloudSimSDN 1.0
|
||||
*/
|
||||
public interface PowerUtilizationMaxHostInterface {
|
||||
void logMaxNumHostsUsed();
|
||||
int getMaxNumHostsUsed();
|
||||
}
|
||||
290
src/org/cloudbus/cloudsim/sdn/request/VMRequestGenerator.java
Normal file
290
src/org/cloudbus/cloudsim/sdn/request/VMRequestGenerator.java
Normal file
@@ -0,0 +1,290 @@
|
||||
package org.cloudbus.cloudsim.sdn.request;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.apache.commons.math3.distribution.ExponentialDistribution;
|
||||
import org.apache.commons.math3.distribution.ParetoDistribution;
|
||||
import org.apache.commons.math3.random.Well19937c;
|
||||
|
||||
/* Generate VM requests, for example:
|
||||
*
|
||||
{
|
||||
"nodes" : [
|
||||
{
|
||||
"name" : "vm01",
|
||||
"type" : "vm",
|
||||
"size" : 1000,
|
||||
"pes": 1,
|
||||
"mips" : 30000000,
|
||||
"ram" : 512,
|
||||
"bw" : 100000,
|
||||
"starttime": 1.3,
|
||||
"endtime" : 20.5,
|
||||
},
|
||||
],
|
||||
"links" : [
|
||||
{
|
||||
"name": "l32",
|
||||
"source" : "vm03" ,
|
||||
"destination" : "vm02" ,
|
||||
"bandwidth" : 66000000
|
||||
},
|
||||
],
|
||||
*/
|
||||
public class VMRequestGenerator {
|
||||
|
||||
public static void main(String [] argv) {
|
||||
int numVms = 100;
|
||||
String jsonFileName = "virtual2.json";
|
||||
|
||||
VMRequestGenerator reqg = new VMRequestGenerator();
|
||||
|
||||
List<VMSpec> vms = reqg.generateVMs(numVms);
|
||||
List<LinkSpec> links = reqg.generateLinks();
|
||||
|
||||
reqg.wrtieJSON(vms, links, jsonFileName);
|
||||
|
||||
}
|
||||
|
||||
class VMSpec {
|
||||
String name;
|
||||
String type;
|
||||
long size;
|
||||
int pe;
|
||||
long mips;
|
||||
int ram;
|
||||
long bw;
|
||||
double starttime;
|
||||
double endtime;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
JSONObject toJSON() {
|
||||
VMSpec vm = this;
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("name", vm.name);
|
||||
obj.put("type", vm.type);
|
||||
obj.put("size", vm.size);
|
||||
obj.put("pes", vm.pe);
|
||||
obj.put("mips", vm.mips);
|
||||
obj.put("ram", new Integer(vm.ram));
|
||||
obj.put("bw", vm.bw);
|
||||
obj.put("starttime", vm.starttime);
|
||||
obj.put("endtime", vm.endtime);
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
class LinkSpec {
|
||||
String name;
|
||||
String source;
|
||||
String destination;
|
||||
Long bw;
|
||||
|
||||
public LinkSpec(String name,String source,String destination,Long bw) {
|
||||
this.name = name;
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.bw = bw;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
JSONObject toJSON() {
|
||||
LinkSpec link = this;
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("name", link.name);
|
||||
obj.put("source", link.source);
|
||||
obj.put("destination", link.destination);
|
||||
if(link.bw != null)
|
||||
obj.put("bw", link.bw);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
int vmId = 0;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void wrtieJSON(List<VMSpec> vms, List<LinkSpec> links, String jsonFileName) {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
JSONArray vmList = new JSONArray();
|
||||
JSONArray linkList = new JSONArray();
|
||||
|
||||
for(VMSpec vm:vms) {
|
||||
vmList.add(vm.toJSON());
|
||||
}
|
||||
|
||||
for(LinkSpec link:links) {
|
||||
linkList.add(link.toJSON());
|
||||
}
|
||||
|
||||
obj.put("nodes", vmList);
|
||||
obj.put("links", linkList);
|
||||
|
||||
try {
|
||||
|
||||
FileWriter file = new FileWriter(jsonFileName);
|
||||
file.write(obj.toJSONString());
|
||||
file.flush();
|
||||
file.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println(obj);
|
||||
}
|
||||
|
||||
enum VMtype {
|
||||
WebServer,
|
||||
AppServer,
|
||||
DBServer,
|
||||
Proxy,
|
||||
Firewall
|
||||
}
|
||||
|
||||
public VMSpec generateVM(long vmSize, int pes, long mips, int vmRam, long bw, double startTime, double endTime) {
|
||||
VMSpec vm = new VMSpec();
|
||||
|
||||
vm.name = "vm"+ String.format("%02d", vmId++);
|
||||
vm.type = "vm";
|
||||
vm.size = vmSize;
|
||||
vm.pe = pes;
|
||||
vm.mips = mips;
|
||||
vm.ram = vmRam;
|
||||
vm.bw = bw;
|
||||
vm.starttime = startTime;
|
||||
vm.endtime = endTime;
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
public VMSpec generateVM(VMtype vmtype, double startTime, double endTime) {
|
||||
int pes = 1;
|
||||
long vmSize = 1000;
|
||||
long mips=2000;
|
||||
int vmRam = 512;
|
||||
long bw=1000000000/10;
|
||||
|
||||
switch(vmtype) {
|
||||
case WebServer:
|
||||
//m1.large
|
||||
mips=2000;
|
||||
pes=2;
|
||||
break;
|
||||
case AppServer:
|
||||
//m2.xlarge
|
||||
mips=3000L;
|
||||
pes=8;
|
||||
break;
|
||||
case DBServer:
|
||||
//c1.xlarge
|
||||
mips=2400L;
|
||||
pes=8;
|
||||
break;
|
||||
case Proxy:
|
||||
mips=2000;
|
||||
pes=8;
|
||||
bw=500000000;
|
||||
break;
|
||||
case Firewall:
|
||||
mips=3000L;
|
||||
pes=8;
|
||||
bw=500000000;
|
||||
break;
|
||||
}
|
||||
return generateVM(vmSize, pes, mips, vmRam, bw, startTime, endTime);
|
||||
}
|
||||
|
||||
public List<VMSpec> generateVMGroup(int numVMsInGroup, double startTime, double endTime) {
|
||||
System.out.printf("Generating VM Group(%d): %f - %f\n", numVMsInGroup, startTime, endTime);
|
||||
|
||||
List<VMSpec> vms = new ArrayList<VMSpec>();
|
||||
|
||||
switch(numVMsInGroup) {
|
||||
case 2:
|
||||
vms.add(this.generateVM(VMtype.WebServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.AppServer, startTime, endTime));
|
||||
break;
|
||||
case 3:
|
||||
vms.add(this.generateVM(VMtype.WebServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.AppServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.DBServer, startTime, endTime));
|
||||
break;
|
||||
case 4:
|
||||
vms.add(this.generateVM(VMtype.WebServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.AppServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.DBServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.Proxy, startTime, endTime));
|
||||
break;
|
||||
case 5:
|
||||
vms.add(this.generateVM(VMtype.WebServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.AppServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.DBServer, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.Proxy, startTime, endTime));
|
||||
vms.add(this.generateVM(VMtype.Firewall, startTime, endTime));
|
||||
break;
|
||||
default:
|
||||
System.err.println("Unknown group number"+numVMsInGroup);
|
||||
break;
|
||||
}
|
||||
|
||||
return vms;
|
||||
}
|
||||
|
||||
private static long seed = 10;
|
||||
|
||||
public List<VMSpec> generateVMs(int totalVmNum) {
|
||||
double lastStartTime = 0;
|
||||
|
||||
double startMean = 1800; // sec = 30min
|
||||
double durScale=14400; // sec = 4 hours
|
||||
double durShape=1.2;
|
||||
|
||||
Random rVmNum = new Random(seed);
|
||||
ExponentialDistribution rStartTime = new ExponentialDistribution(new Well19937c(seed), startMean, ExponentialDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
|
||||
ParetoDistribution rDuration = new ParetoDistribution(new Well19937c(seed), durScale, durShape);
|
||||
|
||||
List<VMSpec> vms = new ArrayList<VMSpec>();
|
||||
|
||||
while(this.vmId < totalVmNum) {
|
||||
int vmsInGroup = rVmNum.nextInt(4)+2;
|
||||
double duration = Math.floor(rDuration.sample());
|
||||
|
||||
vms.addAll(generateVMGroup(vmsInGroup, lastStartTime, lastStartTime+duration));
|
||||
lastStartTime += Math.floor(rStartTime.sample());
|
||||
}
|
||||
|
||||
return vms;
|
||||
}
|
||||
|
||||
public List<LinkSpec> generateLinks() {
|
||||
// Dummy links
|
||||
List<LinkSpec> links = new ArrayList<LinkSpec>();
|
||||
|
||||
links.add(new LinkSpec("default", "vm01","vm02", null));
|
||||
links.add(new LinkSpec("default", "vm02","vm01", null));
|
||||
links.add(new LinkSpec("default", "vm02","vm03", null));
|
||||
links.add(new LinkSpec("default", "vm03","vm02", null));
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
public static double round(double value, int places) {
|
||||
if (places < 0) throw new IllegalArgumentException();
|
||||
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(places, RoundingMode.HALF_UP);
|
||||
return bd.doubleValue();
|
||||
//return value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user