Cyclops 4 HPC is the purpose built stack to support large HPC centers with resource accounting and billing of cluster as well as cloud resources.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

834 lines
23 KiB

package dbManager
import (
"errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/Cyclops-Labs/cyclops-4-hpc.git/services/plan-manager/models"
l "gitlab.com/cyclops-utilities/logging"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
const (
statusDuplicated = iota
statusFail
statusMissing
statusOK
)
// DbParameter is the struct defined to group and contain all the methods
// that interact with the database.
// Parameters:
// - connStr: strings with the connection information to the database
// - Db: a gorm.DB pointer to the db to invoke all the db methods
type DbParameter struct {
connStr string
Db *gorm.DB
Metrics map[string]*prometheus.GaugeVec
}
// New is the function to create the struct DbParameter.
// Parameters:
// - dbConn: strings with the connection information to the database
// - tables: array of interfaces that will contains the models to migrate
// to the database on initialization
// Returns:
// - DbParameter: struct to interact with dbManager functionalities
func New(dbConn string, tables ...interface{}) *DbParameter {
l.Trace.Printf("[DB] Gerenating new DBParameter.\n")
var (
dp DbParameter
err error
)
dp.connStr = dbConn
dp.Db, err = gorm.Open(postgres.Open(dbConn), &gorm.Config{})
if err != nil {
l.Error.Printf("[DB] Error opening connection. Error: %v\n", err)
}
l.Trace.Printf("[DB] Migrating tables.\n")
//Database migration, it handles everything
dp.Db.AutoMigrate(tables...)
l.Trace.Printf("[DB] Generating hypertables.\n")
// Hypertables creation for timescaledb in case of needed
//dp.Db.Exec("SELECT create_hypertable('" + dp.Db.NewScope(&models.TABLE).TableName() + "', 'TIMESCALE-ROW-INDEX');")
return &dp
}
// CreateCycle function is to add a new cycle to the system.
// Parameters:
// - p: a reference to Cycle models containing the new data to be stored
// in the system.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) CreateCycle(p *models.Cycle) (id string, status int, e error) {
l.Trace.Printf("[DB] Attempting to create a new Cycle now.\n")
var p0 models.Cycle
if r := d.Db.Where(p).First(&p0).Error; errors.Is(r, gorm.ErrRecordNotFound) {
if r := d.Db.Create(p); r.Error == nil {
l.Info.Printf("Inserted new record for cycle [ %v ] successfully.\n", *p.State)
d.Metrics["count"].With(prometheus.Labels{"type": "Cycles added"}).Inc()
status = statusOK
id = (*r.Statement.Model.(*models.Cycle)).ID
} else {
l.Warning.Printf("Unable to insert the record for cycle [ %v ], check with administrator.\n", *p.State)
e = r.Error
status = statusFail
}
} else {
l.Warning.Printf("Record for cycle [ %v ] already exists, check with administrator.\n", *p.State)
status = statusDuplicated
}
return
}
// CreatePlan function is to add a new plan to the system.
// Parameters:
// - p: a reference to Plan models containing the new data to be stored
// in the system.
// Returns:
// - id: a string containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) CreatePlan(p *models.Plan) (id string, status int, e error) {
l.Trace.Printf("[DB] Attempting to create a new Plan now.\n")
var p0 models.Plan
if r := d.Db.Where(p).First(&p0).Error; errors.Is(r, gorm.ErrRecordNotFound) {
if r := d.Db.Create(p); r.Error == nil {
l.Info.Printf("Inserted new record for plan [ %v ] successfully.\n", *p.Name)
d.Metrics["count"].With(prometheus.Labels{"type": "Plans added"}).Inc()
status = statusOK
id = (*r.Statement.Model.(*models.Plan)).ID
} else {
l.Warning.Printf("Unable to insert the record for plan [ %v ], check with administrator.\n", *p.Name)
e = r.Error
status = statusFail
}
} else {
l.Warning.Printf("Record for plan [ %v ] already exists, check with administrator.\n", *p.Name)
status = statusDuplicated
}
return
}
// CreateSku function is to add a new sku to the system.
// Parameters:
// - s: a reference to Sku models containing the new data to be stored
// in the system.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) CreateSku(s *models.Sku) (id string, status int, e error) {
l.Trace.Printf("[DB] Attempting to create a new Sku now.\n")
var s0 models.Sku
if r := d.Db.Where(s).First(&s0).Error; errors.Is(r, gorm.ErrRecordNotFound) {
if r := d.Db.Create(s); r.Error == nil {
l.Info.Printf("Inserted new record for sku [ %v ] successfully.\n", *s.Name)
d.Metrics["count"].With(prometheus.Labels{"type": "Skus added"}).Inc()
status = statusOK
id = (*r.Statement.Model.(*models.Sku)).ID
} else {
l.Warning.Printf("Unable to insert the record for sku [ %v ], check with administrator.\n", *s.Name)
e = r.Error
status = statusFail
}
} else {
l.Warning.Printf("Record for sku [ %v ] already exists, check with administrator.\n", *s.Name)
status = statusDuplicated
}
return
}
// CreateSkuBundle function is to add a new bundle to the system.
// Parameters:
// - f: a reference to Bundle models containing the new data to be stored
// in the system.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) CreateSkuBundle(f *models.SkuBundle) (id string, status int, e error) {
l.Trace.Printf("[DB] Attempting to create a new Bundle now.\n")
var f0 models.SkuBundle
if r := d.Db.Where(f).First(&f0).Error; errors.Is(r, gorm.ErrRecordNotFound) {
if r := d.Db.Create(f); r.Error == nil {
l.Info.Printf("Inserted new record for bundle [ %v ] successfully.\n", *f.Name)
d.Metrics["count"].With(prometheus.Labels{"type": "Bundles added"}).Inc()
status = statusOK
id = (r.Statement.Model.(*models.SkuBundle)).ID
} else {
l.Warning.Printf("Unable to insert the record for bundle [ %v ], check with administrator.\n", *f.Name)
e = r.Error
status = statusFail
}
} else {
l.Warning.Printf("Record for bundle [ %v ] already exists, check with administrator. Error: %v\n", *f.Name, r)
id = f0.ID
status = statusDuplicated
}
return
}
// CreateSkuPrice function is to add a new sku price to the system.
// Parameters:
// - sp: a reference to Sku Price models containing the new data to be stored
// in the system.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) CreateSkuPrice(sp *models.SkuPrice) (id string, status int, e error) {
l.Trace.Printf("[DB] Attempting to create a new Sku Price now.\n")
var sp0 models.SkuPrice
if r := d.Db.Where(sp).First(&sp0).Error; errors.Is(r, gorm.ErrRecordNotFound) {
if r := d.Db.Create(sp); r.Error == nil {
l.Info.Printf("Inserted new record for sku price [ %v ] successfully.\n", sp.SkuName)
d.Metrics["count"].With(prometheus.Labels{"type": "Sku Prices added"}).Inc()
status = statusOK
id = (*r.Statement.Model.(*models.SkuPrice)).ID
} else {
l.Warning.Printf("Unable to insert the record for sku price [ %v ], check with administrator.\n", sp.SkuName)
e = r.Error
status = statusFail
}
} else {
l.Warning.Printf("Record for sku price [ %v ] already exists, check with administrator.\n", sp.SkuName)
status = statusDuplicated
}
return
}
// GetCompletePlan function is to retrieve a completed plan (includings its
// linked skus) from the system provided its id.
// Parameters:
// - id: a string containing the id of the plan to be retrieved from the system.
// Returns:
// - reference to Plan model containing the requested one stored in the system.
// - error raised in case of problems with the operation.
func (d *DbParameter) GetCompletePlan(id string) (*models.Plan, error) {
l.Trace.Printf("[DB] Attempting to retrieve the Complete Plan [ %v ] now.\n", id)
var object models.Plan
var e error
if e = d.Db.Where(&models.Plan{ID: id}).First(&object).Error; errors.Is(e, gorm.ErrRecordNotFound) {
l.Trace.Printf("[DB] Complete plan with id: %v doesn't exist in the system, check with administrator.", id)
}
d.Db.Where(&models.SkuPrice{PlanID: &object.ID}).Find(&object.SkuPrices)
return &object, e
}
// GetCycle function is to retrieve a cycle from the system provided its id.
// Parameters:
// - id: an int64 containing the id of the cycle to be retrieved from the system.
// Returns:
// - reference to Cycle model containing the requested one stored in the system.
// - error raised in case of problems with the operation.
func (d *DbParameter) GetCycle(id string) (*models.Cycle, error) {
l.Trace.Printf("[DB] Attempting to retrieve the Cycle [ %v ] now.\n", id)
var object models.Cycle
var e error
if e = d.Db.Where(&models.Cycle{ID: id}).First(&object).Error; errors.Is(e, gorm.ErrRecordNotFound) {
l.Trace.Printf("[DB] Cycle with id: %v doesn't exist in the system, check with administrator.", id)
}
return &object, e
}
// GetPlan function is to retrieve a plan from the system provided its id.
// Parameters:
// - id: a string containing the id of the plan to be retrieved from the system.
// Returns:
// - reference to Plan model containing the requested one stored in the system.
// - error raised in case of problems with the operation.
func (d *DbParameter) GetPlan(id string) (*models.Plan, error) {
l.Trace.Printf("[DB] Attempting to retrieve the Plan [ %v ] now.\n", id)
var object models.Plan
var e error
if e = d.Db.Where(&models.Plan{ID: id}).First(&object).Error; errors.Is(e, gorm.ErrRecordNotFound) {
l.Trace.Printf("[DB] Plan with id: %v doesn't exist in the system, check with administrator.", id)
}
return &object, e
}
// GetSku function is to retrieve a sku from the system provided its id.
// Parameters:
// - id: an int64 containing the id of the sku to be retrieved from the system.
// Returns:
// - reference to Sku model containing the requested one stored in the system.
// - error raised in case of problems with the operation.
func (d *DbParameter) GetSku(id string) (*models.Sku, error) {
l.Trace.Printf("[DB] Attempting to retrieve the Sku [ %v ] now.\n", id)
var object models.Sku
var e error
if e = d.Db.Where(&models.Sku{ID: id}).First(&object).Error; errors.Is(e, gorm.ErrRecordNotFound) {
l.Trace.Printf("[DB] Sku with id: %v doesn't exist in the system, check with administrator.", id)
}
return &object, e
}
// GetSkuBundle function is to retrieve a bundle from the system provided its id.
// Parameters:
// - id: an int64 containing the id of the bundle to be retrieved from the system.
// Returns:
// - reference to Bundle model containing the requested one stored in the system.
// - error raised in case of problems with the operation.
func (d *DbParameter) GetSkuBundle(id string) (*models.SkuBundle, error) {
l.Trace.Printf("[DB] Attempting to retrieve the Bundle [ %v ] now.\n", id)
var object models.SkuBundle
var e error
if e = d.Db.Where(&models.SkuBundle{ID: id}).First(&object).Error; errors.Is(e, gorm.ErrRecordNotFound) {
l.Trace.Printf("[DB] Bundle with id: %v doesn't exist in the system, check with administrator.", id)
}
return &object, e
}
// GetSkuBundleByName function is to retrieve a bundle from the system provided its
// name.
// Parameters:
// - name: a string containing the name of the bundle to be retrieved from the system.
// Returns:
// - reference to Bundle model containing the requested one stored in the system.
// - error raised in case of problems with the operation.
func (d *DbParameter) GetSkuBundleByName(name string) (*models.SkuBundle, error) {
l.Trace.Printf("[DB] Attempting to retrieve the Bundle [ %v ] now.\n", name)
var object models.SkuBundle
var e error
if e = d.Db.Where(&models.SkuBundle{Name: &name}).First(&object).Error; errors.Is(e, gorm.ErrRecordNotFound) {
l.Trace.Printf("[DB] Bundle with name: %v doesn't exist in the system, check with administrator.", name)
}
return &object, e
}
// GetSkuPrice function is to retrieve a sku price from the system provided its id.
// Parameters:
// - id: an int64 containing the id of the sku price to be retrieved from the system.
// Returns:
// - reference to Sku Price model containing the requested one stored in the system.
// - error raised in case of problems with the operation.
func (d *DbParameter) GetSkuPrice(id string) (*models.SkuPrice, error) {
l.Trace.Printf("[DB] Attempting to retrieve the Sku Price [ %v ] now.\n", id)
var object models.SkuPrice
var e error
if e = d.Db.Where(&models.SkuPrice{ID: id}).First(&object).Error; errors.Is(e, gorm.ErrRecordNotFound) {
l.Trace.Printf("[DB] Sku price with id: %v doesn't exist in the system, check with administrator.", id)
}
return &object, e
}
// ListCompletePlans function is to retrieve all the complete plans (with the
// linked skus) contained in the system.
// Returns:
// - p: a reference to Plan models containing the list of them stored in the system.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) ListCompletePlans() (p []*models.Plan, e error) {
l.Trace.Printf("[DB] Attempting to retrieve all the Complete Plans in the system now.\n")
var p0 []*models.Plan
if e := d.Db.Find(&p0).Error; e != nil {
l.Warning.Printf("[DB] Error in DB operation. Error: %v\n", e)
}
for i := range p0 {
plan := p0[i]
d.Db.Where(&models.SkuPrice{PlanID: &p0[i].ID}).Find(&plan.SkuPrices)
p = append(p, plan)
}
l.Trace.Printf("[DB] Found [ %d ] complete plans in the db.\n", len(p))
return
}
// ListCycles function is to retrieve all the cycles contained in the system.
// Returns:
// - p: a reference to Cycle models containing the list of them stored in the system.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) ListCycles(state, ty string) (p []*models.Cycle, e error) {
l.Trace.Printf("[DB] Attempting to retrieve all the Cycles in the system now.\n")
var c models.Cycle
if state != "" {
c.State = &state
}
if ty != "" {
c.ResourceType = &ty
}
if e := d.Db.Where(&c).Find(&p).Error; e != nil {
l.Warning.Printf("[DB] Error in DB operation. Error: %v\n", e)
}
l.Trace.Printf("[DB] Found [ %d ] cycles in the db.\n", len(p))
return
}
// ListPlans function is to retrieve all the plans contained in the system.
// Returns:
// - p: a reference to Plan models containing the list of them stored in the system.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) ListPlans() (p []*models.Plan, e error) {
l.Trace.Printf("[DB] Attempting to retrieve all the Plans in the system now.\n")
if e := d.Db.Find(&p).Error; e != nil {
l.Warning.Printf("[DB] Error in DB operation. Error: %v\n", e)
}
l.Trace.Printf("[DB] Found [ %d ] plans in the db.\n", len(p))
return
}
// ListSkuBundles function is to retrieve all the bundles contained in the system.
// Returns:
// - f: a reference to Bundle models containing the list of them stored in the system.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) ListSkuBundles() (f []*models.SkuBundle, e error) {
l.Trace.Printf("[DB] Attempting to retrieve all the Bundles in the system now.\n")
if e := d.Db.Find(&f).Error; e != nil {
l.Warning.Printf("[DB] Error in DB operation. Error: %v\n", e)
}
l.Trace.Printf("[DB] Found [ %d ] bundles in the db.\n", len(f))
return
}
// ListSkuPrices function is to retrieve all the sku prices contained in the system.
// Returns:
// - sp: a reference to Sku Price models containing the list of them stored in the system.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) ListSkuPrices() (sp []*models.SkuPrice, e error) {
l.Trace.Printf("[DB] Attempting to retrieve all the Sku Prices in the system now.\n")
if e := d.Db.Find(&sp).Error; e != nil {
l.Warning.Printf("[DB] Error in DB operation. Error: %v\n", e)
}
l.Trace.Printf("[DB] Found [ %d ] sku prices in the db.\n", len(sp))
return
}
// ListSkus function is to retrieve all the skus contained in the system.
// Returns:
// - s: a reference to Sku models containing the list of them stored in the system.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) ListSkus() (s []*models.Sku, e error) {
l.Trace.Printf("[DB] Attempting to retrieve all the Skus in the system now.\n")
if e := d.Db.Find(&s).Error; e != nil {
l.Warning.Printf("[DB] Error in DB operation. Error: %v\n", e)
}
l.Trace.Printf("[DB] Found [ %d ] skus in the db.\n", len(s))
return
}
// UpdateCycle function is to update the cycle linked to the provided ID
// with the provided new data.
// Parameters:
// - id: an int64 containing the id of the sku price to be updated in the db.
// - p: a reference to Cycle models containing the new data to be updated.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) UpdateCycle(id string, p *models.Cycle) (status int, e error) {
l.Trace.Printf("[DB] Attempting to update the Cycle [ %v ] now.\n", id)
var p0 models.Cycle
if r := d.Db.Where(&models.Cycle{ID: id}).First(&p0).Error; !errors.Is(r, gorm.ErrRecordNotFound) {
if e := d.Db.Model(&p0).Updates(p).Error; e == nil {
l.Info.Printf("[DB] Updated record for cycle [ %v ] successfully.\n", p.ID)
d.Metrics["count"].With(prometheus.Labels{"type": "Cycles updated"}).Inc()
status = statusOK
} else {
l.Warning.Printf("[DB] Unable to update record for cycle [ %v ], check with administrator.\n", p.ID)
status = statusFail
}
} else {
l.Warning.Printf("[DB] Record for cycle [ %v ] not found, check with administrator.\n", p.ID)
status = statusMissing
}
return
}
// UpdatePlan function is to update the plan linked to the provided ID
// with the provided new data.
// Parameters:
// - id: a string containing the id of the sku price to be updated in the db.
// - p: a reference to Plan models containing the new data to be updated.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) UpdatePlan(id string, p *models.Plan) (status int, e error) {
l.Trace.Printf("[DB] Attempting to update the Plan [ %v ] now.\n", id)
var p0 models.Plan
if r := d.Db.Where(&models.Plan{ID: id}).First(&p0).Error; !errors.Is(r, gorm.ErrRecordNotFound) {
if e := d.Db.Model(&p0).Updates(p).Error; e == nil {
l.Info.Printf("[DB] Updated record for plan [ %v ] successfully.\n", p.ID)
d.Metrics["count"].With(prometheus.Labels{"type": "Plans updated"}).Inc()
status = statusOK
} else {
l.Warning.Printf("[DB] Unable to update record for plan [ %v ], check with administrator.\n", p.ID)
status = statusFail
}
} else {
l.Warning.Printf("[DB] Record for plan [ %v ] not found, check with administrator.\n", p.ID)
status = statusMissing
}
return
}
// UpdateSku function is to update the sku linked to the provided ID
// with the provided new data.
// Parameters:
// - id: an int64 containing the id of the sku price to be updated in the db.
// - s: a reference to Sku models containing the new data to be updated.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) UpdateSku(id string, s *models.Sku) (status int, e error) {
l.Trace.Printf("[DB] Attempting to update the Sku [ %v ] now.\n", id)
var s0 models.Sku
if r := d.Db.Where(&models.Sku{ID: id}).First(&s0).Error; !errors.Is(r, gorm.ErrRecordNotFound) {
if e := d.Db.Model(&s0).Updates(s).Error; e == nil {
l.Info.Printf("[DB] Updated record for sku [ %v ] successfully.\n", s.ID)
d.Metrics["count"].With(prometheus.Labels{"type": "Skus updated"}).Inc()
status = statusOK
} else {
l.Warning.Printf("[DB] Unable to update record for sku [ %v ], check with administrator.\n", s.ID)
status = statusFail
}
} else {
l.Warning.Printf("[DB] Record for sku [ %v ] not found, check with administrator.\n", s.ID)
status = statusMissing
}
return
}
// UpdateSkuBundle function is to update the bundle linked to the provided ID
// with the provided new data.
// Parameters:
// - f: a reference to Bundle models containing the new data to be updated.
// Returns:
// - id: an int64 containing the id of the bundle just added to the db.
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) UpdateSkuBundle(id string, b *models.SkuBundle) (status int, e error) {
l.Trace.Printf("[DB] Attempting to update the Bundle [ %v ] now.\n", b.ID)
var b0 models.SkuBundle
if r := d.Db.Where(&models.SkuBundle{ID: id}).First(&b0).Error; !errors.Is(r, gorm.ErrRecordNotFound) {
if e := d.Db.Model(&b0).Updates(b).Error; e == nil {
l.Info.Printf("[DB] Updated record for bundle [ %v ] successfully.\n", b.ID)
d.Metrics["count"].With(prometheus.Labels{"type": "Bundles updated"}).Inc()
status = statusOK
} else {
l.Warning.Printf("[DB] Unable to update record for bundle [ %v ], check with administrator.\n", b.ID)
status = statusFail
}
} else {
l.Warning.Printf("[DB] Record for bundle [ %v ] not found, check with administrator.\n", b.ID)
status = statusMissing
}
return
}
// UpdateSkuPrice function is to update the sku price linked to the provided ID
// with the provided new data.
// Parameters:
// - id: an int64 containing the id of the sku price to be updated in the db.
// - sp: a reference to SkuPrice models containing the new data to be updated.
// Returns:
// - status: an int for informing about the status of the operation.
// - e: an error raised in case of problems with the operation.
func (d *DbParameter) UpdateSkuPrice(id string, sp *models.SkuPrice) (status int, e error) {
l.Trace.Printf("[DB] Attempting to update the Sku Price [ %v ] now.\n", id)
var sp0 models.SkuPrice
if r := d.Db.Where(&models.SkuPrice{ID: id}).First(&sp0).Error; !errors.Is(r, gorm.ErrRecordNotFound) {
if e := d.Db.Model(&sp0).Updates(sp).Error; e == nil {
l.Info.Printf("[DB] Updated record for sku price [ %v ] successfully.\n", sp.ID)
d.Metrics["count"].With(prometheus.Labels{"type": "Sku Prices updated"}).Inc()
status = statusOK
} else {
l.Warning.Printf("[DB] Unable to update record for sku price [ %v ], check with administrator.\n", sp.ID)
status = statusFail
}
} else {
l.Warning.Printf("[DB] Record for sku price [ %v ] not found, check with administrator.\n", sp.ID)
status = statusMissing
}
return
}