github.com/gophercloud/gophercloud@v1.11.0/internal/acceptance/openstack/clustering/v1/clusters_test.go (about)

     1  //go:build acceptance || clustering || policies
     2  // +build acceptance clustering policies
     3  
     4  package v1
     5  
     6  import (
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/gophercloud/gophercloud/internal/acceptance/clients"
    12  	"github.com/gophercloud/gophercloud/internal/acceptance/tools"
    13  	"github.com/gophercloud/gophercloud/openstack/clustering/v1/actions"
    14  	"github.com/gophercloud/gophercloud/openstack/clustering/v1/clusters"
    15  	th "github.com/gophercloud/gophercloud/testhelper"
    16  )
    17  
    18  func TestClustersCRUD(t *testing.T) {
    19  	client, err := clients.NewClusteringV1Client()
    20  	th.AssertNoErr(t, err)
    21  
    22  	profile, err := CreateProfile(t, client)
    23  	th.AssertNoErr(t, err)
    24  	defer DeleteProfile(t, client, profile.ID)
    25  
    26  	cluster, err := CreateCluster(t, client, profile.ID)
    27  	th.AssertNoErr(t, err)
    28  	defer DeleteCluster(t, client, cluster.ID)
    29  
    30  	// Test clusters list
    31  	allPages, err := clusters.List(client, nil).AllPages()
    32  	th.AssertNoErr(t, err)
    33  
    34  	allClusters, err := clusters.ExtractClusters(allPages)
    35  	th.AssertNoErr(t, err)
    36  
    37  	var found bool
    38  	for _, v := range allClusters {
    39  		if v.ID == cluster.ID {
    40  			found = true
    41  		}
    42  	}
    43  
    44  	th.AssertEquals(t, found, true)
    45  
    46  	// Test cluster update
    47  	updateOpts := clusters.UpdateOpts{
    48  		Name: cluster.Name + "-UPDATED",
    49  	}
    50  
    51  	res := clusters.Update(client, cluster.ID, updateOpts)
    52  	th.AssertNoErr(t, res.Err)
    53  
    54  	actionID, err := GetActionID(res.Header)
    55  	th.AssertNoErr(t, err)
    56  
    57  	err = WaitForAction(client, actionID)
    58  	th.AssertNoErr(t, err)
    59  
    60  	newCluster, err := clusters.Get(client, cluster.ID).Extract()
    61  	th.AssertNoErr(t, err)
    62  	th.AssertEquals(t, newCluster.Name, cluster.Name+"-UPDATED")
    63  
    64  	tools.PrintResource(t, newCluster)
    65  
    66  	// Test cluster health
    67  	actionID, err = clusters.Check(client, cluster.ID).Extract()
    68  	th.AssertNoErr(t, err)
    69  
    70  	err = WaitForAction(client, actionID)
    71  	th.AssertNoErr(t, err)
    72  }
    73  
    74  func TestClustersResize(t *testing.T) {
    75  	client, err := clients.NewClusteringV1Client()
    76  	th.AssertNoErr(t, err)
    77  
    78  	profile, err := CreateProfile(t, client)
    79  	th.AssertNoErr(t, err)
    80  	defer DeleteProfile(t, client, profile.ID)
    81  
    82  	cluster, err := CreateCluster(t, client, profile.ID)
    83  	th.AssertNoErr(t, err)
    84  	defer DeleteCluster(t, client, cluster.ID)
    85  
    86  	iTrue := true
    87  	resizeOpts := clusters.ResizeOpts{
    88  		AdjustmentType: clusters.ChangeInCapacityAdjustment,
    89  		Number:         1,
    90  		Strict:         &iTrue,
    91  	}
    92  
    93  	actionID, err := clusters.Resize(client, cluster.ID, resizeOpts).Extract()
    94  	th.AssertNoErr(t, err)
    95  
    96  	err = WaitForAction(client, actionID)
    97  	th.AssertNoErr(t, err)
    98  
    99  	newCluster, err := clusters.Get(client, cluster.ID).Extract()
   100  	th.AssertNoErr(t, err)
   101  	th.AssertEquals(t, newCluster.DesiredCapacity, 2)
   102  
   103  	tools.PrintResource(t, newCluster)
   104  }
   105  
   106  func TestClustersScale(t *testing.T) {
   107  	client, err := clients.NewClusteringV1Client()
   108  	th.AssertNoErr(t, err)
   109  
   110  	profile, err := CreateProfile(t, client)
   111  	th.AssertNoErr(t, err)
   112  	defer DeleteProfile(t, client, profile.ID)
   113  
   114  	cluster, err := CreateCluster(t, client, profile.ID)
   115  	th.AssertNoErr(t, err)
   116  	defer DeleteCluster(t, client, cluster.ID)
   117  
   118  	// increase cluster size to 2
   119  	scaleOutOpts := clusters.ScaleOutOpts{
   120  		Count: 1,
   121  	}
   122  	actionID, err := clusters.ScaleOut(client, cluster.ID, scaleOutOpts).Extract()
   123  	th.AssertNoErr(t, err)
   124  
   125  	err = WaitForAction(client, actionID)
   126  	th.AssertNoErr(t, err)
   127  
   128  	newCluster, err := clusters.Get(client, cluster.ID).Extract()
   129  	th.AssertNoErr(t, err)
   130  	th.AssertEquals(t, newCluster.DesiredCapacity, 2)
   131  
   132  	// reduce cluster size to 0
   133  	count := 2
   134  	scaleInOpts := clusters.ScaleInOpts{
   135  		Count: &count,
   136  	}
   137  
   138  	actionID, err = clusters.ScaleIn(client, cluster.ID, scaleInOpts).Extract()
   139  	th.AssertNoErr(t, err)
   140  
   141  	err = WaitForAction(client, actionID)
   142  	th.AssertNoErr(t, err)
   143  
   144  	newCluster, err = clusters.Get(client, cluster.ID).Extract()
   145  	th.AssertNoErr(t, err)
   146  	th.AssertEquals(t, newCluster.DesiredCapacity, 0)
   147  
   148  	tools.PrintResource(t, newCluster)
   149  }
   150  
   151  func TestClustersPolicies(t *testing.T) {
   152  	client, err := clients.NewClusteringV1Client()
   153  	th.AssertNoErr(t, err)
   154  	client.Microversion = "1.5"
   155  
   156  	profile, err := CreateProfile(t, client)
   157  	th.AssertNoErr(t, err)
   158  	defer DeleteProfile(t, client, profile.ID)
   159  
   160  	cluster, err := CreateCluster(t, client, profile.ID)
   161  	th.AssertNoErr(t, err)
   162  	defer DeleteCluster(t, client, cluster.ID)
   163  
   164  	policy, err := CreatePolicy(t, client)
   165  	th.AssertNoErr(t, err)
   166  	defer DeletePolicy(t, client, policy.ID)
   167  
   168  	iTrue := true
   169  	attachPolicyOpts := clusters.AttachPolicyOpts{
   170  		PolicyID: policy.ID,
   171  		Enabled:  &iTrue,
   172  	}
   173  
   174  	actionID, err := clusters.AttachPolicy(client, cluster.ID, attachPolicyOpts).Extract()
   175  	th.AssertNoErr(t, err)
   176  
   177  	err = WaitForAction(client, actionID)
   178  	th.AssertNoErr(t, err)
   179  
   180  	// List all policies in the cluster to see if the policy was
   181  	// successfully attached.
   182  	allPages, err := clusters.ListPolicies(client, cluster.ID, nil).AllPages()
   183  	th.AssertNoErr(t, err)
   184  
   185  	allPolicies, err := clusters.ExtractClusterPolicies(allPages)
   186  	th.AssertNoErr(t, err)
   187  
   188  	var found bool
   189  	for _, v := range allPolicies {
   190  		tools.PrintResource(t, v)
   191  		if v.PolicyID == policy.ID {
   192  			found = true
   193  		}
   194  	}
   195  
   196  	th.AssertEquals(t, found, true)
   197  
   198  	// Set the policy to disabled
   199  	iFalse := false
   200  	updatePolicyOpts := clusters.UpdatePolicyOpts{
   201  		PolicyID: policy.ID,
   202  		Enabled:  &iFalse,
   203  	}
   204  
   205  	actionID, err = clusters.UpdatePolicy(client, cluster.ID, updatePolicyOpts).Extract()
   206  	th.AssertNoErr(t, err)
   207  
   208  	err = WaitForAction(client, actionID)
   209  	th.AssertNoErr(t, err)
   210  
   211  	clusterPolicy, err := clusters.GetPolicy(client, cluster.ID, policy.ID).Extract()
   212  	th.AssertNoErr(t, err)
   213  	th.AssertEquals(t, clusterPolicy.Enabled, false)
   214  
   215  	// Detach the policy
   216  	detachPolicyOpts := clusters.DetachPolicyOpts{
   217  		PolicyID: policy.ID,
   218  	}
   219  
   220  	actionID, err = clusters.DetachPolicy(client, cluster.ID, detachPolicyOpts).Extract()
   221  	th.AssertNoErr(t, err)
   222  
   223  	err = WaitForAction(client, actionID)
   224  	th.AssertNoErr(t, err)
   225  
   226  	// List all policies in the cluster to see if the policy was
   227  	// successfully detached.
   228  	allPages, err = clusters.ListPolicies(client, cluster.ID, nil).AllPages()
   229  	th.AssertNoErr(t, err)
   230  
   231  	allPolicies, err = clusters.ExtractClusterPolicies(allPages)
   232  	th.AssertNoErr(t, err)
   233  
   234  	found = false
   235  	for _, v := range allPolicies {
   236  		tools.PrintResource(t, v)
   237  		if v.PolicyID == policy.ID {
   238  			found = true
   239  		}
   240  	}
   241  
   242  	th.AssertEquals(t, found, false)
   243  }
   244  
   245  func TestClustersRecovery(t *testing.T) {
   246  	client, err := clients.NewClusteringV1Client()
   247  	th.AssertNoErr(t, err)
   248  
   249  	profile, err := CreateProfile(t, client)
   250  	th.AssertNoErr(t, err)
   251  	defer DeleteProfile(t, client, profile.ID)
   252  
   253  	cluster, err := CreateCluster(t, client, profile.ID)
   254  	th.AssertNoErr(t, err)
   255  	defer DeleteCluster(t, client, cluster.ID)
   256  
   257  	recoverOpts := clusters.RecoverOpts{
   258  		Operation: clusters.RebuildRecovery,
   259  	}
   260  
   261  	actionID, err := clusters.Recover(client, cluster.ID, recoverOpts).Extract()
   262  	th.AssertNoErr(t, err)
   263  
   264  	err = WaitForAction(client, actionID)
   265  	th.AssertNoErr(t, err)
   266  
   267  	newCluster, err := clusters.Get(client, cluster.ID).Extract()
   268  	th.AssertNoErr(t, err)
   269  
   270  	tools.PrintResource(t, newCluster)
   271  }
   272  
   273  func TestClustersAddNode(t *testing.T) {
   274  	client, err := clients.NewClusteringV1Client()
   275  	th.AssertNoErr(t, err)
   276  
   277  	profile, err := CreateProfile(t, client)
   278  	th.AssertNoErr(t, err)
   279  	defer DeleteProfile(t, client, profile.ID)
   280  
   281  	cluster, err := CreateCluster(t, client, profile.ID)
   282  	th.AssertNoErr(t, err)
   283  	defer DeleteCluster(t, client, cluster.ID)
   284  
   285  	node1, err := CreateNode(t, client, "", profile.ID)
   286  	th.AssertNoErr(t, err)
   287  	// Even tho deleting the cluster will delete the nodes but only if added into cluster successfully.
   288  	defer DeleteNode(t, client, node1.ID)
   289  
   290  	node2, err := CreateNode(t, client, "", profile.ID)
   291  	th.AssertNoErr(t, err)
   292  	// Even tho deleting the cluster will delete the nodes but only if added into cluster successfully.
   293  	defer DeleteNode(t, client, node2.ID)
   294  
   295  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   296  	th.AssertNoErr(t, err)
   297  
   298  	nodeIDs := []string{node1.ID, node2.ID}
   299  	nodeIDs = append(nodeIDs, cluster.Nodes...)
   300  
   301  	nodeNames := []string{node1.Name, node2.Name}
   302  	addNodesOpts := clusters.AddNodesOpts{
   303  		Nodes: nodeNames,
   304  	}
   305  	actionID, err := clusters.AddNodes(client, cluster.ID, addNodesOpts).Extract()
   306  	if err != nil {
   307  		t.Fatalf("Unable to add nodes to cluster: %v", err)
   308  	}
   309  
   310  	err = WaitForAction(client, actionID)
   311  	th.AssertNoErr(t, err)
   312  
   313  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   314  	th.AssertNoErr(t, err)
   315  
   316  	sort.Strings(nodeIDs)
   317  	sort.Strings(cluster.Nodes)
   318  
   319  	tools.PrintResource(t, nodeIDs)
   320  	tools.PrintResource(t, cluster.Nodes)
   321  
   322  	th.AssertDeepEquals(t, nodeIDs, cluster.Nodes)
   323  
   324  	tools.PrintResource(t, cluster)
   325  }
   326  
   327  func TestClustersRemoveNodeFromCluster(t *testing.T) {
   328  	client, err := clients.NewClusteringV1Client()
   329  	th.AssertNoErr(t, err)
   330  
   331  	profile, err := CreateProfile(t, client)
   332  	th.AssertNoErr(t, err)
   333  	defer DeleteProfile(t, client, profile.ID)
   334  
   335  	cluster, err := CreateCluster(t, client, profile.ID)
   336  	th.AssertNoErr(t, err)
   337  	defer DeleteCluster(t, client, cluster.ID)
   338  
   339  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   340  	th.AssertNoErr(t, err)
   341  	tools.PrintResource(t, cluster)
   342  
   343  	opt := clusters.RemoveNodesOpts{Nodes: cluster.Nodes}
   344  	actionID, err := clusters.RemoveNodes(client, cluster.ID, opt).Extract()
   345  	if err != nil {
   346  		t.Fatalf("Unable to remove nodes to cluster: %v", err)
   347  	}
   348  
   349  	for _, n := range cluster.Nodes {
   350  		defer DeleteNode(t, client, n)
   351  	}
   352  
   353  	err = WaitForAction(client, actionID)
   354  	th.AssertNoErr(t, err)
   355  
   356  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   357  	th.AssertNoErr(t, err)
   358  
   359  	th.AssertEquals(t, 0, len(cluster.Nodes))
   360  
   361  	tools.PrintResource(t, cluster)
   362  }
   363  
   364  func TestClustersReplaceNode(t *testing.T) {
   365  	client, err := clients.NewClusteringV1Client()
   366  	th.AssertNoErr(t, err)
   367  	client.Microversion = "1.3"
   368  
   369  	profile, err := CreateProfile(t, client)
   370  	th.AssertNoErr(t, err)
   371  	defer DeleteProfile(t, client, profile.ID)
   372  
   373  	cluster, err := CreateCluster(t, client, profile.ID)
   374  	th.AssertNoErr(t, err)
   375  	defer DeleteCluster(t, client, cluster.ID)
   376  
   377  	node1, err := CreateNode(t, client, "", profile.ID)
   378  	th.AssertNoErr(t, err)
   379  	defer DeleteNode(t, client, node1.ID)
   380  
   381  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   382  	th.AssertNoErr(t, err)
   383  	th.AssertEquals(t, true, len(cluster.Nodes) > 0)
   384  	for _, n := range cluster.Nodes {
   385  		defer DeleteNode(t, client, n)
   386  	}
   387  
   388  	nodeIDToBeReplaced := cluster.Nodes[0]
   389  	opts := clusters.ReplaceNodesOpts{Nodes: map[string]string{nodeIDToBeReplaced: node1.ID}}
   390  	actionID, err := clusters.ReplaceNodes(client, cluster.ID, opts).Extract()
   391  	th.AssertNoErr(t, err)
   392  	err = WaitForAction(client, actionID)
   393  	th.AssertNoErr(t, err)
   394  
   395  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   396  	th.AssertNoErr(t, err)
   397  
   398  	clusterNodes := strings.Join(cluster.Nodes, ",")
   399  	th.AssertEquals(t, true, strings.Contains(clusterNodes, node1.ID))
   400  	th.AssertEquals(t, false, strings.Contains(clusterNodes, nodeIDToBeReplaced))
   401  	tools.PrintResource(t, cluster)
   402  }
   403  
   404  func TestClustersCollectAttributes(t *testing.T) {
   405  	client, err := clients.NewClusteringV1Client()
   406  	th.AssertNoErr(t, err)
   407  	client.Microversion = "1.2"
   408  
   409  	profile, err := CreateProfile(t, client)
   410  	th.AssertNoErr(t, err)
   411  	defer DeleteProfile(t, client, profile.ID)
   412  
   413  	cluster, err := CreateCluster(t, client, profile.ID)
   414  	th.AssertNoErr(t, err)
   415  	defer DeleteCluster(t, client, cluster.ID)
   416  
   417  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   418  	th.AssertNoErr(t, err)
   419  	th.AssertEquals(t, true, len(cluster.Nodes) > 0)
   420  
   421  	_, err = CreateNode(t, client, cluster.ID, profile.ID)
   422  	th.AssertNoErr(t, err)
   423  
   424  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   425  	th.AssertNoErr(t, err)
   426  	th.AssertEquals(t, true, len(cluster.Nodes) > 0)
   427  
   428  	for _, n := range cluster.Nodes {
   429  		defer DeleteNode(t, client, n)
   430  	}
   431  
   432  	opts := clusters.CollectOpts{
   433  		Path: "status",
   434  	}
   435  	attrs, err := clusters.Collect(client, cluster.ID, opts).Extract()
   436  	th.AssertNoErr(t, err)
   437  	for _, attr := range attrs {
   438  		th.AssertEquals(t, attr.Value, "ACTIVE")
   439  	}
   440  
   441  	opts = clusters.CollectOpts{
   442  		Path: "data.placement.zone",
   443  	}
   444  	attrs, err = clusters.Collect(client, cluster.ID, opts).Extract()
   445  	th.AssertNoErr(t, err)
   446  	for _, attr := range attrs {
   447  		th.AssertEquals(t, attr.Value, "nova")
   448  	}
   449  
   450  }
   451  
   452  // Performs an operation on a cluster
   453  func TestClustersOps(t *testing.T) {
   454  	choices, err := clients.AcceptanceTestChoicesFromEnv()
   455  	th.AssertNoErr(t, err)
   456  
   457  	client, err := clients.NewClusteringV1Client()
   458  	th.AssertNoErr(t, err)
   459  	client.Microversion = "1.4"
   460  
   461  	profile, err := CreateProfile(t, client)
   462  	th.AssertNoErr(t, err)
   463  	defer DeleteProfile(t, client, profile.ID)
   464  
   465  	cluster, err := CreateCluster(t, client, profile.ID)
   466  	th.AssertNoErr(t, err)
   467  	defer DeleteCluster(t, client, cluster.ID)
   468  
   469  	node, err := CreateNode(t, client, cluster.ID, profile.ID)
   470  	th.AssertNoErr(t, err)
   471  	defer DeleteNode(t, client, node.ID)
   472  
   473  	ops := []clusters.OperationOpts{
   474  		// TODO: Commented out due to backend returns error, as of 2019-01-09
   475  		//{Operation: clusters.RebuildOperation},					// Error in set_admin_password in nova log
   476  		//{Operation: clusters.EvacuateOperation, Params: clusters.OperationParams{"host": cluster.ID, "force": "True"}},
   477  		//{Operation: clusters.ChangePasswordOperation, Params: clusters.OperationParams{"admin_pass": "test"}}, // QEMU guest agent is not enabled.
   478  		{Operation: clusters.RebootOperation, Params: clusters.OperationParams{"type": "SOFT"}},
   479  		{Operation: clusters.LockOperation},
   480  		{Operation: clusters.UnlockOperation},
   481  		{Operation: clusters.SuspendOperation},
   482  		{Operation: clusters.ResumeOperation},
   483  		{Operation: clusters.RescueOperation, Params: clusters.OperationParams{"image_ref": choices.ImageID}},
   484  		{Operation: clusters.PauseOperation},
   485  		{Operation: clusters.UnpauseOperation},
   486  		{Operation: clusters.StopOperation},
   487  		{Operation: clusters.StartOperation},
   488  	}
   489  
   490  	for _, op := range ops {
   491  		opName := string(op.Operation)
   492  		t.Logf("Attempting to perform '%s' on cluster: %s", opName, cluster.ID)
   493  		actionID, res := clusters.Ops(client, cluster.ID, op).Extract()
   494  		th.AssertNoErr(t, res)
   495  
   496  		err = WaitForAction(client, actionID)
   497  		th.AssertNoErr(t, err)
   498  
   499  		action, err := actions.Get(client, actionID).Extract()
   500  		th.AssertNoErr(t, err)
   501  		th.AssertEquals(t, "SUCCEEDED", action.Status)
   502  
   503  		t.Logf("Successfully performed '%s' on cluster: %s", opName, cluster.ID)
   504  	}
   505  
   506  	cluster, err = clusters.Get(client, cluster.ID).Extract()
   507  	th.AssertNoErr(t, err)
   508  	tools.PrintResource(t, cluster)
   509  }