diff --git a/app/controllers/api/v2/registration_controller.rb b/app/controllers/api/v2/registration_controller.rb index 9d442f800a4..6b6885e08ae 100644 --- a/app/controllers/api/v2/registration_controller.rb +++ b/app/controllers/api/v2/registration_controller.rb @@ -77,6 +77,7 @@ def host ActiveRecord::Base.transaction do find_host prepare_host + associate_vm setup_host_params host_setup_extension @template = @host.initial_configuration_template @@ -121,6 +122,19 @@ def prepare_host @host.save! end + def associate_vm + if @host.compute_resource + associator = ComputeResourceHostAssociator.new(@host.compute_resource) + associator.associate_host(@host) + else + ComputeResource.all.each do |compute_resource| + associator = ComputeResourceHostAssociator.new(compute_resource) + associator.associate_host(@host) + break if @host.uuid + end + end + end + # Extension point for plugins def host_setup_extension end diff --git a/app/models/compute_resource.rb b/app/models/compute_resource.rb index a555156e9bd..bb6a9472eb6 100644 --- a/app/models/compute_resource.rb +++ b/app/models/compute_resource.rb @@ -457,6 +457,19 @@ def associate_by(name, attributes) first end + def associated_vm(host) + vms(:eager_loading => true).find { |vm| associate_by_host("mac", vm.interfaces.map(&:mac), host) } + end + + def associate_by_host(name, attributes, host) + attributes = Array.wrap(attributes).map { |mac| Net::Validations.normalize_mac(mac) } if name == 'mac' + Host.authorized(:view_hosts, Host).where(:id => host.id).joins(:primary_interface). + where(:nics => {:primary => true}). + where(ActiveRecord::Base.sanitize_sql("nics.#{name}") => attributes). + readonly(false). + first + end + private def set_vm_volumes_attributes(vm, vm_attrs) diff --git a/app/models/compute_resources/foreman/model/ec2.rb b/app/models/compute_resources/foreman/model/ec2.rb index 930b3316b60..55b5b8f0bdd 100644 --- a/app/models/compute_resources/foreman/model/ec2.rb +++ b/app/models/compute_resources/foreman/model/ec2.rb @@ -147,6 +147,10 @@ def associated_host(vm) associate_by("ip", [vm.public_ip_address, vm.private_ip_address]) end + def associated_vm(host) + vms(:eager_loading => true).find { |vm| associate_by_host("ip", [vm.public_ip_address, vm.private_ip_address], host) } + end + def user_data_supported? true end diff --git a/app/models/compute_resources/foreman/model/openstack.rb b/app/models/compute_resources/foreman/model/openstack.rb index dfc54d6843e..67bdb201924 100644 --- a/app/models/compute_resources/foreman/model/openstack.rb +++ b/app/models/compute_resources/foreman/model/openstack.rb @@ -204,6 +204,10 @@ def associated_host(vm) associate_by("ip", [vm.floating_ip_address, vm.private_ip_address].compact) end + def associated_vm(host) + vms(:eager_loading => true).find { |vm| associate_by_host("ip", [vm.floating_ip_address, vm.private_ip_address].compact, host) } + end + def flavor_name(flavor_ref) client.flavors.get(flavor_ref).try(:name) end diff --git a/app/services/compute_resource_host_associator.rb b/app/services/compute_resource_host_associator.rb index b746588c2a4..cef95b09703 100644 --- a/app/services/compute_resource_host_associator.rb +++ b/app/services/compute_resource_host_associator.rb @@ -15,6 +15,17 @@ def associate_hosts(vms = compute_resource.vms(:eager_loading => true)) end end + def associate_host(host) + vm = compute_resource.associated_vm(host) + if vm.present? + host.associate!(compute_resource, vm) + @hosts << host + end + rescue StandardError => e + @fail_count += 1 + Foreman::Logging.exception("Could not associate host #{host}", e) + end + private def associate_vm(vm)