Stacktach down scenario: added an api to repair exists status after a period of verifier inactivity

added documentation
This commit is contained in:
Manali Latkar 2014-02-17 18:36:24 +05:30
parent 61e269ea03
commit 97666bcb6c
8 changed files with 288 additions and 5 deletions

View File

@ -805,4 +805,4 @@ stacky/usage/exists
]
]
:query instance: desired instance UUID (optional)
:query instance: desired instance UUID (optional)

View File

@ -814,4 +814,40 @@ Returns a count of .verified events stored in Stacktach's Rawdata table from
{
count: 10
}
}
repair
======
.. http:post:: http://example.com/repair/
Changes the status of all the exists of message-ids sent with the request
from 'pending' to 'sent_unverified' so that the verifier does not end up
sending .verified for all those exists(since the .exists have already been
modified as .verified and sent to AH by Yagi). It sends back the message-ids
of exists which could not be updated in the json response.
**Example request**:
.. sourcecode::http
POST /repair/ HTTP/1.1
Host: example.com
Accept: application/json
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/json
{
u'exists_not_pending': [u'494ebfce-0219-4b62-b810-79039a279620'],
u'absent_exists': [u'7609f3b2-3694-4b6f-869e-2f13ae504cb2',
u'0c64032e-4a60-44c0-a99d-5a4f2e46afb0']
}
:query message_ids: list of message_ids of exists messages
:query service: ``nova`` or ``glance``. default="nova"

View File

@ -36,6 +36,7 @@ from stacktach import datetime_to_decimal as dt
from stacktach import models
from stacktach import stacklog
from stacktach import utils
from stacktach.models import InstanceExists, ImageExists
DEFAULT_LIMIT = 50
HARD_LIMIT = 1000
@ -451,3 +452,24 @@ def get_verified_count(request):
except ValueError:
raise BadRequestException(message="Invalid format for date (Correct "
"format should be %YYYY-%mm-%dd)")
def exists_factory(service):
model = InstanceExists
if service == 'glance':
model = ImageExists
return model
def repair_stacktach_down(request):
post_dict = dict((request.POST._iterlists()))
message_ids = post_dict.get('message_ids')
service = post_dict.get('service', ['nova'])
absent_exists, exists_not_pending = \
exists_factory(service[0]).mark_exists_as_sent_unverified(message_ids)
response_data = {'absent_exists': absent_exists,
'exists_not_pending': exists_not_pending}
response = HttpResponse(json.dumps(response_data),
content_type="application/json")
return response

View File

@ -338,6 +338,24 @@ class InstanceExists(models.Model):
def update_status(self, new_status):
self.status = new_status
@staticmethod
def mark_exists_as_sent_unverified(message_ids):
absent_exists = []
exists_not_pending = []
for message_id in message_ids:
try:
exists = InstanceExists.objects.get(message_id=message_id)
if exists.status == InstanceExists.PENDING:
exists.status = InstanceExists.SENT_UNVERIFIED
exists.save()
else:
exists_not_pending.append(message_id)
except Exception:
absent_exists.append(message_id)
return absent_exists, exists_not_pending
class Timing(models.Model):
"""Each Timing record corresponds to a .start/.end event pair
@ -536,6 +554,24 @@ class ImageExists(models.Model):
self.fail_reason = reason
self.save()
@staticmethod
def mark_exists_as_sent_unverified(message_ids):
absent_exists = []
exists_not_pending = []
for message_id in message_ids:
exists_list = ImageExists.objects.filter(message_id=message_id)
if exists_list:
for exists in exists_list:
if exists.status == ImageExists.PENDING:
exists.status = ImageExists.SENT_UNVERIFIED
exists.save()
else:
exists_not_pending.append(message_id)
else :
absent_exists.append(message_id)
return absent_exists, exists_not_pending
def get_model_fields(model):
return model._meta.fields

View File

@ -72,6 +72,7 @@ urlpatterns = patterns('',
url(r'db/confirm/usage/exists/(?P<message_id>[\w\-]+)/$',
'stacktach.dbapi.exists_send_status'),
url(r'db/count/verified', 'stacktach.dbapi.get_verified_count'),
url(r'repair/', 'stacktach.dbapi.repair_stacktach_down'),
url(r'^(?P<deployment_id>\d+)/$', 'stacktach.views.home', name='home'),
url(r'^(?P<deployment_id>\d+)/details/(?P<column>\w+)/(?P<row_id>\d+)/$',
@ -83,5 +84,5 @@ urlpatterns = patterns('',
url(r'^(?P<deployment_id>\d+)/latest_raw/$',
'stacktach.views.latest_raw', name='latest_raw'),
url(r'^(?P<deployment_id>\d+)/instance_status/$',
'stacktach.views.instance_status', name='instance_status'),
'stacktach.views.instance_status', name='instance_status')
)

View File

@ -994,4 +994,55 @@ class DBAPITestCase(StacktachBaseTestCase):
self.assertEqual(response.status_code, 400)
self.assertEqual(json.loads(response.content)['message'],
"Invalid/absent query parameter")
self.mox.VerifyAll()
class StacktachRepairScenarioApi(StacktachBaseTestCase):
def setUp(self):
self.mox = mox.Mox()
def tearDown(self):
self.mox.UnsetStubs()
def test_change_nova_exists_status_for_all_exists(self):
request = self.mox.CreateMockAnything()
request.POST = self.mox.CreateMockAnything()
message_ids = ["04fd94b5-64dd-4559-83b7-981d9d4f7a5a",
"14fd94b5-64dd-4559-83b7-981d9d4f7a5a",
"24fd94b5-64dd-4559-83b7-981d9d4f7a5a"]
request.POST._iterlists().AndReturn([('service', 'nova'),
('message_ids', message_ids)])
self.mox.StubOutWithMock(models.InstanceExists,
'mark_exists_as_sent_unverified')
models.InstanceExists.mark_exists_as_sent_unverified(message_ids).\
AndReturn([[], []])
self.mox.ReplayAll()
response = dbapi.repair_stacktach_down(request)
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
self.assertEqual(response_data['exists_not_pending'], [])
self.assertEqual(response_data['absent_exists'], [])
self.mox.VerifyAll()
def test_change_glance_exists_status_for_all_exists(self):
request = self.mox.CreateMockAnything()
request.POST = self.mox.CreateMockAnything()
message_ids = ['04fd94b5-64dd-4559-83b7-981d9d4f7a5a',
'14fd94b5-64dd-4559-83b7-981d9d4f7a5a',
'24fd94b5-64dd-4559-83b7-981d9d4f7a5a']
request.POST._iterlists().AndReturn([('service', ['glance']),
('message_ids', message_ids)])
self.mox.StubOutWithMock(models.ImageExists,
'mark_exists_as_sent_unverified')
models.ImageExists.mark_exists_as_sent_unverified(message_ids).\
AndReturn([[], []])
self.mox.ReplayAll()
response = dbapi.repair_stacktach_down(request)
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
self.assertEqual(response_data['exists_not_pending'], [])
self.assertEqual(response_data['absent_exists'], [])
self.mox.VerifyAll()

View File

@ -112,6 +112,81 @@ class ImageExistsTestCase(unittest.TestCase):
'owner1-3': [exist4],
'owner2-2': [exist2]})
def test_mark_exists_as_sent_unverified(self):
message_ids = ["0708cb0b-6169-4d7c-9f58-3cf3d5bf694b",
"9156b83e-f684-4ec3-8f94-7e41902f27aa"]
exist1 = self.mox.CreateMockAnything()
exist1.status = "pending"
exist1.save()
exist2 = self.mox.CreateMockAnything()
exist2.status = "pending"
exist2.save()
exist3 = self.mox.CreateMockAnything()
exist3.status = "pending"
exist3.save()
self.mox.StubOutWithMock(ImageExists.objects, 'filter')
ImageExists.objects.filter(message_id=message_ids[0]).AndReturn(
[exist1, exist2])
ImageExists.objects.filter(message_id=message_ids[1]).AndReturn(
[exist3])
self.mox.ReplayAll()
results = ImageExists.mark_exists_as_sent_unverified(message_ids)
self.assertEqual(results, ([], []))
self.mox.VerifyAll()
def test_mark_exists_as_sent_unverified_return_absent_exists(self):
message_ids = ["0708cb0b-6169-4d7c-9f58-3cf3d5bf694b",
"9156b83e-f684-4ec3-8f94-7e41902f27aa"]
exist1 = self.mox.CreateMockAnything()
exist1.status = "pending"
exist1.save()
exist2 = self.mox.CreateMockAnything()
exist2.status = "pending"
exist2.save()
self.mox.StubOutWithMock(ImageExists.objects, 'filter')
ImageExists.objects.filter(message_id=message_ids[0]).AndReturn(
[exist1, exist2])
ImageExists.objects.filter(message_id=message_ids[1]).AndReturn([])
self.mox.ReplayAll()
results = ImageExists.mark_exists_as_sent_unverified(message_ids)
self.assertEqual(results, (['9156b83e-f684-4ec3-8f94-7e41902f27aa'],
[]))
self.mox.VerifyAll()
def test_mark_exists_as_sent_unverified_and_return_exist_not_pending(self):
message_ids = ["0708cb0b-6169-4d7c-9f58-3cf3d5bf694b",
"9156b83e-f684-4ec3-8f94-7e41902f27aa"]
exist1 = self.mox.CreateMockAnything()
exist1.status = "pending"
exist1.save()
exist2 = self.mox.CreateMockAnything()
exist2.status = "verified"
exist3 = self.mox.CreateMockAnything()
exist3.status = "pending"
exist3.save()
self.mox.StubOutWithMock(ImageExists.objects, 'filter')
ImageExists.objects.filter(message_id=message_ids[0]).AndReturn(
[exist1, exist2])
ImageExists.objects.filter(message_id=message_ids[1]).AndReturn(
[exist3])
self.mox.ReplayAll()
results = ImageExists.mark_exists_as_sent_unverified(message_ids)
self.assertEqual(results, ([],
["0708cb0b-6169-4d7c-9f58-3cf3d5bf694b"]))
self.mox.VerifyAll()
class InstanceExistsTestCase(unittest.TestCase):
def setUp(self):
@ -137,3 +212,66 @@ class InstanceExistsTestCase(unittest.TestCase):
self.mox.VerifyAll()
self.assertEqual(results, [1, 2])
def test_mark_exists_as_sent_unverified(self):
message_ids = ["0708cb0b-6169-4d7c-9f58-3cf3d5bf694b",
"9156b83e-f684-4ec3-8f94-7e41902f27aa"]
exist1 = self.mox.CreateMockAnything()
exist1.status = "pending"
exist1.save()
exist2 = self.mox.CreateMockAnything()
exist2.status = "pending"
exist2.save()
self.mox.StubOutWithMock(InstanceExists.objects, 'get')
InstanceExists.objects.get(message_id=message_ids[0]).AndReturn(exist1)
InstanceExists.objects.get(message_id=message_ids[1]).AndReturn(exist2)
self.mox.ReplayAll()
results = InstanceExists.mark_exists_as_sent_unverified(message_ids)
self.assertEqual(results, ([], []))
self.mox.VerifyAll()
def test_mark_exists_as_sent_unverified_return_absent_exists(self):
message_ids = ["0708cb0b-6169-4d7c-9f58-3cf3d5bf694b",
"9156b83e-f684-4ec3-8f94-7e41902f27aa"]
exist1 = self.mox.CreateMockAnything()
exist1.status = "pending"
exist1.save()
self.mox.StubOutWithMock(InstanceExists.objects, 'get')
InstanceExists.objects.get(message_id=message_ids[0]).AndReturn(exist1)
InstanceExists.objects.get(message_id=message_ids[1]).AndRaise(
Exception)
self.mox.ReplayAll()
results = InstanceExists.mark_exists_as_sent_unverified(message_ids)
self.assertEqual(results, (['9156b83e-f684-4ec3-8f94-7e41902f27aa'],
[]))
self.mox.VerifyAll()
def test_mark_exists_as_sent_unverified_and_return_exist_not_pending(self):
message_ids = ["0708cb0b-6169-4d7c-9f58-3cf3d5bf694b",
"9156b83e-f684-4ec3-8f94-7e41902f27aa"]
exist1 = self.mox.CreateMockAnything()
exist1.status = "pending"
exist1.save()
exist2 = self.mox.CreateMockAnything()
exist2.status = "verified"
self.mox.StubOutWithMock(InstanceExists.objects, 'get')
InstanceExists.objects.get(message_id=message_ids[0]).AndReturn(exist1)
InstanceExists.objects.get(message_id=message_ids[1]).AndReturn(exist2)
self.mox.ReplayAll()
results = InstanceExists.mark_exists_as_sent_unverified(message_ids)
self.assertEqual(results, ([],
["9156b83e-f684-4ec3-8f94-7e41902f27aa"]))
self.mox.VerifyAll()

View File

@ -38,8 +38,7 @@ from utils import TENANT_ID_1
from utils import INSTANCE_TYPE_ID_1
from utils import DUMMY_TIME
from utils import INSTANCE_TYPE_ID_2
from utils import IMAGE_UUID_1
from stacktach import stacklog
from stacktach import stacklog, models
from stacktach import notification
from stacktach import views
from tests.unit import StacktachBaseTestCase