summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-server/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-web/opendc-web-server/src/main/kotlin')
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Job.kt111
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Portfolio.kt100
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Project.kt144
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorization.kt64
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/ProjectAuthorizationKey.kt38
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Scenario.kt118
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Topology.kt100
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Trace.kt63
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/UserAccounting.kt81
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/model/Workload.kt39
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/JobRepository.kt94
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/PortfolioRepository.kt76
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ProjectRepository.kt157
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/ScenarioRepository.kt90
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TopologyRepository.kt86
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/TraceRepository.kt53
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/repository/UserAccountingRepository.kt88
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/runner/JobResource.kt2
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/PortfolioResource.kt4
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/rest/user/ProjectResource.kt8
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/JobService.kt97
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/PortfolioService.kt103
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ProjectService.kt88
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/RunnerConversions.kt69
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/ScenarioService.kt141
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TopologyService.kt127
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/TraceService.kt48
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserAccountingService.kt128
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserConversions.kt126
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/UserService.kt44
-rw-r--r--opendc-web/opendc-web-server/src/main/kotlin/org/opendc/web/server/service/Utils.kt40
31 files changed, 7 insertions, 2520 deletions
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<String, Any>? = 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<Scenario> = 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<Portfolio> = 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<Topology> = 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<Scenario> = 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<ProjectAuthorization> = 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<Room> = 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<Job> {
- 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<String, Any>?): 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<Portfolio> {
- 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<ProjectAuthorization> {
- 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<Scenario> {
- 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<Scenario> {
- 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<Topology> {
- 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<Trace> {
- 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<Job> {
- 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<Portfolio> {
- 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<Project> {
- 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<Job> {
- 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<String, Any>?): 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<Portfolio> {
- // 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<ProjectDto> {
- 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<ScenarioDto> {
- // 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<Topology> {
- // 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<Trace> {
- 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