(QENG-5305) Improve vmpooler host selection#242
Conversation
f768ec3 to
0d8c131
Compare
| finish = migrate_vm_and_record_timing(vm_name, pool_name, parent_host_name, host_name, provider) | ||
| $logger.log('s', "[>] [#{pool_name}] '#{vm_name}' migrated from #{parent_host_name} to #{host_name} in #{finish} seconds") | ||
| $redis.sadd('vmpooler__migration', vm_name) | ||
| target_host_name = select_next_host(provider_name, vm['datacenter'], vm['cluster'], vm['architecture']) |
There was a problem hiding this comment.
what if select_next_host returns 'nil'?
There was a problem hiding this comment.
It should cause a failure to be logged reporting that vm migration failed with an error raised from lib/vmpooler/providers/vsphere.rb:90 when migrate_vm is called. Perhaps it's worth emitting a more clear error that there was no target host provided.
There was a problem hiding this comment.
I think it will call the next line migrate_vm_and_record_timing() with target_host_name = nil which seems to go all the way down to the vcenter API to try and get the host by dns name?
We should fail earlier than that.
There was a problem hiding this comment.
This will now fail if the datacenter, or cluster are missing, and if the target is empty, before trying to run the methods with bad data.
|
|
||
| def select_next_host(provider_name, datacenter, cluster, architecture) | ||
| provider_hosts = $provider_hosts | ||
| host = provider_hosts[provider_name][datacenter][cluster]['architectures'][architecture][0] |
There was a problem hiding this comment.
I think if provider_hosts[provider_name][datacenter][cluster]['architectures'][architecture] is a string then [0] could return the first character which is not what you probably expect here?
There was a problem hiding this comment.
That's true. It's populated by select_least_used_hosts from lib/vmpooler/providers/vsphere.rb:607 which returns an array. Do you think I should be more explicit than this at some point to ensure an array is returned?
| end | ||
|
|
||
| hosts_with_arch_versions.each do |host| | ||
| architectures[host[2]] << [host[0], host[1], host[2]] |
There was a problem hiding this comment.
I find it hard to know what is in each index host[0], host[1], host[2]
There was a problem hiding this comment.
Yeah, it probably makes sense to put it in a hash and give these values some titles.
There was a problem hiding this comment.
This now uses a hash which should make clear what's being placed into this array.
glennsarti
left a comment
There was a problem hiding this comment.
There is vpshere specific concepts in the pool manager code (datacenter, cluster etc.). This should really all be in the vsphere provider.
| $threads = {} | ||
|
|
||
| # Host tracking object | ||
| $provider_hosts = {} |
There was a problem hiding this comment.
nit: REALLY REALLY try to avoid adding more global variables. Instance level should be enough.
There was a problem hiding this comment.
@glennsarti are you sure? I specifically require that this variable be accessible across all vmpooler provider threads.
|
@glennsarti how do you think this can be solved in the vsphere code when it needs to constrain and share data across pool manager operations? |
|
Sure
The only reason I can think of to keep state in the pool manager is to allow across-provider communication. Which is not (should not) be required for vsphere host selection. |
|
Ok. I have reworked this to do away with global variables and now use an instance variable in the provider to track host state on a per-provider basis. Tests pass, but I need to complete adding coverage for changes in vsphere and the base provider, but wanted to get this put here so I could get further feedback and input if there are still some clear changes needed. I still intend to address the other feedback. |
407af83 to
5252075
Compare
|
I've pushed an update here that moves migrate_vm to the vsphere provider. This should be a lot cleaner. I've addressed the confusing array population that @sbeaulie brought up earlier, and global variables are no longer used here in favor of instance variables on the provider, which works great. A mutex is added to ensure that all writing to provider_hosts in the provider is safe across all threads. I added one more change to this, which allows a user to specify whether vmpooler should manage host selection at clone time, or if it should be deferred to vsphere. If vmpooler is managing host selection it uses the same method now used for migrations. I'm still working through a handful of remaining tests on the vsphere provider, but this is all functional now. |
|
The jruby tests pass, the others are failing. If I'm reading travis correctly it looks as though setup to run the tests is what's failing. Tests do pass locally for me on ruby 2.3.5p376. |
5252075 to
2d343f0
Compare
|
|
||
| def migrate_vm(vm_name, pool_name, provider) | ||
| Thread.new do | ||
| begin |
There was a problem hiding this comment.
The provider really shouldn't need to contact redis for this. In this case the provider is just removing it from the queue. So the $redis.srem('vmpooler__migrating__' + pool_name, vm_name) should be called here PRIOR to the provider.migrate_vm call
There was a problem hiding this comment.
I took your suggestion and placed this prior to calling provider.migrate_vm.
| rescue => err | ||
| $logger.log('s', "[x] [#{pool_name}] '#{vm_name}' migration failed with an error: #{err}") | ||
| remove_vmpooler_migration_vm(pool_name, vm_name) | ||
| provider.remove_vmpooler_migration_vm(pool_name, vm_name, $redis) |
There was a problem hiding this comment.
This new method remove_vmpooler_migration_vm doesn't exist on the base and on inspection probably shouldn't be in a provider anyway. It's just removing the VM from the task queue.
By doing my previous suggestion, it's not needed as the VM is removed from the queue prior to be actioned in the provider.
| end | ||
| end | ||
|
|
||
| def migration_limit(migration_limit) |
There was a problem hiding this comment.
As the migration limit is now a per vSphere provider setting the documentation should be updated too.
There was a problem hiding this comment.
It probably should be a per vSphere provider setting, but it's still tracking migrations in redis and getting the setting from the global configuration section instead of checking the provider for this setting. I could add this change here. I was considering tackling that and the task_limit concept in a future change.
There was a problem hiding this comment.
Could be as simple as add in the docs migration limit (Only affects vSphere Provider)
There was a problem hiding this comment.
Oh I see what you're saying, not that it's a per provider setting, but rather that it is only a vsphere provider setting.
There was a problem hiding this comment.
yeah... The docs suggest its global but no longer.
There was a problem hiding this comment.
I added a mention in the example configuration file. I couldn't find another reference to migration_limit, please let me know if I've missed another location this should go.
| attr_reader :metrics | ||
| # Provider options passed in during initialization | ||
| attr_reader :provider_options | ||
| # Hash for tracking hosts for deployment |
There was a problem hiding this comment.
These settings seem vsphere specific. Perhaps instead of modifying base, which affects all providers, move them there
| @logger = logger | ||
| @metrics = metrics | ||
| @provider_name = name | ||
| @provider_hosts = {} |
There was a problem hiding this comment.
As above. vsphere provider specific.
| # inputs | ||
| # [String] pool_name : Name of the pool | ||
| # [String] vm_name : Name of the VM to migrate | ||
| # [Class] redis : Redis object |
There was a problem hiding this comment.
Apart from Redis, how is this method signature different from migrate_vm_to_host?. Is it just simply calling
migrate_vm_to_host(pool_name, vm_name, nil) ?
Redis is already a global variable, so no ed to pass it through. That should probably be a separate PR
There was a problem hiding this comment.
The main difference to me, beyond the redis part which as you point out shouldn't be there, is that there's no longer a need to provide the destination host name, so I figured keeping migrate_vm instead of migrate_vm_to_host made sense. I can change it if it makes more sense.
| migration_limit if migration_limit >= 1 | ||
| end | ||
|
|
||
| def migrate_vm(vm_name, pool_name, provider) |
There was a problem hiding this comment.
There is currently no way in Pool Manager to actually add a VM to the migration queue. So this PR will not have any affect yet. Is this by design?
There was a problem hiding this comment.
No, it's an oversight. It's fixed now.
|
I've updated this to include a fix for a behavior witnessed when running this over the weekend. Specifically, if no hosts are available for deployment check_time_finished is still updated in order to allow for things waiting on host selection to proceed. Previously, they would be stuck waiting and gum up pool_manager. Now, they will fail fast and report an error that makes clear why the clone or migration failed. Additionally, settings for utilization maximum and max age are exposed and documented. |
c81c83c to
1aed90b
Compare
This commit adds a global provider_hosts concept in order to allow checking cluster utilization once per interval for a given cluster and retain the results, reusing them for an interval, and tracking the least used set of hosts. Without this change each migration and clone operation inspect host utilization and state for each host in the cluster, which is computationally expensive for vsphere.
This commit adds the capability to create folders within an existing target folder. Without this change folders to support platforms targets need to be created manually.
This commit updates create_vm to target a cluster instead of an individual host for clone operations. Without this change cluster host utilization needs to be inspected for everyone clone operation.
This commit updates cluster host resource inspection to stop weighting memory as a part of the results. Additionally, instead of returning a single least used host a percentage of the eligible hosts with below average utilization are selected. Without this change host migration logic can cause cluster resource imbalances due to a single host being targeted for many migrations before the impacts of the migrations cause numbers to adjust.
This commit moves the migrate_vm logic to the vsphere provider. Without this change migrate_vm has lots of vsphere specific logic in pool_manager migrate_vm method.
This commit updates the providers to move provider_hosts under the vsphere provider, which is the only place it's applicable. Methods where redis is passed through are updated to remove this pass through and use the globally available redis object, where applicable. Remove_vmpooler_migration_vm method is not needed and is removed.
This commit updates host selection to write check_time_finished whether host retrieval was successful or not. Without this change when host selection fails threads waiting for host selection to complete will stuck waiting because check_time_finished doesn't update. Additionally, because it would leave checking => true it would not attempt to inspect and run host selection again. Host selection for clones and migrations now make clear that no hosts are available and fail logging a message. Without this change both migrations and clones would fail with cryptic error messages logged indicating clone and migrations failed. Additionally, this change makes max_age configurable so a user can specify that host selection should happen more or less frequently, as required for migrations or clone operations when host selection is enabled.
This change documents new vshpere specific parameters introduced related to host selection and folder creation. Without this change these paremeters are not documented.
This commit removes an unnecessary rescue that results in duplicate clone error messages. Without this change clone failures due to unavailable host resources are logged twice. A log message is added to specify the host the VM is running on when migration_limit is not set and migration is disabled. Lastly, when a migration fails it reports the host the VM is running on in addition to the reason for the failed migration.
96f68ec to
dd12125
Compare
|
@mattkirby Ready to merge this? |
|
Just about. I've got one more set of tests I'm going to push shortly after which this should be ready to go. That should cover the bits I've added that haven't had tests added yet. |
This commit adds tests for the remaining new vsphere functionality.
|
I've finished tests and this should be ready to go. |
This change updates how vmpooler creates VMs, migrates VMs, and significantly reduces strain placed upon vsphere appliances by eliminating duplicate host state inspection.
TODO: