Build Windows Templates in RHV
This commit is contained in:
29
roles/oatakan.ansible-role-ovirt/.travis.yml
Normal file
29
roles/oatakan.ansible-role-ovirt/.travis.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
language: python
|
||||
python: "2.7"
|
||||
|
||||
# Use the new container infrastructure
|
||||
sudo: false
|
||||
|
||||
# Install ansible
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- python-pip
|
||||
|
||||
install:
|
||||
# Install ansible
|
||||
- pip install ansible
|
||||
|
||||
# Check ansible version
|
||||
- ansible --version
|
||||
|
||||
# Create ansible.cfg with correct roles_path
|
||||
- printf '[defaults]\nroles_path=../' >ansible.cfg
|
||||
|
||||
script:
|
||||
# Basic role syntax check
|
||||
- ansible-playbook tests/test.yml -i tests/inventory --syntax-check
|
||||
|
||||
notifications:
|
||||
webhooks: https://galaxy.ansible.com/api/v1/notifications/
|
||||
38
roles/oatakan.ansible-role-ovirt/README.md
Normal file
38
roles/oatakan.ansible-role-ovirt/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
Role Name
|
||||
=========
|
||||
|
||||
A brief description of the role goes here.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the ovirt module, it may be a good idea to mention in this section that the boto package is required.
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
|
||||
|
||||
- hosts: servers
|
||||
roles:
|
||||
- { role: username.rolename, x: 42 }
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
BSD
|
||||
|
||||
Author Information
|
||||
------------------
|
||||
|
||||
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
|
||||
15
roles/oatakan.ansible-role-ovirt/defaults/main.yml
Normal file
15
roles/oatakan.ansible-role-ovirt/defaults/main.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
|
||||
role_action: provision
|
||||
|
||||
ovirt:
|
||||
url: ''
|
||||
username: ''
|
||||
password: ''
|
||||
|
||||
ansible_port: 22
|
||||
instance_wait_retry_limit: 600
|
||||
instance_wait_connection_timeout: 300
|
||||
|
||||
wait_for_static_ip_assigned: yes
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
install_date: Thu Apr 22 02:46:27 2021
|
||||
version: ''
|
||||
25
roles/oatakan.ansible-role-ovirt/meta/main.yml
Normal file
25
roles/oatakan.ansible-role-ovirt/meta/main.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
galaxy_info:
|
||||
author: Orcun Atakan
|
||||
description: Ansible galaxy role for creating virtual machines on ovirt/rhev
|
||||
company: Red Hat
|
||||
|
||||
license: license (GPLv2, CC-BY, etc)
|
||||
|
||||
min_ansible_version: 1.2
|
||||
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
|
||||
categories:
|
||||
- all
|
||||
|
||||
galaxy_tags:
|
||||
- ovirt
|
||||
- rhev
|
||||
|
||||
collections:
|
||||
- ovirt.ovirt
|
||||
|
||||
dependencies: []
|
||||
65
roles/oatakan.ansible-role-ovirt/tasks/deprovision.yml
Normal file
65
roles/oatakan.ansible-role-ovirt/tasks/deprovision.yml
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
|
||||
- name: remove vms
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ item }}"
|
||||
cluster: "{{ providers.ovirt.cluster | default('Default') }}"
|
||||
storage_domain: "{{ item.storage_domain | default(omit) }}"
|
||||
state: absent
|
||||
wait: yes
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: undeploy
|
||||
loop: "{{ ansible_play_hosts | intersect(nodes | map(attribute='name') | list) }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- hostvars[item].name is defined
|
||||
|
||||
- name: wait for vms to be deleted
|
||||
async_status:
|
||||
jid: "{{ item.ansible_job_id }}"
|
||||
register: vm_remove
|
||||
until: vm_remove.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
loop: "{{ undeploy.results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- undeploy.results is defined
|
||||
- item.ansible_job_id is defined
|
||||
|
||||
- name: delete additional disks
|
||||
ovirt_disk:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{% if item.1.name_prefix | default(true) %}{{ item.0.name }}_{% endif %}{{ item.1.name }}"
|
||||
vm_name: "{{ item.0.name }}"
|
||||
storage_domain: "{{ item.1.storage_domain | default(omit) }}"
|
||||
state: absent
|
||||
wait: no
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: delete_disks
|
||||
with_subelements:
|
||||
- "{{ nodes | json_query(query) }}"
|
||||
- disks
|
||||
- skip_missing: yes
|
||||
when:
|
||||
- nodes is defined
|
||||
- item.1 is defined
|
||||
- item.1.storage_domain is defined
|
||||
vars:
|
||||
query: "@[?contains(`{{ ansible_play_hosts }}`, name)]"
|
||||
|
||||
- name: wait for disk deletion to complete
|
||||
async_status:
|
||||
jid: "{{ item.ansible_job_id }}"
|
||||
register: disks_deletion
|
||||
until: disks_deletion.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
with_items: "{{ delete_disks.results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- delete_disks.results is defined
|
||||
- item.ansible_job_id is defined
|
||||
25
roles/oatakan.ansible-role-ovirt/tasks/main.yml
Normal file
25
roles/oatakan.ansible-role-ovirt/tasks/main.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
|
||||
- block:
|
||||
- name: obtain SSO token with using username/password credentials
|
||||
ovirt_auth:
|
||||
url: "{{ lookup('env', 'OVIRT_URL')|default(ovirt.url, true) }}"
|
||||
username: "{{ lookup('env', 'OVIRT_USERNAME')|default(ovirt.username, true) }}"
|
||||
password: "{{ lookup('env', 'OVIRT_PASSWORD')|default(ovirt.password, true) }}"
|
||||
insecure: yes
|
||||
|
||||
- include_tasks: provision.yml
|
||||
when: role_action == 'provision'
|
||||
|
||||
- include_tasks: deprovision.yml
|
||||
run_once: yes
|
||||
when: role_action == 'deprovision'
|
||||
always:
|
||||
- name: revoke the SSO token
|
||||
ovirt_auth:
|
||||
url: "{{ lookup('env', 'OVIRT_URL')|default(ovirt.url, true) }}"
|
||||
username: "{{ lookup('env', 'OVIRT_USERNAME')|default(ovirt.username, true) }}"
|
||||
password: "{{ lookup('env', 'OVIRT_PASSWORD')|default(ovirt.password, true) }}"
|
||||
insecure: yes
|
||||
ovirt_auth: "{{ ovirt_auth }}"
|
||||
state: absent
|
||||
40
roles/oatakan.ansible-role-ovirt/tasks/preflight_check.yml
Normal file
40
roles/oatakan.ansible-role-ovirt/tasks/preflight_check.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
|
||||
- name: fail if cluster name is not specified
|
||||
fail:
|
||||
msg: "cluster name is not specified, please specify providers.ovirt.cluster"
|
||||
when: (providers.ovirt.cluster | default(None)) is undefined
|
||||
|
||||
- name: get the datacenter name
|
||||
ovirt_datacenter_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "Clusters.name = {{ providers.ovirt.cluster }}"
|
||||
register: datacenter_info
|
||||
|
||||
- name: fail if datacenter is not found
|
||||
fail:
|
||||
msg: "data center is not found"
|
||||
when: datacenter_info.ovirt_datacenters | length == 0
|
||||
|
||||
- name: get storage information
|
||||
ovirt_storage_domain_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "datacenter={{ datacenter_info.ovirt_datacenters[0].name }}"
|
||||
register: storage_info
|
||||
|
||||
- name: set data domain
|
||||
set_fact:
|
||||
disk_storage_domain: "{{ storage_info.ovirt_storage_domains|json_query(the_query)|list|first|default(None) }}"
|
||||
vars:
|
||||
the_query: "[?type=='data']"
|
||||
|
||||
- name: set iso domain (deprecated as of oVirt/RHV 4.3)
|
||||
set_fact:
|
||||
iso_domain: "{{ storage_info.ovirt_storage_domains|json_query(the_query)|list|first|default(None) }}"
|
||||
vars:
|
||||
the_query: "[?type=='iso']"
|
||||
|
||||
- include_tasks: template_check.yml
|
||||
loop: "{{ nodes }}"
|
||||
loop_control:
|
||||
loop_var: node
|
||||
183
roles/oatakan.ansible-role-ovirt/tasks/provision.yml
Normal file
183
roles/oatakan.ansible-role-ovirt/tasks/provision.yml
Normal file
@@ -0,0 +1,183 @@
|
||||
---
|
||||
|
||||
- include_tasks: preflight_check.yml
|
||||
|
||||
- name: clone from template
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ item.name }}"
|
||||
template: "{{ item.template | default(omit) }}"
|
||||
cluster: "{{ providers.ovirt.cluster | default('Default') }}"
|
||||
state: present
|
||||
wait: yes
|
||||
memory: "{{ item.memory }}MiB"
|
||||
memory_max: "{{ ((item.memory_max | string) + 'MiB') if item.memory_max is defined else omit }}"
|
||||
memory_guaranteed: "{{ ((item.memory_guaranteed | string) + 'MiB') if item.memory_guaranteed is defined else omit }}"
|
||||
cpu_mode: "{{ item.cpu_mode | default(omit) }}"
|
||||
cpu_cores: "{{ item.cpu_cores | default(omit) }}"
|
||||
cpu_sockets: "{{ item.cpu }}"
|
||||
cpu_threads: "{{ item.cpu_threads | default(omit) }}"
|
||||
cd_iso: "{{ node_iso_file[item] | default(omit) }}"
|
||||
bios_type: "{{ item.bios_type | default(omit) }}"
|
||||
ballooning_enabled: "{{ item.ballooning_enabled | default(omit) }}"
|
||||
graphical_console: "{{ item.graphical_console | default(omit) }}"
|
||||
host: "{{ item.host | default(omit) }}"
|
||||
host_devices: "{{ item.host_devices | default(omit) }}"
|
||||
placement_policy: "{{ item.placement_policy | default(omit) }}"
|
||||
storage_domain: "{{ item.storage_domain | default(omit) }}"
|
||||
type: "{{ item.type | default('server') }}"
|
||||
high_availability: true
|
||||
nics:
|
||||
- name: nic1
|
||||
profile_name: "{{ item.networks[0].profile_name | default(item.networks[0].name) }}"
|
||||
network: "{{ item.networks[0].name }}"
|
||||
custom_properties: "{{ item.custom_properties | default(omit) }}"
|
||||
operating_system: "{{ item.operating_system | default(omit) }}"
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: deploy
|
||||
loop: "{{ nodes }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
|
||||
- name: wait for instance creation to complete
|
||||
async_status:
|
||||
jid: "{{ item.ansible_job_id }}"
|
||||
register: deployed_instances
|
||||
until: deployed_instances.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
no_log: false
|
||||
with_items: "{{ deploy.results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- deploy.results is defined
|
||||
- item.ansible_job_id is defined
|
||||
|
||||
- name: create additional disks
|
||||
ovirt_disk:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{% if item.1.name_prefix | default(true) %}{{ item.0.name }}_{% endif %}{{ item.1.name }}"
|
||||
vm_name: "{{ item.0.name }}"
|
||||
size: "{{ item.1.size | default(omit) }}"
|
||||
format: "{{ item.1.format | default(omit) }}"
|
||||
interface: "{{ item.1.interface | default(omit) }}"
|
||||
bootable: "{{ item.1.bootable | default(omit) }}"
|
||||
storage_domain: "{{ item.1.storage_domain | default(omit) }}"
|
||||
activate: yes
|
||||
state: present
|
||||
wait: yes
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: create_disks
|
||||
with_subelements:
|
||||
- "{{ nodes }}"
|
||||
- disks
|
||||
- skip_missing: yes
|
||||
when:
|
||||
- nodes is defined
|
||||
- item.1 is defined
|
||||
|
||||
- name: wait for disk creation to complete
|
||||
async_status:
|
||||
jid: "{{ item.ansible_job_id }}"
|
||||
register: disks_creation
|
||||
until: disks_creation.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
with_items: "{{ create_disks.results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- create_disks.results is defined
|
||||
- item.ansible_job_id is defined
|
||||
|
||||
- include_tasks: wait_for_disk_pre29.yml
|
||||
when: ansible_version.full is version('2.9', '<')
|
||||
|
||||
- include_tasks: wait_for_disk.yml
|
||||
when: ansible_version.full is version('2.9', '>=')
|
||||
|
||||
- name: linux - start and customize
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ item.name }}"
|
||||
state: running
|
||||
cloud_init:
|
||||
nic_boot_protocol: "{{ 'static' if item.networks[0].ip is defined and item.networks[0].netmask is defined and item.networks[0].gateway is defined else 'dhcp' }}"
|
||||
nic_ip_address: "{{ item.networks[0].ip | default('') }}"
|
||||
nic_netmask: "{{ item.networks[0].netmask | default('') }}"
|
||||
nic_gateway: "{{ item.networks[0].gateway | default('') }}"
|
||||
nic_name: "{{ item.networks[0].nic_name | default(item.networks[0].device_name) | default('eth0') }}"
|
||||
host_name: "{{ item.name }}.{{ item.domain | default('') }}"
|
||||
dns_servers: "{{ item.dns_servers|join(' ') | default([]) }}"
|
||||
custom_script: "{{ item.custom_script | default('') }}"
|
||||
user_name: "{{ item.user_name | default('') }}"
|
||||
root_password: "{{ item.root_password | default('') }}"
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: deploy_linux
|
||||
loop: "{{ nodes }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- item.sysprep is not defined
|
||||
|
||||
- name: windows - start and customize
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ item.name }}"
|
||||
state: running
|
||||
sysprep:
|
||||
custom_script: "{{ lookup('template', 'templates/unattended.xml.j2') }}"
|
||||
host_name: "{{ item.name | default('') }}"
|
||||
domain: "{{ item.domain | default('') }}"
|
||||
user_name: "{{ item.user_name | default(ansible_user) }}"
|
||||
root_password: "{{ item.root_password | default(ansible_password) }}"
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: deploy_windows
|
||||
loop: "{{ nodes }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- item.sysprep is defined
|
||||
|
||||
- name: combine deployment results
|
||||
set_fact:
|
||||
deploy_results: "{{ deploy_results|default([]) + [ item ] }}"
|
||||
with_items: "{{ deploy_linux.results + deploy_windows.results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- item.ansible_job_id is defined
|
||||
|
||||
- name: wait for vms to be started
|
||||
async_status:
|
||||
jid: "{{ item.ansible_job_id }}"
|
||||
register: instances
|
||||
until: instances.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
with_items: "{{ deploy_results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- deploy_results is defined
|
||||
- item.ansible_job_id is defined
|
||||
|
||||
- name: assign tags to provisioned vms
|
||||
ovirt_tag:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ item.1 }}_{{ item.0.item.item[item.1] }}"
|
||||
vms: ["{{ item.0.item.item.name }}"]
|
||||
state: attached
|
||||
with_nested:
|
||||
- "{{ instances.results }}"
|
||||
- [ 'app_name', 'role' ]
|
||||
when:
|
||||
- nodes is defined
|
||||
- instances.results is defined
|
||||
- item.0.vm is defined
|
||||
- item.0.item.item[item.1] is defined
|
||||
|
||||
- include_tasks: wait_for_ip_pre29.yml
|
||||
when: ansible_version.full is version('2.9', '<')
|
||||
|
||||
- include_tasks: wait_for_ip.yml
|
||||
when: ansible_version.full is version('2.9', '>=')
|
||||
52
roles/oatakan.ansible-role-ovirt/tasks/template_check.yml
Normal file
52
roles/oatakan.ansible-role-ovirt/tasks/template_check.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
|
||||
- name: fail if no template and disk specified
|
||||
fail:
|
||||
msg: "at least one disk must be specified when no template is used"
|
||||
when:
|
||||
- node.template is undefined
|
||||
- node.disks[0].size is undefined | default(False)
|
||||
|
||||
- name: fail if both template and iso is specified
|
||||
fail:
|
||||
msg: "template and cd_iso are mutually exclusive, only define one of them"
|
||||
when:
|
||||
- node.template is defined
|
||||
- node.cd_iso is defined
|
||||
|
||||
- block:
|
||||
- name: check if template exists
|
||||
ovirt_template_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ node.template }} and datacenter={{ datacenter_info.ovirt_datacenters[0].name }}"
|
||||
register: template_info
|
||||
|
||||
- name: fail with message
|
||||
fail:
|
||||
msg: "template ({{ node.template }}) could not be found, make sure it exists"
|
||||
when: ( template_info.ovirt_templates | default([]) ) | length == 0
|
||||
when: node.template is defined
|
||||
|
||||
- block:
|
||||
- name: check iso file on data domain
|
||||
ovirt_disk_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ node.cd_iso }}"
|
||||
register: ovirt_disk_main_iso
|
||||
|
||||
- name: fail with message
|
||||
fail:
|
||||
msg: "iso file ({{ node.cd_iso }}) could not be found on the data domain and iso domain does not exists"
|
||||
when:
|
||||
- (ovirt_disk_main_iso.ovirt_disks[0].id | default(None)) is undefined
|
||||
- iso_domain is undefined or iso_domain|length == 0
|
||||
when: node.cd_iso is defined
|
||||
|
||||
- name: set iso file
|
||||
set_fact:
|
||||
node_iso_file: '{{ node_iso_file | default({}) | combine({node.name: ovirt_disk_main_iso.ovirt_disks[0].id | default(node.cd_iso) | default(None)}) }}'
|
||||
when: (node_iso_file[node.name] | default(None)) is undefined
|
||||
|
||||
- name: set os type
|
||||
set_fact:
|
||||
nodes_os_type: '{{ nodes_os_type | default({}) | combine({node.name: node.os_type | default(template_info.ovirt_templates[0].os.type) | default(None)}) }}'
|
||||
18
roles/oatakan.ansible-role-ovirt/tasks/wait_for_disk.yml
Normal file
18
roles/oatakan.ansible-role-ovirt/tasks/wait_for_disk.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
|
||||
- name: wait until the image is unlocked by the oVirt engine
|
||||
ovirt_disk_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={% if item.1.name_prefix | default(true) %}{{ item.0.name }}_{% endif %}{{ item.1.name }}"
|
||||
register: ovirt_disk_info
|
||||
until: (ovirt_disk_info.ovirt_disks is defined) and (ovirt_disk_info.ovirt_disks | length > 0) and (ovirt_disk_info.ovirt_disks[0].status != "locked")
|
||||
retries: 10
|
||||
delay: 3
|
||||
with_subelements:
|
||||
- "{{ nodes }}"
|
||||
- disks
|
||||
- skip_missing: yes
|
||||
when:
|
||||
- nodes is defined
|
||||
- disks_creation.results is defined
|
||||
- item.1 is defined
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
|
||||
- name: wait until the image is unlocked by the oVirt engine (<2.9)
|
||||
ovirt_disk_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={% if item.1.name_prefix | default(true) %}{{ item.0.name }}_{% endif %}{{ item.1.name }}"
|
||||
until: (ovirt_disks is defined) and (ovirt_disks | length > 0) and (ovirt_disks[0].status != "locked")
|
||||
retries: 10
|
||||
delay: 3
|
||||
with_subelements:
|
||||
- "{{ nodes }}"
|
||||
- disks
|
||||
- skip_missing: yes
|
||||
when:
|
||||
- nodes is defined
|
||||
- disks_creation.results is defined
|
||||
- item.1 is defined
|
||||
69
roles/oatakan.ansible-role-ovirt/tasks/wait_for_ip.yml
Normal file
69
roles/oatakan.ansible-role-ovirt/tasks/wait_for_ip.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
|
||||
#- name: waiting for ip address to be assigned
|
||||
# ovirt_nic_info:
|
||||
# auth: "{{ ovirt_auth }}"
|
||||
# vm: "{{ item.vm.name }}"
|
||||
# name: nic1
|
||||
# register: nics
|
||||
# until:
|
||||
# - nics.ovirt_nics | length > 0
|
||||
# - nics.ovirt_nics[0].reported_devices | length > 0
|
||||
# - nics.ovirt_nics[0].reported_devices[0].ips is defined
|
||||
# - nics.ovirt_nics[0].reported_devices[0].ips | length > 0
|
||||
# - nics.ovirt_nics[0].reported_devices[0].ips[0].address is defined
|
||||
# - nics.ovirt_nics[0].reported_devices[0].ips[0].version == 'v4'
|
||||
# retries: 300
|
||||
# delay: 10
|
||||
# with_items: "{{ instances.results }}"
|
||||
# when:
|
||||
# - nodes is defined
|
||||
# - instances.results is defined
|
||||
# - item.vm is defined
|
||||
|
||||
- name: waiting for servers to come online on predefined ip
|
||||
wait_for:
|
||||
host: "{{ item.networks[0].ip }}"
|
||||
port: "{{ item.ansible_port | default(ansible_port) | default('22') }}"
|
||||
with_items: "{{ nodes }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- item.networks is defined
|
||||
- item.networks[0].ip is defined
|
||||
|
||||
- name: waiting for servers to come online on dhcp ip
|
||||
wait_for:
|
||||
host: "{{ (item.ovirt_nics[0].reported_devices[0].ips | json_query('[?version==`v4`].address'))[0] }}"
|
||||
port: "{{ item.item.item.item.ansible_port | default(ansible_port) | default('22') }}"
|
||||
with_items: "{{ nics.results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- nics.results is defined
|
||||
- item.ovirt_nics is defined
|
||||
- item.item.item.item.networks is defined
|
||||
- item.item.item.item.networks[0].ip is not defined
|
||||
|
||||
- name: waiting for ovirt to show the predefined ip
|
||||
ovirt_nic_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
vm: "{{ item.name }}"
|
||||
name: nic1
|
||||
fetch_nested: yes
|
||||
nested_attributes:
|
||||
- ips
|
||||
register: nics
|
||||
until:
|
||||
- nics.ovirt_nics | length > 0
|
||||
- nics.ovirt_nics[0].reported_devices | length > 0
|
||||
- nics.ovirt_nics[0].reported_devices[0].ips | length > 0
|
||||
- nics.ovirt_nics[0].reported_devices[0].ips[0].address is defined
|
||||
- nics.ovirt_nics[0].reported_devices[0].ips[0].version == 'v4'
|
||||
- nics.ovirt_nics[0].reported_devices[0].ips[0].address == item.networks[0].ip
|
||||
retries: 300
|
||||
delay: 10
|
||||
with_items: "{{ nodes }}"
|
||||
when:
|
||||
- wait_for_static_ip_assigned|bool
|
||||
- nodes is defined
|
||||
- item.networks | length > 0
|
||||
- item.networks[0].ip is defined
|
||||
69
roles/oatakan.ansible-role-ovirt/tasks/wait_for_ip_pre29.yml
Normal file
69
roles/oatakan.ansible-role-ovirt/tasks/wait_for_ip_pre29.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
|
||||
#- name: waiting for ip address to be assigned (<2.9)
|
||||
# ovirt_nic_facts:
|
||||
# auth: "{{ ovirt_auth }}"
|
||||
# vm: "{{ item.vm.name }}"
|
||||
# name: nic1
|
||||
# register: nics
|
||||
# until:
|
||||
# - nics.ansible_facts.ovirt_nics | length > 0
|
||||
# - nics.ansible_facts.ovirt_nics[0].reported_devices | length > 0
|
||||
# - nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips is defined
|
||||
# - nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips | length > 0
|
||||
# - nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips[0].address is defined
|
||||
# - nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips[0].version == 'v4'
|
||||
# retries: 300
|
||||
# delay: 10
|
||||
# with_items: "{{ instances.results }}"
|
||||
# when:
|
||||
# - nodes is defined
|
||||
# - instances.results is defined
|
||||
# - item.vm is defined
|
||||
|
||||
- name: waiting for servers to come online on predefined ip
|
||||
wait_for:
|
||||
host: "{{ item.networks[0].ip }}"
|
||||
port: "{{ item.ansible_port | default(ansible_port) | default('22') }}"
|
||||
with_items: "{{ nodes }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- item.networks is defined
|
||||
- item.networks[0].ip is defined
|
||||
|
||||
- name: waiting for servers to come online on dhcp ip (<2.9)
|
||||
wait_for:
|
||||
host: "{{ (item.ansible_facts.ovirt_nics[0].reported_devices[0].ips | json_query('[?version==`v4`].address'))[0] }}"
|
||||
port: "{{ item.item.item.item.ansible_port | default(ansible_port) | default('22') }}"
|
||||
with_items: "{{ nics.results }}"
|
||||
when:
|
||||
- nodes is defined
|
||||
- nics.results is defined
|
||||
- item.ansible_facts is defined
|
||||
- item.item.item.item.networks is defined
|
||||
- item.item.item.item.networks[0].ip is not defined
|
||||
|
||||
- name: waiting for ovirt to show the predefined ip (<2.9)
|
||||
ovirt_nic_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
vm: "{{ item.name }}"
|
||||
name: nic1
|
||||
fetch_nested: yes
|
||||
nested_attributes:
|
||||
- ips
|
||||
register: nics
|
||||
until:
|
||||
- nics.ansible_facts.ovirt_nics | length > 0
|
||||
- nics.ansible_facts.ovirt_nics[0].reported_devices | length > 0
|
||||
- nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips | length > 0
|
||||
- nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips[0].address is defined
|
||||
- nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips[0].version == 'v4'
|
||||
- nics.ansible_facts.ovirt_nics[0].reported_devices[0].ips[0].address == item.networks[0].ip
|
||||
retries: 300
|
||||
delay: 10
|
||||
with_items: "{{ nodes }}"
|
||||
when:
|
||||
- wait_for_static_ip_assigned|bool
|
||||
- nodes is defined
|
||||
- item.networks | length > 0
|
||||
- item.networks[0].ip is defined
|
||||
20
roles/oatakan.ansible-role-ovirt/templates/cloud_init.yml.j2
Normal file
20
roles/oatakan.ansible-role-ovirt/templates/cloud_init.yml.j2
Normal file
@@ -0,0 +1,20 @@
|
||||
cloud_init:
|
||||
{% if item.networks[0].ip is defined and item.networks[0].netmask is defined and item.networks[0].gateway is defined %}
|
||||
nic_boot_protocol: static
|
||||
nic_ip_address: "{{ item.networks[0].ip }}"
|
||||
nic_netmask: "{{ item.networks[0].netmask }}"
|
||||
nic_gateway: "{{ item.networks[0].gateway }}"
|
||||
{% else %}
|
||||
nic_boot_protocol: dhcp
|
||||
{% endif %}
|
||||
nic_name: {{ item.networks[0].nic_name | default(item.networks[0].device_name) | default('eth0') }}
|
||||
host_name: "{{ item.name }}.{{ item.domain | default('') }}"
|
||||
{% if item.dns_servers is defined %}
|
||||
dns_servers: "{{ item.dns_servers|join(' ') }}"
|
||||
{% endif %}
|
||||
{% if item.user_name is defined %}
|
||||
user_name: "{{ item.user_name }}"
|
||||
{% endif %}
|
||||
{% if item.root_password is defined %}
|
||||
root_password: "{{ item.root_password }}"
|
||||
{% endif %}
|
||||
226
roles/oatakan.ansible-role-ovirt/templates/unattended.xml.j2
Normal file
226
roles/oatakan.ansible-role-ovirt/templates/unattended.xml.j2
Normal file
@@ -0,0 +1,226 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
<settings pass="oobeSystem">
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value>{{ ansible_password | b64encode | b64decode }}</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
<LocalAccounts>
|
||||
<LocalAccount wcm:action="add">
|
||||
<Password>
|
||||
<Value>{{ ansible_password | b64encode | b64decode }}</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
<Description>{{ item.user_name | default('vagrant') }} User</Description>
|
||||
<DisplayName>{{ item.user_name | default('vagrant') }}</DisplayName>
|
||||
<Group>Administrators</Group>
|
||||
<Name>{{ item.user_name | default('vagrant') }}</Name>
|
||||
</LocalAccount>
|
||||
</LocalAccounts>
|
||||
</UserAccounts>
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
<NetworkLocation>Home</NetworkLocation>
|
||||
<ProtectYourPC>1</ProtectYourPC>
|
||||
{% if not '2008' in (windows_distro_name | default(item.template)) %}
|
||||
<HideLocalAccountScreen>true</HideLocalAccountScreen>
|
||||
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||
{% endif %}
|
||||
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||
<SkipUserOOBE>true</SkipUserOOBE>
|
||||
</OOBE>
|
||||
<AutoLogon>
|
||||
<Password>
|
||||
<Value>{{ ansible_password | b64encode | b64decode }}</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
<Username>{{ item.user_name | default('vagrant') }}</Username>
|
||||
<Enabled>true</Enabled>
|
||||
</AutoLogon>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine>
|
||||
<Description>Set Execution Policy 64 Bit</Description>
|
||||
<Order>1</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% if not '2008' in (windows_distro_name | default(item.template)) %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-NetConnectionProfile -NetworkCategory Private"</CommandLine>
|
||||
<Description>Set network connection profile to private</Description>
|
||||
<Order>2</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm quickconfig -q</CommandLine>
|
||||
<Description>winrm quickconfig -q</Description>
|
||||
<Order>4</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm quickconfig -transport:http</CommandLine>
|
||||
<Description>winrm quickconfig -transport:http</Description>
|
||||
<Order>5</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm set winrm/config @{MaxTimeoutms="1800000"}</CommandLine>
|
||||
<Description>Win RM MaxTimoutms</Description>
|
||||
<Order>6</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB="800"}</CommandLine>
|
||||
<Description>Win RM MaxMemoryPerShellMB</Description>
|
||||
<Order>7</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm set winrm/config/service @{AllowUnencrypted="true"}</CommandLine>
|
||||
<Description>Win RM AllowUnencrypted</Description>
|
||||
<Order>8</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm set winrm/config/service/auth @{Basic="true"}</CommandLine>
|
||||
<Description>Win RM auth Basic</Description>
|
||||
<Order>9</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm set winrm/config/client/auth @{Basic="true"}</CommandLine>
|
||||
<Description>Win RM client auth Basic</Description>
|
||||
<Order>10</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c winrm set winrm/config/listener?Address=*+Transport=HTTP @{Port="5985"} </CommandLine>
|
||||
<Description>Win RM listener Address/Port</Description>
|
||||
<Order>11</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c netsh firewall add portopening TCP 5985 "Port 5985"</CommandLine>
|
||||
<Description>Win RM port open</Description>
|
||||
<Order>12</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c net stop winrm</CommandLine>
|
||||
<Description>Stop Win RM Service </Description>
|
||||
<Order>13</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c sc config winrm start= auto</CommandLine>
|
||||
<Description>Win RM Autostart</Description>
|
||||
<Order>14</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c net start winrm</CommandLine>
|
||||
<Description>Start Win RM Service</Description>
|
||||
<Order>15</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% else %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c reg add "HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff" /f</CommandLine>
|
||||
<Description>Network prompt</Description>
|
||||
<Order>2</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "{{ set_network_to_private }}"</CommandLine>
|
||||
<Description>Set network connection profile to private</Description>
|
||||
<Order>3</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% endif %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "& $([scriptblock]::Create((New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1'))) -ForceNewSSLCert -EnableCredSSP"</CommandLine>
|
||||
<Description>Enable winrm</Description>
|
||||
<Order>20</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Enable-WSManCredSSP -Role Server -Force"</CommandLine>
|
||||
<Description>Enable winrm server role</Description>
|
||||
<Order>21</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-Item -Path 'WSMan:\localhost\Service\Auth\CredSSP' -Value $true"</CommandLine>
|
||||
<Description>Enable credssp authentication</Description>
|
||||
<Order>22</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Resize-Partition -DriveLetter C -Size (Get-PartitionSupportedSize -DriveLetter C).Sizemax -ErrorAction SilentlyContinue"</CommandLine>
|
||||
<Description>Extend OS disk</Description>
|
||||
<Order>23</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% if item.networks is defined and item.networks[0].ip is defined and item.networks[0].gateway is defined and item.networks[0].netmask is defined %}
|
||||
{% if not '2008' in (windows_distro_name | default(item.template)) %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "New-NetIPAddress –IPAddress {{ item.networks[0].ip }} -DefaultGateway {{ item.networks[0].gateway }} -PrefixLength {{ (item.networks[0].ip + '/' + item.networks[0].netmask) | ipaddr('prefix') }} -InterfaceIndex (Get-NetAdapter | Where-Object { ($_.Name -like '*Ethernet*') -and ($_.Status -like 'Up') })[0].InterfaceIndex"</CommandLine>
|
||||
<Description>Set static ip</Description>
|
||||
<Order>50</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% else %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c netsh int ipv4 set address "Local Area connection" static {{ item.networks[0].ip }} {{ item.networks[0].netmask }} {{ item.networks[0].gateway }}</CommandLine>
|
||||
<Description>Set static ip</Description>
|
||||
<Order>50</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% endif %}
|
||||
{% if item.networks[0].dns_servers is defined %}
|
||||
{% if not '2008' in (windows_distro_name | default(item.template)) %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-DNSClientServerAddress –InterfaceIndex (Get-NetAdapter | Where-Object { ($_.Name -like '*Ethernet*') -and ($_.Status -like 'Up') })[0].InterfaceIndex –ServerAddresses {{ item.networks[0].dns_servers|join(',') }}"</CommandLine>
|
||||
<Description>Set static ip</Description>
|
||||
<Order>51</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% else %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c netsh int ipv4 set dns "Local Area connection" static {{ item.networks[0].dns_servers[0] }}</CommandLine>
|
||||
<Description>Set static ip</Description>
|
||||
<Order>51</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</FirstLogonCommands>
|
||||
<ShowWindowsLive>false</ShowWindowsLive>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<OEMInformation>
|
||||
<HelpCustomized>false</HelpCustomized>
|
||||
</OEMInformation>
|
||||
<!-- Rename computer here. -->
|
||||
<ComputerName>{{ item.name }}</ComputerName>
|
||||
<TimeZone>Central Standard Time</TimeZone>
|
||||
<RegisteredOwner/>
|
||||
</component>
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<SkipAutoActivation>true</SkipAutoActivation>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Deployment" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ExtendOSPartition>
|
||||
<Extend>true</Extend>
|
||||
</ExtendOSPartition>
|
||||
</component>
|
||||
</settings>
|
||||
<cpi:offlineImage xmlns:cpi="urn:schemas-microsoft-com:cpi" cpi:source="catalog:d:/sources/install_windows 7 ENTERPRISE.clg"/>
|
||||
</unattend>
|
||||
1
roles/oatakan.ansible-role-ovirt/tests/inventory
Normal file
1
roles/oatakan.ansible-role-ovirt/tests/inventory
Normal file
@@ -0,0 +1 @@
|
||||
localhost
|
||||
5
roles/oatakan.ansible-role-ovirt/tests/test.yml
Normal file
5
roles/oatakan.ansible-role-ovirt/tests/test.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- hosts: localhost
|
||||
remote_user: root
|
||||
roles:
|
||||
- ansible-role-ovirt
|
||||
3
roles/oatakan.ansible-role-ovirt/vars/main.yml
Normal file
3
roles/oatakan.ansible-role-ovirt/vars/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
|
||||
set_network_to_private: "([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}'))).GetNetworkConnections() | % {$_.GetNetwork().SetCategory(1)}"
|
||||
Reference in New Issue
Block a user