Skip to content
Snippets Groups Projects
Commit 27bf26b1 authored by Erik Reid's avatar Erik Reid
Browse files

Finished feature POL1-392-add-latch-timestamp.

parents 102dbff6 6464fdcb
No related branches found
No related tags found
No related merge requests found
......@@ -4,42 +4,43 @@ from flask import Blueprint, jsonify, current_app
from inventory_provider.routes import common
from inventory_provider.tasks.common import get_current_redis, get_latch
routes = Blueprint("inventory-data-default-routes", __name__)
routes = Blueprint('inventory-data-default-routes', __name__)
API_VERSION = '0.1'
VERSION_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
'$schema': 'http://json-schema.org/draft-07/schema#',
"definitions": {
"latch": {
"type": "object",
"properties": {
"current": {"type": "integer"},
"next": {"type": "integer"},
"this": {"type": "integer"},
"failure": {"type": "boolean"},
"pending": {"type": "boolean"},
'definitions': {
'latch': {
'type': 'object',
'properties': {
'current': {'type': 'integer'},
'next': {'type': 'integer'},
'this': {'type': 'integer'},
'failure': {'type': 'boolean'},
'pending': {'type': 'boolean'},
'timestamp': {'type': 'number'}
},
"required": ["current", "next", "this", "pending", "failure"],
"additionalProperties": False
'required': ['current', 'next', 'this', 'pending', 'failure'],
'additionalProperties': False
}
},
"type": "object",
"properties": {
"api": {
"type": "string",
"pattern": r'\d+\.\d+'
'type': 'object',
'properties': {
'api': {
'type': 'string',
'pattern': r'\d+\.\d+'
},
"module": {
"type": "string",
"pattern": r'\d+\.\d+'
'module': {
'type': 'string',
'pattern': r'\d+\.\d+'
},
"latch": {"$ref": "#/definitions/latch"}
'latch': {'$ref': '#/definitions/latch'}
},
"required": ["api", "module"],
"additionalProperties": False
'required': ['api', 'module'],
'additionalProperties': False
}
......@@ -48,7 +49,7 @@ def after_request(resp):
return common.after_request(resp)
@routes.route("/version", methods=['GET', 'POST'])
@routes.route('/version', methods=['GET', 'POST'])
@common.require_accepts_json
def version():
"""
......
import json
import logging
import time
import jsonschema
import redis
......@@ -11,17 +12,18 @@ DEFAULT_REDIS_SENTINEL_TIMEOUT = 0.1
DEFAULT_SENTINEL_SOCKET_TIMEOUT = 0.1
DB_LATCH_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"current": {"type": "integer"},
"next": {"type": "integer"},
"this": {"type": "integer"},
"pending": {"type": "boolean"},
"failure": {"type": "boolean"}
'$schema': 'http://json-schema.org/draft-07/schema#',
'type': 'object',
'properties': {
'current': {'type': 'integer'},
'next': {'type': 'integer'},
'this': {'type': 'integer'},
'pending': {'type': 'boolean'},
'failure': {'type': 'boolean'},
'timestamp': {'type': 'number'}
},
"required": ["current", "next", "this"],
"additionalProperties": False
'required': ['current', 'next', 'this'],
'additionalProperties': False
}
TASK_LOG_SCHEMA = {
......@@ -86,17 +88,24 @@ def update_latch_status(config, pending=False, failure=False):
logger.debug('updating latch status: pending={}, failure={}'.format(
pending, failure))
now = time.time()
for db in config['redis-databases']:
r = _get_redis(config, dbid=db)
latch = get_latch(r)
if not latch:
continue
if not pending and not failure:
if not latch['pending'] and not latch['failure']:
logger.error(
'updating latch for db {db} with pending=failure=True, '
f'but latch is already {latch}')
latch['timestamp'] = now
latch['pending'] = pending
latch['failure'] = failure
r.set('db:latch', json.dumps(latch))
def set_latch(config, new_current, new_next):
def set_latch(config, new_current, new_next, timestamp):
logger.debug('setting latch: new current={}, new next={}'.format(
new_current, new_next))
......@@ -107,7 +116,8 @@ def set_latch(config, new_current, new_next):
'next': new_next,
'this': db,
'pending': False,
'failure': False
'failure': False,
'timestamp': timestamp
}
r = _get_redis(config, dbid=db)
......@@ -129,7 +139,11 @@ def latch_db(config):
next_idx = db_ids.index(latch['next'])
next_idx = (next_idx + 1) % len(db_ids)
set_latch(config, new_current=latch['next'], new_next=db_ids[next_idx])
set_latch(
config,
new_current=latch['next'],
new_next=db_ids[next_idx],
timestamp=time.time())
def _get_redis(config, dbid=None):
......
......@@ -541,7 +541,8 @@ def _erase_next_db(config):
set_latch(
config,
new_current=saved_latch['current'],
new_next=saved_latch['next'])
new_next=saved_latch['next'],
timestamp=saved_latch.get('timestamp', 0))
@app.task(base=InventoryTask, bind=True, name='internal_refresh_phase_2')
......
......@@ -77,7 +77,7 @@ def test_next_redis(data_config, mocked_redis):
:param mocked_redis:
:return:
"""
common.set_latch(data_config, 10, 20)
common.set_latch(data_config, 10, 20, 100)
r = common.get_next_redis(data_config)
assert r
......@@ -85,6 +85,7 @@ def test_next_redis(data_config, mocked_redis):
latch = common.get_latch(r)
assert latch['current'] == 10
assert latch['next'] == 20
assert latch['timestamp'] == 100
def test_next_redis_with_none(data_config, mocked_redis):
......
......@@ -5,59 +5,59 @@ from inventory_provider.routes import common
from inventory_provider.routes.default import VERSION_SCHEMA
DEFAULT_REQUEST_HEADERS = {
"Content-type": "application/json",
"Accept": ["application/json"]
'Content-type': 'application/json',
'Accept': ['application/json']
}
def test_version_request(client, mocked_redis):
rv = client.post(
"version",
'version',
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200
jsonschema.validate(
json.loads(rv.data.decode("utf-8")),
json.loads(rv.data.decode('utf-8')),
VERSION_SCHEMA)
def test_load_json_docs(data_config, mocked_redis):
INTERFACE_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
'$schema': 'http://json-schema.org/draft-07/schema#',
"definitions": {
"interface": {
"type": "object",
"properties": {
"logical-system": {"type": "string"},
"name": {"type": "string"},
"description": {"type": "string"},
"bundle": {
"type": "array",
"items": {"type": "string"}
'definitions': {
'interface': {
'type': 'object',
'properties': {
'logical-system': {'type': 'string'},
'name': {'type': 'string'},
'description': {'type': 'string'},
'bundle': {
'type': 'array',
'items': {'type': 'string'}
},
"ipv4": {
"type": "array",
"items": {"type": "string"}
'ipv4': {
'type': 'array',
'items': {'type': 'string'}
},
"ipv6": {
"type": "array",
"items": {"type": "string"}
'ipv6': {
'type': 'array',
'items': {'type': 'string'}
}
},
"required": ["name", "description", "ipv4", "ipv6"],
"additionalProperties": False
'required': ['name', 'description', 'ipv4', 'ipv6'],
'additionalProperties': False
}
},
"type": "object",
"properties": {
"key": {"type": "string"},
"value": {"$ref": "#/definitions/interface"}
'type': 'object',
'properties': {
'key': {'type': 'string'},
'value': {'$ref': '#/definitions/interface'}
},
"required": ["key", "value"],
"additionalProperties": False
'required': ['key', 'value'],
'additionalProperties': False
}
for ifc in common.load_json_docs(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment