From 724ae527b9ef6afc482f3a8684881e1baa869f67 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 6 Jan 2023 17:01:45 +0100 Subject: refactor(web/server): Migrate to Hypersistence Utils This change updates the web server to use the Hypersistence Utils library instead of our custom code to store columns as JSON in H2 and Postgres. --- .../main/kotlin/org/opendc/web/server/model/Job.kt | 5 +- .../org/opendc/web/server/model/Portfolio.kt | 5 +- .../kotlin/org/opendc/web/server/model/Scenario.kt | 5 +- .../kotlin/org/opendc/web/server/model/Topology.kt | 5 +- .../json/AbstractJsonSqlTypeDescriptor.kt | 74 ---------- .../hibernate/json/JsonBinarySqlTypeDescriptor.kt | 48 ------- .../hibernate/json/JsonBytesSqlTypeDescriptor.kt | 88 ------------ .../util/hibernate/json/JsonSqlTypeDescriptor.kt | 110 --------------- .../hibernate/json/JsonStringSqlTypeDescriptor.kt | 63 --------- .../web/server/util/hibernate/json/JsonType.kt | 48 ------- .../util/hibernate/json/JsonTypeDescriptor.kt | 150 --------------------- 11 files changed, 4 insertions(+), 597 deletions(-) delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonType.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt (limited to 'opendc-web/opendc-web-server/src/main/kotlin') diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt index 84a71acf..9c260fc1 100644 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt +++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt @@ -23,9 +23,7 @@ package org.opendc.web.server.model import org.hibernate.annotations.Type -import org.hibernate.annotations.TypeDef import org.opendc.web.proto.JobState -import org.opendc.web.server.util.hibernate.json.JsonType import java.time.Instant import javax.persistence.Column import javax.persistence.Entity @@ -42,7 +40,6 @@ import javax.persistence.Table /** * A simulation job to be run by the simulator. */ -@TypeDef(name = "json", typeClass = JsonType::class) @Entity @Table(name = "jobs") @NamedQueries( @@ -103,7 +100,7 @@ class Job( /** * Experiment results in JSON */ - @Type(type = "json") + @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") @Column(columnDefinition = "jsonb") var results: Map? = null diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt index 09437712..edf1205f 100644 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt +++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt @@ -23,9 +23,7 @@ package org.opendc.web.server.model import org.hibernate.annotations.Type -import org.hibernate.annotations.TypeDef import org.opendc.web.proto.Targets -import org.opendc.web.server.util.hibernate.json.JsonType import javax.persistence.CascadeType import javax.persistence.Column import javax.persistence.Entity @@ -45,7 +43,6 @@ import javax.persistence.UniqueConstraint /** * A portfolio is the composition of multiple scenarios. */ -@TypeDef(name = "json", typeClass = JsonType::class) @Entity @Table( name = "portfolios", @@ -85,7 +82,7 @@ class Portfolio( /** * The portfolio targets (metrics, repetitions). */ - @Type(type = "json") + @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") @Column(columnDefinition = "jsonb", nullable = false, updatable = false) val targets: Targets ) { diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt index 62adc9e2..47c3e8b2 100644 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt +++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt @@ -23,9 +23,7 @@ package org.opendc.web.server.model import org.hibernate.annotations.Type -import org.hibernate.annotations.TypeDef import org.opendc.web.proto.OperationalPhenomena -import org.opendc.web.server.util.hibernate.json.JsonType import javax.persistence.CascadeType import javax.persistence.Column import javax.persistence.Embedded @@ -45,7 +43,6 @@ import javax.persistence.UniqueConstraint /** * A single scenario to be explored by the simulator. */ -@TypeDef(name = "json", typeClass = JsonType::class) @Entity @Table( name = "scenarios", @@ -101,7 +98,7 @@ class Scenario( @ManyToOne(optional = false) val topology: Topology, - @Type(type = "json") + @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") @Column(columnDefinition = "jsonb", nullable = false, updatable = false) val phenomena: OperationalPhenomena, diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt index 26368455..fe48a0f2 100644 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt +++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt @@ -23,9 +23,7 @@ package org.opendc.web.server.model import org.hibernate.annotations.Type -import org.hibernate.annotations.TypeDef import org.opendc.web.proto.Room -import org.opendc.web.server.util.hibernate.json.JsonType import java.time.Instant import javax.persistence.Column import javax.persistence.Entity @@ -43,7 +41,6 @@ import javax.persistence.UniqueConstraint /** * A datacenter design in OpenDC. */ -@TypeDef(name = "json", typeClass = JsonType::class) @Entity @Table( name = "topologies", @@ -86,7 +83,7 @@ class Topology( /** * Datacenter design in JSON */ - @Type(type = "json") + @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") @Column(columnDefinition = "jsonb", nullable = false) var rooms: List = emptyList() ) { diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt deleted file mode 100644 index 9e29b734..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/AbstractJsonSqlTypeDescriptor.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.hibernate.json - -import org.hibernate.type.descriptor.ValueExtractor -import org.hibernate.type.descriptor.WrapperOptions -import org.hibernate.type.descriptor.java.JavaTypeDescriptor -import org.hibernate.type.descriptor.sql.BasicExtractor -import org.hibernate.type.descriptor.sql.SqlTypeDescriptor -import java.sql.CallableStatement -import java.sql.ResultSet -import java.sql.Types - -/** - * Abstract implementation of a [SqlTypeDescriptor] for Hibernate JSON type. - */ -internal abstract class AbstractJsonSqlTypeDescriptor : SqlTypeDescriptor { - - override fun getSqlType(): Int { - return Types.OTHER - } - - override fun canBeRemapped(): Boolean { - return true - } - - override fun getExtractor(typeDescriptor: JavaTypeDescriptor): ValueExtractor { - return object : BasicExtractor(typeDescriptor, this) { - override fun doExtract(rs: ResultSet, name: String, options: WrapperOptions): X { - return typeDescriptor.wrap(extractJson(rs, name), options) - } - - override fun doExtract(statement: CallableStatement, index: Int, options: WrapperOptions): X { - return typeDescriptor.wrap(extractJson(statement, index), options) - } - - override fun doExtract(statement: CallableStatement, name: String, options: WrapperOptions): X { - return typeDescriptor.wrap(extractJson(statement, name), options) - } - } - } - - open fun extractJson(rs: ResultSet, name: String): Any? { - return rs.getObject(name) - } - - open fun extractJson(statement: CallableStatement, index: Int): Any? { - return statement.getObject(index) - } - - open fun extractJson(statement: CallableStatement, name: String): Any? { - return statement.getObject(name) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt deleted file mode 100644 index df6a3013..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBinarySqlTypeDescriptor.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.hibernate.json - -import com.fasterxml.jackson.databind.JsonNode -import org.hibernate.type.descriptor.ValueBinder -import org.hibernate.type.descriptor.WrapperOptions -import org.hibernate.type.descriptor.java.JavaTypeDescriptor -import org.hibernate.type.descriptor.sql.BasicBinder -import java.sql.CallableStatement -import java.sql.PreparedStatement - -/** - * A [AbstractJsonSqlTypeDescriptor] that stores the JSON as binary (JSONB). - */ -internal object JsonBinarySqlTypeDescriptor : AbstractJsonSqlTypeDescriptor() { - override fun getBinder(typeDescriptor: JavaTypeDescriptor): ValueBinder { - return object : BasicBinder(typeDescriptor, this) { - override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) { - st.setObject(index, typeDescriptor.unwrap(value, JsonNode::class.java, options), sqlType) - } - - override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) { - st.setObject(name, typeDescriptor.unwrap(value, JsonNode::class.java, options), sqlType) - } - } - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt deleted file mode 100644 index 4924f586..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonBytesSqlTypeDescriptor.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.hibernate.json - -import org.hibernate.type.descriptor.ValueBinder -import org.hibernate.type.descriptor.WrapperOptions -import org.hibernate.type.descriptor.java.JavaTypeDescriptor -import org.hibernate.type.descriptor.sql.BasicBinder -import java.io.UnsupportedEncodingException -import java.sql.CallableStatement -import java.sql.PreparedStatement -import java.sql.ResultSet -import java.sql.Types - -/** - * A [AbstractJsonSqlTypeDescriptor] that stores the JSON as UTF-8 encoded bytes. - */ -internal object JsonBytesSqlTypeDescriptor : AbstractJsonSqlTypeDescriptor() { - private val CHARSET = Charsets.UTF_8 - - override fun getSqlType(): Int { - return Types.BINARY - } - - override fun getBinder(javaTypeDescriptor: JavaTypeDescriptor): ValueBinder { - return object : BasicBinder(javaTypeDescriptor, this) { - override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) { - st.setBytes(index, toJsonBytes(javaTypeDescriptor.unwrap(value, String::class.java, options))) - } - - override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) { - st.setBytes(name, toJsonBytes(javaTypeDescriptor.unwrap(value, String::class.java, options))) - } - } - } - - override fun extractJson(rs: ResultSet, name: String): Any? { - return fromJsonBytes(rs.getBytes(name)) - } - - override fun extractJson(statement: CallableStatement, index: Int): Any? { - return fromJsonBytes(statement.getBytes(index)) - } - - override fun extractJson(statement: CallableStatement, name: String): Any? { - return fromJsonBytes(statement.getBytes(name)) - } - - private fun toJsonBytes(jsonValue: String): ByteArray? { - return try { - jsonValue.toByteArray(CHARSET) - } catch (e: UnsupportedEncodingException) { - throw IllegalStateException(e) - } - } - - private fun fromJsonBytes(jsonBytes: ByteArray?): String? { - return if (jsonBytes == null) { - null - } else { - try { - String(jsonBytes, CHARSET) - } catch (e: UnsupportedEncodingException) { - throw IllegalStateException(e) - } - } - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt deleted file mode 100644 index bd22ffbe..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonSqlTypeDescriptor.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.hibernate.json - -import org.hibernate.dialect.H2Dialect -import org.hibernate.dialect.PostgreSQL81Dialect -import org.hibernate.internal.SessionImpl -import org.hibernate.type.descriptor.ValueBinder -import org.hibernate.type.descriptor.ValueExtractor -import org.hibernate.type.descriptor.WrapperOptions -import org.hibernate.type.descriptor.java.JavaTypeDescriptor -import org.hibernate.type.descriptor.sql.BasicBinder -import org.hibernate.type.descriptor.sql.BasicExtractor -import org.hibernate.type.descriptor.sql.SqlTypeDescriptor -import java.sql.CallableStatement -import java.sql.PreparedStatement -import java.sql.ResultSet -import java.sql.Types - -/** - * A [SqlTypeDescriptor] that automatically selects the correct implementation for the database dialect. - */ -internal object JsonSqlTypeDescriptor : SqlTypeDescriptor { - - override fun getSqlType(): Int = Types.OTHER - - override fun canBeRemapped(): Boolean = true - - override fun getExtractor(javaTypeDescriptor: JavaTypeDescriptor): ValueExtractor { - return object : BasicExtractor(javaTypeDescriptor, this) { - private var delegate: AbstractJsonSqlTypeDescriptor? = null - - override fun doExtract(rs: ResultSet, name: String, options: WrapperOptions): X { - return javaTypeDescriptor.wrap(delegate(options).extractJson(rs, name), options) - } - - override fun doExtract(statement: CallableStatement, index: Int, options: WrapperOptions): X { - return javaTypeDescriptor.wrap(delegate(options).extractJson(statement, index), options) - } - - override fun doExtract(statement: CallableStatement, name: String, options: WrapperOptions): X { - return javaTypeDescriptor.wrap(delegate(options).extractJson(statement, name), options) - } - - private fun delegate(options: WrapperOptions): AbstractJsonSqlTypeDescriptor { - var delegate = delegate - if (delegate == null) { - delegate = resolveSqlTypeDescriptor(options) - this.delegate = delegate - } - return delegate - } - } - } - - override fun getBinder(javaTypeDescriptor: JavaTypeDescriptor): ValueBinder { - return object : BasicBinder(javaTypeDescriptor, this) { - private var delegate: ValueBinder? = null - - override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) { - delegate(options).bind(st, value, index, options) - } - - override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) { - delegate(options).bind(st, value, name, options) - } - - private fun delegate(options: WrapperOptions): ValueBinder { - var delegate = delegate - if (delegate == null) { - delegate = checkNotNull(resolveSqlTypeDescriptor(options).getBinder(javaTypeDescriptor)) - this.delegate = delegate - } - return delegate - } - } - } - - /** - * Helper method to resolve the appropriate [SqlTypeDescriptor] based on the [WrapperOptions]. - */ - private fun resolveSqlTypeDescriptor(options: WrapperOptions): AbstractJsonSqlTypeDescriptor { - val session = options as? SessionImpl - return when (session?.jdbcServices?.dialect) { - is PostgreSQL81Dialect -> JsonBinarySqlTypeDescriptor - is H2Dialect -> JsonBytesSqlTypeDescriptor - else -> JsonStringSqlTypeDescriptor - } - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt deleted file mode 100644 index 6e015762..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonStringSqlTypeDescriptor.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.hibernate.json - -import org.hibernate.type.descriptor.ValueBinder -import org.hibernate.type.descriptor.WrapperOptions -import org.hibernate.type.descriptor.java.JavaTypeDescriptor -import org.hibernate.type.descriptor.sql.BasicBinder -import java.sql.CallableStatement -import java.sql.PreparedStatement -import java.sql.ResultSet -import java.sql.Types - -/** - * A [AbstractJsonSqlTypeDescriptor] that stores the JSON as string (VARCHAR). - */ -internal object JsonStringSqlTypeDescriptor : AbstractJsonSqlTypeDescriptor() { - override fun getSqlType(): Int = Types.VARCHAR - - override fun getBinder(typeDescriptor: JavaTypeDescriptor): ValueBinder { - return object : BasicBinder(typeDescriptor, this) { - override fun doBind(st: PreparedStatement, value: X, index: Int, options: WrapperOptions) { - st.setString(index, typeDescriptor.unwrap(value, String::class.java, options)) - } - - override fun doBind(st: CallableStatement, value: X, name: String, options: WrapperOptions) { - st.setString(name, typeDescriptor.unwrap(value, String::class.java, options)) - } - } - } - - override fun extractJson(rs: ResultSet, name: String): Any? { - return rs.getString(name) - } - - override fun extractJson(statement: CallableStatement, index: Int): Any? { - return statement.getString(index) - } - - override fun extractJson(statement: CallableStatement, name: String): Any? { - return statement.getString(name) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonType.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonType.kt deleted file mode 100644 index 9ee21a4c..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonType.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.hibernate.json - -import com.fasterxml.jackson.databind.ObjectMapper -import org.hibernate.type.AbstractSingleColumnStandardBasicType -import org.hibernate.type.BasicType -import org.hibernate.usertype.DynamicParameterizedType -import java.util.Properties -import javax.enterprise.inject.spi.CDI - -/** - * A [BasicType] that contains JSON. - */ -class JsonType(objectMapper: ObjectMapper) : AbstractSingleColumnStandardBasicType(JsonSqlTypeDescriptor, JsonTypeDescriptor(objectMapper)), DynamicParameterizedType { - /** - * No-arg constructor for Hibernate to instantiate. - */ - constructor() : this(CDI.current().select(ObjectMapper::class.java).get()) - - override fun getName(): String = "json" - - override fun registerUnderJavaType(): Boolean = true - - override fun setParameterValues(parameters: Properties) { - (javaTypeDescriptor as JsonTypeDescriptor).setParameterValues(parameters) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt deleted file mode 100644 index 9407f940..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/hibernate/json/JsonTypeDescriptor.kt +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.hibernate.json - -import com.fasterxml.jackson.databind.ObjectMapper -import org.hibernate.HibernateException -import org.hibernate.annotations.common.reflection.XProperty -import org.hibernate.annotations.common.reflection.java.JavaXMember -import org.hibernate.engine.jdbc.BinaryStream -import org.hibernate.engine.jdbc.internal.BinaryStreamImpl -import org.hibernate.type.descriptor.WrapperOptions -import org.hibernate.type.descriptor.java.AbstractTypeDescriptor -import org.hibernate.type.descriptor.java.BlobTypeDescriptor -import org.hibernate.type.descriptor.java.DataHelper -import org.hibernate.type.descriptor.java.MutableMutabilityPlan -import org.hibernate.usertype.DynamicParameterizedType -import java.io.ByteArrayInputStream -import java.io.IOException -import java.io.InputStream -import java.lang.reflect.Type -import java.sql.Blob -import java.sql.SQLException -import java.util.Objects -import java.util.Properties - -/** - * An [AbstractTypeDescriptor] implementation for Hibernate JSON type. - */ -internal class JsonTypeDescriptor(private val objectMapper: ObjectMapper) : AbstractTypeDescriptor(Any::class.java, JsonMutabilityPlan(objectMapper)), DynamicParameterizedType { - private var type: Type? = null - - override fun setParameterValues(parameters: Properties) { - val xProperty = parameters[DynamicParameterizedType.XPROPERTY] as XProperty - type = if (xProperty is JavaXMember) { - val x = xProperty as JavaXMember - x.javaType - } else { - (parameters[DynamicParameterizedType.PARAMETER_TYPE] as DynamicParameterizedType.ParameterType).returnedClass - } - } - - override fun areEqual(one: Any?, another: Any?): Boolean { - return when { - one === another -> true - one == null || another == null -> false - one is String && another is String -> one == another - one is Collection<*> && another is Collection<*> -> Objects.equals(one, another) - else -> areJsonEqual(one, another) - } - } - - override fun toString(value: Any?): String { - return objectMapper.writeValueAsString(value) - } - - override fun fromString(string: String): Any? { - return objectMapper.readValue(string, objectMapper.typeFactory.constructType(type)) - } - - override fun unwrap(value: Any?, type: Class, options: WrapperOptions): X? { - if (value == null) { - return null - } - - @Suppress("UNCHECKED_CAST") - return when { - String::class.java.isAssignableFrom(type) -> toString(value) - BinaryStream::class.java.isAssignableFrom(type) || ByteArray::class.java.isAssignableFrom(type) -> { - val stringValue = if (value is String) value else toString(value) - BinaryStreamImpl(DataHelper.extractBytes(ByteArrayInputStream(stringValue.toByteArray()))) - } - Blob::class.java.isAssignableFrom(type) -> { - val stringValue = if (value is String) value else toString(value) - BlobTypeDescriptor.INSTANCE.fromString(stringValue) - } - Any::class.java.isAssignableFrom(type) -> toJsonType(value) - else -> throw unknownUnwrap(type) - } as X - } - - override fun wrap(value: X?, options: WrapperOptions): Any? { - if (value == null) { - return null - } - - var blob: Blob? = null - if (Blob::class.java.isAssignableFrom(value.javaClass)) { - blob = options.lobCreator.wrap(value as Blob?) - } else if (ByteArray::class.java.isAssignableFrom(value.javaClass)) { - blob = options.lobCreator.createBlob(value as ByteArray?) - } else if (InputStream::class.java.isAssignableFrom(value.javaClass)) { - val inputStream = value as InputStream - blob = try { - options.lobCreator.createBlob(inputStream, inputStream.available().toLong()) - } catch (e: IOException) { - throw unknownWrap(value.javaClass) - } - } - - val stringValue: String = try { - if (blob != null) String(DataHelper.extractBytes(blob.binaryStream)) else value.toString() - } catch (e: SQLException) { - throw HibernateException("Unable to extract binary stream from Blob", e) - } - - return fromString(stringValue) - } - - private class JsonMutabilityPlan(private val objectMapper: ObjectMapper) : MutableMutabilityPlan() { - override fun deepCopyNotNull(value: Any): Any { - return objectMapper.treeToValue(objectMapper.valueToTree(value), value.javaClass) - } - } - - private fun readObject(value: String): Any { - return objectMapper.readTree(value) - } - - private fun areJsonEqual(one: Any, another: Any): Boolean { - return readObject(objectMapper.writeValueAsString(one)) == readObject(objectMapper.writeValueAsString(another)) - } - - private fun toJsonType(value: Any?): Any { - return try { - readObject(objectMapper.writeValueAsString(value)) - } catch (e: Exception) { - throw IllegalArgumentException(e) - } - } -} -- cgit v1.2.3 From ccd3b4641ba6135abf6c80f8cf7c34d16148d818 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 6 Jan 2023 17:12:37 +0100 Subject: refactor(web/server): Convert web server utils to Java This change converts the existing utilities of the web server to Java in preparation for future changes. --- .../web/server/util/DevSecurityOverrideFilter.kt | 51 ---------------- .../web/server/util/runner/QuarkusJobManager.kt | 68 ---------------------- 2 files changed, 119 deletions(-) delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/DevSecurityOverrideFilter.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/runner/QuarkusJobManager.kt (limited to 'opendc-web/opendc-web-server/src/main/kotlin') diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/DevSecurityOverrideFilter.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/DevSecurityOverrideFilter.kt deleted file mode 100644 index 0bdf959a..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/DevSecurityOverrideFilter.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util - -import io.quarkus.arc.properties.IfBuildProperty -import java.security.Principal -import javax.ws.rs.container.ContainerRequestContext -import javax.ws.rs.container.ContainerRequestFilter -import javax.ws.rs.container.PreMatching -import javax.ws.rs.core.SecurityContext -import javax.ws.rs.ext.Provider - -/** - * Helper class to disable security for the OpenDC web API when in development mode. - */ -@Provider -@PreMatching -@IfBuildProperty(name = "opendc.security.enabled", stringValue = "false") -class DevSecurityOverrideFilter : ContainerRequestFilter { - override fun filter(requestContext: ContainerRequestContext) { - requestContext.securityContext = object : SecurityContext { - override fun getUserPrincipal(): Principal = Principal { "anon" } - - override fun isSecure(): Boolean = false - - override fun isUserInRole(role: String): Boolean = true - - override fun getAuthenticationScheme(): String = "basic" - } - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/runner/QuarkusJobManager.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/runner/QuarkusJobManager.kt deleted file mode 100644 index 742a510c..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/runner/QuarkusJobManager.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util.runner - -import org.opendc.web.proto.JobState -import org.opendc.web.proto.runner.Job -import org.opendc.web.runner.JobManager -import org.opendc.web.server.service.JobService -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.transaction.Transactional - -/** - * Implementation of [JobManager] that interfaces directly with [JobService] without overhead of the REST API. - */ -@ApplicationScoped -class QuarkusJobManager @Inject constructor(private val service: JobService) : JobManager { - @Transactional - override fun findNext(): Job? { - return service.queryPending().firstOrNull() - } - - @Transactional - override fun claim(id: Long): Boolean { - return try { - service.updateState(id, JobState.CLAIMED, 0, null) - true - } catch (e: IllegalStateException) { - false - } - } - - @Transactional - override fun heartbeat(id: Long, runtime: Int): Boolean { - val res = service.updateState(id, JobState.RUNNING, runtime, null) - return res?.state != JobState.FAILED - } - - @Transactional - override fun fail(id: Long, runtime: Int) { - service.updateState(id, JobState.FAILED, runtime, null) - } - - @Transactional - override fun finish(id: Long, runtime: Int, results: Map) { - service.updateState(id, JobState.FINISHED, runtime, results) - } -} -- cgit v1.2.3 From e64487cb57ca75d17fe5a8a664c1e8247c7b5168 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sat, 7 Jan 2023 19:23:11 +0000 Subject: refactor(web/server): Use Panache for entity modeling This change updates the OpenDC web server to use Panache (provided by Quarkus) to model entities. Such approach is better supported in Quarkus and simplifies our implementation. --- .../main/kotlin/org/opendc/web/server/model/Job.kt | 111 --------------- .../org/opendc/web/server/model/Portfolio.kt | 100 ------------- .../kotlin/org/opendc/web/server/model/Project.kt | 144 ------------------- .../web/server/model/ProjectAuthorization.kt | 64 --------- .../web/server/model/ProjectAuthorizationKey.kt | 38 ----- .../kotlin/org/opendc/web/server/model/Scenario.kt | 118 ---------------- .../kotlin/org/opendc/web/server/model/Topology.kt | 100 ------------- .../kotlin/org/opendc/web/server/model/Trace.kt | 63 --------- .../org/opendc/web/server/model/UserAccounting.kt | 81 ----------- .../kotlin/org/opendc/web/server/model/Workload.kt | 39 ----- .../opendc/web/server/repository/JobRepository.kt | 94 ------------ .../web/server/repository/PortfolioRepository.kt | 76 ---------- .../web/server/repository/ProjectRepository.kt | 157 --------------------- .../web/server/repository/ScenarioRepository.kt | 90 ------------ .../web/server/repository/TopologyRepository.kt | 86 ----------- .../web/server/repository/TraceRepository.kt | 53 ------- .../server/repository/UserAccountingRepository.kt | 88 ------------ .../opendc/web/server/rest/runner/JobResource.kt | 2 +- .../web/server/rest/user/PortfolioResource.kt | 4 +- .../opendc/web/server/rest/user/ProjectResource.kt | 8 +- .../org/opendc/web/server/service/JobService.kt | 97 ------------- .../opendc/web/server/service/PortfolioService.kt | 103 -------------- .../opendc/web/server/service/ProjectService.kt | 88 ------------ .../opendc/web/server/service/RunnerConversions.kt | 69 --------- .../opendc/web/server/service/ScenarioService.kt | 141 ------------------ .../opendc/web/server/service/TopologyService.kt | 127 ----------------- .../org/opendc/web/server/service/TraceService.kt | 48 ------- .../web/server/service/UserAccountingService.kt | 128 ----------------- .../opendc/web/server/service/UserConversions.kt | 126 ----------------- .../org/opendc/web/server/service/UserService.kt | 44 ------ .../kotlin/org/opendc/web/server/service/Utils.kt | 40 ------ 31 files changed, 7 insertions(+), 2520 deletions(-) delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Project.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorization.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorizationKey.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Trace.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/UserAccounting.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Workload.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/JobRepository.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/PortfolioRepository.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ProjectRepository.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ScenarioRepository.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TopologyRepository.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TraceRepository.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/UserAccountingRepository.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/JobService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/PortfolioService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ProjectService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/RunnerConversions.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ScenarioService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TopologyService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TraceService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserConversions.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/Utils.kt (limited to 'opendc-web/opendc-web-server/src/main/kotlin') diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt deleted file mode 100644 index 9c260fc1..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import org.hibernate.annotations.Type -import org.opendc.web.proto.JobState -import java.time.Instant -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.FetchType -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.JoinColumn -import javax.persistence.NamedQueries -import javax.persistence.NamedQuery -import javax.persistence.OneToOne -import javax.persistence.Table - -/** - * A simulation job to be run by the simulator. - */ -@Entity -@Table(name = "jobs") -@NamedQueries( - value = [ - NamedQuery( - name = "Job.findAll", - query = "SELECT j FROM Job j WHERE j.state = :state" - ), - NamedQuery( - name = "Job.updateOne", - query = """ - UPDATE Job j - SET j.state = :newState, j.updatedAt = :updatedAt, j.runtime = :runtime, j.results = :results - WHERE j.id = :id AND j.state = :oldState - """ - ) - ] -) -class Job( - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - val id: Long, - - @Column(name = "created_by", nullable = false, updatable = false) - val createdBy: String, - - @OneToOne(optional = false, mappedBy = "job", fetch = FetchType.EAGER) - @JoinColumn(name = "scenario_id", nullable = false) - val scenario: Scenario, - - @Column(name = "created_at", nullable = false, updatable = false) - val createdAt: Instant, - - /** - * The number of simulation runs to perform. - */ - @Column(nullable = false, updatable = false) - val repeats: Int -) { - /** - * The instant at which the job was updated. - */ - @Column(name = "updated_at", nullable = false) - var updatedAt: Instant = createdAt - - /** - * The state of the job. - */ - @Column(nullable = false) - var state: JobState = JobState.PENDING - - /** - * The runtime of the job (in seconds). - */ - @Column(nullable = false) - var runtime: Int = 0 - - /** - * Experiment results in JSON - */ - @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") - @Column(columnDefinition = "jsonb") - var results: Map? = null - - /** - * Return a string representation of this job. - */ - override fun toString(): String = "Job[id=$id,scenario=${scenario.id},state=$state]" -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt deleted file mode 100644 index edf1205f..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import org.hibernate.annotations.Type -import org.opendc.web.proto.Targets -import javax.persistence.CascadeType -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.Index -import javax.persistence.JoinColumn -import javax.persistence.ManyToOne -import javax.persistence.NamedQueries -import javax.persistence.NamedQuery -import javax.persistence.OneToMany -import javax.persistence.OrderBy -import javax.persistence.Table -import javax.persistence.UniqueConstraint - -/** - * A portfolio is the composition of multiple scenarios. - */ -@Entity -@Table( - name = "portfolios", - uniqueConstraints = [UniqueConstraint(columnNames = ["project_id", "number"])], - indexes = [Index(name = "fn_portfolios_number", columnList = "project_id, number")] -) -@NamedQueries( - value = [ - NamedQuery( - name = "Portfolio.findAll", - query = "SELECT p FROM Portfolio p WHERE p.project.id = :projectId" - ), - NamedQuery( - name = "Portfolio.findOne", - query = "SELECT p FROM Portfolio p WHERE p.project.id = :projectId AND p.number = :number" - ) - ] -) -class Portfolio( - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - val id: Long, - - /** - * Unique number of the portfolio for the project. - */ - @Column(nullable = false) - val number: Int, - - @Column(nullable = false) - val name: String, - - @ManyToOne(optional = false) - @JoinColumn(name = "project_id", nullable = false) - val project: Project, - - /** - * The portfolio targets (metrics, repetitions). - */ - @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") - @Column(columnDefinition = "jsonb", nullable = false, updatable = false) - val targets: Targets -) { - /** - * The scenarios in this portfolio. - */ - @OneToMany(cascade = [CascadeType.ALL], mappedBy = "portfolio", orphanRemoval = true) - @OrderBy("id ASC") - val scenarios: MutableSet = mutableSetOf() - - /** - * Return a string representation of this portfolio. - */ - override fun toString(): String = "Job[id=$id,name=$name,project=${project.id},targets=$targets]" -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Project.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Project.kt deleted file mode 100644 index 41d1a786..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Project.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import java.time.Instant -import javax.persistence.CascadeType -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.NamedQueries -import javax.persistence.NamedQuery -import javax.persistence.OneToMany -import javax.persistence.OrderBy -import javax.persistence.Table - -/** - * A project in OpenDC encapsulates all the datacenter designs and simulation runs for a set of users. - */ -@Entity -@Table(name = "projects") -@NamedQueries( - value = [ - NamedQuery( - name = "Project.findAll", - query = """ - SELECT a - FROM ProjectAuthorization a - WHERE a.key.userId = :userId - """ - ), - NamedQuery( - name = "Project.allocatePortfolio", - query = """ - UPDATE Project p - SET p.portfoliosCreated = :oldState + 1, p.updatedAt = :now - WHERE p.id = :id AND p.portfoliosCreated = :oldState - """ - ), - NamedQuery( - name = "Project.allocateTopology", - query = """ - UPDATE Project p - SET p.topologiesCreated = :oldState + 1, p.updatedAt = :now - WHERE p.id = :id AND p.topologiesCreated = :oldState - """ - ), - NamedQuery( - name = "Project.allocateScenario", - query = """ - UPDATE Project p - SET p.scenariosCreated = :oldState + 1, p.updatedAt = :now - WHERE p.id = :id AND p.scenariosCreated = :oldState - """ - ) - ] -) -class Project( - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - val id: Long, - - @Column(nullable = false) - var name: String, - - @Column(name = "created_at", nullable = false, updatable = false) - val createdAt: Instant -) { - /** - * The instant at which the project was updated. - */ - @Column(name = "updated_at", nullable = false) - var updatedAt: Instant = createdAt - - /** - * The portfolios belonging to this project. - */ - @OneToMany(cascade = [CascadeType.ALL], mappedBy = "project", orphanRemoval = true) - @OrderBy("id ASC") - val portfolios: MutableSet = mutableSetOf() - - /** - * The number of portfolios created for this project (including deleted portfolios). - */ - @Column(name = "portfolios_created", nullable = false) - var portfoliosCreated: Int = 0 - - /** - * The topologies belonging to this project. - */ - @OneToMany(cascade = [CascadeType.ALL], mappedBy = "project", orphanRemoval = true) - @OrderBy("id ASC") - val topologies: MutableSet = mutableSetOf() - - /** - * The number of topologies created for this project (including deleted topologies). - */ - @Column(name = "topologies_created", nullable = false) - var topologiesCreated: Int = 0 - - /** - * The scenarios belonging to this project. - */ - @OneToMany(mappedBy = "project", orphanRemoval = true) - val scenarios: MutableSet = mutableSetOf() - - /** - * The number of scenarios created for this project (including deleted scenarios). - */ - @Column(name = "scenarios_created", nullable = false) - var scenariosCreated: Int = 0 - - /** - * The users authorized to access the project. - */ - @OneToMany(cascade = [CascadeType.ALL], mappedBy = "project", orphanRemoval = true) - val authorizations: MutableSet = mutableSetOf() - - /** - * Return a string representation of this project. - */ - override fun toString(): String = "Project[id=$id,name=$name]" -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorization.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorization.kt deleted file mode 100644 index 791725cd..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorization.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import org.opendc.web.proto.user.ProjectRole -import javax.persistence.Column -import javax.persistence.EmbeddedId -import javax.persistence.Entity -import javax.persistence.JoinColumn -import javax.persistence.ManyToOne -import javax.persistence.MapsId -import javax.persistence.Table - -/** - * An authorization for some user to participate in a project. - */ -@Entity -@Table(name = "project_authorizations") -class ProjectAuthorization( - /** - * The user identifier of the authorization. - */ - @EmbeddedId - val key: ProjectAuthorizationKey, - - /** - * The project that the user is authorized to participate in. - */ - @ManyToOne(optional = false) - @MapsId("projectId") - @JoinColumn(name = "project_id", updatable = false, insertable = false, nullable = false) - val project: Project, - - /** - * The role of the user in the project. - */ - @Column(nullable = false) - val role: ProjectRole -) { - /** - * Return a string representation of this project authorization. - */ - override fun toString(): String = "ProjectAuthorization[project=${key.projectId},user=${key.userId},role=$role]" -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorizationKey.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorizationKey.kt deleted file mode 100644 index 449b6608..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorizationKey.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import javax.persistence.Column -import javax.persistence.Embeddable - -/** - * Key for representing a [ProjectAuthorization] object. - */ -@Embeddable -data class ProjectAuthorizationKey( - @Column(name = "user_id", nullable = false) - val userId: String, - - @Column(name = "project_id", nullable = false) - val projectId: Long -) : java.io.Serializable diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt deleted file mode 100644 index 47c3e8b2..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import org.hibernate.annotations.Type -import org.opendc.web.proto.OperationalPhenomena -import javax.persistence.CascadeType -import javax.persistence.Column -import javax.persistence.Embedded -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.Index -import javax.persistence.JoinColumn -import javax.persistence.ManyToOne -import javax.persistence.NamedQueries -import javax.persistence.NamedQuery -import javax.persistence.OneToOne -import javax.persistence.Table -import javax.persistence.UniqueConstraint - -/** - * A single scenario to be explored by the simulator. - */ -@Entity -@Table( - name = "scenarios", - uniqueConstraints = [UniqueConstraint(columnNames = ["project_id", "number"])], - indexes = [Index(name = "fn_scenarios_number", columnList = "project_id, number")] -) -@NamedQueries( - value = [ - NamedQuery( - name = "Scenario.findAll", - query = "SELECT s FROM Scenario s WHERE s.project.id = :projectId" - ), - NamedQuery( - name = "Scenario.findAllForPortfolio", - query = """ - SELECT s - FROM Scenario s - JOIN Portfolio p ON p.id = s.portfolio.id AND p.number = :number - WHERE s.project.id = :projectId - """ - ), - NamedQuery( - name = "Scenario.findOne", - query = "SELECT s FROM Scenario s WHERE s.project.id = :projectId AND s.number = :number" - ) - ] -) -class Scenario( - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - val id: Long, - - /** - * Unique number of the scenario for the project. - */ - @Column(nullable = false) - val number: Int, - - @Column(nullable = false, updatable = false) - val name: String, - - @ManyToOne(optional = false) - @JoinColumn(name = "project_id", nullable = false) - val project: Project, - - @ManyToOne(optional = false) - @JoinColumn(name = "portfolio_id", nullable = false) - val portfolio: Portfolio, - - @Embedded - val workload: Workload, - - @ManyToOne(optional = false) - val topology: Topology, - - @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") - @Column(columnDefinition = "jsonb", nullable = false, updatable = false) - val phenomena: OperationalPhenomena, - - @Column(name = "scheduler_name", nullable = false, updatable = false) - val schedulerName: String -) { - /** - * The [Job] associated with the scenario. - */ - @OneToOne(cascade = [CascadeType.ALL]) - lateinit var job: Job - - /** - * Return a string representation of this scenario. - */ - override fun toString(): String = "Scenario[id=$id,name=$name,project=${project.id},portfolio=${portfolio.id}]" -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt deleted file mode 100644 index fe48a0f2..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import org.hibernate.annotations.Type -import org.opendc.web.proto.Room -import java.time.Instant -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.Index -import javax.persistence.JoinColumn -import javax.persistence.ManyToOne -import javax.persistence.NamedQueries -import javax.persistence.NamedQuery -import javax.persistence.Table -import javax.persistence.UniqueConstraint - -/** - * A datacenter design in OpenDC. - */ -@Entity -@Table( - name = "topologies", - uniqueConstraints = [UniqueConstraint(columnNames = ["project_id", "number"])], - indexes = [Index(name = "fn_topologies_number", columnList = "project_id, number")] -) -@NamedQueries( - value = [ - NamedQuery( - name = "Topology.findAll", - query = "SELECT t FROM Topology t WHERE t.project.id = :projectId" - ), - NamedQuery( - name = "Topology.findOne", - query = "SELECT t FROM Topology t WHERE t.project.id = :projectId AND t.number = :number" - ) - ] -) -class Topology( - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - val id: Long, - - /** - * Unique number of the topology for the project. - */ - @Column(nullable = false) - val number: Int, - - @Column(nullable = false) - val name: String, - - @ManyToOne(optional = false) - @JoinColumn(name = "project_id", nullable = false) - val project: Project, - - @Column(name = "created_at", nullable = false, updatable = false) - val createdAt: Instant, - - /** - * Datacenter design in JSON - */ - @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType") - @Column(columnDefinition = "jsonb", nullable = false) - var rooms: List = emptyList() -) { - /** - * The instant at which the topology was updated. - */ - @Column(name = "updated_at", nullable = false) - var updatedAt: Instant = createdAt - - /** - * Return a string representation of this topology. - */ - override fun toString(): String = "Topology[id=$id,name=$name,project=${project.id}]" -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Trace.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Trace.kt deleted file mode 100644 index 14a88c5a..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Trace.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.Id -import javax.persistence.NamedQueries -import javax.persistence.NamedQuery -import javax.persistence.Table - -/** - * A workload trace available for simulation. - * - * @param id The unique identifier of the trace. - * @param name The name of the trace. - * @param type The type of trace. - */ -@Entity -@Table(name = "traces") -@NamedQueries( - value = [ - NamedQuery( - name = "Trace.findAll", - query = "SELECT t FROM Trace t" - ) - ] -) -class Trace( - @Id - val id: String, - - @Column(nullable = false, updatable = false) - val name: String, - - @Column(nullable = false, updatable = false) - val type: String -) { - /** - * Return a string representation of this trace. - */ - override fun toString(): String = "Trace[id=$id,name=$name,type=$type]" -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/UserAccounting.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/UserAccounting.kt deleted file mode 100644 index 5b813044..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/UserAccounting.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import java.time.LocalDate -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.Id -import javax.persistence.NamedQueries -import javax.persistence.NamedQuery -import javax.persistence.Table - -/** - * Entity to track the number of simulation minutes used by a user. - */ -@Entity -@Table(name = "user_accounting") -@NamedQueries( - value = [ - NamedQuery( - name = "UserAccounting.consumeBudget", - query = """ - UPDATE UserAccounting a - SET a.simulationTime = a.simulationTime + :seconds - WHERE a.userId = :userId AND a.periodEnd = :periodEnd - """ - ), - NamedQuery( - name = "UserAccounting.resetBudget", - query = """ - UPDATE UserAccounting a - SET a.periodEnd = :periodEnd, a.simulationTime = :seconds - WHERE a.userId = :userId AND a.periodEnd = :oldPeriodEnd - """ - ) - ] -) -class UserAccounting( - @Id - @Column(name = "user_id", nullable = false) - val userId: String, - - /** - * The end of the accounting period. - */ - @Column(name = "period_end", nullable = false) - var periodEnd: LocalDate, - - /** - * The number of simulation seconds to be used per accounting period. - */ - @Column(name = "simulation_time_budget", nullable = false) - var simulationTimeBudget: Int -) { - /** - * The number of simulation seconds used in this period. This number should reset once the accounting period has - * been reached. - */ - @Column(name = "simulation_time", nullable = false) - var simulationTime: Int = 0 -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Workload.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Workload.kt deleted file mode 100644 index 9c59dc25..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Workload.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.model - -import javax.persistence.Column -import javax.persistence.Embeddable -import javax.persistence.ManyToOne - -/** - * Specification of the workload for a [Scenario]. - */ -@Embeddable -class Workload( - @ManyToOne(optional = false) - val trace: Trace, - - @Column(name = "sampling_fraction", nullable = false, updatable = false) - val samplingFraction: Double -) diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/JobRepository.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/JobRepository.kt deleted file mode 100644 index e9bf0af0..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/JobRepository.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.repository - -import org.opendc.web.proto.JobState -import org.opendc.web.server.model.Job -import java.time.Instant -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityManager - -/** - * A repository to manage [Job] entities. - */ -@ApplicationScoped -class JobRepository @Inject constructor(private val em: EntityManager) { - /** - * Find all jobs currently residing in [state]. - * - * @param state The state in which the jobs should be. - * @return The list of jobs in state [state]. - */ - fun findAll(state: JobState): List { - return em.createNamedQuery("Job.findAll", Job::class.java) - .setParameter("state", state) - .resultList - } - - /** - * Find the [Job] with the specified [id]. - * - * @param id The unique identifier of the job. - * @return The trace or `null` if it does not exist. - */ - fun findOne(id: Long): Job? { - return em.find(Job::class.java, id) - } - - /** - * Delete the specified [job]. - */ - fun delete(job: Job) { - em.remove(job) - } - - /** - * Save the specified [job] to the database. - */ - fun save(job: Job) { - em.persist(job) - } - - /** - * Atomically update the specified [job]. - * - * @param job The job to update atomically. - * @param newState The new state to enter into. - * @param time The time at which the update occurs. - * @param results The results to possible set. - * @return `true` when the update succeeded`, `false` when there was a conflict. - */ - fun updateOne(job: Job, newState: JobState, time: Instant, runtime: Int, results: Map?): Boolean { - val count = em.createNamedQuery("Job.updateOne") - .setParameter("id", job.id) - .setParameter("oldState", job.state) - .setParameter("newState", newState) - .setParameter("updatedAt", Instant.now()) - .setParameter("runtime", runtime) - .setParameter("results", results) - .executeUpdate() - em.refresh(job) - return count > 0 - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/PortfolioRepository.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/PortfolioRepository.kt deleted file mode 100644 index 77130c15..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/PortfolioRepository.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.repository - -import org.opendc.web.server.model.Portfolio -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityManager - -/** - * A repository to manage [Portfolio] entities. - */ -@ApplicationScoped -class PortfolioRepository @Inject constructor(private val em: EntityManager) { - /** - * Find all [Portfolio]s that belong to [project][projectId]. - * - * @param projectId The unique identifier of the project. - * @return The list of portfolios that belong to the specified project. - */ - fun findAll(projectId: Long): List { - return em.createNamedQuery("Portfolio.findAll", Portfolio::class.java) - .setParameter("projectId", projectId) - .resultList - } - - /** - * Find the [Portfolio] with the specified [number] belonging to [project][projectId]. - * - * @param projectId The unique identifier of the project. - * @param number The number of the portfolio. - * @return The portfolio or `null` if it does not exist. - */ - fun findOne(projectId: Long, number: Int): Portfolio? { - return em.createNamedQuery("Portfolio.findOne", Portfolio::class.java) - .setParameter("projectId", projectId) - .setParameter("number", number) - .setMaxResults(1) - .resultList - .firstOrNull() - } - - /** - * Delete the specified [portfolio]. - */ - fun delete(portfolio: Portfolio) { - em.remove(portfolio) - } - - /** - * Save the specified [portfolio] to the database. - */ - fun save(portfolio: Portfolio) { - em.persist(portfolio) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ProjectRepository.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ProjectRepository.kt deleted file mode 100644 index 519da3de..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ProjectRepository.kt +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.repository - -import org.opendc.web.server.model.Project -import org.opendc.web.server.model.ProjectAuthorization -import org.opendc.web.server.model.ProjectAuthorizationKey -import java.time.Instant -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityManager - -/** - * A repository to manage [Project] entities. - */ -@ApplicationScoped -class ProjectRepository @Inject constructor(private val em: EntityManager) { - /** - * List all projects for the user with the specified [userId]. - * - * @param userId The identifier of the user that is requesting the list of projects. - * @return A list of projects that the user has received authorization for. - */ - fun findAll(userId: String): List { - return em.createNamedQuery("Project.findAll", ProjectAuthorization::class.java) - .setParameter("userId", userId) - .resultList - } - - /** - * Find the project with [id] for the user with the specified [userId]. - * - * @param userId The identifier of the user that is requesting the list of projects. - * @param id The unique identifier of the project. - * @return The project with the specified identifier or `null` if it does not exist or is not accessible to the - * user with the specified identifier. - */ - fun findOne(userId: String, id: Long): ProjectAuthorization? { - return em.find(ProjectAuthorization::class.java, ProjectAuthorizationKey(userId, id)) - } - - /** - * Delete the specified [project]. - */ - fun delete(project: Project) { - em.remove(project) - } - - /** - * Save the specified [project] to the database. - */ - fun save(project: Project) { - em.persist(project) - } - - /** - * Save the specified [auth] to the database. - */ - fun save(auth: ProjectAuthorization) { - em.persist(auth) - } - - /** - * Allocate the next portfolio number for the specified [project]. - * - * @param project The project to allocate the portfolio number for. - * @param time The time at which the new portfolio is created. - * @param tries The number of times to try to allocate the number before failing. - */ - fun allocatePortfolio(project: Project, time: Instant, tries: Int = 4): Int { - repeat(tries) { - val count = em.createNamedQuery("Project.allocatePortfolio") - .setParameter("id", project.id) - .setParameter("oldState", project.portfoliosCreated) - .setParameter("now", time) - .executeUpdate() - - if (count > 0) { - return project.portfoliosCreated + 1 - } else { - em.refresh(project) - } - } - - throw IllegalStateException("Failed to allocate next portfolio") - } - - /** - * Allocate the next topology number for the specified [project]. - * - * @param project The project to allocate the topology number for. - * @param time The time at which the new topology is created. - * @param tries The number of times to try to allocate the number before failing. - */ - fun allocateTopology(project: Project, time: Instant, tries: Int = 4): Int { - repeat(tries) { - val count = em.createNamedQuery("Project.allocateTopology") - .setParameter("id", project.id) - .setParameter("oldState", project.topologiesCreated) - .setParameter("now", time) - .executeUpdate() - - if (count > 0) { - return project.topologiesCreated + 1 - } else { - em.refresh(project) - } - } - - throw IllegalStateException("Failed to allocate next topology") - } - - /** - * Allocate the next scenario number for the specified [project]. - * - * @param project The project to allocate the scenario number for. - * @param time The time at which the new scenario is created. - * @param tries The number of times to try to allocate the number before failing. - */ - fun allocateScenario(project: Project, time: Instant, tries: Int = 4): Int { - repeat(tries) { - val count = em.createNamedQuery("Project.allocateScenario") - .setParameter("id", project.id) - .setParameter("oldState", project.scenariosCreated) - .setParameter("now", time) - .executeUpdate() - - if (count > 0) { - return project.scenariosCreated + 1 - } else { - em.refresh(project) - } - } - - throw IllegalStateException("Failed to allocate next scenario") - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ScenarioRepository.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ScenarioRepository.kt deleted file mode 100644 index 145db71d..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ScenarioRepository.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.repository - -import org.opendc.web.server.model.Scenario -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityManager - -/** - * A repository to manage [Scenario] entities. - */ -@ApplicationScoped -class ScenarioRepository @Inject constructor(private val em: EntityManager) { - /** - * Find all [Scenario]s that belong to [project][projectId]. - * - * @param projectId The unique identifier of the project. - * @return The list of scenarios that belong to the specified project. - */ - fun findAll(projectId: Long): List { - return em.createNamedQuery("Scenario.findAll", Scenario::class.java) - .setParameter("projectId", projectId) - .resultList - } - - /** - * Find all [Scenario]s that belong to [portfolio][number] of [project][projectId]. - * - * @param projectId The unique identifier of the project. - * @param number The number of the portfolio to which the scenarios should belong. - * @return The list of scenarios that belong to the specified portfolio. - */ - fun findAll(projectId: Long, number: Int): List { - return em.createNamedQuery("Scenario.findAllForPortfolio", Scenario::class.java) - .setParameter("projectId", projectId) - .setParameter("number", number) - .resultList - } - - /** - * Find the [Scenario] with the specified [number] belonging to [project][projectId]. - * - * @param projectId The unique identifier of the project. - * @param number The number of the scenario. - * @return The scenario or `null` if it does not exist. - */ - fun findOne(projectId: Long, number: Int): Scenario? { - return em.createNamedQuery("Scenario.findOne", Scenario::class.java) - .setParameter("projectId", projectId) - .setParameter("number", number) - .setMaxResults(1) - .resultList - .firstOrNull() - } - - /** - * Delete the specified [scenario]. - */ - fun delete(scenario: Scenario) { - em.remove(scenario) - } - - /** - * Save the specified [scenario] to the database. - */ - fun save(scenario: Scenario) { - em.persist(scenario) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TopologyRepository.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TopologyRepository.kt deleted file mode 100644 index e8eadd63..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TopologyRepository.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.repository - -import org.opendc.web.server.model.Topology -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityManager - -/** - * A repository to manage [Topology] entities. - */ -@ApplicationScoped -class TopologyRepository @Inject constructor(private val em: EntityManager) { - /** - * Find all [Topology]s that belong to [project][projectId]. - * - * @param projectId The unique identifier of the project. - * @return The list of topologies that belong to the specified project. - */ - fun findAll(projectId: Long): List { - return em.createNamedQuery("Topology.findAll", Topology::class.java) - .setParameter("projectId", projectId) - .resultList - } - - /** - * Find the [Topology] with the specified [number] belonging to [project][projectId]. - * - * @param projectId The unique identifier of the project. - * @param number The number of the topology. - * @return The topology or `null` if it does not exist. - */ - fun findOne(projectId: Long, number: Int): Topology? { - return em.createNamedQuery("Topology.findOne", Topology::class.java) - .setParameter("projectId", projectId) - .setParameter("number", number) - .setMaxResults(1) - .resultList - .firstOrNull() - } - - /** - * Find the [Topology] with the specified [id]. - * - * @param id Unique identifier of the topology. - * @return The topology or `null` if it does not exist. - */ - fun findOne(id: Long): Topology? { - return em.find(Topology::class.java, id) - } - - /** - * Delete the specified [topology]. - */ - fun delete(topology: Topology) { - em.remove(topology) - } - - /** - * Save the specified [topology] to the database. - */ - fun save(topology: Topology) { - em.persist(topology) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TraceRepository.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TraceRepository.kt deleted file mode 100644 index f328eea6..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TraceRepository.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.repository - -import org.opendc.web.server.model.Trace -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityManager - -/** - * A repository to manage [Trace] entities. - */ -@ApplicationScoped -class TraceRepository @Inject constructor(private val em: EntityManager) { - /** - * Find all workload traces in the database. - * - * @return The list of available workload traces. - */ - fun findAll(): List { - return em.createNamedQuery("Trace.findAll", Trace::class.java).resultList - } - - /** - * Find the [Trace] with the specified [id]. - * - * @param id The unique identifier of the trace. - * @return The trace or `null` if it does not exist. - */ - fun findOne(id: String): Trace? { - return em.find(Trace::class.java, id) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/UserAccountingRepository.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/UserAccountingRepository.kt deleted file mode 100644 index f0265d3d..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/UserAccountingRepository.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.repository - -import org.opendc.web.server.model.UserAccounting -import java.time.LocalDate -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityManager - -/** - * A repository to manage [UserAccounting] entities. - */ -@ApplicationScoped -class UserAccountingRepository @Inject constructor(private val em: EntityManager) { - /** - * Find the [UserAccounting] object for the specified [userId]. - * - * @param userId The unique identifier of the user. - * @return The [UserAccounting] object or `null` if it does not exist. - */ - fun findForUser(userId: String): UserAccounting? { - return em.find(UserAccounting::class.java, userId) - } - - /** - * Save the specified [UserAccounting] object to the database. - */ - fun save(accounting: UserAccounting) { - em.persist(accounting) - } - - /** - * Atomically consume the budget for the specified [UserAccounting] object. - * - * @param accounting The [UserAccounting] object to update atomically. - * @param seconds The number of seconds to consume from the user. - * @return `true` when the update succeeded`, `false` when there was a conflict. - */ - fun consumeBudget(accounting: UserAccounting, seconds: Int): Boolean { - val count = em.createNamedQuery("UserAccounting.consumeBudget") - .setParameter("userId", accounting.userId) - .setParameter("periodEnd", accounting.periodEnd) - .setParameter("seconds", seconds) - .executeUpdate() - em.refresh(accounting) - return count > 0 - } - - /** - * Atomically reset the budget for the specified [UserAccounting] object. - * - * @param accounting The [UserAccounting] object to update atomically. - * @param periodEnd The new end period for the budget. - * @param seconds The number of seconds that have already been consumed. - * @return `true` when the update succeeded`, `false` when there was a conflict. - */ - fun resetBudget(accounting: UserAccounting, periodEnd: LocalDate, seconds: Int): Boolean { - val count = em.createNamedQuery("UserAccounting.resetBudget") - .setParameter("userId", accounting.userId) - .setParameter("oldPeriodEnd", accounting.periodEnd) - .setParameter("periodEnd", periodEnd) - .setParameter("seconds", seconds) - .executeUpdate() - em.refresh(accounting) - return count > 0 - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt index d0432360..1e9abc14 100644 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt +++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt @@ -45,7 +45,7 @@ class JobResource @Inject constructor(private val jobService: JobService) { */ @GET fun queryPending(): List { - return jobService.queryPending() + return jobService.listPending() } /** diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt index ebe57ae2..82843a5a 100644 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt +++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt @@ -50,7 +50,7 @@ class PortfolioResource @Inject constructor( */ @GET fun getAll(@PathParam("project") projectId: Long): List { - return portfolioService.findAll(identity.principal.name, projectId) + return portfolioService.findByUser(identity.principal.name, projectId) } /** @@ -68,7 +68,7 @@ class PortfolioResource @Inject constructor( @GET @Path("{portfolio}") fun get(@PathParam("project") projectId: Long, @PathParam("portfolio") number: Int): Portfolio { - return portfolioService.findOne(identity.principal.name, projectId, number) ?: throw WebApplicationException("Portfolio not found", 404) + return portfolioService.findByUser(identity.principal.name, projectId, number) ?: throw WebApplicationException("Portfolio not found", 404) } /** diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt index 817f53a5..d12fc690 100644 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt +++ b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt @@ -50,7 +50,7 @@ class ProjectResource @Inject constructor( */ @GET fun getAll(): List { - return projectService.findWithUser(identity.principal.name) + return projectService.findByUser(identity.principal.name) } /** @@ -59,7 +59,7 @@ class ProjectResource @Inject constructor( @POST @Transactional fun create(@Valid request: Project.Create): Project { - return projectService.createForUser(identity.principal.name, request.name) + return projectService.create(identity.principal.name, request.name) } /** @@ -68,7 +68,7 @@ class ProjectResource @Inject constructor( @GET @Path("{project}") fun get(@PathParam("project") id: Long): Project { - return projectService.findWithUser(identity.principal.name, id) ?: throw WebApplicationException("Project not found", 404) + return projectService.findByUser(identity.principal.name, id) ?: throw WebApplicationException("Project not found", 404) } /** @@ -79,7 +79,7 @@ class ProjectResource @Inject constructor( @Transactional fun delete(@PathParam("project") id: Long): Project { try { - return projectService.deleteWithUser(identity.principal.name, id) ?: throw WebApplicationException("Project not found", 404) + return projectService.delete(identity.principal.name, id) ?: throw WebApplicationException("Project not found", 404) } catch (e: IllegalArgumentException) { throw WebApplicationException(e.message, 403) } diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/JobService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/JobService.kt deleted file mode 100644 index a0ebd4f4..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/JobService.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.JobState -import org.opendc.web.proto.runner.Job -import org.opendc.web.server.repository.JobRepository -import java.time.Instant -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject - -/** - * Service for managing [Job]s. - */ -@ApplicationScoped -class JobService @Inject constructor( - private val repository: JobRepository, - private val accountingService: UserAccountingService -) { - /** - * Query the pending simulation jobs. - */ - fun queryPending(): List { - return repository.findAll(JobState.PENDING).map { it.toRunnerDto() } - } - - /** - * Find a job by its identifier. - */ - fun findById(id: Long): Job? { - return repository.findOne(id)?.toRunnerDto() - } - - /** - * Atomically update the state of a [Job]. - * - * @param id The identifier of the job. - * @param newState The next state for the job. - * @param runtime The runtime of the job (in seconds). - * @param results The potential results of the job. - */ - fun updateState(id: Long, newState: JobState, runtime: Int, results: Map?): Job? { - val entity = repository.findOne(id) ?: return null - val state = entity.state - if (!state.isTransitionLegal(newState)) { - throw IllegalArgumentException("Invalid transition from $state to $newState") - } - - val now = Instant.now() - var nextState = newState - val consumedBudget = (runtime - entity.runtime).coerceAtLeast(1) - - // Check whether the user still has any simulation budget left - if (accountingService.consumeSimulationBudget(entity.createdBy, consumedBudget) && nextState == JobState.RUNNING) { - nextState = JobState.FAILED // User has consumed all their budget; cancel the job - } - - if (!repository.updateOne(entity, nextState, now, runtime, results)) { - throw IllegalStateException("Conflicting update") - } - - return entity.toRunnerDto() - } - - /** - * Determine whether the transition from [this] to [newState] is legal. - */ - private fun JobState.isTransitionLegal(newState: JobState): Boolean { - // Note that we always allow transitions from the state - return newState == this || when (this) { - JobState.PENDING -> newState == JobState.CLAIMED - JobState.CLAIMED -> newState == JobState.RUNNING || newState == JobState.FAILED - JobState.RUNNING -> newState == JobState.FINISHED || newState == JobState.FAILED - JobState.FINISHED, JobState.FAILED -> false - } - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/PortfolioService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/PortfolioService.kt deleted file mode 100644 index c83b7a54..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/PortfolioService.kt +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.user.Portfolio -import org.opendc.web.server.repository.PortfolioRepository -import org.opendc.web.server.repository.ProjectRepository -import java.time.Instant -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import org.opendc.web.server.model.Portfolio as PortfolioEntity - -/** - * Service for managing [Portfolio]s. - */ -@ApplicationScoped -class PortfolioService @Inject constructor( - private val projectRepository: ProjectRepository, - private val portfolioRepository: PortfolioRepository -) { - /** - * List all [Portfolio]s that belong a certain project. - */ - fun findAll(userId: String, projectId: Long): List { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) ?: return emptyList() - val project = auth.toUserDto() - return portfolioRepository.findAll(projectId).map { it.toUserDto(project) } - } - - /** - * Find a [Portfolio] with the specified [number] belonging to [project][projectId]. - */ - fun findOne(userId: String, projectId: Long, number: Int): Portfolio? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) ?: return null - return portfolioRepository.findOne(projectId, number)?.toUserDto(auth.toUserDto()) - } - - /** - * Delete the portfolio with the specified [number] belonging to [project][projectId]. - */ - fun delete(userId: String, projectId: Long, number: Int): Portfolio? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) - - if (auth == null) { - return null - } else if (!auth.role.canEdit) { - throw IllegalStateException("Not permitted to edit project") - } - - val entity = portfolioRepository.findOne(projectId, number) ?: return null - val portfolio = entity.toUserDto(auth.toUserDto()) - portfolioRepository.delete(entity) - return portfolio - } - - /** - * Construct a new [Portfolio] with the specified name. - */ - fun create(userId: String, projectId: Long, request: Portfolio.Create): Portfolio? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) - - if (auth == null) { - return null - } else if (!auth.role.canEdit) { - throw IllegalStateException("Not permitted to edit project") - } - - val now = Instant.now() - val project = auth.project - val number = projectRepository.allocatePortfolio(auth.project, now) - - val portfolio = PortfolioEntity(0, number, request.name, project, request.targets) - - project.portfolios.add(portfolio) - portfolioRepository.save(portfolio) - - return portfolio.toUserDto(auth.toUserDto()) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ProjectService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ProjectService.kt deleted file mode 100644 index 2fc5a054..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ProjectService.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.user.ProjectRole -import org.opendc.web.server.model.Project -import org.opendc.web.server.model.ProjectAuthorization -import org.opendc.web.server.model.ProjectAuthorizationKey -import org.opendc.web.server.repository.ProjectRepository -import java.time.Instant -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import org.opendc.web.proto.user.Project as ProjectDto - -/** - * Service for managing [Project]s. - */ -@ApplicationScoped -class ProjectService @Inject constructor(private val repository: ProjectRepository) { - /** - * List all projects for the user with the specified [userId]. - */ - fun findWithUser(userId: String): List { - return repository.findAll(userId).map { it.toUserDto() } - } - - /** - * Obtain the project with the specified [id] for the user with the specified [userId]. - */ - fun findWithUser(userId: String, id: Long): ProjectDto? { - return repository.findOne(userId, id)?.toUserDto() - } - - /** - * Create a new [Project] for the user with the specified [userId]. - */ - fun createForUser(userId: String, name: String): ProjectDto { - val now = Instant.now() - val entity = Project(0, name, now) - repository.save(entity) - - val authorization = ProjectAuthorization(ProjectAuthorizationKey(userId, entity.id), entity, ProjectRole.OWNER) - - entity.authorizations.add(authorization) - repository.save(authorization) - - return authorization.toUserDto() - } - - /** - * Delete a project by its identifier. - * - * @param userId The user that invokes the action. - * @param id The identifier of the project. - */ - fun deleteWithUser(userId: String, id: Long): ProjectDto? { - val auth = repository.findOne(userId, id) ?: return null - - if (!auth.role.canDelete) { - throw IllegalArgumentException("Not allowed to delete project") - } - - val now = Instant.now() - val project = auth.toUserDto().copy(updatedAt = now) - repository.delete(auth.project) - return project - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/RunnerConversions.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/RunnerConversions.kt deleted file mode 100644 index 465ac2df..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/RunnerConversions.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.server.model.Job -import org.opendc.web.server.model.Portfolio -import org.opendc.web.server.model.Scenario -import org.opendc.web.server.model.Topology - -/** - * Conversions into DTOs provided to OpenDC runners. - */ - -/** - * Convert a [Topology] into a runner-facing DTO. - */ -internal fun Topology.toRunnerDto(): org.opendc.web.proto.runner.Topology { - return org.opendc.web.proto.runner.Topology(id, number, name, rooms, createdAt, updatedAt) -} - -/** - * Convert a [Portfolio] into a runner-facing DTO. - */ -internal fun Portfolio.toRunnerDto(): org.opendc.web.proto.runner.Portfolio { - return org.opendc.web.proto.runner.Portfolio(id, number, name, targets) -} - -/** - * Convert a [Job] into a runner-facing DTO. - */ -internal fun Job.toRunnerDto(): org.opendc.web.proto.runner.Job { - return org.opendc.web.proto.runner.Job(id, scenario.toRunnerDto(), state, createdAt, updatedAt, runtime, results) -} - -/** - * Convert a [Job] into a runner-facing DTO. - */ -internal fun Scenario.toRunnerDto(): org.opendc.web.proto.runner.Scenario { - return org.opendc.web.proto.runner.Scenario( - id, - number, - portfolio.toRunnerDto(), - name, - workload.toDto(), - topology.toRunnerDto(), - phenomena, - schedulerName - ) -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ScenarioService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ScenarioService.kt deleted file mode 100644 index 083f2451..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ScenarioService.kt +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.JobState -import org.opendc.web.server.model.Job -import org.opendc.web.server.model.Scenario -import org.opendc.web.server.model.Workload -import org.opendc.web.server.repository.PortfolioRepository -import org.opendc.web.server.repository.ProjectRepository -import org.opendc.web.server.repository.ScenarioRepository -import org.opendc.web.server.repository.TopologyRepository -import org.opendc.web.server.repository.TraceRepository -import java.time.Instant -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import org.opendc.web.proto.user.Scenario as ScenarioDto - -/** - * Service for managing [Scenario]s. - */ -@ApplicationScoped -class ScenarioService @Inject constructor( - private val projectRepository: ProjectRepository, - private val portfolioRepository: PortfolioRepository, - private val topologyRepository: TopologyRepository, - private val traceRepository: TraceRepository, - private val scenarioRepository: ScenarioRepository, - private val accountingService: UserAccountingService -) { - /** - * List all [Scenario]s that belong a certain portfolio. - */ - fun findAll(userId: String, projectId: Long, number: Int): List { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) ?: return emptyList() - val project = auth.toUserDto() - return scenarioRepository.findAll(projectId).map { it.toUserDto(project) } - } - - /** - * Obtain a [Scenario] by identifier. - */ - fun findOne(userId: String, projectId: Long, number: Int): ScenarioDto? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) ?: return null - val project = auth.toUserDto() - return scenarioRepository.findOne(projectId, number)?.toUserDto(project) - } - - /** - * Delete the specified scenario. - */ - fun delete(userId: String, projectId: Long, number: Int): ScenarioDto? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) - - if (auth == null) { - return null - } else if (!auth.role.canEdit) { - throw IllegalStateException("Not permitted to edit project") - } - - val entity = scenarioRepository.findOne(projectId, number) ?: return null - val scenario = entity.toUserDto(auth.toUserDto()) - scenarioRepository.delete(entity) - return scenario - } - - /** - * Construct a new [Scenario] with the specified data. - */ - fun create(userId: String, projectId: Long, portfolioNumber: Int, request: ScenarioDto.Create): ScenarioDto? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) - - if (auth == null) { - return null - } else if (!auth.role.canEdit) { - throw IllegalStateException("Not permitted to edit project") - } - - val portfolio = portfolioRepository.findOne(projectId, portfolioNumber) ?: return null - val topology = requireNotNull( - topologyRepository.findOne( - projectId, - request.topology.toInt() - ) - ) { "Referred topology does not exist" } - val trace = - requireNotNull(traceRepository.findOne(request.workload.trace)) { "Referred trace does not exist" } - - val now = Instant.now() - val project = auth.project - val number = projectRepository.allocateScenario(auth.project, now) - - val scenario = Scenario( - 0, - number, - request.name, - project, - portfolio, - Workload(trace, request.workload.samplingFraction), - topology, - request.phenomena, - request.schedulerName - ) - val job = Job(0, userId, scenario, now, portfolio.targets.repeats) - - // Fail the job if there is not enough budget for the simulation - if (!accountingService.hasSimulationBudget(userId)) { - job.state = JobState.FAILED - } - - scenario.job = job - portfolio.scenarios.add(scenario) - scenarioRepository.save(scenario) - - return scenario.toUserDto(auth.toUserDto()) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TopologyService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TopologyService.kt deleted file mode 100644 index 5c2a457a..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TopologyService.kt +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.user.Topology -import org.opendc.web.server.repository.ProjectRepository -import org.opendc.web.server.repository.TopologyRepository -import java.time.Instant -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import org.opendc.web.server.model.Topology as TopologyEntity - -/** - * Service for managing [Topology]s. - */ -@ApplicationScoped -class TopologyService @Inject constructor( - private val projectRepository: ProjectRepository, - private val topologyRepository: TopologyRepository -) { - /** - * List all [Topology]s that belong a certain project. - */ - fun findAll(userId: String, projectId: Long): List { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) ?: return emptyList() - val project = auth.toUserDto() - return topologyRepository.findAll(projectId).map { it.toUserDto(project) } - } - - /** - * Find the [Topology] with the specified [number] belonging to [project][projectId]. - */ - fun findOne(userId: String, projectId: Long, number: Int): Topology? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) ?: return null - return topologyRepository.findOne(projectId, number)?.toUserDto(auth.toUserDto()) - } - - /** - * Delete the [Topology] with the specified [number] belonging to [project][projectId]. - */ - fun delete(userId: String, projectId: Long, number: Int): Topology? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) - - if (auth == null) { - return null - } else if (!auth.role.canEdit) { - throw IllegalStateException("Not permitted to edit project") - } - - val entity = topologyRepository.findOne(projectId, number) ?: return null - val now = Instant.now() - val topology = entity.toUserDto(auth.toUserDto()).copy(updatedAt = now) - topologyRepository.delete(entity) - - return topology - } - - /** - * Update a [Topology] with the specified [number] belonging to [project][projectId]. - */ - fun update(userId: String, projectId: Long, number: Int, request: Topology.Update): Topology? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) - - if (auth == null) { - return null - } else if (!auth.role.canEdit) { - throw IllegalStateException("Not permitted to edit project") - } - - val entity = topologyRepository.findOne(projectId, number) ?: return null - val now = Instant.now() - - entity.updatedAt = now - entity.rooms = request.rooms - - return entity.toUserDto(auth.toUserDto()) - } - - /** - * Construct a new [Topology] with the specified name. - */ - fun create(userId: String, projectId: Long, request: Topology.Create): Topology? { - // User must have access to project - val auth = projectRepository.findOne(userId, projectId) - - if (auth == null) { - return null - } else if (!auth.role.canEdit) { - throw IllegalStateException("Not permitted to edit project") - } - - val now = Instant.now() - val project = auth.project - val number = projectRepository.allocateTopology(auth.project, now) - - val topology = TopologyEntity(0, number, request.name, project, now, request.rooms) - - project.topologies.add(topology) - topologyRepository.save(topology) - - return topology.toUserDto(auth.toUserDto()) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TraceService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TraceService.kt deleted file mode 100644 index bd14950c..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TraceService.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.Trace -import org.opendc.web.server.repository.TraceRepository -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject - -/** - * Service for managing [Trace]s. - */ -@ApplicationScoped -class TraceService @Inject constructor(private val repository: TraceRepository) { - /** - * Obtain all available workload traces. - */ - fun findAll(): List { - return repository.findAll().map { it.toUserDto() } - } - - /** - * Obtain a workload trace by identifier. - */ - fun findById(id: String): Trace? { - return repository.findOne(id)?.toUserDto() - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt deleted file mode 100644 index 11066bfb..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.eclipse.microprofile.config.inject.ConfigProperty -import org.opendc.web.server.model.UserAccounting -import org.opendc.web.server.repository.UserAccountingRepository -import java.time.Duration -import java.time.LocalDate -import java.time.temporal.TemporalAdjusters -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject -import javax.persistence.EntityExistsException -import org.opendc.web.proto.user.UserAccounting as UserAccountingDto - -/** - * Service for tracking the simulation budget of users. - * - * @param repository The [UserAccountingRepository] used to communicate with the database. - * @param simulationBudget The default simulation budget for new users. - */ -@ApplicationScoped -class UserAccountingService @Inject constructor( - private val repository: UserAccountingRepository, - @ConfigProperty(name = "opendc.accounting.simulation-budget", defaultValue = "2000m") - private val simulationBudget: Duration -) { - /** - * Return the [UserAccountingDto] object for the user with the specified [userId]. If the object does not exist in the - * database, a default value is constructed. - */ - fun getAccounting(userId: String): UserAccountingDto { - val accounting = repository.findForUser(userId) - return if (accounting != null) { - UserAccountingDto(accounting.periodEnd, accounting.simulationTime, accounting.simulationTimeBudget) - } else { - UserAccountingDto(getNextAccountingPeriod(), 0, simulationBudget.toSeconds().toInt()) - } - } - - /** - * Determine whether the user with [userId] has any remaining simulation budget. - * - * @param userId The unique identifier of the user. - * @return `true` when the user still has budget left, `false` otherwise. - */ - fun hasSimulationBudget(userId: String): Boolean { - val accounting = repository.findForUser(userId) ?: return true - val today = LocalDate.now() - - // The accounting period must be over or there must be budget remaining. - return !today.isBefore(accounting.periodEnd) || accounting.simulationTimeBudget > accounting.simulationTime - } - - /** - * Consume [seconds] from the simulation budget of the user with [userId]. - * - * @param userId The unique identifier of the user. - * @param seconds The seconds to consume from the simulation budget. - * @param `true` if the user has consumed his full budget or `false` if there is still budget remaining. - */ - fun consumeSimulationBudget(userId: String, seconds: Int): Boolean { - val today = LocalDate.now() - val nextAccountingPeriod = getNextAccountingPeriod(today) - val repository = repository - - // We need to be careful to prevent conflicts in case of concurrency - // 1. First, we try to create the accounting object if it does not exist yet. This may fail if another instance - // creates the object concurrently. - // 2. Second, we check if the budget needs to be reset and try this atomically. - // 3. Finally, we atomically consume the budget from the object - // This is repeated three times in case there is a conflict - repeat(3) { - val accounting = repository.findForUser(userId) - - if (accounting == null) { - try { - val newAccounting = UserAccounting(userId, nextAccountingPeriod, simulationBudget.toSeconds().toInt()) - newAccounting.simulationTime = seconds - repository.save(newAccounting) - - return newAccounting.simulationTime >= newAccounting.simulationTimeBudget - } catch (e: EntityExistsException) { - // Conflict due to concurrency; retry - } - } else { - val success = if (!today.isBefore(accounting.periodEnd)) { - repository.resetBudget(accounting, nextAccountingPeriod, seconds) - } else { - repository.consumeBudget(accounting, seconds) - } - - if (success) { - return accounting.simulationTimeBudget <= accounting.simulationTime - } - } - } - - throw IllegalStateException("Failed to allocate consume budget due to conflict") - } - - /** - * Helper method to find next accounting period. - */ - private fun getNextAccountingPeriod(today: LocalDate = LocalDate.now()): LocalDate { - return today.with(TemporalAdjusters.firstDayOfNextMonth()) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserConversions.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserConversions.kt deleted file mode 100644 index e28d9c0f..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserConversions.kt +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.user.Project -import org.opendc.web.server.model.Job -import org.opendc.web.server.model.Portfolio -import org.opendc.web.server.model.ProjectAuthorization -import org.opendc.web.server.model.Scenario -import org.opendc.web.server.model.Topology -import org.opendc.web.server.model.Trace -import org.opendc.web.server.model.Workload - -/** - * Conversions into DTOs provided to users. - */ - -/** - * Convert a [Trace] entity into a [org.opendc.web.proto.Trace] DTO. - */ -internal fun Trace.toUserDto(): org.opendc.web.proto.Trace { - return org.opendc.web.proto.Trace(id, name, type) -} - -/** - * Convert a [ProjectAuthorization] entity into a [Project] DTO. - */ -internal fun ProjectAuthorization.toUserDto(): Project { - return Project(project.id, project.name, project.createdAt, project.updatedAt, role) -} - -/** - * Convert a [Topology] entity into a [org.opendc.web.proto.user.Topology] DTO. - */ -internal fun Topology.toUserDto(project: Project): org.opendc.web.proto.user.Topology { - return org.opendc.web.proto.user.Topology(id, number, project, name, rooms, createdAt, updatedAt) -} - -/** - * Convert a [Topology] entity into a [org.opendc.web.proto.user.Topology.Summary] DTO. - */ -private fun Topology.toSummaryDto(): org.opendc.web.proto.user.Topology.Summary { - return org.opendc.web.proto.user.Topology.Summary(id, number, name, createdAt, updatedAt) -} - -/** - * Convert a [Portfolio] entity into a [org.opendc.web.proto.user.Portfolio] DTO. - */ -internal fun Portfolio.toUserDto(project: Project): org.opendc.web.proto.user.Portfolio { - return org.opendc.web.proto.user.Portfolio(id, number, project, name, targets, scenarios.map { it.toSummaryDto() }) -} - -/** - * Convert a [Portfolio] entity into a [org.opendc.web.proto.user.Portfolio.Summary] DTO. - */ -private fun Portfolio.toSummaryDto(): org.opendc.web.proto.user.Portfolio.Summary { - return org.opendc.web.proto.user.Portfolio.Summary(id, number, name, targets) -} - -/** - * Convert a [Scenario] entity into a [org.opendc.web.proto.user.Scenario] DTO. - */ -internal fun Scenario.toUserDto(project: Project): org.opendc.web.proto.user.Scenario { - return org.opendc.web.proto.user.Scenario( - id, - number, - project, - portfolio.toSummaryDto(), - name, - workload.toDto(), - topology.toSummaryDto(), - phenomena, - schedulerName, - job.toUserDto() - ) -} - -/** - * Convert a [Scenario] entity into a [org.opendc.web.proto.user.Scenario.Summary] DTO. - */ -private fun Scenario.toSummaryDto(): org.opendc.web.proto.user.Scenario.Summary { - return org.opendc.web.proto.user.Scenario.Summary( - id, - number, - name, - workload.toDto(), - topology.toSummaryDto(), - phenomena, - schedulerName, - job.toUserDto() - ) -} - -/** - * Convert a [Job] entity into a [org.opendc.web.proto.user.Job] DTO. - */ -internal fun Job.toUserDto(): org.opendc.web.proto.user.Job { - return org.opendc.web.proto.user.Job(id, state, createdAt, updatedAt, results) -} - -/** - * Convert a [Workload] entity into a DTO. - */ -internal fun Workload.toDto(): org.opendc.web.proto.Workload { - return org.opendc.web.proto.Workload(trace.toUserDto(), samplingFraction) -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt deleted file mode 100644 index 39352267..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import io.quarkus.security.identity.SecurityIdentity -import org.opendc.web.proto.user.User -import javax.enterprise.context.ApplicationScoped -import javax.inject.Inject - -/** - * Service for managing [User]s. - */ -@ApplicationScoped -class UserService @Inject constructor(private val accounting: UserAccountingService) { - /** - * Obtain the [User] object for the specified [identity]. - */ - fun getUser(identity: SecurityIdentity): User { - val userId = identity.principal.name - val accounting = accounting.getAccounting(userId) - - return User(userId, accounting) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/Utils.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/Utils.kt deleted file mode 100644 index 2d0da3b3..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/Utils.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service - -import org.opendc.web.proto.user.ProjectRole - -/** - * Flag to indicate that the user can edit a project. - */ -internal val ProjectRole.canEdit: Boolean - get() = when (this) { - ProjectRole.OWNER, ProjectRole.EDITOR -> true - ProjectRole.VIEWER -> false - } - -/** - * Flag to indicate that the user can delete a project. - */ -internal val ProjectRole.canDelete: Boolean - get() = this == ProjectRole.OWNER -- cgit v1.2.3 From 6927c51885bb3073b310150c4f40c64eea44a919 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 22 Jan 2023 00:30:51 +0000 Subject: refactor(web/server): Convert resources to Java This change converts the resource classes of the OpenDC web server to use Java, The Quarkus integration for Java is more mature and the programming quality of experience is not that much worse. --- .../org/opendc/web/server/OpenDCApplication.kt | 30 ------- .../opendc/web/server/rest/SchedulerResource.kt | 48 ----------- .../org/opendc/web/server/rest/TraceResource.kt | 54 ------------- .../error/MissingKotlinParameterExceptionMapper.kt | 43 ---------- .../rest/error/WebApplicationExceptionMapper.kt | 45 ----------- .../opendc/web/server/rest/runner/JobResource.kt | 76 ----------------- .../web/server/rest/user/PortfolioResource.kt | 83 ------------------- .../server/rest/user/PortfolioScenarioResource.kt | 63 --------------- .../opendc/web/server/rest/user/ProjectResource.kt | 87 -------------------- .../web/server/rest/user/ScenarioResource.kt | 64 --------------- .../web/server/rest/user/TopologyResource.kt | 94 ---------------------- .../opendc/web/server/rest/user/UserResource.kt | 45 ----------- .../web/server/util/KotlinModuleCustomizer.kt | 38 --------- 13 files changed, 770 deletions(-) delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/OpenDCApplication.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/SchedulerResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/TraceResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioScenarioResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ScenarioResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/TopologyResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt delete mode 100644 opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/KotlinModuleCustomizer.kt (limited to 'opendc-web/opendc-web-server/src/main/kotlin') diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/OpenDCApplication.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/OpenDCApplication.kt deleted file mode 100644 index 1a426095..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/OpenDCApplication.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server - -import javax.ws.rs.core.Application - -/** - * [Application] definition for the OpenDC web API. - */ -class OpenDCApplication : Application() diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/SchedulerResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/SchedulerResource.kt deleted file mode 100644 index 919b25fc..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/SchedulerResource.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest - -import javax.ws.rs.GET -import javax.ws.rs.Path - -/** - * A resource representing the available schedulers that can be used during experiments. - */ -@Path("/schedulers") -class SchedulerResource { - /** - * Obtain all available schedulers. - */ - @GET - fun getAll() = listOf( - "mem", - "mem-inv", - "core-mem", - "core-mem-inv", - "active-servers", - "active-servers-inv", - "provisioned-cores", - "provisioned-cores-inv", - "random" - ) -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/TraceResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/TraceResource.kt deleted file mode 100644 index a33bd8f1..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/TraceResource.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest - -import org.opendc.web.proto.Trace -import org.opendc.web.server.service.TraceService -import javax.inject.Inject -import javax.ws.rs.GET -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.WebApplicationException - -/** - * A resource representing the workload traces available in the OpenDC instance. - */ -@Path("/traces") -class TraceResource @Inject constructor(private val traceService: TraceService) { - /** - * Obtain all available traces. - */ - @GET - fun getAll(): List { - return traceService.findAll() - } - - /** - * Obtain trace information by identifier. - */ - @GET - @Path("{id}") - fun get(@PathParam("id") id: String): Trace { - return traceService.findById(id) ?: throw WebApplicationException("Trace not found", 404) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.kt deleted file mode 100644 index e50917aa..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.error - -import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException -import org.opendc.web.proto.ProtocolError -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import javax.ws.rs.ext.ExceptionMapper -import javax.ws.rs.ext.Provider - -/** - * An [ExceptionMapper] for [MissingKotlinParameterException] thrown by Jackson. - */ -@Provider -class MissingKotlinParameterExceptionMapper : ExceptionMapper { - override fun toResponse(exception: MissingKotlinParameterException): Response { - return Response.status(Response.Status.BAD_REQUEST) - .entity(ProtocolError(Response.Status.BAD_REQUEST.statusCode, "Field '${exception.parameter.name}' is missing from body.")) - .type(MediaType.APPLICATION_JSON) - .build() - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.kt deleted file mode 100644 index aa046abf..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.error - -import org.opendc.web.proto.ProtocolError -import javax.ws.rs.WebApplicationException -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import javax.ws.rs.ext.ExceptionMapper -import javax.ws.rs.ext.Provider - -/** - * Helper class to transform a [WebApplicationException] into an JSON error response. - */ -@Provider -class WebApplicationExceptionMapper : ExceptionMapper { - override fun toResponse(exception: WebApplicationException): Response { - val code = exception.response.status - - return Response.status(code) - .entity(ProtocolError(code, exception.message ?: "Unknown error")) - .type(MediaType.APPLICATION_JSON) - .build() - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt deleted file mode 100644 index 1e9abc14..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.runner - -import org.opendc.web.proto.runner.Job -import org.opendc.web.server.service.JobService -import javax.annotation.security.RolesAllowed -import javax.inject.Inject -import javax.transaction.Transactional -import javax.validation.Valid -import javax.ws.rs.GET -import javax.ws.rs.POST -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.WebApplicationException - -/** - * A resource representing the available simulation jobs. - */ -@Path("/jobs") -@RolesAllowed("runner") -class JobResource @Inject constructor(private val jobService: JobService) { - /** - * Obtain all pending simulation jobs. - */ - @GET - fun queryPending(): List { - return jobService.listPending() - } - - /** - * Get a job by identifier. - */ - @GET - @Path("{job}") - fun get(@PathParam("job") id: Long): Job { - return jobService.findById(id) ?: throw WebApplicationException("Job not found", 404) - } - - /** - * Atomically update the state of a job. - */ - @POST - @Path("{job}") - @Transactional - fun update(@PathParam("job") id: Long, @Valid update: Job.Update): Job { - return try { - jobService.updateState(id, update.state, update.runtime, update.results) - ?: throw WebApplicationException("Job not found", 404) - } catch (e: IllegalArgumentException) { - throw WebApplicationException(e, 400) - } catch (e: IllegalStateException) { - throw WebApplicationException(e, 409) - } - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt deleted file mode 100644 index 82843a5a..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.user - -import io.quarkus.security.identity.SecurityIdentity -import org.opendc.web.proto.user.Portfolio -import org.opendc.web.server.service.PortfolioService -import javax.annotation.security.RolesAllowed -import javax.inject.Inject -import javax.transaction.Transactional -import javax.validation.Valid -import javax.ws.rs.DELETE -import javax.ws.rs.GET -import javax.ws.rs.POST -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.WebApplicationException - -/** - * A resource representing the portfolios of a project. - */ -@Path("/projects/{project}/portfolios") -@RolesAllowed("openid") -class PortfolioResource @Inject constructor( - private val portfolioService: PortfolioService, - private val identity: SecurityIdentity -) { - /** - * Get all portfolios that belong to the specified project. - */ - @GET - fun getAll(@PathParam("project") projectId: Long): List { - return portfolioService.findByUser(identity.principal.name, projectId) - } - - /** - * Create a portfolio for this project. - */ - @POST - @Transactional - fun create(@PathParam("project") projectId: Long, @Valid request: Portfolio.Create): Portfolio { - return portfolioService.create(identity.principal.name, projectId, request) ?: throw WebApplicationException("Project not found", 404) - } - - /** - * Obtain a portfolio by its identifier. - */ - @GET - @Path("{portfolio}") - fun get(@PathParam("project") projectId: Long, @PathParam("portfolio") number: Int): Portfolio { - return portfolioService.findByUser(identity.principal.name, projectId, number) ?: throw WebApplicationException("Portfolio not found", 404) - } - - /** - * Delete a portfolio. - */ - @DELETE - @Path("{portfolio}") - @Transactional - fun delete(@PathParam("project") projectId: Long, @PathParam("portfolio") number: Int): Portfolio { - return portfolioService.delete(identity.principal.name, projectId, number) ?: throw WebApplicationException("Portfolio not found", 404) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioScenarioResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioScenarioResource.kt deleted file mode 100644 index 82f35127..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioScenarioResource.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.user - -import io.quarkus.security.identity.SecurityIdentity -import org.opendc.web.proto.user.Scenario -import org.opendc.web.server.service.ScenarioService -import javax.annotation.security.RolesAllowed -import javax.inject.Inject -import javax.transaction.Transactional -import javax.validation.Valid -import javax.ws.rs.GET -import javax.ws.rs.POST -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.WebApplicationException - -/** - * A resource representing the scenarios of a portfolio. - */ -@Path("/projects/{project}/portfolios/{portfolio}/scenarios") -@RolesAllowed("openid") -class PortfolioScenarioResource @Inject constructor( - private val scenarioService: ScenarioService, - private val identity: SecurityIdentity -) { - /** - * Get all scenarios that belong to the specified portfolio. - */ - @GET - fun get(@PathParam("project") projectId: Long, @PathParam("portfolio") portfolioNumber: Int): List { - return scenarioService.findAll(identity.principal.name, projectId, portfolioNumber) - } - - /** - * Create a scenario for this portfolio. - */ - @POST - @Transactional - fun create(@PathParam("project") projectId: Long, @PathParam("portfolio") portfolioNumber: Int, @Valid request: Scenario.Create): Scenario { - return scenarioService.create(identity.principal.name, projectId, portfolioNumber, request) ?: throw WebApplicationException("Portfolio not found", 404) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt deleted file mode 100644 index d12fc690..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.user - -import io.quarkus.security.identity.SecurityIdentity -import org.opendc.web.proto.user.Project -import org.opendc.web.server.service.ProjectService -import javax.annotation.security.RolesAllowed -import javax.inject.Inject -import javax.transaction.Transactional -import javax.validation.Valid -import javax.ws.rs.DELETE -import javax.ws.rs.GET -import javax.ws.rs.POST -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.WebApplicationException - -/** - * A resource representing the created projects. - */ -@Path("/projects") -@RolesAllowed("openid") -class ProjectResource @Inject constructor( - private val projectService: ProjectService, - private val identity: SecurityIdentity -) { - /** - * Obtain all the projects of the current user. - */ - @GET - fun getAll(): List { - return projectService.findByUser(identity.principal.name) - } - - /** - * Create a new project for the current user. - */ - @POST - @Transactional - fun create(@Valid request: Project.Create): Project { - return projectService.create(identity.principal.name, request.name) - } - - /** - * Obtain a single project by its identifier. - */ - @GET - @Path("{project}") - fun get(@PathParam("project") id: Long): Project { - return projectService.findByUser(identity.principal.name, id) ?: throw WebApplicationException("Project not found", 404) - } - - /** - * Delete a project. - */ - @DELETE - @Path("{project}") - @Transactional - fun delete(@PathParam("project") id: Long): Project { - try { - return projectService.delete(identity.principal.name, id) ?: throw WebApplicationException("Project not found", 404) - } catch (e: IllegalArgumentException) { - throw WebApplicationException(e.message, 403) - } - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ScenarioResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ScenarioResource.kt deleted file mode 100644 index 56bb4290..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ScenarioResource.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.user - -import io.quarkus.security.identity.SecurityIdentity -import org.opendc.web.proto.user.Scenario -import org.opendc.web.server.service.ScenarioService -import javax.annotation.security.RolesAllowed -import javax.inject.Inject -import javax.transaction.Transactional -import javax.ws.rs.DELETE -import javax.ws.rs.GET -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.WebApplicationException - -/** - * A resource representing the scenarios of a portfolio. - */ -@Path("/projects/{project}/scenarios") -@RolesAllowed("openid") -class ScenarioResource @Inject constructor( - private val scenarioService: ScenarioService, - private val identity: SecurityIdentity -) { - /** - * Obtain a scenario by its identifier. - */ - @GET - @Path("{scenario}") - fun get(@PathParam("project") projectId: Long, @PathParam("scenario") number: Int): Scenario { - return scenarioService.findOne(identity.principal.name, projectId, number) ?: throw WebApplicationException("Scenario not found", 404) - } - - /** - * Delete a scenario. - */ - @DELETE - @Path("{scenario}") - @Transactional - fun delete(@PathParam("project") projectId: Long, @PathParam("scenario") number: Int): Scenario { - return scenarioService.delete(identity.principal.name, projectId, number) ?: throw WebApplicationException("Scenario not found", 404) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/TopologyResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/TopologyResource.kt deleted file mode 100644 index 8eef66c8..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/TopologyResource.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.user - -import io.quarkus.security.identity.SecurityIdentity -import org.opendc.web.proto.user.Topology -import org.opendc.web.server.service.TopologyService -import javax.annotation.security.RolesAllowed -import javax.inject.Inject -import javax.transaction.Transactional -import javax.validation.Valid -import javax.ws.rs.DELETE -import javax.ws.rs.GET -import javax.ws.rs.POST -import javax.ws.rs.PUT -import javax.ws.rs.Path -import javax.ws.rs.PathParam -import javax.ws.rs.WebApplicationException - -/** - * A resource representing the constructed datacenter topologies. - */ -@Path("/projects/{project}/topologies") -@RolesAllowed("openid") -class TopologyResource @Inject constructor( - private val topologyService: TopologyService, - private val identity: SecurityIdentity -) { - /** - * Get all topologies that belong to the specified project. - */ - @GET - fun getAll(@PathParam("project") projectId: Long): List { - return topologyService.findAll(identity.principal.name, projectId) - } - - /** - * Create a topology for this project. - */ - @POST - @Transactional - fun create(@PathParam("project") projectId: Long, @Valid request: Topology.Create): Topology { - return topologyService.create(identity.principal.name, projectId, request) ?: throw WebApplicationException("Topology not found", 404) - } - - /** - * Obtain a topology by its number. - */ - @GET - @Path("{topology}") - fun get(@PathParam("project") projectId: Long, @PathParam("topology") number: Int): Topology { - return topologyService.findOne(identity.principal.name, projectId, number) ?: throw WebApplicationException("Topology not found", 404) - } - - /** - * Update the specified topology by its number. - */ - @PUT - @Path("{topology}") - @Transactional - fun update(@PathParam("project") projectId: Long, @PathParam("topology") number: Int, @Valid request: Topology.Update): Topology { - return topologyService.update(identity.principal.name, projectId, number, request) ?: throw WebApplicationException("Topology not found", 404) - } - - /** - * Delete the specified topology. - */ - @Path("{topology}") - @DELETE - @Transactional - fun delete(@PathParam("project") projectId: Long, @PathParam("topology") number: Int): Topology { - return topologyService.delete(identity.principal.name, projectId, number) ?: throw WebApplicationException("Topology not found", 404) - } -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt deleted file mode 100644 index d640cc08..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/UserResource.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.rest.user - -import io.quarkus.security.identity.SecurityIdentity -import org.opendc.web.proto.user.User -import org.opendc.web.server.service.UserService -import javax.annotation.security.RolesAllowed -import javax.inject.Inject -import javax.ws.rs.GET -import javax.ws.rs.Path - -/** - * A resource representing the active user. - */ -@Path("/users") -@RolesAllowed("openid") -class UserResource @Inject constructor(private val userService: UserService, private val identity: SecurityIdentity) { - /** - * Get the current active user data. - */ - @GET - @Path("me") - fun get(): User = userService.getUser(identity) -} diff --git a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/KotlinModuleCustomizer.kt b/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/KotlinModuleCustomizer.kt deleted file mode 100644 index 8634c8a4..00000000 --- a/opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/util/KotlinModuleCustomizer.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.util - -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.kotlin.KotlinModule -import io.quarkus.jackson.ObjectMapperCustomizer -import javax.inject.Singleton - -/** - * Helper class to register the Kotlin Jackson module. - */ -@Singleton -class KotlinModuleCustomizer : ObjectMapperCustomizer { - override fun customize(objectMapper: ObjectMapper) { - objectMapper.registerModule(KotlinModule.Builder().build()) - } -} -- cgit v1.2.3