Merge "Ring checker in swift-recon"

This commit is contained in:
Jenkins 2015-02-28 00:58:44 +00:00 committed by Gerrit Code Review
commit 41058ba809
2 changed files with 168 additions and 0 deletions

View File

@ -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:

View File

@ -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)])