bosh_vsphere_cpi 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,72 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../../../../spec_helper", __FILE__)
4
+
5
+ describe VSphereCloud::Resources::Datacenter do
6
+ before(:each) do
7
+ @client = mock(:client)
8
+ VSphereCloud::Config.client = @client
9
+ VSphereCloud::Config.mem_overcommit = 1.0
10
+ end
11
+
12
+ describe :initialize do
13
+ it "should create a datacenter" do
14
+ dc_mob = mock(:dc_mob)
15
+ cluster_mob = mock(:cluster_mob)
16
+
17
+ @client.should_receive(:find_by_inventory_path).with("TEST_DC").
18
+ and_return(dc_mob)
19
+ @client.should_receive(:get_managed_objects).
20
+ with(VimSdk::Vim::ClusterComputeResource,
21
+ {:root=>dc_mob, :include_name=>true}).
22
+ and_return({"foo" => cluster_mob})
23
+ @client.should_receive(:get_properties).
24
+ with([cluster_mob], VimSdk::Vim::ClusterComputeResource,
25
+ %w(name datastore resourcePool host), {:ensure_all => true}).
26
+ and_return({cluster_mob => {:foo => :bar}})
27
+
28
+ folder_config = VSphereCloud::Config::FolderConfig.new
29
+ folder_config.vm = "vms"
30
+ folder_config.template = "templates"
31
+ folder_config.shared = false
32
+ cluster_config = VSphereCloud::Config::ClusterConfig.new("foo")
33
+ datastore_config = VSphereCloud::Config::DatastoreConfig.new
34
+ datastore_config.disk_path = "bosh_disks"
35
+
36
+ dc_config = mock(:dc_config)
37
+ dc_config.stub(:name).and_return("TEST_DC")
38
+ dc_config.stub(:folders).and_return(folder_config)
39
+ dc_config.stub(:clusters).and_return({"foo" => cluster_config})
40
+ dc_config.stub(:datastores).and_return(datastore_config)
41
+
42
+ vm_folder = mock(:vm_folder)
43
+ VSphereCloud::Resources::Folder.stub!(:new).
44
+ with(an_instance_of(VSphereCloud::Resources::Datacenter),
45
+ "vms", false).
46
+ and_return(vm_folder)
47
+
48
+ template_folder = mock(:template_folder)
49
+ VSphereCloud::Resources::Folder.stub!(:new).
50
+ with(an_instance_of(VSphereCloud::Resources::Datacenter),
51
+ "templates", false).
52
+ and_return(template_folder)
53
+
54
+ cluster = mock(:cluster)
55
+ cluster.stub(:name).and_return("foo")
56
+ VSphereCloud::Resources::Cluster.stub!(:new).
57
+ with(an_instance_of(VSphereCloud::Resources::Datacenter),
58
+ cluster_config, {:foo => :bar}).
59
+ and_return(cluster)
60
+
61
+ datacenter = VSphereCloud::Resources::Datacenter.new(dc_config)
62
+ datacenter.mob.should == dc_mob
63
+ datacenter.clusters.should == {"foo" => cluster}
64
+ datacenter.vm_folder.should == vm_folder
65
+ datacenter.template_folder.should == template_folder
66
+ datacenter.config.should == dc_config
67
+ datacenter.name.should == "TEST_DC"
68
+ datacenter.disk_path.should == "bosh_disks"
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../../../../spec_helper", __FILE__)
4
+
5
+ describe VSphereCloud::Resources::Datastore do
6
+ before(:each) do
7
+ @client = mock(:client)
8
+ VSphereCloud::Config.client = @client
9
+ VSphereCloud::Config.mem_overcommit = 1.0
10
+ end
11
+
12
+ describe :initialize do
13
+ it "should create a datastore" do
14
+ ds_mob = mock(:ds_mob)
15
+ datastore = VSphereCloud::Resources::Datastore.new({
16
+ :obj => ds_mob,
17
+ "name" => "foo_lun",
18
+ "summary.capacity" => 16 * 1024 * 1024 * 1024,
19
+ "summary.freeSpace" => 8 * 1024 * 1024 * 1024
20
+ })
21
+
22
+ datastore.mob.should == ds_mob
23
+ datastore.total_space.should == 16384
24
+ datastore.free_space.should == 8192
25
+ datastore.synced_free_space.should == 8192
26
+ datastore.allocated_after_sync.should == 0
27
+ end
28
+ end
29
+
30
+ describe :allocate do
31
+ it "should allocate space" do
32
+ ds_mob = mock(:ds_mob)
33
+ datastore = VSphereCloud::Resources::Datastore.new({
34
+ :obj => ds_mob,
35
+ "name" => "foo_lun",
36
+ "summary.capacity" => 16 * 1024 * 1024 * 1024,
37
+ "summary.freeSpace" => 8 * 1024 * 1024 * 1024
38
+ })
39
+ datastore.allocate(1024)
40
+ datastore.free_space.should == 7168
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../../../../spec_helper", __FILE__)
4
+
5
+ describe VSphereCloud::Resources::Folder do
6
+ before(:each) do
7
+ @client = mock(:client)
8
+ VSphereCloud::Config.client = @client
9
+ VSphereCloud::Config.mem_overcommit = 1.0
10
+ end
11
+
12
+ describe :initialize do
13
+ it "should create a folder" do
14
+ datacenter = mock(:datacenter)
15
+ datacenter.stub(:name).and_return("TEST_DC")
16
+
17
+ folder_mob = mock(:folder_mob)
18
+
19
+ @client.should_receive(:find_by_inventory_path).with(%w(TEST_DC vm foo)).
20
+ and_return(folder_mob)
21
+
22
+ folder = VSphereCloud::Resources::Folder.new(datacenter, "foo", false)
23
+ folder.mob.should == folder_mob
24
+ folder.name.should == "foo"
25
+ end
26
+
27
+ it "should create a namespaced folder" do
28
+ datacenter = mock(:datacenter)
29
+ datacenter.stub(:name).and_return("TEST_DC")
30
+
31
+ folder_mob = mock(:folder_mob)
32
+ @client.should_receive(:find_by_inventory_path).with(%w(TEST_DC vm foo)).
33
+ and_return(folder_mob)
34
+
35
+ ns_folder_mob = mock(:ns_folder_mob)
36
+ @client.should_receive(:find_by_inventory_path).
37
+ with(["TEST_DC", "vm", %w(foo 123)]).and_return(ns_folder_mob)
38
+
39
+ folder = VSphereCloud::Resources::Folder.new(datacenter, "foo", true)
40
+ folder.mob.should == ns_folder_mob
41
+ folder.name.should == %w(foo 123)
42
+ end
43
+
44
+ it "should create a namespaced folder and create it in vSphere" do
45
+ datacenter = mock(:datacenter)
46
+ datacenter.stub(:name).and_return("TEST_DC")
47
+
48
+ folder_mob = mock(:folder_mob)
49
+ @client.should_receive(:find_by_inventory_path).with(%w(TEST_DC vm foo)).
50
+ and_return(folder_mob)
51
+ @client.should_receive(:find_by_inventory_path).
52
+ with(["TEST_DC", "vm", %w(foo 123)]).and_return(nil)
53
+
54
+ ns_folder_mob = mock(:ns_folder_mob)
55
+ folder_mob.should_receive(:create_folder).with("123").
56
+ and_return(ns_folder_mob)
57
+
58
+ folder = VSphereCloud::Resources::Folder.new(datacenter, "foo", true)
59
+ folder.mob.should == ns_folder_mob
60
+ folder.name.should == %w(foo 123)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,42 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../../../../spec_helper", __FILE__)
4
+
5
+ describe VSphereCloud::Resources::ResourcePool do
6
+ before(:each) do
7
+ @client = mock(:client)
8
+ VSphereCloud::Config.client = @client
9
+ VSphereCloud::Config.mem_overcommit = 1.0
10
+ end
11
+
12
+ describe :initialize do
13
+ it "should create a resource pool" do
14
+ cluster = mock(:cluster)
15
+ cluster_config = VSphereCloud::Config::ClusterConfig.new("foo")
16
+ cluster.stub(:config).and_return(cluster_config)
17
+ root_resource_pool_mob = mock(:root_resource_pool)
18
+
19
+ resource_pool = VSphereCloud::Resources::ResourcePool.new(
20
+ cluster, root_resource_pool_mob)
21
+ resource_pool.mob.should == root_resource_pool_mob
22
+ end
23
+
24
+ it "should create a resource pool with the specified name" do
25
+ cluster = mock(:cluster)
26
+ cluster_config = VSphereCloud::Config::ClusterConfig.new(
27
+ {"foo" => {"resource_pool" => "bar"}})
28
+ cluster.stub(:config).and_return(cluster_config)
29
+ root_resource_pool_mob = mock(:root_resource_pool)
30
+
31
+ child_resource_pool_mob = mock(:child_resource_pool_mob)
32
+ @client.should_receive(:get_managed_object).
33
+ with(VimSdk::Vim::ResourcePool,
34
+ {:root=> root_resource_pool_mob, :name=>"bar"}).
35
+ and_return(child_resource_pool_mob)
36
+
37
+ resource_pool = VSphereCloud::Resources::ResourcePool.new(
38
+ cluster, root_resource_pool_mob)
39
+ resource_pool.mob.should == child_resource_pool_mob
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,73 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../../../../spec_helper", __FILE__)
4
+
5
+ describe VSphereCloud::Resources::Scorer do
6
+
7
+ def create_datastores(sizes)
8
+ datastores = {}
9
+ sizes.each_with_index do |size, i|
10
+ datastore = mock(:datastore)
11
+ datastore.stub(:free_space).and_return(size)
12
+ datastores["ds_#{i}"] = datastore
13
+ end
14
+ datastores
15
+ end
16
+
17
+ def create_cluster(memory, ephemeral, persistent, shared)
18
+ cluster = mock(:cluster)
19
+ cluster.stub(:name).and_return("foo")
20
+ cluster.stub(:free_memory).and_return(memory)
21
+ cluster.stub(:ephemeral_datastores).
22
+ and_return(create_datastores(ephemeral))
23
+ cluster.stub(:persistent_datastores).
24
+ and_return(create_datastores(persistent))
25
+ cluster.stub(:shared_datastores).
26
+ and_return(create_datastores(shared))
27
+ cluster
28
+ end
29
+
30
+ describe :score do
31
+ it "should return 0 when memory is not available" do
32
+ cluster = create_cluster(500, [32 * 1024], [32 * 1024], [])
33
+ scorer = VSphereCloud::Resources::Scorer.new(cluster, 512, 1, [])
34
+ scorer.score.should == 0
35
+ end
36
+
37
+ it "should return 0 when ephemeral space is not available" do
38
+ cluster = create_cluster(16 * 1024, [512], [32 * 1024], [])
39
+ scorer = VSphereCloud::Resources::Scorer.new(cluster, 1, 1024, [])
40
+ scorer.score.should == 0
41
+ end
42
+
43
+ it "should return 0 when persistent space is not available" do
44
+ cluster = create_cluster(16 * 1024, [32 * 1024], [512], [])
45
+ scorer = VSphereCloud::Resources::Scorer.new(cluster, 1, 1, [1024])
46
+ scorer.score.should == 0
47
+ end
48
+
49
+ it "should calculate memory bound score" do
50
+ cluster = create_cluster(16 * 1024, [32 * 1024], [32 * 1024], [])
51
+ scorer = VSphereCloud::Resources::Scorer.new(cluster, 512, 1, [])
52
+ scorer.score.should == 31
53
+ end
54
+
55
+ it "should calculate ephemeral bound score" do
56
+ cluster = create_cluster(16 * 1024, [32 * 1024], [32 * 1024], [])
57
+ scorer = VSphereCloud::Resources::Scorer.new(cluster, 1, 512, [])
58
+ scorer.score.should == 62
59
+ end
60
+
61
+ it "should calculate persistent bound score" do
62
+ cluster = create_cluster(16 * 1024, [32 * 1024], [32 * 1024], [])
63
+ scorer = VSphereCloud::Resources::Scorer.new(cluster, 1, 1, [512])
64
+ scorer.score.should == 62
65
+ end
66
+
67
+ it "should calculate shared bound score" do
68
+ cluster = create_cluster(16 * 1024, [], [], [32 * 1024])
69
+ scorer = VSphereCloud::Resources::Scorer.new(cluster, 1, 1024, [512])
70
+ scorer.score.should == 20
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../../../../spec_helper", __FILE__)
4
+
5
+ describe VSphereCloud::Resources::Util do
6
+ describe :average_csv do
7
+ it "should compute the average integer value" do
8
+ VSphereCloud::Resources::Util.average_csv("1,2,3").should == 2
9
+ end
10
+
11
+ it "should compute the average float value" do
12
+ VSphereCloud::Resources::Util.average_csv("1.5,2.5,3.5").should == 2.5
13
+ end
14
+
15
+ it "should return 0 when there is no data" do
16
+ VSphereCloud::Resources::Util.average_csv("").should == 0
17
+ end
18
+ end
19
+
20
+ describe :weighted_random do
21
+ it "should calculate the weighted random" do
22
+ util = VSphereCloud::Resources::Util
23
+ util.should_receive(:rand).with(3).and_return(0)
24
+ util.should_receive(:rand).with(3).and_return(1)
25
+ util.should_receive(:rand).with(3).and_return(2)
26
+ util.weighted_random([[:a, 1], [:b, 2]]).should == :a
27
+ util.weighted_random([[:a, 1], [:b, 2]]).should == :b
28
+ util.weighted_random([[:a, 1], [:b, 2]]).should == :b
29
+ end
30
+
31
+ it "should return nil when there are no elements" do
32
+ VSphereCloud::Resources::Util.weighted_random([]).should be_nil
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,216 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../../../spec_helper", __FILE__)
4
+
5
+ describe VSphereCloud::Resources do
6
+
7
+ describe :datacenters do
8
+ it "should fetch the datacenters the first time" do
9
+ vcenter_config = mock(:vcenter_config)
10
+ VSphereCloud::Config.vcenter = vcenter_config
11
+ dc_config = mock(:dc_config)
12
+ dc_config.stub(:name).and_return("foo")
13
+ vcenter_config.stub(:datacenters).and_return({"foo" => dc_config})
14
+ dc = mock(:dc)
15
+ VSphereCloud::Resources::Datacenter.should_receive(:new).with(dc_config).
16
+ once.and_return(dc)
17
+
18
+ resources = VSphereCloud::Resources.new
19
+ resources.datacenters.should == {"foo" => dc}
20
+ end
21
+
22
+ it "should use cached datacenters" do
23
+ vcenter_config = mock(:vcenter_config)
24
+ VSphereCloud::Config.vcenter = vcenter_config
25
+ dc_config = mock(:dc_config)
26
+ dc_config.stub(:name).and_return("foo")
27
+ vcenter_config.stub(:datacenters).and_return({"foo" => dc_config})
28
+ dc = mock(:dc)
29
+ VSphereCloud::Resources::Datacenter.should_receive(:new).with(dc_config).
30
+ once.and_return(dc)
31
+
32
+ resources = VSphereCloud::Resources.new
33
+ resources.datacenters.should == {"foo" => dc}
34
+ resources.datacenters.should == {"foo" => dc}
35
+ end
36
+
37
+ it "should flush stale cached datacenters" do
38
+ vcenter_config = mock(:vcenter_config)
39
+ VSphereCloud::Config.vcenter = vcenter_config
40
+ dc_config = mock(:dc_config)
41
+ dc_config.stub(:name).and_return("foo")
42
+ vcenter_config.stub(:datacenters).and_return({"foo" => dc_config})
43
+ dc = mock(:dc)
44
+ VSphereCloud::Resources::Datacenter.should_receive(:new).with(dc_config).
45
+ twice.and_return(dc)
46
+
47
+ now = Time.now.to_i
48
+ Time.should_receive(:now).and_return(now, now, now + 120, now + 120)
49
+
50
+ resources = VSphereCloud::Resources.new
51
+ resources.datacenters.should == {"foo" => dc}
52
+ resources.datacenters.should == {"foo" => dc}
53
+ end
54
+ end
55
+
56
+ describe :persistent_datastore do
57
+ it "should return the persistent datastore" do
58
+ dc = mock(:dc)
59
+ cluster = mock(:cluster)
60
+ dc.stub(:clusters).and_return({"bar" => cluster})
61
+ datastore = mock(:datastore)
62
+ cluster.stub(:persistent).with("baz").and_return(datastore)
63
+ resources = VSphereCloud::Resources.new
64
+ resources.stub(:datacenters).and_return({"foo" => dc})
65
+ resources.persistent_datastore("foo", "bar", "baz").should == datastore
66
+ resources.persistent_datastore("foo", "ba", "baz").should be_nil
67
+ end
68
+ end
69
+
70
+ describe :validate_persistent_datastore do
71
+ it "should return true if the provided datastore is still persistent" do
72
+ dc = mock(:dc)
73
+ cluster = mock(:cluster)
74
+ dc.stub(:clusters).and_return({"bar" => cluster})
75
+ datastore = mock(:datastore)
76
+ cluster.stub(:persistent).with("baz").and_return(datastore)
77
+ resources = VSphereCloud::Resources.new
78
+ resources.stub(:datacenters).and_return({"foo" => dc})
79
+ resources.validate_persistent_datastore("foo", "baz").should be_true
80
+ end
81
+
82
+ it "should return false if the provided datastore is not persistent" do
83
+ dc = mock(:dc)
84
+ cluster = mock(:cluster)
85
+ dc.stub(:clusters).and_return({"bar" => cluster})
86
+ cluster.stub(:persistent).with("baz").and_return(nil)
87
+ resources = VSphereCloud::Resources.new
88
+ resources.stub(:datacenters).and_return({"foo" => dc})
89
+ resources.validate_persistent_datastore("foo", "baz").should be_false
90
+ end
91
+ end
92
+
93
+ describe :place_persistent_datastore do
94
+ it "should return the datastore when it was placed successfully" do
95
+ dc = mock(:dc)
96
+ cluster = mock(:cluster)
97
+ dc.stub(:clusters).and_return({"bar" => cluster})
98
+ datastore = mock(:datastore)
99
+ datastore.should_receive(:allocate).with(1024)
100
+ cluster.should_receive(:pick_persistent).with(1024).and_return(datastore)
101
+ resources = VSphereCloud::Resources.new
102
+ resources.stub(:datacenters).and_return({"foo" => dc})
103
+ resources.place_persistent_datastore("foo", "bar", 1024).
104
+ should == datastore
105
+ end
106
+
107
+ it "should return nil when it wasn't placed successfully" do
108
+ dc = mock(:dc)
109
+ cluster = mock(:cluster)
110
+ dc.stub(:clusters).and_return({"bar" => cluster})
111
+ cluster.should_receive(:pick_persistent).with(1024).and_return(nil)
112
+ resources = VSphereCloud::Resources.new
113
+ resources.stub(:datacenters).and_return({"foo" => dc})
114
+ resources.place_persistent_datastore("foo", "bar", 1024).
115
+ should be_nil
116
+ end
117
+ end
118
+
119
+ describe :place do
120
+ it "should allocate memory and ephemeral disk space" do
121
+ dc = mock(:dc)
122
+ cluster = mock(:cluster)
123
+ dc.stub(:clusters).and_return({"bar" => cluster})
124
+ datastore = mock(:datastore)
125
+ cluster.stub(:name).and_return("bar")
126
+ cluster.stub(:persistent).with("baz").and_return(datastore)
127
+ resources = VSphereCloud::Resources.new
128
+ resources.stub(:datacenters).and_return({"foo" => dc})
129
+
130
+ scorer = mock(:scorer)
131
+ scorer.should_receive(:score).and_return(4)
132
+ VSphereCloud::Resources::Scorer.should_receive(:new).
133
+ with(cluster, 512, 1024, []).and_return(scorer)
134
+
135
+ cluster.should_receive(:allocate).with(512)
136
+ cluster.should_receive(:pick_ephemeral).with(1024).and_return(datastore)
137
+ datastore.should_receive(:allocate).with(1024)
138
+
139
+ resources.place(512, 1024, []).should == [cluster, datastore]
140
+ end
141
+
142
+ it "should prioritize persistent locality" do
143
+ dc = mock(:dc)
144
+ cluster_a = mock(:cluster_a)
145
+ cluster_b = mock(:cluster_b)
146
+ dc.stub(:clusters).and_return({"a" => cluster_a, "b" => cluster_b})
147
+
148
+ datastore_a = mock(:datastore_a)
149
+ cluster_a.stub(:name).and_return("ds_a")
150
+ cluster_a.stub(:persistent).with("ds_a").and_return(datastore_a)
151
+ cluster_a.stub(:persistent).with("ds_b").and_return(nil)
152
+
153
+ datastore_b = mock(:datastore_b)
154
+ cluster_b.stub(:name).and_return("ds_b")
155
+ cluster_b.stub(:persistent).with("ds_a").and_return(nil)
156
+ cluster_b.stub(:persistent).with("ds_b").and_return(datastore_b)
157
+
158
+ resources = VSphereCloud::Resources.new
159
+ resources.stub(:datacenters).and_return({"foo" => dc})
160
+
161
+ scorer_b = mock(:scorer_a)
162
+ scorer_b.should_receive(:score).and_return(4)
163
+ VSphereCloud::Resources::Scorer.should_receive(:new).
164
+ with(cluster_b, 512, 1024, [2048]).and_return(scorer_b)
165
+
166
+ cluster_b.should_receive(:allocate).with(512)
167
+ cluster_b.should_receive(:pick_ephemeral).with(1024).
168
+ and_return(datastore_b)
169
+ datastore_b.should_receive(:allocate).with(1024)
170
+
171
+ resources.place(512, 1024,
172
+ [{:size => 2048, :dc_name => "foo", :ds_name => "ds_a"},
173
+ {:size => 4096, :dc_name => "foo", :ds_name => "ds_b"}]).
174
+ should == [cluster_b, datastore_b]
175
+ end
176
+
177
+ it "should ignore locality when there is no space" do
178
+ dc = mock(:dc)
179
+ cluster_a = mock(:cluster_a)
180
+ cluster_b = mock(:cluster_b)
181
+ dc.stub(:clusters).and_return({"a" => cluster_a, "b" => cluster_b})
182
+
183
+ datastore_a = mock(:datastore_a)
184
+ cluster_a.stub(:name).and_return("ds_a")
185
+ cluster_a.stub(:persistent).with("ds_a").and_return(datastore_a)
186
+ cluster_a.stub(:persistent).with("ds_b").and_return(nil)
187
+
188
+ datastore_b = mock(:datastore_b)
189
+ cluster_b.stub(:name).and_return("ds_b")
190
+ cluster_b.stub(:persistent).with("ds_a").and_return(nil)
191
+ cluster_b.stub(:persistent).with("ds_b").and_return(datastore_b)
192
+
193
+ resources = VSphereCloud::Resources.new
194
+ resources.stub(:datacenters).and_return({"foo" => dc})
195
+
196
+ scorer_a = mock(:scorer_a)
197
+ scorer_a.should_receive(:score).twice.and_return(0)
198
+ VSphereCloud::Resources::Scorer.should_receive(:new).
199
+ with(cluster_a, 512, 1024, []).twice.and_return(scorer_a)
200
+
201
+ scorer_b = mock(:scorer_b)
202
+ scorer_b.should_receive(:score).and_return(4)
203
+ VSphereCloud::Resources::Scorer.should_receive(:new).
204
+ with(cluster_b, 512, 1024, [2048]).and_return(scorer_b)
205
+
206
+ cluster_b.should_receive(:allocate).with(512)
207
+ cluster_b.should_receive(:pick_ephemeral).with(1024).
208
+ and_return(datastore_b)
209
+ datastore_b.should_receive(:allocate).with(1024)
210
+
211
+ resources.place(512, 1024,
212
+ [{:size => 2048, :dc_name => "foo", :ds_name => "ds_a"}]).
213
+ should == [cluster_b, datastore_b]
214
+ end
215
+ end
216
+ end