Apache ACE is a system that can be used to provision software to OSGi based and other targets. It manages the life cycle of bundles and provides a controlled, centralized way to install, update and uninstall software and related artifacts such as configuration data, native code and device firmware.
Purpose and scope
The purpose of this document is to provide a comprehensive overview of the software architecture of the system. It uses a number of different views to depict the important aspects of the system and captures and conveys the significant architectural decisions which have been made on the system.
It serves three purposes:
- Abstraction of the system. The architecture provides a relatively small, intellectually graspable model of how the system is structured and how components interact.
- Mutual communication. The model described here forms the common basis for all of the stakeholders to communicate with each other and form consensus about the system.
- Major design decisions. The description of the architecture represents the earliest set of design decisions that have a significant impact on the system as a whole. They are relevant to ensure the qualities and features of the architecture.
The document starts with an introduction, outlining the scope and purpose of this document and defining some acronyms and abbreviations. It then goes on by first sketching the architectural context, exploring the domain and the constraints. That is followed by the architectural design, which uses the 4+1 view as a guide to describe the system.
All stakeholders should read the architectural context, as it explains what the system does and how it interacts with its surroundings.
Software engineers in particular should read the architectural design, which outlines the foundation and describes the high level design that forms the basis for further analysis and design.
Definitions, acronyms and abbreviations
|OSGi||The OSGi alliance is an independent non-profit organization that maintains the OSGi standard. OSGi technology provides a service-oriented, component-based environment for developers and offers standardized ways to manage the software life cycle.|
|Provisioning||Software provisioning is the process of installing and updating software.|
|Target||A target, or OSGi gateway, is a computer or device that has an OSGi framework installed.|
|REST||Representational State Transfer (REST) is a style of software architecture for distributed hypermedia systems. The term was introduced in the doctoral dissertation in 2000 by Roy Fielding, one of the principal authors of the Hypertext Transfer Protocol (HTTP) specification, and has come into widespread use in the networking community.|
|JMX||Java Management Extensions provides the tools for building distributed, web-based, modular and dynamic solutions for managing and monitoring devices, applications and service-driven networks. Since Java 5, it is part of the Java SE platform.|
|SOAP||SOAP is a protocol for exchanging XML-based messages over computer networks, normally using HTTP/HTTPS. SOAP forms the foundation layer of the Web services stack, providing a basic messaging framework that more abstract layers can build on.|
|DIY||An acronym for "do it yourself".|
The system consists of the following domains, as shown in the picture below.
On the left hand side, the user interface and dependency repository are shown. The dependency repository, sometimes referred to in an analogy as the "shop", is mainly concerned with the dependency management domain, effectively linking artifacts to targets through various mechanisms of grouping and filtering based on requirements and capabilities of the individual artifacts.
On the right hand side, the deployment aspect deals with the actual provisioning of versioned sets of artifacts to targets.
Finally, on the target itself, the life cycle is monitored and managed by the management agent.
The OBR does not need to be a part of our system, but it is used both in the dependency and deployment domain.
The lower part of the image deals with feedback. Feedback is responsible for providing historic data of all changes to the actual life cycle of the target, which is collected in the audit log and synchronized back to the server.
Whenever you are dealing with collections of artifacts, you want to start grouping them to form logical subsystems. Doing this makes the artifacts more manageable by users that are not intimately familiar with the architecture of the software components that are being deployed.
As an analogy, we often use the example of IKEA. They create modular furniture, and sell their modules in configurations that make sense to their users. You can order a cupboard that consists of planks, screws and doors, and they give those configurations names. Apache ACE pretty much allows you to do the same thing, which is why we like the "shop" analogy. In ACE we group our artifacts into named distributions, and users can install one or more of these onto a target.
When installing artifacts together, we also need to make sure this collection actually works together. Each bundle can have dependencies on other bundles, services, packages or even specific hardware or operating systems. These dependencies all need to be managed.
Within an OSGi framework, there are two layers that feature dependencies:
- the module layer, that has package dependencies;
- the service layer, that has service dependencies.
Traditionally, in OSGi, a bundle contains enough meta-data to analyze package dependencies and ensure that these can be resolved. Service dependencies, however, are a lot harder to analyze because of the extremely dynamic nature of a service and the fact that there is no meta-data available. Also, modern dependency management frameworks can express dependencies on more than just services, allowing users to have configuration dependencies or even custom dependencies like a dependency on the time of day.
For other dependencies, such as required screen sizes, or the presence of specific hardware, no meta-data is available in the bundle, so that is one thing we need to add externally.
Summing it up, it is important to make sure that you first of all have a clear overview of the artifacts and their different deployable distributions and secondly that you end up deploying sets of artifacts that work together well in the environments in which they're deployed.
In short, deployment is responsible for getting software artifacts onto target systems. The general strategy is to have a management agent on each OSGi based target that receives and deploys these artifacts.
An important aspect of deployment is the actual distribution of artifacts. The provisioning server takes an OBR as its source and artifacts somehow need to find a way to the targets. In real-life scenarios, there often won't be a completely open, two way connection between server and target, so catering for all kinds of scenarios here is important.
Life cycle management
Life cycle management deals with managing the life cycle of artifacts within the OSGi based target.
The management agent is responsible for managing these life cycles, when to update and even to figure out what update strategy to implement. The management agent is also responsible for monitoring any changes and reporting those back via the audit log (see "Feedback" below).
Different types of artifacts might have different life cycles. From a provisioning point of view, each artifact is either present on a target or it is not. Bundles have a more extensive life cycle, where the following states can be identified:
The following state diagram shows these states and their transitions:
The transitions are explained below:
- install - Each bundle starts its life cycle when it is first installed in the OSGi framework. When a bundle is installed it is stored persistently in the framework.
- start - As soon as the bundle is started, it will transition through a couple of states. The first step is the resolving of package dependencies. Here the bundle is "wired up" and if that succeeds, it ends up in the resolved state. From there it will go to starting, where the bundle activator gets instantiated and a bundle can become an active entity (it can start threads, initialize, etc.). Finally it ends up in the active state.
- update - As soon as a bundle is installed, it can be updated. When a bundle is updated, if it was active, it will be stopped. Subsequently it will have to be resolved again, and started.
- stop - When a bundle is active, it can be stopped. It will first go to the stopping state, where it will have to cleanup (basically undo everything it did during starting). It will end up as resolved.
- uninstall - When a bundle is no longer needed, it can be uninstalled. That's a final state, from there it can never be started again.
Feedback is responsible for collecting log data and synchronizing it back to the server. By default, all life cycle data is collected in the audit log. This mechanism is extensible and can support domain specific extensions.
An audit log is a full historic account of all events that are relevant for a certain target. In this case, it provides historic data of all changes to the actual life cycle of the target, both triggered by the management agent and by other mechanisms on the target (for example, it also shows when the framework itself was started and stopped).