@@ -4563,21 +4563,144 @@ def test_create_instance_name_all_blank_spaces(self):
4563
4563
self .assertRaises (exception .ValidationError ,
4564
4564
self .controller .create , req , body = body )
4565
4565
4566
- def test_create_az_with_leading_trailing_spaces (self ):
4566
+ def test_create_instance_az_with_leading_trailing_spaces (self ):
4567
4567
self .body ['server' ]['availability_zone' ] = ' zone1 '
4568
4568
self .req .body = jsonutils .dump_as_bytes (self .body )
4569
4569
self .assertRaises (exception .ValidationError ,
4570
4570
self .controller .create , self .req , body = self .body )
4571
4571
4572
- def test_create_az_with_leading_trailing_spaces_in_compat_mode (
4573
- self ):
4572
+ def test_create_instance_az_with_leading_trailing_spaces_compat_mode (self ):
4574
4573
self .body ['server' ]['name' ] = ' abc def '
4575
- self .body ['server' ]['availability_zones ' ] = ' zone1 '
4574
+ self .body ['server' ]['availability_zone ' ] = ' zone1 '
4576
4575
self .req .body = jsonutils .dump_as_bytes (self .body )
4577
4576
self .req .set_legacy_v2 ()
4578
- with mock .patch .object (availability_zones , 'get_availability_zones' ,
4579
- return_value = [' zone1 ' ]):
4577
+ with mock .patch .object (
4578
+ availability_zones , 'get_availability_zones' ,
4579
+ return_value = [' zone1 ' ],
4580
+ ) as mock_get_azs :
4580
4581
self .controller .create (self .req , body = self .body )
4582
+ mock_get_azs .assert_called_once ()
4583
+
4584
+ def test_create_instance_invalid_az (self ):
4585
+ self .body ['server' ]['availability_zone' ] = 'zone1'
4586
+ self .req .body = jsonutils .dump_as_bytes (self .body )
4587
+ with mock .patch .object (
4588
+ availability_zones , 'get_availability_zones' ,
4589
+ return_value = ['zone2' ],
4590
+ ) as mock_get_azs :
4591
+ self .assertRaises (
4592
+ webob .exc .HTTPBadRequest ,
4593
+ self .controller .create ,
4594
+ self .req , body = self .body )
4595
+ mock_get_azs .assert_called_once ()
4596
+
4597
+ @mock .patch .object (objects .AggregateList , 'get_by_host' )
4598
+ @mock .patch .object (servers , 'LOG' )
4599
+ def test_create_instance_az_host (self , mock_log , mock_get_host_aggs ):
4600
+ """Ensure we handle az:host format for 'availability_zone'."""
4601
+ mock_get_host_aggs .return_value = objects .AggregateList (
4602
+ objects = [
4603
+ objects .Aggregate (metadata = {'availability_zone' : 'zone1' }),
4604
+ ],
4605
+ )
4606
+
4607
+ self .body ['server' ]['availability_zone' ] = 'zone1:host1'
4608
+ self .req .body = jsonutils .dump_as_bytes (self .body )
4609
+
4610
+ self .controller .create (self .req , body = self .body )
4611
+
4612
+ mock_get_host_aggs .assert_called_once ()
4613
+ mock_log .warning .assert_not_called ()
4614
+
4615
+ @mock .patch .object (objects .AggregateList , 'get_by_host' )
4616
+ @mock .patch .object (servers , 'LOG' )
4617
+ def test_create_instance_az_host_mismatch_without_aggs (
4618
+ self , mock_log , mock_get_host_aggs ,
4619
+ ):
4620
+ """User requests an AZ but the host doesn't have one"""
4621
+ mock_get_host_aggs .return_value = objects .AggregateList (objects = [])
4622
+
4623
+ self .body ['server' ]['availability_zone' ] = 'zone1:host1'
4624
+ self .req .body = jsonutils .dump_as_bytes (self .body )
4625
+
4626
+ self .controller .create (self .req , body = self .body )
4627
+
4628
+ mock_get_host_aggs .assert_called_once ()
4629
+ # we should see a log since the host doesn't belong to the requested AZ
4630
+ self .assertIn ('bug #1934770' , mock_log .warning .call_args [0 ][0 ])
4631
+
4632
+ @mock .patch .object (objects .AggregateList , 'get_by_host' )
4633
+ @mock .patch .object (servers , 'LOG' )
4634
+ def test_create_instance_az_host_mismatch_without_aggs_in_default_az (
4635
+ self , mock_log , mock_get_host_aggs ,
4636
+ ):
4637
+ """User requests the default AZ and host isn't in any explicit AZ"""
4638
+ self .flags (default_availability_zone = 'zone1' )
4639
+ mock_get_host_aggs .return_value = objects .AggregateList (objects = [])
4640
+
4641
+ self .body ['server' ]['availability_zone' ] = 'zone1:host1'
4642
+ self .req .body = jsonutils .dump_as_bytes (self .body )
4643
+
4644
+ self .controller .create (self .req , body = self .body )
4645
+
4646
+ mock_get_host_aggs .assert_called_once ()
4647
+ # we shouldn't see a log since the host is not in any aggregate and
4648
+ # therefore is in the default AZ
4649
+ mock_log .warning .assert_not_called ()
4650
+
4651
+ @mock .patch .object (objects .AggregateList , 'get_by_host' )
4652
+ @mock .patch .object (servers , 'LOG' )
4653
+ def test_create_instance_az_host_mismatch_with_aggs (
4654
+ self , mock_log , mock_get_host_aggs ,
4655
+ ):
4656
+ """User requests an AZ but the host has a different one."""
4657
+ mock_get_host_aggs .return_value = objects .AggregateList (
4658
+ objects = [
4659
+ objects .Aggregate (metadata = {'availability_zone' : 'zone2' }),
4660
+ ],
4661
+ )
4662
+
4663
+ self .body ['server' ]['availability_zone' ] = 'zone1:host1'
4664
+ self .req .body = jsonutils .dump_as_bytes (self .body )
4665
+
4666
+ self .controller .create (self .req , body = self .body )
4667
+
4668
+ mock_get_host_aggs .assert_called_once ()
4669
+ # we should see a log since the host belongs to a different AZ
4670
+ self .assertIn ('bug #1934770' , mock_log .warning .call_args [0 ][0 ])
4671
+
4672
+ @mock .patch .object (objects .AggregateList , 'get_by_host' )
4673
+ @mock .patch .object (servers , 'LOG' )
4674
+ def test_create_instance_az_host_mismatch_with_aggs_in_default_az (
4675
+ self , mock_log , mock_get_host_aggs ,
4676
+ ):
4677
+ """User requests the default AZ and host is in aggregates without AZ"""
4678
+ self .flags (default_availability_zone = 'zone1' )
4679
+ mock_get_host_aggs .return_value = objects .AggregateList (
4680
+ objects = [objects .Aggregate (metadata = {})],
4681
+ )
4682
+
4683
+ self .body ['server' ]['availability_zone' ] = 'zone1:host1'
4684
+ self .req .body = jsonutils .dump_as_bytes (self .body )
4685
+
4686
+ self .controller .create (self .req , body = self .body )
4687
+
4688
+ mock_get_host_aggs .assert_called_once ()
4689
+ # we shouldn't see a log since none of the host aggregates have an
4690
+ # explicit AZ set and the host is therefore in the default AZ
4691
+ mock_log .warning .assert_not_called ()
4692
+
4693
+ def test_create_instance_invalid_az_format (self ):
4694
+ self .body ['server' ]['availability_zone' ] = 'invalid::::zone'
4695
+ self .assertRaises (webob .exc .HTTPBadRequest ,
4696
+ self .controller .create ,
4697
+ self .req , body = self .body )
4698
+
4699
+ def test_create_instance_invalid_az_as_int (self ):
4700
+ self .body ['server' ]['availability_zone' ] = 123
4701
+ self .assertRaises (exception .ValidationError ,
4702
+ self .controller .create ,
4703
+ self .req , body = self .body )
4581
4704
4582
4705
def test_create_instance (self ):
4583
4706
self .stub_out ('uuid.uuid4' , lambda : FAKE_UUID )
@@ -6181,18 +6304,6 @@ def test_create_instance_raise_image_bad_request(self, mock_create):
6181
6304
self .controller .create ,
6182
6305
self .req , body = self .body )
6183
6306
6184
- def test_create_instance_invalid_availability_zone (self ):
6185
- self .body ['server' ]['availability_zone' ] = 'invalid::::zone'
6186
- self .assertRaises (webob .exc .HTTPBadRequest ,
6187
- self .controller .create ,
6188
- self .req , body = self .body )
6189
-
6190
- def test_create_instance_invalid_availability_zone_as_int (self ):
6191
- self .body ['server' ]['availability_zone' ] = 123
6192
- self .assertRaises (exception .ValidationError ,
6193
- self .controller .create ,
6194
- self .req , body = self .body )
6195
-
6196
6307
@mock .patch .object (compute_api .API , 'create' ,
6197
6308
side_effect = exception .FixedIpNotFoundForAddress (
6198
6309
address = 'dummy' ))
0 commit comments