diff --git a/app/models/miq_server.rb b/app/models/miq_server.rb index f27f5c56b73..c0e46c57e66 100644 --- a/app/models/miq_server.rb +++ b/app/models/miq_server.rb @@ -331,6 +331,8 @@ def is_recently_active? end def is_deleteable? + return true if MiqEnvironment::Command.is_podified? + if self.is_local? message = N_("Cannot delete currently used %{log_message}") % {:log_message => format_short_log_msg} @errors ||= ActiveModel::Errors.new(self) diff --git a/app/models/zone.rb b/app/models/zone.rb index 9dc9c52a7ee..36e94e4303c 100644 --- a/app/models/zone.rb +++ b/app/models/zone.rb @@ -29,7 +29,9 @@ class Zone < ApplicationRecord has_many :containers, :through => :container_managers virtual_has_many :active_miq_servers, :class_name => "MiqServer" + before_destroy :remove_servers_if_podified before_destroy :check_zone_in_use_on_destroy + after_create :create_server_if_podified include AuthenticationMixin @@ -239,11 +241,30 @@ def ntp_reload_queue servers.each(&:ntp_reload_queue) end + def message_for_invalid_delete + return _("cannot delete default zone") if name == "default" + return _("cannot delete maintenance zone") if self == miq_region.maintenance_zone + return _("zone name '%{name}' is used by a server") % {:name => name} if miq_servers.present? + _("zone name '%{name}' is used by a provider") % {:name => name} if ext_management_systems.present? + end + protected + def remove_servers_if_podified + return unless MiqEnvironment::Command.is_podified? + + miq_servers.destroy_all + end + + def create_server_if_podified + return unless MiqEnvironment::Command.is_podified? + return if name == "default" || !visible + + miq_servers.create!(:name => name) + end + def check_zone_in_use_on_destroy - raise _("cannot delete default zone") if name == "default" - raise _("cannot delete maintenance zone") if self == miq_region.maintenance_zone - raise _("zone name '%{name}' is used by a server") % {:name => name} unless miq_servers.blank? + msg = message_for_invalid_delete + raise msg if msg end end diff --git a/spec/lib/workers/evm_server_spec.rb b/spec/lib/workers/evm_server_spec.rb index 9a2c7bec6f6..af5a890838c 100644 --- a/spec/lib/workers/evm_server_spec.rb +++ b/spec/lib/workers/evm_server_spec.rb @@ -55,18 +55,21 @@ expect(subject.servers_to_monitor.first.id).to eq(MiqServer.first.id) 4.times { FactoryBot.create(:miq_server) } - expect(subject).to receive(:impersonate_server).exactly(4).times - expect(subject).to receive(:start_server).exactly(4).times + + num_servers = MiqServer.count + + # one for each new server + expect(subject).to receive(:impersonate_server).exactly(num_servers - 1).times + expect(subject).to receive(:start_server).exactly(num_servers - 1).times subject.refresh_servers_to_monitor - expect(subject.servers_to_monitor.count).to eq(5) + expect(subject.servers_to_monitor.count).to eq(num_servers) expect(subject.servers_to_monitor.map(&:id)).to match_array(MiqServer.all.map(&:id)) end it "removes a server when it is removed from the database" do server = FactoryBot.create(:miq_server) expect(subject.servers_to_monitor.map(&:id)).to include(server.id) - expect(subject.servers_to_monitor.count).to eq(2) monitor_server = subject.servers_to_monitor.find { |s| s.id == server.id } expect(monitor_server).to receive(:shutdown) @@ -75,7 +78,6 @@ subject.refresh_servers_to_monitor expect(subject.servers_to_monitor.map(&:id)).not_to include(server.id) - expect(subject.servers_to_monitor.count).to eq(1) end # Note: this is a very important spec @@ -86,8 +88,8 @@ initial_object_id = subject.servers_to_monitor.first.object_id 4.times { FactoryBot.create(:miq_server) } - expect(subject).to receive(:impersonate_server).exactly(4).times - expect(subject).to receive(:start_server).exactly(4).times + allow(subject).to receive(:impersonate_server) + allow(subject).to receive(:start_server) subject.refresh_servers_to_monitor new_objects = subject.servers_to_monitor.map(&:object_id) diff --git a/spec/models/miq_server/queue_management_spec.rb b/spec/models/miq_server/queue_management_spec.rb index ea6d66187ab..487c41d714b 100644 --- a/spec/models/miq_server/queue_management_spec.rb +++ b/spec/models/miq_server/queue_management_spec.rb @@ -3,8 +3,8 @@ describe "#ntp_reload_queue" do it "enqueues a message if the server is an appliance, but not a container" do - expect(MiqEnvironment::Command).to receive(:is_appliance?).and_return(true) - expect(MiqEnvironment::Command).to receive(:is_container?).and_return(false) + allow(MiqEnvironment::Command).to receive(:is_appliance?).and_return(true) + allow(MiqEnvironment::Command).to receive(:is_container?).and_return(false) server.ntp_reload_queue @@ -12,7 +12,7 @@ end it "doesn't enqueue a message if the server is not an appliance" do - expect(MiqEnvironment::Command).to receive(:is_appliance?).and_return(false) + allow(MiqEnvironment::Command).to receive(:is_appliance?).and_return(false) server.ntp_reload_queue @@ -20,8 +20,8 @@ end it "doesn't enqueue a message if the server is a container" do - expect(MiqEnvironment::Command).to receive(:is_appliance?).and_return(true) - expect(MiqEnvironment::Command).to receive(:is_container?).and_return(true) + allow(MiqEnvironment::Command).to receive(:is_appliance?).and_return(true) + allow(MiqEnvironment::Command).to receive(:is_container?).and_return(true) server.ntp_reload_queue diff --git a/spec/models/miq_server_spec.rb b/spec/models/miq_server_spec.rb index d7bb17ab1e0..c3fd7f7b929 100644 --- a/spec/models/miq_server_spec.rb +++ b/spec/models/miq_server_spec.rb @@ -172,6 +172,13 @@ expect(@miq_server.errors.full_messages.first).to match(/recently/) end + + it "doesn't enforce when podified" do + allow(MiqEnvironment::Command).to receive(:is_podified?).and_return(true) + allow(@miq_server).to receive(:is_local?).and_return(true) + @miq_server.last_heartbeat = 2.minutes.ago.utc + @miq_server.destroy! + end end context "#ntp_reload_queue" do diff --git a/spec/models/zone_spec.rb b/spec/models/zone_spec.rb index 7d9ec7af3bb..1acc716f11f 100644 --- a/spec/models/zone_spec.rb +++ b/spec/models/zone_spec.rb @@ -167,8 +167,8 @@ context "#ntp_reload_queue" do it "queues a ntp reload for all active servers in the zone" do - expect(MiqEnvironment::Command).to receive(:is_appliance?).and_return(true) - expect(MiqEnvironment::Command).to receive(:is_container?).and_return(false) + allow(MiqEnvironment::Command).to receive(:is_appliance?).and_return(true) + allow(MiqEnvironment::Command).to receive(:is_container?).and_return(false) zone = FactoryBot.create(:zone) server_1 = FactoryBot.create(:miq_server, :zone => zone) FactoryBot.create(:miq_server, :zone => zone, :status => "stopped") @@ -203,6 +203,11 @@ described_class.seed expect(described_class.maintenance_zone.visible).to eq(false) end + + it "cannot be destroyed" do + described_class.seed + expect { described_class.maintenance_zone.destroy! }.to raise_error(RuntimeError) + end end context "validate multi region" do @@ -224,4 +229,66 @@ zone.destroy! expect(MiqQueue.where(:zone => zone.name).count).to eq(0) end + + it "doesn't create a server for the zone when not podified" do + zone = FactoryBot.create(:zone) + expect(zone.miq_servers.count).to eq(0) + end + + describe "#destroy" do + before { MiqRegion.seed } + + it "fails for a zone with servers when not podified" do + zone = FactoryBot.create(:zone) + zone.miq_servers.create!(:name => "my_server") + expect { zone.destroy! }.to raise_error(RuntimeError) + end + + it "fails for the default zone" do + described_class.seed + expect { described_class.default_zone.destroy! }.to raise_error(RuntimeError) + end + + it "fails for a zone with a provider" do + zone = FactoryBot.create(:zone) + FactoryBot.create(:ext_management_system, :zone => zone) + + expect { zone.destroy! }.to raise_error(RuntimeError) + end + end + + context "when podified" do + before do + allow(MiqEnvironment::Command).to receive(:is_podified?).and_return(true) + end + + describe ".create" do + it "automatically creates a server" do + zone = Zone.create!(:name => "my_zone", :description => "some zone") + expect(zone.miq_servers.count).to eq(1) + + server = zone.miq_servers.first + expect(server.name).to eq("my_zone") + end + + it "doesn't create a server for non-visible zones" do + zone = Zone.create!(:name => "my_zone", :description => "some zone", :visible => false) + expect(zone.miq_servers.count).to eq(0) + end + + it "doesn't create a server for the default zone" do + zone = Zone.create!(:name => "default", :description => "Default Zone") + expect(zone.miq_servers.count).to eq(0) + end + end + + it ".destroy deletes the server in the zone" do + MiqRegion.seed + zone = Zone.create!(:name => "my_zone", :description => "some zone") + server = zone.miq_servers.first + zone.destroy! + + expect(MiqServer.find_by(:id => server.id)).to be_nil + end + end end