|
| 1 | +require_relative "event_parser" |
| 2 | + |
| 3 | +class EventCatcher |
| 4 | + def initialize(ems, endpoint, authentication, messaging, logger, page_size = 20) |
| 5 | + @ems = ems |
| 6 | + @endpoint = endpoint |
| 7 | + @authentication = authentication |
| 8 | + @logger = logger |
| 9 | + @messaging = messaging |
| 10 | + @page_size = page_size |
| 11 | + end |
| 12 | + |
| 13 | + def run! |
| 14 | + vim = connect |
| 15 | + event_history_collector = create_event_history_collector(vim, page_size) |
| 16 | + property_filter = create_property_filter(vim, event_history_collector) |
| 17 | + |
| 18 | + notify_started |
| 19 | + |
| 20 | + logger.info("Collecting events...") |
| 21 | + |
| 22 | + wait_for_updates(vim) do |property_change| |
| 23 | + logger.info(property_change.name) |
| 24 | + next unless property_change.name.match?(/latestPage.*/) |
| 25 | + |
| 26 | + events = Array(property_change.val).map do |event| |
| 27 | + EventParser.parse_event(event).merge(:ems_id => ems["id"]) |
| 28 | + end |
| 29 | + |
| 30 | + logger.info(events.to_json) |
| 31 | + |
| 32 | + publish_events(events) |
| 33 | + end |
| 34 | + rescue Interrupt |
| 35 | + # Catch SIGINT |
| 36 | + ensure |
| 37 | + notify_stopping |
| 38 | + property_filter&.DestroyPropertyFilter |
| 39 | + event_history_collector&.DestroyCollector |
| 40 | + vim&.close |
| 41 | + end |
| 42 | + |
| 43 | + def stop! |
| 44 | + end |
| 45 | + |
| 46 | + private |
| 47 | + |
| 48 | + attr_reader :ems, :endpoint, :authentication, :logger, :messaging, :page_size |
| 49 | + |
| 50 | + def connect |
| 51 | + vim_opts = { |
| 52 | + :ns => 'urn:vim25', |
| 53 | + :ssl => true, |
| 54 | + :host => endpoint["hostname"], |
| 55 | + :port => endpoint["port"] || 443, |
| 56 | + :insecure => endpoint["verify_ssl"] == OpenSSL::SSL::VERIFY_NONE, |
| 57 | + :path => '/sdk', |
| 58 | + :rev => '7.0', |
| 59 | + } |
| 60 | + |
| 61 | + RbVmomi::VIM.new(vim_opts).tap do |vim| |
| 62 | + vim.rev = vim.serviceContent.about.apiVersion |
| 63 | + vim.serviceContent.sessionManager.Login( |
| 64 | + :userName => authentication["userid"], |
| 65 | + :password => authentication["password"] |
| 66 | + ) |
| 67 | + end |
| 68 | + end |
| 69 | + |
| 70 | + def create_event_history_collector(vim, page_size) |
| 71 | + filter = RbVmomi::VIM.EventFilterSpec() |
| 72 | + |
| 73 | + event_manager = vim.serviceContent.eventManager |
| 74 | + event_manager.CreateCollectorForEvents(:filter => filter).tap do |c| |
| 75 | + c.SetCollectorPageSize(:maxCount => page_size) |
| 76 | + end |
| 77 | + end |
| 78 | + |
| 79 | + def create_property_filter(vim, event_history_collector) |
| 80 | + vim.propertyCollector.CreateFilter( |
| 81 | + :spec => RbVmomi::VIM.PropertyFilterSpec( |
| 82 | + :objectSet => [ |
| 83 | + RbVmomi::VIM.ObjectSpec( |
| 84 | + :obj => event_history_collector |
| 85 | + ) |
| 86 | + ], |
| 87 | + :propSet => [ |
| 88 | + RbVmomi::VIM.PropertySpec( |
| 89 | + :type => event_history_collector.class.wsdl_name, |
| 90 | + :all => false, |
| 91 | + :pathSet => ["latestPage"] |
| 92 | + ) |
| 93 | + ] |
| 94 | + ), |
| 95 | + :partialUpdates => true |
| 96 | + ) |
| 97 | + end |
| 98 | + |
| 99 | + def wait_for_updates(vim, &block) |
| 100 | + version = nil |
| 101 | + options = RbVmomi::VIM.WaitOptions(:maxWaitSeconds => 60) |
| 102 | + |
| 103 | + loop do |
| 104 | + update_set = vim.propertyCollector.WaitForUpdatesEx(:version => version, :options => options) |
| 105 | + heartbeat |
| 106 | + next if update_set.nil? |
| 107 | + |
| 108 | + version = update_set.version |
| 109 | + |
| 110 | + Array(update_set.filterSet).each do |property_filter_update| |
| 111 | + Array(property_filter_update.objectSet).each do |object_update| |
| 112 | + next unless object_update.kind == "modify" |
| 113 | + |
| 114 | + Array(object_update.changeSet).each(&block) |
| 115 | + end |
| 116 | + end |
| 117 | + end |
| 118 | + end |
| 119 | + |
| 120 | + def publish_events(events) |
| 121 | + events.each do |event| |
| 122 | + messaging_client.publish_topic( |
| 123 | + :service => "manageiq.ems", |
| 124 | + :sender => ems["id"], |
| 125 | + :event => event[:event_type], |
| 126 | + :payload => event |
| 127 | + ) |
| 128 | + end |
| 129 | + end |
| 130 | + |
| 131 | + def messaging_client |
| 132 | + @messaging_client ||= ManageIQ::Messaging::Client.open( |
| 133 | + messaging.merge(:client_ref => "vmware-event-catcher-#{ems["id"]}") |
| 134 | + ) |
| 135 | + end |
| 136 | + |
| 137 | + def notify_started |
| 138 | + SdNotify.ready if ENV.fetch("NOTIFY_SOCKET", nil) |
| 139 | + end |
| 140 | + |
| 141 | + def heartbeat |
| 142 | + SdNotify.watchdog if ENV.fetch("NOTIFY_SOCKET", nil) |
| 143 | + end |
| 144 | + |
| 145 | + def notify_stopping |
| 146 | + SdNotify.stopping if ENV.fetch("NOTIFY_SOCKET", nil) |
| 147 | + end |
| 148 | +end |
0 commit comments