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 all 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
9 changes: 9 additions & 0 deletions acceptance/clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type AcceptanceTestChoices struct {

// DBDatastoreTypeID is the datastore type version for DB tests.
DBDatastoreVersion string

// LiveMigrate indicates ability to run multi-node migration tests
LiveMigrate bool
}

// AcceptanceTestChoicesFromEnv populates a ComputeChoices struct from environment variables.
Expand All @@ -57,6 +60,11 @@ func AcceptanceTestChoicesFromEnv() (*AcceptanceTestChoices, error) {
dbDatastoreType := os.Getenv("OS_DB_DATASTORE_TYPE")
dbDatastoreVersion := os.Getenv("OS_DB_DATASTORE_VERSION")

var liveMigrate bool
if v := os.Getenv("OS_LIVE_MIGRATE"); v != "" {
liveMigrate = true
}

missing := make([]string, 0, 3)
if imageID == "" {
missing = append(missing, "OS_IMAGE_ID")
Expand Down Expand Up @@ -106,6 +114,7 @@ func AcceptanceTestChoicesFromEnv() (*AcceptanceTestChoices, error) {
ShareNetworkID: shareNetworkID,
DBDatastoreType: dbDatastoreType,
DBDatastoreVersion: dbDatastoreVersion,
LiveMigrate: liveMigrate,
}, nil
}

Expand Down
37 changes: 37 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,40 @@ func TestMigrate(t *testing.T) {
t.Fatalf("Error during migration: %v", err)
}
}

func TestLiveMigrate(t *testing.T) {
choices, err := clients.AcceptanceTestChoicesFromEnv()
if err != nil {
t.Fatal(err)
}

if !choices.LiveMigrate {
t.Skip("Testing of live migration is disabled")
}

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
39 changes: 39 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,42 @@ 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 {
// The host to which to migrate the server.
// If this parameter is None, the scheduler chooses a host.
Host *string `json:"host"`

// 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)
}