github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/provider/openstack/live_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package openstack_test 5 6 import ( 7 "crypto/rand" 8 "fmt" 9 "io" 10 "sort" 11 12 gc "launchpad.net/gocheck" 13 "launchpad.net/goose/client" 14 "launchpad.net/goose/identity" 15 "launchpad.net/goose/nova" 16 17 "launchpad.net/juju-core/constraints" 18 "launchpad.net/juju-core/environs" 19 "launchpad.net/juju-core/environs/bootstrap" 20 "launchpad.net/juju-core/environs/config" 21 "launchpad.net/juju-core/environs/jujutest" 22 "launchpad.net/juju-core/environs/storage" 23 envtesting "launchpad.net/juju-core/environs/testing" 24 jujutesting "launchpad.net/juju-core/juju/testing" 25 "launchpad.net/juju-core/provider/openstack" 26 coretesting "launchpad.net/juju-core/testing" 27 "launchpad.net/juju-core/testing/testbase" 28 ) 29 30 // generate a different bucket name for each config instance, so that 31 // we are not polluted by previous test state. 32 func randomName() string { 33 buf := make([]byte, 8) 34 _, err := io.ReadFull(rand.Reader, buf) 35 if err != nil { 36 panic(fmt.Sprintf("error from crypto rand: %v", err)) 37 } 38 return fmt.Sprintf("%x", buf) 39 } 40 41 func makeTestConfig(cred *identity.Credentials) map[string]interface{} { 42 // The following attributes hold the environment configuration 43 // for running the OpenStack integration tests. 44 // 45 // This is missing keys for security reasons; set the following 46 // environment variables to make the OpenStack testing work: 47 // access-key: $OS_USERNAME 48 // secret-key: $OS_PASSWORD 49 // 50 attrs := coretesting.FakeConfig().Merge(coretesting.Attrs{ 51 "name": "sample-" + randomName(), 52 "type": "openstack", 53 "auth-mode": "userpass", 54 "control-bucket": "juju-test-" + randomName(), 55 "username": cred.User, 56 "password": cred.Secrets, 57 "region": cred.Region, 58 "auth-url": cred.URL, 59 "tenant-name": cred.TenantName, 60 }) 61 return attrs 62 } 63 64 // Register tests to run against a real Openstack instance. 65 func registerLiveTests(cred *identity.Credentials) { 66 config := makeTestConfig(cred) 67 gc.Suite(&LiveTests{ 68 cred: cred, 69 LiveTests: jujutest.LiveTests{ 70 TestConfig: config, 71 Attempt: *openstack.ShortAttempt, 72 CanOpenState: true, 73 HasProvisioner: true, 74 }, 75 }) 76 } 77 78 // LiveTests contains tests that can be run against OpenStack deployments. 79 // The deployment can be a real live instance or service doubles. 80 // Each test runs using the same connection. 81 type LiveTests struct { 82 testbase.LoggingSuite 83 jujutest.LiveTests 84 cred *identity.Credentials 85 metadataStorage storage.Storage 86 } 87 88 func (t *LiveTests) SetUpSuite(c *gc.C) { 89 t.LoggingSuite.SetUpSuite(c) 90 // Update some Config items now that we have services running. 91 // This is setting the simplestreams urls and auth-url because that 92 // information is set during startup of the localLiveSuite 93 cl := client.NewClient(t.cred, identity.AuthUserPass, nil) 94 err := cl.Authenticate() 95 c.Assert(err, gc.IsNil) 96 containerURL, err := cl.MakeServiceURL("object-store", nil) 97 c.Assert(err, gc.IsNil) 98 t.TestConfig = t.TestConfig.Merge(coretesting.Attrs{ 99 "tools-metadata-url": containerURL + "/juju-dist-test/tools", 100 "image-metadata-url": containerURL + "/juju-dist-test", 101 "auth-url": t.cred.URL, 102 }) 103 t.LiveTests.SetUpSuite(c) 104 // For testing, we create a storage instance to which is uploaded tools and image metadata. 105 t.PrepareOnce(c) 106 t.metadataStorage = openstack.MetadataStorage(t.Env) 107 // Put some fake tools metadata in place so that tests that are simply 108 // starting instances without any need to check if those instances 109 // are running can find the metadata. 110 envtesting.UploadFakeTools(c, t.metadataStorage) 111 } 112 113 func (t *LiveTests) TearDownSuite(c *gc.C) { 114 if t.Env == nil { 115 // This can happen if SetUpSuite fails. 116 return 117 } 118 if t.metadataStorage != nil { 119 envtesting.RemoveFakeToolsMetadata(c, t.metadataStorage) 120 } 121 t.LiveTests.TearDownSuite(c) 122 t.LoggingSuite.TearDownSuite(c) 123 } 124 125 func (t *LiveTests) SetUpTest(c *gc.C) { 126 t.LoggingSuite.SetUpTest(c) 127 t.LiveTests.SetUpTest(c) 128 } 129 130 func (t *LiveTests) TearDownTest(c *gc.C) { 131 t.LiveTests.TearDownTest(c) 132 t.LoggingSuite.TearDownTest(c) 133 } 134 135 func (t *LiveTests) TestEnsureGroupSetsGroupId(c *gc.C) { 136 t.PrepareOnce(c) 137 rules := []nova.RuleInfo{ 138 { // First group explicitly asks for all services 139 IPProtocol: "tcp", 140 FromPort: 22, 141 ToPort: 22, 142 Cidr: "0.0.0.0/0", 143 }, 144 { // Second group should only allow access from within the group 145 IPProtocol: "tcp", 146 FromPort: 1, 147 ToPort: 65535, 148 }, 149 } 150 groupName := "juju-test-group-" + randomName() 151 // Make sure things are clean before we start, and clean when we are done 152 cleanup := func() { 153 c.Check(openstack.DiscardSecurityGroup(t.Env, groupName), gc.IsNil) 154 } 155 cleanup() 156 defer cleanup() 157 group, err := openstack.EnsureGroup(t.Env, groupName, rules) 158 c.Assert(err, gc.IsNil) 159 c.Check(group.Rules, gc.HasLen, 2) 160 c.Check(*group.Rules[0].IPProtocol, gc.Equals, "tcp") 161 c.Check(*group.Rules[0].FromPort, gc.Equals, 22) 162 c.Check(*group.Rules[0].ToPort, gc.Equals, 22) 163 c.Check(group.Rules[0].IPRange["cidr"], gc.Equals, "0.0.0.0/0") 164 c.Check(group.Rules[0].Group.Name, gc.Equals, "") 165 c.Check(group.Rules[0].Group.TenantId, gc.Equals, "") 166 c.Check(*group.Rules[1].IPProtocol, gc.Equals, "tcp") 167 c.Check(*group.Rules[1].FromPort, gc.Equals, 1) 168 c.Check(*group.Rules[1].ToPort, gc.Equals, 65535) 169 c.Check(group.Rules[1].IPRange, gc.HasLen, 0) 170 c.Check(group.Rules[1].Group.Name, gc.Equals, groupName) 171 c.Check(group.Rules[1].Group.TenantId, gc.Equals, group.TenantId) 172 } 173 174 func (t *LiveTests) TestSetupGlobalGroupExposesCorrectPorts(c *gc.C) { 175 t.PrepareOnce(c) 176 groupName := "juju-test-group-" + randomName() 177 // Make sure things are clean before we start, and will be clean when we finish 178 cleanup := func() { 179 c.Check(openstack.DiscardSecurityGroup(t.Env, groupName), gc.IsNil) 180 } 181 cleanup() 182 defer cleanup() 183 statePort := 12345 // Default 37017 184 apiPort := 34567 // Default 17070 185 group, err := openstack.SetUpGlobalGroup(t.Env, groupName, statePort, apiPort) 186 c.Assert(err, gc.IsNil) 187 c.Assert(err, gc.IsNil) 188 // We default to exporting 22, statePort, apiPort, and icmp/udp/tcp on 189 // all ports to other machines inside the same group 190 // TODO(jam): 2013-09-18 http://pad.lv/1227142 191 // We shouldn't be exposing the API and State ports on all the machines 192 // that *aren't* hosting the state server. (And once we finish 193 // client-via-API we can disable the State port as well.) 194 stringRules := make([]string, 0, len(group.Rules)) 195 for _, rule := range group.Rules { 196 ruleStr := fmt.Sprintf("%s %d %d %q %q", 197 *rule.IPProtocol, 198 *rule.FromPort, 199 *rule.ToPort, 200 rule.IPRange["cidr"], 201 rule.Group.Name, 202 ) 203 stringRules = append(stringRules, ruleStr) 204 } 205 // We don't care about the ordering, so we sort the result, and compare it. 206 expectedRules := []string{ 207 `tcp 22 22 "0.0.0.0/0" ""`, 208 fmt.Sprintf(`tcp %d %d "0.0.0.0/0" ""`, statePort, statePort), 209 fmt.Sprintf(`tcp %d %d "0.0.0.0/0" ""`, apiPort, apiPort), 210 fmt.Sprintf(`tcp 1 65535 "" "%s"`, groupName), 211 fmt.Sprintf(`udp 1 65535 "" "%s"`, groupName), 212 fmt.Sprintf(`icmp -1 -1 "" "%s"`, groupName), 213 } 214 sort.Strings(stringRules) 215 sort.Strings(expectedRules) 216 c.Check(stringRules, gc.DeepEquals, expectedRules) 217 } 218 219 func (s *LiveTests) assertStartInstanceDefaultSecurityGroup(c *gc.C, useDefault bool) { 220 attrs := s.TestConfig.Merge(coretesting.Attrs{ 221 "name": "sample-" + randomName(), 222 "control-bucket": "juju-test-" + randomName(), 223 "use-default-secgroup": useDefault, 224 }) 225 cfg, err := config.New(config.NoDefaults, attrs) 226 c.Assert(err, gc.IsNil) 227 // Set up a test environment. 228 env, err := environs.New(cfg) 229 c.Assert(err, gc.IsNil) 230 c.Assert(env, gc.NotNil) 231 defer env.Destroy() 232 // Bootstrap and start an instance. 233 err = bootstrap.Bootstrap(coretesting.Context(c), env, constraints.Value{}) 234 c.Assert(err, gc.IsNil) 235 inst, _ := jujutesting.AssertStartInstance(c, env, "100") 236 // Check whether the instance has the default security group assigned. 237 novaClient := openstack.GetNovaClient(env) 238 groups, err := novaClient.GetServerSecurityGroups(string(inst.Id())) 239 c.Assert(err, gc.IsNil) 240 defaultGroupFound := false 241 for _, group := range groups { 242 if group.Name == "default" { 243 defaultGroupFound = true 244 break 245 } 246 } 247 c.Assert(defaultGroupFound, gc.Equals, useDefault) 248 } 249 250 func (s *LiveTests) TestStartInstanceWithDefaultSecurityGroup(c *gc.C) { 251 s.assertStartInstanceDefaultSecurityGroup(c, true) 252 } 253 254 func (s *LiveTests) TestStartInstanceWithoutDefaultSecurityGroup(c *gc.C) { 255 s.assertStartInstanceDefaultSecurityGroup(c, false) 256 }