diff --git a/docs/liquids/nova.md b/docs/liquids/nova.md new file mode 100644 index 000000000..9824872e --- /dev/null +++ b/docs/liquids/nova.md @@ -0,0 +1,24 @@ +# Liquid: `nova` + +This liquid provides support for the compute service Nova. + +- The suggested service type is `liquid-nova`. +- The suggested area is `compute`. + +## Service-specific configuration + +TODO + +## Resources + +TODO: Description + +| Resource | Unit | Capabilities | +| --- | --- | --- | +| `cores` | None | HasCapacity = true, HasQuota = true | +| `ram` | MiB | HasCapacity = true, HasQuota = true | +| `instances` | None | HasCapacity = true, HasQuota = true | +| `server_groups` | None | HasCapacity = false, HasQuota = true | +| `server_group_members` | None | HasCapacity = false, HasQuota = true | +| `instances_$FLAVOR_NAME` | None | HasCapacity = true, HasQuota = true | + diff --git a/internal/liquids/ironic/liquid.go b/internal/liquids/ironic/liquid.go index 3ef7fe89..e5525b80 100644 --- a/internal/liquids/ironic/liquid.go +++ b/internal/liquids/ironic/liquid.go @@ -32,7 +32,7 @@ import ( "github.com/sapcc/go-api-declarations/liquid" "github.com/sapcc/limes/internal/liquids" - "github.com/sapcc/limes/internal/plugins/nova" + "github.com/sapcc/limes/internal/liquids/nova" ) type Logic struct { diff --git a/internal/plugins/nova/binpack_simulation.go b/internal/liquids/nova/binpack_simulation.go similarity index 100% rename from internal/plugins/nova/binpack_simulation.go rename to internal/liquids/nova/binpack_simulation.go diff --git a/internal/plugins/nova/capacity.go b/internal/liquids/nova/capacity.go similarity index 100% rename from internal/plugins/nova/capacity.go rename to internal/liquids/nova/capacity.go diff --git a/internal/plugins/nova/constants.go b/internal/liquids/nova/constants.go similarity index 100% rename from internal/plugins/nova/constants.go rename to internal/liquids/nova/constants.go diff --git a/internal/plugins/nova/flavor_selection.go b/internal/liquids/nova/flavor_selection.go similarity index 100% rename from internal/plugins/nova/flavor_selection.go rename to internal/liquids/nova/flavor_selection.go diff --git a/internal/plugins/nova/gophercloud_fixes.go b/internal/liquids/nova/gophercloud_fixes.go similarity index 100% rename from internal/plugins/nova/gophercloud_fixes.go rename to internal/liquids/nova/gophercloud_fixes.go diff --git a/internal/plugins/nova/hypervisor_selection.go b/internal/liquids/nova/hypervisor_selection.go similarity index 100% rename from internal/plugins/nova/hypervisor_selection.go rename to internal/liquids/nova/hypervisor_selection.go diff --git a/internal/plugins/nova/hypervisor_subcapacity.go b/internal/liquids/nova/hypervisor_subcapacity.go similarity index 100% rename from internal/plugins/nova/hypervisor_subcapacity.go rename to internal/liquids/nova/hypervisor_subcapacity.go diff --git a/internal/liquids/nova/liquid.go b/internal/liquids/nova/liquid.go new file mode 100644 index 000000000..4f6f7e75 --- /dev/null +++ b/internal/liquids/nova/liquid.go @@ -0,0 +1,112 @@ +/******************************************************************************* +* +* Copyright 2024 SAP SE +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You should have received a copy of the License along with this +* program. If not, 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 nova + +import ( + "context" + "errors" + "time" + + "github.com/gophercloud/gophercloud/v2" + "github.com/gophercloud/gophercloud/v2/openstack" + "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/flavors" + "github.com/sapcc/go-api-declarations/liquid" +) + +type Logic struct { + NovaV2 *gophercloud.ServiceClient `yaml:"-"` +} + +// Init implements the liquidapi.Logic interface. +func (l *Logic) Init(ctx context.Context, provider *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (err error) { + l.NovaV2, err = openstack.NewComputeV2(provider, eo) + if err != nil { + return err + } + l.NovaV2.Microversion = "2.61" // to include extra specs in flavors.ListDetail() + + return nil +} + +// BuildServiceInfo implements the liquidapi.Logic interface. +func (l *Logic) BuildServiceInfo(ctx context.Context) (liquid.ServiceInfo, error) { + resources := map[liquid.ResourceName]liquid.ResourceInfo{ + "cores": { + Unit: liquid.UnitNone, + HasCapacity: true, + HasQuota: true, + }, + "instances": { + Unit: liquid.UnitNone, + HasCapacity: true, + HasQuota: true, + }, + "ram": { + Unit: liquid.UnitMebibytes, + HasCapacity: true, + HasQuota: true, + }, + "server_groups": { + Unit: liquid.UnitNone, + HasQuota: true, + }, + "server_group_members": { + Unit: liquid.UnitNone, + HasQuota: true, + }, + } + + err := FlavorSelection{}.ForeachFlavor(ctx, l.NovaV2, func(f flavors.Flavor) error { + if IsIronicFlavor(f) { + return nil + } + if f.ExtraSpecs["quota:separate"] == "true" { + resources[liquid.ResourceName("instances_"+f.Name)] = liquid.ResourceInfo{ + Unit: liquid.UnitNone, + HasCapacity: true, + HasQuota: true, + } + } + return nil + }) + if err != nil { + return liquid.ServiceInfo{}, err + } + + return liquid.ServiceInfo{ + Version: time.Now().Unix(), + Resources: resources, + }, nil +} + +// ScanCapacity implements the liquidapi.Logic interface. +func (l *Logic) ScanCapacity(ctx context.Context, req liquid.ServiceCapacityRequest, serviceInfo liquid.ServiceInfo) (liquid.ServiceCapacityReport, error) { + return liquid.ServiceCapacityReport{}, errors.New("TODO") +} + +// ScanUsage implements the liquidapi.Logic interface. +func (l *Logic) ScanUsage(ctx context.Context, projectUUID string, req liquid.ServiceUsageRequest, serviceInfo liquid.ServiceInfo) (liquid.ServiceUsageReport, error) { + return liquid.ServiceUsageReport{}, errors.New("TODO") +} + +// SetQuota implements the liquidapi.Logic interface. +func (l *Logic) SetQuota(ctx context.Context, projectUUID string, req liquid.ServiceQuotaRequest, serviceInfo liquid.ServiceInfo) error { + return errors.New("TODO") +} diff --git a/internal/plugins/nova/ostype_prober.go b/internal/liquids/nova/ostype_prober.go similarity index 100% rename from internal/plugins/nova/ostype_prober.go rename to internal/liquids/nova/ostype_prober.go diff --git a/internal/plugins/nova/server_group_prober.go b/internal/liquids/nova/server_group_prober.go similarity index 100% rename from internal/plugins/nova/server_group_prober.go rename to internal/liquids/nova/server_group_prober.go diff --git a/internal/plugins/nova/types.go b/internal/liquids/nova/types.go similarity index 100% rename from internal/plugins/nova/types.go rename to internal/liquids/nova/types.go diff --git a/internal/plugins/capacity_nova.go b/internal/plugins/capacity_nova.go index 7c1c8794..b8a4b2a2 100644 --- a/internal/plugins/capacity_nova.go +++ b/internal/plugins/capacity_nova.go @@ -39,7 +39,7 @@ import ( "github.com/sapcc/limes/internal/core" "github.com/sapcc/limes/internal/db" "github.com/sapcc/limes/internal/liquids" - "github.com/sapcc/limes/internal/plugins/nova" + "github.com/sapcc/limes/internal/liquids/nova" ) type capacityNovaPlugin struct { diff --git a/internal/plugins/nova.go b/internal/plugins/nova.go index bf31c293..7080e733 100644 --- a/internal/plugins/nova.go +++ b/internal/plugins/nova.go @@ -40,7 +40,7 @@ import ( "github.com/sapcc/limes/internal/core" "github.com/sapcc/limes/internal/db" - "github.com/sapcc/limes/internal/plugins/nova" + "github.com/sapcc/limes/internal/liquids/nova" ) type novaPlugin struct { diff --git a/internal/plugins/nova_subresources.go b/internal/plugins/nova_subresources.go index 4863ab36..59e3ea7a 100644 --- a/internal/plugins/nova_subresources.go +++ b/internal/plugins/nova_subresources.go @@ -31,7 +31,7 @@ import ( "github.com/sapcc/go-api-declarations/limes" "github.com/sapcc/limes/internal/core" - "github.com/sapcc/limes/internal/plugins/nova" + "github.com/sapcc/limes/internal/liquids/nova" ) // A compute instance as shown in our compute/instances subresources. diff --git a/main.go b/main.go index d9ecdf06..03a9edb1 100644 --- a/main.go +++ b/main.go @@ -64,6 +64,7 @@ import ( "github.com/sapcc/limes/internal/liquids/ironic" "github.com/sapcc/limes/internal/liquids/manila" "github.com/sapcc/limes/internal/liquids/neutron" + "github.com/sapcc/limes/internal/liquids/nova" "github.com/sapcc/limes/internal/liquids/octavia" "github.com/sapcc/limes/internal/liquids/swift" "github.com/sapcc/limes/internal/util" @@ -120,6 +121,8 @@ func main() { must.Succeed(liquidapi.Run(ctx, &manila.Logic{}, opts)) case "neutron": must.Succeed(liquidapi.Run(ctx, &neutron.Logic{}, opts)) + case "nova": + must.Succeed(liquidapi.Run(ctx, &nova.Logic{}, opts)) case "octavia": must.Succeed(liquidapi.Run(ctx, &octavia.Logic{}, opts)) case "swift":