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:
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

Explain:

  • abstract and concrete classes - abstract are not instantiated
  • 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 

Advantages

  • Modules make it easier for developers to implement new technologies to be used with VCL easily
  • Core VCL code does not need to be altered in order to support additional technologies or functionality
  • Increased flexibility for different configurations
  • Consistent methods to access data stored in the database
  • Code maintainability is increased because each module focuses on a distinct task and the core code does not need to check for numerous different conditions based on the technology being used

Explain: 

  • more about benefits of inheritance
  • give OS example and include diagram
    • Windows - Desktop - XP - Vista
    • implement subs as high up as possible so child classes inherit them
    • child classes can override an inherited sub if it doesn't fit its needs
    • 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

  Explain:

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

vcld (VCL::vcld)

Explain:

  • main exe
  • loops every 12 seconds by default
  • doesn't inherit
  • creates DataStructure object
  • forks
  • sets some $ENV variables
  • reaps dead processes

DataStructure.pm (VCL::DataStructure)

Explain:

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

utils.pm (VCL::utils)

Explain:

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

Module.pm (VCL::Module)

  • Provides a constructor for all derived objects to use
    • Objects which inherit from VCL::Module do not need to implement their own new() subroutines
    • Objects which inherit from VCL::Module do not need to deal with "blessing" themselves
  • Provides access to the database data for the reservation via the data() subroutine implemented by Module.pm
    • Any module derived from VCL::Module can call $self->data->[get_something] or $self->data->[set_something]

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

  • Supports the core VCL state modules such as new.pm, image.pm, reclaim.pm, and others
  • Provides an initialize() subroutine which performs common tasks whenever a state object is created
    • initialize() creates the provisioning and OS objects
  • Provides an os() subroutine which allows the state objects to interact with the resource's operating system by calling $self->os->[subroutine]
  • Provides a provisioner() subroutine which allows the state objects to interact with the provisioning engine that has been configured for the resource by calling $self->provisioner->[subroutine]
  • Provides other subroutines such as reservation_failed() which performs a consistent set of tasks when a reservation fails

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

  • Provisioning engine modules should inherit from VCL::Module::Provisioning
  • Modules which are a subclass of VCL::Module::Provisioning also receive the functionality provided by VCL::Module through inheritance
  • VCL::Module::Provisioning provides provisioning modules with access to the OS object created for the reservation

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

  • OS modules should inherit from VCL::Module::OS
  • Modules which are a subclass of VCL::Module::OS also receive the functionality provided by VCL::Module through inheritance
  • VCL::Module::OS provides OS modules with access to the provisioning object created for the reservation
    • This is useful if the OS needs to perform a task such as power cycling the computer if a reboot fails

Implementation Details

Working with Inheritance

Explain:

  • code to set up inheritance
  • using $self->
  • when to use $self-> (object method) and when to call a sub directly (class method)
  • how to check if sub was called as an object method or not

Including Non-Inherited Modules

 Explain:

  • use file::bin to include the lib directory
  • use warnings, strict, diagnostics are a good practice
  • use 'VCL::utils' is the only VCL module you should need to include, all else should be handled by inheritance/objects

Module Initialization

Explain how modules can implement initialize() subs which are automatically called

Database Configuration for Modules

Explain module table, computer.moduleid, managementnode.predictivemoduleid

Cross-Module Access

Explain why some modules shouldn't have access to others, which is why Module.pm doesn't make os() and provisioner() available

Required & Optional Module Subroutines

Explain:

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

Package Organization

Explain:

  • how directories under lib/VCL should be organized
  • the 'package' line in the modules should match the location of the file
    • Example: "package VCL::Module::OS::Windows" resides in "lib/VCL/Module/OS/Windows.pm"
  • some core modules don't follow this - the state modules reside directly under lib/VCL, should eventually reside under lib/VCL/Module/State
  • No labels