diff --git a/incus-osd/internal/providers/provider_images.go b/incus-osd/internal/providers/provider_images.go index 12edf0f..24166c0 100644 --- a/incus-osd/internal/providers/provider_images.go +++ b/incus-osd/internal/providers/provider_images.go @@ -182,7 +182,7 @@ func (p *images) checkRelease(ctx context.Context) (*apiupdate.UpdateFull, error return nil, err } - resp, err := p.tryRequest(req) + resp, err := tryRequest(http.DefaultClient, req) if err != nil { return nil, err } @@ -269,23 +269,6 @@ func (p *images) checkRelease(ctx context.Context) (*apiupdate.UpdateFull, error return latestUpdate, nil } -func (*images) tryRequest(req *http.Request) (*http.Response, error) { - var err error - - for range 5 { - var resp *http.Response - - resp, err = http.DefaultClient.Do(req) - if err == nil { - return resp, nil - } - - time.Sleep(time.Second) - } - - return nil, errors.New("http request timed out after five seconds: %s" + err.Error()) -} - // An application from the images provider. type imagesApplication struct { provider *images diff --git a/incus-osd/internal/providers/provider_operations_center.go b/incus-osd/internal/providers/provider_operations_center.go index f311532..2df222d 100644 --- a/incus-osd/internal/providers/provider_operations_center.go +++ b/incus-osd/internal/providers/provider_operations_center.go @@ -283,6 +283,10 @@ func (p *operationsCenter) load(ctx context.Context) error { return errors.New("no operations center token provided") } + return p.loadTLS(ctx) +} + +func (p *operationsCenter) loadTLS(ctx context.Context) error { // Prepare the TLS config. tlsConfig := &tls.Config{ MinVersion: tls.VersionTLS13, @@ -356,8 +360,52 @@ func (p *operationsCenter) apiRequest(ctx context.Context, method string, path s } // Make the REST call. - resp, err := p.client.Do(req) + resp, err := tryRequest(p.client, req) if err != nil { + isCertError := func(err error) bool { + var urlErr *url.Error + + if !errors.As(err, &urlErr) { + return false + } + + { + var errCase0 *tls.CertificateVerificationError + switch { + case errors.As(urlErr.Unwrap(), &errCase0): + return true + default: + return false + } + } + } + + // Check if we got a potential transition to a globally valid certificate. + if p.serverCertificate != "" && isCertError(err) { + // Retry with the system CA. + p.serverCertificate = "" + + // Re-load the TLS client. + err = p.loadTLS(ctx) + if err != nil { + // Attempt to reset the client from config. + _ = p.load(ctx) + + return nil, err + } + + // Re-try the request. + resp, err := p.apiRequest(ctx, method, path, data) + if err != nil { + return nil, err + } + + // If successful, commit the change of config. + delete(p.state.System.Provider.Config.Config, "server_certificate") + + return resp, nil + } + return nil, err } diff --git a/incus-osd/internal/providers/utils.go b/incus-osd/internal/providers/utils.go index 81c253b..651da83 100644 --- a/incus-osd/internal/providers/utils.go +++ b/incus-osd/internal/providers/utils.go @@ -9,6 +9,7 @@ import ( "io" "net/http" "os" + "time" ) func downloadAsset(ctx context.Context, client *http.Client, assetURL string, expectedSHA256 string, target string, progressFunc func(float64)) error { @@ -77,3 +78,21 @@ func downloadAsset(ctx context.Context, client *http.Client, assetURL string, ex return nil } + +// tryRequest attempts the request multiple times over 5s. +func tryRequest(client *http.Client, req *http.Request) (*http.Response, error) { + var err error + + for range 5 { + var resp *http.Response + + resp, err = client.Do(req) + if err == nil { + return resp, nil + } + + time.Sleep(time.Second) + } + + return nil, errors.New("http request timed out after five seconds: %s" + err.Error()) +} diff --git a/incus-osd/internal/services/service_linstor.go b/incus-osd/internal/services/service_linstor.go index abcaee4..f625af8 100644 --- a/incus-osd/internal/services/service_linstor.go +++ b/incus-osd/internal/services/service_linstor.go @@ -196,7 +196,7 @@ func (n *Linstor) Start(ctx context.Context) error { } // Start Linstor Satellite. - err = systemd.StartUnit(ctx, "linstor-satellite.service") + err = systemd.EnableUnit(ctx, true, "linstor-satellite.service") if err != nil { return err }