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

add physical server profile template #81

Merged
merged 20 commits into from
Nov 30, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -6,6 +6,7 @@ def collect
decomissioned_servers
physical_racks
physical_server_profiles
physical_server_profile_templates
firmware_firmware_summaries
network_elements
physical_chassis
Expand Down Expand Up @@ -50,6 +51,13 @@ def physical_server_profiles
_log.error("Collecting process of Server Profiles has failed: #{e.response_body}. There might be a potential license issue.")
end

def physical_server_profile_templates
@physical_server_profile_templates ||= server_api.get_server_profile_template_list.results
rescue IntersightClient::ApiError => e
@physical_server_profile_templates = {}
_log.error("Collecting process of Server Profiles Templates has failed: #{e.response_body}. There might be a potential license issue.")
end

def device_contract_informations_by_moid
@device_contract_informations_by_moid ||= device_contract_informations.index_by do |dev_contract_info|
dev_contract_info.registered_device.moid
Expand Down Expand Up @@ -156,6 +164,10 @@ def server_api
@server_api ||= IntersightClient::ServerApi.new(api_client)
end

def bulk_api
@bulk_api ||= IntersightClient::BulkApi.new(api_client)
end

# API key and keyid configuration
def api_client
# Sets API key and keyid for the manager
Expand Down
Expand Up @@ -5,6 +5,7 @@ def parse
physical_racks
physical_chassis
physical_server_profiles
physical_server_profile_templates
physical_switches
end

Expand Down Expand Up @@ -102,6 +103,13 @@ def physical_switches
end
end

def physical_server_profile_templates
collector.physical_server_profile_templates.each do |c|
# build collection physical_server_profile_templates
build_physical_server_profile_templates(c)
end
end

def physical_server_profiles
collector.physical_server_profiles.each do |c|
# build collection physical_server_profiles
Expand Down Expand Up @@ -465,6 +473,18 @@ def build_physical_server_profiles(physical_server_profile)
)
end

def build_physical_server_profile_templates(physical_server_profile_template)
# Builds out collection physical_server_profile_templates
# Object types:
# - physical_server_profile_template - ServerProfileTemplate, object obtained by intersight client
# Returns:
# ManageIQ's object ManageIQ::Providers::CiscoIntersight::PhysicalInfraManager::PhysicalServerProfileTemplate
persister.physical_server_profile_templates.build(
:ems_ref => physical_server_profile_template.moid,
:name => physical_server_profile_template.name
)
end

# Helper methods to the ones that directly build inventory collections

def get_health_state(object)
Expand Down
Expand Up @@ -19,6 +19,7 @@ def initialize_physical_infra_collections
physical_switch_firmwares
physical_switch_network_ports
physical_server_profiles
physical_server_profile_templates
].each do |name|
add_collection(physical_infra, name)
end
Expand Down
Expand Up @@ -7,6 +7,7 @@ class PhysicalInfraManager < ManageIQ::Providers::PhysicalInfraManager
require_nested :EventCatcher
require_nested :EventParser
require_nested :PhysicalServer
require_nested :PhysicalServerProfileTemplate

include Vmdb::Logging
include ManagerMixin
Expand Down
@@ -0,0 +1,43 @@
class ManageIQ::Providers::CiscoIntersight::PhysicalInfraManager::EmsRefreshWorkflow < ManageIQ::Providers::EmsRefreshWorkflow
def run_native_op
queue_signal(:poll_native_task)
end
alias start run_native_op

def poll_native_task
wf_api = ext_management_system.connect(:service=>'WorkflowApi')
native_object_response = wf_api.get_workflow_workflow_info_list({:filter => "Input.workflowContext.WorkflowType eq 'serverconfig' and Input.workflowContext.WorkflowSubtype eq 'Deploy' and Input.workflowContext.InitiatorCtx.InitiatorMoid eq '#{options[:native_task_id]}'", :select => "Status"})
native_object = native_object_response.results[0]

case native_object.status
when "FAILED"
signal(:abort, "Task failed")
when "TIME_OUT"
signal(:abort, "Task time out")
when "COMPLETED"
queue_signal(:refresh)
else
queue_signal(:poll_native_task, :deliver_on => Time.now.utc + options[:interval])
end
rescue => err
_log.log_backtrace(err)
signal(:abort, err.message, "error")
end

def refresh
task_ids = EmsRefresh.queue_refresh_task(ext_management_system)
if task_ids.blank?
process_error("Failed to queue refresh", "error")
queue_signal(:error)
else
context[:refresh_task_ids] = task_ids
update!(:context => context)

queue_signal(:poll_refresh)
end
end
Comment on lines +27 to +38
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE this looks identical to the method in core except for the target_entity/ext_management_system bit. It would be nice to add a refresh_target method in core that defaults to target_entity if targeted_refresh is supported and ext_management_system otherwise which would allow you to override it and simply return ext_management_system if you just want to do a full.

Would be a good follow-up PR if you want to implement that in core.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


def ext_management_system
@ext_management_system ||= ExtManagementSystem.find(options[:ems_id])
end
end
@@ -0,0 +1,64 @@
module ManageIQ::Providers::CiscoIntersight
class PhysicalInfraManager::PhysicalServerProfileTemplate < ::PhysicalServerProfileTemplate
def self.display_name(number = 1)
n_('Physical Server Profile Template (CiscoIntersight)', 'Physical Server Profile Template (CiscoIntersight)', number)
end

def provider_object(connection)
connection.find!(ems_ref)
end

def deploy_server_from_template(server_id, profile_name)
# Load the gem
require 'intersight_client'

bulk = ext_management_system.connect(:service=>'BulkApi')
cloner = IntersightClient::BulkMoCloner.new({:sources => [{"Moid" => ems_ref, "ObjectType" => 'server.ProfileTemplate'}], :targets => [{"Name" => profile_name, :ObjectType => 'server.Profile'}]})

# create a new server profile from server profile template

result = bulk.create_bulk_mo_cloner(cloner)
new_profile_moid = result.responses[0].body.moid

server_profile_updated = IntersightClient::ServerProfile.new(
{
:assigned_server => {"Moid" => server_id, "ObjectType" => "compute.Blade"},
:server_assignment_mode => "Static",
:target_platform => nil,
:uuid_address_type => nil
}
)
# assign the profile server to the selected server
server_api = ext_management_system.connect(:service=>'ServerApi')
begin
result = server_api.patch_server_profile(new_profile_moid, server_profile_updated, {})
_log.info("Server profile successfully assigned with server #{server_id} (ems_ref #{result.assigned_server.moid})")
rescue IntersightClient::ApiError => e
_log.error("Assign server failed for server profile (ems_ref #{new_profile_moid}) server (ems_ref #{server_id})")
raise MiqException::Error, "Assign server failed: #{e.response_body}"
end

server_profile_updated = {'Action' => "Deploy"}
# deploy the server
begin
result = server_api.patch_server_profile(new_profile_moid, server_profile_updated, {})
_log.info("Server profile #{result.config_context.control_action} initiated successfully")
rescue IntersightClient::ApiError => e
_log.error("#{action} server failed for server profile (ems_ref #{new_profile_moid})")
raise MiqException::Error, "#Deploy server failed: #{e.response_body}"
end

# create a job to refresh the cisco intersight provider after the deployment finished
options = {
:target_class => self.class.name,
:target_id => id,
:ems_id => ext_management_system.id,
:native_task_id => new_profile_moid,
:interval => 30.seconds,
:target_option => "deploy"
}

ManageIQ::Providers::CiscoIntersight::PhysicalInfraManager::EmsRefreshWorkflow.create_job(options).tap(&:signal_start)
end
end
end