Skip to content

Commit

Permalink
WIP Keep quota history by archiving
Browse files Browse the repository at this point in the history
  • Loading branch information
cben committed Jan 7, 2018
1 parent 57dac5a commit fc8b192
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 5 deletions.
3 changes: 2 additions & 1 deletion app/models/container_project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class ContainerProject < ApplicationRecord
has_many :containers, :through => :container_groups
has_many :container_images, -> { distinct }, :through => :container_groups
has_many :container_nodes, -> { distinct }, :through => :container_groups
has_many :container_quotas
has_many :container_quotas, -> { active }
has_many :container_quota_scopes, :through => :container_quotas
has_many :container_quota_items, :through => :container_quotas
has_many :container_limits
has_many :container_limit_items, :through => :container_limits
Expand Down
25 changes: 24 additions & 1 deletion app/models/container_quota.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
class ContainerQuota < ApplicationRecord
# For this model and children, we want to record full changes history.
#
# - The ContainerQuota itself doesn't have anything that changes
# (except resource_version whose history is not interesting).
# So we do standard archiving on deletion here.
#
# - Scopes are immutable once ContainerQuota is created, so don't need archiving.
#
# - ContainerQuotaItems can be added/deleted/changed, and we use archiving to
# record changes too!
include ArchivedMixin

belongs_to :ext_management_system, :foreign_key => "ems_id"
belongs_to :container_project

has_many :container_quota_scopes, :dependent => :destroy
has_many :container_quota_items, :dependent => :destroy
has_many :container_quota_items, -> { active }
has_many :all_container_quota_items, :dependent => :destroy, :class_name => "ContainerQuotaItem", :dependent => :destroy

def disconnect_inv
return if archived?
_log.info("Archiving Container Quota [#{name}] id [#{id}]")
# This allows looking only at ContainerQuotaItem created_at..deleted_on
# without also checking parent ContaineQuota is active.
self.container_quota_items.each(&:disconnect_inv)
self.deleted_on = Time.now.utc
save
end
end
14 changes: 14 additions & 0 deletions app/models/container_quota_item.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
class ContainerQuotaItem < ApplicationRecord
# This model is unusual in using archiving not only to record deletions but also changes in quota_desired, quota_enforced, quota_observed.
# Instead of updating in-place, we archive the old record and create a new one.
include ArchivedMixin

belongs_to :container_quota
has_many :container_quota_scopes, :through => :container_quota

virtual_column :quota_desired_display, :type => :string
virtual_column :quota_enforced_display, :type => :string
virtual_column :quota_observed_display, :type => :string

def disconnect_inv
return if archived?
_log.info("Archiving Container Quota id [#{container_quota_id}] Item [#{resource}]")
# This allows looking only at ContainerQuotaItem created_at..deleted_on
# without also checking parent ContaineQuota is active.
self.deleted_on = Time.now.utc
save
end

def quota_desired_display
quota_display(quota_desired)
end
Expand Down
8 changes: 6 additions & 2 deletions app/models/ems_refresh/save_inventory_container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def save_container_quotas_inventory(ems, hashes)
end

save_inventory_multi(ems.container_quotas, hashes, :use_association,
[:ems_ref], [:container_quota_items, :container_quota_scopes], :project)
[:ems_ref], [:container_quota_items, :container_quota_scopes], :project,
true)
store_ids_for_new_records(ems.container_quotas, hashes, :ems_ref)
end

Expand All @@ -78,7 +79,10 @@ def save_container_quota_items_inventory(container_quota, hashes)
return if hashes.nil?
container_quota.container_quota_items.reset

save_inventory_multi(container_quota.container_quota_items, hashes, :use_association, [:resource])
# Archive and create new on changes, not only on deletion - by including the data in find_key.
save_inventory_multi(container_quota.container_quota_items, hashes, :use_association,
[:resource, :quota_desired, :quota_enforced, :quota_observed], [], [],
true)
store_ids_for_new_records(container_quota.container_quota_items, hashes, :resource)
end

Expand Down
3 changes: 2 additions & 1 deletion app/models/manageiq/providers/container_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ContainerManager < BaseManager
has_many :container_replicators, :foreign_key => :ems_id, :dependent => :destroy
has_many :containers, -> { active }, :foreign_key => :ems_id
has_many :container_projects, -> { active }, :foreign_key => :ems_id
has_many :container_quotas, :foreign_key => :ems_id, :dependent => :destroy
has_many :container_quotas, :foreign_key => :ems_id
has_many :container_limits, :foreign_key => :ems_id, :dependent => :destroy
has_many :container_image_registries, :foreign_key => :ems_id, :dependent => :destroy
has_many :container_images, -> { active }, :foreign_key => :ems_id
Expand Down Expand Up @@ -45,6 +45,7 @@ class ContainerManager < BaseManager
has_many :all_container_projects, :foreign_key => :ems_id, :dependent => :destroy, :class_name => "ContainerProject"
has_many :all_container_images, :foreign_key => :ems_id, :dependent => :destroy, :class_name => "ContainerImage"
has_many :all_container_nodes, :foreign_key => :ems_id, :dependent => :destroy, :class_name => "ContainerNode"
has_many :all_container_quotas, :foreign_key => :ems_id, :dependent => :destroy, :class_name => "ContainerQuota"


virtual_column :port_show, :type => :string
Expand Down
18 changes: 18 additions & 0 deletions app/models/mixins/archived_mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@ def active?
deleted_on.nil?
end

module ClassMethods
def were_active_at_time(time)
# TODO: express conditions with AR, not SQL string, so this is join-friendly.
unscope(:where => :deleted_on).where("#{created_column_name} <= ? AND (deleted_on IS NULL OR deleted_on >= ?)", time, time)
end

def walk_history(start_time, end_time)
# TODO
end

# TODO: rename created_on/created_at to something consistent.
def created_column_name
@created_column_name ||= ['created_at', 'created_on'].detect do |name|
columns_hash.include?(name)
end
end
end

# Needed for metrics
def my_zone
if ext_management_system.present?
Expand Down

0 comments on commit fc8b192

Please sign in to comment.