1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
//go:build linux && cgo && !agent
package cluster
import (
"context"
"database/sql"
"time"
"github.com/lxc/incus/v6/internal/server/device/config"
"github.com/lxc/incus/v6/internal/server/instance/instancetype"
"github.com/lxc/incus/v6/shared/api"
"github.com/lxc/incus/v6/shared/osarch"
)
// Code generation directives.
//
//generate-database:mapper target instances.mapper.go
//generate-database:mapper reset -i -b "//go:build linux && cgo && !agent"
//
//generate-database:mapper stmt -e instance objects
//generate-database:mapper stmt -e instance objects-by-ID
//generate-database:mapper stmt -e instance objects-by-Project
//generate-database:mapper stmt -e instance objects-by-Project-and-Type
//generate-database:mapper stmt -e instance objects-by-Project-and-Type-and-Node
//generate-database:mapper stmt -e instance objects-by-Project-and-Type-and-Node-and-Name
//generate-database:mapper stmt -e instance objects-by-Project-and-Type-and-Name
//generate-database:mapper stmt -e instance objects-by-Project-and-Name
//generate-database:mapper stmt -e instance objects-by-Project-and-Name-and-Node
//generate-database:mapper stmt -e instance objects-by-Project-and-Node
//generate-database:mapper stmt -e instance objects-by-Type
//generate-database:mapper stmt -e instance objects-by-Type-and-Name
//generate-database:mapper stmt -e instance objects-by-Type-and-Name-and-Node
//generate-database:mapper stmt -e instance objects-by-Type-and-Node
//generate-database:mapper stmt -e instance objects-by-Node
//generate-database:mapper stmt -e instance objects-by-Node-and-Name
//generate-database:mapper stmt -e instance objects-by-Name
//generate-database:mapper stmt -e instance id
//generate-database:mapper stmt -e instance create
//generate-database:mapper stmt -e instance rename
//generate-database:mapper stmt -e instance delete-by-Project-and-Name
//generate-database:mapper stmt -e instance update
//
//generate-database:mapper method -i -e instance GetMany references=Config,Device
//generate-database:mapper method -i -e instance GetOne
//generate-database:mapper method -i -e instance ID
//generate-database:mapper method -i -e instance Exists
//generate-database:mapper method -i -e instance Create references=Config,Device
//generate-database:mapper method -i -e instance Rename
//generate-database:mapper method -i -e instance DeleteOne-by-Project-and-Name
//generate-database:mapper method -i -e instance Update references=Config,Device
// Instance is a value object holding db-related details about an instance.
type Instance struct {
ID int
Project string `db:"primary=yes&join=projects.name"`
Name string `db:"primary=yes"`
Node string `db:"join=nodes.name"`
Type instancetype.Type
Snapshot bool `db:"ignore"`
Architecture int
Ephemeral bool
CreationDate time.Time
Stateful bool
LastUseDate sql.NullTime
Description string `db:"coalesce=''"`
ExpiryDate sql.NullTime
}
// InstanceFilter specifies potential query parameter fields.
type InstanceFilter struct {
ID *int
Project *string
Name *string
Node *string
Type *instancetype.Type
}
// ToAPI converts the database Instance to API type.
func (i *Instance) ToAPI(ctx context.Context, tx *sql.Tx, instanceDevices map[int][]Device, profileConfigs map[int]map[string]string, profileDevices map[int][]Device) (*api.Instance, error) {
profiles, err := GetInstanceProfiles(ctx, tx, i.ID)
if err != nil {
return nil, err
}
if profileConfigs == nil {
profileConfigs, err = GetAllProfileConfigs(ctx, tx)
if err != nil {
return nil, err
}
}
if profileDevices == nil {
profileDevices, err = GetAllProfileDevices(ctx, tx)
if err != nil {
return nil, err
}
}
apiProfiles := make([]api.Profile, 0, len(profiles))
profileNames := make([]string, 0, len(profiles))
for _, p := range profiles {
apiProfile, err := p.ToAPI(ctx, tx, profileConfigs, profileDevices)
if err != nil {
return nil, err
}
apiProfiles = append(apiProfiles, *apiProfile)
profileNames = append(profileNames, p.Name)
}
var devices map[string]Device
if instanceDevices != nil {
devices = map[string]Device{}
for _, dev := range instanceDevices[i.ID] {
devices[dev.Name] = dev
}
} else {
devices, err = GetInstanceDevices(ctx, tx, i.ID)
if err != nil {
return nil, err
}
}
apiDevices := DevicesToAPI(devices)
expandedDevices := ExpandInstanceDevices(config.NewDevices(apiDevices), apiProfiles)
config, err := GetInstanceConfig(ctx, tx, i.ID)
if err != nil {
return nil, err
}
expandedConfig := ExpandInstanceConfig(config, apiProfiles)
archName, err := osarch.ArchitectureName(i.Architecture)
if err != nil {
return nil, err
}
return &api.Instance{
InstancePut: api.InstancePut{
Architecture: archName,
Config: config,
Devices: apiDevices,
Ephemeral: i.Ephemeral,
Profiles: profileNames,
Stateful: i.Stateful,
Description: i.Description,
},
CreatedAt: i.CreationDate,
ExpandedConfig: expandedConfig,
ExpandedDevices: expandedDevices.CloneNative(),
Name: i.Name,
LastUsedAt: i.LastUseDate.Time,
Location: i.Node,
Type: i.Type.String(),
Project: i.Project,
}, nil
}
// GetAllInstanceConfigs returns a map of all instance configurations, keyed by database ID.
func GetAllInstanceConfigs(ctx context.Context, tx *sql.Tx) (map[int]map[string]string, error) {
return GetConfig(ctx, tx, "instances", "instance")
}
// GetAllInstanceDevices returns a map of all instance devices, keyed by database ID.
func GetAllInstanceDevices(ctx context.Context, tx *sql.Tx) (map[int][]Device, error) {
return GetDevices(ctx, tx, "instances", "instance")
}
|