Error if we can't remove instance from provider

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
Gabriel Adrian Samfira 2023-03-26 22:08:51 +03:00
parent c6366ab896
commit e7f208367b
No known key found for this signature in database
GPG key ID: 7D073DCC2C074CB5
18 changed files with 114 additions and 85 deletions

View file

@ -84,11 +84,11 @@ func ConnectLXD(url string, args *ConnectionArgs) (InstanceServer, error) {
//
// Unless the remote server is trusted by the system CA, the remote certificate must be provided (TLSServerCert).
func ConnectLXDWithContext(ctx context.Context, url string, args *ConnectionArgs) (InstanceServer, error) {
logger.Debug("Connecting to a remote LXD over HTTPS")
// Cleanup URL
url = strings.TrimSuffix(url, "/")
logger.Debug("Connecting to a remote LXD over HTTPS", logger.Ctx{"url": url})
return httpsLXD(ctx, url, args)
}

View file

@ -440,7 +440,7 @@ func (r *ProtocolLXD) rawWebsocket(url string) (*websocket.Conn, error) {
if remoteTCP != nil {
err = tcp.SetTimeouts(remoteTCP, 0)
if err != nil {
logger.Error("Failed setting TCP timeouts on remote connection", logger.Ctx{"err": err})
logger.Warn("Failed setting TCP timeouts on remote connection", logger.Ctx{"err": err})
}
}

View file

@ -651,8 +651,8 @@ func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExec
}
// Call the control handler with a connection to the control socket
if args.Control != nil && fds["control"] != "" {
conn, err := r.GetOperationWebsocket(opAPI.ID, fds["control"])
if args.Control != nil && fds[api.SecretNameControl] != "" {
conn, err := r.GetOperationWebsocket(opAPI.ID, fds[api.SecretNameControl])
if err != nil {
return nil, err
}
@ -1546,11 +1546,11 @@ func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.Contain
var controlConn *websocket.Conn
// Call the control handler with a connection to the control socket
if fds["control"] == "" {
if fds[api.SecretNameControl] == "" {
return nil, fmt.Errorf("Did not receive a file descriptor for the control channel")
}
controlConn, err = r.GetOperationWebsocket(opAPI.ID, fds["control"])
controlConn, err = r.GetOperationWebsocket(opAPI.ID, fds[api.SecretNameControl])
if err != nil {
return nil, err
}

View file

@ -1046,8 +1046,8 @@ func (r *ProtocolLXD) ExecInstance(instanceName string, exec api.InstanceExecPos
}
// Call the control handler with a connection to the control socket
if args.Control != nil && fds["control"] != "" {
conn, err := r.GetOperationWebsocket(opAPI.ID, fds["control"])
if args.Control != nil && fds[api.SecretNameControl] != "" {
conn, err := r.GetOperationWebsocket(opAPI.ID, fds[api.SecretNameControl])
if err != nil {
return nil, err
}
@ -2209,11 +2209,11 @@ func (r *ProtocolLXD) ConsoleInstance(instanceName string, console api.InstanceC
var controlConn *websocket.Conn
// Call the control handler with a connection to the control socket
if fds["control"] == "" {
if fds[api.SecretNameControl] == "" {
return nil, fmt.Errorf("Did not receive a file descriptor for the control channel")
}
controlConn, err = r.GetOperationWebsocket(opAPI.ID, fds["control"])
controlConn, err = r.GetOperationWebsocket(opAPI.ID, fds[api.SecretNameControl])
if err != nil {
return nil, err
}
@ -2296,11 +2296,11 @@ func (r *ProtocolLXD) ConsoleInstanceDynamic(instanceName string, console api.In
}
// Call the control handler with a connection to the control socket.
if fds["control"] == "" {
if fds[api.SecretNameControl] == "" {
return nil, nil, fmt.Errorf("Did not receive a file descriptor for the control channel")
}
controlConn, err := r.GetOperationWebsocket(opAPI.ID, fds["control"])
controlConn, err := r.GetOperationWebsocket(opAPI.ID, fds[api.SecretNameControl])
if err != nil {
return nil, nil, err
}
@ -2600,7 +2600,7 @@ func (r *ProtocolLXD) proxyMigration(targetOp *operation, targetSecrets map[stri
}
}
if targetSecrets["control"] == "" {
if targetSecrets[api.SecretNameControl] == "" {
return fmt.Errorf("Migration target didn't setup the required \"control\" socket")
}
@ -2614,17 +2614,17 @@ func (r *ProtocolLXD) proxyMigration(targetOp *operation, targetSecrets map[stri
proxies := map[string]*proxy{}
// Connect the control socket
sourceConn, err := source.GetOperationWebsocket(sourceOp.ID, sourceSecrets["control"])
sourceConn, err := source.GetOperationWebsocket(sourceOp.ID, sourceSecrets[api.SecretNameControl])
if err != nil {
return err
}
targetConn, err := r.GetOperationWebsocket(targetOp.ID, targetSecrets["control"])
targetConn, err := r.GetOperationWebsocket(targetOp.ID, targetSecrets[api.SecretNameControl])
if err != nil {
return err
}
proxies["control"] = &proxy{
proxies[api.SecretNameControl] = &proxy{
done: shared.WebsocketProxy(sourceConn, targetConn),
sourceConn: sourceConn,
targetConn: targetConn,
@ -2632,7 +2632,7 @@ func (r *ProtocolLXD) proxyMigration(targetOp *operation, targetSecrets map[stri
// Connect the data sockets
for name := range sourceSecrets {
if name == "control" {
if name == api.SecretNameControl {
continue
}
@ -2657,13 +2657,13 @@ func (r *ProtocolLXD) proxyMigration(targetOp *operation, targetSecrets map[stri
// Cleanup once everything is done
go func() {
// Wait for control socket
<-proxies["control"].done
_ = proxies["control"].sourceConn.Close()
_ = proxies["control"].targetConn.Close()
<-proxies[api.SecretNameControl].done
_ = proxies[api.SecretNameControl].sourceConn.Close()
_ = proxies[api.SecretNameControl].targetConn.Close()
// Then deal with the others
for name, proxy := range proxies {
if name == "control" {
if name == api.SecretNameControl {
continue
}

10
vendor/github.com/lxc/lxd/shared/api/migration.go generated vendored Normal file
View file

@ -0,0 +1,10 @@
package api
// SecretNameControl is the secret name used for the migration control connection.
const SecretNameControl = "control"
// SecretNameFilesystem is the secret name used for the migration filesystem connection.
const SecretNameFilesystem = "fs"
// SecretNameState is the secret name used for the migration state connection.
const SecretNameState = "criu" // Legacy value used for backward compatibility for clients.

View file

@ -150,6 +150,7 @@ var InstanceConfigKeysAny = map[string]func(value string) error{
"volatile.apply_quota": validate.IsAny,
"volatile.uuid": validate.Optional(validate.IsUUID),
"volatile.vsock_id": validate.Optional(validate.IsInt64),
"volatile.uuid.generation": validate.Optional(validate.IsUUID),
// Caller is responsible for full validation of any raw.* value.
"raw.idmap": validate.IsAny,
@ -256,8 +257,12 @@ var InstanceConfigKeysVM = map[string]func(value string) error{
"raw.qemu": validate.IsAny,
"raw.qemu.conf": validate.IsAny,
"security.agent.metrics": validate.Optional(validate.IsBool),
"security.secureboot": validate.Optional(validate.IsBool),
"security.agent.metrics": validate.Optional(validate.IsBool),
"security.secureboot": validate.Optional(validate.IsBool),
"security.sev": validate.Optional(validate.IsBool),
"security.sev.policy.es": validate.Optional(validate.IsBool),
"security.sev.session.dh": validate.Optional(validate.IsAny),
"security.sev.session.data": validate.Optional(validate.IsAny),
"agent.nic_config": validate.Optional(validate.IsBool),

View file

@ -375,10 +375,14 @@ func DefaultWriter(conn *websocket.Conn, w io.WriteCloser, writeDone chan<- bool
type WebsocketIO struct {
Conn *websocket.Conn
reader io.Reader
mu sync.Mutex
mur sync.Mutex
muw sync.Mutex
}
func (w *WebsocketIO) Read(p []byte) (n int, err error) {
w.mur.Lock()
defer w.mur.Unlock()
// Get new message if no active one.
if w.reader == nil {
var mt int
@ -410,26 +414,22 @@ func (w *WebsocketIO) Read(p []byte) (n int, err error) {
return n, nil
}
func (w *WebsocketIO) Write(p []byte) (n int, err error) {
w.mu.Lock()
defer w.mu.Unlock()
wr, err := w.Conn.NextWriter(websocket.BinaryMessage)
func (w *WebsocketIO) Write(p []byte) (int, error) {
w.muw.Lock()
defer w.muw.Unlock()
err := w.Conn.WriteMessage(websocket.BinaryMessage, p)
if err != nil {
return -1, err
}
n, err = wr.Write(p)
if err != nil {
return -1, err
}
return n, wr.Close()
return len(p), nil
}
// Close sends a control message indicating the stream is finished, but it does not actually close the socket.
func (w *WebsocketIO) Close() error {
w.mu.Lock()
defer w.mu.Unlock()
w.muw.Lock()
defer w.muw.Unlock()
// Target expects to get a control message indicating stream is finished.
return w.Conn.WriteMessage(websocket.TextMessage, []byte{})
}

View file

@ -138,6 +138,10 @@ func (s *SimpleStreams) cachedDownload(path string) ([]byte, error) {
return nil, err
}
if len(body) == 0 {
return nil, fmt.Errorf("No content in download from %q", uri)
}
// Attempt to store in cache
if s.cachePath != "" {
cacheName := filepath.Join(s.cachePath, fileName)
@ -159,11 +163,13 @@ func (s *SimpleStreams) parseStream() (*Stream, error) {
return nil, err
}
pathURL, _ := shared.JoinUrls(s.url, path)
// Parse the idnex
stream := Stream{}
err = json.Unmarshal(body, &stream)
if err != nil {
return nil, fmt.Errorf("Failed decoding stream JSON from %q: %w", path, err)
return nil, fmt.Errorf("Failed decoding stream JSON from %q: %w (%q)", pathURL, err, string(body))
}
s.cachedStream = &stream