.. _intro-overview:

======================
Bombardier at a glance
======================

Bombardier provides all of the components of a mature change
management system for production datacenters:

 * A package format for delivering application binary data and
   application setup script files

 * A cross-platform scripting language and libraries for package
   installation, configuration, verification, and uninstallation
   (basically Python)

 * A centralized Configuration Management Database (CMDB) for keeping
   track of all configuration items (CIs), with a means for packages
   that are being delivered to a target system to read configuration
   items for that package

 * A means for storing and tracking all packages in the system in a
   Definitive Software Library (DSL)

 * A central console for managing all network operations on all
   servers in a network using a scriptable command-line interface.

The goal of this document is to give you enough technical specifics to
understand how Bombardier works, but this isn't intended to be a
tutorial or reference -- but we've got both! When you're ready to
start a project, you can :ref:`start with the tutorial
<intro-tutorial01>` or :ref:`dive right into more detailed
documentation <topics-index>`.

Design your Packages
====================

A set of software packages are the heart of a Bombardier system. When
thinking about rolling out Bombardier, ask yourself: What components
of my datacenter are...

 * configuration-intensive,

 * change frequently, and 

 * are critical to keeping my customers happy?

Perhaps this starts with a core website or an LDAP directory or a
backend database system. Bombardier is perfect for managing all these
things, and many more. Start with the components of the system which
make you the most nervous, which have the most mystery around them and
"tribal knowledge" around their installation, configuration, and
maintenance. However, it may be easiest to tackle some simple and
well-defined problems first: perhaps your SVN repository.

Most datacenters have large, dark, frightening silos of murky know-how
around managing certain services.  Bombardier is typically used like a
flash-light to shine light in each of these murky areas one at a time
to verify and prove that installation and configuration processes are
known and repeatable and to then provide a simple and universal tool
for their ongoing management. As you tackle these areas of your
datacenter one at a time, the process will gain momentum:
administrators will wonder why it took so long to organize these
processes, they will demand that all critical components be packaged,
and you will see a gradual relief spread over your IT staff as they
begin to realize that they know how to perform any type of maintenance
in the datacenter quickly, efficiently, and flawlessly whenever needed.


Not everything needs to be packaged
-----------------------------------

Once you start converting things into packages, it can be tempting to
have Bombardier manage everything. But there are quite a few software
components that don't need to be packaged at all. For example, if your
operating system has a good software distribution system of its own
such as Yum or APT, it will probably be preferable to use this system
for installing run-of-the-mill utilities such as screen or vim; things
that don't take any configuration, don't provide any end-value to
your customers, and pose almost no risk to causing a problem with the
healthy operating of other things on the server, such as Apache
HTTPD.  Bombardier packages are really only useful for managing highly
critical software components that provide value to someone outside
your company or department.


What a package looks like
=========================

metadata
--------

A package consists of two things: metadata and a Python class.  The
metadata describes the package-- what it does, what configuration data
it needs, what dependencies it has, etc. An example of package
metadata is this::

  class_name: SvnServer.SvnServer
  configuration:
    fqdn: ''
    ip_address: ''
    ldap:
      admin_email: admin@test.com
      admin_pass: abc123
      admin_user: admin
      backup_dir: NOT_CONFIGURED
      base: dc=mycompany,dc=com
      groupOu: UNKNOWN
      ignore_users: []
      password_complexity: '100'
      port: '389'
      schema: {}
      userOu: UNKNOWN
      users: {}
    ssl_cert: ''
    ssl_key: ''
    svn:
      admin_pass: NONE
      daemon_group: www-data
      daemon_user: www-data
      friendly_email: The SVN admins
      lock_dir: /var/lock/apache2
      log_dir: /var/log/apache2
      name: Un-named repository
      ou: UKNOWN
      repositories: []
      repository_root: ''
      rights: {}
      server_port: '443'
      server_root: /etc/apache2
  dependencies:
  - LdapServer
  executables:
  - configure
  - generate_auth_files
  - install
  - start
  - stop
  - uninstall
  - verify
  injectors:
    LdapManager:
      path: /var/deploy/repos/injectors/LdapManager-526.tar.gz
      svn: https://svn.ge-is-beta.com/icontrol/src/trunk/libs/LdapManager
      version: '526'
    apache_templates:
      path: /var/deploy/repos/injectors/apache_templates-526.tar.gz
      svn: https://svn.ge-is-beta.com/icontrol/src/trunk/injector/apache_templates/
      version: '526'
    sousaphone:
      path: /var/deploy/repos/injectors/sousaphone-526.tar.gz
      svn: https://svn.ge-is-beta.com/icontrol/src/trunk/injector/sousaphone/
      version: '526'
  libs:
    LdapManager:
      path: /var/deploy/repos/libs/LdapManager-526.tar.gz
      svn: https://svn.ge-is-beta.com/icontrol/src/trunk/libs/LdapManager
      version: '526'
    SvnServer:
      path: /var/deploy/repos/libs/SvnServer-526.tar.gz
  package-version: 5
  release: 26

This metadata defines what configuration data the package requires (in
this case, test.directory and test.value), what executables it
provides (more on this later). What Python libraries are required to
install and manage this package (under libs), and what supplementary
files should be shipped with the package (typically these are the
files that will actually get installed onto the server), which are
called "injectors."


Class file
----------

The class that is responsible for installing, configuring, verifying
and uninstalling the package needs to be called out under the
**class_name** directive in the package metadata. This class can be
part of the package, under the libs directory. Here's a quick example
of a class::

  class SvnServer(SpkgV5):
      "Class for SVN/Apache installation"

      def __init__(self, config):
	  SpkgV5.__init__(self, config)

	  self.debug = "False"
	  domain_white_list = config.listobj("svn.domain_white_list", [], optional=True)
	  self.domain_white_list = ','.join(domain_white_list)
	  self.friendly_email = config.string('svn.friendly_email', "The SVN admins")
	  self.fqdn = config.string('fqdn')
	  self.company = config.string("svn.company_name", optional=True)
	  if not self.company:
	      self.company = self.fqdn
	  self.days_before_token_expiration = config.string("svn.days_before_token_expiration",
							    "2", optional=True)
	  self.server_root = config.string("svn.server_root", "/etc/apache2")
	  self.lock_dir = config.string("svn.lock_dir", '/var/lock/apache2')
	  self.daemon_user = config.string("svn.daemon_user", 'www-data')
	  self.daemon_group = config.string("svn.daemon_group", 'www-data')
	  self.log_dir = config.string("svn.log_dir", '/var/log/apache2')
	  self.admin_pass = config.string("svn.admin_pass", "NONE")
	  self.server_port = config.string("svn.server_port", '443')

      def configure(self):
	  "Standard configuration method for a package"
	  self.stop()
	  self._info("Current directory: %s" % os.getcwd())
	  sites_dir = os.path.join(self.server_root, "sites-enabled")
	  if not os.path.isdir(sites_dir):
	      os.system("mkdir -p %s" % sites_dir)
	  config_file = os.path.join(self.server_root, 'apache2.conf')
	  template_file = "apache_templates/apache-svn.template"
	  status1 = self._modify_template(template_file, config_file)
	  self._info("Creating repository configuration")
	  status2 = self._create_repositories()
	  self._info("Generating authorization file...")
	  status3 = self.generate_auth_files()
	  if [status1, status2, status3] == 3 * [OK]:
	      return OK
	  return FAIL



Install it
==========

Packages have to get installed on a computer somewhere in order for
them to be useful. We call the computers that are part of the
datacenter "machines" in order to distinguish them from the Bombardier
server.

Set up a machine
----------------

A machine has a metadata file similar to the package just
shown. Here's an example of a miniumum machine configuration file for
a machine svn_server::

  default_user: root
  ip_address: 10.10.1.70
  platform: linux

If you're going to install the SVN package on this server, you'll have
to add the configuration values to it that the package requires (not
shown). Finally, you'll need to actually install the package onto the
remote server::

  ( machine svn_server )> inst svn
  >>> Job name: admin@svn_server-10
    |  admin@svn_server-10 | Package SvnServer does not have a priority (assuming 100)
    | admin@svn_server-10 | Packages remaining to install (in order): ['SvnServer']
    | admin@svn_server-10 | Currently installing package priority 100 [SvnServer]
    | admin@svn_server-10 | svn_server installing SvnServer-27
    | admin@svn_server-10 | [injectors]|Template: settings.template
    | admin@svn_server-10 | [injectors]|Created: sousaphone/settings.py
    | admin@svn_server-10 | [injectors]|Installing the sousaphone webapp libraries...
    | admin@svn_server-10 | [injectors]|Template: sousaphone/header.html.template
    | admin@svn_server-10 | [injectors]|Created: /var/www/templates/header.html
    | admin@svn_server-10 | [injectors]|Template: sousaphone/password_policy.html.template
    | admin@svn_server-10 | [injectors]|Created: /var/www/site_media/password_policy.html
    |  admin@svn_server-10 | [injectors]|No PID file: /var/lock/apache2/apache.pid
    | admin@svn_server-10 | [injectors]|Current directory: /opt/spkg/svn_server/packages/SvnServer-27/injectors
    | admin@svn_server-10 | [injectors]|Template: apache_templates/apache-svn.template
    | admin@svn_server-10 | [injectors]|Created: /etc/apache2/apache2.conf
    | admin@svn_server-10 | [injectors]|Creating repository configuration
    | admin@svn_server-10 | [injectors]|Generating authorization file...
    | admin@svn_server-10 | install OK: SvnServer-27
    | admin@svn_server-10 | Verifying package SvnServer-27
    | admin@svn_server-10 | verify OK: SvnServer-27
    | svn_server | Finished install for SvnServer.
    | svn_server | Finished install for SvnServer.
  >>> Joining...
   info:
     Generated /etc/apache2/devel
     Generated /etc/apache2/partner
     Generated /etc/apache2/admin

  ( machine svn_server )> exec svn start
  >>> Job name: admin@svn_server-11
    | admin@svn_server-11 | Using SvnServer
    |  admin@svn_server-11 | Package SvnServer does not have a priority (assuming 100)
    | admin@svn_server-11 | Executing (start) inside package (SvnServer-27)
    | admin@svn_server-11 | [injectors]|Waiting for apache2 to start...
    | admin@svn_server-11 | start OK: SvnServer-27
    | svn_server | Finished execute for SvnServer.
    | svn_server | Finished execute for SvnServer.
  >>> Joining...
   time to start: 0

  ( machine svn_server )>


Enjoy the free API
==================

With that, you've got a free, and rich, Python API to write
installation and configuration packages however you like.  Bombardier
also provides quite a bit of assistance on the remote machine side for
making packages easier to create. For example, you'll notice that the
class SvnServer inherited from SpkgV5.  With this inheritence you get
the following:

config object
-------------

A "config" object is passed into your constructor. This object
provides your installer class with all the information that the
administrator has configured for this machine.  For example, if you
want to know what daemon the Apache server should be configured to run
as, you can request the information from the config object in the
following way::

    apache_user = config.string("svn.daemon_user")

logging methods
---------------

If you want to report-out the the user-interface anything of interest
that happens during the installation, you can use the build-in logging
methods:

 * self._debug()
 * self._info()
 * self._warning()
 * self._error()
 * self._critical()

While the installation is proceeding, the administrator running the
package commands will be able to see what's going on with the
installation, and the details of the package actions will be recorded
in Bombardier's permanent log file for forensic analysis if that's
ever necessary.

standard interface methods
--------------------------

Each package installation class must provide the following standard
interface methods:

install()
   This method is called on the class when the user wants to install
   the package

configure()
   This method is called on the class when the user wants to make a
   configuration change to an already-installed system.  Configuration
   is supported on already-installed systems and provides for those
   changes that you can make to a 'live' system.

verify()
   This method is used to verify that the software is deployed
   as-designed.

uninstall()
   This method is used when a package is to be removed (uninstalled)
   from the system. The package should provide for *idempotance*,
   meaning that the system should be left in exactly the same state
   after being uninstalled that it was before the package was
   installed. 

additional interface methods
----------------------------

Any non-public methods (methods that don't start with an underscore)
in your class will also be made available to the administrator for
performing specific functions with that package. For example,
``start``, ``stop``, and ``backup`` are often added as public methods
to a package class to start services and backup data.

This is just the surface
========================

This has been only a quick overview of Bombardier's functionality. Some more useful
features:

    * The Bombardier CLI :ref:` <topics-cli>` that provides for a
      great and simple command-line user experience.

The next obvious steps are for you to `download Bombardier`_, read
:ref:`the tutorial <intro-tutorial01>`. Thanks for your interest!

.. _download Bombardier: https://launchpad.net/bombardier/+download
