Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orchestration Stack and Cloud Tenant targeted refresh #86

Merged
merged 1 commit into from
Oct 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def parse_ems_event_targets(ems_event)
target_collection = ManagerRefresh::TargetCollection.new(:manager => ems_event.ext_management_system, :event => ems_event)
if ems_event.event_type.start_with?("compute.instance")
collect_compute_instance_references!(target_collection, ems_event)
elsif ems_event.event_type.start_with?("identity.project")
collect_identity_tenant_references!(target_collection, ems_event)
elsif ems_event.event_type.start_with?("orchestration.stack")
collect_orchestration_stack_references!(target_collection, ems_event)
end

target_collection.targets
Expand All @@ -39,4 +43,15 @@ def collect_compute_instance_references!(target_collection, ems_event)
instance_id = ems_event.full_data.fetch_path(:payload, 'instance_id')
add_target(target_collection, :vms, instance_id) if instance_id
end

def collect_identity_tenant_references!(target_collection, ems_event)
tenant_id = ems_event.full_data.fetch_path(:payload, 'project_id') || ems_event.full_data.fetch_path(:payload, 'initiator', 'project_id')
add_target(target_collection, :cloud_tenants, tenant_id) if tenant_id
end

def collect_orchestration_stack_references!(target_collection, ems_event)
stack_id = ems_event.full_data.fetch_path(:payload, 'stack_id')
tenant_id = ems_event.full_data.fetch_path(:payload, 'tenant_id')
target_collection.add_target(:association => :orchestration_stacks, :manager_ref => {:ems_ref => stack_id}, :options => {:tenant_id => tenant_id})
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ def references(collection)
target.manager_refs_by_association.try(:[], collection).try(:[], :ems_ref).try(:to_a) || []
end

def orchestration_stack_references
@orchestration_stack_references ||= target.targets.select { |x| x.kind_of?(ManagerRefresh::Target) && x.association == :orchestration_stacks }
end

def name_references(collection)
target.manager_refs_by_association.try(:[], collection).try(:[], :name).try(:to_a) || []
end
Expand Down Expand Up @@ -69,17 +73,22 @@ def floating_ips
end

def orchestration_stacks
return [] if references(:orchestration_stacks).blank?
return [] if orchestration_stack_references.blank?
return @orchestration_stacks if @orchestration_stacks.any?
@orchestration_stacks = orchestration_service.handled_list(:stacks, :show_nested => true).collect(&:details).select do |s|
references(:orchestration_stacks).include?(s.id)
@orchestration_stacks = orchestration_stack_references.collect do |target|
get_orchestration_stack(target.manager_ref[:ems_ref], target.options[:tenant_id])
end.compact
rescue Excon::Errors::Forbidden
# Orchestration service is detected but not open to the user
$log.warn("Skip collecting stack references during targeted refresh because the user cannot access the orchestration service.")
[]
end

def get_orchestration_stack(stack_id, tenant_id)
tenant = memoized_get_tenant(tenant_id)
safe_get { @os_handle.detect_orchestration_service(tenant.try(:name)).stacks.get(stack_id) }
end

def vms
return [] if references(:vms).blank?
return @vms if @vms.any?
Expand Down Expand Up @@ -108,10 +117,18 @@ def tenants
return [] if references(:cloud_tenants).blank?
return @tenants if @tenants.any?
@tenants = references(:cloud_tenants).collect do |cloud_tenant_id|
safe_get { identity_service.tenants.find_by_id(cloud_tenant_id) }
memoized_get_tenant(cloud_tenant_id)
end.compact
end

def memoized_get_tenant(tenant_id)
return nil if tenant_id.blank?
@tenant_memo ||= Hash.new do |h, key|
h[key] = safe_get { identity_service.tenants.find_by_id(key) }
end
@tenant_memo[tenant_id]
end

def key_pairs
return [] if references(:key_pairs).blank?
return @key_pairs if @key_pairs.any?
Expand Down Expand Up @@ -180,19 +197,19 @@ def parse_targets!
target.targets.each do |t|
case t
when Vm
parse_vm_target!(t)
add_simple_target!(:vms, t.ems_ref)
when CloudTenant
add_simple_target!(:cloud_tenants, t.ems_ref)
when OrchestrationStack
add_simple_target!(:orchestration_stacks, t.ems_ref)
end
end
end

def parse_vm_target!(t)
add_simple_target!(:vms, t.ems_ref)
end

def add_simple_target!(association, ems_ref)
def add_simple_target!(association, ems_ref, options = {})
return if ems_ref.blank?

target.add_target(:association => association, :manager_ref => {:ems_ref => ems_ref})
target.add_target(:association => association, :manager_ref => {:ems_ref => ems_ref}, :options => options)
end

def infer_related_ems_refs!
Expand All @@ -203,6 +220,42 @@ def infer_related_ems_refs!
infer_related_vm_ems_refs_db!
infer_related_vm_ems_refs_api!
end
unless references(:cloud_tenants).blank?
infer_related_cloud_tenant_ems_refs_db!
infer_related_cloud_tenant_ems_refs_api!
end
unless references(:orchestration_stacks).blank?
infer_related_orchestration_stacks_ems_refs_db!
infer_related_orchestration_stacks_ems_refs_api!
end
end

def infer_related_orchestration_stacks_ems_refs_db!
changed_stacks = manager.orchestration_stacks.where(:ems_ref => references(:orchestration_stacks))
changed_stacks.each do |stack|
add_simple_target!(:cloud_tenants, stack.cloud_tenant.ems_ref) unless stack.cloud_tenant.nil?
add_simple_target!(:orchestration_stacks, stack.parent.ems_ref, :tenant_id => stack.parent.cloud_tenant.ems_ref) unless stack.parent.nil?
end
end

def infer_related_orchestration_stacks_ems_refs_api!
orchestration_stacks.each do |stack|
add_simple_target!(:orchestration_stacks, stack.parent, :tenant_id => stack.service.current_tenant["id"]) unless stack.parent.blank?
add_simple_target!(:cloud_tenants, stack.service.current_tenant["id"]) unless stack.service.current_tenant["id"].blank?
end
end

def infer_related_cloud_tenant_ems_refs_db!
changed_tenants = manager.cloud_tenants.where(:ems_ref => references(:cloud_tenants))
changed_tenants.each do |tenant|
add_simple_target!(:cloud_tenants, tenant.parent.ems_ref) unless tenant.parent.nil?
end
end

def infer_related_cloud_tenant_ems_refs_api!
tenants.each do |tenant|
add_simple_target(:cloud_tenants, tenant.try(:parent_id)) unless tenant.try(:parent_id).blank?
end
end

def infer_related_vm_ems_refs_db!
Expand All @@ -212,7 +265,7 @@ def infer_related_vm_ems_refs_db!
stack = vm.orchestration_stack
all_stacks = ([stack] + (stack.try(:ancestors) || [])).compact

all_stacks.collect(&:ems_ref).compact.each { |ems_ref| add_simple_target!(:orchestration_stacks, ems_ref) }
all_stacks.each { |s| add_simple_target!(:orchestration_stacks, s.ems_ref, :tenant_id => s.cloud_tenant.id) }
vm.cloud_networks.collect(&:ems_ref).compact.each { |ems_ref| add_simple_target!(:cloud_networks, ems_ref) }
vm.floating_ips.collect(&:address).compact.each { |address| add_simple_target!(:floating_ips, address) }
vm.network_ports.collect(&:ems_ref).compact.each do |ems_ref|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ def initialize_inventory_collections
# Top level models with direct references for Cloud
add_inventory_collections_with_references(
cloud,
%i(vms miq_templates availability_zones orchestration_stacks cloud_tenants flavors)
%i(vms miq_templates availability_zones orchestration_stacks cloud_tenants flavors),
:builder_params => {:ext_management_system => manager}
)

add_inventory_collection_with_references(
Expand Down
12 changes: 12 additions & 0 deletions lib/vcr_recorder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ def load_credentials

file_name = File.join(vcr_base_dir, "refresher_rhos_#{env_name}_vm_targeted_refresh.yml")
change_file(file_name, OBFUSCATED_PASSWORD, env["password"], OBFUSCATED_IP, env["ip"])

file_name = File.join(vcr_base_dir, "refresher_rhos_#{env_name}_stack_targeted_refresh.yml")
change_file(file_name, OBFUSCATED_PASSWORD, env["password"], OBFUSCATED_IP, env["ip"])

file_name = File.join(vcr_base_dir, "refresher_rhos_#{env_name}_tenant_targeted_refresh.yml")
change_file(file_name, OBFUSCATED_PASSWORD, env["password"], OBFUSCATED_IP, env["ip"])
end
end

Expand Down Expand Up @@ -81,6 +87,12 @@ def obfuscate_credentials

file_name = File.join(vcr_base_dir, "refresher_rhos_#{env_name}_vm_targeted_refresh.yml")
change_file(file_name, env["password"], OBFUSCATED_PASSWORD, env["ip"], OBFUSCATED_IP)

file_name = File.join(vcr_base_dir, "refresher_rhos_#{env_name}_stack_targeted_refresh.yml")
change_file(file_name, env["password"], OBFUSCATED_PASSWORD, env["ip"], OBFUSCATED_IP)

file_name = File.join(vcr_base_dir, "refresher_rhos_#{env_name}_tenant_targeted_refresh.yml")
change_file(file_name, env["password"], OBFUSCATED_PASSWORD, env["ip"], OBFUSCATED_IP)
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,23 @@ def assert_specific_tenant
end
end

def assert_targeted_tenant
assert_objects_with_hashes([CloudTenant.find_by(:name => "EmsRefreshSpec-Project")], [identity_data.projects[1]])

identity_data.projects.each do |project|
next unless project[:__parent_name]

parent_id = CloudTenant.find_by(:name => project[:__parent_name]).try(:id)
cloud_tenant = CloudTenant.find_by(:name => project[:name])
expect(cloud_tenant.parent_id).to eq(parent_id)
end

CloudTenant.all.each do |tenant|
expect(tenant).to be_kind_of(CloudTenant)
expect(tenant.ext_management_system).to eq(@ems)
end
end

def assert_key_pairs
assert_objects_with_hashes(ManageIQ::Providers::Openstack::CloudManager::AuthKeyPair.all, compute_data.key_pairs)
end
Expand Down Expand Up @@ -679,6 +696,15 @@ def assert_specific_stacks
[:template, :parameters])
end

def assert_targeted_stack
stack_target = OrchestrationStack.find_by(:name => "stack1")
assert_objects_with_hashes([stack_target],
[orchestration_data.stacks[0]],
orchestration_data.stack_translate_table,
{},
[:template, :parameters])
end

def assert_specific_vms
all_vms = ManageIQ::Providers::Openstack::CloudManager::Vm.all
if orchestration_supported?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
end

context "when configured with skips" do

it "will not parse the ignored items" do
with_cassette(@environment, @ems) do
EmsRefresh.refresh(@ems)
Expand Down Expand Up @@ -80,5 +79,33 @@
end
end
end

it "will perform a targeted stack refresh against RHOS #{@environment}" do
# stack1
stack_target = ManagerRefresh::Target.new(:manager => @ems,
:association => :orchestration_stacks,
:manager_ref => {:ems_ref => "091e1e54-e01c-4ec5-a0ab-b00bee4d425c"},
:options => {:tenant_id => "69f8f7205ade4aa59084c32c83e60b5a"})
2.times do # Run twice to verify that a second run with existing data does not change anything
with_cassette("#{@environment}_stack_targeted_refresh", @ems) do
EmsRefresh.refresh(stack_target)
assert_targeted_stack
end
end
end

it "will perform a targeted tenant refresh against RHOS #{@environment}" do
# EmsRefreshSpec-Project
stack_target = ManagerRefresh::Target.new(:manager => @ems,
:association => :cloud_tenants,
:manager_ref => {:ems_ref => "69f8f7205ade4aa59084c32c83e60b5a"})
2.times do # Run twice to verify that a second run with existing data does not change anything
with_cassette("#{@environment}_tenant_targeted_refresh", @ems) do
EmsRefresh.refresh(stack_target)
expect(CloudTenant.count).to eq(1)
assert_targeted_tenant
end
end
end
end
end
Loading