2022-09-05 03:06:08 -04:00
|
|
|
/*
|
|
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
2022-04-21 10:28:37 -04:00
|
|
|
package qemu
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-06-30 05:14:26 -04:00
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
2022-04-21 10:28:37 -04:00
|
|
|
|
2022-09-21 07:47:57 -04:00
|
|
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
2022-04-21 10:28:37 -04:00
|
|
|
)
|
|
|
|
|
2022-06-30 05:14:26 -04:00
|
|
|
const qemuMetadataEndpoint = "10.42.0.1:8080"
|
|
|
|
|
2022-11-15 04:31:55 -05:00
|
|
|
// Cloud provides an interface to fake a CSP API for QEMU instances.
|
|
|
|
type Cloud struct{}
|
|
|
|
|
|
|
|
// New returns a new Cloud instance.
|
|
|
|
func New() *Cloud {
|
|
|
|
return &Cloud{}
|
|
|
|
}
|
2022-04-21 10:28:37 -04:00
|
|
|
|
|
|
|
// List retrieves all instances belonging to the current constellation.
|
2022-11-15 04:31:55 -05:00
|
|
|
func (c *Cloud) List(ctx context.Context) ([]metadata.InstanceMetadata, error) {
|
|
|
|
instancesRaw, err := c.retrieveMetadata(ctx, "/peers")
|
2022-06-30 05:14:26 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-06-28 10:08:05 -04:00
|
|
|
var instances []metadata.InstanceMetadata
|
2022-06-30 05:14:26 -04:00
|
|
|
err = json.Unmarshal(instancesRaw, &instances)
|
|
|
|
return instances, err
|
2022-04-21 10:28:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Self retrieves the current instance.
|
2022-11-15 04:31:55 -05:00
|
|
|
func (c *Cloud) Self(ctx context.Context) (metadata.InstanceMetadata, error) {
|
|
|
|
instanceRaw, err := c.retrieveMetadata(ctx, "/self")
|
2022-06-30 05:14:26 -04:00
|
|
|
if err != nil {
|
2022-06-28 10:08:05 -04:00
|
|
|
return metadata.InstanceMetadata{}, err
|
2022-06-30 05:14:26 -04:00
|
|
|
}
|
|
|
|
|
2022-06-28 10:08:05 -04:00
|
|
|
var instance metadata.InstanceMetadata
|
2022-06-30 05:14:26 -04:00
|
|
|
err = json.Unmarshal(instanceRaw, &instance)
|
|
|
|
return instance, err
|
2022-04-21 10:28:37 -04:00
|
|
|
}
|
|
|
|
|
2022-08-01 10:51:34 -04:00
|
|
|
// GetLoadBalancerEndpoint returns the endpoint of the load balancer.
|
2022-11-02 07:56:16 -04:00
|
|
|
// For QEMU, the load balancer is the first control plane node returned by the metadata API.
|
2022-11-15 04:31:55 -05:00
|
|
|
func (c *Cloud) GetLoadBalancerEndpoint(ctx context.Context) (string, error) {
|
|
|
|
endpointRaw, err := c.retrieveMetadata(ctx, "/endpoint")
|
2022-11-02 07:56:16 -04:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
var endpoint string
|
|
|
|
err = json.Unmarshal(endpointRaw, &endpoint)
|
|
|
|
return endpoint, err
|
2022-05-24 04:04:42 -04:00
|
|
|
}
|
|
|
|
|
2022-07-29 10:30:24 -04:00
|
|
|
// UID returns the UID of the constellation.
|
2022-11-15 04:31:55 -05:00
|
|
|
func (c *Cloud) UID(ctx context.Context) (string, error) {
|
2022-07-29 10:30:24 -04:00
|
|
|
// We expect only one constellation to be deployed in the same QEMU / libvirt environment.
|
|
|
|
// the UID can be an empty string.
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
2022-11-15 04:31:55 -05:00
|
|
|
func (c *Cloud) retrieveMetadata(ctx context.Context, uri string) ([]byte, error) {
|
2022-06-30 05:14:26 -04:00
|
|
|
url := &url.URL{
|
|
|
|
Scheme: "http",
|
|
|
|
Host: qemuMetadataEndpoint,
|
|
|
|
Path: uri,
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url.String(), nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
res, err := (&http.Client{}).Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
|
|
|
|
return io.ReadAll(res.Body)
|
2022-05-24 04:04:42 -04:00
|
|
|
}
|