It is possible to specify nested lockHost steps. You can also specify a lockingMode attribute for each nested lockHost step:
1st group of steps
<lockHost lockingMode="PHYSICAL">
2nd nested group of steps
<lockHost lockingMode="VIRTUAL">
3rd nested group of steps
</lockHost>
4th nested group of steps
</lockHost>
5th nested group of steps
In the above example, no hosts are locked for the 1st group of steps, since there are no locks: the lockHost step has not been used.
Only the physical host is locked for 2nd group of steps, because the lockHost step has been used with the lockingMode attribute set to PHYSICAL.
Both the physical and the virtual host are locked for the 3rd group of steps, because a lockHost step has been used with the lockingMode attribute set to VIRTUAL and the physical lock has not yet been closed.
Only the physical host is locked for 4th group of steps, because the virtual lock has been closed. No hosts are locked for the 5th group of steps, because the physical lock has now been closed.
Here is a simple example of the lockHost step:
<simpleSteps implicitLocking="false">
<pause delaySecs="1"/>
<lockHost>
<pause delaySecs="1"/>
</lockHost>
</simpleSteps>
Note that implicitLocking is set to false. To lock the host in the above simple example, the lockHost step would therefore be required. Since the lockingMode attribute is omitted, both the physical host and any virtual host are locked, if the plan is executed on a virtual host. If the plan is executed on a physical host, the physical host only would be locked as there is no virtual host to lock.
Here is a more complex example of the lockHost step including a retargeted step:
<simpleSteps implicitLocking="false">
<pause delaySecs="1"/>
<lockHost lockingMode="VIRTUAL">
<pause delaySecs="1"/>
<retarget host="newhost">
<pause delaySecs="2"/>
</retarget>
</lockHost>
<pause delaySecs="3"/>
</simpleSteps>
In this example:
implicitLocking is set to false, so if the plan is executed on host1, neither newhost nor host1 are locked initially.
When the lockHost step is executed, host1 is locked. The first pause step is executed before host1 is locked.
If host1 is already locked, the plan does not act on host1 until host1 becomes available.
newhost is locked when the retarget step is executed. The lock on host1 is not released, so both hosts are now locked. If locking newhost would result in a deadlock, then an error is thrown. Depending in the configuration, the error message is either Deadlock detected when initial host X tried locking host Y. That lock is already held by host Z or Locking the host results in a deadlock
The lock on newhost is released on completion of the retarget step.
The lock on host1 is released on completion of the lockHost step.
The 1 second and 3 second pause steps are executed on an unlocked host; the 2 second pause step is executed on a locked host.
The lockingMode is set to VIRTUAL, so only the virtual host to which the retarget step is aimed is locked.
Contrast the above example with this:
<simpleSteps implicitLocking="false">
<pause delaySecs="1"/>
<pause delaySecs="1"/>
<retarget host="newhost">
<lockHost>
<pause delaySecs="2"/>
</lockHost>
</retarget>
<pause delaySecs="3"/>
</simpleSteps>
Here, only newhost is locked, and only on the execution of the lockHost step inside the retarget step. The retargeted host is not locked when the retarget step is executed. Only the 2 second pause step is executed on a locked host.
For clarity, several mandatory component attributes are omitted from this example.
<component name="comp1"...>
<installList>
<installSteps name="installA">
<pause delaySecs="1">
</installSteps>
</installList>
</component>
The installA installSteps element does not specify the requireLocking attribute. The requireLocking attribute is therefore set to true, by default. Executing the following plan would therefore cause a preflight error:
<simpleSteps implicitLocking="false">
<install blockName="installA">
<component path="/" name="comp1"/>
</install>
</simpleSteps>
The plan indicates that locking should be disabled by specifying the implicitLocking attribute with a value of false. The plan attempts to operate on a component using a block that requires locking without locking the host. The install block executed by the plan does not specify the lockingMode attribute, which means that the block requires the host to be locked upon execution. The plan could be changed to explicitly lock the host before installing the component:
<simpleSteps implicitLocking="false">
<lockHost>
<install blockName="installA">
<component path="/" name="comp1"/>
</install>
</lockHost>
</simpleSteps>
Here is an simplified sample of a component that does not always require the host to be locked:
<component name="comp2"...>
<installList>
<installSteps name="installA" requireLocking="false">
<pause delaySecs="1">
</installSteps>
<uninstallSteps name="uninstallB" requireLocking="true">
<pause delaySecs="1">
</uninstallSteps>
<control name="controlC">
<pause delaySecs="1">
</control>
</installList>
</component>
In the above simplified sample:
The install block, installA, does not require the host to be locked
uninstallB and controlC both require the host to be locked. uninstallB states the explicit requirement while controlC does not, but the default value if unspecified is true.
The following plan is provides an example of legal operation with this component:
<simpleSteps implicitLocking="false">
<install blockName="installA">
<component path="/" name="comp1"/>
</install>
<lockHost>
<call blockName="controlC">
<installedComponent path="/" name="comp1" =installPath="/tmp"/>
</call>
<uninstall blockName="uninstallB">
<installedComponent name="comp1"/>
</uninstall>
</lockHost>
</simpleSteps>
A component block that does not require the host to be locked can be called while the host is locked; the install step above could legally be moved inside the lockHost step. Neither the uninstall nor the call, however, could be moved outside the lockHost step.