/*******************************************************************************
* Copyright 2012 I3M-GRyCAP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.grycap.vmrc.utils.parsing;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import org.apache.log4j.Logger;
import org.grycap.vmrc.entity.Application;
import org.grycap.vmrc.entity.OS;
import org.grycap.vmrc.entity.VMI;
public class VMIDescriptor {
private Hashtable<String, List<VMIStatement>> descHard;
private Hashtable<String, List<VMIStatement>> descSoft;
private transient Logger log;
public VMIDescriptor() {
this.log = Logger.getLogger(getClass());
initTables();
}
private void initTables() {
this.descHard = new Hashtable<String, List<VMIStatement>>();
this.descSoft = new Hashtable<String, List<VMIStatement>>();
}
public VMI parseVMIFromString(String vmiDesc) throws Exception {
initTables();
parseFromString(vmiDesc);
return toVMI();
}
public void parseFromFile(String fileName) throws Exception {
String vmiDesc = loadFromFile(fileName);
parseFromString(vmiDesc);
}
public void parseFromString(String vmiDesc) throws Exception {
Scanner scanner = new Scanner(vmiDesc);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
VMIStatement vs = parseVMIStatement(line);
insertStatement(vs);
}
}
public Hashtable<String, List<VMIStatement>> getHardRequirements(){
return this.descHard;
}
protected VMIStatement parseVMIStatement(String line) throws Exception {
try{
log.debug("About to parse VMI Descriptor line: " + line);
VMIStatement vs = new VMIStatement(line);
log.debug("Successfully parsed VMI Descriptor line: " + line);
return vs;
}catch(UnableToParseException ex){
log.error("Could not parse VMIStatement " + line + ". Reason: " + ex.getMessage());
throw ex;
}
}
private void insertStatement(VMIStatement vp) {
Hashtable<String, List<VMIStatement>> ht = vp.isSoft() ? this.descSoft : this.descHard;
List<VMIStatement> l = ht.get(vp.getAttribute());
if (l == null) {
l = new ArrayList<VMIStatement>();
}
l.add(vp);
ht.put(vp.getAttribute(), l);
}
private String loadFromFile(String textFilePath) throws IOException {
String result;
FileInputStream fis = new FileInputStream(textFilePath);
byte[] b = new byte[fis.available()];
fis.read(b);
fis.close();
result = new String(b);
return result;
}
private String toString(Hashtable<String, List<VMIStatement>> ht) {
String str = "";
Enumeration<String> e = ht.keys();
while (e.hasMoreElements()) {
String key = e.nextElement();
List<VMIStatement> l = ht.get(key);
for (VMIStatement v : l) {
str += v + "\n";
}
}
return str;
}
public String toString() {
return toString(this.descHard) + toString(this.descSoft);
}
public void setName(String vmiName){
List<VMIStatement> l = this.descHard.get("system.name");
l.get(0).setValue(vmiName);
}
private String getAttributeValue(String attr) {
String value = "";
List<VMIStatement> l = this.descHard.get(attr);
if (l == null) {
log.error("NULL");
} else {
value = l.get(0).getValue().toString();
}
return value;
}
private boolean hasAttributeValue(String attr){
return getAttributeValue(attr) != null;
}
public VMI toVMI() {
VMI vmi = new VMI();
if(hasAttributeValue("system.name")) vmi.setName(getAttributeValue("system.name"));
if (hasAttributeValue("system.hypervisor")) vmi.setHypervisor(getAttributeValue("system.hypervisor"));
if (hasAttributeValue("system.location")) vmi.setLocation(getAttributeValue("system.location"));
if (hasAttributeValue("cpu.arch")) vmi.setArch(getAttributeValue("cpu.arch"));
if (hasAttributeValue("disk.size")) vmi.setDiskSize(getAttributeValue("disk.size"));
if (hasAttributeValue("disk.os.name")){
OS os = new OS();
os.setName(getAttributeValue("disk.os.name"));
os.setFlavour(getAttributeValue("disk.os.flavour"));
os.setVersion(getAttributeValue("disk.os.version"));
vmi.setOs(os);
}
if (hasAttributeValue("disk.os.credentials.user")) vmi.setUserLogin(getAttributeValue("disk.os.credentials.user"));
if (hasAttributeValue("disk.os.credentials.password")) vmi.setUserPassword(getAttributeValue("disk.os.credentials.password"));
List<VMIStatement> l = this.descHard.get("disk.applications");
if (l!=null) {
Set<Application> setApps = new HashSet<Application>();
for (VMIStatement vs : l) {
setApps.add((Application) vs.getValue());
}
vmi.setApplications(setApps);
}
return vmi;
}
public int rankVMI(VMI vmi) {
List<VMIStatement> l;
int rankValue = 0;
log.debug("Ranking VMI " + vmi.getName());
// Check disk.os.version
boolean satisfiesOsVersion = false;
if ((l = this.descHard.get("disk.os.version")) != null) {
VMIStatement vs = l.get(0);
if (vmi.getOs().matchesVersion(vs.getValue().toString(), vs.getOperator())) {
log.info("VMI satisfies the VMIDescriptor for disk.os.version");
satisfiesOsVersion = true;
}
} else satisfiesOsVersion = true;
// Check hard apps
boolean satisfiesHardApps = true;
log.debug("Checking if " + vmi.getName() + " satisfies the application hard requirements");
if ((l = this.descHard.get("disk.applications")) != null) {
for (VMIStatement vs2 : l) {
log.debug("Checking statement " + vs2);
Application app = (Application) vs2.getValue();
if (!vmi.matchesApplication(app, vs2.getOperator())) {
log.debug("Statement " + vs2 + " cannot be met by VMI " + vmi.getName());
satisfiesHardApps = false;
break;
}
}
}
if (!satisfiesHardApps || !satisfiesOsVersion)
return -1;
/*
* Checking soft requirements. Currently only soft requirements for apps
* are considered
*/
// Check hard apps
// boolean satisfiesSoftApps = true;
if ((l = this.descSoft.get("disk.applications")) != null) {
for (VMIStatement vs2 : l) {
log.debug("Checking soft VMIStatement " + vs2);
Application app = (Application) vs2.getValue();
if (vmi.matchesApplication(app, vs2.getOperator())) {
log.debug("The Rank Value of the VMIStatement is: " + vs2.getRankValue());
rankValue += vs2.getRankValue();
}
}
}
return rankValue;
}
}