{"action":"created","comment":{"url":"https://api.github.com/repos/Katello/katello/pulls/comments/44128276","id":44128276,"diff_hunk":"@@ -0,0 +1,213 @@\n+class MigrateContentHosts < ActiveRecord::Migration\n+  class Katello::HostCollectionAssociation < ActiveRecord::Base\n+    self.table_name = \"katello_system_host_collections\"\n+  end\n+\n+  class Katello::ErrataAssociation < ActiveRecord::Base\n+    self.table_name = \"katello_system_errata\"\n+  end\n+\n+  class Katello::RepositoryAssociation < ActiveRecord::Base\n+    self.table_name = \"katello_system_repositories\"\n+  end\n+\n+  class Katello::System < ActiveRecord::Base\n+    def backend_data\n+      @data ||= ::Katello::Resources::Candlepin::Consumer.get(uuid)\n+    end\n+\n+    def facts\n+      backend_data[:facts]\n+    end\n+\n+    self.table_name = \"katello_systems\"\n+\n+    has_many :system_activation_keys, :class_name => \"Katello::SystemActivationKey\", :dependent => :destroy\n+    has_many :activation_keys,\n+             :through => :system_activation_keys,\n+             :after_add    => :add_activation_key,\n+             :after_remove => :remove_activation_key\n+    belongs_to :content_view, :inverse_of => :systems\n+    belongs_to :environment, :class_name => \"Katello::KTEnvironment\", :inverse_of => :systems\n+    has_many :errata_associations, :class_name => \"Katello::ErrataAssociation\", :dependent => :destroy\n+    has_many :repository_associations, :class_name => \"Katello::RepositoryAssociation\", :dependent => :destroy\n+    has_many :host_collections, :class_name => \"Katello::HostCollectionAssociation\", :dependent => :destroy\n+    has_many :applicable_errata, :through => :system_errata, :class_name => \"Katello::Erratum\", :source => :erratum\n+    has_many :system_errata, :class_name => \"Katello::SystemErratum\", :dependent => :destroy, :inverse_of => :system\n+    has_many :bound_repositories, :through => :system_repositories, :class_name => \"Katello::Repository\", :source => :repository\n+    has_many :system_repositories, :class_name => \"Katello::SystemRepository\", :dependent => :destroy, :inverse_of => :system\n+\n+  end\n+\n+  def logger\n+    Rails.logger\n+  end\n+\n+  def create_content_aspect(host, system)\n+    logger.info(\"Creating content aspect for host #{host.name}.\")\n+    content_aspect = host.content_aspect = ::Katello::Host::ContentAspect.new(:content_view => system.content_view,\n+                                                                              :lifecycle_environment => system.environment)\n+    content_aspect.uuid = system.uuid\n+    content_aspect.bound_repositories = system.bound_repositories\n+    content_aspect.applicable_errata = system.applicable_errata\n+    content_aspect.save!\n+  end\n+\n+  def create_subscription_aspect(host, system)\n+    logger.info(\"Creating subscription aspect for host #{host.name}.\")\n+    subscription_aspect = host.subscription_aspect = Katello::Host::SubscriptionAspect.new\n+    subscription_aspect.activation_keys = system.activation_keys\n+    subscription_aspect.uuid = system.uuid\n+\n+    if system.backend_data\n+      subscription_aspect.service_level = system.backend_data['serviceLevel']\n+      subscription_aspect.release_version = system.backend_data['releaseVer']['releaseVer']\n+      subscription_aspect.last_checkin = system.backend_data['lastCheckin']\n+      subscription_aspect.autoheal = system.backend_data['autoheal']\n+    end\n+\n+    subscription_aspect.save!\n+  end\n+\n+  def get_systems_with_facts(systems)\n+    systems_to_remove = []\n+\n+    systems.each do |system|\n+      begin\n+        facts = system.facts\n+        unless facts\n+          systems_to_remove.push(system)\n+        end\n+      rescue RestClient::Exception\n+        systems_to_remove.push(system)\n+      end\n+    end\n+\n+    systems_to_remove.each do |system|\n+      logger.info(\"Content Host #{system.uuid} doesn't have candlepin information, unregistering.\")\n+      systems.delete(system)\n+      unregister_system(system)\n+    end\n+\n+    systems\n+  end\n+\n+  def group_systems_by_hostname(systems)\n+    system_hostnames = {}\n+\n+    systems.each do |system|\n+      hostname = system.facts['network.hostname']\n+\n+      if system_hostnames[hostname]\n+        system_hostnames[hostname].push(system)\n+      else\n+        system_hostnames[hostname] = [system]\n+      end\n+    end\n+\n+    system_hostnames\n+  end\n+\n+  def ensure_one_system_per_hostname(systems)\n+    # ensure only one system exists per hostname and unregister all except the last registered\n+    systems = get_systems_with_facts(systems)\n+    system_hostnames = group_systems_by_hostname(systems)\n+\n+    system_hostnames.each do |hostname, duplicate_systems|\n+      if duplicate_systems.count > 1\n+        logger.warn(\"Multiple content hosts with the hostname #{hostname} found, unregistering all except last registered.\")\n+        unregister_all_but_last_system(duplicate_systems)\n+      end\n+    end\n+  end\n+\n+  def unregister_system(system)\n+    logger.warn(\"Unregistering content host with UUID: #{system.uuid}\")\n+\n+    begin\n+      logger.info(\"Removing Candlepin consumer #{system.uuid}\")\n+      Katello::Resources::Candlepin::Consumer.destroy(system.uuid)\n+    rescue RestClient::Exception => e\n+      logger.warn(\"Exception when destroying candlepin consumer #{system.uuid}:#{e.inspect}\")\n+    end\n+\n+    begin\n+      logger.info(\"Removing Pulp consumer #{system.uuid}\")\n+      Katello.pulp_server.extensions.consumer.delete(system.uuid)\n+    rescue RestClient::ResourceNotFound\n+      logger.warn(\"Pulp consumer not found for consumer #{system.uuid} proceeding.\")\n+      #do nothing\n+    rescue RestClient::Exception => e\n+      logger.warn(\"Exception when destroying pulp consumer #{system.uuid}:#{e.inspect}\")\n+    end\n+\n+    logger.info(\"Removing system #{system.uuid}\")\n+    system.destroy\n+  end\n+\n+  def unregister_all_but_last_system(systems)\n+    systems_by_created_date = systems.sort_by(&:created_at)\n+    system = systems_by_created_date.pop\n+\n+    systems_by_created_date.each do |system_to_remove|\n+      unregister_system(system_to_remove)\n+    end\n+\n+    system\n+  end\n+\n+  # rubocop:disable MethodLength\n+  def up\n+    if User.where(:login => User::ANONYMOUS_API_ADMIN).first.nil?\n+      logger.warn(\"Foreman anonymous admin does not exist, skipping content host migration.\")\n+      return\n+    end\n+\n+    User.current = User.anonymous_api_admin\n+\n+    ensure_one_system_per_hostname(Katello::System.all)\n+\n+    systems = get_systems_with_facts(Katello::System.all)\n+\n+    systems.each do |system|\n+      hostname = system.facts['network.hostname']\n+\n+      logger.info(\"Processing content host #{system.uuid} #{hostname}\")\n+\n+      if hostname.nil?\n+        logger.warn(\"Content host #{system.uuid} does not have a hostname, removing.\")\n+        unregister_system(system)\n+        break\n+      end\n+\n+      hosts = ::Host.where(:name => hostname)\n+      if hosts.empty? # no host exists\n+        logger.info(\"No host exists with hostname #{hostname}, creating new host.\")\n+        params = system.attributes.to_options\n+        params[:facts] = system.facts\n+        host = Katello::Host::SubscriptionAspect.new_host_from_rhsm_params(params, system.environment.organization, Location.default_location)\n+        host.save!\n+\n+        create_content_aspect(host, system)\n+        create_subscription_aspect(host, system)\n+\n+      elsif hosts.where(:organization_id => system.environment.organization.id).empty? # host is not in the correct org\n+        logger.warn(\"Found host with hostname #{hostname} but it's in org #{hosts[0].org.name} instead of #{system.environment.organization.name}.\")\n+        host = hosts.first\n+\n+        create_content_aspect(host, system)\n+        unregister_system(system)\n+\n+      else #host exists in the correct org\n+        logger.info(\"Found host with hostname #{hostname}.\")\n+        host = hosts.first\n+\n+        host.content_aspect = create_content_aspect(host, system)\n+        host.subscription_aspect = create_subscription_aspect(host, system)","path":"db/migrate/20150930183738_migrate_content_hosts.rb","position":205,"original_position":206,"commit_id":"2b6b043e77eb12305b7fe27d02c98f34be375cc7","original_commit_id":"b9f64c5f50e56f809944d65a725945af7470cc8b","user":{"login":"jlsherrill","id":395077,"avatar_url":"https://avatars.githubusercontent.com/u/395077?v=3","gravatar_id":"","url":"https://api.github.com/users/jlsherrill","html_url":"https://github.com/jlsherrill","followers_url":"https://api.github.com/users/jlsherrill/followers","following_url":"https://api.github.com/users/jlsherrill/following{/other_user}","gists_url":"https://api.github.com/users/jlsherrill/gists{/gist_id}","starred_url":"https://api.github.com/users/jlsherrill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jlsherrill/subscriptions","organizations_url":"https://api.github.com/users/jlsherrill/orgs","repos_url":"https://api.github.com/users/jlsherrill/repos","events_url":"https://api.github.com/users/jlsherrill/events{/privacy}","received_events_url":"https://api.github.com/users/jlsherrill/received_events","type":"User","site_admin":false},"body":"it doesn't look like this is fixed?","created_at":"2015-11-06T11:35:33Z","updated_at":"2015-11-06T11:35:33Z","html_url":"https://github.com/Katello/katello/pull/5528#discussion_r44128276","pull_request_url":"https://api.github.com/repos/Katello/katello/pulls/5528","_links":{"self":{"href":"https://api.github.com/repos/Katello/katello/pulls/comments/44128276"},"html":{"href":"https://github.com/Katello/katello/pull/5528#discussion_r44128276"},"pull_request":{"href":"https://api.github.com/repos/Katello/katello/pulls/5528"}}},"pull_request":{"url":"https://api.github.com/repos/Katello/katello/pulls/5528","id":47447761,"html_url":"https://github.com/Katello/katello/pull/5528","diff_url":"https://github.com/Katello/katello/pull/5528.diff","patch_url":"https://github.com/Katello/katello/pull/5528.patch","issue_url":"https://api.github.com/repos/Katello/katello/issues/5528","number":5528,"state":"open","locked":false,"title":"Fixes #11500: migrate content hosts to hosts.","user":{"login":"waldenraines","id":4116405,"avatar_url":"https://avatars.githubusercontent.com/u/4116405?v=3","gravatar_id":"","url":"https://api.github.com/users/waldenraines","html_url":"https://github.com/waldenraines","followers_url":"https://api.github.com/users/waldenraines/followers","following_url":"https://api.github.com/users/waldenraines/following{/other_user}","gists_url":"https://api.github.com/users/waldenraines/gists{/gist_id}","starred_url":"https://api.github.com/users/waldenraines/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waldenraines/subscriptions","organizations_url":"https://api.github.com/users/waldenraines/orgs","repos_url":"https://api.github.com/users/waldenraines/repos","events_url":"https://api.github.com/users/waldenraines/events{/privacy}","received_events_url":"https://api.github.com/users/waldenraines/received_events","type":"User","site_admin":false},"body":"http://projects.theforeman.org/issues/11500\r\n\r\nThis should be the flow of the migration:\r\n\r\n![content host to host](https://cloud.githubusercontent.com/assets/4116405/10434823/d427cee4-70e9-11e5-82bd-440626754a5a.png)\r\n","created_at":"2015-10-12T18:02:28Z","updated_at":"2015-11-06T11:35:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4266380b0d5309f46021b526cf81a811bb8e84b9","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Katello/katello/pulls/5528/commits","review_comments_url":"https://api.github.com/repos/Katello/katello/pulls/5528/comments","review_comment_url":"https://api.github.com/repos/Katello/katello/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Katello/katello/issues/5528/comments","statuses_url":"https://api.github.com/repos/Katello/katello/statuses/2b6b043e77eb12305b7fe27d02c98f34be375cc7","head":{"label":"waldenraines:11500","ref":"11500","sha":"2b6b043e77eb12305b7fe27d02c98f34be375cc7","user":{"login":"waldenraines","id":4116405,"avatar_url":"https://avatars.githubusercontent.com/u/4116405?v=3","gravatar_id":"","url":"https://api.github.com/users/waldenraines","html_url":"https://github.com/waldenraines","followers_url":"https://api.github.com/users/waldenraines/followers","following_url":"https://api.github.com/users/waldenraines/following{/other_user}","gists_url":"https://api.github.com/users/waldenraines/gists{/gist_id}","starred_url":"https://api.github.com/users/waldenraines/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waldenraines/subscriptions","organizations_url":"https://api.github.com/users/waldenraines/orgs","repos_url":"https://api.github.com/users/waldenraines/repos","events_url":"https://api.github.com/users/waldenraines/events{/privacy}","received_events_url":"https://api.github.com/users/waldenraines/received_events","type":"User","site_admin":false},"repo":{"id":9356709,"name":"katello","full_name":"waldenraines/katello","owner":{"login":"waldenraines","id":4116405,"avatar_url":"https://avatars.githubusercontent.com/u/4116405?v=3","gravatar_id":"","url":"https://api.github.com/users/waldenraines","html_url":"https://github.com/waldenraines","followers_url":"https://api.github.com/users/waldenraines/followers","following_url":"https://api.github.com/users/waldenraines/following{/other_user}","gists_url":"https://api.github.com/users/waldenraines/gists{/gist_id}","starred_url":"https://api.github.com/users/waldenraines/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waldenraines/subscriptions","organizations_url":"https://api.github.com/users/waldenraines/orgs","repos_url":"https://api.github.com/users/waldenraines/repos","events_url":"https://api.github.com/users/waldenraines/events{/privacy}","received_events_url":"https://api.github.com/users/waldenraines/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/waldenraines/katello","description":"Katello integrates open source systems management tools into a single solution for controlling the lifecycle of your machines.","fork":true,"url":"https://api.github.com/repos/waldenraines/katello","forks_url":"https://api.github.com/repos/waldenraines/katello/forks","keys_url":"https://api.github.com/repos/waldenraines/katello/keys{/key_id}","collaborators_url":"https://api.github.com/repos/waldenraines/katello/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/waldenraines/katello/teams","hooks_url":"https://api.github.com/repos/waldenraines/katello/hooks","issue_events_url":"https://api.github.com/repos/waldenraines/katello/issues/events{/number}","events_url":"https://api.github.com/repos/waldenraines/katello/events","assignees_url":"https://api.github.com/repos/waldenraines/katello/assignees{/user}","branches_url":"https://api.github.com/repos/waldenraines/katello/branches{/branch}","tags_url":"https://api.github.com/repos/waldenraines/katello/tags","blobs_url":"https://api.github.com/repos/waldenraines/katello/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/waldenraines/katello/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/waldenraines/katello/git/refs{/sha}","trees_url":"https://api.github.com/repos/waldenraines/katello/git/trees{/sha}","statuses_url":"https://api.github.com/repos/waldenraines/katello/statuses/{sha}","languages_url":"https://api.github.com/repos/waldenraines/katello/languages","stargazers_url":"https://api.github.com/repos/waldenraines/katello/stargazers","contributors_url":"https://api.github.com/repos/waldenraines/katello/contributors","subscribers_url":"https://api.github.com/repos/waldenraines/katello/subscribers","subscription_url":"https://api.github.com/repos/waldenraines/katello/subscription","commits_url":"https://api.github.com/repos/waldenraines/katello/commits{/sha}","git_commits_url":"https://api.github.com/repos/waldenraines/katello/git/commits{/sha}","comments_url":"https://api.github.com/repos/waldenraines/katello/comments{/number}","issue_comment_url":"https://api.github.com/repos/waldenraines/katello/issues/comments{/number}","contents_url":"https://api.github.com/repos/waldenraines/katello/contents/{+path}","compare_url":"https://api.github.com/repos/waldenraines/katello/compare/{base}...{head}","merges_url":"https://api.github.com/repos/waldenraines/katello/merges","archive_url":"https://api.github.com/repos/waldenraines/katello/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/waldenraines/katello/downloads","issues_url":"https://api.github.com/repos/waldenraines/katello/issues{/number}","pulls_url":"https://api.github.com/repos/waldenraines/katello/pulls{/number}","milestones_url":"https://api.github.com/repos/waldenraines/katello/milestones{/number}","notifications_url":"https://api.github.com/repos/waldenraines/katello/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/waldenraines/katello/labels{/name}","releases_url":"https://api.github.com/repos/waldenraines/katello/releases{/id}","created_at":"2013-04-10T21:49:02Z","updated_at":"2014-06-24T21:15:25Z","pushed_at":"2015-11-05T21:07:02Z","git_url":"git://github.com/waldenraines/katello.git","ssh_url":"git@github.com:waldenraines/katello.git","clone_url":"https://github.com/waldenraines/katello.git","svn_url":"https://github.com/waldenraines/katello","homepage":"katello.org","size":78215,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Katello:host_unification","ref":"host_unification","sha":"6b14273fe374528e068da695c08602fc8833a526","user":{"login":"Katello","id":1316386,"avatar_url":"https://avatars.githubusercontent.com/u/1316386?v=3","gravatar_id":"","url":"https://api.github.com/users/Katello","html_url":"https://github.com/Katello","followers_url":"https://api.github.com/users/Katello/followers","following_url":"https://api.github.com/users/Katello/following{/other_user}","gists_url":"https://api.github.com/users/Katello/gists{/gist_id}","starred_url":"https://api.github.com/users/Katello/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Katello/subscriptions","organizations_url":"https://api.github.com/users/Katello/orgs","repos_url":"https://api.github.com/users/Katello/repos","events_url":"https://api.github.com/users/Katello/events{/privacy}","received_events_url":"https://api.github.com/users/Katello/received_events","type":"Organization","site_admin":false},"repo":{"id":4007018,"name":"katello","full_name":"Katello/katello","owner":{"login":"Katello","id":1316386,"avatar_url":"https://avatars.githubusercontent.com/u/1316386?v=3","gravatar_id":"","url":"https://api.github.com/users/Katello","html_url":"https://github.com/Katello","followers_url":"https://api.github.com/users/Katello/followers","following_url":"https://api.github.com/users/Katello/following{/other_user}","gists_url":"https://api.github.com/users/Katello/gists{/gist_id}","starred_url":"https://api.github.com/users/Katello/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Katello/subscriptions","organizations_url":"https://api.github.com/users/Katello/orgs","repos_url":"https://api.github.com/users/Katello/repos","events_url":"https://api.github.com/users/Katello/events{/privacy}","received_events_url":"https://api.github.com/users/Katello/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Katello/katello","description":"Katello integrates open source systems management tools into a single solution for controlling the lifecycle of your machines.","fork":false,"url":"https://api.github.com/repos/Katello/katello","forks_url":"https://api.github.com/repos/Katello/katello/forks","keys_url":"https://api.github.com/repos/Katello/katello/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Katello/katello/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Katello/katello/teams","hooks_url":"https://api.github.com/repos/Katello/katello/hooks","issue_events_url":"https://api.github.com/repos/Katello/katello/issues/events{/number}","events_url":"https://api.github.com/repos/Katello/katello/events","assignees_url":"https://api.github.com/repos/Katello/katello/assignees{/user}","branches_url":"https://api.github.com/repos/Katello/katello/branches{/branch}","tags_url":"https://api.github.com/repos/Katello/katello/tags","blobs_url":"https://api.github.com/repos/Katello/katello/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Katello/katello/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Katello/katello/git/refs{/sha}","trees_url":"https://api.github.com/repos/Katello/katello/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Katello/katello/statuses/{sha}","languages_url":"https://api.github.com/repos/Katello/katello/languages","stargazers_url":"https://api.github.com/repos/Katello/katello/stargazers","contributors_url":"https://api.github.com/repos/Katello/katello/contributors","subscribers_url":"https://api.github.com/repos/Katello/katello/subscribers","subscription_url":"https://api.github.com/repos/Katello/katello/subscription","commits_url":"https://api.github.com/repos/Katello/katello/commits{/sha}","git_commits_url":"https://api.github.com/repos/Katello/katello/git/commits{/sha}","comments_url":"https://api.github.com/repos/Katello/katello/comments{/number}","issue_comment_url":"https://api.github.com/repos/Katello/katello/issues/comments{/number}","contents_url":"https://api.github.com/repos/Katello/katello/contents/{+path}","compare_url":"https://api.github.com/repos/Katello/katello/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Katello/katello/merges","archive_url":"https://api.github.com/repos/Katello/katello/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Katello/katello/downloads","issues_url":"https://api.github.com/repos/Katello/katello/issues{/number}","pulls_url":"https://api.github.com/repos/Katello/katello/pulls{/number}","milestones_url":"https://api.github.com/repos/Katello/katello/milestones{/number}","notifications_url":"https://api.github.com/repos/Katello/katello/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Katello/katello/labels{/name}","releases_url":"https://api.github.com/repos/Katello/katello/releases{/id}","created_at":"2012-04-12T16:59:08Z","updated_at":"2015-11-05T08:08:22Z","pushed_at":"2015-11-06T00:21:32Z","git_url":"git://github.com/Katello/katello.git","ssh_url":"git@github.com:Katello/katello.git","clone_url":"https://github.com/Katello/katello.git","svn_url":"https://github.com/Katello/katello","homepage":"katello.org","size":241070,"stargazers_count":171,"watchers_count":171,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":114,"mirror_url":null,"open_issues_count":105,"forks":114,"open_issues":105,"watchers":171,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Katello/katello/pulls/5528"},"html":{"href":"https://github.com/Katello/katello/pull/5528"},"issue":{"href":"https://api.github.com/repos/Katello/katello/issues/5528"},"comments":{"href":"https://api.github.com/repos/Katello/katello/issues/5528/comments"},"review_comments":{"href":"https://api.github.com/repos/Katello/katello/pulls/5528/comments"},"review_comment":{"href":"https://api.github.com/repos/Katello/katello/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Katello/katello/pulls/5528/commits"},"statuses":{"href":"https://api.github.com/repos/Katello/katello/statuses/2b6b043e77eb12305b7fe27d02c98f34be375cc7"}}}}