If you need to use a particular piece of code frequently, you can organize it into commands. These commands are executed by calling ./noc <command_name>.
For instance, to display the version, you can use the command ./noc about, which is located in the commands/about.py file.
The BaseCommand.print() function is used to print output to stdout when developing custom commands. It is recommended to always use this function instead of the built-in print() function within your commands.
In this case, we are using it to print the version information.
As an example, we will extract the code for checking configured metrics into a command. We will add the ability to pass a list of metrics as parameters. The code will be placed in the commands/check-metrics.py file.
We check if command line parameters are provided ( option["metrics"] ), and if not, we call the BaseCommand.die() function. The die() function prints an error message to stderr and terminates the command with a system error code.
We need to retrieve the object (database record) by its name. In NOC, to fetch a record by name, model methods like .get_by_name() are used. In addition to simplifying the code, .get_by_name() also provides caching, which can significantly enhance performance.
If the record is not found, .get_by_name() returns None. We use the check for None to ensure that the user has provided the correct metric name. If the user has provided an incorrect name, we print an error message and move on to processing the next metric.
At this point, we check if the metric scope is Interface. If it is, we add the metric to the iface_metrics list; otherwise, we add it to object_metrics.
If the user has provided at least one interface metric, we call the check_interface_metrics function and pass the interface_metrics list as a parameter.
check-metrics.py
38394041424344454647484950
mt_check:dict[str,MetricType]={str(mt.id):mtformtinmetrics}formopinManagedObjectProfile.objects.filter(enable_periodic_discovery_metrics=True,enable_periodic_discovery=True):checks=set(mt_check)formcinmop.metrics:ifmc["metric_type"]inchecks:checks.remove(mc["metric_type"])ifchecks:self.print(f"[{mop.name}] Not configured metrics: ",",".join(mt_check[c].nameforcinchecks),)
Now, let's define the check_object_metrics function, which takes a list of object metrics as input.
check-metrics.py
38394041424344454647484950
mt_check:dict[str,MetricType]={str(mt.id):mtformtinmetrics}formopinManagedObjectProfile.objects.filter(enable_periodic_discovery_metrics=True,enable_periodic_discovery=True):checks=set(mt_check)formcinmop.metrics:ifmc["metric_type"]inchecks:checks.remove(mc["metric_type"])ifchecks:self.print(f"[{mop.name}] Not configured metrics: ",",".join(mt_check[c].nameforcinchecks),)
We build a dictionary mt_check, where the metric ID is used as the key, and the metric object is stored as the value.
check-metrics.py
38394041424344454647484950
mt_check:dict[str,MetricType]={str(mt.id):mtformtinmetrics}formopinManagedObjectProfile.objects.filter(enable_periodic_discovery_metrics=True,enable_periodic_discovery=True):checks=set(mt_check)formcinmop.metrics:ifmc["metric_type"]inchecks:checks.remove(mc["metric_type"])ifchecks:self.print(f"[{mop.name}] Not configured metrics: ",",".join(mt_check[c].nameforcinchecks),)
We retrieve all object profiles where periodic discovery is enabled and metrics are defined.
check-metrics.py
38394041424344454647484950
mt_check:dict[str,MetricType]={str(mt.id):mtformtinmetrics}formopinManagedObjectProfile.objects.filter(enable_periodic_discovery_metrics=True,enable_periodic_discovery=True):checks=set(mt_check)formcinmop.metrics:ifmc["metric_type"]inchecks:checks.remove(mc["metric_type"])ifchecks:self.print(f"[{mop.name}] Not configured metrics: ",",".join(mt_check[c].nameforcinchecks),)
We create a set check based on the keys in mt_check. In the future, we will remove the discovered metrics from it.
check-metrics.py
38394041424344454647484950
mt_check:dict[str,MetricType]={str(mt.id):mtformtinmetrics}formopinManagedObjectProfile.objects.filter(enable_periodic_discovery_metrics=True,enable_periodic_discovery=True):checks=set(mt_check)formcinmop.metrics:ifmc["metric_type"]inchecks:checks.remove(mc["metric_type"])ifchecks:self.print(f"[{mop.name}] Not configured metrics: ",",".join(mt_check[c].nameforcinchecks),)
We iterate through all the metrics defined in the profile and, if they are present in our check, we remove them from the check set.
check-metrics.py
38394041424344454647484950
mt_check:dict[str,MetricType]={str(mt.id):mtformtinmetrics}formopinManagedObjectProfile.objects.filter(enable_periodic_discovery_metrics=True,enable_periodic_discovery=True):checks=set(mt_check)formcinmop.metrics:ifmc["metric_type"]inchecks:checks.remove(mc["metric_type"])ifchecks:self.print(f"[{mop.name}] Not configured metrics: ",",".join(mt_check[c].nameforcinchecks),)
If there are remaining metrics in our check set, we write a message stating that they are not configured for the profile.
check-metrics.py
535455565758596061
foripinInterfaceProfile.objects.filter(metrics__exists=True):checks=set(metrics)formcinip.metrics:ifmc.metric_typeinchecks:checks.remove(mc.metric_type)ifchecks:self.print(f"[{ip.name}] Not configured metrics: ",",".join(c.nameforcinchecks))
Now, let's define the check_interface_metrics function, which takes a list of interface metrics as input.
check-metrics.py
545556575859606162
foripinInterfaceProfile.objects.filter(metrics__exists=True):checks=set(metrics)formcinip.metrics:ifmc.metric_typeinchecks:checks.remove(mc.metric_type)ifchecks:self.print(f"[{ip.name}] Not configured metrics: ",",".join(c.nameforcinchecks))
Now, let's define the check_interface_metrics function, which takes a list of interface metrics as input.
check-metrics.py
545556575859606162
foripinInterfaceProfile.objects.filter(metrics__exists=True):checks=set(metrics)formcinip.metrics:ifmc.metric_typeinchecks:checks.remove(mc.metric_type)ifchecks:self.print(f"[{ip.name}] Not configured metrics: ",",".join(c.nameforcinchecks))
We create a set check from all the input function parameters.
check-metrics.py
545556575859606162
foripinInterfaceProfile.objects.filter(metrics__exists=True):checks=set(metrics)formcinip.metrics:ifmc.metric_typeinchecks:checks.remove(mc.metric_type)ifchecks:self.print(f"[{ip.name}] Not configured metrics: ",",".join(c.nameforcinchecks))
We iterate through the metrics defined in the profile, and if they are present in our check, we remove them from the check set.
check-metrics.py
545556575859606162
foripinInterfaceProfile.objects.filter(metrics__exists=True):checks=set(metrics)formcinip.metrics:ifmc.metric_typeinchecks:checks.remove(mc.metric_type)ifchecks:self.print(f"[{ip.name}] Not configured metrics: ",",".join(c.nameforcinchecks))
If there are remaining metrics in our check set, we write a message stating that they are not configured for the profile.
check-metrics.py
65
Command().run()
This part of the code is common to all commands and is responsible for running our command from the command line.