Plug-ins

Plug-ins are delivered as a jar and contain modules and extensions as below.  A plug-in is merely a container for one or more modules.  Plug-ins do not exist as a first class object in the code, only the modules are.  The modules in the plug-in are discovered and loaded dynamically.

Modules

CloudStack is arranged into a series of modules that are in a hierarchical arrangement.  Depending on which modules are selected to load determines what extensions are loaded.  The above picture is used an example of modules but does not reflect the actual module hierarchy in CloudStack.

Implementation

Spring

The implementation of the modules is based on assembling a hierarchy of Spring application contexts.  With Spring each application context can have a parent.  Each module defines its own Spring XML configuration that will be loaded in its own application context.  Each module also specifies what is it's parent context.  From a Spring perspective, this means each module is isolated from its siblings.  This means that network element A can not pollute the application context of network element B.  Additionally this means that "plugins" will be isolated from core application contexts of CloudStack.  Thus if CloudStack core defines a bean "MyPoorlyNamedBean" and network element A defines a bean of the same name, network element A will not mess up the rest of the CloudStack by overriding that bean.  It could of course mess up itself though.

Module Life Cycle

The life cycle of the modules follows the Spring managed life cycle. Parent contexts are always initiated before the child contexts. Child contexts are destroyed before parent contexts are. All beans respect the standard JSR-250 life cycle annotations, @PreDestroy and @PostConstruct. While dynamic module loading is not in the initial scope of the first implementation, such a thing will be possible. If you wish to unload network element A, the Spring context for network element A will be stopped, initiating a context shutdown. Refer to "Plugin Discovery" for more information on how plugins are discovered and (un)registered.

Module Discovery

Modules are discovered and loaded based on classpath scanning. If a file META-INF/cloudstack/*/module.properties is found it is treated as a module. It will then find the rest of the configuration for that module. It will be automatically loaded.  Since module discovery is based on classpath scanning (basically looking up and finding URL's) this means modules could really be loaded from anywhere. So, for example, you could create CloudStack as a Java Web Start application, or even embedded in OSGi, or whatever.

Class Loader Management

Ideally each module should be loaded in its own class loader. This is completely feasible. The ModuleDefinitionLocator is responsible for discovering the modules and their respective class loaders. For the first implementation, we will focus on a simple strategy of assuming a single classloader.

Extension Management

Before spring modularization, plugins, adapters, gurus, widgets, or "whatever vague term you want" were registered through either modifying Spring XML or programmatic registration as part of the configure method. In the new module system this will all be consolidated to one mechanism that is truly decoupled and extensible. As modules are loaded the modules will be scanned for beans of pluggable types, like NetworkElement or Investigator. That bean will then be registered in a fashion that makes it available to the consumers of the pluggable types.

When a context is shutdown, the pluggable types will be shutdown and deregistered.

Sample Configuration

META-INF/cloudstack/mycomponent/module.properties

This is the main file that defines a module. The contents should be

name=mycomponent
parent=myparent

The name should match the directory it is in. It would be nice to discover the module name based on the directory, but unfortunately that isn't really possible if you truly want to respect the opaque nature of URLs in Java. The parent parameter is obviously the parent context

META-INF/cloudstack/mycomponet/*context.xml

Spring XML files for the component named "mycomponent" are expected to be found at META-INF/cloudstack/mycomponet/*context.xml. A module can define as many XML files as it chooses.

Hierarchy as of 4.3

Below is the actually hierarchy of modules in ACS 4.3

 bootstrap
   system
     core
       allocator
         host-allocator-random
         planner
           api-planner
           baremetal-planner
           explicit-dedication
           host-anti-affinity
           implicit-dedication
           server-planner
           user-concentrated-pod
         server-allocator
       api
         acl-static-role-based
         ldap
         md5
         plaintext
         rate-limit
         server-api
         sha256salted
       backend
         compute
           baremetal-compute
           kvm-compute
           ovm-compute
           server-alert-adapter-compute
           server-compute
           server-fencer
           server-investigator
           vmware-compute
           xenserver-compute
         network
           baremetal-network
           elb
           midonet
           nvp
           ovs
           server-network
           ssp
           vmware-network
           vns
           vxlan
         server-alert-adapter-backend
         storage
           baremetal-storage
           server-alert-adapter-storage
           server-storage
           server-template-adapter
           storage-allocator
           storage-image-default
           storage-image-s3
           storage-image-swift
           storage-volume-default
           storage-volume-solidfire
           vmware-storage
       discoverer
         baremetal-discoverer
         ovm-discoverer
         secondary-storage-discoverer
         server-discoverer
         vmware-discoverer
         xenserver-discoverer

Extensions

Extensions are the specific interfaces that can be implemented in ACS to provide functionality.  For example NetworkElement or PrimaryDataStoreProvider.  To implement an extension you must do the following

  1. Implement the specific interface
  2. Register the bean in a Spring XML in a module as defined by the module system
  3. Define your module as a child of the specific module required by the extension
  4. Package your code and configuration in a jar and place on the classpath

Refer to Extensions for a complete list of extensions and their module parents.

  • No labels