Commit graph

151 commits

Author SHA1 Message Date
Glenn Sarti
5e46ace584 (POOLER-73) Add spec tests for execute!
Add spec tests for execute!

Previously the execute! method would execute the loop indefinitely as it did not
have a terminating condition.  This made it impossible to test.  This commit
modifies the execute! method so that it can take a maxloop and delay parameter
so that it can be tested.
2017-02-17 15:51:03 -08:00
Rick Bradley
1bbd623609 Merge pull request #174 from mattkirby/pooler_48
(POOLER-48) Clear migrations at application start time
2016-12-01 16:40:58 -06:00
kirby@puppetlabs.com
fdc30f44bf Remove duplicate log for check_pool completed VMs 2016-12-01 13:36:57 -08:00
kirby@puppetlabs.com
f859826c65 (POOLER-47) Send clone errors up
This commit updates vmpooler to ensure clone errors, and other pool manager errors are raised to the parent method. Without this change vmpooler gets stuck after a connection fails during clone operations and will not attempt to clone again.
2016-12-01 12:41:01 -08:00
kirby@puppetlabs.com
bf8fb1850e (POOLER-48) Clear migrations at application start time
This commit updates vmpooler to clear the migrations queue at application start time. When the application is shut down it is not considerate of any activities, like migrations, in flight. The result is that when the application is started again any stale entries in vmpooler__migration will be left until manually removed, which can prevent migrations from occurring.
2016-12-01 09:58:29 -08:00
kirby@puppetlabs.com
86aedd0754 Add retry logic with a delay for vsphere connections
This commit adds retry logic and configurable delays to vsphere helper.
Without this change vmpooler instances that have large numbers of pools
can create enough connections in a short period of time to cause vcenter
issues.
2016-11-29 03:43:18 -08:00
kirby@puppetlabs.com
c43c02bf55 Add a counter for vsphere connections 2016-11-23 11:08:19 -08:00
kirby@puppetlabs.com
4faeb6a9ba (POOLER-44) Fix vmpooler.migrate reference
This commit updates vmpooler.migrate metric to send the pool name. Without this change the VM name is sent. Additionally, counts are added for migrate_from_#host and migrate_to_#host in order to allow tracking host migrations, and correlating them with CPU ready time changes.
2016-11-22 15:05:16 -08:00
kirby@puppetlabs.com
02327dfcd6 (POOLER-26) Fix lost VMs getting stuck in pending
This commit updates vmpooler to understand how to resolve a situation
where a pending VM does not exist. Without this change a pending VM that
does not exist in vmware inventory gets stuck in the pending state,
preventing the pool from ever reaching its target capacity.

As a part of this change the find_vm method is updated to perform a
light, then heavy search each time find_vm is called and all usage of
find_vm || find_vm_heavy is replaced. This makes find_vm usage
consistent across pool_manager.

Additionally, open_socket method is updated to resolve an incorrect
reference to the host name.
2016-11-22 10:23:16 -08:00
kirby@puppetlabs.com
a6c8c76d31 Use open socket method for opening socket
This commit updates pool manager to use a method for opening a socket
instead of opening it directly from check_pending_vm. Support is added
for specifying the domain of the VM to connect to, which lays the
groundwork for doing away with the assumption of having DNS search
domains set for vmpooler to move VMs to the ready state.

Additionally, this commit adds a block to ensure open_socket closes open connections. Without this change sockets are opened to each VM before moving to the ready state, and never explicitly closed.

Also, use open socket for check_ready_vm
2016-11-22 10:23:16 -08:00
kirby@puppetlabs.com
109f197fe7 Update migration_count method for greater readability and predictability.
Update migrate_vm to make clear when an if block is the end of the line by returning. Use scard instead of smembers.size() for determining migrations in progress.
2016-11-22 10:23:16 -08:00
kirby@puppetlabs.com
a15090e005 Simplify vsphere connection handling in order to make it reasonable to test. Simplify migrate_vm method by breaking out some componenents. Improve error handling around migrate_vm.
Add helpers to support setting up redis for migration at checkout
testing.
2016-11-22 10:03:24 -08:00
kirby@puppetlabs.com
f8bd79a8d9 Handle empty queues in pool manager
Remove unneeded begin block in method

Fix formatting of rescue block in fail_pending_vm
2016-11-22 10:03:10 -08:00
kirby@puppetlabs.com
a244f9b92a Stop reloading configuration file from vspherehelper and instead source credentials from the configuration object that itself loads the configuration file when the application starts. Without this change the configuration file is reloaded every time vspherehelper is called. Additionally, this change makes it more straightforward to test vspherehelper connections.
A method is added to make more clear what's happening when checking if a socket can be opened to a pending VM on port 22. Additionally, the connection appends domain from the configuration, when present, to the VM name so DNS search is not required.
2016-11-22 09:48:28 -08:00
kirby@puppetlabs.com
58a548bc90 Add support for migrating VMs to pool_manager.
This commit adds a capability to pool_manager to migrate VMs placed in the migrating queue. When a VM is checked out an entry is created in vmpooler__migrating. The existing process for evaluating VM states executes the migrate_vm method for the provided VM, and removes it from the queue. The least used compatible host for the provided VM is selected and, if necessary, a migration to the lesser used host is performed. Migration time and time from the task being queued until completion are both tracked with the redis VM object in 'migration_time' and 'checkout_to_migration'. The migration time is logged in the vmpooler.log, or the VM is reported as not requiring migration. Without this change VMs are not evaluated for checkout at request time.

Add a method to wrap find_vm and find_vm_heavy in order to allow a
single operation to be performed that does both.

This commit also adds support for a configuration setting called
migration_limit that makes migration at checkout optional. Additionally,
logging is added to report a VM parent host when it is checked out. Without this
change vmpooler assumes that migration at checkout is always enabled.
If this setting is not present, or if the setting is 0, then migration
at checkout will be disabled. If the setting is greater than 0 then that
setting will be used to enforce a limit for the number of simultaneous
migrations that will be evaluated.

Documentation of this configuration option is added to the
vmpooler.yaml.example file.
2016-11-08 16:32:10 -08:00
Rick Sherman
34b93ca6c3 Merge CI.next into Master (#161)
* [QENG-3919] Make vmpooler checkouts be all or nothing (#153)

* (QENG-3919) spike for implementation of all-or-nothing checkout

* Fix two botched variable references

* Aggregate API helper methods

* Add specs for failed multi-vm allocation API endpoints

* (QENG-3919) Add tests for multiple vm requests

* (QENG-3919) Add (failing) specs for POST /vm/pool1+pool2 usages

This exposes the old (bad) behavior on this other code path. Will fix this up next.

* (QENG-3919) Bring query params version in line with JSON post version

Not clear to me why these had to be implemented so differently.

* (QENG-3919) extract common method from both methods of VM allocation

* (QENG-3919) Naming fix, cosmetic cleanups

I mean, I presume all these commits are going to get squashed away on merge anyway.

* (QENG-3919) Update API docs

We consider it a bug that the actual behavior was not this behavior, but the
documentation was also silent on this point.

* (QENG-3919) minor readability tweak in refactored method

* (QENG-3919) Clean up interim comments re: status codes

* (QENG-3919) Drop now-orphaned `checkout_vm` method

We kept this up-to-date while we were upgrading and refactoring, but, turns out,
this method is no longer called anywhere.  💀 🔥

* (QENG-3919) Return 503 status on failed allocation

Making sure we go back to the original functionality, which was:

 - status 200 when vms successfully allocated
 - status 404 when a pool name is unknown
 - status 404 when no pool name is specified
 - status 503 when vm allocation failed

* (QENG-3919) add net-ldap to Gemfile

Maybe we shouldn't foil-ball gems onto servers.

* (QENG-3919) Turns out, spush isn't a redis command

And hence we see once again the weakness of mockist tests.

* (QENG-3919) Pin the net-ldap gem to 0.11 for the jrubies, etc.

* (QENG-3919) Correct an old spelling error in spec descriptions

* (QENG-3919) Further tweak net-ldap version

* (QENG-3919) return_single_vm -> return_vm_to_ready_state

cc @shermdog

* (RE-7014) Add support for statsd
They way we were using graphite was incorrect for the type of data we were sending it.  statsd is the appropriate mechanism for our needs.
statsd and graphite are mutually exclusive and configuring statsd will take precendence over Graphite.  Example of configuration in vmpooler.yaml.example

* (RE-7014) Add tracking of vm gets via statsd
Add the tracking of successful, failed, invalid, and empty pool vm gets.  It is possible we may want to tweak this, but have validated with spec tests and pcaps.

```
vmpooler-tmp-dev.ready.debian-7-x86_64:1|c
vmpooler-tmp-dev.running.debian-7-x86_64:1|c

vmpooler-tmp-dev.checkout.invalid:1|c
vmpooler-tmp-dev.checkout.success.debian-7-x86_64:1|c
vmpooler-tmp-dev.checkout.empty:1|c

vmpooler-tmp-dev.running.debian-7-x86_64:1|c

vmpooler-tmp-dev.clone.debian-7-x86_64:12.10|ms

vmpooler-tmp-dev.ready.debian-7-x86_64:1|c
```

* (RE-7014) statsd nitpicks and additional rspec
Cleaned up some code review nitpicks and added pool_manager_spec for empty pool.

* (RE-7014) update statsd to use gauge for running/ready
Previously was using increment which was incorrect for that particular application.

* Revert "Merge pull request #155 from shermdog/RE-7014-cinext"

This reverts commit cc03a86f6a, reversing
changes made to 5aaab7c5c2.

* (QENG-4070) Consistently return 503 if valid pool is empty

There were several problems with how the pooler checked out vms with
respect to empty pools, invalid pools, and aliases:

- If the vmpooler config did not contain any aliases and the caller
requested a vm from an empty pool or a non-existent one, the vmpooler
would error with:

    NoMethodError - undefined method `[]' for nil:NilClass

If the config contained a non-nil alias section, then:

- If the caller requested a vm from an empty pool and either the vm
didn't have an alias or the aliased pool was empty or non-existent, then
the request for that vm would be silently ignored. The vmpooler would
return 200 if the caller asked for multiple vms and the vmpooler was
able to checkout at least one vm.  Otherwise it would return 404.

- Similarly, if the caller requested a vm from a non-existent pool, then
the request was silently ignored.

This commit adds a `pool_names` Set to the config containing all valid
pool names including aliases. This is used to determine whether a
requested template name is valid or not. This is necessary because redis
does not distinguish between empty and non-existent sets, e.g. the
following returns false in both cases:

    backend.exists('vmpooler__ready__' + key)

If the caller requests a vm (single or multiple), and any vm references
an invalid pool name, we immediately return 404. Otherwise, we know the
request is for valid pool names, since the vmpooler requires a restart
to change pool names and counts.

We then attempt to acquire each vm, trying to match on pool name or
failing back to aliased pool name, as was the previous behavior.

The resulting behavior is:

- If the caller asks for at least one vm from an unknown pool, then
don't try to checkout any vms and respond with 404.
- If the caller asks for a vm, and at least one pool is empty, then
respond with 503, returning checked out vms back to the pool.
- Otherwise return 200 with the list of checked out vms.

This commit also makes `alias` optional again.

This commit also re-enables tests that were merged in from master, but
originally commented out due to the bugs described above..

* (maint) Add json pessimistic pin

json 2.0.x was released on July 1 and is not compatible with ruby < 2.0.
Since we still support that version, add a pessimistic pin, which is
what we were using prior to July 1.

* [QENG-4070] Make json version conditional on RUBY_VERSION

* Drop extraneous mocks from updated test

* Revert "Revert "Merge pull request #155 from shermdog/RE-7014-cinext""

This reverts commit 0fd6fff934.

* Fix some spec errors

These were caused in part by dropping changes from the original PR when we
dropped the v1_spec.rb master test file (in favor of the updated and separated
versions).

* [QENG-4075] Fix bug with template name on allocation failure

We're returning [nil,nil] in this case, meaning that name will not be set. This
means we'll get an error trying to concatenate the stats string. Use the
requested template name here instead.

* [QENG-4075] Refactor statsd methods / classes

Prior to this we could easily run into situations where `statds_prefix` would
be `nil` (and possibly the `statsd` handle itself). There was some significant
complexity and brittleness in how statsd was set up.

Refactored so that:

 - `statsd_prefix` is no longer exposed to any callers of statsd methods
 - there is now a `Vmpooler::DummyStatsd` class which can be returned when we are not actually going to publish stats, but would like to keep the calling interface consistent
 - setup of the statsd handle is via just passing in `config[:statsd]`, if `nil`, this will result in a dummy handle being return
 - defaulting of `server` values was fixed -- this did not actually work in the previous implementation. `config[:statsd][:server]` is now required.
 - tests use a `DummyStatsd` instance instead of an rspec double.
 - calls to `statsd.increment` were taking incorrect arguments (some our fault, some part of the prior implementation), and were not collecting data on which pools were "invalid" or "empty". Fixed this and are now explicitly tracking the invalid/empty pool names.

* [QENG-4075] Drop now-superfluous :statsd config defaulting

* [QENG-4075] Unify graphite and statsd for the pool manager

Prior to this, the `pool_manager.rb` library could take handles for both
graphite and statsd endpoints (which were considered mutually exclusive),
and then would use one. There was a bevy of conditional logic around sending
metrics to the graphite/statsd handles (and actually at least one bug of
omission).

Here we refactor more, building on earlier work:

 - Our graphite class comes into line with the API of our Statsd and DummyStatsd classes
 - In `pool_manager.rb` we now accept a single "metrics" handle, and we drop all the conditional logic around statsd vs. graphite
 - We move the inconsistent error handling out of the calling classes and into our metrics classes, actually logging to `$stderr` when we can't publish metrics
 - We unify the setup code to use `config` to determine whether statsd, graphite, or a dummy metrics handle should be used, and make that happen.
 - Cleaned up some tests. We could probably stand to do a bit more work in this area.

* [QENG-4075] Clean up pool manager, specs

Prior to this, `pool_manager.rb` allowed the `metrics` argument to be optional,
but at this point it will be an instance of `Vmpooler::Statsd`,
'Vmpooler::Graphite', or `Vmpooler::DummyStatsd`, so making this non-optional.

Cleaned up that file's tests, cosmetically, as well as recognizing that the
behavioral difference between graphite and statsd does not depend on the pool
manager.

* [QENG-4075] update example vmpooler.yaml file

This documents the changes to :server being mandatory for all metrics
endpoints, as well as the graphite endpoint supporting an optional :port
configuration value.

* [QENG-4075] Rename usages of statsd -> metrics

Really, let's just support a generic metrics interface.

* (maint) move statsd-ruby require into Vmpooler::Statsd class

We've managed to move mentions of this out of the calling code, so let's
move the require.

* (maint) metrics.log -> metrics.timing

We missed this during the refactoring. Bringing this up to date.

* [QENG-4075] Allow specifying 'graphs:' for dashboard

Prior to this the dashboard front-end would use the configuration settings
for `graphite[:server]`/`graphite[:prefix]` to locate a graphite server
to use for rendering graphs.

Now that we have multiple possible metrics backends, the front-end graph
host for the dashboard could be entirely different from the back-end metrics
server that we publish to (if any).

This decouples those settings:

 - use `graphs[:server]` / `graphs[:prefix]` for the graphite-compatible web front-end to use for dashboard display graphs
 - fall back to `graphite[:server]`/`graphite[:prefix]` if `graphs` is not specified, in order to support legacy `vmpooler.yaml` configurations.

Note that since `statsd` takes precedence over `graphite`, it's possible to specify both `statsd` (for publishing) and `graphite` (for reading). We still prefer `graphs` over `graphite`.

Updated the example `vmpooler.yaml` config file.

* (maint) fix variable reference in new_metrics

This was referencing config directly, when what we want is for a
hash to be passed in (derived from config).

* (maint) Fix typo in updated graph link call

* (maint) default :graphs prefix to 'vmpooler'

* (maint) Fix parse error in vmpooler script

The things you find through manual QA 🧌

* (maint) use strings instead of symbols in config

Nested hash data comes back with string keys, not symbols. Be consistent.

* [QENG-4075] Factor out Vmpooler::DummyStatsd

This makes it visible to lib/vmpooler.rb, as well as putting this dummy
metrics endpoint in its own file for easier discovery.

* (maint) clean up statsd inclusion and require lines

The library is actually required as 'statsd' and not 'ruby-statsd', best I can tell.

* (maint) construct ::Statsd instead of Statsd

Because it's ambiguous in this scope, and, well, it doesn't
actually work in production.

* [QENG-4075] Also track completely invalid requests

When we don't even get a pool name we still want metrics to be recorded.
2016-07-25 10:43:32 -05:00
Colin
d4f3eb3c5f Merge pull request #147 from sschneid/add_disk
Allow new disks to be added to running VMs via vmpooler API
2016-01-14 14:38:24 -08:00
Scott Schneider
48a1a8d621 Add new disks via API
Add an additional disk to a running VM via the vmpooler API.

````
$ curl -X POST -H X-AUTH-TOKEN:a9znth9dn01t416hrguu56ze37t790bl --url vmpooler.company.com/api/v1/vm/fq6qlpjlsskycq6/disk/8
````
````json
{
  "ok": true,
  "fq6qlpjlsskycq6": {
    "disk": "+8mb"
  }
}
````

Provisioning and attaching disks can take a moment, but once the task completes it will be reflected in a `GET /vm/<hostname>` query:

````
$ curl --url vmpooler.company.com/api/v1/vm/fq6qlpjlsskycq6
````
````json
{
  "ok": true,
  "fq6qlpjlsskycq6": {
    "template": "debian-7-x86_64",
    "lifetime": 2,
    "running": 0.08,
    "state": "running",
    "disk": [
      "+8mb"
    ],
    "domain": "delivery.puppetlabs.net"
  }
}
2016-01-14 10:46:57 -08:00
FOXX
10e507c262 Added prefix parameter to the vmpooler configuration 2016-01-14 11:42:12 -06:00
Heath Seals
6b9bcc4307 add guestinfo.hostname to VirtualMachineConfigSpecs
This commit adds a custom guestinfo keyword and hostname variable
that allows the VMware Tools to query the hostname.
2015-11-10 16:50:27 -08:00
Colin
7b9b178861 (MAINT) Remove Ping Check on Running VMs
Prior to this commit, a running VM could fail a ping check and be
destroyed. This causes issues when network hiccups occur or the machine
is performing a reboot.

A VM that is in a ready state will now be destroyed when handed back or
it hits the lifetime TTL.
2015-10-02 13:03:48 -07:00
Colin
b8bdfe1301 (maint) Move VM Only When SSH Check Succeeds
An SSH check was added before moving a VM from pending to ready.
However, the result of that check did not matter and move_pending would
still be called. This moves the move_pending call to within the begin
block that holds the SSH check. If the check fails, then only
fail_pending will be called.
2015-09-17 12:54:29 -07:00
Scott Schneider
5b6985c3a7 (QENG-2952) Check that SSH is available
SSH should be available before a VM is moved from the 'pending' queue to
'ready'.

`check_ssh` should probably be a function in the tradition of DRY; I'm
going to hopefully follow up this PR with a `Vmpooler::Utility` library.
2015-09-17 11:12:51 -07:00
Scott Schneider
fe65d5b11b Merge branch 'master' into host_snapshots 2015-07-16 10:42:16 -07:00
Scott Schneider
1c3045fd65 Host snapshot functionality 2015-07-16 10:29:49 -07:00
Scott Schneider
821ffd866a Log empty pools
Make a note in the logfile when a pool is detected to be empty.

Also:

- vmpooler__empty__<pool> Redis key to determine when to log
- lifetime/TTL checks moved to `_check_running_vm` method
  - no longer pay attention to VMware-based 'host.runtime.bootTime'

This PR implements a bunch of other stuff to account for rspec testing:

- Thread creation and looping in `check_pool`
- Everything else in `_check_pool`
2015-07-07 11:12:46 -07:00
Colin
dec95ba693 (QENG-2360) check_running_vm Spec Tests
Add spec tests for pool_manager#check_running_vm. In the process of
writing these tests, the method was broken in to smaller methods for
testability reasons.
2015-05-19 10:23:31 -07:00
Scott Schneider
818b92100b running-to-lifetime comparison should be 'greater than or equal to' 2015-04-09 12:35:13 -07:00
Scott Schneider
f9de28236b Auto-expire Redis metadata key via Redis EXPIRE
This commit also removed the unnecessary Vmpooler::Janitor lib
2015-04-07 11:01:37 -07:00
Colin
e6ee6b1257 (QENG-1906) Break apart check_pending_vm and add spec tests
This commit breaks apart the method check_pending_vm in to three,
smaller methods that are easier to test. There are no functionality
changes or bug fixes.

This adds spec tests for the overall functionality that was
check_pending_vm.
2015-04-01 15:42:28 -07:00
Colin
1408f35867 (QENG-1906) Refactor initialize to allow config passing
Prior to this commit, several pieces of vmpooler performed configuration
and initialization steps within 'initialize'. This made it difficult to
pass in mock objects for testing purposes.

This commit performs a single configuration and passes the results to
the various pieces of vmpooler.
2015-03-30 14:23:06 -07:00
Scott Schneider
7b97e58e0f Clean up Redis VM objects after redis['data_ttl'] 2015-03-20 10:25:51 -07:00
Scott Schneider
48a9ef0dfd Store checkout and destroy timestamps 2015-03-20 09:57:47 -07:00
Scott Schneider
18703efd60 Guard against nil VM clone time 2015-03-04 13:06:49 -08:00
Scott Schneider
ba01b60541 Store template (pool) name with hostname in Redis metric keys 2015-03-03 15:21:06 -08:00
Scott Schneider
a2a8515728 Track 'boot' (pending -> ready) durations 2015-03-03 15:16:17 -08:00
Scott Schneider
b3a4f9c0a6 Rubocop --auto-correct syntax fixups 2015-02-06 11:08:54 -08:00
Scott Schneider
d6ade5ebef Store and retrieve daily clone statistics from Redis db 2015-02-03 14:14:12 -08:00
Scott Schneider
ecd17606f6 Record clone times in Redis, add a '/status' API endpoint 2015-01-27 12:59:11 -08:00
Scott Schneider
b54d42aea4 Allow for a globally-configurable 'pending' timeout 2015-01-08 14:16:13 -08:00
Scott Schneider
4363d8e067 Store template name in vmpooler__vm__$vm Redis hash 2014-11-03 09:27:28 -08:00
Scott Schneider
f9f3ae26ba Allow per-pool override for clone_target 2014-08-27 16:45:29 -07:00
Scott Schneider
5078f8f1a0 Increase sleep time = decrease CPU usage 2014-08-26 18:09:55 -07:00
Scott Schneider
c41d8dc3e2 Correctly log a VM's lifetime 2014-08-22 13:35:18 -07:00
Scott Schneider
b836ceea90 Custom-set VM lifetimes override system-wide 2014-08-22 11:04:38 -07:00
Scott Schneider
76ef04c100 Fixing typo 2014-07-28 10:55:42 -07:00
Scott Schneider
e8125e7702 Allow a 'clone_target' configuration setting
If set, this setting will enable "fake DRS", cloning VMs onto the host
in the specified cluster containing the least amount of VMs.
2014-07-28 10:51:45 -07:00
Scott Schneider
4f3c5323d8 Don't use VMware resource pools for organization
This commit removes support for VMware 'resource pool' functionality
entirely, as VMware installations without the DRS feature enabled are
unable to configure or use resource pools.

Also, resource pools should have never been used for organization;
that's what folders are for.
2014-07-21 13:49:57 -07:00
Scott Schneider
3af680f860 Allow a configurable Graphite namespace (prefix) 2014-03-06 10:53:27 -08:00
Scott Schneider
60eead6455 Centralize external Gem loading 2014-03-05 13:19:43 -08:00