|
| 1 | +.. _sticky-modules-rcp: |
| 2 | + |
| 3 | +Sticky modules |
| 4 | +============== |
| 5 | + |
| 6 | +When providing a configurable environment to users, site's staff may require |
| 7 | +that some part of this environment remain loaded whatever the user does. |
| 8 | + |
| 9 | +Such feature is for instance useful when every details of the user environment |
| 10 | +are configured through the use of modulefiles. Even the core setup that is |
| 11 | +usually configured through the :file:`/etc/profile.d` initialization scripts. |
| 12 | +But by using modulefiles for core initialization, end users can fully see how |
| 13 | +things are setup on their environment by using |
| 14 | +:subcmd:`module display<display>`. When the environment core setup is achieved |
| 15 | +by loading a specific modulefile, it is important that such module remains |
| 16 | +loaded to keep this initial setup on whatever the module actions the user |
| 17 | +performs over its environment. |
| 18 | + |
| 19 | +This recipe describes how to keep modulefiles loaded by forbidding their |
| 20 | +unload. Such unloadable modules are called *sticky modules*. |
| 21 | + |
| 22 | +Implementation |
| 23 | +-------------- |
| 24 | + |
| 25 | +:ref:`Sticky modules` are simply modules that cannot be unloaded once loaded. |
| 26 | +Such behavior could be achieved by basically breaking the modulefile |
| 27 | +evaluation when attempting to unload the sticky module: |
| 28 | + |
| 29 | +.. code-block:: tcl |
| 30 | +
|
| 31 | + if {[module-info mode unload]} { |
| 32 | + break |
| 33 | + } |
| 34 | +
|
| 35 | +Using the ``break`` Tcl command to stop the modulefile evaluation does not |
| 36 | +require to install a recent version of Modules to get a basic sticky |
| 37 | +mechanism. |
| 38 | + |
| 39 | +To get a smoother sticky mechanism with two different level of stickyness, |
| 40 | +allowing to reload environment or to swap a sticky module by another |
| 41 | +version of the same module name, the *sticky* and *super-sticky* module tags |
| 42 | +have been introduced in Modules v4.7. |
| 43 | + |
| 44 | +A modulefile is declared *sticky* by applying it the ``sticky`` tag with the |
| 45 | +:mfcmd:`module-tag` modulefile command. Such sticky module cannot be unloaded, |
| 46 | +unless if the unload action is forced or if the module reloads after being |
| 47 | +unloaded. |
| 48 | + |
| 49 | +Modulefile can also be defined ``super-sticky`` by applying the corresponding |
| 50 | +module tag. *Super-sticky* module cannot be unloaded even if the unload action |
| 51 | +is forced. It can only be unloaded if the module reloads afterward. |
| 52 | + |
| 53 | +In case the stickyness applies to the generic module name (and does not target |
| 54 | +a specific module version or version-set), one version of the sticky or |
| 55 | +super-sticky module can be swapped by another version of this same module. |
| 56 | + |
| 57 | +**Compatible with Modules v4.7+** |
| 58 | + |
| 59 | +Usage examples |
| 60 | +-------------- |
| 61 | + |
| 62 | +For this recipe, a *core* module acts as the initial setup of user's |
| 63 | +environment. This module must not be unloaded otherwise user's environment may |
| 64 | +be considered broken. |
| 65 | + |
| 66 | +So this *core* module is tagged *super-sticky* with the :mfcmd:`module-tag` |
| 67 | +modulefile command in :file:`core/.modulerc` file: |
| 68 | + |
| 69 | +.. code-block:: tcl |
| 70 | +
|
| 71 | + module-tag super-sticky core |
| 72 | +
|
| 73 | +Once module got loaded, it cannot be unloaded even if these unload actions are |
| 74 | +forced. |
| 75 | + |
| 76 | +.. parsed-literal:: |
| 77 | +
|
| 78 | + :ps:`$` module list |
| 79 | + Currently Loaded Modulefiles: |
| 80 | + 1) :sgrss:`core/1.0` |
| 81 | +
|
| 82 | + Key: |
| 83 | + :sgrss:`super-sticky` |
| 84 | + :ps:`$` module unload core |
| 85 | + Unloading :sgrhi:`core/1.0` |
| 86 | + :sgrer:`ERROR`: Unload of super-sticky module 'core/1.0' skipped |
| 87 | + :ps:`$` module purge -f |
| 88 | + Unloading :sgrhi:`core/1.0` |
| 89 | + :sgrer:`ERROR`: Unload of super-sticky module 'core/1.0' skipped |
| 90 | + :ps:`$` module list |
| 91 | + Currently Loaded Modulefiles: |
| 92 | + 1) :sgrss:`core/1.0` |
| 93 | +
|
| 94 | + Key: |
| 95 | + :sgrss:`super-sticky` |
| 96 | +
|
| 97 | +However it is still possible to change version of this *super-sticky* module. |
| 98 | + |
| 99 | +.. parsed-literal:: |
| 100 | +
|
| 101 | + :ps:`$` module switch core/2.0 |
| 102 | + :ps:`$` module list |
| 103 | + Currently Loaded Modulefiles: |
| 104 | + 1) :sgrss:`core/2.0` |
| 105 | +
|
| 106 | + Key: |
| 107 | + :sgrss:`super-sticky` |
| 108 | +
|
| 109 | +In this recipe environment, the *compiler* module provides several flavors: |
| 110 | +*compA* and *compB*. Site's staff have decided that user's environment should |
| 111 | +always have a compiler module loaded by default. |
| 112 | + |
| 113 | +So the *compiler* module is set *sticky* with the :mfcmd:`module-tag` |
| 114 | +modulefile command in :file:`compiler/.modulerc` file: |
| 115 | + |
| 116 | +.. code-block:: tcl |
| 117 | +
|
| 118 | + module-tag sticky compiler |
| 119 | +
|
| 120 | +As stickyness is defined over the generic *compiler* name, users can switch |
| 121 | +between available compiler flavors: |
| 122 | + |
| 123 | +.. parsed-literal:: |
| 124 | +
|
| 125 | + :ps:`$` module list |
| 126 | + Currently Loaded Modulefiles: |
| 127 | + 1) :sgrss:`core/2.0` 2) :sgrs:`compiler/compB/2.1` |
| 128 | +
|
| 129 | + Key: |
| 130 | + :sgrss:`super-sticky` :sgrs:`sticky` |
| 131 | + :ps:`$` module switch compiler/compA |
| 132 | + :ps:`$` module list |
| 133 | + Currently Loaded Modulefiles: |
| 134 | + 1) :sgrss:`core/2.0` 2) :sgrs:`compiler/compA/1.2` |
| 135 | +
|
| 136 | + Key: |
| 137 | + :sgrss:`super-sticky` :sgrs:`sticky` |
| 138 | +
|
| 139 | +Unload attempt fails by default: |
| 140 | + |
| 141 | +.. parsed-literal:: |
| 142 | +
|
| 143 | + :ps:`$` module unload compiler |
| 144 | + Unloading :sgrhi:`compiler/compA/1.2` |
| 145 | + :sgrer:`ERROR`: Unload of sticky module 'compiler/compA/1.2' skipped |
| 146 | +
|
| 147 | +However if a user really wants to get rid of the *compiler* module, the unload |
| 148 | +action can be forced: |
| 149 | + |
| 150 | +.. parsed-literal:: |
| 151 | +
|
| 152 | + :ps:`$` module unload -f compiler |
| 153 | + Unloading :sgrhi:`compiler/compA/1.2` |
| 154 | + :sgrwa:`WARNING`: Unload of sticky module 'compiler/compA/1.2' forced |
| 155 | + :ps:`$` module list |
| 156 | + Currently Loaded Modulefiles: |
| 157 | + 1) :sgrss:`core/2.0` |
| 158 | +
|
| 159 | + Key: |
| 160 | + :sgrss:`super-sticky` |
| 161 | +
|
| 162 | +Last but not least, the sticky modules should get loaded when the user's shell |
| 163 | +session initializes. So the *core* and *compiler* modules should be defined |
| 164 | +for load in the initialization RC file |file etcdir_initrc|: |
| 165 | + |
| 166 | +.. code-block:: tcl |
| 167 | +
|
| 168 | + #%Module |
| 169 | + module use --append .../example/sticky-modules/modulefiles |
| 170 | + module load core |
| 171 | + module load compiler/compB |
0 commit comments