mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-12-31 02:46:16 +01:00
Remove support for mysql/mariadb
This commit is contained in:
11
README.md
11
README.md
@@ -29,12 +29,11 @@ is also served by the backend using [Svelte](https://svelte.dev/) components.
|
|||||||
Layout and styling are based on [Bootstrap 5](https://getbootstrap.com/) using
|
Layout and styling are based on [Bootstrap 5](https://getbootstrap.com/) using
|
||||||
[Bootstrap Icons](https://icons.getbootstrap.com/).
|
[Bootstrap Icons](https://icons.getbootstrap.com/).
|
||||||
|
|
||||||
The backend uses [SQLite 3](https://sqlite.org/) as a relational SQL database by
|
The backend uses [SQLite 3](https://sqlite.org/) as the relational SQL database.
|
||||||
default. Optionally it can use a MySQL/MariaDB database server. While there are
|
While there are metric data backends for the InfluxDB and Prometheus time series
|
||||||
metric data backends for the InfluxDB and Prometheus time series databases, the
|
databases, the only tested and supported setup is to use cc-metric-store as the
|
||||||
only tested and supported setup is to use cc-metric-store as the metric data
|
metric data backend. Documentation on how to integrate ClusterCockpit with other
|
||||||
backend. Documentation on how to integrate ClusterCockpit with other time series
|
time series databases will be added in the future.
|
||||||
databases will be added in the future.
|
|
||||||
|
|
||||||
Completed batch jobs are stored in a file-based job archive according to
|
Completed batch jobs are stored in a file-based job archive according to
|
||||||
[this specification](https://github.com/ClusterCockpit/cc-specifications/tree/master/job-archive).
|
[this specification](https://github.com/ClusterCockpit/cc-specifications/tree/master/job-archive).
|
||||||
|
|||||||
@@ -105,9 +105,9 @@ func initEnv() {
|
|||||||
cclog.Abortf("Could not create default ./var folder with permissions '0o777'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
cclog.Abortf("Could not create default ./var folder with permissions '0o777'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
err := repository.MigrateDB("sqlite3", "./var/job.db")
|
err := repository.MigrateDB("./var/job.db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cclog.Abortf("Could not initialize default sqlite3 database as './var/job.db'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
cclog.Abortf("Could not initialize default SQLite database as './var/job.db'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
if err := os.Mkdir("var/job-archive", 0o777); err != nil {
|
if err := os.Mkdir("var/job-archive", 0o777); err != nil {
|
||||||
cclog.Abortf("Could not create default ./var/job-archive folder with permissions '0o777'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
cclog.Abortf("Could not create default ./var/job-archive folder with permissions '0o777'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import (
|
|||||||
"github.com/google/gops/agent"
|
"github.com/google/gops/agent"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -120,30 +119,30 @@ func initDatabase() error {
|
|||||||
|
|
||||||
func handleDatabaseCommands() error {
|
func handleDatabaseCommands() error {
|
||||||
if flagMigrateDB {
|
if flagMigrateDB {
|
||||||
err := repository.MigrateDB(config.Keys.DBDriver, config.Keys.DB)
|
err := repository.MigrateDB(config.Keys.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("migrating database to version %d: %w", repository.Version, err)
|
return fmt.Errorf("migrating database to version %d: %w", repository.Version, err)
|
||||||
}
|
}
|
||||||
cclog.Exitf("MigrateDB Success: Migrated '%s' database at location '%s' to version %d.\n",
|
cclog.Exitf("MigrateDB Success: Migrated SQLite database at '%s' to version %d.\n",
|
||||||
config.Keys.DBDriver, config.Keys.DB, repository.Version)
|
config.Keys.DB, repository.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
if flagRevertDB {
|
if flagRevertDB {
|
||||||
err := repository.RevertDB(config.Keys.DBDriver, config.Keys.DB)
|
err := repository.RevertDB(config.Keys.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reverting database to version %d: %w", repository.Version-1, err)
|
return fmt.Errorf("reverting database to version %d: %w", repository.Version-1, err)
|
||||||
}
|
}
|
||||||
cclog.Exitf("RevertDB Success: Reverted '%s' database at location '%s' to version %d.\n",
|
cclog.Exitf("RevertDB Success: Reverted SQLite database at '%s' to version %d.\n",
|
||||||
config.Keys.DBDriver, config.Keys.DB, repository.Version-1)
|
config.Keys.DB, repository.Version-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if flagForceDB {
|
if flagForceDB {
|
||||||
err := repository.ForceDB(config.Keys.DBDriver, config.Keys.DB)
|
err := repository.ForceDB(config.Keys.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("forcing database to version %d: %w", repository.Version, err)
|
return fmt.Errorf("forcing database to version %d: %w", repository.Version, err)
|
||||||
}
|
}
|
||||||
cclog.Exitf("ForceDB Success: Forced '%s' database at location '%s' to version %d.\n",
|
cclog.Exitf("ForceDB Success: Forced SQLite database at '%s' to version %d.\n",
|
||||||
config.Keys.DBDriver, config.Keys.DB, repository.Version)
|
config.Keys.DB, repository.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
{
|
|
||||||
"addr": "127.0.0.1:8080",
|
|
||||||
"short-running-jobs-duration": 300,
|
|
||||||
"archive": {
|
|
||||||
"kind": "file",
|
|
||||||
"path": "./var/job-archive"
|
|
||||||
},
|
|
||||||
"jwts": {
|
|
||||||
"max-age": "2000h"
|
|
||||||
},
|
|
||||||
"db-driver": "mysql",
|
|
||||||
"db": "clustercockpit:demo@tcp(127.0.0.1:3306)/clustercockpit",
|
|
||||||
"enable-resampling": {
|
|
||||||
"trigger": 30,
|
|
||||||
"resolutions": [600, 300, 120, 60]
|
|
||||||
},
|
|
||||||
"emission-constant": 317,
|
|
||||||
"clusters": [
|
|
||||||
{
|
|
||||||
"name": "fritz",
|
|
||||||
"metricDataRepository": {
|
|
||||||
"kind": "cc-metric-store",
|
|
||||||
"url": "http://localhost:8082",
|
|
||||||
"token": ""
|
|
||||||
},
|
|
||||||
"filterRanges": {
|
|
||||||
"numNodes": {
|
|
||||||
"from": 1,
|
|
||||||
"to": 64
|
|
||||||
},
|
|
||||||
"duration": {
|
|
||||||
"from": 0,
|
|
||||||
"to": 86400
|
|
||||||
},
|
|
||||||
"startTime": {
|
|
||||||
"from": "2022-01-01T00:00:00Z",
|
|
||||||
"to": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "alex",
|
|
||||||
"metricDataRepository": {
|
|
||||||
"kind": "cc-metric-store",
|
|
||||||
"url": "http://localhost:8082",
|
|
||||||
"token": ""
|
|
||||||
},
|
|
||||||
"filterRanges": {
|
|
||||||
"numNodes": {
|
|
||||||
"from": 1,
|
|
||||||
"to": 64
|
|
||||||
},
|
|
||||||
"duration": {
|
|
||||||
"from": 0,
|
|
||||||
"to": 86400
|
|
||||||
},
|
|
||||||
"startTime": {
|
|
||||||
"from": "2022-01-01T00:00:00Z",
|
|
||||||
"to": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
2
go.mod
2
go.mod
@@ -21,7 +21,6 @@ require (
|
|||||||
github.com/expr-lang/expr v1.17.6
|
github.com/expr-lang/expr v1.17.6
|
||||||
github.com/go-co-op/gocron/v2 v2.18.2
|
github.com/go-co-op/gocron/v2 v2.18.2
|
||||||
github.com/go-ldap/ldap/v3 v3.4.12
|
github.com/go-ldap/ldap/v3 v3.4.12
|
||||||
github.com/go-sql-driver/mysql v1.9.3
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||||
github.com/golang-migrate/migrate/v4 v4.19.1
|
github.com/golang-migrate/migrate/v4 v4.19.1
|
||||||
github.com/google/gops v0.3.28
|
github.com/google/gops v0.3.28
|
||||||
@@ -48,7 +47,6 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
github.com/agnivade/levenshtein v1.2.1 // indirect
|
github.com/agnivade/levenshtein v1.2.1 // indirect
|
||||||
|
|||||||
49
go.sum
49
go.sum
@@ -2,8 +2,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
|||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
github.com/99designs/gqlgen v0.17.84 h1:iVMdiStgUVx/BFkMb0J5GAXlqfqtQ7bqMCYK6v52kQ0=
|
github.com/99designs/gqlgen v0.17.84 h1:iVMdiStgUVx/BFkMb0J5GAXlqfqtQ7bqMCYK6v52kQ0=
|
||||||
github.com/99designs/gqlgen v0.17.84/go.mod h1:qjoUqzTeiejdo+bwUg8unqSpeYG42XrcrQboGIezmFA=
|
github.com/99designs/gqlgen v0.17.84/go.mod h1:qjoUqzTeiejdo+bwUg8unqSpeYG42XrcrQboGIezmFA=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||||
github.com/ClusterCockpit/cc-lib v1.0.2 h1:ZWn3oZkXgxrr3zSigBdlOOfayZ4Om4xL20DhmritPPg=
|
github.com/ClusterCockpit/cc-lib v1.0.2 h1:ZWn3oZkXgxrr3zSigBdlOOfayZ4Om4xL20DhmritPPg=
|
||||||
@@ -12,8 +10,6 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc
|
|||||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||||
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
|
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
|
||||||
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
|
||||||
github.com/NVIDIA/go-nvml v0.13.0-1 h1:OLX8Jq3dONuPOQPC7rndB6+iDmDakw0XTYgzMxObkEw=
|
github.com/NVIDIA/go-nvml v0.13.0-1 h1:OLX8Jq3dONuPOQPC7rndB6+iDmDakw0XTYgzMxObkEw=
|
||||||
github.com/NVIDIA/go-nvml v0.13.0-1/go.mod h1:+KNA7c7gIBH7SKSJ1ntlwkfN80zdx8ovl4hrK3LmPt4=
|
github.com/NVIDIA/go-nvml v0.13.0-1/go.mod h1:+KNA7c7gIBH7SKSJ1ntlwkfN80zdx8ovl4hrK3LmPt4=
|
||||||
github.com/PuerkitoBio/goquery v1.11.0 h1:jZ7pwMQXIITcUXNH83LLk+txlaEy6NVOfTuP43xxfqw=
|
github.com/PuerkitoBio/goquery v1.11.0 h1:jZ7pwMQXIITcUXNH83LLk+txlaEy6NVOfTuP43xxfqw=
|
||||||
@@ -70,10 +66,6 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
|||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
|
||||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
|
||||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
|
||||||
github.com/coreos/go-oidc/v3 v3.16.0 h1:qRQUCFstKpXwmEjDQTIbyY/5jF00+asXzSkmkoa/mow=
|
github.com/coreos/go-oidc/v3 v3.16.0 h1:qRQUCFstKpXwmEjDQTIbyY/5jF00+asXzSkmkoa/mow=
|
||||||
github.com/coreos/go-oidc/v3 v3.16.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
|
github.com/coreos/go-oidc/v3 v3.16.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||||
@@ -85,16 +77,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
|||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo=
|
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo=
|
||||||
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||||
github.com/dhui/dktest v0.4.6 h1:+DPKyScKSEp3VLtbMDHcUq6V5Lm5zfZZVb0Sk7Ahom4=
|
|
||||||
github.com/dhui/dktest v0.4.6/go.mod h1:JHTSYDtKkvFNFHJKqCzVzqXecyv+tKt8EzceOmQOgbU=
|
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
|
||||||
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
|
|
||||||
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
|
||||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
|
||||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
|
||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
|
||||||
github.com/expr-lang/expr v1.17.6 h1:1h6i8ONk9cexhDmowO/A64VPxHScu7qfSl2k8OlINec=
|
github.com/expr-lang/expr v1.17.6 h1:1h6i8ONk9cexhDmowO/A64VPxHScu7qfSl2k8OlINec=
|
||||||
github.com/expr-lang/expr v1.17.6/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
|
github.com/expr-lang/expr v1.17.6/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
@@ -113,10 +95,6 @@ github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZR
|
|||||||
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4=
|
github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo=
|
github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
|
||||||
github.com/go-openapi/jsonpointer v0.22.3 h1:dKMwfV4fmt6Ah90zloTbUKWMD+0he+12XYAsPotrkn8=
|
github.com/go-openapi/jsonpointer v0.22.3 h1:dKMwfV4fmt6Ah90zloTbUKWMD+0he+12XYAsPotrkn8=
|
||||||
github.com/go-openapi/jsonpointer v0.22.3/go.mod h1:0lBbqeRsQ5lIanv3LHZBrmRGHLHcQoOXQnf88fHlGWo=
|
github.com/go-openapi/jsonpointer v0.22.3/go.mod h1:0lBbqeRsQ5lIanv3LHZBrmRGHLHcQoOXQnf88fHlGWo=
|
||||||
github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc=
|
github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc=
|
||||||
@@ -145,15 +123,12 @@ github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8U
|
|||||||
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
|
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
|
||||||
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
|
||||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE=
|
github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE=
|
||||||
github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||||
github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
|
github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
|
||||||
@@ -241,17 +216,11 @@ github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO
|
|||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
||||||
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
|
||||||
@@ -265,13 +234,7 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
|
github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
|
||||||
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
|
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
|
||||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
|
||||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
@@ -323,16 +286,6 @@ github.com/vektah/gqlparser/v2 v2.5.31/go.mod h1:c1I28gSOVNzlfc4WuDlqU7voQnsqI6O
|
|||||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg=
|
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg=
|
||||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
|
||||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
|
||||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
|
||||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
|
||||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
|
||||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
|
||||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Description=ClusterCockpit Web Server
|
|||||||
Documentation=https://github.com/ClusterCockpit/cc-backend
|
Documentation=https://github.com/ClusterCockpit/cc-backend
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
After=mariadb.service mysql.service
|
# Database is file-based SQLite - no service dependency required
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
WorkingDirectory=/opt/monitoring/cc-backend
|
WorkingDirectory=/opt/monitoring/cc-backend
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ func setup(t *testing.T) *api.RestAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbfilepath := filepath.Join(tmpdir, "test.db")
|
dbfilepath := filepath.Join(tmpdir, "test.db")
|
||||||
err := repository.MigrateDB("sqlite3", dbfilepath)
|
err := repository.MigrateDB(dbfilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ type ProgramConfig struct {
|
|||||||
EmbedStaticFiles bool `json:"embed-static-files"`
|
EmbedStaticFiles bool `json:"embed-static-files"`
|
||||||
StaticFiles string `json:"static-files"`
|
StaticFiles string `json:"static-files"`
|
||||||
|
|
||||||
// 'sqlite3' or 'mysql' (mysql will work for mariadb as well)
|
// Database driver - only 'sqlite3' is supported
|
||||||
DBDriver string `json:"db-driver"`
|
DBDriver string `json:"db-driver"`
|
||||||
|
|
||||||
// For sqlite3 a filename, for mysql a DSN in this format: https://github.com/go-sql-driver/mysql#dsn-data-source-name (Without query parameters!).
|
// Path to SQLite database file
|
||||||
DB string `json:"db"`
|
DB string `json:"db"`
|
||||||
|
|
||||||
// Keep all metric data in the metric data repositories,
|
// Keep all metric data in the metric data repositories,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ var configSchema = `
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"db": {
|
"db": {
|
||||||
"description": "For sqlite3 a filename, for mysql a DSN in this format: https://github.com/go-sql-driver/mysql#dsn-data-source-name (Without query parameters!).",
|
"description": "Path to SQLite database file (e.g., './var/job.db')",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"disable-archive": {
|
"disable-archive": {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func setup(t *testing.T) *repository.JobRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbfilepath := filepath.Join(tmpdir, "test.db")
|
dbfilepath := filepath.Join(tmpdir, "test.db")
|
||||||
err := repository.MigrateDB("sqlite3", dbfilepath)
|
err := repository.MigrateDB(dbfilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ func Connect(driver string, db string) {
|
|||||||
var err error
|
var err error
|
||||||
var dbHandle *sqlx.DB
|
var dbHandle *sqlx.DB
|
||||||
|
|
||||||
|
if driver != "sqlite3" {
|
||||||
|
cclog.Abortf("Unsupported database driver '%s'. Only 'sqlite3' is supported.\n", driver)
|
||||||
|
}
|
||||||
|
|
||||||
dbConnOnce.Do(func() {
|
dbConnOnce.Do(func() {
|
||||||
opts := DatabaseOptions{
|
opts := DatabaseOptions{
|
||||||
URL: db,
|
URL: db,
|
||||||
@@ -64,39 +68,31 @@ func Connect(driver string, db string) {
|
|||||||
ConnectionMaxIdleTime: repoConfig.ConnectionMaxIdleTime,
|
ConnectionMaxIdleTime: repoConfig.ConnectionMaxIdleTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch driver {
|
// TODO: Have separate DB handles for Writes and Reads
|
||||||
case "sqlite3":
|
// Optimize SQLite connection: https://kerkour.com/sqlite-for-servers
|
||||||
// TODO: Have separate DB handles for Writes and Reads
|
connectionURLParams := make(url.Values)
|
||||||
// Optimize SQLite connection: https://kerkour.com/sqlite-for-servers
|
connectionURLParams.Add("_txlock", "immediate")
|
||||||
connectionURLParams := make(url.Values)
|
connectionURLParams.Add("_journal_mode", "WAL")
|
||||||
connectionURLParams.Add("_txlock", "immediate")
|
connectionURLParams.Add("_busy_timeout", "5000")
|
||||||
connectionURLParams.Add("_journal_mode", "WAL")
|
connectionURLParams.Add("_synchronous", "NORMAL")
|
||||||
connectionURLParams.Add("_busy_timeout", "5000")
|
connectionURLParams.Add("_cache_size", "1000000000")
|
||||||
connectionURLParams.Add("_synchronous", "NORMAL")
|
connectionURLParams.Add("_foreign_keys", "true")
|
||||||
connectionURLParams.Add("_cache_size", "1000000000")
|
opts.URL = fmt.Sprintf("file:%s?%s", opts.URL, connectionURLParams.Encode())
|
||||||
connectionURLParams.Add("_foreign_keys", "true")
|
|
||||||
opts.URL = fmt.Sprintf("file:%s?%s", opts.URL, connectionURLParams.Encode())
|
|
||||||
|
|
||||||
if cclog.Loglevel() == "debug" {
|
if cclog.Loglevel() == "debug" {
|
||||||
sql.Register("sqlite3WithHooks", sqlhooks.Wrap(&sqlite3.SQLiteDriver{}, &Hooks{}))
|
sql.Register("sqlite3WithHooks", sqlhooks.Wrap(&sqlite3.SQLiteDriver{}, &Hooks{}))
|
||||||
dbHandle, err = sqlx.Open("sqlite3WithHooks", opts.URL)
|
dbHandle, err = sqlx.Open("sqlite3WithHooks", opts.URL)
|
||||||
} else {
|
} else {
|
||||||
dbHandle, err = sqlx.Open("sqlite3", opts.URL)
|
dbHandle, err = sqlx.Open("sqlite3", opts.URL)
|
||||||
}
|
|
||||||
|
|
||||||
err = setupSqlite(dbHandle.DB)
|
|
||||||
if err != nil {
|
|
||||||
cclog.Abortf("Failed sqlite db setup.\nError: %s\n", err.Error())
|
|
||||||
}
|
|
||||||
case "mysql":
|
|
||||||
opts.URL += "?multiStatements=true"
|
|
||||||
dbHandle, err = sqlx.Open("mysql", opts.URL)
|
|
||||||
default:
|
|
||||||
cclog.Abortf("DB Connection: Unsupported database driver '%s'.\n", driver)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cclog.Abortf("DB Connection: Could not connect to '%s' database with sqlx.Open().\nError: %s\n", driver, err.Error())
|
cclog.Abortf("DB Connection: Could not connect to SQLite database with sqlx.Open().\nError: %s\n", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setupSqlite(dbHandle.DB)
|
||||||
|
if err != nil {
|
||||||
|
cclog.Abortf("Failed sqlite db setup.\nError: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
dbHandle.SetMaxOpenConns(opts.MaxOpenConnections)
|
dbHandle.SetMaxOpenConns(opts.MaxOpenConnections)
|
||||||
@@ -105,7 +101,7 @@ func Connect(driver string, db string) {
|
|||||||
dbHandle.SetConnMaxIdleTime(opts.ConnectionMaxIdleTime)
|
dbHandle.SetConnMaxIdleTime(opts.ConnectionMaxIdleTime)
|
||||||
|
|
||||||
dbConnInstance = &DBConnection{DB: dbHandle, Driver: driver}
|
dbConnInstance = &DBConnection{DB: dbHandle, Driver: driver}
|
||||||
err = checkDBVersion(driver, dbHandle.DB)
|
err = checkDBVersion(dbHandle.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cclog.Abortf("DB Connection: Failed DB version check.\nError: %s\n", err.Error())
|
cclog.Abortf("DB Connection: Failed DB version check.\nError: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
// Initialize the database connection before using any repository:
|
// Initialize the database connection before using any repository:
|
||||||
//
|
//
|
||||||
// repository.Connect("sqlite3", "./var/job.db")
|
// repository.Connect("sqlite3", "./var/job.db")
|
||||||
// // or for MySQL:
|
|
||||||
// repository.Connect("mysql", "user:password@tcp(localhost:3306)/dbname")
|
|
||||||
//
|
//
|
||||||
// # Configuration
|
// # Configuration
|
||||||
//
|
//
|
||||||
@@ -158,52 +156,22 @@ func scanJob(row interface{ Scan(...any) error }) (*schema.Job, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *JobRepository) Optimize() error {
|
func (r *JobRepository) Optimize() error {
|
||||||
var err error
|
if _, err := r.DB.Exec(`VACUUM`); err != nil {
|
||||||
|
return err
|
||||||
switch r.driver {
|
|
||||||
case "sqlite3":
|
|
||||||
if _, err = r.DB.Exec(`VACUUM`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "mysql":
|
|
||||||
cclog.Info("Optimize currently not supported for mysql driver")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *JobRepository) Flush() error {
|
func (r *JobRepository) Flush() error {
|
||||||
var err error
|
if _, err := r.DB.Exec(`DELETE FROM jobtag`); err != nil {
|
||||||
|
return err
|
||||||
switch r.driver {
|
}
|
||||||
case "sqlite3":
|
if _, err := r.DB.Exec(`DELETE FROM tag`); err != nil {
|
||||||
if _, err = r.DB.Exec(`DELETE FROM jobtag`); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
if _, err := r.DB.Exec(`DELETE FROM job`); err != nil {
|
||||||
if _, err = r.DB.Exec(`DELETE FROM tag`); err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = r.DB.Exec(`DELETE FROM job`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "mysql":
|
|
||||||
if _, err = r.DB.Exec(`SET FOREIGN_KEY_CHECKS = 0`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = r.DB.Exec(`TRUNCATE TABLE jobtag`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = r.DB.Exec(`TRUNCATE TABLE tag`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = r.DB.Exec(`TRUNCATE TABLE job`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = r.DB.Exec(`SET FOREIGN_KEY_CHECKS = 1`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
|
|
||||||
cclog "github.com/ClusterCockpit/cc-lib/ccLogger"
|
cclog "github.com/ClusterCockpit/cc-lib/ccLogger"
|
||||||
"github.com/golang-migrate/migrate/v4"
|
"github.com/golang-migrate/migrate/v4"
|
||||||
"github.com/golang-migrate/migrate/v4/database/mysql"
|
|
||||||
"github.com/golang-migrate/migrate/v4/database/sqlite3"
|
"github.com/golang-migrate/migrate/v4/database/sqlite3"
|
||||||
"github.com/golang-migrate/migrate/v4/source/iofs"
|
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||||
)
|
)
|
||||||
@@ -22,40 +21,19 @@ const Version uint = 10
|
|||||||
//go:embed migrations/*
|
//go:embed migrations/*
|
||||||
var migrationFiles embed.FS
|
var migrationFiles embed.FS
|
||||||
|
|
||||||
func checkDBVersion(backend string, db *sql.DB) error {
|
func checkDBVersion(db *sql.DB) error {
|
||||||
var m *migrate.Migrate
|
driver, err := sqlite3.WithInstance(db, &sqlite3.Config{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d, err := iofs.New(migrationFiles, "migrations/sqlite3")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
switch backend {
|
m, err := migrate.NewWithInstance("iofs", d, "sqlite3", driver)
|
||||||
case "sqlite3":
|
if err != nil {
|
||||||
driver, err := sqlite3.WithInstance(db, &sqlite3.Config{})
|
return err
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d, err := iofs.New(migrationFiles, "migrations/sqlite3")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err = migrate.NewWithInstance("iofs", d, "sqlite3", driver)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "mysql":
|
|
||||||
driver, err := mysql.WithInstance(db, &mysql.Config{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d, err := iofs.New(migrationFiles, "migrations/mysql")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err = migrate.NewWithInstance("iofs", d, "mysql", driver)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
cclog.Abortf("Migration: Unsupported database backend '%s'.\n", backend)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v, dirty, err := m.Version()
|
v, dirty, err := m.Version()
|
||||||
@@ -80,37 +58,22 @@ func checkDBVersion(backend string, db *sql.DB) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMigrateInstance(backend string, db string) (m *migrate.Migrate, err error) {
|
func getMigrateInstance(db string) (m *migrate.Migrate, err error) {
|
||||||
switch backend {
|
d, err := iofs.New(migrationFiles, "migrations/sqlite3")
|
||||||
case "sqlite3":
|
if err != nil {
|
||||||
d, err := iofs.New(migrationFiles, "migrations/sqlite3")
|
return nil, err
|
||||||
if err != nil {
|
}
|
||||||
cclog.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err = migrate.NewWithSourceInstance("iofs", d, fmt.Sprintf("sqlite3://%s?_foreign_keys=on", db))
|
m, err = migrate.NewWithSourceInstance("iofs", d, fmt.Sprintf("sqlite3://%s?_foreign_keys=on", db))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return m, err
|
return nil, err
|
||||||
}
|
|
||||||
case "mysql":
|
|
||||||
d, err := iofs.New(migrationFiles, "migrations/mysql")
|
|
||||||
if err != nil {
|
|
||||||
return m, err
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err = migrate.NewWithSourceInstance("iofs", d, fmt.Sprintf("mysql://%s?multiStatements=true", db))
|
|
||||||
if err != nil {
|
|
||||||
return m, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
cclog.Abortf("Migration: Unsupported database backend '%s'.\n", backend)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MigrateDB(backend string, db string) error {
|
func MigrateDB(db string) error {
|
||||||
m, err := getMigrateInstance(backend, db)
|
m, err := getMigrateInstance(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -144,8 +107,8 @@ func MigrateDB(backend string, db string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RevertDB(backend string, db string) error {
|
func RevertDB(db string) error {
|
||||||
m, err := getMigrateInstance(backend, db)
|
m, err := getMigrateInstance(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -162,8 +125,8 @@ func RevertDB(backend string, db string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ForceDB(backend string, db string) error {
|
func ForceDB(db string) error {
|
||||||
m, err := getMigrateInstance(backend, db)
|
m, err := getMigrateInstance(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
DROP TABLE IF EXISTS job;
|
|
||||||
DROP TABLE IF EXISTS tags;
|
|
||||||
DROP TABLE IF EXISTS jobtag;
|
|
||||||
DROP TABLE IF EXISTS configuration;
|
|
||||||
DROP TABLE IF EXISTS user;
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS job (
|
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY ,
|
|
||||||
job_id BIGINT NOT NULL,
|
|
||||||
cluster VARCHAR(255) NOT NULL,
|
|
||||||
subcluster VARCHAR(255) NOT NULL,
|
|
||||||
start_time BIGINT NOT NULL, -- Unix timestamp
|
|
||||||
|
|
||||||
user VARCHAR(255) NOT NULL,
|
|
||||||
project VARCHAR(255) NOT NULL,
|
|
||||||
`partition` VARCHAR(255) NOT NULL,
|
|
||||||
array_job_id BIGINT NOT NULL,
|
|
||||||
duration INT NOT NULL DEFAULT 0,
|
|
||||||
walltime INT NOT NULL DEFAULT 0,
|
|
||||||
job_state VARCHAR(255) NOT NULL
|
|
||||||
CHECK(job_state IN ('running', 'completed', 'failed', 'cancelled',
|
|
||||||
'stopped', 'timeout', 'preempted', 'out_of_memory')),
|
|
||||||
meta_data TEXT, -- JSON
|
|
||||||
resources TEXT NOT NULL, -- JSON
|
|
||||||
|
|
||||||
num_nodes INT NOT NULL,
|
|
||||||
num_hwthreads INT NOT NULL,
|
|
||||||
num_acc INT NOT NULL,
|
|
||||||
smt TINYINT NOT NULL DEFAULT 1 CHECK(smt IN (0, 1 )),
|
|
||||||
exclusive TINYINT NOT NULL DEFAULT 1 CHECK(exclusive IN (0, 1, 2)),
|
|
||||||
monitoring_status TINYINT NOT NULL DEFAULT 1 CHECK(monitoring_status IN (0, 1, 2, 3)),
|
|
||||||
|
|
||||||
mem_used_max REAL NOT NULL DEFAULT 0.0,
|
|
||||||
flops_any_avg REAL NOT NULL DEFAULT 0.0,
|
|
||||||
mem_bw_avg REAL NOT NULL DEFAULT 0.0,
|
|
||||||
load_avg REAL NOT NULL DEFAULT 0.0,
|
|
||||||
net_bw_avg REAL NOT NULL DEFAULT 0.0,
|
|
||||||
net_data_vol_total REAL NOT NULL DEFAULT 0.0,
|
|
||||||
file_bw_avg REAL NOT NULL DEFAULT 0.0,
|
|
||||||
file_data_vol_total REAL NOT NULL DEFAULT 0.0,
|
|
||||||
UNIQUE (job_id, cluster, start_time)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS tag (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
tag_type VARCHAR(255) NOT NULL,
|
|
||||||
tag_name VARCHAR(255) NOT NULL,
|
|
||||||
UNIQUE (tag_type, tag_name));
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS jobtag (
|
|
||||||
job_id INTEGER,
|
|
||||||
tag_id INTEGER,
|
|
||||||
PRIMARY KEY (job_id, tag_id),
|
|
||||||
FOREIGN KEY (job_id) REFERENCES job (id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (tag_id) REFERENCES tag (id) ON DELETE CASCADE);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS user (
|
|
||||||
username varchar(255) PRIMARY KEY NOT NULL,
|
|
||||||
password varchar(255) DEFAULT NULL,
|
|
||||||
ldap tinyint NOT NULL DEFAULT 0, /* col called "ldap" for historic reasons, fills the "AuthSource" */
|
|
||||||
name varchar(255) DEFAULT NULL,
|
|
||||||
roles varchar(255) NOT NULL DEFAULT "[]",
|
|
||||||
email varchar(255) DEFAULT NULL);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS configuration (
|
|
||||||
username varchar(255),
|
|
||||||
confkey varchar(255),
|
|
||||||
value varchar(255),
|
|
||||||
PRIMARY KEY (username, confkey),
|
|
||||||
FOREIGN KEY (username) REFERENCES user (username) ON DELETE CASCADE ON UPDATE NO ACTION);
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
DROP INDEX IF EXISTS job_stats;
|
|
||||||
DROP INDEX IF EXISTS job_by_user;
|
|
||||||
DROP INDEX IF EXISTS job_by_starttime;
|
|
||||||
DROP INDEX IF EXISTS job_by_job_id;
|
|
||||||
DROP INDEX IF EXISTS job_list;
|
|
||||||
DROP INDEX IF EXISTS job_list_user;
|
|
||||||
DROP INDEX IF EXISTS job_list_users;
|
|
||||||
DROP INDEX IF EXISTS job_list_users_start;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
CREATE INDEX IF NOT EXISTS job_stats ON job (cluster,subcluster,user);
|
|
||||||
CREATE INDEX IF NOT EXISTS job_by_user ON job (user);
|
|
||||||
CREATE INDEX IF NOT EXISTS job_by_starttime ON job (start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS job_by_job_id ON job (job_id);
|
|
||||||
CREATE INDEX IF NOT EXISTS job_list ON job (cluster, job_state);
|
|
||||||
CREATE INDEX IF NOT EXISTS job_list_user ON job (user, cluster, job_state);
|
|
||||||
CREATE INDEX IF NOT EXISTS job_list_users ON job (user, job_state);
|
|
||||||
CREATE INDEX IF NOT EXISTS job_list_users_start ON job (start_time, user, job_state);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE user DROP COLUMN projects;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE user ADD COLUMN projects varchar(255) NOT NULL DEFAULT "[]";
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
ALTER TABLE job
|
|
||||||
MODIFY `partition` VARCHAR(255) NOT NULL,
|
|
||||||
MODIFY array_job_id BIGINT NOT NULL,
|
|
||||||
MODIFY num_hwthreads INT NOT NULL,
|
|
||||||
MODIFY num_acc INT NOT NULL;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
ALTER TABLE job
|
|
||||||
MODIFY `partition` VARCHAR(255),
|
|
||||||
MODIFY array_job_id BIGINT,
|
|
||||||
MODIFY num_hwthreads INT,
|
|
||||||
MODIFY num_acc INT;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
ALTER TABLE tag DROP COLUMN insert_time;
|
|
||||||
ALTER TABLE jobtag DROP COLUMN insert_time;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
ALTER TABLE tag ADD COLUMN insert_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
|
||||||
ALTER TABLE jobtag ADD COLUMN insert_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE configuration MODIFY value VARCHAR(255);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE configuration MODIFY value TEXT;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
SET FOREIGN_KEY_CHECKS = 0;
|
|
||||||
ALTER TABLE tag MODIFY id INTEGER;
|
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
SET FOREIGN_KEY_CHECKS = 0;
|
|
||||||
ALTER TABLE tag MODIFY id INTEGER AUTO_INCREMENT;
|
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
ALTER TABLE job DROP energy;
|
|
||||||
ALTER TABLE job DROP energy_footprint;
|
|
||||||
ALTER TABLE job ADD COLUMN flops_any_avg;
|
|
||||||
ALTER TABLE job ADD COLUMN mem_bw_avg;
|
|
||||||
ALTER TABLE job ADD COLUMN mem_used_max;
|
|
||||||
ALTER TABLE job ADD COLUMN load_avg;
|
|
||||||
ALTER TABLE job ADD COLUMN net_bw_avg;
|
|
||||||
ALTER TABLE job ADD COLUMN net_data_vol_total;
|
|
||||||
ALTER TABLE job ADD COLUMN file_bw_avg;
|
|
||||||
ALTER TABLE job ADD COLUMN file_data_vol_total;
|
|
||||||
|
|
||||||
UPDATE job SET flops_any_avg = json_extract(footprint, '$.flops_any_avg');
|
|
||||||
UPDATE job SET mem_bw_avg = json_extract(footprint, '$.mem_bw_avg');
|
|
||||||
UPDATE job SET mem_used_max = json_extract(footprint, '$.mem_used_max');
|
|
||||||
UPDATE job SET load_avg = json_extract(footprint, '$.cpu_load_avg');
|
|
||||||
UPDATE job SET net_bw_avg = json_extract(footprint, '$.net_bw_avg');
|
|
||||||
UPDATE job SET net_data_vol_total = json_extract(footprint, '$.net_data_vol_total');
|
|
||||||
UPDATE job SET file_bw_avg = json_extract(footprint, '$.file_bw_avg');
|
|
||||||
UPDATE job SET file_data_vol_total = json_extract(footprint, '$.file_data_vol_total');
|
|
||||||
|
|
||||||
ALTER TABLE job DROP footprint;
|
|
||||||
-- Do not use reserved keywords anymore
|
|
||||||
RENAME TABLE hpc_user TO `user`;
|
|
||||||
ALTER TABLE job RENAME COLUMN hpc_user TO `user`;
|
|
||||||
ALTER TABLE job RENAME COLUMN cluster_partition TO `partition`;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_user;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_project;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_subcluster;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_jobstate;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_jobstate_user;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_jobstate_project;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_jobstate_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_jobstate_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_partition_jobstate_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_jobstate;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_jobstate_user;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_jobstate_project;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_jobstate_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_jobstate_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_jobstate_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_user;
|
|
||||||
DROP INDEX IF EXISTS jobs_user_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_user_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_user_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_project;
|
|
||||||
DROP INDEX IF EXISTS jobs_project_user;
|
|
||||||
DROP INDEX IF EXISTS jobs_project_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_project_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_project_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_jobstate;
|
|
||||||
DROP INDEX IF EXISTS jobs_jobstate_user;
|
|
||||||
DROP INDEX IF EXISTS jobs_jobstate_project;
|
|
||||||
DROP INDEX IF EXISTS jobs_jobstate_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_jobstate_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_jobstate_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_arrayjobid_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_cluster_arrayjobid_starttime;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_duration;
|
|
||||||
DROP INDEX IF EXISTS jobs_numnodes;
|
|
||||||
|
|
||||||
DROP INDEX IF EXISTS jobs_duration_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_numnodes_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_numacc_starttime;
|
|
||||||
DROP INDEX IF EXISTS jobs_energy_starttime;
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
DROP INDEX IF EXISTS job_stats ON job;
|
|
||||||
DROP INDEX IF EXISTS job_by_user ON job;
|
|
||||||
DROP INDEX IF EXISTS job_by_starttime ON job;
|
|
||||||
DROP INDEX IF EXISTS job_by_job_id ON job;
|
|
||||||
DROP INDEX IF EXISTS job_list ON job;
|
|
||||||
DROP INDEX IF EXISTS job_list_user ON job;
|
|
||||||
DROP INDEX IF EXISTS job_list_users ON job;
|
|
||||||
DROP INDEX IF EXISTS job_list_users_start ON job;
|
|
||||||
|
|
||||||
ALTER TABLE job ADD COLUMN energy REAL NOT NULL DEFAULT 0.0;
|
|
||||||
ALTER TABLE job ADD COLUMN energy_footprint JSON;
|
|
||||||
|
|
||||||
ALTER TABLE job ADD COLUMN footprint JSON;
|
|
||||||
ALTER TABLE tag ADD COLUMN tag_scope TEXT NOT NULL DEFAULT 'global';
|
|
||||||
|
|
||||||
-- Do not use reserved keywords anymore
|
|
||||||
RENAME TABLE `user` TO hpc_user;
|
|
||||||
ALTER TABLE job RENAME COLUMN `user` TO hpc_user;
|
|
||||||
ALTER TABLE job RENAME COLUMN `partition` TO cluster_partition;
|
|
||||||
|
|
||||||
ALTER TABLE job MODIFY COLUMN cluster VARCHAR(50);
|
|
||||||
ALTER TABLE job MODIFY COLUMN hpc_user VARCHAR(50);
|
|
||||||
ALTER TABLE job MODIFY COLUMN subcluster VARCHAR(50);
|
|
||||||
ALTER TABLE job MODIFY COLUMN project VARCHAR(50);
|
|
||||||
ALTER TABLE job MODIFY COLUMN cluster_partition VARCHAR(50);
|
|
||||||
ALTER TABLE job MODIFY COLUMN job_state VARCHAR(25);
|
|
||||||
|
|
||||||
UPDATE job SET footprint = '{"flops_any_avg": 0.0}';
|
|
||||||
UPDATE job SET footprint = json_replace(footprint, '$.flops_any_avg', job.flops_any_avg);
|
|
||||||
UPDATE job SET footprint = json_insert(footprint, '$.mem_bw_avg', job.mem_bw_avg);
|
|
||||||
UPDATE job SET footprint = json_insert(footprint, '$.mem_used_max', job.mem_used_max);
|
|
||||||
UPDATE job SET footprint = json_insert(footprint, '$.cpu_load_avg', job.load_avg);
|
|
||||||
UPDATE job SET footprint = json_insert(footprint, '$.net_bw_avg', job.net_bw_avg) WHERE job.net_bw_avg != 0;
|
|
||||||
UPDATE job SET footprint = json_insert(footprint, '$.net_data_vol_total', job.net_data_vol_total) WHERE job.net_data_vol_total != 0;
|
|
||||||
UPDATE job SET footprint = json_insert(footprint, '$.file_bw_avg', job.file_bw_avg) WHERE job.file_bw_avg != 0;
|
|
||||||
UPDATE job SET footprint = json_insert(footprint, '$.file_data_vol_total', job.file_data_vol_total) WHERE job.file_data_vol_total != 0;
|
|
||||||
|
|
||||||
ALTER TABLE job DROP flops_any_avg;
|
|
||||||
ALTER TABLE job DROP mem_bw_avg;
|
|
||||||
ALTER TABLE job DROP mem_used_max;
|
|
||||||
ALTER TABLE job DROP load_avg;
|
|
||||||
ALTER TABLE job DROP net_bw_avg;
|
|
||||||
ALTER TABLE job DROP net_data_vol_total;
|
|
||||||
ALTER TABLE job DROP file_bw_avg;
|
|
||||||
ALTER TABLE job DROP file_data_vol_total;
|
|
||||||
|
|
||||||
-- Indices for: Single filters, combined filters, sorting, sorting with filters
|
|
||||||
-- Cluster Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster ON job (cluster);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_user ON job (cluster, hpc_user);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_project ON job (cluster, project);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_subcluster ON job (cluster, subcluster);
|
|
||||||
-- Cluster Filter Sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_starttime ON job (cluster, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_duration ON job (cluster, duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_numnodes ON job (cluster, num_nodes);
|
|
||||||
|
|
||||||
-- Cluster+Partition Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition ON job (cluster, cluster_partition);
|
|
||||||
-- Cluster+Partition Filter Sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_starttime ON job (cluster, cluster_partition, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_duration ON job (cluster, cluster_partition, duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_numnodes ON job (cluster, cluster_partition, num_nodes);
|
|
||||||
|
|
||||||
-- Cluster+Partition+Jobstate Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_jobstate ON job (cluster, cluster_partition, job_state);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_jobstate_user ON job (cluster, cluster_partition, job_state, hpc_user);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_jobstate_project ON job (cluster, cluster_partition, job_state, project);
|
|
||||||
-- Cluster+Partition+Jobstate Filter Sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_jobstate_starttime ON job (cluster, cluster_partition, job_state, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_jobstate_duration ON job (cluster, cluster_partition, job_state, duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_partition_jobstate_numnodes ON job (cluster, cluster_partition, job_state, num_nodes);
|
|
||||||
|
|
||||||
-- Cluster+JobState Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_jobstate ON job (cluster, job_state);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_jobstate_user ON job (cluster, job_state, hpc_user);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_jobstate_project ON job (cluster, job_state, project);
|
|
||||||
-- Cluster+JobState Filter Sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_jobstate_starttime ON job (cluster, job_state, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_jobstate_duration ON job (cluster, job_state, duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_jobstate_numnodes ON job (cluster, job_state, num_nodes);
|
|
||||||
|
|
||||||
-- User Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_user ON job (hpc_user);
|
|
||||||
-- User Filter Sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_user_starttime ON job (hpc_user, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_user_duration ON job (hpc_user, duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_user_numnodes ON job (hpc_user, num_nodes);
|
|
||||||
|
|
||||||
-- Project Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_project ON job (project);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_project_user ON job (project, hpc_user);
|
|
||||||
-- Project Filter Sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_project_starttime ON job (project, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_project_duration ON job (project, duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_project_numnodes ON job (project, num_nodes);
|
|
||||||
|
|
||||||
-- JobState Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_jobstate ON job (job_state);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_jobstate_user ON job (job_state, hpc_user);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_jobstate_project ON job (job_state, project);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_jobstate_cluster ON job (job_state, cluster);
|
|
||||||
-- JobState Filter Sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_jobstate_starttime ON job (job_state, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_jobstate_duration ON job (job_state, duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_jobstate_numnodes ON job (job_state, num_nodes);
|
|
||||||
|
|
||||||
-- ArrayJob Filter
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_arrayjobid_starttime ON job (array_job_id, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_cluster_arrayjobid_starttime ON job (cluster, array_job_id, start_time);
|
|
||||||
|
|
||||||
-- Sorting without active filters
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_starttime ON job (start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_duration ON job (duration);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_numnodes ON job (num_nodes);
|
|
||||||
|
|
||||||
-- Single filters with default starttime sorting
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_duration_starttime ON job (duration, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_numnodes_starttime ON job (num_nodes, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_numacc_starttime ON job (num_acc, start_time);
|
|
||||||
CREATE INDEX IF NOT EXISTS jobs_energy_starttime ON job (energy, start_time);
|
|
||||||
|
|
||||||
-- Optimize DB index usage
|
|
||||||
@@ -130,7 +130,7 @@ func nodeTestSetup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbfilepath := filepath.Join(tmpdir, "test.db")
|
dbfilepath := filepath.Join(tmpdir, "test.db")
|
||||||
err := MigrateDB("sqlite3", dbfilepath)
|
err := MigrateDB(dbfilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ func setup(tb testing.TB) *JobRepository {
|
|||||||
tb.Helper()
|
tb.Helper()
|
||||||
cclog.Init("warn", true)
|
cclog.Init("warn", true)
|
||||||
dbfile := "testdata/job.db"
|
dbfile := "testdata/job.db"
|
||||||
err := MigrateDB("sqlite3", dbfile)
|
err := MigrateDB(dbfile)
|
||||||
noErr(tb, err)
|
noErr(tb, err)
|
||||||
Connect("sqlite3", dbfile)
|
Connect("sqlite3", dbfile)
|
||||||
return GetJobRepository()
|
return GetJobRepository()
|
||||||
|
|||||||
@@ -73,9 +73,6 @@ func (r *JobRepository) buildStatsQuery(
|
|||||||
col string,
|
col string,
|
||||||
) sq.SelectBuilder {
|
) sq.SelectBuilder {
|
||||||
var query sq.SelectBuilder
|
var query sq.SelectBuilder
|
||||||
castType := r.getCastType()
|
|
||||||
|
|
||||||
// fmt.Sprintf(`CAST(ROUND((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) / 3600) as %s) as value`, time.Now().Unix(), castType)
|
|
||||||
|
|
||||||
if col != "" {
|
if col != "" {
|
||||||
// Scan columns: id, name, totalJobs, totalUsers, totalWalltime, totalNodes, totalNodeHours, totalCores, totalCoreHours, totalAccs, totalAccHours
|
// Scan columns: id, name, totalJobs, totalUsers, totalWalltime, totalNodes, totalNodeHours, totalCores, totalCoreHours, totalAccs, totalAccHours
|
||||||
@@ -84,26 +81,26 @@ func (r *JobRepository) buildStatsQuery(
|
|||||||
"name",
|
"name",
|
||||||
"COUNT(job.id) as totalJobs",
|
"COUNT(job.id) as totalJobs",
|
||||||
"COUNT(DISTINCT job.hpc_user) AS totalUsers",
|
"COUNT(DISTINCT job.hpc_user) AS totalUsers",
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END)) / 3600) as %s) as totalWalltime`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END)) / 3600) as int) as totalWalltime`, time.Now().Unix()),
|
||||||
fmt.Sprintf(`CAST(SUM(job.num_nodes) as %s) as totalNodes`, castType),
|
fmt.Sprintf(`CAST(SUM(job.num_nodes) as int) as totalNodes`),
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_nodes) / 3600) as %s) as totalNodeHours`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_nodes) / 3600) as int) as totalNodeHours`, time.Now().Unix()),
|
||||||
fmt.Sprintf(`CAST(SUM(job.num_hwthreads) as %s) as totalCores`, castType),
|
fmt.Sprintf(`CAST(SUM(job.num_hwthreads) as int) as totalCores`),
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_hwthreads) / 3600) as %s) as totalCoreHours`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_hwthreads) / 3600) as int) as totalCoreHours`, time.Now().Unix()),
|
||||||
fmt.Sprintf(`CAST(SUM(job.num_acc) as %s) as totalAccs`, castType),
|
fmt.Sprintf(`CAST(SUM(job.num_acc) as int) as totalAccs`),
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_acc) / 3600) as %s) as totalAccHours`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_acc) / 3600) as int) as totalAccHours`, time.Now().Unix()),
|
||||||
).From("job").LeftJoin("hpc_user ON hpc_user.username = job.hpc_user").GroupBy(col)
|
).From("job").LeftJoin("hpc_user ON hpc_user.username = job.hpc_user").GroupBy(col)
|
||||||
} else {
|
} else {
|
||||||
// Scan columns: totalJobs, totalUsers, totalWalltime, totalNodes, totalNodeHours, totalCores, totalCoreHours, totalAccs, totalAccHours
|
// Scan columns: totalJobs, totalUsers, totalWalltime, totalNodes, totalNodeHours, totalCores, totalCoreHours, totalAccs, totalAccHours
|
||||||
query = sq.Select(
|
query = sq.Select(
|
||||||
"COUNT(job.id) as totalJobs",
|
"COUNT(job.id) as totalJobs",
|
||||||
"COUNT(DISTINCT job.hpc_user) AS totalUsers",
|
"COUNT(DISTINCT job.hpc_user) AS totalUsers",
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END)) / 3600) as %s)`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END)) / 3600) as int)`, time.Now().Unix()),
|
||||||
fmt.Sprintf(`CAST(SUM(job.num_nodes) as %s)`, castType),
|
fmt.Sprintf(`CAST(SUM(job.num_nodes) as int)`),
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_nodes) / 3600) as %s)`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_nodes) / 3600) as int)`, time.Now().Unix()),
|
||||||
fmt.Sprintf(`CAST(SUM(job.num_hwthreads) as %s)`, castType),
|
fmt.Sprintf(`CAST(SUM(job.num_hwthreads) as int)`),
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_hwthreads) / 3600) as %s)`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_hwthreads) / 3600) as int)`, time.Now().Unix()),
|
||||||
fmt.Sprintf(`CAST(SUM(job.num_acc) as %s)`, castType),
|
fmt.Sprintf(`CAST(SUM(job.num_acc) as int)`),
|
||||||
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_acc) / 3600) as %s)`, time.Now().Unix(), castType),
|
fmt.Sprintf(`CAST(ROUND(SUM((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) * job.num_acc) / 3600) as int)`, time.Now().Unix()),
|
||||||
).From("job")
|
).From("job")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,21 +111,6 @@ func (r *JobRepository) buildStatsQuery(
|
|||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *JobRepository) getCastType() string {
|
|
||||||
var castType string
|
|
||||||
|
|
||||||
switch r.driver {
|
|
||||||
case "sqlite3":
|
|
||||||
castType = "int"
|
|
||||||
case "mysql":
|
|
||||||
castType = "unsigned"
|
|
||||||
default:
|
|
||||||
castType = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return castType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JobRepository) JobsStatsGrouped(
|
func (r *JobRepository) JobsStatsGrouped(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
filter []*model.JobFilter,
|
filter []*model.JobFilter,
|
||||||
@@ -477,10 +459,9 @@ func (r *JobRepository) AddHistograms(
|
|||||||
targetBinSize = 3600
|
targetBinSize = 3600
|
||||||
}
|
}
|
||||||
|
|
||||||
castType := r.getCastType()
|
|
||||||
var err error
|
var err error
|
||||||
// Return X-Values always as seconds, will be formatted into minutes and hours in frontend
|
// Return X-Values always as seconds, will be formatted into minutes and hours in frontend
|
||||||
value := fmt.Sprintf(`CAST(ROUND(((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) / %d) + 1) as %s) as value`, time.Now().Unix(), targetBinSize, castType)
|
value := fmt.Sprintf(`CAST(ROUND(((CASE WHEN job.job_state = "running" THEN %d - job.start_time ELSE job.duration END) / %d) + 1) as int) as value`, time.Now().Unix(), targetBinSize)
|
||||||
stat.HistDuration, err = r.jobsDurationStatisticsHistogram(ctx, value, filter, targetBinSize, &targetBinCount)
|
stat.HistDuration, err = r.jobsDurationStatisticsHistogram(ctx, value, filter, targetBinSize, &targetBinCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cclog.Warn("Error while loading job statistics histogram: job duration")
|
cclog.Warn("Error while loading job statistics histogram: job duration")
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func setupUserTest(t *testing.T) *UserCfgRepo {
|
|||||||
|
|
||||||
cclog.Init("info", true)
|
cclog.Init("info", true)
|
||||||
dbfilepath := "testdata/job.db"
|
dbfilepath := "testdata/job.db"
|
||||||
err := MigrateDB("sqlite3", dbfilepath)
|
err := MigrateDB(dbfilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func setup(tb testing.TB) *repository.JobRepository {
|
|||||||
tb.Helper()
|
tb.Helper()
|
||||||
cclog.Init("warn", true)
|
cclog.Init("warn", true)
|
||||||
dbfile := "../repository/testdata/job.db"
|
dbfile := "../repository/testdata/job.db"
|
||||||
err := repository.MigrateDB("sqlite3", dbfile)
|
err := repository.MigrateDB(dbfile)
|
||||||
noErr(tb, err)
|
noErr(tb, err)
|
||||||
repository.Connect("sqlite3", dbfile)
|
repository.Connect("sqlite3", dbfile)
|
||||||
return repository.GetJobRepository()
|
return repository.GetJobRepository()
|
||||||
|
|||||||
Reference in New Issue
Block a user