From 990714fe3a1bfc77a7febba4bc239740f98536a1 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 17 Jul 2024 19:58:36 +0100 Subject: [PATCH 1/3] feat!: new VM sandboxing bootstrap role --- roles/vm-sandboxing/README.md | 94 +++++++++++++++++++ roles/vm-sandboxing/defaults/main.yml | 41 ++++++++ roles/vm-sandboxing/handlers/main.yml | 5 + roles/vm-sandboxing/meta/main.yml | 21 +++++ roles/vm-sandboxing/tasks/01-bootstrap-vm.yml | 90 ++++++++++++++++++ roles/vm-sandboxing/tasks/main.yml | 2 + roles/vm-sandboxing/vars/main.yml | 1 + 7 files changed, 254 insertions(+) create mode 100644 roles/vm-sandboxing/README.md create mode 100644 roles/vm-sandboxing/defaults/main.yml create mode 100644 roles/vm-sandboxing/handlers/main.yml create mode 100644 roles/vm-sandboxing/meta/main.yml create mode 100644 roles/vm-sandboxing/tasks/01-bootstrap-vm.yml create mode 100644 roles/vm-sandboxing/tasks/main.yml create mode 100644 roles/vm-sandboxing/vars/main.yml diff --git a/roles/vm-sandboxing/README.md b/roles/vm-sandboxing/README.md new file mode 100644 index 0000000..d20497b --- /dev/null +++ b/roles/vm-sandboxing/README.md @@ -0,0 +1,94 @@ +# fluencelabs.provider.vm-sandboxing + +Installs pre-requisites and bootstraps a VM for workload sandboxing purposes. + +## Usage + +See this [example](https://github.com/fluencelabs/ansible/blob/main/example/) + +## Role Variables + +See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/vm-sandboxing/defaults) for details and examples. + +#### `remote_host` + +- Host target to sent meta information on VM startup. +- type: string +- default: + ```yml + libvirt_user: info-catcher.fluence.dev + ``` + +#### `vm_name` + +- libvirt domain name +- type: string +- default: + ```yml + vm_name: sandbox + ``` + +#### `vm_image_url` + +- QEMU image image URL to download +- type: string + +#### `vm_image_local_path` + +- The image path to use bootstraping the VM +- type: string + +#### `libvirt_user` + +- default debian-based distros user for libvirt +- type: string +- default: + ```yml + libvirt_user: libvirt-qemu + ``` + +#### `libvirt_group` + +- default debian-based distros group for libvirt +- type: string +- default: + ```yml + libvirt_group: kvm + ``` + +#### `bridge_name` + +- default bridge interface name +- type: string +- default: + ```yml + bridge_name: br422442 + ``` + +#### `physical_iface` + +- Physical interface to put into the VM bridge (Must be set!) +- type: string + +#### `vm_mac` + +- generated MAC address for the VM +- type: string +- default: autogenerated + +#### `vm_uuid` + +- generated UUID address for the VM +- type: string +- default: autogenerated + +#### `vm_ram` + +- generated UUID address for the VM +- type: number +- default: + ```yml + vm_ram: 1048576 + ``` + + diff --git a/roles/vm-sandboxing/defaults/main.yml b/roles/vm-sandboxing/defaults/main.yml new file mode 100644 index 0000000..e30fdbc --- /dev/null +++ b/roles/vm-sandboxing/defaults/main.yml @@ -0,0 +1,41 @@ +remote_host: info-catcher.fluence.dev +vm_name: sandbox +vm_image_url: https://fluence-os-images.fra1.digitaloceanspaces.com/sandbox/latest/image.qcow2 +vm_image_local_path: /var/lib/libvirt/qemu/images/{{ vm_name }}.qcow2 +libvirt_user: libvirt-qemu +libvirt_group: kvm +bridge_name: br422442 +physical_iface: "dummy0" # Physical network interface to be added to the bridge # TBD +vm_mac: "{{ '52:54:00' | community.general.random_mac(seed=inventory_hostname) }}" +vm_uuid: "{{ '123' | to_uuid }}" +vm_ram: 1048576 # RAM size in KiB (1 GiB) + +vm_template: | + + {{ vm_name }} + {{ vm_uuid }} + {{ vm_ram }} + {{ vm_cores }} + + hvm + + + + + + + +
+ + + + + +
+ + + + + + + diff --git a/roles/vm-sandboxing/handlers/main.yml b/roles/vm-sandboxing/handlers/main.yml new file mode 100644 index 0000000..6a5aa4f --- /dev/null +++ b/roles/vm-sandboxing/handlers/main.yml @@ -0,0 +1,5 @@ +handlers: + - name: restart libvirtd + service: + name: libvirtd + state: restarted diff --git a/roles/vm-sandboxing/meta/main.yml b/roles/vm-sandboxing/meta/main.yml new file mode 100644 index 0000000..2527712 --- /dev/null +++ b/roles/vm-sandboxing/meta/main.yml @@ -0,0 +1,21 @@ +galaxy_info: + namespace: fluencelabs + role_name: vm-sandboxing + license: Apache-2.0 + author: Roman Nozdrin + description: Install and setup Fluence-specific VM sandboxing method + issue_tracker_url: https://github.com/fluencelabs/ansible/issues + min_ansible_version: "2.12" + + platforms: + - name: Ubuntu + versions: + - jammy + - name: Debian + versions: + - bookworm + + galaxy_tags: + - fluence + - web3 + diff --git a/roles/vm-sandboxing/tasks/01-bootstrap-vm.yml b/roles/vm-sandboxing/tasks/01-bootstrap-vm.yml new file mode 100644 index 0000000..2fe5e6e --- /dev/null +++ b/roles/vm-sandboxing/tasks/01-bootstrap-vm.yml @@ -0,0 +1,90 @@ + + tasks: + - name: Call HTTP service at localhost + command: curl http://localhost:18080/peer_id + register: localhost_response + + - name: Gather facts + setup: + + - name: Set vm_cores to the number of logical cores + set_fact: + vm_cores: "{{ ansible_processor_vcpus - 4 }}" + + - name: Install libvirt on Debian-based systems + apt: + name: libvirt-daemon-system + state: present + when: ansible_os_family == 'Debian' + + - name: Install virsh on Debian-based systems + apt: + name: qemu-kvm + state: present + when: ansible_os_family == 'Debian' + + - name: Install bridge-utils on Debian-based systems + apt: + name: bridge-utils + state: present + when: ansible_os_family == 'Debian' + + - name: Create bridge interface br422442 + command: brctl addbr {{ bridge_name }} + args: + creates: /sys/class/net/{{ bridge_name }} + + - name: Check if physical interface is part of the bridge + command: brctl show {{ bridge_name }} + register: bridge_output + changed_when: false + + - name: Set fact if physical interface is not in bridge + set_fact: + iface_not_in_bridge: "{{ physical_iface not in bridge_output.stdout }}" + + - name: Add physical interface to the bridge if not already added + command: brctl addif {{ bridge_name }} {{ physical_iface }} + when: iface_not_in_bridge + ignore_errors: yes + + - name: Bring up the bridge interface + command: ip link set {{ bridge_name }} up + when: "bridge_name not in ansible_facts.interfaces" + + - name: Bring up the physical interface + command: ip link set {{ physical_iface }} up + + - name: Download VM image + get_url: + url: "{{ vm_image_url }}" + dest: "{{ vm_image_local_path }}" + mode: '0644' + owner: "{{ libvirt_user }}" + group: "{{ libvirt_group }}" + + - name: Ensure a simple VM is defined + community.libvirt.virt: + command: define + xml: "{{ vm_template }}" + autostart: true + notify: restart libvirtd + + - name: Start the VM + community.libvirt.virt: + name: "{{ vm_name }}" + state: running + + - name: Extract peer_id from JSON response + set_fact: + peer_id: "{{ (localhost_response.stdout | from_json).peer_id }}" + + - name: Print peer_id + debug: + msg: "The peer_id is {{ peer_id }}" + + - name: Call HTTP service on a remote host + command: curl -L http://{{ remote_host }}/peer_id/?{{ peer_id }} + register: remotehost_response + + diff --git a/roles/vm-sandboxing/tasks/main.yml b/roles/vm-sandboxing/tasks/main.yml new file mode 100644 index 0000000..acdb703 --- /dev/null +++ b/roles/vm-sandboxing/tasks/main.yml @@ -0,0 +1,2 @@ +- name: Bootstrap VM sandboxing + ansible.builtin.include_tasks: 01-bootstrap-vm.yml diff --git a/roles/vm-sandboxing/vars/main.yml b/roles/vm-sandboxing/vars/main.yml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/roles/vm-sandboxing/vars/main.yml @@ -0,0 +1 @@ + From 3ef6eabbeaefebe0573cdf2ff5fc50bb3595a434 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 19 Jul 2024 13:46:53 +0100 Subject: [PATCH 2/3] fix!: rename role to omit - sign that annoys galaxy --- roles/{vm-sandboxing => vmsandboxing}/README.md | 4 ++-- roles/{vm-sandboxing => vmsandboxing}/defaults/main.yml | 0 roles/{vm-sandboxing => vmsandboxing}/handlers/main.yml | 0 roles/{vm-sandboxing => vmsandboxing}/meta/main.yml | 2 +- .../{vm-sandboxing => vmsandboxing}/tasks/01-bootstrap-vm.yml | 0 roles/{vm-sandboxing => vmsandboxing}/tasks/main.yml | 0 roles/{vm-sandboxing => vmsandboxing}/vars/main.yml | 0 7 files changed, 3 insertions(+), 3 deletions(-) rename roles/{vm-sandboxing => vmsandboxing}/README.md (94%) rename roles/{vm-sandboxing => vmsandboxing}/defaults/main.yml (100%) rename roles/{vm-sandboxing => vmsandboxing}/handlers/main.yml (100%) rename roles/{vm-sandboxing => vmsandboxing}/meta/main.yml (93%) rename roles/{vm-sandboxing => vmsandboxing}/tasks/01-bootstrap-vm.yml (100%) rename roles/{vm-sandboxing => vmsandboxing}/tasks/main.yml (100%) rename roles/{vm-sandboxing => vmsandboxing}/vars/main.yml (100%) diff --git a/roles/vm-sandboxing/README.md b/roles/vmsandboxing/README.md similarity index 94% rename from roles/vm-sandboxing/README.md rename to roles/vmsandboxing/README.md index d20497b..e985bcd 100644 --- a/roles/vm-sandboxing/README.md +++ b/roles/vmsandboxing/README.md @@ -1,4 +1,4 @@ -# fluencelabs.provider.vm-sandboxing +# fluencelabs.provider.vm_sandboxing Installs pre-requisites and bootstraps a VM for workload sandboxing purposes. @@ -8,7 +8,7 @@ See this [example](https://github.com/fluencelabs/ansible/blob/main/example/) ## Role Variables -See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/vm-sandboxing/defaults) for details and examples. +See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/vm_sandboxing/defaults) for details and examples. #### `remote_host` diff --git a/roles/vm-sandboxing/defaults/main.yml b/roles/vmsandboxing/defaults/main.yml similarity index 100% rename from roles/vm-sandboxing/defaults/main.yml rename to roles/vmsandboxing/defaults/main.yml diff --git a/roles/vm-sandboxing/handlers/main.yml b/roles/vmsandboxing/handlers/main.yml similarity index 100% rename from roles/vm-sandboxing/handlers/main.yml rename to roles/vmsandboxing/handlers/main.yml diff --git a/roles/vm-sandboxing/meta/main.yml b/roles/vmsandboxing/meta/main.yml similarity index 93% rename from roles/vm-sandboxing/meta/main.yml rename to roles/vmsandboxing/meta/main.yml index 2527712..0c7a85d 100644 --- a/roles/vm-sandboxing/meta/main.yml +++ b/roles/vmsandboxing/meta/main.yml @@ -1,6 +1,6 @@ galaxy_info: namespace: fluencelabs - role_name: vm-sandboxing + role_name: vm_sandboxing license: Apache-2.0 author: Roman Nozdrin description: Install and setup Fluence-specific VM sandboxing method diff --git a/roles/vm-sandboxing/tasks/01-bootstrap-vm.yml b/roles/vmsandboxing/tasks/01-bootstrap-vm.yml similarity index 100% rename from roles/vm-sandboxing/tasks/01-bootstrap-vm.yml rename to roles/vmsandboxing/tasks/01-bootstrap-vm.yml diff --git a/roles/vm-sandboxing/tasks/main.yml b/roles/vmsandboxing/tasks/main.yml similarity index 100% rename from roles/vm-sandboxing/tasks/main.yml rename to roles/vmsandboxing/tasks/main.yml diff --git a/roles/vm-sandboxing/vars/main.yml b/roles/vmsandboxing/vars/main.yml similarity index 100% rename from roles/vm-sandboxing/vars/main.yml rename to roles/vmsandboxing/vars/main.yml From 578a11e3ced3a2826d10adb4999484d10823c341 Mon Sep 17 00:00:00 2001 From: Anatoly Laskaris Date: Tue, 23 Jul 2024 12:47:22 +0300 Subject: [PATCH 3/3] Add preflight and update vars names --- roles/vmsandboxing/README.md | 48 +++++----- roles/vmsandboxing/defaults/main.yml | 11 +-- roles/vmsandboxing/tasks/00-preflight.yml | 98 ++++++++++++++++++++ roles/vmsandboxing/tasks/01-bootstrap-vm.yml | 25 +++-- roles/vmsandboxing/tasks/main.yml | 6 +- roles/vmsandboxing/vars/main.yml | 1 - 6 files changed, 143 insertions(+), 46 deletions(-) create mode 100644 roles/vmsandboxing/tasks/00-preflight.yml delete mode 100644 roles/vmsandboxing/vars/main.yml diff --git a/roles/vmsandboxing/README.md b/roles/vmsandboxing/README.md index e985bcd..e37547e 100644 --- a/roles/vmsandboxing/README.md +++ b/roles/vmsandboxing/README.md @@ -8,15 +8,17 @@ See this [example](https://github.com/fluencelabs/ansible/blob/main/example/) ## Role Variables -See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/vm_sandboxing/defaults) for details and examples. +See +[defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/vm_sandboxing/defaults) +for details and examples. -#### `remote_host` +#### `vm_remote_host` - Host target to sent meta information on VM startup. - type: string - default: ```yml - libvirt_user: info-catcher.fluence.dev + vm_libvirt_user: info-catcher.fluence.dev ``` #### `vm_name` @@ -38,57 +40,55 @@ See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/vm_sandbo - The image path to use bootstraping the VM - type: string -#### `libvirt_user` +#### `vm_libvirt_user` - default debian-based distros user for libvirt - type: string - default: - ```yml - libvirt_user: libvirt-qemu - ``` + ```yml + vm_libvirt_user: libvirt-qemu + ``` -#### `libvirt_group` +#### `vm_libvirt_group` - default debian-based distros group for libvirt - type: string - default: - ```yml - libvirt_group: kvm - ``` + ```yml + vm_libvirt_group: kvm + ``` -#### `bridge_name` +#### `vm_bridge_name` - default bridge interface name - type: string - default: - ```yml - bridge_name: br422442 - ``` + ```yml + vm_bridge_name: br422442 + ``` -#### `physical_iface` +#### `vm_physical_iface` - Physical interface to put into the VM bridge (Must be set!) - type: string #### `vm_mac` -- generated MAC address for the VM +- generated MAC address for the VM - type: string - default: autogenerated #### `vm_uuid` -- generated UUID address for the VM +- generated UUID address for the VM - type: string - default: autogenerated #### `vm_ram` -- generated UUID address for the VM +- generated UUID address for the VM - type: number - default: - ```yml - vm_ram: 1048576 - ``` - - + ```yml + vm_ram: 1048576 + ``` diff --git a/roles/vmsandboxing/defaults/main.yml b/roles/vmsandboxing/defaults/main.yml index e30fdbc..f949319 100644 --- a/roles/vmsandboxing/defaults/main.yml +++ b/roles/vmsandboxing/defaults/main.yml @@ -1,11 +1,11 @@ -remote_host: info-catcher.fluence.dev +vm_remote_host: info-catcher.fluence.dev vm_name: sandbox vm_image_url: https://fluence-os-images.fra1.digitaloceanspaces.com/sandbox/latest/image.qcow2 vm_image_local_path: /var/lib/libvirt/qemu/images/{{ vm_name }}.qcow2 -libvirt_user: libvirt-qemu -libvirt_group: kvm -bridge_name: br422442 -physical_iface: "dummy0" # Physical network interface to be added to the bridge # TBD +vm_libvirt_user: libvirt-qemu +vm_libvirt_group: kvm +vm_bridge_name: br422442 +# vm_physical_iface: "dummy0" # Physical network interface to be added to the bridge # TBD vm_mac: "{{ '52:54:00' | community.general.random_mac(seed=inventory_hostname) }}" vm_uuid: "{{ '123' | to_uuid }}" vm_ram: 1048576 # RAM size in KiB (1 GiB) @@ -38,4 +38,3 @@ vm_template: | - diff --git a/roles/vmsandboxing/tasks/00-preflight.yml b/roles/vmsandboxing/tasks/00-preflight.yml new file mode 100644 index 0000000..a577291 --- /dev/null +++ b/roles/vmsandboxing/tasks/00-preflight.yml @@ -0,0 +1,98 @@ +- name: check "vm_remote_host" variable + tags: always + ansible.builtin.assert: + that: + - vm_remote_host is defined + - vm_remote_host is string + - vm_remote_host | length + quiet: true + +- name: check "vm_name" variable + tags: always + ansible.builtin.assert: + that: + - vm_name is defined + - vm_name is string + - vm_name | length + quiet: true + +- name: check "vm_image_url" variable + tags: always + ansible.builtin.assert: + that: + - vm_image_url is defined + - vm_image_url is string + - vm_image_url | length + quiet: true + +- name: check "vm_image_local_path" variable + tags: always + ansible.builtin.assert: + that: + - vm_image_local_path is defined + - vm_image_local_path is string + - vm_image_local_path | length + quiet: true + +- name: check "vm_libvirt_user" variable + tags: always + ansible.builtin.assert: + that: + - vm_libvirt_user is defined + - vm_libvirt_user is string + - vm_libvirt_user | length + quiet: true + +- name: check "vm_libvirt_group" variable + tags: always + ansible.builtin.assert: + that: + - vm_libvirt_group is defined + - vm_libvirt_group is string + - vm_libvirt_group | length + quiet: true + +- name: check "vm_bridge_name" variable + tags: always + ansible.builtin.assert: + that: + - vm_bridge_name is defined + - vm_bridge_name is string + - vm_bridge_name | length + quiet: true + +- name: check "vm_physical_iface" variable + tags: always + ansible.builtin.assert: + that: + - vm_physical_iface is defined + - vm_physical_iface is string + - vm_physical_iface | length + quiet: true + +- name: check "vm_mac" variable + tags: always + ansible.builtin.assert: + that: + - vm_mac is defined + - vm_mac is string + - vm_mac | length + quiet: true + +- name: check "vm_uuid" variable + tags: always + ansible.builtin.assert: + that: + - vm_uuid is defined + - vm_uuid is string + - vm_uuid | length + quiet: true + +- name: check "vm_ram" variable + tags: always + ansible.builtin.assert: + that: + - vm_ram is defined + - vm_ram is string + - vm_ram | length + quiet: true diff --git a/roles/vmsandboxing/tasks/01-bootstrap-vm.yml b/roles/vmsandboxing/tasks/01-bootstrap-vm.yml index 2fe5e6e..77f3910 100644 --- a/roles/vmsandboxing/tasks/01-bootstrap-vm.yml +++ b/roles/vmsandboxing/tasks/01-bootstrap-vm.yml @@ -1,7 +1,6 @@ - tasks: - name: Call HTTP service at localhost - command: curl http://localhost:18080/peer_id + command: curl http://localhost:18080/peer_id register: localhost_response - name: Gather facts @@ -30,38 +29,38 @@ when: ansible_os_family == 'Debian' - name: Create bridge interface br422442 - command: brctl addbr {{ bridge_name }} + command: brctl addbr {{ vm_bridge_name }} args: - creates: /sys/class/net/{{ bridge_name }} + creates: /sys/class/net/{{ vm_bridge_name }} - name: Check if physical interface is part of the bridge - command: brctl show {{ bridge_name }} + command: brctl show {{ vm_bridge_name }} register: bridge_output changed_when: false - name: Set fact if physical interface is not in bridge set_fact: - iface_not_in_bridge: "{{ physical_iface not in bridge_output.stdout }}" + iface_not_in_bridge: "{{ vm_physical_iface not in bridge_output.stdout }}" - name: Add physical interface to the bridge if not already added - command: brctl addif {{ bridge_name }} {{ physical_iface }} + command: brctl addif {{ vm_bridge_name }} {{ vm_physical_iface }} when: iface_not_in_bridge ignore_errors: yes - name: Bring up the bridge interface - command: ip link set {{ bridge_name }} up + command: ip link set {{ vm_bridge_name }} up when: "bridge_name not in ansible_facts.interfaces" - name: Bring up the physical interface - command: ip link set {{ physical_iface }} up + command: ip link set {{ vm_physical_iface }} up - name: Download VM image get_url: url: "{{ vm_image_url }}" dest: "{{ vm_image_local_path }}" mode: '0644' - owner: "{{ libvirt_user }}" - group: "{{ libvirt_group }}" + owner: "{{ vm_libvirt_user }}" + group: "{{ vm_libvirt_group }}" - name: Ensure a simple VM is defined community.libvirt.virt: @@ -84,7 +83,5 @@ msg: "The peer_id is {{ peer_id }}" - name: Call HTTP service on a remote host - command: curl -L http://{{ remote_host }}/peer_id/?{{ peer_id }} + command: curl -L http://{{ vm_remote_host }}/peer_id/?{{ peer_id }} register: remotehost_response - - diff --git a/roles/vmsandboxing/tasks/main.yml b/roles/vmsandboxing/tasks/main.yml index acdb703..9c717a5 100644 --- a/roles/vmsandboxing/tasks/main.yml +++ b/roles/vmsandboxing/tasks/main.yml @@ -1,2 +1,6 @@ -- name: Bootstrap VM sandboxing +- name: Preflight + tags: always + ansible.builtin.include_tasks: 00-preflight.yml + +- name: Bootstrap VM ansible.builtin.include_tasks: 01-bootstrap-vm.yml diff --git a/roles/vmsandboxing/vars/main.yml b/roles/vmsandboxing/vars/main.yml deleted file mode 100644 index 8b13789..0000000 --- a/roles/vmsandboxing/vars/main.yml +++ /dev/null @@ -1 +0,0 @@ -