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

added test of saved node cards/ports

parent 2e9362c0
No related branches found
No related tags found
No related merge requests found
......@@ -31,18 +31,36 @@ import click
import logging
from jsonschema import validate, ValidationError
import environment
import config
from db import mysql_dsn
from db import init_db_model
from db import model
from db import session_scope
from resource_management.hardware.router import load_line_cards, LINE_CARDS_LIST_SCHEMA
from resource_management import db, config, environment
environment.setup_logging()
logger = logging.getLogger(__name__)
def _save_router_info(fqdn, fpcs):
with db.session_scope() as session:
node = db.model.Node(fqdn=fqdn)
session.add(node)
for _line_card in fpcs:
line_card_record = db.model.LineCard(
model=_line_card['model'],
position=_line_card["position"],
node=node)
session.add(line_card_record)
for port in _line_card['ports']:
port_record = db.model.Port(
name=port['name'],
speed=port["speed"],
line_card=line_card_record)
session.add(port_record)
def _validate_config(_unused_ctx, _unused_param, file):
try:
params = config.load(file)
......@@ -54,43 +72,6 @@ def _validate_config(_unused_ctx, _unused_param, file):
raise click.BadParameter(e.message)
def _save_router_info(fqdn, fpcs):
with session_scope(_callback_create) as session:
node = model.Node(fqdn=fqdn)
session.add(node)
session.flush()
node_id = node.id
logger.info("Registered node with id {0}: {1}".format(node_id, node.fqdn))
stored_line_cards = []
for _line_card in router["line_cards"]:
line_card = model.LineCard(model=_line_card["model"],
position=_line_card["position"],
node_id=node_id)
session.add(line_card)
session.flush()
line_card_id = line_card.id
logger.info("Registered line card with id {0}".format(line_card_id))
stored_line_cards.append({"id": line_card_id,
"position": line_card.position})
for _port in router['ports']:
line_card_id = -1
# The port's line card is determined by the first digit of the port name.
# This digit indicates the line card position, so we search for a matching position among
# the line cards added before, and use the id of that line card as the port's line_card_id.
for _line_card in stored_line_cards:
if _port["_line_card_position"] == _line_card["position"]:
line_card_id = _line_card["id"]
break
port = model.Port(name=_port["name"],
speed=_port["speed"],
line_card_id=line_card_id)
session.add(port)
session.flush()
logger.info("Registered port with id {0}".format(port.id))
@click.command()
@click.option(
'--config',
......@@ -103,7 +84,7 @@ def _save_router_info(fqdn, fpcs):
required=True,
type=click.STRING,
help='config filename')
def create(config, fqdn):
def cli(config, fqdn):
"""
notes:
- first call init_db(dns=mysql_dsn(params from config))
......@@ -116,62 +97,16 @@ def create(config, fqdn):
validate(line_cards, LINE_CARDS_LIST_SCHEMA)
mysql_config = config["mysql"]
dsn = mysql_dsn(mysql_config["username"],
dsn = db.mysql_dsn(mysql_config["username"],
mysql_config["password"],
mysql_config["hostname"],
mysql_config["dbname"])
logger.info("MYSQL DSN is: {0}".format(dsn))
init_db_model(dsn)
db.init_db_model(dsn)
_save_router_info(fqdn, line_cards)
def _callback_create():
logger.info("Node successfully commited to database")
@click.command()
@click.option(
'--config',
required=True,
type=click.File('r'),
help='config filename',
callback=_validate_config)
@click.option(
'--fqdn',
required=True,
type=click.STRING,
help='The FQDN to a router')
@click.option(
'--store',
required=False,
is_flag=True,
default=False,
help='Store JSON info')
def show(config: dict, fqdn: str, store: bool):
click.echo('This will show JSON output')
router_config = config["router"]
jr = junos_router(fqdn, router_config)
router_json = jr.get_hardware_info_as_json()
jr.close_device()
logger.info("Obtained the following hardware info about router: {0}"
.format(router_json))
if store:
# Store line cards
with open("line_cards.json", 'w') as file_object:
json.dump(router_json['line_cards'], file_object)
# store ports
with open("ports.json", 'w') as file_object:
json.dump(router_json['ports'], file_object)
else:
print(json.dumps(router_json['line_cards'], indent=4))
print(json.dumps(router_json['ports'], indent=4))
cli.add_command(create)
cli.add_command(show)
if __name__ == '__main__':
cli()
......@@ -15,8 +15,7 @@ def mysql_dsn(username, password, hostname, db_name):
@contextlib.contextmanager
def session_scope(
callback_before_close: Optional[Callable] = None) -> Iterator[Session]:
def session_scope() -> Iterator[Session]:
# best practice is to keep session scope separate from data processing
# cf. https://docs.sqlalchemy.org/en/13/orm/session_basics.html
......@@ -25,8 +24,6 @@ def session_scope(
try:
yield session
session.commit()
if callback_before_close:
callback_before_close()
except SQLAlchemyError:
logger.exception("caught sql layer exception, rolling back")
session.rollback()
......
......@@ -40,9 +40,10 @@ LINE_CARDS_LIST_SCHEMA = {
'properties': {
'name': {'type': 'string'},
'model': {'type': 'string'},
'position': {'type': 'integer'},
'ports': {'$ref': '#/definitions/port'}
},
'required': ['name', 'model', 'ports'],
'required': ['name', 'model', 'position', 'ports'],
'additionalProperties': False
}
}
......@@ -131,6 +132,7 @@ def load_line_cards(hostname, ssh_config, port=830):
yield {
'name': fpc.name,
'model': fpc.model or 'Unknown',
'position': position,
'ports': [
p for p in ports if _port_card_pos(p) == position]
}
......
from resource_management.db import model
from resource_management.db import session_scope
from resource_management.cli import _save_router_info
from resource_management.hardware.router import load_line_cards
def test_sanity_check(resources_db):
def test_sanity_check(resources_db, router_name):
# router_name unused ... but needed by pytest
with session_scope() as session:
......@@ -27,6 +31,31 @@ def test_sanity_check(resources_db):
assert len(lc.ports) == 20
def test_save_router_info(resources_db, router_name, mocked_router):
ssh = {
'username': 'bogus',
'private-key': 'no file'
}
fpcs = list(load_line_cards(hostname=router_name, ssh_config=ssh))
_save_router_info(fqdn=router_name, fpcs=fpcs)
fpc_position_dict = {f['position']: f['ports'] for f in fpcs}
with session_scope() as session:
node = session.query(model.Node) \
.filter(model.Node.fqdn == router_name).one()
expected_fpc_positions = set(fpc_position_dict.keys())
fpc_positions = {fpc.position for fpc in node.line_cards}
assert expected_fpc_positions == fpc_positions
for fpc in node.line_cards:
expected_ports = {p['name'] for p in fpc_position_dict[fpc.position]}
port_names = {p.name for p in fpc.ports}
assert expected_ports == port_names
# TODO: do this in a tmp container ...
# from resource_management.db import mysql_dsn
# from resource_management.migrations import migration_utils
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment