Integrate `queue_classic` into razor-server

This brings in the `queue_classic` gem: a satisfactory implementation of
background task queuing using the PostgreSQL database.  While not generally
the ideal choice, QC carefully implements reasonably efficient and correct
locking and notification to reduce the cost.

This has the advantage of being predominantly in-process, and while not as
optimal as a queue that could run correctly without any service, it is only
prone to failure when *all* data-touching operations would fail.

This eliminates a robustness failure point that we would hit using, for
example, a second external process queue solution -- when we had to solve the
challenge of the database being up, but the queue down, or vice-versa.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Move base schema creation down the migration pecking order

This simply bumps the base schema creation from slot 2 to 3, allowing room for
the QC schema, triggers, and functions to be loaded into the database before
we deal with the rest of our schema being created.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Add `queue_classic` migration

This adds the database setup -- and teardown -- from QC to a migration,
allowing it to be run as part of the normal Sequel build and cleanup of
the database.

It is a distinct migration script as the QC code maintains transactionality
internally, and we want to disable Sequel migration transactions for this
script -- but only this script!

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Enforce exception-on-failure handling for all `Sequel::Model`s

This manually enforces the, typically default, Sequel::Model behaviour of
raising an exception when unexpected things happen in the ORM universe.

For example, failing to save an object, typecasting problems, update or delete
operations that touch zero or two rows of data, and so forth.

While these are typically the default behaviours in modern versions of Sequel,
and they represent the conservative choice -- so are likely to stay default --
that has not always been true.

Given that, it is much better to be explicit about our expectations, and
ensure we get the behaviour we desire.

Notably, we can also override this default in any model class, or model
instance, or -- most attractively -- in the individual operations.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Add courtesy support for an additional local Gemfile

Like a white courtesy phone, this makes life just a touch nicer: it allows a
local `Gemfile.local` to exist, and to be evaluated, when using bundler.

This allows local development gems such as additional rspec formatters,
debuggers, and other tools to be introduced without having to push them into
the public realm, forcing them on everyone -- and without having to constantly
hack on the main Gemfile, or maintain a second copy of it.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Implement `compose_url` helper for Sinatra

This is a helper to wrap the process of building a URL from component parts,
some of which may need to be URL-escaped.  It takes many arguments, treating
each as a part of the 'relative to the app' URL, and composes them together.

Example:

    compose_url
    => '/'

    compose_url 'api', 'images'
    => '/api/images'

    compose_url 'api', 'images', image.name
    => '/api/images/correctly%20escaped%20name

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Create top level API navigation message handler

This handles an HTTP message fetching the API table: which endpoints are
available for use, and what do they do.  It includes testing and, as a side
effect, an assertion that the client is willing to accept our (only) content
response type across the board.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Implement the `create_new_image` API message handler.

This implements the create new image message, which starts the process of
loading a new ISO image into Razor, along with creating and binding components
together to allow it to be used for later installation.

Much of the work happens in the background; this simply triggers the process,
after performing appropriate validation and transformation of the image.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Implement the new image schema in the database

This updates the database schema, in the existing migration, to reflect the
current needs of the Image model as part of the command.  This removes a pile
of the existing data, which is not actually part of the new world
understanding of how images operate.

This also ties in the appropriate validation, ensuring that we have correct
data -- including assertions that the data passed to the command matches the
publicly modifiable parts of the model.

Some of the validation code is a little convoluted, to work around limits of
regular expressions that are compatible with both Ruby and PostgreSQL
semantics.  The great thing about POSIX regular expressions is how wonderfully
varied the implementations turn out to be.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>
Implement a Razor::Queue plugin for Sequel::Model objects

This implements an additional plugin to add an `enqueue` method to all
Sequel::Model derived classes.

When invoked on an instance, will arrange for a given message to be delivered
to the same instance -- freshly loaded from the database by primary key --
along with the appropriate arguments by a QC worker.

This allows sending background task messages to any Sequel::Model object,
which is a step toward being able to perform background image downloading and
other delayed work processing cleanly.

Signed-off-by: Daniel Pittman <daniel@rimspace.net>