package com.sixsq.slipstream.persistence;
/*
* +=================================================================+
* SlipStream Server (WAR)
* =====
* Copyright (C) 2013 SixSq Sarl (sixsq.com)
* =====
* 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.
* -=================================================================-
*/
import java.util.List;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Query;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementMap;
import com.sixsq.slipstream.exceptions.NotImplementedException;
import com.sixsq.slipstream.exceptions.ValidationException;
/**
* Unit test:
*
* @see ServiceCatalogTest
*
*/
@SuppressWarnings("serial")
@Entity
@NamedQueries({
@NamedQuery(name = "byCloud", query = "SELECT sc FROM ServiceCatalog sc WHERE sc.cloud = :cloud"),
@NamedQuery(name = "all", query = "SELECT sc FROM ServiceCatalog sc") })
public class ServiceCatalog extends
Parameterized<ServiceCatalog, ServiceCatalogParameter> {
private final static String CATEGORY_OVERALL_CAPACITY = "Overall capacity";
private final static String CATEGORY_SINGLE_VM_CAPACITY = "Single VM capacity";
private final static String CATEGORY_PRICE = "Price";
private final static String CATEGORY_LOCATION = "Locations";
private final static String CATEGORY_SUPPLIERS_CATALOG = "Suppliers catalogue";
public final static String RESOURCE_URL_PREFIX = "service_catalog/";
@Attribute
@Id
private String resourceUri;
@Attribute
private String cloud;
@SuppressWarnings("unused")
private ServiceCatalog() {
}
public ServiceCatalog(String cloud) {
setName(cloud);
}
@Override
@ElementMap(name = "parameters", required = false, valueType = ServiceCatalogParameter.class)
protected void setParameters(Map<String, ServiceCatalogParameter> parameters) {
this.parameters = parameters;
}
@Override
@ElementMap(name = "parameters", required = false, valueType = ServiceCatalogParameter.class)
public Map<String, ServiceCatalogParameter> getParameters() {
return parameters;
}
public String getCloud() {
return cloud;
}
@Override
public void validate() throws ValidationException {
validateParameters();
}
// Only used by tests
@SuppressWarnings("unchecked")
public static List<ServiceCatalog> list(String cloud) {
EntityManager em = PersistenceUtil.createEntityManager();
Query q = em.createNamedQuery("byCloud");
q.setParameter("cloud", cloud);
List<ServiceCatalog> list = q.getResultList();
em.close();
return list;
}
@SuppressWarnings("unchecked")
public static List<ServiceCatalog> listall() {
EntityManager em = PersistenceUtil.createEntityManager();
Query q = em.createNamedQuery("all");
List<ServiceCatalog> list = q.getResultList();
em.close();
return list;
}
@Override
public void setContainer(ServiceCatalogParameter parameter) {
parameter.setContainer(this);
}
@Override
public String getResourceUri() {
return constructResourceUri(getCloud());
}
@Override
public String getName() {
return getCloud();
}
@Override
public void setName(String cloud) {
this.cloud = cloud;
this.resourceUri = constructResourceUri(cloud);
}
public static String constructResourceUri(String name) {
return RESOURCE_URL_PREFIX + name;
}
public static ServiceCatalog loadByCloud(String cloud) {
return load(constructResourceUri(cloud));
}
public static ServiceCatalog load(String resourceUrl) {
EntityManager em = PersistenceUtil.createEntityManager();
ServiceCatalog sc = em.find(ServiceCatalog.class, resourceUrl);
em.close();
return sc;
}
public static ServiceCatalog load() {
throw new NotImplementedException();
}
@Override
public ServiceCatalog store() {
return (ServiceCatalog) super.store();
}
public void populateDefinedParameters() throws ValidationException {
for (DefinedParameters dp : DefinedParameters.values()) {
String name = cloud + "." + dp.getName();
ServiceCatalogParameter scp = getParameter(name);
if (scp == null) {
scp = new ServiceCatalogParameter(name, "", dp.getDescription());
}
scp.setCategory(dp.getCategory());
scp.setDescription(dp.getDescription());
scp.setInstructions(dp.getInstruction());
scp.setType(dp.getType());
scp.setReadonly(true);
scp.setMandatory(true);
setParameter(scp);
}
}
public void clearParameters() {
for (ServiceCatalogParameter p : getParameters().values()) {
p.setContainer(null);
}
}
/**
* Encoded names. '_' here corresponds to '.' in config file.
*/
public enum DefinedParameters {
// Overall capacity
OVERALL_CAPACITY_CPU(
"The number of CPU cores (currently) available within (the relevant part of) the supplier’s IaaS environment",
CATEGORY_OVERALL_CAPACITY, "Value: an integer, and possibly approximate, number, e.g. 1,000; Explanation: to give an indication of the scale of the environment available for use"),
OVERALL_CAPACITY_RAM(
"Nature: the amount of random-access memory in total; Value: expressed in relevant terms, e.g. 10 TB; Explanation: the amount of memory available across the installation as a whole. See below for what is available on any one system",
CATEGORY_OVERALL_CAPACITY),
OVERALL_CAPACITY_STORAGE(
"Nature: the amount of persistent storage (e.g. SSD, disk, tape) available within that supplier’s environment; Value: expressed in relevant terms, e.g. 10 PB; Explanation: possibly multiple values, e.g. per technology type",
CATEGORY_OVERALL_CAPACITY),
// Single vm capacity
SINGLE_VM_MIN_CPU(
"Nature: the minimum number of CPU cores with which this supplier’s VMs can be configured; Value: an integer number, e.g. 1; Explanation: to give an indication of the minimum configurable environment",
CATEGORY_SINGLE_VM_CAPACITY),
SINGLE_VM_MAX_CPU(
"Nature: the maximum number of CPU cores with which this supplier’s VMs can be configured; Value: an integer number, e.g. 8; Explanation: to give an indication of the maximum configurable environment",
CATEGORY_SINGLE_VM_CAPACITY),
SINGLE_VM_MIN_RAM(
"Nature: the minimum amount of random-access memory (currently) available within VMs; Value: expressed in relevant terms, e.g. 128 GB; Explanation: the amount of memory available to any one VM within the supplier’s IaaS environment",
CATEGORY_SINGLE_VM_CAPACITY),
SINGLE_VM_MAX_RAM(
"Nature: the maximum amount of random-access memory (currently) available within VMs; Value: expressed in relevant terms, e.g. 128 GB; Explanation: the amount of memory available to any one VM within the supplier’s IaaS environment",
CATEGORY_SINGLE_VM_CAPACITY),
SINGLE_VM_STORAGE_VOLATILE(
"Nature: the amount of volatile storage available locally to that VM; Value: expressed in relevant terms, e.g. 500 GB; Explanation: the amount of “scratch” space, which could be used, e.g. to extend the random access memory of a VM. Local disk space is typically slower than ram but faster than persistent storage space",
CATEGORY_SINGLE_VM_CAPACITY),
SINGLE_VM_STORAGE_PERSISTENT(
"Nature: the amount of persistent storage (e.g. SSD, disk, tape) available to that VM; Storage access method (e.g. local or network); Storage type: block device or network mount; Value: expressed in relevant terms, e.g. 10 TB per drive/block device; Resilience level or equivalent eg. RAID6, RAID5 etc. Explanation: possibly multiple values, e.g. per technology type. This presumes that storage is associated with a particular VM, i.e. it is locally attached or via a restricted network. Otherwise, it could be up to the total figure, as above",
CATEGORY_SINGLE_VM_CAPACITY),
// Price
PRICE_CHARGING_UNIT(
"Nature: the unit used for charging; Value: the pricing unit, e.g. GHz, portion of CPU chip, etc.; Explanation: this could vary per supplier, as there is no standard unit. Work from the ODCA or Deutsche Boerse could be used to derive such a standard, at least for comparative purposes, in the future",
CATEGORY_PRICE),
PRICE_CHARGING_PERIOD(
"Nature: the period used for charging; Value: the pricing period, e.g. hour, month; Explanation: this could vary per resource, e.g. CPU per hour, storage per month",
CATEGORY_PRICE),
PRICE_CPU_PER_HOUR(
"Nature: the price for use of a unit of processing per period, e.g. hour; Value: the price in euros, e.g. €0.05",
CATEGORY_PRICE),
PRICE_RAM_PER_HOUR(
"Nature: the price for use of a unit (e.g. 1 GB) of memory per hour; Value: the price in euros, e.g. €0.05",
CATEGORY_PRICE),
PRICE_STORAGE_PER_HOUR(
"Nature: the price for use of a unit (e.g. 1 GB) of storage per hour; Value: the price in euros, e.g. €0.0005; Explanation: note that is possible that storage is either associated with a particular VM or as a generally-available resource",
CATEGORY_PRICE),
PRICE_IO(
"Nature: the price for transmitting a unit (e.g. 1 GB) in or out of the environment; Value: the price in euros, e.g. €0.30",
CATEGORY_PRICE),
// Location
LOCATION(
"Nature: geographical location of relevant data centre(s); Value: ISO-standard country code and name for cloud location and operational company location, e.g. NL The Netherlands; Explanation: currently, data protection legislation differs per country",
CATEGORY_LOCATION),
// Suppliers catalog
SUPPLIERS_CATALOG(
"Nature: URL of web site with further details; Value: e.g. http://example.com",
CATEGORY_SUPPLIERS_CATALOG);
private final String description;
private final String category;
private final String instructions;
private final ParameterType type;
private final boolean readonly;
public String getInstructions() {
return instructions;
}
private DefinedParameters(String description, String category) {
this.description = description;
this.category = category;
this.instructions = "";
this.type = ParameterType.String;
this.readonly = true;
}
private DefinedParameters(String description, String category,
String instructions) {
this.description = description;
this.category = category;
this.instructions = instructions;
this.type = ParameterType.String;
this.readonly = true;
}
public String getInstruction() {
return instructions;
}
public String getDescription() {
return description;
}
public String getCategory() {
return category;
}
public void validate(String value) {
if (isReadonly()) {
return;
}
if (getType() == ParameterType.Boolean && value == null) {
return;
}
if (value == null || "".equals(value)) {
throw new IllegalArgumentException(
"value cannot be empty or null");
}
}
public ParameterType getType() {
return type;
}
public boolean isReadonly() {
return readonly;
}
/**
* Convert the enum name into parameter name where word separators are
* converted from _ to . and lower cased.
*/
public String getName() {
return name().replace("_", ".").toLowerCase();
}
}
}