~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/provider/openstack/local_test.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
        "net/url"
14
14
        "os"
15
15
        "path/filepath"
 
16
        "regexp"
16
17
        "strings"
17
18
 
18
19
        jujuerrors "github.com/juju/errors"
21
22
        "github.com/juju/utils/arch"
22
23
        "github.com/juju/utils/series"
23
24
        "github.com/juju/utils/ssh"
 
25
        "github.com/juju/version"
24
26
        gc "gopkg.in/check.v1"
25
27
        "gopkg.in/goose.v1/client"
26
28
        "gopkg.in/goose.v1/identity"
36
38
        "github.com/juju/juju/environs"
37
39
        "github.com/juju/juju/environs/bootstrap"
38
40
        "github.com/juju/juju/environs/config"
39
 
        "github.com/juju/juju/environs/configstore"
40
41
        "github.com/juju/juju/environs/filestorage"
41
42
        "github.com/juju/juju/environs/imagemetadata"
42
43
        imagetesting "github.com/juju/juju/environs/imagemetadata/testing"
53
54
        "github.com/juju/juju/network"
54
55
        "github.com/juju/juju/provider/common"
55
56
        "github.com/juju/juju/provider/openstack"
 
57
        "github.com/juju/juju/status"
56
58
        "github.com/juju/juju/storage/provider/registry"
57
59
        coretesting "github.com/juju/juju/testing"
58
 
        "github.com/juju/juju/version"
 
60
        jujuversion "github.com/juju/juju/version"
59
61
)
60
62
 
61
63
type ProviderSuite struct {
179
181
 
180
182
        // Set credentials to use when bootstrapping. Must be done after
181
183
        // starting server to get the auth URL.
182
 
        args := prepareForBootstrapParams(nil, s.cred)
183
 
        s.CloudRegion = args.CloudRegion
184
 
        s.CloudEndpoint = args.CloudEndpoint
185
 
        s.Credential = args.Credentials
 
184
        s.Credential = makeCredential(s.cred)
 
185
        s.CloudEndpoint = s.cred.URL
 
186
        s.CloudRegion = s.cred.Region
186
187
 
187
188
        s.LiveTests.SetUpSuite(c)
188
189
        openstack.UseTestImageData(openstack.ImageMetadataStorage(s.Env), s.cred)
237
238
 
238
239
        // Set credentials to use when bootstrapping. Must be done after
239
240
        // starting server to get the auth URL.
240
 
        args := prepareForBootstrapParams(nil, s.cred)
241
 
        s.CloudRegion = args.CloudRegion
242
 
        s.CloudEndpoint = args.CloudEndpoint
243
 
        s.Credential = args.Credentials
 
241
        s.Credential = makeCredential(s.cred)
 
242
        s.CloudEndpoint = s.cred.URL
 
243
        s.CloudRegion = s.cred.Region
244
244
 
245
245
        cl := client.NewClient(s.cred, identity.AuthUserPass, nil)
246
246
        err := cl.Authenticate()
252
252
                "image-metadata-url": containerURL + "/juju-dist-test",
253
253
                "auth-url":           s.cred.URL,
254
254
        })
255
 
        s.PatchValue(&version.Current, coretesting.FakeVersionNumber)
 
255
        s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber)
256
256
        s.Tests.SetUpTest(c)
257
257
        // For testing, we create a storage instance to which is uploaded tools and image metadata.
258
258
        s.env = s.Prepare(c)
279
279
 
280
280
func (s *localServerSuite) TestBootstrap(c *gc.C) {
281
281
        // Tests uses Prepare, so destroy first.
282
 
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ConfigStore, s.ControllerStore)
 
282
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ControllerStore)
283
283
        c.Assert(err, jc.ErrorIsNil)
284
284
        s.Tests.TestBootstrap(c)
285
285
}
286
286
 
287
287
func (s *localServerSuite) TestStartStop(c *gc.C) {
288
288
        // Tests uses Prepare, so destroy first.
289
 
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ConfigStore, s.ControllerStore)
 
289
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ControllerStore)
290
290
        c.Assert(err, jc.ErrorIsNil)
291
291
        s.Tests.TestStartStop(c)
292
292
}
304
304
        )
305
305
        defer cleanup()
306
306
 
307
 
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ConfigStore, s.ControllerStore)
 
307
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ControllerStore)
308
308
        c.Assert(err, jc.ErrorIsNil)
309
309
 
310
310
        // Create a config that matches s.TestConfig but with use-floating-ip set to true
404
404
        )
405
405
        defer cleanup()
406
406
 
407
 
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ConfigStore, s.ControllerStore)
 
407
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ControllerStore)
408
408
        c.Assert(err, jc.ErrorIsNil)
409
409
 
410
 
        cfg, err := config.New(config.NoDefaults, s.TestConfig.Merge(coretesting.Attrs{
411
 
                "use-floating-ip": false,
412
 
        }))
413
 
        c.Assert(err, jc.ErrorIsNil)
 
410
        attrs := s.TestConfig.Merge(coretesting.Attrs{"use-floating-ip": false})
414
411
        env, err := environs.Prepare(
415
 
                envtesting.BootstrapContext(c), s.ConfigStore,
 
412
                envtesting.BootstrapContext(c),
416
413
                s.ControllerStore,
417
 
                cfg.Name(), prepareForBootstrapParams(cfg, s.cred),
 
414
                prepareParams(attrs, s.cred),
418
415
        )
419
416
        c.Assert(err, jc.ErrorIsNil)
420
417
        err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{})
427
424
func (s *localServerSuite) TestStartInstanceHardwareCharacteristics(c *gc.C) {
428
425
        // Ensure amd64 tools are available, to ensure an amd64 image.
429
426
        amd64Version := version.Binary{
430
 
                Number: version.Current,
 
427
                Number: jujuversion.Current,
431
428
                Arch:   arch.AMD64,
432
429
        }
433
430
        for _, series := range series.SupportedSeries() {
436
433
                        c, s.toolsMetadataStorage, s.env.Config().AgentStream(), s.env.Config().AgentStream(), amd64Version)
437
434
        }
438
435
 
439
 
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ConfigStore, s.ControllerStore)
 
436
        err := environs.Destroy(s.env.Config().Name(), s.env, s.ControllerStore)
440
437
        c.Assert(err, jc.ErrorIsNil)
441
438
 
442
439
        env := s.Prepare(c)
532
529
        // Openstack now has three security groups for the server, the default
533
530
        // group, one group for the entire environment, and another for the
534
531
        // new instance.
535
 
        eUUID, _ := env.Config().UUID()
 
532
        eUUID := env.Config().UUID()
536
533
        assertSecurityGroups(c, env, []string{"default", fmt.Sprintf("juju-%v", eUUID), fmt.Sprintf("juju-%v-%v", eUUID, instanceName)})
537
534
        err = env.StopInstances(inst.Id())
538
535
        c.Assert(err, jc.ErrorIsNil)
562
559
        c.Assert(err, jc.ErrorIsNil)
563
560
        instanceName := "100"
564
561
        inst, _ := testing.AssertStartInstance(c, env, instanceName)
565
 
        eUUID, _ := env.Config().UUID()
 
562
        eUUID := env.Config().UUID()
566
563
        allSecurityGroups := []string{"default", fmt.Sprintf("juju-%v", eUUID), fmt.Sprintf("juju-%v-%v", eUUID, instanceName)}
567
564
        assertSecurityGroups(c, env, allSecurityGroups)
568
565
        err = env.StopInstances(inst.Id())
578
575
        c.Assert(err, jc.ErrorIsNil)
579
576
        instanceName := "100"
580
577
        testing.AssertStartInstance(c, env, instanceName)
581
 
        eUUID, _ := env.Config().UUID()
 
578
        eUUID := env.Config().UUID()
582
579
        allSecurityGroups := []string{"default", fmt.Sprintf("juju-%v", eUUID), fmt.Sprintf("juju-%v-%v", eUUID, instanceName)}
583
580
        assertSecurityGroups(c, env, allSecurityGroups)
584
581
        err = env.Destroy()
594
591
        c.Assert(err, jc.ErrorIsNil)
595
592
        instanceName := "100"
596
593
        testing.AssertStartInstance(c, env, instanceName)
597
 
        eUUID, _ := env.Config().UUID()
 
594
        eUUID := env.Config().UUID()
598
595
        allSecurityGroups := []string{"default", fmt.Sprintf("juju-%v", eUUID), fmt.Sprintf("juju-%v-global", eUUID)}
599
596
        assertSecurityGroups(c, env, allSecurityGroups)
600
597
        err = env.Destroy()
652
649
func (s *localServerSuite) TestInstanceStatus(c *gc.C) {
653
650
        // goose's test service always returns ACTIVE state.
654
651
        inst, _ := testing.AssertStartInstance(c, s.env, "100")
655
 
        c.Assert(inst.Status(), gc.Equals, nova.StatusActive)
 
652
        c.Assert(inst.Status().Status, gc.Equals, status.StatusRunning)
656
653
        err := s.env.StopInstances(inst.Id())
657
654
        c.Assert(err, jc.ErrorIsNil)
658
655
}
762
759
 
763
760
        c.Assert(err, jc.ErrorIsNil)
764
761
        c.Assert(instances, gc.HasLen, 1)
765
 
        c.Assert(instances[0].Status(), gc.Equals, nova.StatusBuildSpawning)
 
762
        c.Assert(instances[0].Status().Message, gc.Equals, nova.StatusBuildSpawning)
766
763
}
767
764
 
768
765
func (s *localServerSuite) TestInstancesShutoffSuspended(c *gc.C) {
795
792
 
796
793
        c.Assert(err, jc.ErrorIsNil)
797
794
        c.Assert(instances, gc.HasLen, 2)
798
 
        c.Assert(instances[0].Status(), gc.Equals, nova.StatusShutoff)
799
 
        c.Assert(instances[1].Status(), gc.Equals, nova.StatusSuspended)
 
795
        c.Assert(instances[0].Status().Message, gc.Equals, nova.StatusShutoff)
 
796
        c.Assert(instances[1].Status().Message, gc.Equals, nova.StatusSuspended)
800
797
}
801
798
 
802
799
func (s *localServerSuite) TestInstancesErrorResponse(c *gc.C) {
895
892
        s.PatchValue(openstack.MakeServiceURL, func(client.AuthenticatingClient, string, []string) (string, error) {
896
893
                return "", errors.New("cannae do it captain")
897
894
        })
898
 
        env := s.Open(c)
 
895
        env := s.Open(c, s.env.Config())
899
896
        sources, err := environs.ImageMetadataSources(env)
900
897
        c.Assert(err, jc.ErrorIsNil)
901
898
        c.Assert(sources, gc.HasLen, 3)
909
906
func (s *localServerSuite) TestGetToolsMetadataSources(c *gc.C) {
910
907
        s.PatchValue(&tools.DefaultBaseURL, "")
911
908
 
912
 
        env := s.Open(c)
 
909
        env := s.Open(c, s.env.Config())
913
910
        sources, err := tools.GetMetadataSources(env)
914
911
        c.Assert(err, jc.ErrorIsNil)
915
912
        c.Assert(sources, gc.HasLen, 2)
927
924
}
928
925
 
929
926
func (s *localServerSuite) TestSupportedArchitectures(c *gc.C) {
930
 
        env := s.Open(c)
 
927
        env := s.Open(c, s.env.Config())
931
928
        a, err := env.SupportedArchitectures()
932
929
        c.Assert(err, jc.ErrorIsNil)
933
930
        c.Assert(a, jc.SameContents, []string{"amd64", "i386", "ppc64el"})
934
931
}
935
932
 
936
933
func (s *localServerSuite) TestSupportsNetworking(c *gc.C) {
937
 
        env := s.Open(c)
 
934
        env := s.Open(c, s.env.Config())
938
935
        _, ok := environs.SupportsNetworking(env)
939
936
        c.Assert(ok, jc.IsFalse)
940
937
}
941
938
 
942
939
func (s *localServerSuite) TestFindImageBadDefaultImage(c *gc.C) {
943
940
        imagetesting.PatchOfficialDataSources(&s.CleanupSuite, "")
944
 
        env := s.Open(c)
 
941
        env := s.Open(c, s.env.Config())
945
942
 
946
943
        // An error occurs if no suitable image is found.
947
944
        _, err := openstack.FindInstanceSpec(env, "saucy", "amd64", "mem=1G", nil)
949
946
}
950
947
 
951
948
func (s *localServerSuite) TestConstraintsValidator(c *gc.C) {
952
 
        env := s.Open(c)
 
949
        env := s.Open(c, s.env.Config())
953
950
        validator, err := env.ConstraintsValidator()
954
951
        c.Assert(err, jc.ErrorIsNil)
955
 
        cons := constraints.MustParse("arch=amd64 cpu-power=10")
 
952
        cons := constraints.MustParse("arch=amd64 cpu-power=10 virt-type=lxd")
956
953
        unsupported, err := validator.Validate(cons)
957
954
        c.Assert(err, jc.ErrorIsNil)
958
955
        c.Assert(unsupported, jc.SameContents, []string{"cpu-power"})
959
956
}
960
957
 
961
958
func (s *localServerSuite) TestConstraintsValidatorVocab(c *gc.C) {
962
 
        env := s.Open(c)
 
959
        env := s.Open(c, s.env.Config())
963
960
        validator, err := env.ConstraintsValidator()
964
961
        c.Assert(err, jc.ErrorIsNil)
965
962
        cons := constraints.MustParse("arch=arm64")
968
965
        cons = constraints.MustParse("instance-type=foo")
969
966
        _, err = validator.Validate(cons)
970
967
        c.Assert(err, gc.ErrorMatches, "invalid constraint value: instance-type=foo\nvalid values are:.*")
 
968
 
 
969
        cons = constraints.MustParse("virt-type=foo")
 
970
        _, err = validator.Validate(cons)
 
971
        c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta("invalid constraint value: virt-type=foo\nvalid values are: [kvm lxd]"))
971
972
}
972
973
 
973
974
func (s *localServerSuite) TestConstraintsMerge(c *gc.C) {
974
 
        env := s.Open(c)
 
975
        env := s.Open(c, s.env.Config())
975
976
        validator, err := env.ConstraintsValidator()
976
977
        c.Assert(err, jc.ErrorIsNil)
977
978
        consA := constraints.MustParse("arch=amd64 mem=1G root-disk=10G")
982
983
}
983
984
 
984
985
func (s *localServerSuite) TestFindImageInstanceConstraint(c *gc.C) {
985
 
        env := s.Open(c)
 
986
        env := s.Open(c, s.env.Config())
986
987
        imageMetadata := []*imagemetadata.ImageMetadata{{
987
988
                Id:   "image-id",
988
989
                Arch: "amd64",
996
997
        c.Assert(spec.InstanceType.Name, gc.Equals, "m1.tiny")
997
998
}
998
999
 
 
1000
func (s *localServerSuite) TestFindInstanceImageConstraintHypervisor(c *gc.C) {
 
1001
        testVirtType := "qemu"
 
1002
        env := s.Open(c, s.env.Config())
 
1003
        imageMetadata := []*imagemetadata.ImageMetadata{{
 
1004
                Id:       "image-id",
 
1005
                Arch:     "amd64",
 
1006
                VirtType: testVirtType,
 
1007
        }}
 
1008
 
 
1009
        spec, err := openstack.FindInstanceSpec(
 
1010
                env, coretesting.FakeDefaultSeries, "amd64", "virt-type="+testVirtType,
 
1011
                imageMetadata,
 
1012
        )
 
1013
        c.Assert(err, jc.ErrorIsNil)
 
1014
        c.Assert(spec.InstanceType.VirtType, gc.NotNil)
 
1015
        c.Assert(*spec.InstanceType.VirtType, gc.Equals, testVirtType)
 
1016
        c.Assert(spec.InstanceType.Name, gc.Equals, "m1.small")
 
1017
}
 
1018
 
 
1019
func (s *localServerSuite) TestFindInstanceImageWithHypervisorNoConstraint(c *gc.C) {
 
1020
        testVirtType := "qemu"
 
1021
        env := s.Open(c, s.env.Config())
 
1022
        imageMetadata := []*imagemetadata.ImageMetadata{{
 
1023
                Id:       "image-id",
 
1024
                Arch:     "amd64",
 
1025
                VirtType: testVirtType,
 
1026
        }}
 
1027
 
 
1028
        spec, err := openstack.FindInstanceSpec(
 
1029
                env, coretesting.FakeDefaultSeries, "amd64", "",
 
1030
                imageMetadata,
 
1031
        )
 
1032
        c.Assert(err, jc.ErrorIsNil)
 
1033
        c.Assert(spec.InstanceType.VirtType, gc.NotNil)
 
1034
        c.Assert(*spec.InstanceType.VirtType, gc.Equals, testVirtType)
 
1035
        c.Assert(spec.InstanceType.Name, gc.Equals, "m1.small")
 
1036
}
 
1037
 
 
1038
func (s *localServerSuite) TestFindInstanceNoConstraint(c *gc.C) {
 
1039
        env := s.Open(c, s.env.Config())
 
1040
        imageMetadata := []*imagemetadata.ImageMetadata{{
 
1041
                Id:   "image-id",
 
1042
                Arch: "amd64",
 
1043
        }}
 
1044
 
 
1045
        spec, err := openstack.FindInstanceSpec(
 
1046
                env, coretesting.FakeDefaultSeries, "amd64", "",
 
1047
                imageMetadata,
 
1048
        )
 
1049
        c.Assert(err, jc.ErrorIsNil)
 
1050
        c.Assert(spec.InstanceType.VirtType, gc.IsNil)
 
1051
        c.Assert(spec.InstanceType.Name, gc.Equals, "m1.small")
 
1052
}
 
1053
 
999
1054
func (s *localServerSuite) TestFindImageInvalidInstanceConstraint(c *gc.C) {
1000
 
        env := s.Open(c)
 
1055
        env := s.Open(c, s.env.Config())
1001
1056
        imageMetadata := []*imagemetadata.ImageMetadata{{
1002
1057
                Id:   "image-id",
1003
1058
                Arch: "amd64",
1010
1065
}
1011
1066
 
1012
1067
func (s *localServerSuite) TestPrecheckInstanceValidInstanceType(c *gc.C) {
1013
 
        env := s.Open(c)
 
1068
        env := s.Open(c, s.env.Config())
1014
1069
        cons := constraints.MustParse("instance-type=m1.small")
1015
1070
        placement := ""
1016
1071
        err := env.PrecheckInstance(coretesting.FakeDefaultSeries, cons, placement)
1018
1073
}
1019
1074
 
1020
1075
func (s *localServerSuite) TestPrecheckInstanceInvalidInstanceType(c *gc.C) {
1021
 
        env := s.Open(c)
 
1076
        env := s.Open(c, s.env.Config())
1022
1077
        cons := constraints.MustParse("instance-type=m1.large")
1023
1078
        placement := ""
1024
1079
        err := env.PrecheckInstance(coretesting.FakeDefaultSeries, cons, placement)
1051
1106
}
1052
1107
 
1053
1108
func (s *localServerSuite) TestValidateImageMetadata(c *gc.C) {
1054
 
        env := s.Open(c)
 
1109
        env := s.Open(c, s.env.Config())
1055
1110
        params, err := env.(simplestreams.MetadataValidator).MetadataLookupParams("some-region")
1056
1111
        c.Assert(err, jc.ErrorIsNil)
1057
1112
        params.Sources, err = environs.ImageMetadataSources(env)
1067
1122
                return simplestreams.NewURLDataSource("my datasource", "bar", false, simplestreams.CUSTOM_CLOUD_DATA, false), nil
1068
1123
        }
1069
1124
        environs.RegisterUserImageDataSourceFunc("my func", src)
1070
 
        env := s.Open(c)
 
1125
        env := s.Open(c, s.env.Config())
1071
1126
        sources, err := environs.ImageMetadataSources(env)
1072
1127
        c.Assert(err, jc.ErrorIsNil)
1073
1128
        var sourceIds []string
1158
1213
 
1159
1214
func (s *localHTTPSServerSuite) SetUpTest(c *gc.C) {
1160
1215
        s.BaseSuite.SetUpTest(c)
1161
 
        s.PatchValue(&version.Current, coretesting.FakeVersionNumber)
 
1216
        s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber)
1162
1217
        s.srv.UseTLS = true
1163
1218
        cred := &identity.Credentials{
1164
1219
                User:       "fred",
1171
1226
        s.cred = cred
1172
1227
        attrs := s.createConfigAttrs(c)
1173
1228
        c.Assert(attrs["auth-url"].(string)[:8], gc.Equals, "https://")
1174
 
        cfg, err := config.New(config.NoDefaults, attrs)
1175
 
        c.Assert(err, jc.ErrorIsNil)
 
1229
        var err error
1176
1230
        s.env, err = environs.Prepare(
1177
 
                envtesting.BootstrapContext(c), configstore.NewMem(),
 
1231
                envtesting.BootstrapContext(c),
1178
1232
                jujuclienttesting.NewMemStore(),
1179
 
                cfg.Name(), prepareForBootstrapParams(cfg, s.cred),
 
1233
                prepareParams(attrs, s.cred),
1180
1234
        )
1181
1235
        c.Assert(err, jc.ErrorIsNil)
1182
1236
        s.attrs = s.env.Config().AllAttrs()
1717
1771
        assertMetadata(extraKey, extraValue)
1718
1772
}
1719
1773
 
1720
 
func prepareForBootstrapParams(cfg *config.Config, cred *identity.Credentials) environs.PrepareForBootstrapParams {
1721
 
        return environs.PrepareForBootstrapParams{
1722
 
                Config: cfg,
1723
 
                Credentials: cloud.NewCredential(
1724
 
                        cloud.UserPassAuthType,
1725
 
                        map[string]string{
1726
 
                                "username":    cred.User,
1727
 
                                "password":    cred.Secrets,
1728
 
                                "tenant-name": cred.TenantName,
1729
 
                        },
1730
 
                ),
1731
 
                CloudEndpoint: cred.URL,
1732
 
                CloudRegion:   cred.Region,
 
1774
func prepareParams(attrs map[string]interface{}, cred *identity.Credentials) environs.PrepareParams {
 
1775
        return environs.PrepareParams{
 
1776
                BaseConfig:     attrs,
 
1777
                ControllerName: attrs["name"].(string),
 
1778
                Credential:     makeCredential(cred),
 
1779
                CloudName:      "openstack",
 
1780
                CloudEndpoint:  cred.URL,
 
1781
                CloudRegion:    cred.Region,
1733
1782
        }
1734
1783
}
1735
1784
 
 
1785
func makeCredential(cred *identity.Credentials) cloud.Credential {
 
1786
        return cloud.NewCredential(
 
1787
                cloud.UserPassAuthType,
 
1788
                map[string]string{
 
1789
                        "username":    cred.User,
 
1790
                        "password":    cred.Secrets,
 
1791
                        "tenant-name": cred.TenantName,
 
1792
                },
 
1793
        )
 
1794
}
 
1795
 
1736
1796
// noSwiftSuite contains tests that run against an OpenStack service double
1737
1797
// that lacks Swift.
1738
1798
type noSwiftSuite struct {
1768
1828
                "agent-version":   coretesting.FakeVersionNumber.String(),
1769
1829
                "authorized-keys": "fakekey",
1770
1830
        })
1771
 
        s.PatchValue(&version.Current, coretesting.FakeVersionNumber)
 
1831
        s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber)
1772
1832
        // Serve fake tools and image metadata using "filestorage",
1773
1833
        // rather than Swift as the rest of the tests do.
1774
1834
        storageDir := c.MkDir()
1786
1846
        openstack.UseTestImageData(imageStorage, s.cred)
1787
1847
        imagetesting.PatchOfficialDataSources(&s.CleanupSuite, storageDir)
1788
1848
 
1789
 
        cfg, err := config.New(config.NoDefaults, attrs)
1790
 
        c.Assert(err, jc.ErrorIsNil)
1791
 
        configStore := configstore.NewMem()
1792
1849
        env, err := environs.Prepare(
1793
 
                envtesting.BootstrapContext(c), configStore,
 
1850
                envtesting.BootstrapContext(c),
1794
1851
                jujuclienttesting.NewMemStore(),
1795
 
                cfg.Name(), prepareForBootstrapParams(cfg, s.cred),
 
1852
                prepareParams(attrs, s.cred),
1796
1853
        )
1797
1854
        c.Assert(err, jc.ErrorIsNil)
1798
1855
        s.env = env
1815
1872
}
1816
1873
 
1817
1874
func newNovaOnlyOpenstackService(mux *http.ServeMux, cred *identity.Credentials, auth identity.AuthMode) *novaservice.Nova {
1818
 
        var identityService identityservice.IdentityService
 
1875
        var identityService, fallbackService identityservice.IdentityService
1819
1876
        if auth == identity.AuthKeyPair {
1820
1877
                identityService = identityservice.NewKeyPair()
1821
1878
        } else {
1822
1879
                identityService = identityservice.NewUserPass()
 
1880
                fallbackService = identityservice.NewV3UserPass()
1823
1881
        }
1824
1882
        userInfo := identityService.AddUser(cred.User, cred.Secrets, cred.TenantName)
1825
1883
        if cred.TenantName == "" {
1826
1884
                panic("Openstack service double requires a tenant to be specified.")
1827
1885
        }
1828
 
        novaService := novaservice.New(cred.URL, "v2", userInfo.TenantId, cred.Region, identityService)
 
1886
        novaService := novaservice.New(cred.URL, "v2", userInfo.TenantId, cred.Region, identityService, fallbackService)
1829
1887
        identityService.SetupHTTP(mux)
1830
1888
        novaService.SetupHTTP(mux)
1831
1889
        return novaService