Apache VCL logo Apache Software Foundation logo

Modularized Architecture

Background

The VCL backend code was significantly reworked in version 2.0 to utilize a "modularized" framework.  This framework allows certain parts of the code to be separated from the core code through the implementation of modules.

VCL interacts with external technologies including: provisioning engines operating systems * monitoring utilities

The technology being used may vary based on the VCL deployment, management node, image, computer, and so on.  Modules make configuring VCL to use a certain technology easy while simplifying the core code.

The advantages of implementing modules are not limited to external technologies.  Modules may be implemented for functions applicable only to VCL, but may vary based on the environment.  For example, research is being conducted to compare different algorithms which are used to select the image that is loaded on a computer after a reservation is complete.  A module is created for each algorithm, and configuring a management node to use a certain algorithm is as simple as changing one value in the database.

Object Orientation and Inheritance

Object orientation and inheritance are used in the VCL modular framework, allowing modules to access functionality from the classes which they inherit from.  This relieves module developers from having to worry about many underlying details and reduces code duplication.

The following diagram shows how inheritance is organized: !inheritance.jpg|align=center! Figure: VCL module inheritance organization   A few notes about the diagram: The yellow modules represent the core VCL modules The blue and green modules represent auxiliary modules Core modules that should not need to be changed regardless of the auxiliary modules being used The core modules provide many functions to the auxiliary modules including: default constructors data access module initialization access to other auxiliary modules where appropriate

{color:#6600ff}{}Explain: {color:#6600ff}{}abstract and concrete classes - abstract are not instantiated{}{color} {color:#6600ff}{}classes can be empty, contain no subs, but act as a placeholder in case it's decided later on that a sub would be useful{}{color}{color:#6600ff} {color}

Advantages

{color:#6600ff}{}Explain:  {color:#6600ff}{}more about benefits of inheritance{}{color} {color:#6600ff}{}give OS example and include diagram{}{color} {color:#6600ff}{}Windows - Desktop - XP - Vista{}{color} {color:#6600ff}{}implement subs as high up as possible so child classes inherit them{}{color} {color:#6600ff}{}child classes can override an inherited sub if it doesn't fit its needs{}{color} {color:#6600ff}{}use example of firewalls in Windows.  Windows.pm implements a firewall sub which works for everything but Vista.  Vista.pm can implement a sub with the same name and it will override the one in Windows.pm, yet Vista.pm still enjoys everthing else Windows.pm offers.

Core Modules

  {color:#6600ff}{}Explain: {color:#6600ff}{}only core modules should ever change the request state/laststate/computer state{}{color} {color:#6600ff}{}only core modules should change anything in the request and rsvp tables{}{color} {color:#6600ff}{}provide state flow{}{color} {color:#6600ff}{}provide data access{}{color} {color:#6600ff}{}provide utility functions  {color:#6600ff}{}database and data structure are abstracted from auxiliary modules{}{color} * {color:#6600ff}{}ongoing - should not contain code specific to something that can be modularized such as "if windows... else linux..."

vcld (VCL::vcld)

{color:#6600ff}{}Explain: {color:#6600ff}{}main exe{}{color} {color:#6600ff}{}loops every 12 seconds by default{}{color} {color:#6600ff}{}doesn't inherit{}{color} {color:#6600ff}{}creates DataStructure object{}{color} {color:#6600ff}{}forks{}{color} {color:#6600ff}{}sets some $ENV variables{}{color} * {color:#6600ff}{}reaps dead processes{}{color}

DataStructure.pm (VCL::DataStructure)

{color:#6600ff}{}Explain: {color:#6600ff}{}abstracts database and data structure{}{color} {color:#6600ff}{}aux modules shouldn't know about the DB or data structure{}{color} {color:#6600ff}{}should be able to change db or data structure and still have aux modules work{}{color} {color:#6600ff}{}uses "Inside Out" technique to accessing modules can't get to the underlying data{}{color} {color:#6600ff}{}data is encapsulated, can only be accessed using accessor functions{}{color} {color:#6600ff}{}encapsulation is good, explain what it is{}{color} {color:#6600ff}{}usage: $self->data->get_image_name() {color:#6600ff}{}need to list methods somewhere (not here), there are tons of them{}{color} {color:#6600ff}{}gets created by vcld when it finds a reservation{}{color} {color:#6600ff}{}passed to module constructor{}{color} {color:#6600ff}{}Module.pm sets up access via data() * {color:#6600ff}{}Result: any class that inherits from VCL::Module gets access{}{color}

utils.pm (VCL::utils)

{color:#6600ff}{}Explain: {color:#6600ff}{}contains several utility subs{}{color} {color:#6600ff}{}doesn't inherit from Module.pm (might be a good idea to look into this) {color:#6600ff}{}contains some legacy stuff - some subs will be removed and moved to OS or provisioing modules{}{color} {color:#6600ff}{}should probably make a page describing utility subs such as notify, run_ssh_command... * {color:#6600ff}{}This should really get sucked out of POD comments in the actual code{}{color} {color:#6600ff}{}have to 'use VCL::utils' in order to use it{}{color}

Module.pm (VCL::Module)

State.pm (VCL::Module::State)

Provisioning.pm (VCL::Module::Provisioning)

OS.pm (VCL::Module::OS)

Implementation Details

Working with Inheritance

{color:#6600ff}{}Explain: {color:#6600ff}{}code to set up inheritance{}{color} {color:#6600ff}{}using $self-> {color:#6600ff}{}when to use $self-> (object method) and when to call a sub directly (class method) {color:#6600ff}how to check if sub was called as an object method or not{color}

Including Non-Inherited Modules

 {color:#6600ff}{}Explain: {color:#6600ff}{}use{}{color} {color:#6600ff}file::bin {color:#6600ff}{}to include the lib directory{}{color} {color:#6600ff}{}use warnings, strict, diagnostics are a good practice{}{color} * {color:#6600ff}{}use 'VCL::utils' is the only VCL module you should need to include, all else should be handled by inheritance/objects{}{color}

Module Initialization

{color:#6600ff}{}Explain how modules can implement initialize() subs which are automatically called{}{color}

Database Configuration for Modules

{color:#6600ff}{}Explain module table, computer.moduleid, managementnode.predictivemoduleid{}{color}

Cross-Module Access

{color:#6600ff}{}Explain why some modules shouldn't have access to others, which is why Module.pm doesn't make os() and provisioner() available{}{color}

Required & Optional Module Subroutines

{color:#6600ff}{}Explain: {color:#6600ff}{}Perl's can() function{}{color} {color:#6600ff}{}core modules use can() to check if module implements a subroutine{}{color} {color:#6600ff}{}some subs should be required such as OS::load(), most should not{}{color} {color:#6600ff}{}if you can think of an exception why a sub wouldn't be needed it shouldn't be required{}{color}

Package Organization

{color:#6600ff}{}Explain: {color:#6600ff}{}how directories under lib/VCL should be organized{}{color} {color:#6600ff}{}the 'package' line in the modules should match the location of the file{}{color} * {color:#6600ff}{}Example: "package VCL::Module::OS::Windows" resides in "lib/VCL/Module/OS/Windows.pm" {color:#6600ff}{}some core modules don't follow this - the state modules reside directly under lib/VCL, should eventually reside under lib/VCL/Module/State{}{color}