diff --git a/ciao-controller/internal/datastore/datastore.go b/ciao-controller/internal/datastore/datastore.go index d7bc8f446..53213ff7a 100644 --- a/ciao-controller/internal/datastore/datastore.go +++ b/ciao-controller/internal/datastore/datastore.go @@ -44,6 +44,7 @@ var ( // Config contains configuration information for the datastore. type Config struct { + DBBackend persistentStore PersistentURI string TransientURI string InitTablesPath string @@ -82,6 +83,7 @@ type attachment struct { } type persistentStore interface { + init(config Config) error disconnect() // interfaces related to logging @@ -208,8 +210,13 @@ func (ds *Datastore) initExternalIPs() { // files if this is the first time the database has been // created. The datastore caches are also filled. func (ds *Datastore) Init(config Config) error { - // init persistentStore first... - ps, err := getPersistentStore(config) + ps := config.DBBackend + + if ps == nil { + ps = &sqliteDB{} + } + + err := ps.init(config) if err != nil { return err } diff --git a/ciao-controller/internal/datastore/datastore_test.go b/ciao-controller/internal/datastore/datastore_test.go index bf0b4e3c3..dcb970ffd 100644 --- a/ciao-controller/internal/datastore/datastore_test.go +++ b/ciao-controller/internal/datastore/datastore_test.go @@ -287,8 +287,6 @@ func TestDeleteInstanceResources(t *testing.T) { resourcesBefore[r.Rname] = r.Usage } - time.Sleep(1 * time.Second) - err = ds.DeleteInstance(instance.ID) if err != nil { t.Fatal(err) @@ -347,8 +345,6 @@ func TestDeleteInstanceNetwork(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) - err = ds.DeleteInstance(instance.ID) if err != nil { t.Fatal(err) @@ -373,8 +369,6 @@ func TestDeleteInstanceNetwork(t *testing.T) { t.Fatal("IP Address not released from cache") } - time.Sleep(1 * time.Second) - // clear tenant from cache ds.tenantsLock.Lock() delete(ds.tenants, tenant.ID) @@ -457,7 +451,6 @@ func TestGetAllInstancesFromTenant(t *testing.T) { // if we don't get 10 eventually, the test will timeout and fail instances, err := ds.GetAllInstancesFromTenant(tenant.ID) for len(instances) < 10 { - time.Sleep(1 * time.Second) instances, err = ds.GetAllInstancesFromTenant(tenant.ID) } @@ -480,7 +473,6 @@ func TestGetAllInstancesByNode(t *testing.T) { retry := 5 for len(newInstances) < len(instances) && retry > 0 { retry-- - time.Sleep(1 * time.Second) newInstances, err = ds.GetAllInstancesByNode(stat.NodeUUID) if err != nil { t.Fatal(err) @@ -501,7 +493,6 @@ func TestGetInstance(t *testing.T) { } for instance == nil { - time.Sleep(1 * time.Second) instance, err = ds.GetInstance(instances[0].ID) if err != nil && err != sql.ErrNoRows { t.Fatal(err) @@ -573,8 +564,6 @@ func TestHandleStats(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) - // check instance stats recorded for i := range stats { id := stats[i].InstanceUUID @@ -649,8 +638,6 @@ func TestGetInstanceLastStats(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) - serverStats := ds.GetInstanceLastStats(stat.NodeUUID) if len(serverStats.Servers) != len(instances) { @@ -714,8 +701,6 @@ func TestGetNodeLastStats(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) - computeNodes := ds.GetNodeLastStats() // how many compute Nodes should be here? If we want to @@ -725,7 +710,7 @@ func TestGetNodeLastStats(t *testing.T) { } } -func TestGetBatchFrameStatistics(t *testing.T) { +func createTestFrameTraces(label string) []payloads.FrameTrace { var nodes []payloads.SSNTPNode for i := 0; i < 3; i++ { node := payloads.SSNTPNode{ @@ -740,7 +725,7 @@ func TestGetBatchFrameStatistics(t *testing.T) { var frames []payloads.FrameTrace for i := 0; i < 3; i++ { stat := payloads.FrameTrace{ - Label: "batch_frame_test", + Label: label, Type: "type", Operand: "operand", StartTimestamp: time.Now().Format(time.RFC3339Nano), @@ -749,9 +734,12 @@ func TestGetBatchFrameStatistics(t *testing.T) { } frames = append(frames, stat) } + return frames +} +func TestGetBatchFrameStatistics(t *testing.T) { trace := payloads.Trace{ - Frames: frames, + Frames: createTestFrameTraces("batch_frame_test"), } err := ds.HandleTraceReport(trace) @@ -766,32 +754,8 @@ func TestGetBatchFrameStatistics(t *testing.T) { } func TestGetBatchFrameSummary(t *testing.T) { - var nodes []payloads.SSNTPNode - for i := 0; i < 3; i++ { - node := payloads.SSNTPNode{ - SSNTPUUID: uuid.Generate().String(), - SSNTPRole: "test", - TxTimestamp: time.Now().Format(time.RFC3339Nano), - RxTimestamp: time.Now().Format(time.RFC3339Nano), - } - nodes = append(nodes, node) - } - - var frames []payloads.FrameTrace - for i := 0; i < 3; i++ { - stat := payloads.FrameTrace{ - Label: "batch_summary_test", - Type: "type", - Operand: "operand", - StartTimestamp: time.Now().Format(time.RFC3339Nano), - EndTimestamp: time.Now().Format(time.RFC3339Nano), - Nodes: nodes, - } - frames = append(frames, stat) - } - trace := payloads.Trace{ - Frames: frames, + Frames: createTestFrameTraces("batch_summary_test"), } err := ds.HandleTraceReport(trace) @@ -839,25 +803,7 @@ func TestClearLog(t *testing.T) { } func TestAddFrameStat(t *testing.T) { - var nodes []payloads.SSNTPNode - for i := 0; i < 3; i++ { - node := payloads.SSNTPNode{ - SSNTPUUID: uuid.Generate().String(), - SSNTPRole: "test", - TxTimestamp: time.Now().Format(time.RFC3339Nano), - RxTimestamp: time.Now().Format(time.RFC3339Nano), - } - nodes = append(nodes, node) - } - - stat := payloads.FrameTrace{ - Label: "test", - Type: "type", - Operand: "operand", - StartTimestamp: time.Now().Format(time.RFC3339Nano), - EndTimestamp: time.Now().Format(time.RFC3339Nano), - Nodes: nodes, - } + stat := createTestFrameTraces("test")[0] err := ds.db.addFrameStat(stat) if err != nil { t.Fatal(err) @@ -951,8 +897,6 @@ func TestAllocateTenantIP(t *testing.T) { t.Fatal("IP Address not claimed in cache") } - time.Sleep(5 * time.Second) - // clear out cache ds.tenantsLock.Lock() delete(ds.tenants, tenant.ID) @@ -1110,32 +1054,8 @@ func TestAddCNCIIP(t *testing.T) { } func TestHandleTraceReport(t *testing.T) { - var nodes []payloads.SSNTPNode - for i := 0; i < 3; i++ { - node := payloads.SSNTPNode{ - SSNTPUUID: uuid.Generate().String(), - SSNTPRole: "test", - TxTimestamp: time.Now().Format(time.RFC3339Nano), - RxTimestamp: time.Now().Format(time.RFC3339Nano), - } - nodes = append(nodes, node) - } - - var frames []payloads.FrameTrace - for i := 0; i < 3; i++ { - stat := payloads.FrameTrace{ - Label: "test", - Type: "type", - Operand: "operand", - StartTimestamp: time.Now().Format(time.RFC3339Nano), - EndTimestamp: time.Now().Format(time.RFC3339Nano), - Nodes: nodes, - } - frames = append(frames, stat) - } - trace := payloads.Trace{ - Frames: frames, + Frames: createTestFrameTraces("test"), } err := ds.HandleTraceReport(trace) @@ -1192,8 +1112,6 @@ func TestReleaseTenantIP(t *testing.T) { t.Fatal("IP Address not marked Used") } - time.Sleep(1 * time.Second) - err = ds.ReleaseTenantIP(tenant.ID, ip.String()) if err != nil { t.Fatal(err) @@ -1210,8 +1128,6 @@ func TestReleaseTenantIP(t *testing.T) { t.Fatal("IP Address not released from cache") } - time.Sleep(1 * time.Second) - // clear tenant from cache ds.tenantsLock.Lock() delete(ds.tenants, tenant.ID) @@ -1307,7 +1223,6 @@ func TestRestartFailure(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) reason := payloads.RestartNoInstance err = ds.RestartFailure(instance.ID, reason) @@ -1332,7 +1247,6 @@ func TestStopFailure(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) reason := payloads.StopNoInstance err = ds.StopFailure(instance.ID, reason) @@ -1357,8 +1271,6 @@ func TestStartFailureFullCloud(t *testing.T) { t.Fatal(err) } - time.Sleep(1 * time.Second) - tenantBefore, err := ds.GetTenant(tenant.ID) if err != nil { t.Fatal(err) @@ -2825,6 +2737,7 @@ func TestMain(m *testing.M) { ds = new(Datastore) dsConfig := Config{ + DBBackend: &MemoryDB{}, PersistentURI: "file:memdb1?mode=memory&cache=shared", TransientURI: "file:memdb2?mode=memory&cache=shared", InitTablesPath: *tablesInitPath, @@ -2833,6 +2746,7 @@ func TestMain(m *testing.M) { err := ds.Init(dsConfig) if err != nil { + fmt.Fprintf(os.Stderr, "%v", err) os.Exit(1) } diff --git a/ciao-controller/internal/datastore/memorydb.go b/ciao-controller/internal/datastore/memorydb.go new file mode 100644 index 000000000..85630fcf9 --- /dev/null +++ b/ciao-controller/internal/datastore/memorydb.go @@ -0,0 +1,306 @@ +// Copyright (c) 2016 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package datastore + +import ( + "encoding/csv" + "fmt" + "os" + + "github.com/01org/ciao/ciao-controller/types" + "github.com/01org/ciao/payloads" +) + +// MemoryDB is a memory backed persistentStore implementation for unit testing +type MemoryDB struct { + tenants map[string]*tenant + workloads map[string]*workload + nodes map[string]*node + instances map[string]*types.Instance + tenantUsage map[string][]types.CiaoUsage + blockDevices map[string]types.BlockData + attachments map[string]types.StorageAttachment + instanceVolumes map[attachment]string + logEntries []*types.LogEntry + cnciWorkload *workload + + tableInitPath string + workloadsPath string +} + +func (db *MemoryDB) fillWorkloads() error { + f, err := os.Open(fmt.Sprintf("%s/workload_template.csv", db.tableInitPath)) + if err != nil { + return err + } + defer f.Close() + + r := csv.NewReader(f) + r.TrimLeadingSpace = true + r.Comment = '#' + + records, err := r.ReadAll() + if err != nil { + return err + } + + for _, line := range records { + + wl := workload{ + Workload: types.Workload{ + ID: line[0], + Description: line[1], + FWType: line[3], + VMType: payloads.Hypervisor(line[4]), + ImageID: line[5], + ImageName: line[6], + }, + filename: line[2], + } + + // CNCI does not appear in main table + internal := line[7] + if internal == "1" { + db.cnciWorkload = &wl + } else { + db.workloads[wl.ID] = &wl + } + } + return nil +} + +func (db *MemoryDB) init(config Config) error { + db.tenants = make(map[string]*tenant) + db.workloads = make(map[string]*workload) + db.nodes = make(map[string]*node) + db.instances = make(map[string]*types.Instance) + db.tenantUsage = make(map[string][]types.CiaoUsage) + db.blockDevices = make(map[string]types.BlockData) + db.attachments = make(map[string]types.StorageAttachment) + db.instanceVolumes = make(map[attachment]string) + + db.tableInitPath = config.InitTablesPath + db.workloadsPath = config.InitWorkloadsPath + err := db.fillWorkloads() + + if err != nil { + return fmt.Errorf("error parsing workloads: %v", err) + } + return nil +} + +func (db *MemoryDB) disconnect() { + +} + +func (db *MemoryDB) logEvent(tenantID string, eventType string, message string) error { + entry := types.LogEntry{ + TenantID: tenantID, + EventType: eventType, + Message: message, + } + + db.logEntries = append(db.logEntries, &entry) + + return nil +} + +func (db *MemoryDB) clearLog() error { + db.logEntries = nil + return nil +} + +func (db *MemoryDB) getEventLog() ([]*types.LogEntry, error) { + return db.logEntries, nil +} + +func (db *MemoryDB) getCNCIWorkloadID() (string, error) { + if db.cnciWorkload != nil { + return db.cnciWorkload.ID, nil + } + return "", fmt.Errorf("CNCI not found") +} + +func (db *MemoryDB) getWorkloadNoCache(id string) (*workload, error) { + workload, ok := db.workloads[id] + if !ok { + return nil, fmt.Errorf("Workload %s not found", id) + } + return workload, nil +} + +func (db *MemoryDB) getWorkloadsNoCache() ([]*workload, error) { + var workloads []*workload + for _, wl := range db.workloads { + workloads = append(workloads, wl) + } + return workloads, nil +} + +func (db *MemoryDB) addLimit(tenantID string, resourceID int, limit int) error { + return nil +} + +func (db *MemoryDB) addTenant(id string, MAC string) error { + t := &tenant{ + Tenant: types.Tenant{ + ID: id, + CNCIMAC: MAC, + }, + network: make(map[int]map[int]bool), + instances: make(map[string]*types.Instance), + devices: make(map[string]types.BlockData), + } + db.tenants[id] = t + return nil +} + +func (db *MemoryDB) getTenantNoCache(id string) (*tenant, error) { + tenant, ok := db.tenants[id] + if !ok { + return nil, fmt.Errorf("Tenant %s not found", id) + } + return tenant, nil +} + +func (db *MemoryDB) getTenantsNoCache() ([]*tenant, error) { + var tenants []*tenant + for _, t := range db.tenants { + tenants = append(tenants, t) + } + return tenants, nil +} + +func (db *MemoryDB) updateTenant(t *tenant) error { + _, ok := db.tenants[t.ID] + if !ok { + return fmt.Errorf("Tenant %s not found", t.ID) + } + db.tenants[t.ID] = t + return nil +} + +func (db *MemoryDB) releaseTenantIP(tenantID string, subnetInt int, rest int) error { + return nil +} + +func (db *MemoryDB) claimTenantIP(tenantID string, subnetInt int, rest int) error { + return nil +} + +func (db *MemoryDB) getInstances() ([]*types.Instance, error) { + var instances []*types.Instance + for _, instance := range db.instances { + instances = append(instances, instance) + } + return instances, nil +} + +func (db *MemoryDB) addInstance(instance *types.Instance) error { + return nil +} + +func (db *MemoryDB) removeInstance(instanceID string) error { + return nil +} + +func (db *MemoryDB) addNodeStatDB(stat payloads.Stat) error { + return nil +} + +func (db *MemoryDB) getNodeSummary() ([]*types.NodeSummary, error) { + return nil, nil +} + +func (db *MemoryDB) addInstanceStatsDB(stats []payloads.InstanceStat, nodeID string) error { + return nil +} + +func (db *MemoryDB) addFrameStat(stat payloads.FrameTrace) error { + return nil +} + +func (db *MemoryDB) getBatchFrameSummary() ([]types.BatchFrameSummary, error) { + return nil, nil +} + +func (db *MemoryDB) getBatchFrameStatistics(label string) ([]types.BatchFrameStat, error) { + return nil, nil +} + +func (db *MemoryDB) getWorkloadStorage(ID string) (*types.StorageResource, error) { + return nil, nil +} + +func (db *MemoryDB) getAllBlockData() (map[string]types.BlockData, error) { + return db.blockDevices, nil +} + +func (db *MemoryDB) createBlockData(data types.BlockData) error { + return nil +} + +func (db *MemoryDB) updateBlockData(types.BlockData) error { + return nil +} + +func (db *MemoryDB) deleteBlockData(string) error { + return nil +} + +func (db *MemoryDB) getTenantDevices(tenantID string) (map[string]types.BlockData, error) { + return nil, nil +} + +func (db *MemoryDB) createStorageAttachment(a types.StorageAttachment) error { + return nil +} + +func (db *MemoryDB) getAllStorageAttachments() (map[string]types.StorageAttachment, error) { + return db.attachments, nil +} + +func (db *MemoryDB) deleteStorageAttachment(ID string) error { + return nil +} + +func (db *MemoryDB) createPool(pool types.Pool) error { + return nil +} + +func (db *MemoryDB) updatePool(pool types.Pool) error { + return nil +} + +func (db *MemoryDB) deletePool(ID string) error { + return nil +} + +func (db *MemoryDB) getAllPools() map[string]types.Pool { + return make(map[string]types.Pool) +} + +func (db *MemoryDB) createMappedIP(m types.MappedIP) error { + return nil +} + +func (db *MemoryDB) deleteMappedIP(ID string) error { + return nil +} + +func (db *MemoryDB) getMappedIPs() map[string]types.MappedIP { + return make(map[string]types.MappedIP) +} diff --git a/ciao-controller/internal/datastore/sqlite3db.go b/ciao-controller/internal/datastore/sqlite3db.go index a343be31f..ad8ddff26 100644 --- a/ciao-controller/internal/datastore/sqlite3db.go +++ b/ciao-controller/internal/datastore/sqlite3db.go @@ -742,29 +742,27 @@ func (ds *sqliteDB) getTableDB(name string) *sql.DB { return nil } -// Init initializes the private data for the database object. +// init initializes the private data for the database object. // The sql tables are populated with initial data from csv // files if this is the first time the database has been // created. The datastore caches are also filled. -func getPersistentStore(config Config) (persistentStore, error) { - var ds = &sqliteDB{} - +func (ds *sqliteDB) init(config Config) error { u, err := url.Parse(config.PersistentURI) if err != nil { - return nil, fmt.Errorf("Invalid URL (%s) for persistent data store: %v", config.PersistentURI, err) + return fmt.Errorf("Invalid URL (%s) for persistent data store: %v", config.PersistentURI, err) } if u.Scheme == "file" { dbDir := filepath.Dir(u.Path) err = os.MkdirAll(dbDir, 0755) if err != nil && dbDir != "." { - return nil, fmt.Errorf("Unable to create db directory (%s) %v", dbDir, err) + return fmt.Errorf("Unable to create db directory (%s) %v", dbDir, err) } } err = ds.Connect(config.PersistentURI, config.TransientURI) if err != nil { - return nil, err + return err } ds.dbLock = &sync.Mutex{} @@ -799,7 +797,7 @@ func getPersistentStore(config Config) (persistentStore, error) { for _, table := range ds.tables { err = table.Init() if err != nil { - return nil, err + return err } } @@ -808,8 +806,7 @@ func getPersistentStore(config Config) (persistentStore, error) { // there's no initial data to populate _ = table.Populate() } - - return ds, nil + return nil } var pSQLLiteConfig = []string{ @@ -2017,113 +2014,6 @@ ON total_instances.node_id = total_exited.node_id return summary, err } -// GetFrameStatistics will return trace data by label id. -func (ds *sqliteDB) GetFrameStatistics(label string) ([]types.FrameStat, error) { - var stats []types.FrameStat - - ds.tdbLock.RLock() - - query := `WITH total AS - ( - SELECT id, - start_timestamp, - end_timestamp, - (julianday(end_timestamp) - julianday(start_timestamp)) * 24 * 60 * 60 AS total_elapsed - FROM frame_statistics - WHERE label = ? - ), - total_start AS - ( - SELECT trace_data.frame_id, - trace_data.ssntp_uuid, - (julianday(trace_data.tx_timestamp) - julianday(total.start_timestamp)) * 24 * 60 * 60 AS total_elapsed - FROM trace_data - JOIN total - WHERE rx_timestamp = '' and trace_data.frame_id = total.id - ), - total_end AS - ( - SELECT trace_data.frame_id, - trace_data.ssntp_uuid, - (julianday(total.end_timestamp) - julianday(trace_data.rx_timestamp)) * 24 * 60 * 60 AS total_elapsed - FROM trace_data - JOIN total - WHERE tx_timestamp = '' and trace_data.frame_id = total.id - ), - total_per_node AS - ( - SELECT trace_data.frame_id, - trace_data.ssntp_uuid, - (julianday(trace_data.tx_timestamp) - julianday(trace_data.rx_timestamp)) * 24 * 60 * 60 AS total_elapsed - FROM trace_data - WHERE tx_timestamp != '' and rx_timestamp != '' - ) - SELECT total_end.ssntp_uuid, - total.total_elapsed, - total_start.total_elapsed, - total_end.total_elapsed, - total_per_node.total_elapsed - FROM total - LEFT JOIN total_start - ON total.id = total_start.frame_id - LEFT JOIN total_end - ON total_start.frame_id = total_end.frame_id - LEFT JOIN total_per_node - ON total_start.frame_id = total_per_node.frame_id - ORDER BY total.start_timestamp;` - - datastore := ds.getTableDB("frame_statistics") - - rows, err := datastore.Query(query, label) - if err != nil { - ds.tdbLock.RUnlock() - return nil, err - } - defer rows.Close() - - stats = make([]types.FrameStat, 0) - - for rows.Next() { - var stat types.FrameStat - var uuid sql.NullString - var controllerTime sql.NullFloat64 - var launcherTime sql.NullFloat64 - var schedulerTime sql.NullFloat64 - var totalTime sql.NullFloat64 - err = rows.Scan(&uuid, &totalTime, &controllerTime, &launcherTime, &schedulerTime) - if err != nil { - ds.tdbLock.RUnlock() - return nil, err - } - - if uuid.Valid { - stat.ID = uuid.String - } - - if controllerTime.Valid { - stat.ControllerTime = controllerTime.Float64 - } - - if launcherTime.Valid { - stat.LauncherTime = launcherTime.Float64 - } - - if schedulerTime.Valid { - stat.SchedulerTime = schedulerTime.Float64 - } - - if totalTime.Valid { - stat.TotalElapsedTime = totalTime.Float64 - } - - stats = append(stats, stat) - } - - ds.tdbLock.RUnlock() - - return stats, err -} - // GetBatchFrameSummary will retieve the count of traces we have for a specific label func (ds *sqliteDB) getBatchFrameSummary() ([]types.BatchFrameSummary, error) { var stats []types.BatchFrameSummary diff --git a/ciao-controller/internal/datastore/sqlite3db_test.go b/ciao-controller/internal/datastore/sqlite3db_test.go index ccc791263..96e0d8e9a 100644 --- a/ciao-controller/internal/datastore/sqlite3db_test.go +++ b/ciao-controller/internal/datastore/sqlite3db_test.go @@ -21,16 +21,27 @@ import ( "github.com/01org/ciao/ciao-controller/types" "github.com/01org/ciao/ciao-storage" + "github.com/01org/ciao/payloads" "github.com/01org/ciao/ssntp/uuid" ) -func TestGetWorkloadStorage(t *testing.T) { +var dbCount = 1 + +func getPersistentStore() (persistentStore, error) { + ps := &sqliteDB{} config := Config{ - PersistentURI: "file:memdb3?mode=memory&cache=shared", - TransientURI: "file:memdb4?mode=memory&cache=shared", - } + PersistentURI: "file:memdb" + string(dbCount) + "?mode=memory&cache=shared", + TransientURI: "file:memdb" + string(dbCount+1) + "?mode=memory&cache=shared", + InitTablesPath: *tablesInitPath, + InitWorkloadsPath: *workloadsPath, + } + err := ps.init(config) + dbCount = dbCount + 2 + return ps, err +} - db, err := getPersistentStore(config) +func TestSQLiteDBGetWorkloadStorage(t *testing.T) { + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -43,13 +54,8 @@ func TestGetWorkloadStorage(t *testing.T) { db.disconnect() } -func TestGetTenantDevices(t *testing.T) { - config := Config{ - PersistentURI: "file:memdb5?mode=memory&cache=shared", - TransientURI: "file:memdb6?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) +func TestSQLiteDBGetTenantDevices(t *testing.T) { + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -85,13 +91,8 @@ func TestGetTenantDevices(t *testing.T) { db.disconnect() } -func TestGetTenantWithStorage(t *testing.T) { - config := Config{ - PersistentURI: "file:memdb11?mode=memory&cache=shared", - TransientURI: "file:memdb12?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) +func TestSQLiteDBGetTenantWithStorage(t *testing.T) { + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -140,13 +141,8 @@ func TestGetTenantWithStorage(t *testing.T) { db.disconnect() } -func TestGetAllBlockData(t *testing.T) { - config := Config{ - PersistentURI: "file:memdb7?mode=memory&cache=shared", - TransientURI: "file:memdb8?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) +func TestSQLiteDBGetAllBlockData(t *testing.T) { + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -181,13 +177,8 @@ func TestGetAllBlockData(t *testing.T) { db.disconnect() } -func TestDeleteBlockData(t *testing.T) { - config := Config{ - PersistentURI: "file:DeleteBlockData1?mode=memory&cache=shared", - TransientURI: "file:DeleteBlockData2?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) +func TestSQLiteDBDeleteBlockData(t *testing.T) { + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -227,13 +218,8 @@ func TestDeleteBlockData(t *testing.T) { db.disconnect() } -func TestGetAllStorageAttachments(t *testing.T) { - config := Config{ - PersistentURI: "file:memdb9?mode=memory&cache=shared", - TransientURI: "file:memdb10?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) +func TestSQLiteDBGetAllStorageAttachments(t *testing.T) { + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -309,12 +295,7 @@ func TestGetAllStorageAttachments(t *testing.T) { } func TestCreatePool(t *testing.T) { - config := Config{ - PersistentURI: "file:testcreatepool?mode=memory&cache=shared", - TransientURI: "file:testcreatepoolt?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -343,12 +324,7 @@ func TestCreatePool(t *testing.T) { } func TestUpdatePool(t *testing.T) { - config := Config{ - PersistentURI: "file:testupdatepool?mode=memory&cache=shared", - TransientURI: "file:testupdatepoolt?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -385,12 +361,7 @@ func TestUpdatePool(t *testing.T) { } func TestDeletePool(t *testing.T) { - config := Config{ - PersistentURI: "file:testdeletepool?mode=memory&cache=shared", - TransientURI: "file:testdeletepoolt?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -434,12 +405,7 @@ func TestDeletePool(t *testing.T) { } func TestCreateSubnet(t *testing.T) { - config := Config{ - PersistentURI: "file:testcreatesubnet?mode=memory&cache=shared", - TransientURI: "file:testcreatesubnett?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -489,12 +455,7 @@ func TestCreateSubnet(t *testing.T) { } func TestDeleteSubnet(t *testing.T) { - config := Config{ - PersistentURI: "file:testdeletesubnet?mode=memory&cache=shared", - TransientURI: "file:testdeletesubnett?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -541,12 +502,7 @@ func TestDeleteSubnet(t *testing.T) { } func TestCreateAddress(t *testing.T) { - config := Config{ - PersistentURI: "file:createaddress?mode=memory&cache=shared", - TransientURI: "file:createaddresst?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -587,12 +543,7 @@ func TestCreateAddress(t *testing.T) { } func TestDeleteAddress(t *testing.T) { - config := Config{ - PersistentURI: "file:deleteaddress?mode=memory&cache=shared", - TransientURI: "file:deleteaddresst?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -640,12 +591,7 @@ func TestDeleteAddress(t *testing.T) { } func TestCreateMappedIP(t *testing.T) { - config := Config{ - PersistentURI: "file:createmappedaddress?mode=memory&cache=shared", - TransientURI: "file:createmappedaddresst?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -703,12 +649,7 @@ func TestCreateMappedIP(t *testing.T) { } func TestDeleteMappedIP(t *testing.T) { - config := Config{ - PersistentURI: "file:deletedmappedaddress?mode=memory&cache=shared", - TransientURI: "file:deletemappedaddresst?mode=memory&cache=shared", - } - - db, err := getPersistentStore(config) + db, err := getPersistentStore() if err != nil { t.Fatal(err) } @@ -774,3 +715,242 @@ func TestDeleteMappedIP(t *testing.T) { t.Fatal("IP not deleted") } } + +func TestSQLiteDBGetAllWorkloads(t *testing.T) { + db, err := getPersistentStore() + if err != nil { + t.Fatal(err) + } + + wls, err := db.getWorkloadsNoCache() + if err != nil { + t.Fatal(err) + } + + if len(wls) == 0 { + t.Fatal("Expected non-empty workload list") + } + + for _, wl := range wls { + wl2, err := db.getWorkloadNoCache(wl.ID) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(wl, wl2) { + t.Fatal("Expected workload equality") + } + } +} + +func createTestTenant(db persistentStore, t *testing.T) *tenant { + tid := uuid.Generate().String() + thw, err := newHardwareAddr() + if err != nil { + t.Fatal(err) + } + err = db.addTenant(tid, thw.String()) + if err != nil { + t.Fatal(err) + } + + tn, err := db.getTenantNoCache(tid) + if err != nil { + t.Fatal(err) + } + if tn == nil { + t.Fatal("Expected added tenant") + } + + if tn.CNCIMAC != thw.String() { + t.Fatal("Expected added tenant CNCI MACs to be equal") + } + return tn +} + +func TestSQLiteDBTestTenants(t *testing.T) { + db, err := getPersistentStore() + if err != nil { + t.Fatal(err) + } + + tns, err := db.getTenantsNoCache() + if err != nil { + t.Fatal(err) + } + + if len(tns) != 0 { + t.Fatal("No tenants expected") + } + + _ = createTestTenant(db, t) + _ = createTestTenant(db, t) + + tns, err = db.getTenantsNoCache() + if err != nil { + t.Fatal(err) + } + + if len(tns) != 2 { + t.Fatal("2 tenants expected") + } + + for _, tn := range tns { + tn2, err := db.getTenantNoCache(tn.ID) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(tn, tn2) { + t.Fatal("Expected tenant equality") + } + } +} + +func TestSQLiteDBTestUpdateTenant(t *testing.T) { + db, err := getPersistentStore() + if err != nil { + t.Fatal(err) + } + + tn := createTestTenant(db, t) + tn.CNCIIP = "127.0.0.2" + + err = db.updateTenant(tn) + if err != nil { + t.Fatal(err) + } + + if tn.CNCIIP != "127.0.0.2" { + t.Fatal("Tenant not updated") + } +} + +func TestSQLiteDBGetBatchFrameStatistics(t *testing.T) { + db, err := getPersistentStore() + if err != nil { + t.Fatal(err) + } + + frames := createTestFrameTraces("batch_frame_test") + for _, frame := range frames { + err := db.addFrameStat(frame) + if err != nil { + t.Fatal(err) + } + } + + _, err = db.getBatchFrameStatistics("batch_frame_test") + if err != nil { + t.Fatal(err) + } +} + +func TestSQLiteDBGetBatchFrameSummary(t *testing.T) { + db, err := getPersistentStore() + if err != nil { + t.Fatal(err) + } + + frames := createTestFrameTraces("batch_summary_test") + for _, frame := range frames { + err := db.addFrameStat(frame) + if err != nil { + t.Fatal(err) + } + } + + _, err = db.getBatchFrameSummary() + if err != nil { + t.Fatal(err) + } +} + +func TestSQLiteDBEventLog(t *testing.T) { + db, err := getPersistentStore() + if err != nil { + t.Fatal(err) + } + + log, err := db.getEventLog() + if err != nil { + t.Fatal(err) + } + + if len(log) != 0 { + t.Fatal("Expected no log messages") + } + + tn := createTestTenant(db, t) + + err = db.logEvent(tn.ID, string(userError), "test message 1") + if err != nil { + t.Fatal(err) + } + + log, err = db.getEventLog() + if err != nil { + t.Fatal(err) + } + if len(log) != 1 { + t.Fatal("Expected 1 log message") + } + + err = db.logEvent(tn.ID, string(userError), "test message 2") + if err != nil { + t.Fatal(err) + } + + log, err = db.getEventLog() + if err != nil { + t.Fatal(err) + } + if len(log) != 2 { + t.Fatal("Expected 2 log message") + } + + err = db.clearLog() + if err != nil { + t.Fatal(err) + } + + log, err = db.getEventLog() + if err != nil { + t.Fatal(err) + } + if len(log) != 0 { + t.Fatal("Expected no log messages") + } +} + +func TestSQLiteDBInstanceStats(t *testing.T) { + db, err := getPersistentStore() + if err != nil { + t.Fatal(err) + } + + var stats []payloads.InstanceStat + + for i := 0; i < 3; i++ { + stat := payloads.InstanceStat{ + InstanceUUID: uuid.Generate().String(), + State: payloads.ComputeStatusRunning, + SSHIP: "192.168.0.1", + SSHPort: 34567, + MemoryUsageMB: 0, + DiskUsageMB: 0, + CPUUsage: 0, + } + stats = append(stats, stat) + } + + nodeID := uuid.Generate().String() + + err = db.addInstanceStatsDB(stats, nodeID) + if err != nil { + t.Fatal(err) + } + + _, err = db.getNodeSummary() + if err != nil { + t.Fatal(err) + } +}