Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement common log.warning function (closes #1793) #1803

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
5 changes: 2 additions & 3 deletions netsim/augment/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,9 @@ def check_group_data_structure(

# Validate node_data attributes (if any)
if 'node_data' in gdata and g_type == 'node':
log.error(
log.warning(
text=f'Group {grp} uses an obsolete attribute node_data. Migrate node parameters into group definition',
category=Warning,
module='groups')
flag='groups.node_data')

validate_attributes(
data=gdata.node_data,
Expand Down
6 changes: 3 additions & 3 deletions netsim/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,11 @@ def check_modified_source(snapshot: str, topology: typing.Optional[Box] = None)
if in_time <= snap_time:
continue

log.error(
log.warning(
text=f'Lab topology source file {infile} has been modified',
more_data=f'after the snapshot {snapshot} has been created',
category=Warning,
module='cli',
flag='snapshot.modified',
more_data=f'after the snapshot {snapshot} has been created',
hint='recreate')

# Load snapshot or topology -- used by 'netlab initial'
Expand Down
5 changes: 2 additions & 3 deletions netsim/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,8 @@ def set_sudo_flag() -> None:
os.environ['SUDO'] = "sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a"
return

log.error(
"sudo command is not available and you're not root. The installation will most likely fail",
category=Warning,
log.warning(
text="sudo command is not available and you're not root. The installation will most likely fail",
module='install')

if strings.confirm('Do you want to continue',blank_line=True):
Expand Down
8 changes: 3 additions & 5 deletions netsim/cli/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,9 @@ def show_lab(args: argparse.Namespace,lab_states: Box) -> None:
show_lab_nodes(topology)
if lab_status != 'started':
print()
log.error(
"Lab is not in 'started' state, inspect details with 'netlab status --log'",
category=Warning,
module=''
)
log.warning(
text="Lab is not in 'started' state, inspect details with 'netlab status --log'",
module='-')

def show_lab_log(args: argparse.Namespace, lab_states: Box) -> None:
iid = get_instance(args,lab_states)
Expand Down
4 changes: 2 additions & 2 deletions netsim/cli/up.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,14 +352,14 @@ def run_up(cli_args: typing.List[str]) -> None:

if args.validate:
if args.no_config:
log.error('Lab is not configured, skipping the validation phase',Warning,'')
log.warning(text='Lab is not configured, skipping the validation phase',module='-')
else:
try:
status = external_commands.run_command('netlab validate',return_exitcode=True)
if status == 1:
log.error('Validation failed',log.FatalError,module='netlab validate')
elif status == 3:
log.error('Validation generated a warning',Warning,module='netlab validate')
log.warning(text='Validation generated a warning',module='netlab validate')
except KeyboardInterrupt: # netlab validate displays its own error message
sys.exit(1)

Expand Down
7 changes: 3 additions & 4 deletions netsim/cli/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,9 @@ def extend_first_wait_time(args: argparse.Namespace, topology: Box) -> None:
v_entry.wait = v_entry.wait + max_delay
if not args.error_only:
indent = (topology._v_len + 3) if topology else 10
log.error(
f'Initial wait time extended by {max_delay} seconds required by {d_device}',
category=Warning,
module='',indent=indent)
log.warning(
text=f'Initial wait time extended by {max_delay} seconds required by {d_device}',
module='-',indent=indent)
return

'''
Expand Down
3 changes: 0 additions & 3 deletions netsim/defaults/hints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ evpn:
route targets. 'bgp.as' specified on individual nodes or groups will not work. You
can also specify the global AS used by EVPN in 'vrf.as' parameter if you use
VRFs, or in 'evpn.as' parameter if you use EVPN in bridging-only scenarios.
bgp:
igp: >
Add a supported IGP (ospf, isis, eigrp) to the list of modules.

report:
source: >
Expand Down
9 changes: 3 additions & 6 deletions netsim/extra/check.config/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ def cleanup(topology: Box) -> None:
data.append_to_list(missing[cfg_id].devices,ndata.device,ndata.name)
ndata.config = [ f for f in ndata.config if f != cfg ]

hint: typing.Optional[str] = "You will have to configure the missing functionality yourself"
for m_config in missing.values():
for m_device,m_nodes in m_config.devices.items():
log.error(
f'Custom configuration {m_config.item} is missing for device {m_device} (nodes {",".join(m_nodes)})',
category=Warning,
more_hints=hint,
log.warning(
text=f'Custom configuration {m_config.item} is missing for device {m_device} (nodes {",".join(m_nodes)})',
more_hints='You will have to configure the missing functionality yourself',
module='check.config')
hint = None
11 changes: 11 additions & 0 deletions netsim/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,17 @@ def cleanup(topology: Box) -> None:
node_transform("cleanup",topology)
link_transform("cleanup",topology)

"""
remove_module: Remove a module from a node
"""
def remove_module(node: Box, module: str, extra: list = []) -> None:
for attr in extra + [ module ]:
node.pop(attr,None) # Remove node configuration
for intf in [ intf for intf in node.interfaces if attr in intf ]:
intf.pop(attr,None) # Remove interface configuration

node.module = [ m for m in node.module if m != module ] # Remove module from the list of node modules

# Set default list of modules for nodes without specific module list
#
def augment_node_module(topology: Box) -> None:
Expand Down
28 changes: 13 additions & 15 deletions netsim/modules/_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def remove_unaddressed_intf(node: Box, proto: str) -> None:
#
# remove_unused_igp -- remove IGP module if it's not configured on any interface
#
def remove_unused_igp(node: Box, proto: str, warning: bool = False) -> bool:
def remove_unused_igp(node: Box, proto: str) -> bool:
if not any(proto in ifdata for ifdata in node.interfaces): # Is protocol configured on any non-loopback interface?
node.pop(proto,None) # ... no, remove protocol data from node

Expand All @@ -298,12 +298,11 @@ def remove_unused_igp(node: Box, proto: str, warning: bool = False) -> bool:
return False # ... OK, we're good

node.module = [ m for m in node.module if m != proto ] # Makes no sense to keep it, remove the config module
if warning:
log.error(
f'{node.name} does not use {proto} on any non-loopback interface or VRF',
more_hints=f'It has been removed from the list of modules active on {node.name}',
category=Warning,
module=proto)
log.warning(
text=f'{node.name} does not use {proto} on any non-loopback interface or VRF',
more_hints=f'It has been removed from the list of modules active on {node.name}',
flag='inactive',
module=proto)

return True

Expand Down Expand Up @@ -459,15 +458,14 @@ def get_unique_router_ids(node: Box, proto: str, topology: Box) -> None:

if rid_pfx: # If we have a prefix, we also have a RID
vdata[proto].router_id = router_id # ... so set it and report the change
log.error(
f'router ID for VRF {vname} on node {node.name} was changed from {rid} to {vdata[proto].router_id}',
category=Warning,
log.warning(
text=f'router ID for VRF {vname} on node {node.name} was changed from {rid} to {vdata[proto].router_id}',
module=proto,
more_hints=f'Device {node.device} requires a unique router ID for each {proto} instance')
more_hints=f'Device {node.device} requires a unique router ID for each {proto} instance',
flag='changed_id')
else: # Ran out of RID pool, report another error
log.error(
f'Cannot change router ID for VRF {vname} on node {node.name}',
category=Warning,
log.warning(
text=f'Cannot change router ID for VRF {vname} on node {node.name}',
module=proto)

"""
Expand Down Expand Up @@ -727,7 +725,7 @@ def igp_post_transform(
if propagate is not None:
propagate(node,topology)

if remove_unused_igp(node,proto,topology.defaults.get(f'{proto}.warnings.inactive',False)):
if remove_unused_igp(node,proto):
return

process_imports(node,proto,topology,['bgp','connected'])
Expand Down
9 changes: 5 additions & 4 deletions netsim/modules/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,12 @@ def build_ibgp_sessions(node: Box, sessions: Box, topology: Box) -> None:
break

if ibgp_warning:
log.error(
f'Node {node.name} has IBGP sessions but no IGP',
category=Warning,
igp_text = f'({", ".join(igp_list)})'
log.warning(
text=f'Node {node.name} has IBGP sessions but no IGP',
module='bgp',
hint='igp')
flag='missing_igp',
more_hints=[ f'Add a supported IGP {igp_text} to the list of modules' ])

"""
build_ebgp_sessions: create EBGP session data structure
Expand Down
2 changes: 1 addition & 1 deletion netsim/modules/bgp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ features:
import: Import routes from other routing protocols
warnings:
missing_igp: True
igp_list: [ ospf, eigrp, isis ]
igp_list: [ ospf, eigrp, isis, ripv2 ]
24 changes: 12 additions & 12 deletions netsim/modules/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import typing
from box import Box

from . import _Module,get_effective_module_attribute
from . import _Module,get_effective_module_attribute,remove_module
from ..utils import log, strings
from .. import data
from ..augment.nodes import reserve_id
Expand Down Expand Up @@ -171,10 +171,10 @@ def link_pre_link_transform(self, link: Box, topology: Box) -> None:
continue # ... sure, I can do that ;)
if 'gateway' in link: # Do we already have 'gateway' on link?
if link.gateway is False: # If we have 'gateway:false' we're dealing with a stupidity
log.error(
'Interface gateway attribute ignored due to gateway:false configured on the link',
log.warning(
text='Interface gateway attribute ignored due to gateway:false configured on the link',
more_data=f'Link {link._linkname} node {intf.node}',
category=Warning,
flag='no_gateway',
module='gateway')
intf.pop('gateway',None)
else:
Expand Down Expand Up @@ -260,12 +260,12 @@ def node_post_transform(self, node: Box, topology: Box) -> None:
if not k in active_proto: # Not a parameter for a FHRP active on this node?
node.gateway.pop(k,None) # ... zap it!

if not active_proto:
if topology.defaults.get('gateway.warnings.inactive',False):
log.error(
f"Node {node.name} does not use any FHRP technology, removing 'gateway' from node modules",
category=Warning,
module='gateway')
if active_proto:
return

log.warning(
text=f"Node {node.name} does not use any FHRP technology, removing 'gateway' from node modules",
flag='inactive',
module='gateway')

node.pop('gateway',None) # If not: Remove its configuration entirely
node.module = [ m for m in node.module if m != 'gateway' ] # and the module
remove_module(node,'gateway')
6 changes: 3 additions & 3 deletions netsim/modules/lag.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,10 +445,10 @@ def node_post_transform(self, node: Box, topology: Box) -> None:
i.lag = node_atts + i.lag # Merge node level settings with interface overrides

if 'mode' in i.lag:
log.error(f'lag.mode {i.lag.mode} used by node {node.name} is deprecated, use only 802.3ad',
category=Warning,
log.warning(
text=f'lag.mode {i.lag.mode} used by node {node.name} is deprecated, use only 802.3ad',
module='lag')
if i.lag.mode!='802.3ad':
if i.lag.mode != '802.3ad':
i.lag.lacp = 'off' # Disable LACP for other modes

linkindex = i.pop('linkindex',None) # Remove linkindex (copied from link that no longer exists)
Expand Down
5 changes: 2 additions & 3 deletions netsim/modules/vlan.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,9 @@ def validate_link_vlan_attributes(link: Box,v_attr: Box,topology: Box) -> bool:

if len(v_attr.access.set) > 1:
set_txt = ','.join(set(v_attr.access.set))
log.error(
f"Using more than one access VLAN per link is not supported",
log.warning(
text=f"Using more than one access VLAN per link is not supported",
more_data=f"Link {link._linkname}, access VLANs: {set_txt}",
category=Warning,
module='vlan')

link_ok = True
Expand Down
17 changes: 8 additions & 9 deletions netsim/modules/vrf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import netaddr
from box import Box

from . import _Module,_routing,_dataplane,get_effective_module_attribute
from . import _Module,_routing,_dataplane,get_effective_module_attribute,remove_module
from ..utils import log
from .. import data
from ..data import global_vars
Expand Down Expand Up @@ -514,16 +514,15 @@ def node_post_transform(self, node: Box, topology: Box) -> None:

# Do we have any need for the VRF module?
if not vrf_count:
if topology.defaults.get('vrf.warnings.inactive',False):
log.error(
f"Node {node.name} uses no VRFs, removing 'vrf' from node modules",
category=Warning,
module='vrf',
hint='inactive')
log.warning(
text=f"Node {node.name} uses no VRFs, removing 'vrf' from node modules",
module='vrf',
flag='inactive',
hint='inactive')

# Remove VRF module from the node if the node has no VRFs, unless the vrf.keep_module flag is set
if not features.get('vrf.keep_module',False):
node.module = [ m for m in node.module if m != 'vrf' ]
node.pop('vrfs',None)
remove_module(node,'vrf',['vrfs'])

return

Expand Down
6 changes: 3 additions & 3 deletions netsim/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ def select_primary_provider(topology: Box) -> None:
if not 'provider' in ndata:
ndata.provider = p_default

log.error(
f'Topology provider changed from {p_default} to {p_top}. Nodes are not affected',
category=Warning,
log.warning(
text=f'Topology provider changed from {p_default} to {p_top}. Nodes are not affected',
flag='providers.change',
module='providers')

"""
Expand Down
7 changes: 2 additions & 5 deletions netsim/providers/libvirt.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,8 @@ def create_vagrant_network(topology: typing.Optional[Box] = None) -> None:
['vagrant','status','--machine-readable'],check_result=True,ignore_errors=True,return_stdout=True)

if isinstance(v_status,str) and ('state,running' in v_status):
log.error(
f'Vagrant virtual machines are already running, skipping the management network setup',
category=Warning,
skip_header=True,
module='libvirt')
log.warning(
text=f'Vagrant virtual machines are already running, skipping the management network setup')
return

mgmt_net = topology.addressing.mgmt._network if topology is not None else ''
Expand Down
Loading
Loading