113
114
obj2lis = listen(('localhost', 0))
114
115
_test_sockets = \
115
116
(prolis, acc1lis, acc2lis, con1lis, con2lis, obj1lis, obj2lis)
116
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
117
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
118
'port': acc1lis.getsockname()[1]},
119
{'id': 1, 'zone': 1, 'device': 'sdb1', 'ip': '127.0.0.1',
120
'port': acc2lis.getsockname()[1]}], 30),
121
GzipFile(os.path.join(_testdir, 'account.ring.gz'), 'wb'))
122
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
123
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
124
'port': con1lis.getsockname()[1]},
125
{'id': 1, 'zone': 1, 'device': 'sdb1', 'ip': '127.0.0.1',
126
'port': con2lis.getsockname()[1]}], 30),
127
GzipFile(os.path.join(_testdir, 'container.ring.gz'), 'wb'))
128
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
129
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
130
'port': obj1lis.getsockname()[1]},
131
{'id': 1, 'zone': 1, 'device': 'sdb1', 'ip': '127.0.0.1',
132
'port': obj2lis.getsockname()[1]}], 30),
133
GzipFile(os.path.join(_testdir, 'object.ring.gz'), 'wb'))
117
with closing(GzipFile(os.path.join(_testdir, 'account.ring.gz'), 'wb')) \
119
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
120
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
121
'port': acc1lis.getsockname()[1]},
122
{'id': 1, 'zone': 1, 'device': 'sdb1', 'ip': '127.0.0.1',
123
'port': acc2lis.getsockname()[1]}], 30),
125
with closing(GzipFile(os.path.join(_testdir, 'container.ring.gz'), 'wb')) \
127
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
128
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
129
'port': con1lis.getsockname()[1]},
130
{'id': 1, 'zone': 1, 'device': 'sdb1', 'ip': '127.0.0.1',
131
'port': con2lis.getsockname()[1]}], 30),
133
with closing(GzipFile(os.path.join(_testdir, 'object.ring.gz'), 'wb')) \
135
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
136
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
137
'port': obj1lis.getsockname()[1]},
138
{'id': 1, 'zone': 1, 'device': 'sdb1', 'ip': '127.0.0.1',
139
'port': obj2lis.getsockname()[1]}], 30),
134
141
prosrv = proxy_server.Application(conf, FakeMemcacheReturnsNone())
135
142
acc1srv = account_server.AccountController(conf)
136
143
acc2srv = account_server.AccountController(conf)
1389
1397
"name": "/d1/seg01",
1390
1398
"content_type": "application/octet-stream"},
1391
{"hash": "d526f1c8ef6c1e4e980e2b8471352d23",
1399
{"hash": "8681fb3ada2715c8754706ee5f23d4f8",
1392
1400
"last_modified": "2012-11-08T04:05:37.846710",
1402
"name": "/d2/sub_manifest",
1403
"content_type": "application/octet-stream"},
1404
{"hash": "419af6d362a14b7a789ba1c7e772bbae",
1405
"last_modified": "2012-11-08T04:05:37.866820",
1394
"name": "/d2/seg02",
1407
"name": "/d1/seg04",
1395
1408
"content_type": "application/octet-stream"}]
1410
sub_listing = [{"hash": "d526f1c8ef6c1e4e980e2b8471352d23",
1411
"last_modified": "2012-11-08T04:05:37.866820",
1413
"name": "/d1/seg02",
1414
"content_type": "application/octet-stream"},
1415
{"hash": "e4c8f1de1c0855c7c2be33196d3c3537",
1416
"last_modified": "2012-11-08T04:05:37.846710",
1418
"name": "/d2/seg03",
1419
"content_type": "application/octet-stream"}]
1397
1421
response_bodies = (
1399
1423
'', # HEAD /a/c
1400
1424
simplejson.dumps(listing), # GET manifest
1401
1425
'Aa', # GET seg01
1426
simplejson.dumps(sub_listing), # GET sub_manifest
1403
1430
with save_globals():
1404
1431
controller = proxy_server.ObjectController(
1405
1432
self.app, 'a', 'c', 'manifest')
1419
1446
200, # HEAD /a/c
1420
1447
200, # GET listing1
1421
1448
200, # GET seg01
1449
200, # GET sub listing1
1422
1450
200, # GET seg02
1423
headers=[{}, {}, slob_headers, {}, slob_headers],
1453
headers=[{}, {}, slob_headers, {}, slob_headers, {}, {}, {}],
1424
1454
body_iter=response_bodies,
1425
1455
give_connect=capture_requested_paths)
1426
1456
req = Request.blank('/a/c/manifest')
1427
1457
resp = controller.GET(req)
1428
1458
self.assertEqual(resp.status_int, 200)
1429
self.assertEqual(resp.content_length, 4) # content incomplete
1459
self.assertEqual(resp.content_length, 8)
1430
1460
self.assertEqual(resp.content_type, 'text/html')
1431
self.assertRaises(SloSegmentError, lambda: resp.body)
1432
# dropped connection, exception is caught by eventlet as it is
1433
# iterating over response
1435
1462
self.assertEqual(
1437
1464
[['HEAD', '/a', {}],
1438
1465
['HEAD', '/a/c', {}],
1466
['GET', '/a/c/manifest', {}]])
1467
# iterating over body will retrieve manifest and sub manifest's
1469
self.assertEqual(resp.body, 'AaBbCcDd')
1472
[['HEAD', '/a', {}],
1473
['HEAD', '/a/c', {}],
1439
1474
['GET', '/a/c/manifest', {}],
1440
1475
['GET', '/a/d1/seg01', {}],
1441
['GET', '/a/d2/seg02', {}]])
1476
['GET', '/a/d2/sub_manifest', {}],
1477
['GET', '/a/d1/seg02', {}],
1478
['GET', '/a/d2/seg03', {}],
1479
['GET', '/a/d1/seg04', {}]])
1443
1481
def test_GET_bad_404_manifest_slo(self):
1444
1482
listing = [{"hash": "98568d540134639be4655198a36614a4",
1998
2036
res = controller.POST(req)
1999
2037
self.assertEquals(res.status_int, 400)
2039
def test_PUT_not_autodetect_content_type(self):
2040
with save_globals():
2041
controller = proxy_server.ObjectController(
2042
self.app, 'a', 'c', 'o.html')
2044
headers = {'Content-Type': 'something/right', 'Content-Length': 0}
2047
def verify_content_type(ipaddr, port, device, partition,
2048
method, path, headers=None,
2050
if path == '/a/c/o.html':
2052
headers['Content-Type'].startswith('something/right'))
2054
set_http_connect(204, 204, 201, 201, 201,
2055
give_connect=verify_content_type)
2056
req = Request.blank('/a/c/o.html', {}, headers=headers)
2057
self.app.update_request(req)
2058
res = controller.PUT(req)
2059
self.assertNotEquals(it_worked, [])
2060
self.assertTrue(all(it_worked))
2062
def test_PUT_autodetect_content_type(self):
2063
with save_globals():
2064
controller = proxy_server.ObjectController(
2065
self.app, 'a', 'c', 'o.html')
2067
headers = {'Content-Type': 'something/wrong', 'Content-Length': 0,
2068
'X-Detect-Content-Type': 'True'}
2071
def verify_content_type(ipaddr, port, device, partition,
2072
method, path, headers=None,
2074
if path == '/a/c/o.html':
2076
headers['Content-Type'].startswith('text/html'))
2078
set_http_connect(204, 204, 201, 201, 201,
2079
give_connect=verify_content_type)
2080
req = Request.blank('/a/c/o.html', {}, headers=headers)
2081
self.app.update_request(req)
2082
res = controller.PUT(req)
2083
self.assertNotEquals(it_worked, [])
2084
self.assertTrue(all(it_worked))
2001
2086
def test_client_timeout(self):
2002
2087
with save_globals():
2003
2088
self.app.account_ring.get_nodes('account')
4607
4692
200, 200, 200, 200, 200) # HEAD HEAD DELETE DELETE DELETE
4609
4694
self.assertEqual(seen_headers, [
4610
{'X-Container-Host': '10.0.0.0:1000,10.0.0.3:1003',
4611
'X-Container-Partition': '1',
4612
'X-Container-Device': 'sda,sdd'},
4613
{'X-Container-Host': '10.0.0.1:1001',
4614
'X-Container-Partition': '1',
4615
'X-Container-Device': 'sdb'},
4616
{'X-Container-Host': '10.0.0.2:1002',
4617
'X-Container-Partition': '1',
4618
'X-Container-Device': 'sdc'}])
4695
{'X-Container-Host': '10.0.0.0:1000,10.0.0.3:1003',
4696
'X-Container-Partition': '1',
4697
'X-Container-Device': 'sda,sdd'},
4698
{'X-Container-Host': '10.0.0.1:1001',
4699
'X-Container-Partition': '1',
4700
'X-Container-Device': 'sdb'},
4701
{'X-Container-Host': '10.0.0.2:1002',
4702
'X-Container-Partition': '1',
4703
'X-Container-Device': 'sdc'}
4620
4706
@mock.patch('time.time', new=lambda: STATIC_TIME)
4621
4707
def test_PUT_x_delete_at_with_fewer_container_replicas(self):
4638
4724
'X-Delete-At-Partition', 'X-Delete-At-Container'))
4640
4726
self.assertEqual(seen_headers, [
4641
{'X-Delete-At-Host': '10.0.0.0:1000',
4642
'X-Delete-At-Container': delete_at_container,
4643
'X-Delete-At-Partition': '1',
4644
'X-Delete-At-Device': 'sda'},
4645
{'X-Delete-At-Host': '10.0.0.1:1001',
4646
'X-Delete-At-Container': delete_at_container,
4647
'X-Delete-At-Partition': '1',
4648
'X-Delete-At-Device': 'sdb'},
4649
{'X-Delete-At-Host': None,
4650
'X-Delete-At-Container': None,
4651
'X-Delete-At-Partition': None,
4652
'X-Delete-At-Device': None}])
4727
{'X-Delete-At-Host': '10.0.0.0:1000',
4728
'X-Delete-At-Container': delete_at_container,
4729
'X-Delete-At-Partition': '1',
4730
'X-Delete-At-Device': 'sda'},
4731
{'X-Delete-At-Host': '10.0.0.1:1001',
4732
'X-Delete-At-Container': delete_at_container,
4733
'X-Delete-At-Partition': '1',
4734
'X-Delete-At-Device': 'sdb'},
4735
{'X-Delete-At-Host': None,
4736
'X-Delete-At-Container': None,
4737
'X-Delete-At-Partition': None,
4738
'X-Delete-At-Device': None}
4654
4741
@mock.patch('time.time', new=lambda: STATIC_TIME)
4655
4742
def test_PUT_x_delete_at_with_more_container_replicas(self):
4673
4760
header_list=('X-Delete-At-Host', 'X-Delete-At-Device',
4674
4761
'X-Delete-At-Partition', 'X-Delete-At-Container'))
4675
4762
self.assertEqual(seen_headers, [
4676
{'X-Delete-At-Host': '10.0.0.0:1000,10.0.0.3:1003',
4677
'X-Delete-At-Container': delete_at_container,
4678
'X-Delete-At-Partition': '1',
4679
'X-Delete-At-Device': 'sda,sdd'},
4680
{'X-Delete-At-Host': '10.0.0.1:1001',
4681
'X-Delete-At-Container': delete_at_container,
4682
'X-Delete-At-Partition': '1',
4683
'X-Delete-At-Device': 'sdb'},
4684
{'X-Delete-At-Host': '10.0.0.2:1002',
4685
'X-Delete-At-Container': delete_at_container,
4686
'X-Delete-At-Partition': '1',
4687
'X-Delete-At-Device': 'sdc'}])
4763
{'X-Delete-At-Host': '10.0.0.0:1000,10.0.0.3:1003',
4764
'X-Delete-At-Container': delete_at_container,
4765
'X-Delete-At-Partition': '1',
4766
'X-Delete-At-Device': 'sda,sdd'},
4767
{'X-Delete-At-Host': '10.0.0.1:1001',
4768
'X-Delete-At-Container': delete_at_container,
4769
'X-Delete-At-Partition': '1',
4770
'X-Delete-At-Device': 'sdb'},
4771
{'X-Delete-At-Host': '10.0.0.2:1002',
4772
'X-Delete-At-Container': delete_at_container,
4773
'X-Delete-At-Partition': '1',
4774
'X-Delete-At-Device': 'sdc'}
4690
4778
class TestContainerController(unittest.TestCase):
5508
5596
controller.PUT, req,
5509
5597
200, 201, 201, 201) # HEAD PUT PUT PUT
5510
5598
self.assertEqual(seen_headers, [
5511
{'X-Account-Host': '10.0.0.0:1000',
5512
'X-Account-Partition': '1',
5513
'X-Account-Device': 'sda'},
5514
{'X-Account-Host': '10.0.0.1:1001',
5515
'X-Account-Partition': '1',
5516
'X-Account-Device': 'sdb'},
5517
{'X-Account-Host': None,
5518
'X-Account-Partition': None,
5519
'X-Account-Device': None}])
5599
{'X-Account-Host': '10.0.0.0:1000',
5600
'X-Account-Partition': '1',
5601
'X-Account-Device': 'sda'},
5602
{'X-Account-Host': '10.0.0.1:1001',
5603
'X-Account-Partition': '1',
5604
'X-Account-Device': 'sdb'},
5605
{'X-Account-Host': None,
5606
'X-Account-Partition': None,
5607
'X-Account-Device': None}
5521
5610
def test_PUT_x_account_headers_with_more_account_replicas(self):
5522
5611
self.app.account_ring.set_replicas(4)
5527
5616
controller.PUT, req,
5528
5617
200, 201, 201, 201) # HEAD PUT PUT PUT
5529
5618
self.assertEqual(seen_headers, [
5530
{'X-Account-Host': '10.0.0.0:1000,10.0.0.3:1003',
5531
'X-Account-Partition': '1',
5532
'X-Account-Device': 'sda,sdd'},
5533
{'X-Account-Host': '10.0.0.1:1001',
5534
'X-Account-Partition': '1',
5535
'X-Account-Device': 'sdb'},
5536
{'X-Account-Host': '10.0.0.2:1002',
5537
'X-Account-Partition': '1',
5538
'X-Account-Device': 'sdc'}])
5619
{'X-Account-Host': '10.0.0.0:1000,10.0.0.3:1003',
5620
'X-Account-Partition': '1',
5621
'X-Account-Device': 'sda,sdd'},
5622
{'X-Account-Host': '10.0.0.1:1001',
5623
'X-Account-Partition': '1',
5624
'X-Account-Device': 'sdb'},
5625
{'X-Account-Host': '10.0.0.2:1002',
5626
'X-Account-Partition': '1',
5627
'X-Account-Device': 'sdc'}
5540
5630
def test_DELETE_x_account_headers_with_fewer_account_replicas(self):
5541
5631
self.app.account_ring.set_replicas(2)
5546
5636
controller.DELETE, req,
5547
5637
200, 204, 204, 204) # HEAD DELETE DELETE DELETE
5548
5638
self.assertEqual(seen_headers, [
5549
{'X-Account-Host': '10.0.0.0:1000',
5550
'X-Account-Partition': '1',
5551
'X-Account-Device': 'sda'},
5552
{'X-Account-Host': '10.0.0.1:1001',
5553
'X-Account-Partition': '1',
5554
'X-Account-Device': 'sdb'},
5555
{'X-Account-Host': None,
5556
'X-Account-Partition': None,
5557
'X-Account-Device': None}])
5639
{'X-Account-Host': '10.0.0.0:1000',
5640
'X-Account-Partition': '1',
5641
'X-Account-Device': 'sda'},
5642
{'X-Account-Host': '10.0.0.1:1001',
5643
'X-Account-Partition': '1',
5644
'X-Account-Device': 'sdb'},
5645
{'X-Account-Host': None,
5646
'X-Account-Partition': None,
5647
'X-Account-Device': None}
5559
5650
def test_DELETE_x_account_headers_with_more_account_replicas(self):
5560
5651
self.app.account_ring.set_replicas(4)
5565
5656
controller.DELETE, req,
5566
5657
200, 204, 204, 204) # HEAD DELETE DELETE DELETE
5567
5658
self.assertEqual(seen_headers, [
5568
{'X-Account-Host': '10.0.0.0:1000,10.0.0.3:1003',
5569
'X-Account-Partition': '1',
5570
'X-Account-Device': 'sda,sdd'},
5571
{'X-Account-Host': '10.0.0.1:1001',
5572
'X-Account-Partition': '1',
5573
'X-Account-Device': 'sdb'},
5574
{'X-Account-Host': '10.0.0.2:1002',
5575
'X-Account-Partition': '1',
5576
'X-Account-Device': 'sdc'}])
5659
{'X-Account-Host': '10.0.0.0:1000,10.0.0.3:1003',
5660
'X-Account-Partition': '1',
5661
'X-Account-Device': 'sda,sdd'},
5662
{'X-Account-Host': '10.0.0.1:1001',
5663
'X-Account-Partition': '1',
5664
'X-Account-Device': 'sdb'},
5665
{'X-Account-Host': '10.0.0.2:1002',
5666
'X-Account-Partition': '1',
5667
'X-Account-Device': 'sdc'}
5579
5671
class TestAccountController(unittest.TestCase):