From 5da5f187604bf146d22c171b554c785b4e802b81 Mon Sep 17 00:00:00 2001 From: Evgeniy L Date: Fri, 9 Oct 2015 21:02:38 +0300 Subject: [PATCH 1/2] Add option to boot slave using pxe into bootstrap image This functionality is required in order to perform partitioning/provisioning. --- Vagrantfile | 50 ++++++++++++++++------ bootstrap/playbooks/files/dnsmasq_pxe.conf | 13 ++++++ bootstrap/playbooks/files/nginx.cfg | 8 ++++ bootstrap/playbooks/files/pxelinux.cfg | 11 +++++ bootstrap/playbooks/pxe.yaml | 50 ++++++++++++++++++++++ vagrant-settings.yaml_defaults | 8 ++++ 6 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 bootstrap/playbooks/files/dnsmasq_pxe.conf create mode 100644 bootstrap/playbooks/files/nginx.cfg create mode 100644 bootstrap/playbooks/files/pxelinux.cfg create mode 100644 bootstrap/playbooks/pxe.yaml diff --git a/Vagrantfile b/Vagrantfile index 55656f83..f2e72cca 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -39,6 +39,7 @@ SYNC_TYPE = cfg["sync_type"] MASTER_CPUS = cfg["master_cpus"] SLAVES_CPUS = cfg["slaves_cpus"] PARAVIRT_PROVIDER = cfg.fetch('paravirtprovider', false) +PREPROVISIONED = cfg.fetch('preprovisioned', true) def ansible_playbook_command(filename, args=[]) "ansible-playbook -v -i \"localhost,\" -c local /vagrant/bootstrap/playbooks/#{filename} #{args.join ' '}" @@ -52,6 +53,9 @@ master_celery = ansible_playbook_command("celery.yaml", ["--skip-tags", "slave"] slave_celery = ansible_playbook_command("celery.yaml", ["--skip-tags", "master"]) +master_pxe = ansible_playbook_command("pxe.yaml") + + Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.define "solar-dev", primary: true do |config| @@ -59,6 +63,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.provision "shell", inline: solar_script, privileged: true config.vm.provision "shell", inline: master_celery, privileged: true + config.vm.provision "shell", inline: master_pxe, privileged: true unless PREPROVISIONED config.vm.provision "file", source: "~/.vagrant.d/insecure_private_key", destination: "/vagrant/tmp/keys/ssh_private" config.vm.provision "file", source: "bootstrap/ansible.cfg", destination: "/home/vagrant/.ansible.cfg" config.vm.network "private_network", ip: "10.0.0.2" @@ -101,17 +106,26 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| index = i + 1 ip_index = i + 3 config.vm.define "solar-dev#{index}" do |config| - # standard box with all stuff preinstalled - config.vm.box = SLAVES_IMAGE - config.vm.provision "file", source: "bootstrap/ansible.cfg", destination: "/home/vagrant/.ansible.cfg" - config.vm.provision "shell", inline: slave_script, privileged: true - config.vm.provision "shell", inline: solar_script, privileged: true - config.vm.provision "shell", inline: slave_celery, privileged: true - config.vm.network "private_network", ip: "10.0.0.#{ip_index}" + # Standard box with all stuff preinstalled + config.vm.box = SLAVES_IMAGE config.vm.host_name = "solar-dev#{index}" + if PREPROVISIONED + config.vm.provision "file", source: "bootstrap/ansible.cfg", destination: "/home/vagrant/.ansible.cfg" + config.vm.provision "shell", inline: slave_script, privileged: true + config.vm.provision "shell", inline: solar_script, privileged: true + config.vm.provision "shell", inline: slave_celery, privileged: true + config.vm.network "private_network", ip: "10.0.0.#{ip_index}" + else + config.vm.network "private_network", adapter: 1, ip: "10.0.0.#{ip_index}" + config.vbguest.no_install = true + config.ssh.username = 'root' + config.ssh.insert_key = false + end + config.vm.provider :virtualbox do |v| + boot_order(v, ['net', 'disk']) v.customize [ "modifyvm", :id, "--memory", SLAVES_RAM, @@ -133,14 +147,26 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| libvirt.volume_cache = 'unsafe' end - if SYNC_TYPE == 'nfs' - config.vm.synced_folder ".", "/vagrant", type: "nfs" - end - if SYNC_TYPE == 'rsync' - config.vm.synced_folder ".", "/vagrant", rsync: "nfs", + if PREPROVISIONED + if SYNC_TYPE == 'nfs' + config.vm.synced_folder ".", "/vagrant", type: "nfs" + end + if SYNC_TYPE == 'rsync' + config.vm.synced_folder ".", "/vagrant", rsync: "nfs", rsync__args: ["--verbose", "--archive", "--delete", "-z"] + end end + end end end + +def boot_order(virt_config, order) + # Boot order is specified with special flag: + # --boot<1-4> none|floppy|dvd|disk|net + 4.times do |idx| + device = order[idx] || 'none' + virt_config.customize ['modifyvm', :id, "--boot#{idx + 1}", device] + end +end diff --git a/bootstrap/playbooks/files/dnsmasq_pxe.conf b/bootstrap/playbooks/files/dnsmasq_pxe.conf new file mode 100644 index 00000000..05e9e45f --- /dev/null +++ b/bootstrap/playbooks/files/dnsmasq_pxe.conf @@ -0,0 +1,13 @@ +# Specify interface for dhcp server +interface={{dhcp_interface}} +bind-interfaces + +# Specify IP addresses range +dhcp-range={{dhcp_range_start}},{{dhcp_range_end}},12h + +# Net boot file name +dhcp-boot=tag:!nopxe,pxelinux.0 + +# Configure tftp +enable-tftp +tftp-root={{tftp_root}} diff --git a/bootstrap/playbooks/files/nginx.cfg b/bootstrap/playbooks/files/nginx.cfg new file mode 100644 index 00000000..ebc4c19a --- /dev/null +++ b/bootstrap/playbooks/files/nginx.cfg @@ -0,0 +1,8 @@ +server { + listen 8000; + root /var/lib/tftp; + + location / { + autoindex on; + } +} diff --git a/bootstrap/playbooks/files/pxelinux.cfg b/bootstrap/playbooks/files/pxelinux.cfg new file mode 100644 index 00000000..4c08facd --- /dev/null +++ b/bootstrap/playbooks/files/pxelinux.cfg @@ -0,0 +1,11 @@ +default vesamenu.c32 +menu title Live CD Choices +prompt 0 +timeout 3 +menu autoboot + +label ubuntu + menu label Ubuntu + kernel /ubuntu/linux + append initrd=/ubuntu/initramfs.img verbose fetch=http://{{http_ip}}:{{http_port}}/ubuntu/root.squashfs ip=dhcp boot=live + iappend 2 diff --git a/bootstrap/playbooks/pxe.yaml b/bootstrap/playbooks/pxe.yaml new file mode 100644 index 00000000..08853539 --- /dev/null +++ b/bootstrap/playbooks/pxe.yaml @@ -0,0 +1,50 @@ +--- + +- name: Setup dhcp server with bootstrap image + hosts: all + sudo: yes + vars: + tftp_root: /var/lib/tftp + dhcp_range_start: 10.0.0.42 + dhcp_range_end: 10.0.0.53 + dhcp_interface: eth1 + pxe_netboot_image: http://archive.ubuntu.com/ubuntu/dists/trusty-updates/main/installer-amd64/current/images/netboot/pxelinux.0 + pxe_netboot_menu: http://archive.ubuntu.com/ubuntu/dists/trusty-updates/main/installer-amd64/current/images/netboot/ubuntu-installer/amd64/boot-screens/vesamenu.c32 + insecure_pub_key: https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub + insecure_pub_key_path: /tmp/ssh_insecure.pub + image_builder_path: /tmp/image_builder + http_ip: 10.0.0.2 + http_port: 8000 + + tasks: + # Istall and configure dnsmasq + - apt: name=dnsmasq state=present + - file: path={{tftp_root}} state=directory + - template: src=files/dnsmasq_pxe.conf dest=/etc/dnsmasq.d/pxe.conf + - service: name=dnsmasq state=restarted + - file: path="{{tftp_root}}/pxelinux.cfg" state=directory + - template: src=files/pxelinux.cfg dest="{{tftp_root}}/pxelinux.cfg/default" + + # Prepare pxe configs and download pxe image + - get_url: url={{pxe_netboot_image}} dest="{{tftp_root}}/pxelinux.0" + - get_url: url={{pxe_netboot_menu}} dest="{{tftp_root}}/vesamenu.c32" + + # Build image + - get_url: url={{insecure_pub_key}} dest={{insecure_pub_key_path}} + - apt: name=debootstrap state=present + - file: path={{tftp_root}}/ubuntu state=directory + - git: repo=https://github.com/rustyrobot/fuel-bootstrap-image-builder dest={{image_builder_path}} + - shell: "{{image_builder_path}}/bin/fuel-bootstrap-image 2>&1 | tee /tmp/image_build.log" + environment: + BOOTSTRAP_SSH_KEYS: "{{insecure_pub_key_path}}" + DESTDIR: "{{tftp_root}}/ubuntu" + - file: path="{{tftp_root}}/ubuntu/{{item}}" mode=0644 state=file + with_items: + - initramfs.img + - linux + - root.squashfs + + # Configure http server to load root + - apt: name=nginx state=present + - template: src=files/nginx.cfg dest=/etc/nginx/conf.d/pxe_image.conf + - service: name=nginx state=restarted diff --git a/vagrant-settings.yaml_defaults b/vagrant-settings.yaml_defaults index 4b3a4c12..e2e6f2c4 100644 --- a/vagrant-settings.yaml_defaults +++ b/vagrant-settings.yaml_defaults @@ -17,3 +17,11 @@ slaves_cpus: 1 # Uncomment following option to change it. # Possible options are: rsync, nfs # sync_type: nfs + +# Use vagrant image in order to perform provisioning +preprovisioned: true + +# Use pxe bootstrap in order to bootstrap nodes +# it should be used in order to provision nodes +# by solar +# preprovisioned: false From 39170b3b1b1b9e22cb2c7637552f5a9d66cac317 Mon Sep 17 00:00:00 2001 From: Evgeniy L Date: Mon, 12 Oct 2015 19:26:41 +0300 Subject: [PATCH 2/2] Make vagrant silently run pxe nodes, without checks --- Vagrantfile | 13 ++++++- bootstrap/vagrant_plugins/noop.rb | 61 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 bootstrap/vagrant_plugins/noop.rb diff --git a/Vagrantfile b/Vagrantfile index f2e72cca..521e7602 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -41,6 +41,9 @@ SLAVES_CPUS = cfg["slaves_cpus"] PARAVIRT_PROVIDER = cfg.fetch('paravirtprovider', false) PREPROVISIONED = cfg.fetch('preprovisioned', true) +# Initialize noop plugins only in case of PXE boot +require_relative 'bootstrap/vagrant_plugins/noop' unless PREPROVISIONED + def ansible_playbook_command(filename, args=[]) "ansible-playbook -v -i \"localhost,\" -c local /vagrant/bootstrap/playbooks/#{filename} #{args.join ' '}" end @@ -118,10 +121,15 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.provision "shell", inline: slave_celery, privileged: true config.vm.network "private_network", ip: "10.0.0.#{ip_index}" else + # Disable attempts to install guest os and check that node is booted using ssh, + # because nodes will have ip addresses from dhcp, and vagrant doesn't know + # which ip to use to perform connection + config.vm.communicator = :noop + config.vm.guest = :noop_guest + # Configure network to boot vm using pxe config.vm.network "private_network", adapter: 1, ip: "10.0.0.#{ip_index}" config.vbguest.no_install = true - config.ssh.username = 'root' - config.ssh.insert_key = false + config.vbguest.auto_update = false end config.vm.provider :virtualbox do |v| @@ -162,6 +170,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| end + def boot_order(virt_config, order) # Boot order is specified with special flag: # --boot<1-4> none|floppy|dvd|disk|net diff --git a/bootstrap/vagrant_plugins/noop.rb b/bootstrap/vagrant_plugins/noop.rb new file mode 100644 index 00000000..95246d62 --- /dev/null +++ b/bootstrap/vagrant_plugins/noop.rb @@ -0,0 +1,61 @@ +# Noop Vagrant plugins are used in case if Vagrant does not +# have an access to VMs (e.g. there is no information about ip), +# so it just runs VMs and does not try to perform additional +# actions using SSH. + +class NoopCommunicator < Vagrant.plugin("2", :communicator) + + def ready? + true + end + + def wait_for_ready(timeout) + true + end + +end + + +class NoopGuest < Vagrant.plugin("2", :guest) + + def self.change_host_name(*args) + true + end + + def self.configure_networks(*args) + true + end + + def self.mount_virtualbox_shared_folder(*args) + true + end + +end + + +class NoopCommunicatorPlugin < Vagrant.plugin("2") + + name 'Noop communicator/guest' + description 'Noop communicator/guest' + + communicator('noop') do + NoopCommunicator + end + + guest 'noop_guest' do + NoopGuest + end + + guest_capability 'noop_guest', 'change_host_name' do + NoopGuest + end + + guest_capability 'noop_guest', 'configure_networks' do + NoopGuest + end + + guest_capability 'noop_guest', 'mount_virtualbox_shared_folder' do + NoopGuest + end + +end