-
Notifications
You must be signed in to change notification settings - Fork 1
Amazon EC2
Previously, we modeled an imaginary service in order to introduce some functionalities of the API. Now, let's try to model a service with a pricing method little bit more complex: Amazon's EC2 m3.medium On Demand Virtual Machine.

Let's begin by creating the Service instance and populating it with some features, just like we did on the [Simple Example](Simple Example):
//first, create the services
Service s1 = new Service();
s1.setName("m3.medium-OD");
//64 bits 1 3 3,75 1 x 4 SSD*6 – Moderada
QualitativeValue Arch = new QualitativeValue();
Arch.addType(CLOUDEnum.BIT64.getConceptURI());
Arch.setHasLabel("64Bits");
s1.addQualFeature(Arch);
QuantitativeValue CPUCores=null,CPUSpeed=null;
CPUCores =new QuantitativeValue();
CPUSpeed = new QuantitativeValue();
CPUCores.addType(CLOUDEnum.CPUCORES.getConceptURI());
CPUCores.setValue(1);
CPUSpeed.addType(CLOUDEnum.CPUSPEED.getConceptURI());
CPUSpeed.setValue(3);
CPUSpeed.setUnitOfMeasurement("ECU");//EC2 Compute Unit
s1.addQuantFeature(CPUCores);
s1.addQuantFeature(CPUSpeed);
// /MEMORYSIZE
QuantitativeValue MemorySize = new QuantitativeValue();
MemorySize.addType(CLOUDEnum.MEMORYSIZE.getConceptURI());
MemorySize.setValue(3.75);
MemorySize.setUnitOfMeasurement("E34");//GB
s1.addQuantFeature(MemorySize);
.
.
Now, we need to create the Offering instance that'll associate the service's description with its PricePlan. As previously mentioned, the PricePlan class is responsible for modeling the service's pricing method and calculating it's total cost based on the customer's preferences.
Offering of = new Offering();
of.addService(s1);
of.setName("m3.medium-OD Offering");
PricePlan pp = new PricePlan();
of.setPricePlan(pp);
pp.setName("PricePlan-m3.medium-OD");
As you already know, a PricePlan is composed by one or more PriceComponents. These PriceComponents represent the billable attributes of the service. In the [Simple Example](Simple Example), a single PriceComponent was enough to model the cost of the service since it only had one billable attribute: the amount of time that the customer is renting the service.
Amazon EC2 Virtual Machine's have a cost per hour fee which, like in the [Simple Example](Simple Example), can be modeled through a PriceComponent(and a PriceFunction) and a simple mathematical expression: NumberOfHours * CostPHour. Aside its cost per hour fee, there's at least another attribute that influences the cost of the service: Data transferrals. Looking at their pricing table for data transfers we can identify these three components:
- Pricing Data Transfer IN To Amazon EC2 From
- Data Transfer OUT From Amazon EC2 To
- Data Transfer OUT From Amazon EC2 To Internet
For this example, I focused on the last component since, from a technical perspective, all three of them are modeled in the same way.

To model the costs of data transfers we need to create a new PriceComponent however, the mathematical expression that calculates its cost is far more complex than the mathematical expression that calculates the cost per hour of the virtual machine:
- Each month, the customer has 1 free Gb
- Each following Gb up to 10Tb costs 0.12
- Each Gb from 10Tb up to 40Tb costs 0.09
- Each Gb from 40Tb up to 100Tb costs 0.07
- Each Gb from 100Tb up to 350Tb costs 0.05
NOTE: 350Tb is the limite due to the lack of information on their website
It's simple to identify the variables of the mathematical expression. Depending on the quantity of data transferred, the price per the Gb changes:
- Usage Variables - Amount of data that the user expects to transfer from the Virtual Machine to the Internet per month
- Provider Variables - Four in total, the costs per Gb
Regarding the mathematical expression, using IF-ELSE conditions simplifies its construction. For example (consider that GBout is the amount of data that the customer expects to transfer from the virtual machine to the internet per month ):
IF GBout <= 1, price=0
ELSE IF (GBOut > 1) && (GBOut <= 10*1024) , price=(GBout-1)*0.12
ELSE IF (GBOut > 10*1024) && (GBOut <= 40*1024) , price=(10*1024*0.012) + ((GBOut - 10*1024 - 1)*0.09)
ELSE IF (GBOut > 40*1024) && (GBOut <= 100*1024) , price = (10*1024*0.012) + (40*1024*0.09) + ((GBOut - 10*1024 - 40*1024 - 1)*0.07)
ELSE IF (GBOut > 100*1024) && (GBOut <= 350*1024) , price = (10*1024*0.012) + (40*1024*0.09) + (100*1024*0.07) + ((GBOut - 10*1024 - 40*1024 - 100*1024 - 1)*0.05)
The LinkedUSDL Pricing API supports the usage of IF-ELSE conditions in the mathematical expression's String thus, mapping this type mathematical expression through the API becomes quite easy:
data_cost_pf.setStringFunction(" IF ("+gbout.getName()+"<= 1) ; 1 * 0.00 ~"+
" ELSEIF"+gbout.getName()+" > 1 && "+gbout.getName()+" <= 10*1024 ; 1*0.00 + ("+gbout.getName()+"-1) * "+price10.getName()+" ~ "
+ "ELSEIF ("+gbout.getName()+" > 10*1024) && ("+gbout.getName()+"<= 40*1024) ; 1*0.00 + 10*1024*"+price10.getName()+" + ("+gbout.getName()+"-10*1024-1)*"+price40.getName()+" ~ "
+ "ELSEIF ("+gbout.getName()+" >= 40*1024) && ("+gbout.getName()+" < 100*1024) ; 1*0.00 + 10*1024*"+price10.getName()+" + 40*1024*"+price40.getName()+" + ("+gbout.getName()+"-1-10*1024-40*1024)*"+price100.getName()+" ~ "
+ "ELSEIF ("+gbout.getName()+" >= 100*1024) && ("+gbout.getName()+" < 350*1024) ; 1*0.00 + 10*1024*"+price10.getName()+" + 40*1024*"+price40.getName()+" + 100*1024*"+price100.getName()+" + ("+gbout.getName()+"-1-10*1024-40*1024-100*1024)*"+price350.getName()+"");
When modeling IF-ELSE mathematical expressions, it's important to keep in mind these two restrictions:
- Each IF,ELSEIF,ELSE condition needs to be separated by the "~" character.
- The Condition and its behaviour need to be separated by the ";" character.
The full modeling of the data transfer PriceComponent:
PriceComponent traffic_pc = new PriceComponent();//Component responsible for calculating the total price to pay related only to the Data transferral on Amazon EC2
pp.addPriceComponent(traffic_pc);
traffic_pc.setName("DataCostPC-PPm3.medium-OD");
PriceFunction data_cost_pf = new PriceFunction();
traffic_pc.setPriceFunction(data_cost_pf);
data_cost_pf.setName("m3.medium-OD-data_transferrals_cost");
Provider price10 = new Provider();
data_cost_pf.addProviderVariable(price10);
price10.setName("price10"+"TIME"+System.nanoTime());
QuantitativeValue valb = new QuantitativeValue();
price10.setValue(valb);
valb.setValue(0.12);
valb.setUnitOfMeasurement("USD");
Provider price40 = new Provider();
data_cost_pf.addProviderVariable(price40);
price40.setName("price40"+"TIME"+System.nanoTime());
QuantitativeValue valc = new QuantitativeValue();
price40.setValue(valc);
valc.setValue(0.09);
valc.setUnitOfMeasurement("USD");
Provider price100 = new Provider();
data_cost_pf.addProviderVariable(price100);
price100.setName("price100"+"TIME"+System.nanoTime());
QuantitativeValue vald = new QuantitativeValue();
price100.setValue(vald);
vald.setValue(0.07);
vald.setUnitOfMeasurement("USD");
Provider price350 = new Provider();
data_cost_pf.addProviderVariable(price350);
price350.setName("price350"+"TIME"+System.nanoTime());
QuantitativeValue vale = new QuantitativeValue();
price350.setValue(vale);
vale.setValue(0.05);
vale.setUnitOfMeasurement("USD");
Usage gbout = new Usage();
data_cost_pf.addUsageVariable(gbout);
gbout.setName("gbout"+"TIME"+System.nanoTime());
gbout.setComment("Total GB of data that you expect to send out from Amazon EC2 to the internet.");
data_cost_pf.setStringFunction(" IF ("+gbout.getName()+"<= 1) ; 1 * 0.00 ~"
+ " ELSEIF"+gbout.getName()+" > 1 && "+gbout.getName()+" <= 10*1024 ; 1*0.00 + ("+gbout.getName()+"-1) * "+price10.getName()+" ~ "
+ "ELSEIF ("+gbout.getName()+" > 10*1024) && ("+gbout.getName()+"<= 40*1024) ; 1*0.00 + 10*1024*"+price10.getName()+" + ("+gbout.getName()+"-10*1024-1)*"+price40.getName()+" ~ "
+ "ELSEIF ("+gbout.getName()+" >= 40*1024) && ("+gbout.getName()+" < 100*1024) ; 1*0.00 + 10*1024*"+price10.getName()+" + 40*1024*"+price40.getName()+" + ("+gbout.getName()+"-1-10*1024-40*1024)*"+price100.getName()+" ~ "
+ "ELSEIF ("+gbout.getName()+" >= 100*1024) && ("+gbout.getName()+" < 350*1024) ; 1*0.00 + 10*1024*"+price10.getName()+" + 40*1024*"+price40.getName()+" + 100*1024*"+price100.getName()+" + ("+gbout.getName()+"-1-10*1024-40*1024-100*1024)*"+price350.getName()+"");
For this example, these two PriceComponents are enough to introduce the modeling of a service with a somewhat complex pricing method. Now that we've finished modeling the service and its PricePlan, we can call the WriteToModel() function to create our semantic representation:
Model instance = jmodel.WriteToModel();//transform the java models to a semantic representation
File outputFile = new File("./DebuggingFiles/amazonOD.ttl");
if (!outputFile.exists()) {
outputFile.createNewFile();
}
FileOutputStream out = new FileOutputStream(outputFile);
instance.write(out, "Turtle");
out.close();
We can use the LinkedUSDL Pricing API to test the model and use Amazon's EC2 calculator to compare the obtained output with the real cost of the service:
Comparing both results we can see that the modeling of the service was successful!
The full source code for this example can be reviewed here.
To learn how you can use/edit the models created by the API checkout the next tutorial!
#####[Next: Loading and testing the Semantic models](Using and Editing the created model)