How to create a new generator¶
A generator takes the local base repository and it changes the OKS database to obtain the desired configuration. The scripts in this package will then commit the changes and create the configuration on the remote operation repository.
The generators are called automatically from the scripts of this package to create the corresponding configurations. So, creating a configuration is equivalent to write the corresponding generator.
Generator structure¶
Generators are stored in the base repo, as they are specific for the base that they have to work upon in order to create the necessary configuration.
Specifically, they are stored in the folder functions/generators directory in the subdirectory specific for the apparatus relevant for the generator.
Generators are python modules and are expected to be named with with <configuration_name>.py.
As the generators might be imported by other generators, their names cannot contain -.
Generators will have to contains a generate function with signature
def generate( path:str ) -> bool :
The generate function must return True once the generation is successfully completed.
Otherwise, it should return False or raise an exception.
In order to use the configutions in the base repository, some environmental variables need to be set.
This is usually done with the script setup_db_path.sh contained in the base.
While writing a generator, one should assume that those environmental variables are correctly setup and should not try to set them from the scripts.
Good practices¶
As the generator is a python script, one could do everything.
Yet it is recommended that the OKS database are managed through the OKS, conffwk or daqconf python interfaces/scripts which guarantess type safety.
One should not change the files using python open or other low level file editing tools.
It is also recommended that we limit the changes to the objects to just changing the references rather than the attributes of the objects. Although in some cases that might be unavoidable.
Generator testing¶
Generators should be tested before committing and before starting updating the operation repository. In order to test the generator, it is recommended that that the generator contains the block
if __name__ == '__main__':
generate(sys.argv[1])
So that the generator can be tested by simply executing
python my_generator.py /path/to/base
While developing, personal experience suggested that is quite useful to develop the generator by initially saving the file outside the local base git repository. In this way the chages made to the base by executing the generator can simply be reverted with a
(cd /path/to/base; git restore)
Validators¶
Similarly to the generate function, the same file can contain - but it's not mandatory - a
def validate( path:str ) -> bool :
generate function, this is called by the runconftools scripts.
The function must return True in case the configuration is found to be correct by the function, or False otherwise.
Common operations¶
It is possible to call other generators or common functions.
Common functions should be store in the base repository, in the directory functions/common.
As the function directory is added to the PYTHONPATH, one can invoke those functions just by importing.
For example:
import common.trigger
import generators.np02.monitoring_no_tpg
if __name__ == '__main__':
sys.path.append(sys.argv[1] + "/functions")
generate(sys.argv[1])
validate(sys.argv[1])
Example¶
import sys
import conffwk
import confmodel
import daqconf.enable as enable
def generate( path:str ) -> bool :
import common.np02.config_base as base
entry = base.get_entry_file(path)
session=base.get_session_name()
# enable all the det streams for the daphne
enable.enable(entry, False, ["np02-pds107-s00-sid50"], session)
db = base.get_database(path)
# change the daphne configuration
daphne_app = db.get_dal("DaphneApplication", "daphne-app")
daphne_conf = db.get_dal("DaphneConf", "full_mode_bias_off")
daphne_app.configuration = daphne_conf
db.update_dal(daphne_app)
# change the descriptor of the queue rule in the flx readout app
queue_rule = db.get_dal("QueueConnectionRule", "daphne-raw-data-rule")
queue_descriptor = db.get_dal("QueueDescriptor", "daphne-fullstream-raw-input")
queue_rule.descriptor=queue_descriptor
db.update_dal(queue_rule)
# change the link handler in the RU
readout_app = db.get_dal("ReadoutApplication", "runp02srv030flx4")
data_handler = db.get_dal("DataHandlerConf", "pds-handler-numa0-fullstream")
readout_app.link_handler = data_handler
db.update_dal(readout_app)
# Change the felix controller
flx_controller_app = db.get_dal("DaqApplication", "pds-felix")
full_stream_controller_module = db.get_dal("FelixCardControllerModule", "np02-pds-controller-fullstream")
flx_controller_app.modules=[full_stream_controller_module]
db.update_dal(flx_controller_app)
# change the protocol to full
flx_senders = db.get_dals("FelixDataSender")
for s in flx_senders :
s.protocol = "full"
db.update_dal(s)
db.commit()
return True
if __name__ == '__main__':
sys.path.append(sys.argv[1] + "/functions")
generate(sys.argv[1])
This is an example of a generator that uses both daqconf and conffwk scripts.
As you can see, most of the time, it is just changing the reference between the objects.
The only exception is the FelixDataSender class that it's part of the topology description of the connections.
Therefore its objects are not duplicated.
Last git commit to the markdown source of this page:
Author: MRiganSUSX
Date: Tue Apr 8 12:49:40 2025 +0200
If you see a problem with the documentation on this page, please file an Issue at https://github.com/DUNE-DAQ/runconftools/issues