The agent is the part of fabric that is responsible for applying the profiles to containers. The agent can be run into any container and its role is to retrieve profile information from the registry and apply them locally. In more details, the agent will retrieve the profiles and versions that are assigned to the container on which its running, reconfigure the container, calculate what needs to be installed, removed or updated on the container and finally perform those task.
In reality there are two modules involved in the process:
Often the term agent refers to just the deployment agent (fabric-agent module), but this section of the documentation will cover both and provide detailed information about the role of each one of them.
The configuration admin bridge is responsible for bridging the zookeeper registry with the configuration admin service. Once it connects to the zookeeper registry it will determine what version is assigned to the container, retrieve the version of profiles that are assigned to the container and translate them into configuration, which is then applied locally.
Note, that the profile contain two types of information:
The configuration admin bridge will read all of them and create the OSGi configuration that represents them. All the provisioning & system information will go under the org.fusesource.fabric.agent pid. For containers that are assigned multiple profiles, or just use the profile hierarchy the overlay view of the profiles will be added to org.fusesource.fabric.agent (There is a single pid even if we have multiple profiles).
All the OSGi configuration will just you the pid and key value pairs that have been added to the profile.
The bridge will also watch the registry for changes, so any change in the profiles that are assigned to the container will be tracked and will immediately be applied to the local OSGi configuration of the container.
The deployment agent is listening for local configuration changes on the org.fusesource.fabric.agent pid. Any change in that configuration will trigger the deployment agent. Once the deployment agent is triggered, it will read the whole org.fusesource.fabric.agent pid and calculate the bundles that the container should have installed. If the profiles assigned to the container also contain features or fabs, the deployment agent will translate them to bundles in order to populate a full list of bundles that the container should use. The next action of the deployment agent is to compare that list of bundles, with the list of bundles that are currently installed, in order to identify:
Finally, it downloads all the missing parts and perform the installation / uninstallation of bundles.
The deployment agent is capable of downloading artifacts from two different types of maven repositories:
Priority is always give to the fabric maven proxies. If more than one is registered in the cluster they will be used in order from the oldest to the newest.
If the target artifact is not found, then the configured maven repositories will be used. The list of repositories can be retrieved from the org.ops4j.pax.url.mvn.repositories property of the org.fusesource.fabric.agent pid.
To change that list of repositories for a specific profile you can simply, you the fabric:profile-edit command:
fabric:profile-edit --pid org.fusesource.fabric.agent/org.ops4j.pax.url.mvn.repositories=http://repositorymanager.mylocalnetwork.net default
It is suggested to keep this configuration in one profile and have the rest of profiles inherit from it. The default profile, which is the root of all of the default profiles, seems the ideal place.
It is important to clarify that during the process the container is kept alive, no restarts are needed. The only exception in this rule is when changing things that are related to the osgi framework or the system itself.
So, in most cases the container will be kept alive, since those exceptions are extremely rare. Even when the container will need a restart, that will be done automatically by the deployment agent and after the restart the container will reconnect to the cluster without any manual intervention.
Through the whole process of the deployment / provisioning, the deployment agent will store the state in the runtime registry, so that its available to the whole cluster.
The user is able at any time to see that status using the fabric:container-list command.
fabric:container-list
[id] [version] [alive] [profiles] [provision status]
root* 1.0 true fabric, fabric-ensemble-0000-1 success
mq1 1.0 true mq success
mq2 1.0 true mq downloading
billing-broker 1.0 true billing success
admin-console 1.0 true web, admin-console success
To have a real time view of the provisioning status, you can make use of the shell:watch, as described bellow
shell:watch fabric:container-list
Here is a small clip that demonstrates the use of the fabric:container-list while the containers are changing profiles and the deployment againsts starts provisioning.
In order to successfully determine what needs to be installed and what needs to be removed, the fabric-agent will use the OBR resolver. The resolver will make sure that all requirements are meet. The requirements are usually package requirements but can also be service requirements. The resolver will use the bundle headers to identify both:
The last point is really important, because blueprint users the have mandatory references of services in their blueprint descriptor, will automatically have the Import-Service headers in their bundle (assuming the use of maven-bundle-plugin). If the bundle that exports that service doesn't explicitly specify it in its headers, then resolution will fail. Either the exporter bundle will have to add an Export-Service directive or the importer bundle will have to remove the Import-Service directive.
When the resolution is successful the fabric-agent will start the bundles. Even though you should try to avoid having requirements in the startup order of your bundles, the fabric-agent will attempt to start the bundles based on their expressed requirements and capabilities. This will not solve all issues, especially in cases where asynchronous service registration is involved. The best way to deal with this kind of issues is to use OSGi services.