From ea285258528df54d3291a4d81d2258b960699348 Mon Sep 17 00:00:00 2001
From: Albert Louis Rossi
Date: Mon, 7 Aug 2023 09:27:10 -0500
Subject: [PATCH] dcache-common: add QoS Json policy objects
Motivation:
Implement version 1 of the QoS Policy/Rule engine.
Modification:
This patch adds the various JSON objects used
to define a QoS policy.
A parsing unit test is included.
Result:
The QoS policy (schema) is now defined.
Target: master
Patch: https://rb.dcache.org/r/14024/
Acked-by: Tigran
---
.../qos/DefaultQoSDiskSpecification.java | 139 +++++++++
.../qos/DefaultQoSPolicyJsonDeserializer.java | 148 ++++++++++
.../qos/DefaultQoSTapeSpecification.java | 123 ++++++++
.../org/dcache/qos/QoSDiskSpecification.java | 82 ++++++
.../org/dcache/qos/QoSHsmSpecification.java | 80 ++++++
.../main/java/org/dcache/qos/QoSPolicy.java | 119 ++++++++
.../main/java/org/dcache/qos/QoSState.java | 128 +++++++++
.../java/org/dcache/qos/QoSStorageMedium.java | 64 +++++
.../qos/QoSStorageMediumSpecification.java | 83 ++++++
.../java/org/dcache/qos/QoSPolicyTest.java | 270 ++++++++++++++++++
10 files changed, 1236 insertions(+)
create mode 100644 modules/common/src/main/java/org/dcache/qos/DefaultQoSDiskSpecification.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/DefaultQoSPolicyJsonDeserializer.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/DefaultQoSTapeSpecification.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/QoSDiskSpecification.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/QoSHsmSpecification.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/QoSPolicy.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/QoSState.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/QoSStorageMedium.java
create mode 100644 modules/common/src/main/java/org/dcache/qos/QoSStorageMediumSpecification.java
create mode 100644 modules/common/src/test/java/org/dcache/qos/QoSPolicyTest.java
diff --git a/modules/common/src/main/java/org/dcache/qos/DefaultQoSDiskSpecification.java b/modules/common/src/main/java/org/dcache/qos/DefaultQoSDiskSpecification.java
new file mode 100644
index 00000000000..ab269496116
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/DefaultQoSDiskSpecification.java
@@ -0,0 +1,139 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A simple disk specification. Type may or may not be supported by the QoS verifier.
+ */
+public class DefaultQoSDiskSpecification extends QoSDiskSpecification {
+
+ private static final long serialVersionUID = -4741659925401058789L;
+
+ /**
+ * e.g., "SSD", "Spinning"
+ */
+ private String type;
+
+ /**
+ * Total number of copies on this medium.
+ */
+ private Integer numberOfCopies;
+
+ /**
+ * How the copies should be partitioned across the media instances, if there
+ * are more than one.
+ */
+ private List partitionKeys;
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public Integer getNumberOfCopies() {
+ return numberOfCopies;
+ }
+
+ @Override
+ public List getPartitionKeys() {
+ return partitionKeys;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public void setNumberOfCopies(Integer numberOfCopies) {
+ this.numberOfCopies = numberOfCopies;
+ }
+
+ public void setPartitionKeys(List partitionKeys) {
+ this.partitionKeys = partitionKeys;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DefaultQoSDiskSpecification)) {
+ return false;
+ }
+
+ DefaultQoSDiskSpecification other = (DefaultQoSDiskSpecification) obj;
+
+ if ((type == null && other.type != null) ||
+ type != null && !type.equals(other.type)) {
+ return false;
+ }
+
+ if ((numberOfCopies == null && other.numberOfCopies != null) ||
+ (numberOfCopies != null && numberOfCopies != other.numberOfCopies)) {
+ return false;
+ }
+
+ return (partitionKeys == null && other.partitionKeys == null) ||
+ partitionKeys != null && partitionKeys.equals(other.partitionKeys);
+ }
+
+ public int hashCode() {
+ return Objects.hash(type, numberOfCopies, partitionKeys);
+ }
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/DefaultQoSPolicyJsonDeserializer.java b/modules/common/src/main/java/org/dcache/qos/DefaultQoSPolicyJsonDeserializer.java
new file mode 100644
index 00000000000..8becfe64137
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/DefaultQoSPolicyJsonDeserializer.java
@@ -0,0 +1,148 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ * Uses the default specification objects to populate the policy from its JSON representation.
+ */
+public class DefaultQoSPolicyJsonDeserializer {
+
+ private static final String NAME = "name";
+ private static final String STATES = "states";
+ private static final String DURATION = "duration";
+ private static final String MEDIA = "media";
+ private static final String STORAGE_ELEMENT = "storageElement";
+ private static final String TYPE = "type";
+ private static final String NUMBER_OF_COPIES = "numberOfCopies";
+ private static final String PARTITION_KEYS = "partitionKeys";
+ private static final String INSTANCE = "instance";
+
+ public static QoSPolicy fromJsonString(String json) {
+ return deserializePolicy(new JSONObject(json));
+ }
+
+ private static QoSPolicy deserializePolicy(JSONObject object) {
+ QoSPolicy policy = new QoSPolicy();
+ policy.setName(object.getString(NAME));
+ JSONArray stateArray = object.getJSONArray(STATES);
+ int len = stateArray.length();
+ List states = new ArrayList<>();
+ for (int i = 0; i < len; ++i) {
+ states.add(deserializeState(stateArray.getJSONObject(i)));
+ }
+ policy.setStates(states);
+ return policy;
+ }
+
+ private static QoSState deserializeState(JSONObject jsonState) {
+ QoSState state = new QoSState();
+ if (jsonState.has(DURATION)) {
+ state.setDuration(jsonState.getString(DURATION));
+ }
+ List media = new ArrayList<>();
+ JSONArray mediaArray = jsonState.getJSONArray(MEDIA);
+ int len = mediaArray.length();
+ for (int i = 0; i < len; ++i) {
+ media.add(deserializeStorageElement(mediaArray.getJSONObject(i)));
+ }
+ state.setMedia(media);
+ return state;
+ }
+
+ private static QoSStorageMediumSpecification deserializeStorageElement(JSONObject jsonMedia) {
+ switch(jsonMedia.getEnum(QoSStorageMedium.class, STORAGE_ELEMENT)) {
+ case DISK:
+ DefaultQoSDiskSpecification diskSpec = new DefaultQoSDiskSpecification();
+ if (jsonMedia.has(TYPE)) {
+ diskSpec.setType(jsonMedia.getString(TYPE));
+ }
+ diskSpec.setNumberOfCopies(jsonMedia.getInt(NUMBER_OF_COPIES));
+ if (jsonMedia.has(PARTITION_KEYS)) {
+ List partitionKeys = new ArrayList<>();
+ JSONArray keyArray = jsonMedia.getJSONArray(PARTITION_KEYS);
+ int len = keyArray.length();
+ for (int i = 0; i < len; ++i) {
+ partitionKeys.add(keyArray.getString(i));
+ }
+ diskSpec.setPartitionKeys(partitionKeys);
+ }
+ return diskSpec;
+ case HSM:
+ default:
+ DefaultQoSTapeSpecification tapeSpec = new DefaultQoSTapeSpecification();
+ if (jsonMedia.has(TYPE)) {
+ tapeSpec.setType(jsonMedia.getString(TYPE));
+ }
+ if (jsonMedia.has(INSTANCE)) {
+ tapeSpec.setInstance(jsonMedia.getString(INSTANCE));
+ }
+ return tapeSpec;
+ }
+ }
+
+ private DefaultQoSPolicyJsonDeserializer() {
+ // static singleton
+ }
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/DefaultQoSTapeSpecification.java b/modules/common/src/main/java/org/dcache/qos/DefaultQoSTapeSpecification.java
new file mode 100644
index 00000000000..1427ba6b84f
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/DefaultQoSTapeSpecification.java
@@ -0,0 +1,123 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import java.util.Objects;
+
+/**
+ * A simple tape specification.
+ */
+public class DefaultQoSTapeSpecification extends QoSHsmSpecification {
+
+ private static final long serialVersionUID = -7122977962254426993L;
+
+ private String instance;
+
+ /**
+ * E.g., "Enstore", "CTA", etc.
+ */
+ private String type;
+
+ @Override
+ public String getInstance() {
+ return instance;
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ /*
+ * Currently, we only allow one copy per tape system instance.
+ */
+ @Override
+ public Integer getNumberOfCopies() {
+ return 1;
+ }
+
+ public void setInstance(String instance) {
+ this.instance = instance;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DefaultQoSTapeSpecification)) {
+ return false;
+ }
+
+ DefaultQoSTapeSpecification other = (DefaultQoSTapeSpecification) obj;
+
+ if ((type == null && other.type != null) ||
+ type != null && !type.equals(other.type)) {
+ return false;
+ }
+
+ return (instance == null && other.instance == null) ||
+ instance != null && instance.equals(other.instance);
+ }
+
+ public int hashCode() {
+ return Objects.hash(type, instance);
+ }
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/QoSDiskSpecification.java b/modules/common/src/main/java/org/dcache/qos/QoSDiskSpecification.java
new file mode 100644
index 00000000000..c2205a0b4ac
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/QoSDiskSpecification.java
@@ -0,0 +1,82 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import static org.dcache.qos.QoSStorageMedium.DISK;
+
+import java.util.List;
+
+public abstract class QoSDiskSpecification implements QoSStorageMediumSpecification {
+
+ /**
+ * In order to get this to appear in the JSON object, there needs to be
+ * an instance variable.
+ */
+ private final QoSStorageMedium storageMedium = DISK;
+
+ /**
+ * @return if more than one copy is to be kept on this medium, the keys used to distribute them.
+ */
+ public abstract List getPartitionKeys();
+
+ public final QoSStorageMedium getStorageMedium() {
+ return storageMedium;
+ }
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/QoSHsmSpecification.java b/modules/common/src/main/java/org/dcache/qos/QoSHsmSpecification.java
new file mode 100644
index 00000000000..c77a54fb12d
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/QoSHsmSpecification.java
@@ -0,0 +1,80 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import static org.dcache.qos.QoSStorageMedium.HSM;
+
+public abstract class QoSHsmSpecification implements QoSStorageMediumSpecification {
+
+ /**
+ * In order to get this to appear in the JSON object, there needs to be
+ * an instance variable.
+ */
+ private final QoSStorageMedium storageMedium = HSM;
+
+ /**
+ * @return an identifier (e.g., URI), distinguishing a particular instance of the HSM.
+ */
+ public abstract String getInstance();
+
+ public final QoSStorageMedium getStorageMedium() {
+ return storageMedium;
+ }
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/QoSPolicy.java b/modules/common/src/main/java/org/dcache/qos/QoSPolicy.java
new file mode 100644
index 00000000000..48f04e959b5
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/QoSPolicy.java
@@ -0,0 +1,119 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * This is the template used to govern a file's QoS lifetime.
+ */
+public class QoSPolicy implements Serializable {
+
+ private static final long serialVersionUID = -3271665359959015633L;
+
+ /**
+ * Specifies a particular policy as established by the administrator.
+ * A file can have only one policy at a time. The names must be
+ * unique within the dCache instance.
+ */
+ private String name;
+
+ /**
+ * An ordered list of states determining the transitions from one set of media to another
+ * that the file should undergo during its lifetime.
+ */
+ private List states;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List getStates() {
+ return states;
+ }
+
+ public void setStates(List states) {
+ this.states = states;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof QoSPolicy)) {
+ return false;
+ }
+
+ QoSPolicy other = (QoSPolicy) obj;
+ if ((name == null && other.name != null) || !name.equals(other.name)) {
+ return false;
+ }
+
+ return (states == null && other.states == null) ||
+ states != null && states.equals(other.states);
+ }
+
+ public int hashCode() {
+ return Objects.hash(name, states);
+ }
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/QoSState.java b/modules/common/src/main/java/org/dcache/qos/QoSState.java
new file mode 100644
index 00000000000..bb7e1116e16
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/QoSState.java
@@ -0,0 +1,128 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents the QoS state of the file. This includes the length of time that this
+ * state should last, and the set of media specifications for the file (disk, tape, how many
+ * copies, etc.).
+ */
+public class QoSState implements Serializable {
+
+ /**
+ * Amount of time until the transition to the next state.
+ *
+ * The value is one of null
, "INF", or an ISO 8601 formatted string
+ * (https://en.wikipedia.org/wiki/ISO_8601).
+ *
+ * There is a difference between null
> and INF: the latter means
+ * this file's state (presumably the last) should be continuously checked;
+ * the former means that once the file has gone to this state, it
+ * no longer need be verified.
+ */
+ private String duration;
+
+ /**
+ * The set of media involved in this state. For instance, a file may have two
+ * specifications, one tape and one disk, with the latter specifying 2 copies,
+ * and so forth.
+ */
+ private List media;
+
+ public String getDuration() {
+ return duration;
+ }
+
+ public void setDuration(String duration) {
+ this.duration = duration;
+ }
+
+ public List getMedia() {
+ return media;
+ }
+
+ public void setMedia(List media) {
+ this.media = media;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof QoSState)) {
+ return false;
+ }
+
+ QoSState other = (QoSState) obj;
+
+ if ((duration == null && other.duration != null) ||
+ duration != null && !duration.equals(other.duration)) {
+ return false;
+ }
+
+ return (media == null && other.media == null) ||
+ media != null && media.equals(other.media);
+ }
+
+ public int hashCode() {
+ return Objects.hash(duration, media);
+ }
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/QoSStorageMedium.java b/modules/common/src/main/java/org/dcache/qos/QoSStorageMedium.java
new file mode 100644
index 00000000000..b9385a51076
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/QoSStorageMedium.java
@@ -0,0 +1,64 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+public enum QoSStorageMedium {
+ DISK,HSM
+}
diff --git a/modules/common/src/main/java/org/dcache/qos/QoSStorageMediumSpecification.java b/modules/common/src/main/java/org/dcache/qos/QoSStorageMediumSpecification.java
new file mode 100644
index 00000000000..18e2345d44d
--- /dev/null
+++ b/modules/common/src/main/java/org/dcache/qos/QoSStorageMediumSpecification.java
@@ -0,0 +1,83 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import java.io.Serializable;
+
+/**
+ * Describes a possible storage medium type.
+ */
+public interface QoSStorageMediumSpecification extends Serializable {
+
+ /**
+ * @return either DISK or HSM
+ */
+ QoSStorageMedium getStorageMedium();
+
+ /**
+ * @return a generic identifier for this medium (e.g., tape-system name, disk type, etc.)
+ */
+ String getType();
+
+ /**
+ * @return how many replicas of the file should be stored on this medium/
+ */
+ Integer getNumberOfCopies();
+}
diff --git a/modules/common/src/test/java/org/dcache/qos/QoSPolicyTest.java b/modules/common/src/test/java/org/dcache/qos/QoSPolicyTest.java
new file mode 100644
index 00000000000..1da8b3264d5
--- /dev/null
+++ b/modules/common/src/test/java/org/dcache/qos/QoSPolicyTest.java
@@ -0,0 +1,270 @@
+/*
+COPYRIGHT STATUS:
+Dec 1st 2001, Fermi National Accelerator Laboratory (FNAL) documents and
+software are sponsored by the U.S. Department of Energy under Contract No.
+DE-AC02-76CH03000. Therefore, the U.S. Government retains a world-wide
+non-exclusive, royalty-free license to publish or reproduce these documents
+and software for U.S. Government purposes. All documents and software
+available from this server are protected under the U.S. and Foreign
+Copyright Laws, and FNAL reserves all rights.
+
+Distribution of the software available from this server is free of
+charge subject to the user following the terms of the Fermitools
+Software Legal Information.
+
+Redistribution and/or modification of the software shall be accompanied
+by the Fermitools Software Legal Information (including the copyright
+notice).
+
+The user is asked to feed back problems, benefits, and/or suggestions
+about the software to the Fermilab Software Providers.
+
+Neither the name of Fermilab, the URA, nor the names of the contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+DISCLAIMER OF LIABILITY (BSD):
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FERMILAB,
+OR THE URA, OR THE U.S. DEPARTMENT of ENERGY, OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Liabilities of the Government:
+
+This software is provided by URA, independent from its Prime Contract
+with the U.S. Department of Energy. URA is acting independently from
+the Government and in its own private capacity and is not acting on
+behalf of the U.S. Government, nor as its contractor nor its agent.
+Correspondingly, it is understood and agreed that the U.S. Government
+has no connection to this software and in no manner whatsoever shall
+be liable for nor assume any responsibility or obligation for any claim,
+cost, or damages arising out of or resulting from the use of the software
+available from this server.
+
+Export Control:
+
+All documents and software available from this server are subject to U.S.
+export control laws. Anyone downloading information from this server is
+obligated to secure any necessary Government licenses before exporting
+documents or software obtained from this server.
+ */
+package org.dcache.qos;
+
+import static org.dcache.qos.QoSPolicyTest.QoSPolicyBuilder.aQoSPolicy;
+import static org.dcache.qos.QoSPolicyTest.QoSStateBuilder.aQoSState;
+import static org.dcache.qos.QoSPolicyTest.SpecificationBuilder.aDiskSpecification;
+import static org.dcache.qos.QoSPolicyTest.SpecificationBuilder.aTapeSpecification;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gson.GsonBuilder;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.Test;
+
+public class QoSPolicyTest {
+
+ static class QoSPolicyBuilder {
+
+ QoSPolicy policy;
+
+ static QoSPolicyBuilder aQoSPolicy(String name) {
+ QoSPolicyBuilder builder = new QoSPolicyBuilder();
+ builder.policy = new QoSPolicy();
+ builder.policy.setName(name);
+ return builder;
+ }
+
+ QoSPolicyBuilder withStates(QoSStateBuilder... builder) {
+ policy.setStates(
+ Arrays.stream(builder).map(QoSStateBuilder::build).collect(Collectors.toList()));
+ return this;
+ }
+
+ QoSPolicy build() {
+ return policy;
+ }
+ }
+
+ static class QoSStateBuilder {
+
+ QoSState state;
+
+ static QoSStateBuilder aQoSState() {
+ QoSStateBuilder builder = new QoSStateBuilder();
+ builder.state = new QoSState();
+ return builder;
+ }
+
+ QoSStateBuilder with(SpecificationBuilder... builder) {
+ state.setMedia(Arrays.stream(builder).map(SpecificationBuilder::build)
+ .collect(Collectors.toList()));
+ return this;
+ }
+
+ QoSStateBuilder lasting(String duration) {
+ state.setDuration(duration);
+ return this;
+ }
+
+ QoSState build() {
+ return state;
+ }
+ }
+
+ static class SpecificationBuilder {
+
+ QoSStorageMediumSpecification specification;
+
+ static SpecificationBuilder aDiskSpecification(String type) {
+ SpecificationBuilder builder = new SpecificationBuilder();
+ builder.specification = new DefaultQoSDiskSpecification();
+ ((DefaultQoSDiskSpecification) builder.specification).setType(type);
+ return builder;
+ }
+
+ static SpecificationBuilder aTapeSpecification(String type) {
+ SpecificationBuilder builder = new SpecificationBuilder();
+ builder.specification = new DefaultQoSTapeSpecification();
+ ((DefaultQoSTapeSpecification) builder.specification).setType(type);
+ return builder;
+ }
+
+ SpecificationBuilder withCopies(int copies) {
+ ((DefaultQoSDiskSpecification) specification).setNumberOfCopies(copies);
+ return this;
+ }
+
+ SpecificationBuilder partitionedBy(String... keys) {
+ ((DefaultQoSDiskSpecification) specification).setPartitionKeys(
+ Arrays.stream(keys).collect(
+ Collectors.toList()));
+ return this;
+ }
+
+ SpecificationBuilder withInstance(String instance) {
+ ((DefaultQoSTapeSpecification) specification).setInstance(instance);
+ return this;
+ }
+
+ QoSStorageMediumSpecification build() {
+ return specification;
+ }
+ }
+
+ private QoSPolicy policy;
+ private String jsonPolicy;
+
+ @Test
+ public void shouldParseQoSPolicyCorrectly() {
+ givenAQoSPolicy();
+ whenSerializedAsJson();
+ verifyJsonEqualsJavaObject();
+ }
+
+ @Test
+ public void shouldDeserializePolicyCorrectly() {
+ givenAQoSPolicy();
+ whenSerializedAsJson();
+ assertEquals("JSON did not deserialize properly", policy, thePolicyDeserializedFromJson());
+ }
+
+ private void givenAQoSPolicy() {
+ policy = aQoSPolicy("MyAnalysisData")
+ .withStates(
+ aQoSState().lasting("P1M")
+ .with(aDiskSpecification("SSD").withCopies(2).partitionedBy("hostname"),
+ aDiskSpecification("spinning").withCopies(1)),
+ aQoSState().lasting("P3M")
+ .with(aDiskSpecification("spinning").withCopies(2)
+ .partitionedBy("hostname"),
+ aTapeSpecification("CTA").withInstance("CTA::public")),
+ aQoSState().with(aTapeSpecification("CTA").withInstance("CTA::public"))).build();
+ }
+
+ private QoSPolicy thePolicyDeserializedFromJson() {
+ return DefaultQoSPolicyJsonDeserializer.fromJsonString(jsonPolicy);
+ }
+
+ private void verifyJsonEqualsJavaObject() {
+ JSONObject object = new JSONObject(jsonPolicy);
+ assertEquals("different policy name!", policy.getName(), object.getString("name"));
+ List states = policy.getStates();
+ JSONArray stateArray = object.getJSONArray("states");
+ int len = policy.getStates().size();
+ assertEquals("different number of states!", len, stateArray.length());
+ for (int i = 0; i < len; ++i) {
+ QoSState origState = states.get(i);
+ JSONObject jsonState = stateArray.optJSONObject(i);
+ String duration = origState.getDuration();
+ if (duration == null) {
+ assertFalse("duration should have been null!", jsonState.has("duration"));
+ } else {
+ assertTrue("duration should not be null!", jsonState.has("duration"));
+ assertEquals("duration are different!", duration,
+ jsonState.getString("duration"));
+ }
+
+ List media = origState.getMedia();
+ JSONArray mediaArray = jsonState.getJSONArray("media");
+ int mLen = media.size();
+ assertEquals(mLen, mediaArray.length());
+ for (int j = 0; j < mLen; ++j) {
+ QoSStorageMediumSpecification origSpec = media.get(j);
+ JSONObject jsonSpec = mediaArray.getJSONObject(j);
+ assertEquals("storage element at " + j + " does not match!",
+ origSpec.getStorageMedium().name(),
+ jsonSpec.getString("storageElement"));
+ assertEquals("storage element type does not match",
+ origSpec.getType(), jsonSpec.getString("type"));
+ switch (origSpec.getStorageMedium()) {
+ case DISK:
+ assertEquals("number of copies does not match",
+ origSpec.getNumberOfCopies(),
+ (Integer) jsonSpec.getInt("numberOfCopies"));
+ QoSDiskSpecification disk = (QoSDiskSpecification) origSpec;
+ List keys = disk.getPartitionKeys();
+ if (keys == null) {
+ assertFalse("partition keys should have been null!",
+ jsonSpec.has("partitionKeys"));
+ continue;
+ }
+ assertTrue("partition keys should not be null!",
+ jsonSpec.has("partitionKeys"));
+ int kLen = keys.size();
+ JSONArray keyArray = jsonSpec.getJSONArray("partitionKeys");
+ assertEquals(kLen, keyArray.length());
+ for (int k = 0; k < kLen; ++k) {
+ assertEquals("partition key does not match!", keys.get(k),
+ keyArray.get(k));
+ }
+ break;
+ case HSM:
+ QoSHsmSpecification hsm = (QoSHsmSpecification) origSpec;
+ assertEquals("hsm instance does not match!", hsm.getInstance(),
+ jsonSpec.getString("instance"));
+ break;
+ }
+ }
+ }
+ }
+
+ private void whenSerializedAsJson() {
+ jsonPolicy = new GsonBuilder().setPrettyPrinting()
+ .disableHtmlEscaping()
+ .create().toJson(policy);
+ }
+}