Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compute v2: Add Live Migration Action #728

Merged
merged 6 commits into from
Jan 21, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions acceptance/openstack/compute/v2/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,31 @@ func TestMigrate(t *testing.T) {
t.Fatalf("Error during migration: %v", err)
}
}

func TestLiveMigrate(t *testing.T) {
client, err := clients.NewComputeV2Client()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}

server, err := CreateServer(t, client)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
defer DeleteServer(t, client, server)

t.Logf("Attempting to migrate server %s", server.ID)

blockMigration := false
diskOverCommit := false

liveMigrateOpts := migrate.LiveMigrateOpts{
BlockMigration: &blockMigration,
DiskOverCommit: &diskOverCommit,
}

err = migrate.LiveMigrate(client, server.ID, liveMigrateOpts).ExtractErr()
if err != nil {
t.Fatalf("Error during live migration: %v", err)
}
}
19 changes: 18 additions & 1 deletion openstack/compute/v2/extensions/migrate/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@
Package migrate provides functionality to migrate servers that have been
provisioned by the OpenStack Compute service.

Example to Migrate a Server
Example of Migrate Server (migrate Action)

serverID := "b16ba811-199d-4ffd-8839-ba96c1185a67"
err := migrate.Migrate(computeClient, serverID).ExtractErr()
if err != nil {
panic(err)
}

Example of Live-Migrate Server (os-migrateLive Action)

serverID := "b16ba811-199d-4ffd-8839-ba96c1185a67"
host := "01c0cadef72d47e28a672a76060d492c"
blockMigration := false

migrationOpts := migrate.LiveMigrateOpts{
Host: &host,
BlockMigration: &blockMigration,
}

err := migrate.LiveMigrate(computeClient, serverID, migrationOpts).ExtractErr()
if err != nil {
panic(err)
}

*/
package migrate
40 changes: 40 additions & 0 deletions openstack/compute/v2/extensions/migrate/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,43 @@ func Migrate(client *gophercloud.ServiceClient, id string) (r MigrateResult) {
_, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"migrate": nil}, nil, nil)
return
}

// LiveMigrateOptsBuilder allows extensions to add additional parameters to the
// LiveMigrate request.
type LiveMigrateOptsBuilder interface {
ToLiveMigrateMap() (map[string]interface{}, error)
}

// LiveMigrateOpts specifies parameters of live migrate action.
type LiveMigrateOpts struct {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can you remove this line?

// The host to which to migrate the server.
// If this parameter is None, the scheduler chooses a host.
Host *string `json:"host"`
Copy link
Contributor

@jtopjian jtopjian Jan 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this so you can specify "" as a valid host value? Is that different than if host was omitted from the request body?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jtopjian It will be "valid", but I reckon that "host" has to be always in the request body according to this line.
Moreover there's no clear mention as for migrate-server-migrate-action

If you specify null or don’t specify this parameter, the scheduler chooses a host.

I might be wrong please correct me.


// Set to True to migrate local disks by using block migration.
// If the source or destination host uses shared storage and you set
// this value to True, the live migration fails.
BlockMigration *bool `json:"block_migration,omitempty"`

// Set to True to enable over commit when the destination host is checked
// for available disk space. Set to False to disable over commit. This setting
// affects only the libvirt virt driver.
DiskOverCommit *bool `json:"disk_over_commit,omitempty"`
}

// ToLiveMigrateMap constructs a request body from LiveMigrateOpts.
func (opts LiveMigrateOpts) ToLiveMigrateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "os-migrateLive")
}

// LiveMigrate will initiate a live-migration (without rebooting) of the instance to another host.
func LiveMigrate(client *gophercloud.ServiceClient, id string, opts LiveMigrateOptsBuilder) (r MigrateResult) {
b, err := opts.ToLiveMigrateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = client.Post(actionURL(client, id), b, nil, nil)
return
}
15 changes: 15 additions & 0 deletions openstack/compute/v2/extensions/migrate/testing/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,18 @@ func mockMigrateResponse(t *testing.T, id string) {
w.WriteHeader(http.StatusAccepted)
})
}

func mockLiveMigrateResponse(t *testing.T, id string) {
th.Mux.HandleFunc("/servers/"+id+"/action", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
th.TestJSONRequest(t, r, `{
"os-migrateLive": {
"host": "01c0cadef72d47e28a672a76060d492c",
"block_migration": false,
"disk_over_commit": true
}
}`)
w.WriteHeader(http.StatusAccepted)
})
}
20 changes: 20 additions & 0 deletions openstack/compute/v2/extensions/migrate/testing/requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,23 @@ func TestMigrate(t *testing.T) {
err := migrate.Migrate(client.ServiceClient(), serverID).ExtractErr()
th.AssertNoErr(t, err)
}

func TestLiveMigrate(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()

mockLiveMigrateResponse(t, serverID)

host := "01c0cadef72d47e28a672a76060d492c"
blockMigration := false
diskOverCommit := true

migrationOpts := migrate.LiveMigrateOpts{
Host: &host,
BlockMigration: &blockMigration,
DiskOverCommit: &diskOverCommit,
}

err := migrate.LiveMigrate(client.ServiceClient(), serverID, migrationOpts).ExtractErr()
th.AssertNoErr(t, err)
}