github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/provider/ec2/ebs_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package ec2_test
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  	"strconv"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/names"
    13  	jc "github.com/juju/testing/checkers"
    14  	awsec2 "gopkg.in/amz.v3/ec2"
    15  	"gopkg.in/amz.v3/ec2/ec2test"
    16  	gc "gopkg.in/check.v1"
    17  
    18  	"github.com/juju/juju/constraints"
    19  	"github.com/juju/juju/environs/config"
    20  	"github.com/juju/juju/environs/jujutest"
    21  	"github.com/juju/juju/instance"
    22  	"github.com/juju/juju/juju/arch"
    23  	"github.com/juju/juju/provider/ec2"
    24  	"github.com/juju/juju/storage"
    25  	"github.com/juju/juju/testing"
    26  	"github.com/juju/juju/version"
    27  )
    28  
    29  type storageSuite struct {
    30  	testing.BaseSuite
    31  }
    32  
    33  var _ = gc.Suite(&storageSuite{})
    34  
    35  func (*storageSuite) TestValidateConfigUnknownConfig(c *gc.C) {
    36  	p := ec2.EBSProvider()
    37  	cfg, err := storage.NewConfig("foo", ec2.EBS_ProviderType, map[string]interface{}{
    38  		"unknown": "config",
    39  	})
    40  	c.Assert(err, jc.ErrorIsNil)
    41  	err = p.ValidateConfig(cfg)
    42  	c.Assert(err, jc.ErrorIsNil) // unknown attrs ignored
    43  }
    44  
    45  func (s *storageSuite) TestSupports(c *gc.C) {
    46  	p := ec2.EBSProvider()
    47  	c.Assert(p.Supports(storage.StorageKindBlock), jc.IsTrue)
    48  	c.Assert(p.Supports(storage.StorageKindFilesystem), jc.IsFalse)
    49  }
    50  
    51  var _ = gc.Suite(&ebsVolumeSuite{})
    52  
    53  type ebsVolumeSuite struct {
    54  	testing.BaseSuite
    55  	jujutest.Tests
    56  	srv                localServer
    57  	restoreEC2Patching func()
    58  
    59  	instanceId string
    60  }
    61  
    62  func (s *ebsVolumeSuite) SetUpSuite(c *gc.C) {
    63  	// Upload arches that ec2 supports; add to this
    64  	// as ec2 coverage expands.
    65  	s.UploadArches = []string{arch.AMD64, arch.I386}
    66  	s.TestConfig = localConfigAttrs
    67  	s.restoreEC2Patching = patchEC2ForTesting()
    68  	s.BaseSuite.SetUpSuite(c)
    69  }
    70  
    71  func (s *ebsVolumeSuite) TearDownSuite(c *gc.C) {
    72  	s.BaseSuite.TearDownSuite(c)
    73  	s.restoreEC2Patching()
    74  }
    75  
    76  func (s *ebsVolumeSuite) SetUpTest(c *gc.C) {
    77  	s.BaseSuite.SetUpTest(c)
    78  	s.srv.startServer(c)
    79  	s.Tests.SetUpTest(c)
    80  	s.PatchValue(&version.Current, version.Binary{
    81  		Number: version.Current.Number,
    82  		Series: testing.FakeDefaultSeries,
    83  		Arch:   arch.AMD64,
    84  	})
    85  }
    86  
    87  func (s *ebsVolumeSuite) TearDownTest(c *gc.C) {
    88  	s.Tests.TearDownTest(c)
    89  	s.srv.stopServer(c)
    90  	s.BaseSuite.TearDownTest(c)
    91  }
    92  
    93  func (s *ebsVolumeSuite) volumeSource(c *gc.C, cfg *storage.Config) storage.VolumeSource {
    94  	envCfg, err := config.New(config.NoDefaults, s.TestConfig)
    95  	c.Assert(err, jc.ErrorIsNil)
    96  	p := ec2.EBSProvider()
    97  	vs, err := p.VolumeSource(envCfg, cfg)
    98  	c.Assert(err, jc.ErrorIsNil)
    99  	return vs
   100  }
   101  
   102  func (s *ebsVolumeSuite) createVolumes(vs storage.VolumeSource, instanceId string) ([]storage.Volume, error) {
   103  	if instanceId == "" {
   104  		instanceId = s.srv.ec2srv.NewInstances(1, "m1.medium", imageId, ec2test.Running, nil)[0]
   105  	}
   106  	volume0 := names.NewVolumeTag("0")
   107  	volume1 := names.NewVolumeTag("1")
   108  	volume2 := names.NewVolumeTag("2")
   109  	params := []storage.VolumeParams{{
   110  		Tag:      volume0,
   111  		Size:     10 * 1000,
   112  		Provider: ec2.EBS_ProviderType,
   113  		Attributes: map[string]interface{}{
   114  			"persistent":  true,
   115  			"volume-type": "io1",
   116  			"iops":        100,
   117  		},
   118  		Attachment: &storage.VolumeAttachmentParams{
   119  			AttachmentParams: storage.AttachmentParams{
   120  				InstanceId: instance.Id(instanceId),
   121  			},
   122  		},
   123  	}, {
   124  		Tag:      volume1,
   125  		Size:     20 * 1000,
   126  		Provider: ec2.EBS_ProviderType,
   127  		Attributes: map[string]interface{}{
   128  			"persistent": true,
   129  		},
   130  		Attachment: &storage.VolumeAttachmentParams{
   131  			AttachmentParams: storage.AttachmentParams{
   132  				InstanceId: instance.Id(instanceId),
   133  			},
   134  		},
   135  	}, {
   136  		Tag:      volume2,
   137  		Size:     30 * 1000,
   138  		Provider: ec2.EBS_ProviderType,
   139  		ResourceTags: map[string]string{
   140  			"abc": "123",
   141  		},
   142  		Attachment: &storage.VolumeAttachmentParams{
   143  			AttachmentParams: storage.AttachmentParams{
   144  				InstanceId: instance.Id(instanceId),
   145  			},
   146  		},
   147  	}}
   148  	vols, _, err := vs.CreateVolumes(params)
   149  	return vols, err
   150  }
   151  
   152  func (s *ebsVolumeSuite) assertCreateVolumes(c *gc.C, vs storage.VolumeSource, instanceId string) {
   153  	vols, err := s.createVolumes(vs, instanceId)
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	c.Assert(vols, gc.HasLen, 3)
   156  	c.Assert(vols, jc.SameContents, []storage.Volume{{
   157  		names.NewVolumeTag("0"),
   158  		storage.VolumeInfo{
   159  			Size:       10240,
   160  			VolumeId:   "vol-0",
   161  			Persistent: true,
   162  		},
   163  	}, {
   164  		names.NewVolumeTag("1"),
   165  		storage.VolumeInfo{
   166  			Size:       20480,
   167  			VolumeId:   "vol-1",
   168  			Persistent: true,
   169  		},
   170  	}, {
   171  		names.NewVolumeTag("2"),
   172  		storage.VolumeInfo{
   173  			Size:       30720,
   174  			VolumeId:   "vol-2",
   175  			Persistent: false,
   176  		},
   177  	}})
   178  	ec2Client := ec2.StorageEC2(vs)
   179  	ec2Vols, err := ec2Client.Volumes(nil, nil)
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	c.Assert(ec2Vols.Volumes, gc.HasLen, 3)
   182  	sortBySize(ec2Vols.Volumes)
   183  	c.Assert(ec2Vols.Volumes[0].Size, gc.Equals, 10)
   184  	c.Assert(ec2Vols.Volumes[1].Size, gc.Equals, 20)
   185  	c.Assert(ec2Vols.Volumes[2].Size, gc.Equals, 30)
   186  }
   187  
   188  type volumeSorter struct {
   189  	vols []awsec2.Volume
   190  	less func(i, j awsec2.Volume) bool
   191  }
   192  
   193  func sortBySize(vols []awsec2.Volume) {
   194  	sort.Sort(volumeSorter{vols, func(i, j awsec2.Volume) bool {
   195  		return i.Size < j.Size
   196  	}})
   197  }
   198  
   199  func (s volumeSorter) Len() int {
   200  	return len(s.vols)
   201  }
   202  
   203  func (s volumeSorter) Swap(i, j int) {
   204  	s.vols[i], s.vols[j] = s.vols[j], s.vols[i]
   205  }
   206  
   207  func (s volumeSorter) Less(i, j int) bool {
   208  	return s.less(s.vols[i], s.vols[j])
   209  }
   210  
   211  func (s *ebsVolumeSuite) TestCreateVolumes(c *gc.C) {
   212  	vs := s.volumeSource(c, nil)
   213  	s.assertCreateVolumes(c, vs, "")
   214  }
   215  
   216  func (s *ebsVolumeSuite) TestVolumeTags(c *gc.C) {
   217  	vs := s.volumeSource(c, nil)
   218  	vols, err := s.createVolumes(vs, "")
   219  	c.Assert(err, jc.ErrorIsNil)
   220  	c.Assert(vols, gc.HasLen, 3)
   221  	c.Assert(vols, jc.SameContents, []storage.Volume{{
   222  		names.NewVolumeTag("0"),
   223  		storage.VolumeInfo{
   224  			Size:       10240,
   225  			VolumeId:   "vol-0",
   226  			Persistent: true,
   227  		},
   228  	}, {
   229  		names.NewVolumeTag("1"),
   230  		storage.VolumeInfo{
   231  			Size:       20480,
   232  			VolumeId:   "vol-1",
   233  			Persistent: true,
   234  		},
   235  	}, {
   236  		names.NewVolumeTag("2"),
   237  		storage.VolumeInfo{
   238  			Size:       30720,
   239  			VolumeId:   "vol-2",
   240  			Persistent: false,
   241  		},
   242  	}})
   243  	ec2Client := ec2.StorageEC2(vs)
   244  	ec2Vols, err := ec2Client.Volumes(nil, nil)
   245  	c.Assert(err, jc.ErrorIsNil)
   246  	c.Assert(ec2Vols.Volumes, gc.HasLen, 3)
   247  	sortBySize(ec2Vols.Volumes)
   248  	c.Assert(ec2Vols.Volumes[0].Tags, jc.SameContents, []awsec2.Tag{
   249  		{"Name", "juju-sample-volume-0"},
   250  	})
   251  	c.Assert(ec2Vols.Volumes[1].Tags, jc.SameContents, []awsec2.Tag{
   252  		{"Name", "juju-sample-volume-1"},
   253  	})
   254  	c.Assert(ec2Vols.Volumes[2].Tags, jc.SameContents, []awsec2.Tag{
   255  		{"Name", "juju-sample-volume-2"},
   256  		{"abc", "123"},
   257  	})
   258  }
   259  
   260  func (s *ebsVolumeSuite) TestVolumeTypeAliases(c *gc.C) {
   261  	instanceIdRunning := s.srv.ec2srv.NewInstances(1, "m1.medium", imageId, ec2test.Running, nil)[0]
   262  	vs := s.volumeSource(c, nil)
   263  	ec2Client := ec2.StorageEC2(vs)
   264  	aliases := [][2]string{
   265  		{"magnetic", "standard"},
   266  		{"ssd", "gp2"},
   267  		{"provisioned-iops", "io1"},
   268  	}
   269  	for i, alias := range aliases {
   270  		params := []storage.VolumeParams{{
   271  			Tag:      names.NewVolumeTag("0"),
   272  			Size:     10 * 1000,
   273  			Provider: ec2.EBS_ProviderType,
   274  			Attributes: map[string]interface{}{
   275  				"volume-type": alias[0],
   276  			},
   277  			Attachment: &storage.VolumeAttachmentParams{
   278  				AttachmentParams: storage.AttachmentParams{
   279  					InstanceId: instance.Id(instanceIdRunning),
   280  				},
   281  			},
   282  		}}
   283  		if alias[1] == "io1" {
   284  			params[0].Attributes["iops"] = 100
   285  		}
   286  		vols, _, err := vs.CreateVolumes(params)
   287  		c.Assert(err, jc.ErrorIsNil)
   288  		c.Assert(vols, gc.HasLen, 1)
   289  		c.Assert(vols[0].VolumeId, gc.Equals, fmt.Sprintf("vol-%d", i))
   290  	}
   291  	ec2Vols, err := ec2Client.Volumes(nil, nil)
   292  	c.Assert(err, jc.ErrorIsNil)
   293  	c.Assert(ec2Vols.Volumes, gc.HasLen, len(aliases))
   294  	sort.Sort(volumeSorter{ec2Vols.Volumes, func(i, j awsec2.Volume) bool {
   295  		return i.Id < j.Id
   296  	}})
   297  	for i, alias := range aliases {
   298  		c.Assert(ec2Vols.Volumes[i].VolumeType, gc.Equals, alias[1])
   299  	}
   300  }
   301  
   302  func (s *ebsVolumeSuite) TestDeleteVolumes(c *gc.C) {
   303  	vs := s.volumeSource(c, nil)
   304  	params := s.setupAttachVolumesTest(c, vs, ec2test.Running)
   305  	err := vs.DetachVolumes(params)
   306  	c.Assert(err, jc.ErrorIsNil)
   307  	errs := vs.DestroyVolumes([]string{"vol-0"})
   308  	c.Assert(errs, jc.DeepEquals, []error{nil})
   309  
   310  	ec2Client := ec2.StorageEC2(vs)
   311  	ec2Vols, err := ec2Client.Volumes(nil, nil)
   312  	c.Assert(err, jc.ErrorIsNil)
   313  	c.Assert(ec2Vols.Volumes, gc.HasLen, 2)
   314  	sortBySize(ec2Vols.Volumes)
   315  	c.Assert(ec2Vols.Volumes[0].Size, gc.Equals, 20)
   316  }
   317  
   318  func (s *ebsVolumeSuite) TestVolumes(c *gc.C) {
   319  	vs := s.volumeSource(c, nil)
   320  	s.assertCreateVolumes(c, vs, "")
   321  
   322  	vols, err := vs.DescribeVolumes([]string{"vol-0", "vol-1"})
   323  	c.Assert(err, jc.ErrorIsNil)
   324  	c.Assert(vols, gc.HasLen, 2)
   325  	c.Assert(vols, jc.SameContents, []storage.VolumeInfo{{
   326  		Size:     10240,
   327  		VolumeId: "vol-0",
   328  	}, {
   329  		Size:     20480,
   330  		VolumeId: "vol-1",
   331  	}})
   332  }
   333  
   334  func (s *ebsVolumeSuite) TestCreateVolumesErrors(c *gc.C) {
   335  	vs := s.volumeSource(c, nil)
   336  	volume0 := names.NewVolumeTag("0")
   337  
   338  	instanceIdPending := s.srv.ec2srv.NewInstances(1, "m1.medium", imageId, ec2test.Pending, nil)[0]
   339  	instanceIdRunning := s.srv.ec2srv.NewInstances(1, "m1.medium", imageId, ec2test.Running, nil)[0]
   340  	attachmentParams := storage.VolumeAttachmentParams{
   341  		AttachmentParams: storage.AttachmentParams{
   342  			InstanceId: instance.Id(instanceIdRunning),
   343  		},
   344  	}
   345  
   346  	for _, test := range []struct {
   347  		params storage.VolumeParams
   348  		err    string
   349  	}{{
   350  		params: storage.VolumeParams{
   351  			Provider: ec2.EBS_ProviderType,
   352  			Attachment: &storage.VolumeAttachmentParams{
   353  				AttachmentParams: storage.AttachmentParams{
   354  					InstanceId: "woat",
   355  				},
   356  			},
   357  		},
   358  		err: `querying instance details: instance "woat" not found \(InvalidInstanceID.NotFound\)`,
   359  	}, {
   360  		params: storage.VolumeParams{
   361  			Provider: ec2.EBS_ProviderType,
   362  			Attachment: &storage.VolumeAttachmentParams{
   363  				AttachmentParams: storage.AttachmentParams{
   364  					InstanceId: instance.Id(instanceIdPending),
   365  				},
   366  			},
   367  		},
   368  		err: "querying instance details: volumes can only be attached to running instances, these instances are not running: i-3",
   369  	}, {
   370  		params: storage.VolumeParams{
   371  			Size:       100000000,
   372  			Provider:   ec2.EBS_ProviderType,
   373  			Attributes: map[string]interface{}{},
   374  			Attachment: &attachmentParams,
   375  		},
   376  		err: "97657 GiB exceeds the maximum of 1024 GiB",
   377  	}, {
   378  		params: storage.VolumeParams{
   379  			Tag:      volume0,
   380  			Size:     1000,
   381  			Provider: ec2.EBS_ProviderType,
   382  			Attributes: map[string]interface{}{
   383  				"volume-type": "io1",
   384  				"iops":        "1234",
   385  			},
   386  			Attachment: &attachmentParams,
   387  		},
   388  		err: "volume size is 1 GiB, must be at least 10 GiB for provisioned IOPS",
   389  	}, {
   390  		params: storage.VolumeParams{
   391  			Tag:      volume0,
   392  			Size:     10000,
   393  			Provider: ec2.EBS_ProviderType,
   394  			Attributes: map[string]interface{}{
   395  				"volume-type": "io1",
   396  				"iops":        "1234",
   397  			},
   398  			Attachment: &attachmentParams,
   399  		},
   400  		err: "volume size is 10 GiB, must be at least 41 GiB to support 1234 IOPS",
   401  	}, {
   402  		params: storage.VolumeParams{
   403  			Tag:      volume0,
   404  			Size:     10000,
   405  			Provider: ec2.EBS_ProviderType,
   406  			Attributes: map[string]interface{}{
   407  				"volume-type": "standard",
   408  				"iops":        "1234",
   409  			},
   410  			Attachment: &attachmentParams,
   411  		},
   412  		err: `IOPS specified, but volume type is "standard"`,
   413  	}, {
   414  		params: storage.VolumeParams{
   415  			Tag:      volume0,
   416  			Size:     10000,
   417  			Provider: ec2.EBS_ProviderType,
   418  			Attributes: map[string]interface{}{
   419  				"volume-type": "what",
   420  			},
   421  			Attachment: &attachmentParams,
   422  		},
   423  		err: "validating EBS storage config: volume-type: unexpected value \"what\"",
   424  	}} {
   425  		_, _, err := vs.CreateVolumes([]storage.VolumeParams{test.params})
   426  		c.Check(err, gc.ErrorMatches, test.err)
   427  	}
   428  }
   429  
   430  var imageId = "ami-ccf405a5" // Ubuntu Maverick, i386, EBS store
   431  
   432  func (s *ebsVolumeSuite) setupAttachVolumesTest(
   433  	c *gc.C, vs storage.VolumeSource, state awsec2.InstanceState,
   434  ) []storage.VolumeAttachmentParams {
   435  
   436  	instanceId := s.srv.ec2srv.NewInstances(1, "m1.medium", imageId, state, nil)[0]
   437  	s.assertCreateVolumes(c, vs, instanceId)
   438  
   439  	return []storage.VolumeAttachmentParams{{
   440  		Volume:   names.NewVolumeTag("0"),
   441  		VolumeId: "vol-0",
   442  		AttachmentParams: storage.AttachmentParams{
   443  			Machine:    names.NewMachineTag("1"),
   444  			InstanceId: instance.Id(instanceId),
   445  		},
   446  	}}
   447  }
   448  
   449  func (s *ebsVolumeSuite) TestAttachVolumesNotRunning(c *gc.C) {
   450  	vs := s.volumeSource(c, nil)
   451  	instanceId := s.srv.ec2srv.NewInstances(1, "m1.medium", imageId, ec2test.Pending, nil)[0]
   452  	_, err := s.createVolumes(vs, instanceId)
   453  	c.Assert(errors.Cause(err), gc.ErrorMatches, ".* these instances are not running: i-3")
   454  }
   455  
   456  func (s *ebsVolumeSuite) TestAttachVolumes(c *gc.C) {
   457  	vs := s.volumeSource(c, nil)
   458  	params := s.setupAttachVolumesTest(c, vs, ec2test.Running)
   459  	result, err := vs.AttachVolumes(params)
   460  	c.Assert(err, jc.ErrorIsNil)
   461  	c.Assert(result, gc.HasLen, 1)
   462  	c.Assert(result[0], gc.Equals, storage.VolumeAttachment{
   463  		names.NewVolumeTag("0"),
   464  		names.NewMachineTag("1"),
   465  		storage.VolumeAttachmentInfo{
   466  			DeviceName: "xvdf",
   467  			ReadOnly:   false,
   468  		},
   469  	})
   470  
   471  	ec2Client := ec2.StorageEC2(vs)
   472  	ec2Vols, err := ec2Client.Volumes(nil, nil)
   473  	c.Assert(err, jc.ErrorIsNil)
   474  	c.Assert(ec2Vols.Volumes, gc.HasLen, 3)
   475  	sortBySize(ec2Vols.Volumes)
   476  	c.Assert(ec2Vols.Volumes[0].Attachments, jc.DeepEquals, []awsec2.VolumeAttachment{{
   477  		VolumeId:            "vol-0",
   478  		InstanceId:          "i-3",
   479  		Device:              "/dev/sdf",
   480  		Status:              "attached",
   481  		DeleteOnTermination: true,
   482  	}})
   483  
   484  	// Test idempotency.
   485  	result, err = vs.AttachVolumes(params)
   486  	c.Assert(err, jc.ErrorIsNil)
   487  	c.Assert(result, gc.HasLen, 1)
   488  	c.Assert(result[0], gc.Equals, storage.VolumeAttachment{
   489  		names.NewVolumeTag("0"),
   490  		names.NewMachineTag("1"),
   491  		storage.VolumeAttachmentInfo{
   492  			DeviceName: "xvdf",
   493  			ReadOnly:   false,
   494  		},
   495  	})
   496  }
   497  
   498  func (s *ebsVolumeSuite) TestDetachVolumes(c *gc.C) {
   499  	vs := s.volumeSource(c, nil)
   500  	params := s.setupAttachVolumesTest(c, vs, ec2test.Running)
   501  	_, err := vs.AttachVolumes(params)
   502  	c.Assert(err, jc.ErrorIsNil)
   503  	err = vs.DetachVolumes(params)
   504  	c.Assert(err, jc.ErrorIsNil)
   505  
   506  	ec2Client := ec2.StorageEC2(vs)
   507  	ec2Vols, err := ec2Client.Volumes(nil, nil)
   508  	c.Assert(err, jc.ErrorIsNil)
   509  	c.Assert(ec2Vols.Volumes, gc.HasLen, 3)
   510  	sortBySize(ec2Vols.Volumes)
   511  	c.Assert(ec2Vols.Volumes[0].Attachments, gc.HasLen, 0)
   512  
   513  	// Test idempotent
   514  	err = vs.DetachVolumes(params)
   515  	c.Assert(err, jc.ErrorIsNil)
   516  }
   517  
   518  type blockDeviceMappingSuite struct {
   519  	testing.BaseSuite
   520  }
   521  
   522  var _ = gc.Suite(&blockDeviceMappingSuite{})
   523  
   524  func (*blockDeviceMappingSuite) TestBlockDeviceNamer(c *gc.C) {
   525  	var nextName func() (string, string, error)
   526  	expect := func(expectRequest, expectActual string) {
   527  		request, actual, err := nextName()
   528  		c.Assert(err, jc.ErrorIsNil)
   529  		c.Assert(request, gc.Equals, expectRequest)
   530  		c.Assert(actual, gc.Equals, expectActual)
   531  	}
   532  	expectN := func(expectRequest, expectActual string) {
   533  		for i := 1; i <= 6; i++ {
   534  			request, actual, err := nextName()
   535  			c.Assert(err, jc.ErrorIsNil)
   536  			c.Assert(request, gc.Equals, expectRequest+strconv.Itoa(i))
   537  			c.Assert(actual, gc.Equals, expectActual+strconv.Itoa(i))
   538  		}
   539  	}
   540  	expectErr := func(expectErr string) {
   541  		_, _, err := nextName()
   542  		c.Assert(err, gc.ErrorMatches, expectErr)
   543  	}
   544  
   545  	// First without numbers.
   546  	nextName = ec2.BlockDeviceNamer(awsec2.Instance{
   547  		VirtType: "hvm",
   548  	})
   549  	expect("/dev/sdf", "xvdf")
   550  	expect("/dev/sdg", "xvdg")
   551  	expect("/dev/sdh", "xvdh")
   552  	expect("/dev/sdi", "xvdi")
   553  	expect("/dev/sdj", "xvdj")
   554  	expect("/dev/sdk", "xvdk")
   555  	expect("/dev/sdl", "xvdl")
   556  	expect("/dev/sdm", "xvdm")
   557  	expect("/dev/sdn", "xvdn")
   558  	expect("/dev/sdo", "xvdo")
   559  	expect("/dev/sdp", "xvdp")
   560  	expectErr("too many EBS volumes to attach")
   561  
   562  	// Now with numbers.
   563  	nextName = ec2.BlockDeviceNamer(awsec2.Instance{
   564  		VirtType: "paravirtual",
   565  	})
   566  	expect("/dev/sdf1", "xvdf1")
   567  	expect("/dev/sdf2", "xvdf2")
   568  	expect("/dev/sdf3", "xvdf3")
   569  	expect("/dev/sdf4", "xvdf4")
   570  	expect("/dev/sdf5", "xvdf5")
   571  	expect("/dev/sdf6", "xvdf6")
   572  	expectN("/dev/sdg", "xvdg")
   573  	expectN("/dev/sdh", "xvdh")
   574  	expectN("/dev/sdi", "xvdi")
   575  	expectN("/dev/sdj", "xvdj")
   576  	expectN("/dev/sdk", "xvdk")
   577  	expectN("/dev/sdl", "xvdl")
   578  	expectN("/dev/sdm", "xvdm")
   579  	expectN("/dev/sdn", "xvdn")
   580  	expectN("/dev/sdo", "xvdo")
   581  	expectN("/dev/sdp", "xvdp")
   582  	expectErr("too many EBS volumes to attach")
   583  }
   584  
   585  func (*blockDeviceMappingSuite) TestGetBlockDeviceMappings(c *gc.C) {
   586  	mapping, err := ec2.GetBlockDeviceMappings(constraints.Value{})
   587  	c.Assert(err, jc.ErrorIsNil)
   588  	c.Assert(mapping, gc.DeepEquals, []awsec2.BlockDeviceMapping{{
   589  		VolumeSize: 8,
   590  		DeviceName: "/dev/sda1",
   591  	}, {
   592  		VirtualName: "ephemeral0",
   593  		DeviceName:  "/dev/sdb",
   594  	}, {
   595  		VirtualName: "ephemeral1",
   596  		DeviceName:  "/dev/sdc",
   597  	}, {
   598  		VirtualName: "ephemeral2",
   599  		DeviceName:  "/dev/sdd",
   600  	}, {
   601  		VirtualName: "ephemeral3",
   602  		DeviceName:  "/dev/sde",
   603  	}})
   604  }