diff --git a/firecracker.go b/firecracker.go index caec29ef..87a5a29a 100644 --- a/firecracker.go +++ b/firecracker.go @@ -307,3 +307,12 @@ func (f *Client) PatchGuestDriveByID(ctx context.Context, driveID, pathOnHost st return f.client.Operations.PatchGuestDriveByID(params) } + +// DescribeInstance is a wrapper for the swagger generated client to make +// calling of the API easier. +func (f *Client) DescribeInstance(ctx context.Context) (*ops.DescribeInstanceOK, error) { + params := ops.NewDescribeInstanceParams() + params.SetContext(ctx) + + return f.client.Operations.DescribeInstance(params) +} diff --git a/firecracker_test.go b/firecracker_test.go index c729a40c..d2a8a436 100644 --- a/firecracker_test.go +++ b/firecracker_test.go @@ -52,4 +52,8 @@ func TestClient(t *testing.T) { if _, err := client.PutGuestDriveByID(ctx, "test", drive); err != nil { t.Errorf("unexpected error on PutGuestDriveByID, %v", err) } + + if _, err := client.DescribeInstance(ctx); err != nil { + t.Errorf("unexpected error on DescribeInstance, %v", err) + } } diff --git a/machine.go b/machine.go index 97d6673b..475a7433 100644 --- a/machine.go +++ b/machine.go @@ -27,8 +27,9 @@ import ( "syscall" "time" - models "github.com/firecracker-microvm/firecracker-go-sdk/client/models" log "github.com/sirupsen/logrus" + + models "github.com/firecracker-microvm/firecracker-go-sdk/client/models" ) const ( @@ -707,6 +708,23 @@ func (m *Machine) UpdateGuestDrive(ctx context.Context, driveID, pathOnHost stri return nil } +// IsRunning makes sure that a Firecracker instance is running and responds via API by +// calling `DescribeInstance` endpoint behind. +func (m *Machine) IsRunning(ctx context.Context) error { + instance, err := m.client.DescribeInstance(ctx) + if err != nil { + return err + } + + state := StringValue(instance.Payload.State) + switch state { + case models.InstanceInfoStateStarting, models.InstanceInfoStateRunning: + return nil + default: + return fmt.Errorf("invalid instance state: %q", state) + } +} + // refreshMachineConfiguration synchronizes our cached representation of the machine configuration // with that reported by the Firecracker API func (m *Machine) refreshMachineConfiguration() error { diff --git a/machine_test.go b/machine_test.go index 8bcbfeee..4c80474b 100644 --- a/machine_test.go +++ b/machine_test.go @@ -335,6 +335,7 @@ func TestMicroVMExecution(t *testing.T) { t.Run("TestUpdateGuestDrive", func(t *testing.T) { testUpdateGuestDrive(ctx, t, m) }) t.Run("TestUpdateGuestNetworkInterface", func(t *testing.T) { testUpdateGuestNetworkInterface(ctx, t, m) }) t.Run("TestStartInstance", func(t *testing.T) { testStartInstance(ctx, t, m) }) + t.Run("IsRunning", func(t *testing.T) { testIsRunning(ctx, t, m) }) // Let the VMM start and stabilize... timer := time.NewTimer(5 * time.Second) @@ -691,6 +692,13 @@ func testGetMetadata(ctx context.Context, t *testing.T, m *Machine) { } } +func testIsRunning(ctx context.Context, t *testing.T, m *Machine) { + err := m.IsRunning(ctx) + if err != nil { + t.Errorf("machine is expected to be running: %v", err) + } +} + func TestLogFiles(t *testing.T) { cfg := Config{ Debug: true, diff --git a/machineiface.go b/machineiface.go index 194eb6b3..9d38fdee 100644 --- a/machineiface.go +++ b/machineiface.go @@ -30,4 +30,5 @@ type MachineIface interface { SetMetadata(context.Context, interface{}) error UpdateGuestDrive(context.Context, string, string, ...PatchGuestDriveByIDOpt) error UpdateGuestNetworkInterfaceRateLimit(context.Context, string, RateLimiterSet, ...PatchGuestNetworkInterfaceByIDOpt) error + IsRunning(ctx context.Context) error }