Commit ccecd1e8 authored by Slawek Figiel's avatar Slawek Figiel
Browse files

[#682] Remove unused module

parent 95c7f98a
package testutil
import (
"fmt"
"math"
"github.com/go-pg/pg/v10"
"github.com/pkg/errors"
dbmodel "isc.org/stork/server/database/model"
)
// Configuration of the seed function with number of entries to generate.
type SeedConfig struct {
Machines int
// Number of apps per machine
Apps int
// Number of IPv4 subnets per app
SubnetsV4 int
// Number of IPv6 subnets per app
SubnetsV6 int
// Number of daemons per app
Daemons int
// Number of in-pool host reservations per subnet
HostReservationsInPool int
// Number of out-of-pool host reservations per subnet
HostReservationsOutOfPool int
// Number of (out-of-pool) global host reservations
// Half of them is IPv4 and half IPv6
HostReservationsGlobal int
// Number of in-pool prefix reservations per IPv6 subnet
PrefixReservationsInPool int
// Number of out-of-pool prefix reservations per IPv6 subnet
PrefixReservationsOutOfPool int
// Number of (out-of-pool) global prefix reservations
PrefixReservationsGlobal int
}
// The generator is simple and only for development use.
// It means that it has some limitations.
// This function returns false if the generated entries will be for sure invalid.
// But true output doesn't guarantee that the results are valid.
// Be careful with huge generation inputs.
func (c *SeedConfig) validate() (string, bool) {
if c.HostReservationsInPool > 100 {
return "too many in-pool host reservations", false
}
if c.HostReservationsOutOfPool > 155 {
return "too many out-of-pool host reservations", false
}
if c.PrefixReservationsInPool > 255 {
return "too many in-pool prefix reservations", false
}
if c.PrefixReservationsOutOfPool > 255 {
return "too many out-of-pool prefix reservations", false
}
if c.Machines*c.Apps*int(math.Max(float64(c.SubnetsV4), float64(c.SubnetsV6))) > 255*255 {
return "too many total subnets", false
}
if c.HostReservationsGlobal > 255 {
return "too many global host reservations", false
}
if c.PrefixReservationsGlobal > 255 {
return "too many global prefix reservations", false
}
if c.Machines*c.Apps > 255 {
return "too many machines or apps", false
}
return "", true
}
// Helper structure to store index of the iteration.
type index struct {
item int
total int
}
// Constructor of the index structure.
func newIndex(item, total int) *index {
return &index{item, total}
}
// Combine two indices into one.
// It is useful to obtain unique index in multi-nested for loop.
// The combination order is important. The caller index should
// be higher-order then an argument index.
func (i *index) combine(other *index) *index {
return newIndex(
i.item*other.total+other.item,
i.total*other.total,
)
}
// Generate fake data and save them into database.
// Helper function to perform performance tests.
func Seed(db *pg.DB, config *SeedConfig) error {
if msg, ok := config.validate(); !ok {
return errors.Errorf("Configuration exceed the generator limitations: %s", msg)
}
for machineI := 0; machineI < config.Machines; machineI++ {
machine := dbmodel.Machine{
Address: fmt.Sprintf("machine-%d", machineI),
AgentPort: int64(1024 + machineI),
Authorized: true,
}
machineIdx := newIndex(machineI, config.Machines)
if err := dbmodel.AddMachine(db, &machine); err != nil {
return err
}
for appI := 0; appI < config.Apps; appI++ {
appIdx := machineIdx.combine(newIndex(appI, config.Apps))
accessPoint := &dbmodel.AccessPoint{
Address: fmt.Sprintf("access-point-%d", appIdx.item),
Port: int64(1024 + appI),
Type: "control",
}
var daemons []*dbmodel.Daemon
for daemonI := 0; daemonI < config.Daemons; daemonI++ {
daemonIdx := appIdx.combine(newIndex(daemonI, config.Daemons))
daemon := &dbmodel.Daemon{
Pid: int32(10 + daemonI),
Name: fmt.Sprintf("daemon-v4-%d", daemonIdx.item),
Active: true,
Monitored: true,
Uptime: int64(daemonIdx.item),
}
daemons = append(daemons, daemon)
}
app := &dbmodel.App{
MachineID: machine.ID,
Active: true,
Type: dbmodel.AppTypeKea,
Name: fmt.Sprintf("app-%d", appIdx),
AccessPoints: []*dbmodel.AccessPoint{accessPoint},
Daemons: daemons,
}
_, err := dbmodel.AddApp(db, app)
if err != nil {
return err
}
for subnetI := 0; subnetI < config.SubnetsV4; subnetI++ {
subnetIdx := appIdx.combine(newIndex(subnetI, config.SubnetsV4))
subnetPrefix := fmt.Sprintf("10.%d.%d", (subnetIdx.item-subnetIdx.item%256)/256, subnetIdx.item%256)
subnet := &dbmodel.Subnet{
Prefix: fmt.Sprintf("%s.0/24", subnetPrefix),
ClientClass: fmt.Sprintf("class-%02d-%02d", (subnetIdx.item-subnetIdx.item%100)/100, subnetIdx.item%100),
AddressPools: []dbmodel.AddressPool{
{
LowerBound: fmt.Sprintf("%s.1", subnetPrefix),
UpperBound: fmt.Sprintf("%s.101", subnetPrefix),
},
},
AddrUtilization: int16(subnetIdx.item % 1000),
}
if err := dbmodel.AddSubnet(db, subnet); err != nil {
return err
}
host := &dbmodel.Host{
SubnetID: subnet.ID,
Hostname: fmt.Sprintf("host-v4-%d", subnetIdx.item),
IPReservations: generateSubnetReservationsIPv4(
subnetPrefix,
config.HostReservationsInPool,
config.HostReservationsOutOfPool),
}
if err := dbmodel.AddHost(db, host); err != nil {
return err
}
}
for subnetI := 0; subnetI < config.SubnetsV6; subnetI++ {
subnetIdx := appIdx.combine(newIndex(subnetI, config.SubnetsV6))
subnetPrefix := fmt.Sprintf("30:%02x:%02x", (subnetIdx.item-subnetIdx.item%256)/256, subnetIdx.item%256)
subnet := &dbmodel.Subnet{
Prefix: fmt.Sprintf("%s::/64", subnetPrefix),
ClientClass: fmt.Sprintf("class-%02d-%02d", (subnetIdx.item-subnetIdx.item%100)/100, subnetIdx.item%100),
AddressPools: []dbmodel.AddressPool{
{
LowerBound: fmt.Sprintf("%s::1", subnetPrefix),
UpperBound: fmt.Sprintf("%s::101", subnetPrefix),
},
},
PrefixPools: []dbmodel.PrefixPool{
{
Prefix: fmt.Sprintf("%s:FF::/64", subnetPrefix),
DelegatedLen: 80,
},
},
AddrUtilization: int16(subnetIdx.item % 1000),
PdUtilization: int16(subnetIdx.item % 1000),
}
if err := dbmodel.AddSubnet(db, subnet); err != nil {
return err
}
host := &dbmodel.Host{
SubnetID: subnet.ID,
Hostname: fmt.Sprintf("host-v6-%d", subnetIdx.item),
IPReservations: generateSubnetReservationsIPv6(
subnetPrefix,
config.HostReservationsInPool,
config.HostReservationsOutOfPool,
config.PrefixReservationsInPool,
config.PrefixReservationsOutOfPool,
),
}
if err := dbmodel.AddHost(db, host); err != nil {
return err
}
}
err = insertGlobalReservations(db, appIdx, config.HostReservationsGlobal, config.PrefixReservationsGlobal)
if err != nil {
return err
}
}
}
return nil
}
// Generate the IPv4 subnet reservations.
func generateSubnetReservationsIPv4(subnetPrefix string, hostsInPool, hostsOutOfPool int) []dbmodel.IPReservation {
var reservations []dbmodel.IPReservation
for reservationIdx := 0; reservationIdx < hostsInPool; reservationIdx++ {
reservation := dbmodel.IPReservation{
Address: fmt.Sprintf("%s.%d", subnetPrefix, reservationIdx+1),
}
reservations = append(reservations, reservation)
}
for reservationIdx := 0; reservationIdx < hostsOutOfPool; reservationIdx++ {
reservation := dbmodel.IPReservation{
Address: fmt.Sprintf("%s.%d", subnetPrefix, 102+reservationIdx),
}
reservations = append(reservations, reservation)
}
return reservations
}
// Generate the IPv6 subnet reservations.
func generateSubnetReservationsIPv6(subnetPrefix string, hostsInPool, hostsOutOfPool, prefixesInPool, prefixesOutOfPool int) []dbmodel.IPReservation {
var reservations []dbmodel.IPReservation
for reservationIdx := 0; reservationIdx < hostsInPool; reservationIdx++ {
reservation := dbmodel.IPReservation{
Address: fmt.Sprintf("%s::%d", subnetPrefix, reservationIdx+1),
}
reservations = append(reservations, reservation)
}
for reservationIdx := 0; reservationIdx < hostsOutOfPool; reservationIdx++ {
reservation := dbmodel.IPReservation{
Address: fmt.Sprintf("%s::%d", subnetPrefix, 102+reservationIdx),
}
reservations = append(reservations, reservation)
}
for reservationIdx := 0; reservationIdx < prefixesInPool; reservationIdx++ {
reservation := dbmodel.IPReservation{
Address: fmt.Sprintf("%s:FF:%02d::/80", subnetPrefix, reservationIdx+1),
}
reservations = append(reservations, reservation)
}
for reservationIdx := 0; reservationIdx < prefixesOutOfPool; reservationIdx++ {
reservation := dbmodel.IPReservation{
Address: fmt.Sprintf("%s:EE:%02d::/80", subnetPrefix, reservationIdx+1),
}
reservations = append(reservations, reservation)
}
return reservations
}
// Generate and insert the global reservations.
func insertGlobalReservations(db *pg.DB, parentIdx *index, hosts, prefixes int) error {
var globalReservations []dbmodel.IPReservation
for reservationI := 0; reservationI < hosts; reservationI++ {
var address string
if reservationI%2 == 0 {
address = fmt.Sprintf("33.1.%02d.%d", parentIdx.item, reservationI)
} else {
address = fmt.Sprintf("99:1:%02x::%d", parentIdx.item, reservationI)
}
reservation := dbmodel.IPReservation{
Address: address,
}
globalReservations = append(globalReservations, reservation)
}
for reservationI := 0; reservationI < prefixes; reservationI++ {
reservation := dbmodel.IPReservation{
Address: fmt.Sprintf("98:1:%02x:%d::/64", parentIdx.item, reservationI),
}
globalReservations = append(globalReservations, reservation)
}
globalHost := &dbmodel.Host{
SubnetID: 0,
Hostname: "host-global",
IPReservations: globalReservations,
}
return dbmodel.AddHost(db, globalHost)
}
package testutil
import (
"testing"
"github.com/stretchr/testify/require"
dbmodel "isc.org/stork/server/database/model"
dbtest "isc.org/stork/server/database/test"
)
// Test that multiple indexes can be combined into one.
func TestIndexCombination(t *testing.T) {
// Picture
// The data are indexed using schema: layer, row, column.
// The inner values indicate the unique index from a
// combination of these three data.
//
// Layer 0
// Columns
// 0 1 2 3 4
// R 0 0 1 2 3 4
// o 1 5 6 7 8 9
// w 2 10 11 12 13 14
// s 3 15 16 17 18 19
//
// Layer 1
// Columns
// 0 1 2 3 4
// R 0 20 21 22 23 24
// o 1 25 26 27 28 29
// w 2 30 31 32 33 34
// s 3 35 36 37 38 39
// Arrange
columns := 5
rows := 4
layers := 2
column := 2
row := 3
layer := 1
columnIdx := newIndex(column, columns)
rowIdx := newIndex(row, rows)
layerIdx := newIndex(layer, layers)
// Act
planeIdx := rowIdx.combine(columnIdx)
cubicIdx := layerIdx.combine(planeIdx)
// Assert
require.EqualValues(t, 17, planeIdx.item)
require.EqualValues(t, 20, planeIdx.total)
require.EqualValues(t, 37, cubicIdx.item)
require.EqualValues(t, 40, cubicIdx.total)
}
// Checks if the seed function creates expected number of entries.
func TestSeedExecute(t *testing.T) {
// Arrange
db, _, teardown := dbtest.SetupDatabaseTestCase(t)
defer teardown()
config := &SeedConfig{
Machines: 2,
Apps: 3,
SubnetsV4: 4,
SubnetsV6: 5,
Daemons: 6,
HostReservationsInPool: 7,
HostReservationsOutOfPool: 8,
HostReservationsGlobal: 9,
PrefixReservationsInPool: 11,
PrefixReservationsOutOfPool: 12,
PrefixReservationsGlobal: 13,
}
// Act
err := Seed(db, config)
// Assert
require.NoError(t, err)
machines, _ := dbmodel.GetAllMachines(db, nil)
require.Len(t, machines, 2)
apps, _ := dbmodel.GetAllApps(db, true)
require.Len(t, apps, 2*3)
subnetsV4, _ := dbmodel.GetAllSubnets(db, 4)
require.Len(t, subnetsV4, 2*3*4)
subnetsV6, _ := dbmodel.GetAllSubnets(db, 6)
require.Len(t, subnetsV6, 2*3*5)
hosts, _ := dbmodel.GetAllHosts(db, 0)
require.Len(t, hosts, 2*3*(4+5+1))
for _, app := range apps {
require.Len(t, app.Daemons, 6)
}
totalHostReservations := 0
totalPrefixReservations := 0
for _, host := range hosts {
for _, reservation := range host.IPReservations {
if reservation.IsPrefix() {
totalPrefixReservations++
} else {
totalHostReservations++
}
}
}
require.EqualValues(t, 2*3*(4+5)*(7+8)+2*3*9, totalHostReservations)
require.EqualValues(t, 2*3*5*(11+12)+2*3*13, totalPrefixReservations)
outOfPoolAddressCounts, _ := dbmodel.CountOutOfPoolAddressReservations(db)
totalOutOfPoolAddressReservations := uint64(0)
for _, count := range outOfPoolAddressCounts {
totalOutOfPoolAddressReservations += count
}
require.EqualValues(t, 2*3*(4+5)*8, totalOutOfPoolAddressReservations)
outOfPoolPrefixCounts, _ := dbmodel.CountOutOfPoolPrefixReservations(db)
totalOutOfPoolPrefixReservations := uint64(0)
for _, count := range outOfPoolPrefixCounts {
totalOutOfPoolPrefixReservations += count
}
require.EqualValues(t, 2*3*(5)*12, totalOutOfPoolPrefixReservations)
globalAddresses, globalNAs, globalPDs, _ := dbmodel.CountGlobalReservations(db)
require.EqualValues(t, 2*3*5, globalAddresses)
require.EqualValues(t, 2*3*4, globalNAs)
require.EqualValues(t, 2*3*13, globalPDs)
}
// Test that the seed function generates expected number of out-of-pool reservations.
func TestSeedGenerateHostReservations(t *testing.T) {
// Arrange
db, _, teardown := dbtest.SetupDatabaseTestCase(t)
defer teardown()
config := &SeedConfig{
Machines: 1,
Apps: 1,
SubnetsV4: 1,
SubnetsV6: 1,
Daemons: 0,
HostReservationsInPool: 10,
HostReservationsOutOfPool: 20,
// HostReservationsGlobalInPool: 0,
// HostReservationsGlobalOutOfPool: 0,
PrefixReservationsInPool: 0,
PrefixReservationsOutOfPool: 0,
// PrefixReservationsGlobalInPool: 0,
// PrefixReservationsGlobalOutOfPool: 0,
}
// Act
err := Seed(db, config)
// Assert
require.NoError(t, err)
outOfPoolCounts, _ := dbmodel.CountOutOfPoolAddressReservations(db)
totalOutOfPoolHostReservations := uint64(0)
for _, count := range outOfPoolCounts {
totalOutOfPoolHostReservations += count
}
require.EqualValues(t, 2*20, totalOutOfPoolHostReservations)
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment