diff --git a/app/api/v_sphere/cluster.rb b/app/api/v_sphere/cluster.rb index 094a74ab..e8f5d650 100644 --- a/app/api/v_sphere/cluster.rb +++ b/app/api/v_sphere/cluster.rb @@ -35,6 +35,10 @@ def ==(other) equal? other end + def networks + @cluster.network + end + private def managed_folder_entry diff --git a/app/api/v_sphere/folder.rb b/app/api/v_sphere/folder.rb index 8fe623e7..7fcd7e66 100644 --- a/app/api/v_sphere/folder.rb +++ b/app/api/v_sphere/folder.rb @@ -70,7 +70,9 @@ def move_here(folder_entry) end def create_vm(cpu, ram, capacity, name, cluster) - vm_config = creation_config(cpu, ram, capacity, name) + return nil if cluster.networks.empty? + + vm_config = creation_config(cpu, ram, capacity, name, cluster.networks.first) vm = @folder.CreateVM_Task(config: vm_config, pool: cluster.resource_pool).wait_for_completion VSphere::VirtualMachine.new vm end @@ -81,7 +83,7 @@ def managed_folder_entry @folder end - def creation_config(cpu, ram, capacity, name) # rubocop:disable Metrics/MethodLength + def creation_config(cpu, ram, capacity, name, network) # rubocop:disable Metrics/MethodLength { name: name, guestId: 'otherGuest', @@ -119,7 +121,7 @@ def creation_config(cpu, ram, capacity, name) # rubocop:disable Metrics/MethodLe summary: 'VM Network' }, backing: RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo( - deviceName: 'VM Network' + deviceName: network.name ), addressType: 'generated' ) diff --git a/app/models/request.rb b/app/models/request.rb index e9a7552a..71f4df19 100644 --- a/app/models/request.rb +++ b/app/models/request.rb @@ -84,27 +84,33 @@ def create_vm clusters = VSphere::Cluster.all return nil, 'VM could not be created, as there are no clusters available in vSphere!' if clusters.empty? - warning = nil - begin - push_to_git - rescue Git::GitExecuteError => e - logger.error(e) - warning = "Your VM was created, but users could not be associated with the VM! Push to git failed, error: \"#{e.message}\"" - end - [create_vm_in_cluster(clusters.sample), warning] + cluster = clusters.sample + return nil, 'VM could not be created, there is no network available in the cluster' if cluster.networks.empty? + + warning = push_to_git_with_warnings + [create_vm_in_cluster(cluster), warning] end def create_vm_in_cluster(cluster) vm = VSphere::Connection.instance.root_folder.create_vm(cpu_cores, gibi_to_mibi(ram_gb), gibi_to_kibi(storage_gb), name, cluster) - vm.ensure_config.responsible_users = responsible_users - vm.config.project = project - vm.config.description = description - vm.config.save + vm.ensure_config.update( + responsible_users: responsible_users, + project: project, + description: description + ) vm.move_into_correct_subfolder vm end - # Error handling has been moved into create_vm to provide easier feedback for the user + def push_to_git_with_warnings + push_to_git + nil + rescue Git::GitExecuteError => error + logger.error error + "Your VM was created, but users could not be associated with the VM! Push to git failed, error:\n\"#{error.message}\"" + end + + # Error handling has been moved into push_to_git_with_warnings to provide easier feedback for the user def push_to_git GitHelper.open_repository(Puppetscript.puppet_script_path, for_write: true) do |git_writer| git_writer.write_file(Puppetscript.node_file_name(name), generate_puppet_node_script) diff --git a/app/views/layouts/_flash_message.html.erb b/app/views/layouts/_flash_message.html.erb index 9a031055..c658070b 100644 --- a/app/views/layouts/_flash_message.html.erb +++ b/app/views/layouts/_flash_message.html.erb @@ -2,7 +2,7 @@ <% flash.each do |key, value| %>
× - <%= content_tag :div, value %> + <%= content_tag :div, simple_format(value) %>
<% end %> diff --git a/app/views/requests/show.html.erb b/app/views/requests/show.html.erb index d9c75233..8d4a057b 100644 --- a/app/views/requests/show.html.erb +++ b/app/views/requests/show.html.erb @@ -3,7 +3,7 @@ - diff --git a/spec/api/v_sphere_api_mocker.rb b/spec/api/v_sphere_api_mocker.rb index e202c9d7..21878cc4 100644 --- a/spec/api/v_sphere_api_mocker.rb +++ b/spec/api/v_sphere_api_mocker.rb @@ -25,6 +25,9 @@ # has many messages that have to be chained which we want to mock. # rubocop:disable RSpec/MessageChain +# Disable AbcSize and MethodLength as mocking is not really complex, but increases these 2 metrics very fast +# rubocop:disable Metrics/AbcSize, Metrics/MethodLength + def extract_vim_objects(collection) collection.map do |each| if [VSphere::Cluster, VSphere::Folder, VSphere::VirtualMachine].include? each.class @@ -66,7 +69,6 @@ def v_sphere_folder_mock(name, subfolders: [], vms: [], clusters: []) VSphere::Folder.new vim_folder_mock(name, subfolders, vms, clusters) end -# rubocop:disable Metrics/AbcSize, Metrics/MethodLength def vim_vm_summary_mock(power_state: 'poweredOn') summary_double = double allow(summary_double).to receive_message_chain(:storage, :committed).and_return(100) @@ -83,7 +85,6 @@ def vim_vm_summary_mock(power_state: 'poweredOn') allow(summary_double).to receive_message_chain(:runtime, :host, :name).and_return 'aHost' summary_double end -# rubocop:enable Metrics/AbcSize, Metrics/MethodLength def vim_disks_mock disk = double @@ -98,7 +99,6 @@ def vim_guest_mock(tools_status: 'toolsNotInstalled') guest end -# rubocop:disable Metrics/AbcSize def vim_vm_mock( name, power_state: 'poweredOn', @@ -122,7 +122,6 @@ def vim_vm_mock( vm end -# rubocop:enable Metrics/AbcSize def v_sphere_vm_mock(name, power_state: 'poweredOn', vm_ware_tools: 'toolsNotInstalled', boot_time: Time.now - 60 * 60 * 24) VSphere::VirtualMachine.new vim_vm_mock(name, @@ -131,6 +130,21 @@ def v_sphere_vm_mock(name, power_state: 'poweredOn', vm_ware_tools: 'toolsNotIns boot_time: boot_time) end +def vim_host_summary_mock + summary = double + allow(summary).to receive_message_chain(:runtime, :powerState) + allow(summary).to receive_message_chain(:config, :product, :osType).and_return('someOS') + allow(summary).to receive_message_chain(:config, :product, :fullName).and_return(['someProduct']) + allow(summary).to receive_message_chain(:hardware, :cpuModel).and_return('someModel') + allow(summary).to receive_message_chain(:hardware, :numCpuCores).and_return(4) + allow(summary).to receive_message_chain(:hardware, :numCpuThreads).and_return(4) + allow(summary).to receive_message_chain(:hardware, :cpuMhz).and_return(1000) + allow(summary).to receive_message_chain(:hardware, :memorySize).and_return(1000 * 1024**3) # in bytes + allow(summary).to receive_message_chain(:quickStats, :overallMemoryUsage).and_return(0) + allow(summary).to receive_message_chain(:quickStats, :overallCpuUsage).and_return(0) + summary +end + def vim_host_mock(name) host = double allow(host).to receive(:name).and_return name @@ -149,18 +163,7 @@ def vim_host_mock(name) power_state: 'poweredOn', vm_ware_tools: 'toolsInstalled')]) - summary = double - allow(summary).to receive_message_chain(:runtime, :powerState) - allow(summary).to receive_message_chain(:config, :product, :osType).and_return('someOS') - allow(summary).to receive_message_chain(:config, :product, :fullName).and_return(['someProduct']) - allow(summary).to receive_message_chain(:hardware, :cpuModel).and_return('someModel') - allow(summary).to receive_message_chain(:hardware, :numCpuCores).and_return(4) - allow(summary).to receive_message_chain(:hardware, :numCpuThreads).and_return(4) - allow(summary).to receive_message_chain(:hardware, :cpuMhz).and_return(1000) - allow(summary).to receive_message_chain(:hardware, :memorySize).and_return(1000 * 1024**3) # in bytes - allow(summary).to receive_message_chain(:quickStats, :overallMemoryUsage).and_return(0) - allow(summary).to receive_message_chain(:quickStats, :overallCpuUsage).and_return(0) - allow(host).to receive(:summary).and_return summary + allow(host).to receive(:summary).and_return vim_host_summary_mock datastore = double allow(datastore).to receive_message_chain(:summary, :capacity).and_return(1000 * 1024**3) # in bytes @@ -174,7 +177,6 @@ def v_sphere_host_mock(name) VSphere::Host.new vim_host_mock(name) end -# rubocop:disable Metrics/AbcSize def vim_cluster_mock(name, hosts) hosts = extract_vim_objects hosts cluster = double @@ -183,9 +185,11 @@ def vim_cluster_mock(name, hosts) allow(cluster).to receive(:host).and_return hosts allow(cluster).to receive(:name).and_return name allow(cluster).to receive(:resourcePool).and_return nil + network = double + allow(network).to receive(:name).and_return 'MyNetwork' + allow(cluster).to receive(:network).and_return [network] cluster end -# rubocop:enable Metrics/AbcSize def v_sphere_cluster_mock(name, hosts) VSphere::Cluster.new vim_cluster_mock(name, hosts) @@ -212,4 +216,5 @@ def v_sphere_connection_mock( double_connection end +# rubocop:enable Metrics/AbcSize, Metrics/MethodLength # rubocop:enable RSpec/MessageChain diff --git a/spec/controllers/requests_controller_spec.rb b/spec/controllers/requests_controller_spec.rb index f58ea32b..280b9812 100644 --- a/spec/controllers/requests_controller_spec.rb +++ b/spec/controllers/requests_controller_spec.rb @@ -221,7 +221,7 @@ end describe 'PATCH #update' do - context 'with valid params' do + context 'accepts the request' do let(:new_attributes) do { name: 'mynewvm', @@ -230,7 +230,6 @@ storage_gb: 3, operating_system: 'MyNewOS', comment: 'newComment', - status: 'pending', user: user, sudo_user_ids: ['', sudo_user.id.to_s, user.id.to_s], user_ids: [''] @@ -245,25 +244,41 @@ request end - before do + it 'redirects to the index page if no cluster is available' do + allow(VSphere::Cluster).to receive(:all).and_return [] patch :update, params: { id: the_request.to_param, request: new_attributes } - the_request.reload + expect(response).to redirect_to(requests_path) end - it 'updates the request' do - expect(the_request.name).to eq('mynewvm') + it 'redirects to the index page if the cluster does not have a network' do + cluster = double + allow(cluster).to receive(:networks).and_return [] + allow(VSphere::Cluster).to receive(:all).and_return [cluster] + patch :update, params: { id: the_request.to_param, request: new_attributes } + expect(response).to redirect_to(requests_path) end - it 'redirects to the new VMS config' do - expect(response).to redirect_to(edit_config_path(the_request.name)) - end + context 'update already performed' do + before do + patch :update, params: { id: the_request.to_param, request: new_attributes } + the_request.reload + end - it 'accepts the request' do - expect(the_request).to be_accepted - end + it 'updates the request' do + expect(the_request.name).to eq('mynewvm') + end + + it 'redirects to the new VMS config' do + expect(response).to redirect_to(edit_config_path(the_request.name)) + end + + it 'accepts the request' do + expect(the_request).to be_accepted + end - it 'correctly updates the sudo users' do - expect(the_request.sudo_users).to match_array([sudo_user, user]) + it 'correctly updates the sudo users' do + expect(the_request.sudo_users).to match_array([sudo_user, user]) + end end end
VM Name + VM Name <%= @request.name %>