1# -*- mode: ruby -*- 2# vi: set ft=ruby : 3 4require 'open3' 5def get_box_type(distro, force_distro) 6 spdk_distro = 'spdk/' + distro 7 localboxes, stderr, status = Open3.capture3("vagrant box list") 8 return spdk_distro if localboxes.include?(spdk_distro) 9 10 distro_to_type = { 11 'centos7' => 'centos/7', 12 'centos8' => 'centos/8', 13 'ubuntu1604' => 'peru/ubuntu-16.04-server-amd64', 14 'ubuntu1804' => 'peru/ubuntu-18.04-server-amd64', 15 'ubuntu2004' => 'peru/ubuntu-20.04-server-amd64', 16 'fedora32' => 'generic/fedora32', 17 'fedora33' => 'generic/fedora33', 18 'fedora34' => 'fedora/34-cloud-base', 19 'arch' => 'generic/arch', 20 'freebsd12' => 'generic/freebsd12', 21 } 22 abort("Invalid argument! #{distro}") unless distro_to_type.key?(distro) || force_distro 23 24 return distro_to_type[distro] ? distro_to_type[distro] : distro 25end 26 27def setup_proxy(config,distro) 28 return unless ENV['http_proxy'] 29 30 if Vagrant.has_plugin?("vagrant-proxyconf") 31 config.proxy.http = ENV['http_proxy'] 32 config.proxy.https = ENV['https_proxy'] 33 config.proxy.no_proxy = "localhost,127.0.0.1" 34 end 35 36 # Proxyconf does not seem to support FreeBSD boxes or at least it's 37 # docs do not mention that. Set up proxy configuration manually. 38 if distro.include?("freebsd") 39 $freebsd_proxy = <<-SCRIPT 40 sudo -s 41 echo "export http_proxy=#{ENV['http_proxy']}" >> /etc/profile 42 echo "export https_proxy=#{ENV['http_proxy']}" >> /etc/profile 43 echo "pkg_env: {http_proxy: #{ENV['http_proxy']}}" > /usr/local/etc/pkg.conf 44 chown root:wheel /usr/local/etc/pkg.conf 45 chmod 644 /usr/local/etc/pkg.conf 46 SCRIPT 47 config.vm.provision "shell", inline: $freebsd_proxy 48 end 49end 50 51def copy_gitconfig(config) 52 src_path = '~/.gitconfig' 53 return unless File.file?(File.expand_path(src_path)) 54 55 config.vm.provision "file", source: src_path, destination: ".gitconfig" 56end 57 58def copy_tsocks(config) 59 tsocks_file = 'tsocks.conf' 60 tsocks_file_path = '/etc/' + tsocks_file 61 62 return unless File.file?(tsocks_file_path) 63 64 $tsocks_copy_cmd = <<-SCRIPT 65 sudo -s 66 mv -f "#{tsocks_file}" "#{tsocks_file_path}" 67 chown root "#{tsocks_file_path}" 68 chmod 644 "#{tsocks_file_path}" 69 SCRIPT 70 71 config.vm.provision "file", source: tsocks_file_path, destination: tsocks_file 72 config.vm.provision "shell", inline: $tsocks_copy_cmd 73end 74 75def copy_vagrant_tools(config,files_sync_backend) 76 src_path = '~/vagrant_tools' 77 return unless File.directory?(File.expand_path(src_path)) 78 79 config.vm.synced_folder src_path, "/home/vagrant/tools", files_sync_backend 80end 81 82def copy_spdk_dir(config, files_sync_backend) 83 return unless ENV['COPY_SPDK_DIR'] == "1" 84 return unless ENV['SPDK_DIR'] 85 86 config.vm.synced_folder ENV['SPDK_DIR'], '/home/vagrant/spdk_repo/spdk', files_sync_backend 87end 88 89def copy_spdk_artifacts(config, plugins_sync_backend) 90 return unless ENV['COPY_SPDK_ARTIFACTS'] == "1" 91 92 vagrantfile_dir=(ENV['VAGRANTFILE_DIR'] || "none") 93 config.vm.synced_folder "#{vagrantfile_dir}/output", "/home/vagrant/spdk_repo/output", plugins_sync_backend 94end 95 96def make_spdk_local_copy_of_nfs(config,distro) 97 user_group = 'vagrant:vagrant' 98 99 spdk_path = '/home/vagrant/spdk_repo/spdk' 100 spdk_tmp_path = '/tmp/spdk' 101 $spdk_repo_cmd = <<-SCRIPT 102 sudo -s 103 cp -R '#{spdk_path}' '#{spdk_tmp_path}' 104 umount '#{spdk_path}' && rm -rf '#{spdk_path}' 105 mv '#{spdk_tmp_path}' '#{spdk_path}' 106 chown -R #{user_group} '#{spdk_path}' 107 SCRIPT 108 109 config.vm.provision "shell", inline: $spdk_repo_cmd 110end 111 112def get_nvme_disk(disk, index) 113 if ENV['NVME_FILE'] 114 nvme_file = ENV['NVME_FILE'].split(',') 115 nvme_disk = nvme_file[index] 116 else 117 nvme_disk = '/var/lib/libvirt/images/nvme_disk.img' 118 end 119 120 unless File.exist? (nvme_disk) 121 puts 'If run with libvirt provider please execute create_nvme_img.sh' 122 end 123 124 return nvme_disk 125end 126 127def setup_nvme_disk(libvirt, disk, index) 128 nvme_disk_id = disk + '-' + index.to_s 129 nvme_disk = get_nvme_disk(disk, index) 130 131 nvme_namespaces=(ENV['NVME_DISKS_NAMESPACES'] || "").split(',') 132 nvme_cmbs=(ENV['NVME_CMB'] || "").split(',') 133 nvme_pmrs=(ENV['NVME_PMR'] || "").split(',') 134 135 libvirt.qemuargs :value => "-drive" 136 libvirt.qemuargs :value => "format=raw,file=#{nvme_disk},if=none,id=#{nvme_disk_id}" 137 libvirt.qemuargs :value => "-device" 138 nvme_drive = "nvme,drive=#{nvme_disk_id},serial=1234#{index}" 139 if !nvme_namespaces[index].nil? && nvme_namespaces[index] != "1" 140 nvme_drive << ",namespaces=#{nvme_namespaces[index]}" 141 end 142 143 pmr_cmdline = "" 144 145 if !nvme_cmbs[index].nil? && nvme_cmbs[index] == "true" 146 # Fix the size of the buffer to 128M 147 nvme_drive << ",cmb_size_mb=128" 148 end 149 if !nvme_pmrs[index].nil? 150 pmr_path, pmr_size = nvme_pmrs[index].split(':') 151 if !File.exist?(pmr_path) 152 abort("#{pmr_path} does not exist, aborting") 153 end 154 if pmr_size.nil? 155 pmr_size = "16M" 156 end 157 nvme_drive << ",pmrdev=pmr#{index}" 158 pmr_cmdline = "memory-backend-file,id=pmr#{index},share=on,mem-path=#{pmr_path},size=#{pmr_size}" 159 end 160 libvirt.qemuargs :value => nvme_drive 161 if pmr_cmdline != "" 162 libvirt.qemuargs :value => "-object" 163 libvirt.qemuargs :value => pmr_cmdline 164 end 165end 166 167def setup_ssh(config) 168 config.ssh.forward_agent = true 169 config.ssh.forward_x11 = true 170 if ENV['VAGRANT_PASSWORD_AUTH'] == "1" 171 config.ssh.username = "vagrant" 172 config.ssh.password = "vagrant" 173 config.ssh.private_key_path = nil 174 end 175end 176 177def deploy_test_vm(config, distro, plugins_sync_backend) 178 return unless ENV['DEPLOY_TEST_VM'] == "1" 179 return unless ENV['COPY_SPDK_DIR'] == "1" 180 return unless ENV['SPDK_DIR'] 181 182 # use http proxy if avaiable 183 setup_proxy(config, distro) 184 185 # Copy the tsocks configuration file for use when installing some spdk test pool dependencies 186 copy_tsocks(config) 187 188 # freebsd boxes in order to have spdk sources synced from 189 # host properly will use NFS with "ro" option enabled to prevent changes 190 # on host filesystem. 191 # To make sources usable in the guest VM we need to unmount them and use 192 # local copy. 193 make_spdk_local_copy_of_nfs(config,distro) if plugins_sync_backend[:type] == :nfs 194 195 config.vm.provision "shell" do |setup| 196 setup.inline = "/home/vagrant/spdk_repo/spdk/test/common/config/vm_setup.sh" 197 setup.privileged = false 198 setup.args = ["-u", "-i"] 199 end 200end 201 202def setup_virtualbox(config, vmcpu, vmram) 203 config.vm.provider "virtualbox" do |vb| 204 vb.customize ["modifyvm", :id, "--ioapic", "on"] 205 vb.memory = vmram 206 vb.cpus = vmcpu 207 208 nvme_disk=(ENV['NVME_FILE'] || "nvme_disk.img") 209 unless File.exist? (nvme_disk) 210 vb.customize ["createhd", "--filename", nvme_disk, "--variant", "Fixed", "--size", "1024"] 211 vb.customize ["storagectl", :id, "--name", "nvme", "--add", "pcie", "--controller", "NVMe", "--portcount", "1", "--bootable", "off"] 212 vb.customize ["storageattach", :id, "--storagectl", "nvme", "--type", "hdd", "--medium", nvme_disk, "--port", "0"] 213 end 214 215 #support for the SSE4.x instruction is required in some versions of VB. 216 vb.customize ["setextradata", :id, "VBoxInternal/CPUM/SSE4.1", "1"] 217 vb.customize ["setextradata", :id, "VBoxInternal/CPUM/SSE4.2", "1"] 218 end 219end 220 221def setup_libvirt(config, vmcpu, vmram, distro) 222 emulated_nvme_types=(ENV['NVME_DISKS_TYPE'] || "nvme").split(',') 223 224 config.vm.provider "libvirt" do |libvirt, override| 225 libvirt.random_hostname = "1" 226 libvirt.driver = "kvm" 227 libvirt.graphics_type = "vnc" 228 libvirt.memory = vmram 229 libvirt.cpus = vmcpu 230 libvirt.video_type = "cirrus" 231 232 if (distro.include?("freebsd")) 233 # generic/freebsd boxes need to be explicitly run with SCSI bus, 234 # otherwise boot process fails on mounting the disk 235 libvirt.disk_bus = "scsi" 236 elsif (distro.include?("arch")) 237 # Run generic/arch boxes explicitly with IDE bus, 238 # otherwise boot process fails on mounting the disk 239 libvirt.disk_bus = "ide" 240 else 241 libvirt.disk_bus = "virtio" 242 end 243 244 if ENV['SPDK_QEMU_EMULATOR'] 245 libvirt.emulator_path = ENV['SPDK_QEMU_EMULATOR'] 246 libvirt.machine_type = "pc" 247 end 248 249 # we put nvme_disk inside default pool to eliminate libvirt/SELinux Permissions Problems 250 # and to be able to run vagrant from user $HOME directory 251 252 # Loop to create all emulated disks set 253 emulated_nvme_types.each_with_index { |disk, index| 254 if disk == "nvme" 255 setup_nvme_disk(libvirt, disk, index) 256 end 257 } 258 259 # Add network interface for openstack tests 260 if ENV['SPDK_OPENSTACK_NETWORK'] == "1" 261 libvirt.qemuargs :value => "-device" 262 libvirt.qemuargs :value => "virtio-net,netdev=openstack.0" 263 libvirt.qemuargs :value => "-netdev" 264 libvirt.qemuargs :value => "user,id=openstack.0" 265 end 266 267 if ENV['VAGRANT_HUGE_MEM'] == "1" 268 libvirt.memorybacking :hugepages 269 end 270 271 # Optional field if we want use other storage pools than default 272 # libvirt.storage_pool_name = "vm" 273 end 274end 275 276################################################################################################# 277# Pick the right distro and bootstrap, default is fedora33 278distro = (ENV['SPDK_VAGRANT_DISTRO'] || "fedora33") 279provider = (ENV['SPDK_VAGRANT_PROVIDER'] || "virtualbox") 280 281# Get all variables for creating vm 282vmcpu = (ENV['SPDK_VAGRANT_VMCPU'] || 2) 283vmram = (ENV['SPDK_VAGRANT_VMRAM'] || 4096) 284 285# generic/freebsd boxes do not work properly with vagrant-proxyconf and 286# have issues installing rsync and sshfs for syncing files. NFS is 287# pre-installed, so use it. 288# generic/fedora boxes on the other hand have problems running NFS 289# service so use sshfs+rsync combo instead. 290force_distro = ENV['FORCE_DISTRO'] == "true" ? true : false 291 292distro_to_use = get_box_type(distro, force_distro) 293if (distro_to_use.include?("generic/freebsd")) 294 files_sync_backend = {type: :nfs, nfs_udp: false, mount_options: ['ro']} 295 plugins_sync_backend = {type: :nfs, nfs_udp: false} 296else 297 # Remove --copy-links from default rsync cmdline since we do want to sync 298 # actual symlinks as well. Also, since copy is made between host and its 299 # local VM we don't need to worry about saturating the local link so skip 300 # the compression to speed up the whole transfer. 301 files_sync_backend = {type: "rsync", rsync__auto: false, rsync__args: ["--archive", "--verbose", "--delete"]} 302 plugins_sync_backend = {type: :sshfs} 303end 304 305Vagrant.configure(2) do |config| 306 config.vm.box = distro_to_use 307 config.vm.box_check_update = false 308 config.vm.synced_folder '.', '/vagrant', disabled: true 309 if ENV['VAGRANT_BOX_VERSION'] 310 config.vm.box_version = ENV['VAGRANT_BOX_VERSION'] 311 end 312 313 # Copy in the .gitconfig if it exists 314 copy_gitconfig(config) 315 316 # Copy in the user's tools if they exists 317 copy_vagrant_tools(config,files_sync_backend) 318 319 # rsync the spdk directory if provision hasn't happened yet 320 # Warning: rsync does not work with freebsd boxes, so this step is disabled 321 copy_spdk_dir(config, files_sync_backend) 322 323 # rsync artifacts from build 324 copy_spdk_artifacts(config, plugins_sync_backend) 325 326 # Setup SSH 327 setup_ssh(config) 328 329 # Virtualbox configuration 330 setup_virtualbox(config,vmcpu,vmram) 331 332 # This setup was Tested on Fedora 27 333 # libvirt configuration need modern Qemu(tested on 2.10) & vagrant-libvirt in version 0.0.39+ 334 # There are few limitation for SElinux - The file added outside libvirt must have proper SE ACL policy or setenforce 0 335 setup_libvirt(config,vmcpu,vmram,distro) 336 337 # provision the vm with all of the necessary spdk dependencies for running the autorun.sh tests 338 deploy_test_vm(config, distro, plugins_sync_backend) 339end 340