server

package
v1.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: Apache-2.0 Imports: 46 Imported by: 0

README

Server

Purpose

pkg/handler/server handles compute-server lifecycle.

It contains both deprecated v1 paths and the preferred v2 model, but the package is worth documenting separately because server handling is richer than basic CRUD:

  • create/update/delete
  • power operations
  • console access
  • snapshot creation
  • stronger validation of referenced resources

In v2, server context is primarily inferred from the selected network and related dependencies rather than from nested path scope.

Distinctive Behaviour

  • v1 servers are nested more explicitly under identity paths
  • v2 servers are network-linked resources with direct ID-based access
  • create/update validate the requested image through the provider layer under a single shared contract: the image must exist and be visible, be Ready, and be architecture/disk/virtualization compatible with the requested flavor. The two paths differ only in how a flavor the region no longer offers is treated: create rejects it with HTTP 422 (a create cannot proceed on retired hardware), while update tolerates it — the flavor is immutable and already in use by that exact server, so a retired flavor must not block an image update (e.g. a security-patch rebuild); the flavor-dependent compatibility checks are skipped because the flavor's metadata is unavailable, and Nova remains the backstop for a truly incompatible rebuild. An image reporting an unrecognized virtualization type fails closed with HTTP 422 — an unknown value is evidence of version skew or bad provider metadata, and the gate fronts a destructive root-disk rebuild. Absent metadata fails open on both axes: images lacking the virtualization property (out-of-band Glance uploads, images predating the label) or an architecture are not rejected, because absence of evidence is not evidence of incompatibility
  • create/update can validate and bind an SSH certificate authority
  • create accepts an explicit SSH injection mode: ca, identityKeypair, or none. Omitted values preserve the legacy contract: requests with sshCertificateAuthorityId resolve to ca, all other requests resolve to identityKeypair. Pinned servers cannot use identityKeypair because it is scoped to the tenant credentials and is not valid for the privileged pinned-create path
  • create/update reject references that escape the server's scope, enforced at the API edge with HTTP 422. The RBAC read check that fetches a reference only proves the caller may see it — a caller authorized across several tenancies could otherwise attach a resource from another tenancy — so an explicit scope check is applied on top:
    • a referenced security group must belong to the same network as the server. A network belongs to exactly one identity (one underlying OpenStack project), which belongs to one organization and project, so same-network is the natural granularity that closes the cross-tenancy hole and matches what OpenStack itself permits. The owning network is exposed identically in region (the NetworkLabel) and in the read model the compute service consumes (status.networkId), so the same rule is enforced uniformly across both services.
    • a referenced SSH certificate authority (which is not network-scoped) must share the server's organization and project.
  • create can carry an infrastructureRef that pins initial placement to a provider-specific physical host; reads expose the value in status so callers can verify the placement request that was persisted
  • create can carry immutable providerCreateGates; reads expose only status.remainingProviderCreateGates, while the stored Kubernetes object retains per-gate status details for operators
  • internal service callers can satisfy an existing provider-create gate through POST /api/v2/servers/{serverID}/provider-create-gates, which records the authenticated service actor, reason, and message on the status subresource
  • snapshot creation bridges server lifecycle into image provenance semantics
  • snapshot creation is also a cross-resource permission bridge: the caller must already be able to see the server and also be allowed to create images in the owning organization
  • the package exposes operational verbs:
    • start
    • stop
    • soft reboot
    • hard reboot
    • console output/session
  • server-name uniqueness is enforced per network to avoid aliasing cloud-side host identity; the Kubernetes resource name is derived deterministically from (networkID, serverName) so a duplicate create collides at the Kubernetes layer and is rejected with HTTP 409 without a read-before-write
  • server names are immutable after creation; update requests that supply a different name are rejected with HTTP 422
  • a v2 update replaces the persisted userData wholesale — an omitted field clears the stored value. The value is never applied to the running guest; it is consumed by the next recreate. A rebuild (image change) re-runs the create-time user data, not the updated value — applying updated user data on rebuild is deferred until Nova's microversion 2.57 user_data field is wired through the client library
  • the image is immutable through the v1 API: a v1 update carrying a different imageId succeeds but preserves the stored image (the rest of the update still applies). The imageId on a v1 update is ignored entirely and not validated — the value is discarded, so even one referencing a since-deleted image does not fail the update. The destructive rebuild contract below is exposed — and its compatibility validation and settlement-aware status reporting enforced — only by v2, so v1 must never let the stored image drift from the running server. This preserves v1's historical accept-and-ignore behaviour for image changes, now enforced at the API boundary instead of falling out of the old create-only image handling in the provider.
  • changing a v2 server's imageId is a destructive in-place Nova rebuild. It recreates the root disk and destroys its contents while retaining the server UUID, ports, fixed and floating IP relationships, attached data volumes, flavor, metadata, and placement. Flavor changes remain unsupported and are rejected with HTTP 422. An accepted rebuild destroys the previous root disk contents even if the rebuild subsequently fails, so failure recovery is choosing another image or replacing the server — never data restoration.
  • while a rebuild is pending (any recorded rebuild intent that has not settled-and-cleared, including one armed but not yet accepted by Nova) the v2 read reports provisioningStatus=provisioning even though the controller has finished its reconcile pass and core would otherwise report provisioned. The target image is not yet realized, so the server is not settled: provisioned means settled, which the sole consumer (uni-compute's instance settlement gate) relies on. A parked rebuild still surfaces as error, so a failure stays visible. See the provider's rebuild handling in ../../providers/internal/openstack/README.md.

Invariants And Guard Rails

  • v2 is the intended model; v1 is compatibility surface only.
  • direct v2 object access is gated to resources labeled with ResourceAPIVersionLabel=2.
  • A Server v2 is owned by its network for cascading deletion.
  • User data is validated at create time, and at update time whenever the persisted value would change, against the server provisioner's cloud-init parser, so malformed payloads are rejected with HTTP 422 instead of failing mid-provision (when managed augmentation parses them) or silently inside the guest at boot. With an SSH certificate authority (on update, the server's current one — updates preserve the CA chosen at create) the payload must additionally support managed cloud-init augmentation (which excludes gzip); without one, gzip payloads are accepted and passed through unmodified. Unchanged user-data is never re-validated, so legacy servers whose stored payloads predate validation keep working when a client PUTs the same bytes back.
  • GET /api/v2/servers/{serverID}/sshkey only returns the identity private key for servers where Region requested identityKeypair SSH injection during create. It returns not found for ca and none servers.
  • Power-operation errors are translated carefully from provider conflict/not-found states into user-facing API semantics.
  • infrastructureRef is create-time placement input. Updates preserve the existing value and the CRD marks it immutable, because moving an existing server to a different physical host is not an in-place server update.
  • providerCreateGates is create-time coordination input. Updates preserve the existing gate list and the CRD marks it immutable; only Region writes the derived status entries.
  • The provider-create gate action has its own region:servers:v2/provider-create-gates permission. It also requires normal server read access because callers must not satisfy gates on servers they cannot see.
  • The Kubernetes resource name for a v2 server is a deterministic UUID v5 derived from (networkID, serverName) at creation time, making the name immutable for the lifetime of the resource — consistent with OpenStack not changing a VM's hostname after boot.
  • Servers provisioned before this mechanism was introduced have random-UUID names and are not covered by it; deduplication applies only to resources created after deployment.
  • Image rebuild automatically submits at most one Nova-accepted action for a target image. A failed accepted action parks the server until a new image update or server replacement re-arms it; there is no explicit retry.

Caveats

  • This package is partly CRUD handler and partly operational façade over the provider compute API.
  • Snapshot behaviour is coupled to image provenance and ownership semantics, so server is not fully self-contained as a lifecycle concept.
  • Some semantics, such as user-data validation, are important but narrow enough that they should stay local to this package; the parser itself is owned by the server provisioner so the boundary check and provisioning behaviour cannot drift apart.

TODO

  • Delete the deprecated v1 handler surface once migration is complete.

Cross-Package Context

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	common.ClientArgs
}

Client provides a restful API for identities.

func NewClient

func NewClient(clientArgs common.ClientArgs) *Client

New creates a new client.

func (*Client) Create

func (c *Client) Create(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, identityID regionids.IdentityID, request *openapi.ServerWrite) (*openapi.ServerRead, error)

Create instantiates a new resource.

func (*Client) CreateConsoleSession added in v1.8.0

func (c *Client) CreateConsoleSession(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, identityID regionids.IdentityID, serverID regionids.ServerID) (*openapi.ConsoleSessionResponse, error)

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, serverID regionids.ServerID) error

Delete a resource.

func (*Client) Get

func (c *Client) Get(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, serverID regionids.ServerID) (*openapi.ServerRead, error)

Get a resource.

func (*Client) List

List returns an ordered list of all resources in scope.

func (*Client) Reboot added in v1.7.0

func (c *Client) Reboot(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, identityID regionids.IdentityID, serverID regionids.ServerID, hard bool) error

func (*Client) Start added in v1.7.0

func (c *Client) Start(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, identityID regionids.IdentityID, serverID regionids.ServerID) error

func (*Client) Stop added in v1.7.0

func (c *Client) Stop(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, identityID regionids.IdentityID, serverID regionids.ServerID) error

func (*Client) Update added in v1.2.0

func (c *Client) Update(ctx context.Context, organizationID identityids.OrganizationID, projectID identityids.ProjectID, identityID regionids.IdentityID, serverID regionids.ServerID, request *openapi.ServerWrite) (*openapi.ServerRead, error)

Update a resource.

type ClientV2 added in v1.13.0

type ClientV2 struct {
	*Client
}

func NewClientV2 added in v1.13.0

func NewClientV2(clientArgs common.ClientArgs) *ClientV2

func (*ClientV2) ConsoleOutputV2 added in v1.13.0

func (*ClientV2) ConsoleSessionV2 added in v1.13.0

func (c *ClientV2) ConsoleSessionV2(ctx context.Context, serverID regionids.ServerID) (*openapi.ConsoleSessionResponse, error)

func (*ClientV2) CreateV2 added in v1.13.0

func (c *ClientV2) CreateV2(ctx context.Context, request *openapi.ServerV2Create) (*openapi.ServerV2Read, error)

func (*ClientV2) CreateV2Snapshot added in v1.13.0

func (c *ClientV2) CreateV2Snapshot(ctx context.Context, serverID regionids.ServerID, request *openapi.SnapshotCreate) (*openapi.ImageResponse, error)

func (*ClientV2) DeleteV2 added in v1.13.0

func (c *ClientV2) DeleteV2(ctx context.Context, serverID regionids.ServerID) error

func (*ClientV2) GetV2 added in v1.13.0

func (c *ClientV2) GetV2(ctx context.Context, serverID regionids.ServerID) (*openapi.ServerV2Read, error)

func (*ClientV2) GetV2Raw added in v1.13.0

func (c *ClientV2) GetV2Raw(ctx context.Context, serverID string) (*regionv1.Server, error)

func (*ClientV2) ListV2 added in v1.13.0

func (*ClientV2) RebootV2 added in v1.13.0

func (c *ClientV2) RebootV2(ctx context.Context, serverID regionids.ServerID, hard bool) error

func (*ClientV2) SSHKey added in v1.13.0

func (c *ClientV2) SSHKey(ctx context.Context, serverID regionids.ServerID) (*openapi.SshKey, error)

func (*ClientV2) SatisfyProviderCreateGate added in v1.21.0

func (c *ClientV2) SatisfyProviderCreateGate(ctx context.Context, serverID regionids.ServerID, request *openapi.ServerProviderCreateGateAction) error

func (*ClientV2) StartV2 added in v1.13.0

func (c *ClientV2) StartV2(ctx context.Context, serverID regionids.ServerID) error

func (*ClientV2) StopV2 added in v1.13.0

func (c *ClientV2) StopV2(ctx context.Context, serverID regionids.ServerID) error

func (*ClientV2) UpdateV2 added in v1.13.0

func (c *ClientV2) UpdateV2(ctx context.Context, serverID regionids.ServerID, request *openapi.ServerV2Update) (*openapi.ServerV2Read, error)

Directories

Path Synopsis
Code generated by MockGen.
Code generated by MockGen.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL