Merge "Ring checker in swift-recon"
This commit is contained in:
commit
41058ba809
@ -109,6 +109,34 @@ class Scout(object):
|
||||
url, content, status = self.scout_host(base_url, self.recon_type)
|
||||
return url, content, status
|
||||
|
||||
def scout_server_type(self, host):
|
||||
"""
|
||||
Obtain Server header by calling OPTIONS.
|
||||
|
||||
:param host: host to check
|
||||
:returns: Server type, status
|
||||
"""
|
||||
try:
|
||||
url = "http://%s:%s/" % (host[0], host[1])
|
||||
req = urllib2.Request(url)
|
||||
req.get_method = lambda: 'OPTIONS'
|
||||
conn = urllib2.urlopen(req)
|
||||
header = conn.info().getheader('Server')
|
||||
server_header = header.split('/')
|
||||
content = server_header[0]
|
||||
status = 200
|
||||
except urllib2.HTTPError as err:
|
||||
if not self.suppress_errors or self.verbose:
|
||||
print("-> %s: %s" % (url, err))
|
||||
content = err
|
||||
status = err.code
|
||||
except urllib2.URLError as err:
|
||||
if not self.suppress_errors or self.verbose:
|
||||
print("-> %s: %s" % (url, err))
|
||||
content = err
|
||||
status = -1
|
||||
return url, content, status
|
||||
|
||||
|
||||
class SwiftRecon(object):
|
||||
"""
|
||||
@ -334,6 +362,29 @@ class SwiftRecon(object):
|
||||
print("Device errors: %s on %s" % (entry, node))
|
||||
print("=" * 79)
|
||||
|
||||
def server_type_check(self, hosts):
|
||||
"""
|
||||
Check for server types on the ring
|
||||
|
||||
:param hosts: set of hosts to check. in the format of:
|
||||
set([('127.0.0.1', 6020), ('127.0.0.2', 6030)])
|
||||
"""
|
||||
errors = {}
|
||||
recon = Scout("server_type_check", self.verbose, self.suppress_errors,
|
||||
self.timeout)
|
||||
print("[%s] Validating server type '%s' on %s hosts..." %
|
||||
(self._ptime(), self.server_type, len(hosts)))
|
||||
for url, response, status in self.pool.imap(
|
||||
recon.scout_server_type, hosts):
|
||||
if status == 200:
|
||||
if response != self.server_type + '-server':
|
||||
errors[url] = response
|
||||
print("%s/%s hosts ok, %s error[s] while checking hosts." % (
|
||||
len(hosts) - len(errors), len(hosts), len(errors)))
|
||||
for host in errors:
|
||||
print("Invalid: %s is %s" % (host, errors[host]))
|
||||
print("=" * 79)
|
||||
|
||||
def expirer_check(self, hosts):
|
||||
"""
|
||||
Obtain and print expirer statistics
|
||||
@ -872,6 +923,8 @@ class SwiftRecon(object):
|
||||
help="Get cluster load average stats")
|
||||
args.add_option('--quarantined', '-q', action="store_true",
|
||||
help="Get cluster quarantine stats")
|
||||
args.add_option('--validate-servers', action="store_true",
|
||||
help="Validate servers on the ring")
|
||||
args.add_option('--md5', action="store_true",
|
||||
help="Get md5sum of servers ring and compare to "
|
||||
"local copy")
|
||||
@ -938,6 +991,7 @@ class SwiftRecon(object):
|
||||
self.get_ringmd5(hosts, swift_dir)
|
||||
self.quarantine_check(hosts)
|
||||
self.socket_usage(hosts)
|
||||
self.server_type_check(hosts)
|
||||
else:
|
||||
if options.async:
|
||||
if self.server_type == 'object':
|
||||
@ -966,6 +1020,8 @@ class SwiftRecon(object):
|
||||
self.expirer_check(hosts)
|
||||
else:
|
||||
print("Error: Can't check expired on non object servers.")
|
||||
if options.validate_servers:
|
||||
self.server_type_check(hosts)
|
||||
if options.loadstats:
|
||||
self.load_check(hosts)
|
||||
if options.diskusage:
|
||||
|
@ -56,6 +56,7 @@ class TestScout(unittest.TestCase):
|
||||
def setUp(self, *_args, **_kwargs):
|
||||
self.scout_instance = recon.Scout("type", suppress_errors=True)
|
||||
self.url = 'http://127.0.0.1:8080/recon/type'
|
||||
self.server_type_url = 'http://127.0.0.1:8080/'
|
||||
|
||||
@mock.patch('eventlet.green.urllib2.urlopen')
|
||||
def test_scout_ok(self, mock_urlopen):
|
||||
@ -85,6 +86,37 @@ class TestScout(unittest.TestCase):
|
||||
self.assertTrue(isinstance(content, urllib2.HTTPError))
|
||||
self.assertEqual(status, 404)
|
||||
|
||||
@mock.patch('eventlet.green.urllib2.urlopen')
|
||||
def test_scout_server_type_ok(self, mock_urlopen):
|
||||
def getheader(name):
|
||||
d = {'Server': 'server-type'}
|
||||
return d.get(name)
|
||||
mock_urlopen.return_value.info.return_value.getheader = getheader
|
||||
url, content, status = self.scout_instance.scout_server_type(
|
||||
("127.0.0.1", "8080"))
|
||||
self.assertEqual(url, self.server_type_url)
|
||||
self.assertEqual(content, 'server-type')
|
||||
self.assertEqual(status, 200)
|
||||
|
||||
@mock.patch('eventlet.green.urllib2.urlopen')
|
||||
def test_scout_server_type_url_error(self, mock_urlopen):
|
||||
mock_urlopen.side_effect = urllib2.URLError("")
|
||||
url, content, status = self.scout_instance.scout_server_type(
|
||||
("127.0.0.1", "8080"))
|
||||
self.assertTrue(isinstance(content, urllib2.URLError))
|
||||
self.assertEqual(url, self.server_type_url)
|
||||
self.assertEqual(status, -1)
|
||||
|
||||
@mock.patch('eventlet.green.urllib2.urlopen')
|
||||
def test_scout_server_type_http_error(self, mock_urlopen):
|
||||
mock_urlopen.side_effect = urllib2.HTTPError(
|
||||
self.server_type_url, 404, "Internal error", None, None)
|
||||
url, content, status = self.scout_instance.scout_server_type(
|
||||
("127.0.0.1", "8080"))
|
||||
self.assertEqual(url, self.server_type_url)
|
||||
self.assertTrue(isinstance(content, urllib2.HTTPError))
|
||||
self.assertEqual(status, 404)
|
||||
|
||||
|
||||
class TestRecon(unittest.TestCase):
|
||||
def setUp(self, *_args, **_kwargs):
|
||||
@ -289,6 +321,86 @@ class TestReconCommands(unittest.TestCase):
|
||||
|
||||
return mock.patch('eventlet.green.urllib2.urlopen', fake_urlopen)
|
||||
|
||||
def test_server_type_check(self):
|
||||
hosts = [('127.0.0.1', 6010), ('127.0.0.1', 6011),
|
||||
('127.0.0.1', 6012)]
|
||||
|
||||
# sample json response from http://<host>:<port>/
|
||||
responses = {6010: 'object-server', 6011: 'container-server',
|
||||
6012: 'account-server'}
|
||||
|
||||
def mock_scout_server_type(app, host):
|
||||
url = 'http://%s:%s/' % (host[0], host[1])
|
||||
response = responses[host[1]]
|
||||
status = 200
|
||||
return url, response, status
|
||||
|
||||
stdout = StringIO()
|
||||
patches = [
|
||||
mock.patch('swift.cli.recon.Scout.scout_server_type',
|
||||
mock_scout_server_type),
|
||||
mock.patch('sys.stdout', new=stdout),
|
||||
]
|
||||
|
||||
res_object = 'Invalid: http://127.0.0.1:6010/ is object-server'
|
||||
res_container = 'Invalid: http://127.0.0.1:6011/ is container-server'
|
||||
res_account = 'Invalid: http://127.0.0.1:6012/ is account-server'
|
||||
valid = "1/1 hosts ok, 0 error[s] while checking hosts."
|
||||
|
||||
#Test for object server type - default
|
||||
with nested(*patches):
|
||||
self.recon.server_type_check(hosts)
|
||||
|
||||
output = stdout.getvalue()
|
||||
self.assertTrue(res_container in output.splitlines())
|
||||
self.assertTrue(res_account in output.splitlines())
|
||||
stdout.truncate(0)
|
||||
|
||||
#Test ok for object server type - default
|
||||
with nested(*patches):
|
||||
self.recon.server_type_check([hosts[0]])
|
||||
|
||||
output = stdout.getvalue()
|
||||
self.assertTrue(valid in output.splitlines())
|
||||
stdout.truncate(0)
|
||||
|
||||
#Test for account server type
|
||||
with nested(*patches):
|
||||
self.recon.server_type = 'account'
|
||||
self.recon.server_type_check(hosts)
|
||||
|
||||
output = stdout.getvalue()
|
||||
self.assertTrue(res_container in output.splitlines())
|
||||
self.assertTrue(res_object in output.splitlines())
|
||||
stdout.truncate(0)
|
||||
|
||||
#Test ok for account server type
|
||||
with nested(*patches):
|
||||
self.recon.server_type = 'account'
|
||||
self.recon.server_type_check([hosts[2]])
|
||||
|
||||
output = stdout.getvalue()
|
||||
self.assertTrue(valid in output.splitlines())
|
||||
stdout.truncate(0)
|
||||
|
||||
#Test for container server type
|
||||
with nested(*patches):
|
||||
self.recon.server_type = 'container'
|
||||
self.recon.server_type_check(hosts)
|
||||
|
||||
output = stdout.getvalue()
|
||||
self.assertTrue(res_account in output.splitlines())
|
||||
self.assertTrue(res_object in output.splitlines())
|
||||
stdout.truncate(0)
|
||||
|
||||
#Test ok for container server type
|
||||
with nested(*patches):
|
||||
self.recon.server_type = 'container'
|
||||
self.recon.server_type_check([hosts[1]])
|
||||
|
||||
output = stdout.getvalue()
|
||||
self.assertTrue(valid in output.splitlines())
|
||||
|
||||
def test_get_swiftconfmd5(self):
|
||||
hosts = set([('10.1.1.1', 10000),
|
||||
('10.2.2.2', 10000)])
|
||||
|
Loading…
Reference in New Issue
Block a user