WIP3
This commit is contained in:
29
roles/oatakan.windows_ovirt_template/.travis.yml
Normal file
29
roles/oatakan.windows_ovirt_template/.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/
|
||||
21
roles/oatakan.windows_ovirt_template/LICENSE
Normal file
21
roles/oatakan.windows_ovirt_template/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Orcun Atakan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
95
roles/oatakan.windows_ovirt_template/README.md
Normal file
95
roles/oatakan.windows_ovirt_template/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# windows_ovirt_template
|
||||
This repo contains an Ansible role that builds a Windows VM template from an ISO file on Ovirt/RHV.
|
||||
You can run this role as a part of CI/CD pipeline for building Windows templates on Ovirt/RHV from an ISO file.
|
||||
|
||||
> **_Note:_** This role is provided as an example only. Do not use this in production. You can fork/clone and add/remove steps for your environment based on your organization's security and operational requirements.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
You need to have the following packages installed on your ansible control machine:
|
||||
|
||||
- mkisofs
|
||||
|
||||
You need to enable qemu_cmdline hook on your RHV/Ovirt environment, this is required to enable attaching multiple iso files. Follow the instructions documented here:
|
||||
|
||||
https://www.ovirt.org/develop/developer-guide/vdsm/hook/qemucmdline.html
|
||||
|
||||
Before you can use this role, you need to make sure you have Windows install media iso file uploaded to a iso domain on your RHV/Ovirt environment.
|
||||
|
||||
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 roles that this role utilizes, make sure to call this out in requirements.yml file under roles directory or download manually:
|
||||
|
||||
- oatakan.windows_template_build
|
||||
|
||||
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:
|
||||
|
||||
- name: create a ovirt windows template
|
||||
hosts: all
|
||||
gather_facts: False
|
||||
connection: local
|
||||
become: no
|
||||
vars:
|
||||
template_force: yes #overwrite existing template with the same name
|
||||
export_ovf: no # export the template to export domain upon creation
|
||||
local_account_password: ''
|
||||
local_administrator_password: ''
|
||||
windows_distro_name: 2019_standard # this needs to be one of the standard values see 'os_short_names' var
|
||||
template_vm_name: win2019_template
|
||||
template_vm_root_disk_size: 30
|
||||
template_vm_guest_id: windows_2019x64
|
||||
template_vm_memory: 4096
|
||||
template_vm_efi: false # you need to install efi file to use this, false should be fine in most cases
|
||||
iso_file_name: '' # name of the iso file
|
||||
iso_image_index: '' # put index number here from the order inside the iso, for example 1 - standard, 2 - core etc
|
||||
iso_product_key: ''
|
||||
vm_ansible_port: 5986
|
||||
vm_ansible_winrm_transport: credssp
|
||||
vm_upgrade_powershell: false # only needed for 2008 R2
|
||||
install_updates: false # it will take longer to build with the updates, set to true if you want the updates
|
||||
|
||||
ovirt_datacenter: '' # name of the datacenter
|
||||
ovirt_cluster: '' # name of the cluster
|
||||
ovirt_data_domain: '' # name of the data domain
|
||||
ovirt_export_domain: '' # name of the iso domain
|
||||
ovirt_iso_domain: '' # this is deprecated as of 4.3 you can omit if not used
|
||||
|
||||
template_vm_network_name: ovirtmgmt
|
||||
template_vm_ip_address: 192.168.10.95 # static ip is required
|
||||
template_vm_netmask: 255.255.255.0
|
||||
template_vm_gateway: 192.168.10.254
|
||||
template_vm_domain: example.com
|
||||
template_vm_dns_servers:
|
||||
- 8.8.4.4
|
||||
- 8.8.8.8
|
||||
|
||||
roles:
|
||||
- oatakan.windows_ovirt_template
|
||||
|
||||
For disconnected environments, you can overwrite this variable to point to a local copy of a script to enable winrm:
|
||||
|
||||
**winrm_enable_script_url:** https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1
|
||||
|
||||
you can also localize virtio-win and update the virtio_iso_url variable to point to your local url:
|
||||
|
||||
**virtio_iso_url:** https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.173-2/virtio-win.iso
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
|
||||
Author Information
|
||||
------------------
|
||||
|
||||
Orcun Atakan
|
||||
68
roles/oatakan.windows_ovirt_template/defaults/main.yml
Normal file
68
roles/oatakan.windows_ovirt_template/defaults/main.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
|
||||
instance_wait_retry_limit: 300
|
||||
instance_wait_connection_timeout: 400
|
||||
|
||||
# this will remove existing template with the same name
|
||||
template_force: no
|
||||
template_found: no
|
||||
|
||||
export_ovf: no
|
||||
|
||||
enable_auto_logon: yes
|
||||
|
||||
remove_vm_on_error: yes
|
||||
vm_failed: no
|
||||
|
||||
virtio_iso_url: https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.173-2/virtio-win.iso
|
||||
winrm_enable_script_url: https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1
|
||||
|
||||
windows_build_role: oatakan.windows_template_build
|
||||
|
||||
local_administrator_password: Chang3MyP@ssw0rd21
|
||||
local_account_username: ansible
|
||||
local_account_password: Chang3MyP@ssw0rd21
|
||||
|
||||
windows_distro_name: 2019_standard_core
|
||||
iso_file_name: 17763.253.190108-0006.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso
|
||||
windows_sysprep_template_folder: windows_server
|
||||
|
||||
vm_ansible_port: 5986
|
||||
vm_ansible_winrm_transport: credssp
|
||||
vm_upgrade_powershell: no
|
||||
|
||||
template_vm_name: windows-2019-standard-core-auto
|
||||
template_vm_root_disk_size: 30
|
||||
template_vm_root_disk_format: cow
|
||||
template_vm_root_disk_interface: virtio
|
||||
template_vm_memory: 4096
|
||||
template_vm_cpu: 2
|
||||
template_vm_guest_id: windows_2019x64
|
||||
template_vm_efi: no
|
||||
template_vm_network_name: ovirtmgmt
|
||||
template_vm_ip_address: 192.168.10.95
|
||||
template_vm_netmask: 255.255.255.0
|
||||
template_vm_gateway: 192.168.10.254
|
||||
template_vm_domain: home.ad
|
||||
template_vm_dns_servers:
|
||||
- 192.168.1.254
|
||||
- 8.8.8.8
|
||||
|
||||
template_convert_timeout: 900
|
||||
template_convert_seal: no
|
||||
template_timezone: 'GMT Standard Time'
|
||||
|
||||
ovirt_datacenter: mydatacenter
|
||||
ovirt_cluster: production
|
||||
ovirt_data_domain: data_domain
|
||||
ovirt_export_domain: export_domain
|
||||
ovirt_iso_domain: iso_domain
|
||||
|
||||
os_short_names:
|
||||
2008_r2_standard: 2k8R2
|
||||
2012_r2_standard: 2k12R2
|
||||
2012_r2_datacenter: 2k12R2
|
||||
2016_standard: 2k16
|
||||
2016_standard_core: 2k16
|
||||
2019_standard: 2k19
|
||||
2019_standard_core: 2k19
|
||||
@@ -0,0 +1,2 @@
|
||||
install_date: Wed Jun 24 18:44:33 2020
|
||||
version: master
|
||||
28
roles/oatakan.windows_ovirt_template/meta/main.yml
Normal file
28
roles/oatakan.windows_ovirt_template/meta/main.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Orcun Atakan
|
||||
description: Ansible galaxy role for building a Windows VM templates from an ISO file on Ovirt/RHV.
|
||||
role_name: windows_ovirt_template
|
||||
company: Red Hat
|
||||
|
||||
license: MIT
|
||||
|
||||
min_ansible_version: 2.5
|
||||
|
||||
platforms:
|
||||
- name: Windows
|
||||
versions:
|
||||
- all
|
||||
|
||||
cloud_platforms:
|
||||
- oVirt
|
||||
|
||||
galaxy_tags:
|
||||
- windows
|
||||
- ovirt
|
||||
- rhv
|
||||
- cloud
|
||||
- multicloud
|
||||
- template
|
||||
|
||||
dependencies: []
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: convert to template
|
||||
ovirt_template:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ template.name }}"
|
||||
vm: "{{ template.name }}"
|
||||
cluster: "{{ providers.ovirt.cluster }}"
|
||||
timeout: "{{ template_convert_timeout }}"
|
||||
seal: "{{ template_convert_seal }}"
|
||||
when: template is defined
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
|
||||
- block:
|
||||
- name: remove iso file from data_domain
|
||||
ovirt_disk:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ iso_file }}"
|
||||
storage_domain: "{{ providers.ovirt.data_domain | default('data_domain') }}"
|
||||
state: absent
|
||||
rescue:
|
||||
- include_tasks: wait_iso_disk_unlock_pre29.yml
|
||||
when: ansible_version.full is version('2.9', '<')
|
||||
|
||||
- include_tasks: wait_iso_disk_unlock.yml
|
||||
when: ansible_version.full is version('2.9', '>=')
|
||||
|
||||
- name: remove iso file from data_domain
|
||||
ovirt_disk:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ iso_file }}"
|
||||
storage_domain: "{{ providers.ovirt.data_domain | default('data_domain') }}"
|
||||
state: absent
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
|
||||
- name: upload iso file to data_domain
|
||||
ovirt_disk:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ iso_file }}"
|
||||
upload_image_path: "{{ playbook_dir }}/{{ temp_directory }}/windows_{{ windows_distro_name }}_autounattend_autogen.iso"
|
||||
storage_domain: "{{ providers.ovirt.data_domain | default('data_domain') }}"
|
||||
size: 20MiB
|
||||
wait: true
|
||||
bootable: true
|
||||
format: raw
|
||||
content_type: iso
|
||||
force: yes
|
||||
register: disk_iso_file
|
||||
|
||||
- name: set iso file disk id
|
||||
set_fact:
|
||||
ks_iso_file_disk_id: "{{ disk_iso_file.disk.id }}"
|
||||
ks_iso_file_image_id: "{{ disk_iso_file.disk.image_id }}"
|
||||
ovirt_datacenter_id: "{{ disk_iso_file.disk.quota.href | regex_replace('^/ovirt-engine/api/datacenters/(.*)/quotas.*$', '\\1') }}"
|
||||
ovirt_datastore_id: "{{ disk_iso_file.disk.storage_domains[0].id }}"
|
||||
20
roles/oatakan.windows_ovirt_template/tasks/export_ovf.yml
Normal file
20
roles/oatakan.windows_ovirt_template/tasks/export_ovf.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
|
||||
- name: export template to export domain
|
||||
ovirt_template:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
state: exported
|
||||
name: "{{ template.name }}"
|
||||
export_domain: "{{ providers.ovirt.export_domain }}"
|
||||
cluster: "{{ providers.ovirt.cluster }}"
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: export_ovf_file
|
||||
|
||||
- name: wait for export to complete
|
||||
async_status:
|
||||
jid: "{{ export_ovf_file.ansible_job_id }}"
|
||||
register: ovf
|
||||
until: ovf.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
119
roles/oatakan.windows_ovirt_template/tasks/main.yml
Normal file
119
roles/oatakan.windows_ovirt_template/tasks/main.yml
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
|
||||
- name: obtain SSO token with using username/password credentials
|
||||
ovirt_auth:
|
||||
url: "{{ lookup('env', 'OVIRT_URL')|default(ovirt.url) }}"
|
||||
username: "{{ lookup('env', 'OVIRT_USERNAME')|default(ovirt.username) }}"
|
||||
password: "{{ lookup('env', 'OVIRT_PASSWORD')|default(ovirt.password) }}"
|
||||
insecure: yes
|
||||
|
||||
- include_tasks: preflight_check_pre29.yml
|
||||
when: ansible_version.full is version('2.9', '<')
|
||||
|
||||
- include_tasks: preflight_check.yml
|
||||
when: ansible_version.full is version('2.9', '>=')
|
||||
|
||||
# remove existing template
|
||||
- block:
|
||||
|
||||
- include_tasks: remove_template.yml
|
||||
|
||||
when:
|
||||
- template_force|bool
|
||||
- template_found|bool
|
||||
|
||||
- block:
|
||||
- include_tasks: make_iso.yml
|
||||
|
||||
- include_tasks: provision_vm.yml
|
||||
|
||||
- name: refresh inventory
|
||||
meta: refresh_inventory
|
||||
|
||||
- name: clear gathered facts
|
||||
meta: clear_facts
|
||||
|
||||
- name: clear any host errors
|
||||
meta: clear_host_errors
|
||||
|
||||
- name: add host
|
||||
add_host:
|
||||
hostname: template_host
|
||||
ansible_host: "{{ template_vm_ip_address }}"
|
||||
ansible_user: "{{ unattend.local_accounts[0].name }}"
|
||||
ansible_password: "{{ unattend.local_accounts[0].password }}"
|
||||
ansible_port: "{{ vm_ansible_port | default('5986') }}"
|
||||
ansible_connection: winrm
|
||||
ansible_winrm_transport: "{{ vm_ansible_winrm_transport | default('credssp') }}"
|
||||
ansible_winrm_server_cert_validation: ignore
|
||||
ansible_winrm_operation_timeout_sec: 250
|
||||
ansible_winrm_read_timeout_sec: 280
|
||||
ansible_win_async_startup_timeout: 60
|
||||
|
||||
- include_role:
|
||||
name: "{{ windows_build_role }}"
|
||||
apply:
|
||||
vars:
|
||||
target_ovirt: yes
|
||||
install_updates: yes
|
||||
remove_apps: yes
|
||||
clean_up_components: yes
|
||||
upgrade_powershell: "{{ vm_upgrade_powershell | default('no') }}"
|
||||
delegate_to: template_host
|
||||
|
||||
- name: refresh SSO credentials
|
||||
ovirt_auth:
|
||||
url: "{{ lookup('env', 'OVIRT_URL')|default(ovirt.url) }}"
|
||||
username: "{{ lookup('env', 'OVIRT_USERNAME')|default(ovirt.username) }}"
|
||||
password: "{{ lookup('env', 'OVIRT_PASSWORD')|default(ovirt.password) }}"
|
||||
insecure: yes
|
||||
|
||||
- include_tasks: stop_vm.yml
|
||||
|
||||
- include_tasks: convert_to_template.yml
|
||||
|
||||
- include_tasks: export_ovf.yml
|
||||
when: export_ovf|bool
|
||||
|
||||
rescue:
|
||||
- name: refresh SSO credentials
|
||||
ovirt_auth:
|
||||
url: "{{ lookup('env', 'OVIRT_URL')|default(ovirt.url) }}"
|
||||
username: "{{ lookup('env', 'OVIRT_USERNAME')|default(ovirt.username) }}"
|
||||
password: "{{ lookup('env', 'OVIRT_PASSWORD')|default(ovirt.password) }}"
|
||||
insecure: yes
|
||||
|
||||
- include_tasks: remove_template.yml
|
||||
when: remove_vm_on_error|bool
|
||||
|
||||
- name: set vm_failed variable
|
||||
set_fact:
|
||||
vm_failed: yes
|
||||
|
||||
always:
|
||||
- name: refresh SSO credentials
|
||||
ovirt_auth:
|
||||
url: "{{ lookup('env', 'OVIRT_URL')|default(ovirt.url) }}"
|
||||
username: "{{ lookup('env', 'OVIRT_USERNAME')|default(ovirt.username) }}"
|
||||
password: "{{ lookup('env', 'OVIRT_PASSWORD')|default(ovirt.password) }}"
|
||||
insecure: yes
|
||||
|
||||
- include_tasks: remove_vm.yml
|
||||
when: remove_vm_on_error|bool or (not remove_vm_on_error|bool and not vm_failed|bool)
|
||||
|
||||
- include_tasks: datastore_iso_remove.yml
|
||||
|
||||
- name: remove temporary directory
|
||||
file:
|
||||
path: "{{ temp_directory }}"
|
||||
state: absent
|
||||
|
||||
- name: logout from oVirt
|
||||
ovirt_auth:
|
||||
state: absent
|
||||
ovirt_auth: "{{ ovirt_auth }}"
|
||||
|
||||
- name: fail if needed
|
||||
fail:
|
||||
msg: "fail to create a template."
|
||||
when: vm_failed|bool
|
||||
30
roles/oatakan.windows_ovirt_template/tasks/make_iso.yml
Normal file
30
roles/oatakan.windows_ovirt_template/tasks/make_iso.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
- block:
|
||||
- name: create temporary directory
|
||||
file:
|
||||
path: "{{ temp_directory }}/ks_iso"
|
||||
state: directory
|
||||
|
||||
- name: create Autounattend.xml file
|
||||
template:
|
||||
src: "{{ windows_sysprep_template_folder }}/Autounattend.xml.j2"
|
||||
dest: "{{ temp_directory }}/ks_iso/Autounattend.xml"
|
||||
|
||||
- name: include virtio drivers
|
||||
include_tasks: virtio_drivers.yml
|
||||
|
||||
- name: create iso
|
||||
command: mkisofs -V ADDISO -r -iso-level 4 -o {{ playbook_dir }}/{{ temp_directory }}/windows_{{ windows_distro_name }}_autounattend_autogen.iso .
|
||||
args:
|
||||
chdir: "{{ playbook_dir }}/{{ temp_directory }}/ks_iso"
|
||||
|
||||
- include_tasks: datastore_upload.yml
|
||||
always:
|
||||
- name: remove temporary files
|
||||
file:
|
||||
path: "{{ temp_directory }}/{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- windows_{{ windows_distro_name }}_autounattend_autogen.iso
|
||||
- virtio_win.iso
|
||||
- ks_iso/
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
|
||||
- name: get the datacenter name
|
||||
ovirt_datacenter_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "Clusters.name = {{ providers.ovirt.cluster }}"
|
||||
register: datacenter_info
|
||||
|
||||
- name: get storage information
|
||||
ovirt_storage_domain_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "datacenter={{ datacenter_info.ovirt_datacenters[0].name }}"
|
||||
register: storage_info
|
||||
when:
|
||||
- template_disk_storage is undefined
|
||||
|
||||
- name: get data domain
|
||||
set_fact:
|
||||
disk_storage_domain: "{{ storage_info.ovirt_storage_domains|json_query(the_query)|list|first|default(None) }}"
|
||||
when:
|
||||
- template_disk_storage is undefined
|
||||
vars:
|
||||
the_query: "[?type=='data']"
|
||||
|
||||
- name: get 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']"
|
||||
|
||||
- name: check if template already exists
|
||||
ovirt_template_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ template.name }} and datacenter={{ datacenter_info.ovirt_datacenters[0].name }}"
|
||||
register: template_info
|
||||
|
||||
- block:
|
||||
- name: set template_found to yes
|
||||
set_fact:
|
||||
template_found: yes
|
||||
|
||||
- name: fail with message
|
||||
fail:
|
||||
msg: "Existing template found on ovirt/rhv: {{ template.name }}"
|
||||
when: not template_force|bool
|
||||
when:
|
||||
- template_info.ovirt_templates is defined
|
||||
- template_info.ovirt_templates | length > 0
|
||||
|
||||
- name: check iso file on data domain
|
||||
ovirt_disk_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ iso_file_name }}"
|
||||
register: ovirt_disk_main_iso
|
||||
when: iso_file_name is defined
|
||||
|
||||
- debug:
|
||||
msg: "{{ ovirt_disk_main_iso }}"
|
||||
|
||||
- name: set file id of the iso file
|
||||
set_fact:
|
||||
iso_file_id: "{{ ovirt_disk_main_iso.ovirt_disks[0].id }}"
|
||||
when:
|
||||
- ovirt_disk_main_iso.ovirt_disks | length > 0
|
||||
- ovirt_disk_main_iso.ovirt_disks[0].id is defined
|
||||
- ovirt_disk_main_iso.ovirt_disks[0].content_type == 'iso'
|
||||
|
||||
- name: fail with message
|
||||
fail:
|
||||
msg: "iso file ({{ iso_file_name }}) could not be found on the data domain and iso domain does not exists"
|
||||
when:
|
||||
- iso_file_id is undefined
|
||||
- iso_domain is undefined or iso_domain|length == 0
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
|
||||
- name: get the datacenter name (<2.9)
|
||||
ovirt_datacenter_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "Clusters.name = {{ providers.ovirt.cluster }}"
|
||||
|
||||
- name: get storage information (<2.9)
|
||||
ovirt_storage_domain_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "datacenter={{ ovirt_datacenters[0].name }}"
|
||||
when:
|
||||
- template_disk_storage is undefined
|
||||
|
||||
- name: get data domain (<2.9)
|
||||
set_fact:
|
||||
disk_storage_domain: "{{ ovirt_storage_domains|json_query(the_query)|list|first }}"
|
||||
when:
|
||||
- template_disk_storage is undefined
|
||||
vars:
|
||||
the_query: "[?type=='data']"
|
||||
|
||||
- name: get iso domain (deprecated as of oVirt/RHV 4.3) (<2.9)
|
||||
set_fact:
|
||||
iso_domain: "{{ ovirt_storage_domains|json_query(the_query)|list|first }}"
|
||||
vars:
|
||||
the_query: "[?type=='iso']"
|
||||
|
||||
- name: check if template already exists (<2.9)
|
||||
ovirt_template_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ template.name }} and datacenter={{ ovirt_datacenters[0].name }}"
|
||||
|
||||
- block:
|
||||
- name: set template_found to yes
|
||||
set_fact:
|
||||
template_found: yes
|
||||
|
||||
- name: fail with message
|
||||
fail:
|
||||
msg: "Existing template found on ovirt/rhv: {{ template.name }}"
|
||||
when: not template_force|bool
|
||||
when:
|
||||
- ovirt_templates is defined
|
||||
- ovirt_templates | length > 0
|
||||
|
||||
- name: check iso file on data domain
|
||||
ovirt_disk_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ iso_file_name }}"
|
||||
when: iso_file_name is defined
|
||||
|
||||
- debug:
|
||||
msg: "{{ ovirt_disks }}"
|
||||
|
||||
- name: set file id of the iso file
|
||||
set_fact:
|
||||
iso_file_id: "{{ ovirt_disks[0].id }}"
|
||||
when:
|
||||
- ovirt_disks | length > 0
|
||||
- ovirt_disks[0].id is defined
|
||||
- ovirt_disks[0].content_type == 'iso'
|
||||
|
||||
- name: fail with message
|
||||
fail:
|
||||
msg: "iso file ({{ iso_file_name }}) could not be found on the data domain and iso domain does not exists"
|
||||
when:
|
||||
- iso_file_id is undefined
|
||||
- iso_domain is undefined or iso_domain|length == 0
|
||||
123
roles/oatakan.windows_ovirt_template/tasks/provision_vm.yml
Normal file
123
roles/oatakan.windows_ovirt_template/tasks/provision_vm.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
|
||||
- name: provision a new vm
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ template.name }}"
|
||||
cluster: "{{ providers.ovirt.cluster|default('Default') }}"
|
||||
state: present
|
||||
wait: yes
|
||||
memory: "{{ template.memory }}MiB"
|
||||
cpu_sockets: "{{ template.cpu }}"
|
||||
boot_devices:
|
||||
- hd
|
||||
- cdrom
|
||||
cd_iso: "{{ template.cd_iso }}"
|
||||
type: server
|
||||
high_availability: true
|
||||
nics:
|
||||
- name: nic1
|
||||
profile_name: "{{ template.networks[0].name }}"
|
||||
network: "{{ template.networks[0].name }}"
|
||||
custom_properties: "{{ custom_properties | default(omit) }}"
|
||||
operating_system: "{{ template_vm_guest_id | default(omit) }}"
|
||||
timezone: "{{ template_timezone | default(omit) }}"
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: deploy
|
||||
|
||||
- name: wait for instance creation to complete
|
||||
async_status: jid="{{ deploy.ansible_job_id }}"
|
||||
register: instance
|
||||
until: instance.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
|
||||
- name: create a disk
|
||||
ovirt_disk:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{% if item.name_prefix | default(false) %}{{ template.name }}_{% endif %}{{ item.name }}"
|
||||
vm_name: "{{ template.name }}"
|
||||
size: "{{ item.size | default(omit) }}"
|
||||
format: "{{ item.format | default(omit) }}"
|
||||
interface: "{{ item.interface | default(omit) }}"
|
||||
bootable: "{{ item.bootable | default(omit) }}"
|
||||
storage_domain: "{{ item.storage_domain | default(omit) }}"
|
||||
activate: yes
|
||||
state: present
|
||||
wait: yes
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: create_disks
|
||||
loop: "{{ template.disks }}"
|
||||
when:
|
||||
- template is defined
|
||||
- template.disks 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
|
||||
loop: "{{ create_disks.results }}"
|
||||
when:
|
||||
- template is defined
|
||||
- create_disks.results is defined
|
||||
- item.ansible_job_id is defined
|
||||
|
||||
- include_tasks: wait_disk_unlock_pre29.yml
|
||||
when:
|
||||
- ansible_version.full is version('2.9', '<')
|
||||
- template is defined
|
||||
- template.disks is defined
|
||||
- disks_creation.results is defined
|
||||
|
||||
- include_tasks: wait_disk_unlock.yml
|
||||
when:
|
||||
- ansible_version.full is version('2.9', '>=')
|
||||
- template is defined
|
||||
- template.disks is defined
|
||||
- disks_creation.results is defined
|
||||
|
||||
- name: assign tags to provisioned vms
|
||||
ovirt_tag:
|
||||
name: "{{ item }}_{{ instance.item.item[item] }}"
|
||||
vms: ["{{ instance.item.item.name }}"]
|
||||
state: attached
|
||||
loop:
|
||||
- app_name
|
||||
- role
|
||||
when:
|
||||
- template is defined
|
||||
- instance is defined
|
||||
- instance.vm is defined
|
||||
- instance.item.item[item] is defined
|
||||
|
||||
- name: start vm
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
name: "{{ template.name }}"
|
||||
cluster: "{{ providers.ovirt.cluster|default('Default') }}"
|
||||
state: running
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: start
|
||||
|
||||
- name: wait for instance creation to complete
|
||||
async_status: jid="{{ start.ansible_job_id }}"
|
||||
register: instance
|
||||
until: instance.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
|
||||
- name: waiting for server to come online
|
||||
wait_for:
|
||||
host: "{{ template.networks[0].ip }}"
|
||||
port: "{{ template.ansible_port | default(vm_ansible_port) | default(ansible_port) | default('5986') }}"
|
||||
timeout: "{{ instance_wait_connection_timeout }}"
|
||||
when:
|
||||
- instance is changed
|
||||
- template is defined
|
||||
ignore_errors: yes
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
|
||||
- name: remove template
|
||||
ovirt_template:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
cluster: "{{ providers.ovirt.cluster }}"
|
||||
name: "{{ template.name }}"
|
||||
state: absent
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: undeploy
|
||||
when: template is defined
|
||||
|
||||
- name: wait for template deletion to complete
|
||||
async_status:
|
||||
jid: "{{ undeploy.ansible_job_id }}"
|
||||
register: instance
|
||||
until: instance.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
20
roles/oatakan.windows_ovirt_template/tasks/remove_vm.yml
Normal file
20
roles/oatakan.windows_ovirt_template/tasks/remove_vm.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
|
||||
- name: remove vm
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
cluster: "{{ providers.ovirt.cluster }}"
|
||||
name: "{{ template.name }}"
|
||||
state: absent
|
||||
async: 7200
|
||||
poll: 0
|
||||
register: undeploy
|
||||
when: template is defined
|
||||
|
||||
- name: wait for template deletion to complete
|
||||
async_status:
|
||||
jid: "{{ undeploy.ansible_job_id }}"
|
||||
register: instance
|
||||
until: instance.finished
|
||||
retries: "{{ instance_wait_retry_limit }}"
|
||||
delay: 10
|
||||
35
roles/oatakan.windows_ovirt_template/tasks/stop_vm.yml
Normal file
35
roles/oatakan.windows_ovirt_template/tasks/stop_vm.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
|
||||
- block:
|
||||
|
||||
- name: wait for server to stop responding
|
||||
wait_for:
|
||||
host: "{{ template_vm_ip_address }}"
|
||||
port: "{{ vm_ansible_port | default('5986') }}"
|
||||
timeout: 120
|
||||
state: stopped
|
||||
ignore_errors: yes
|
||||
|
||||
- include_tasks: wait_vm_poweredoff_pre29.yml
|
||||
when: ansible_version.full is version('2.9', '<')
|
||||
|
||||
- include_tasks: wait_vm_poweredoff.yml
|
||||
when: ansible_version.full is version('2.9', '>=')
|
||||
|
||||
rescue:
|
||||
- name: ignoring any error
|
||||
debug:
|
||||
msg: "ignoring error..."
|
||||
|
||||
- name: reconfigure vm
|
||||
ovirt_vm:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
cluster: "{{ providers.ovirt.cluster }}"
|
||||
name: "{{ template.name }}"
|
||||
boot_devices:
|
||||
- hd
|
||||
cd_iso: ""
|
||||
custom_properties: "{{ custom_properties_efi if template_vm_efi|bool else '' }}"
|
||||
force: yes
|
||||
state: present
|
||||
when: template is defined
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
|
||||
- name: download virtio win iso file
|
||||
get_url:
|
||||
url: "{{ virtio_iso_url }}"
|
||||
dest: "{{ temp_directory }}/virtio_win.iso"
|
||||
register: download_virtio_iso
|
||||
until: download_virtio_iso is success
|
||||
delay: 3
|
||||
retries: 5
|
||||
|
||||
- name: set list of directories to copy
|
||||
set_fact:
|
||||
virtio_iso_list_of_directories_to_extract:
|
||||
- /viostor/{{ os_short_names[windows_distro_name] | default('2k16') }}/amd64
|
||||
- /NetKVM/{{ os_short_names[windows_distro_name] | default('2k16') }}/amd64
|
||||
|
||||
- name: get a list of files from template iso
|
||||
shell: >
|
||||
set -o pipefail &&
|
||||
isoinfo -f -R -i {{ playbook_dir }}/{{ temp_directory }}/virtio_win.iso |
|
||||
grep -E "^{{ virtio_iso_list_of_directories_to_extract | join('|^') }}"
|
||||
changed_when: False
|
||||
register: virtio_iso_list_of_files
|
||||
|
||||
- name: copy files from virtio iso to target
|
||||
shell: |
|
||||
set -o pipefail &&
|
||||
isoinfo -f -R -i {{ playbook_dir }}/{{ temp_directory }}/virtio_win.iso |\
|
||||
grep -E "^{{ virtio_iso_list_of_directories_to_extract | join('|^') }}" | while read line; do
|
||||
d=$(dirname $line)
|
||||
od=".${d}"
|
||||
[ -f $od ] && rm -f $od
|
||||
[ -d $od ] || mkdir -p $od
|
||||
[ -d ".${line}" ] || isoinfo -R -i \
|
||||
{{ playbook_dir }}/{{ temp_directory }}/virtio_win.iso -x $line > ".${line}"
|
||||
done
|
||||
changed_when: True
|
||||
args:
|
||||
chdir: "{{ playbook_dir }}/{{ temp_directory }}/ks_iso"
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
|
||||
- name: wait until the image is unlocked by the oVirt engine
|
||||
ovirt_disk_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={% if item.name_prefix | default(false) %}{{ template.name }}_{% endif %}{{ item.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
|
||||
loop: "{{ template.disks }}"
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
|
||||
- name: wait until the image is unlocked by the oVirt engine (<2.9)
|
||||
ovirt_disk_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={% if item.name_prefix | default(false) %}{{ template.name }}_{% endif %}{{ item.name }}"
|
||||
until: (ovirt_disks is defined) and (ovirt_disks | length > 0) and (ovirt_disks[0].status != "locked")
|
||||
retries: 10
|
||||
delay: 3
|
||||
loop: "{{ template.disks }}"
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
|
||||
- name: wait until the disk is unlocked by the oVirt engine
|
||||
ovirt_disk_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ iso_file }}"
|
||||
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
|
||||
when: iso_file is defined
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
|
||||
- name: wait until the disk is unlocked by the oVirt engine (<2.9)
|
||||
ovirt_disk_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: "name={{ iso_file }}"
|
||||
until: (ovirt_disks is defined) and (ovirt_disks | length > 0) and (ovirt_disks[0].status != "locked")
|
||||
retries: 10
|
||||
delay: 3
|
||||
when: iso_file is defined
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
|
||||
- name: wait for vm status to be poweredoff
|
||||
ovirt_vm_info:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: name={{ template.name }} and cluster={{ providers.ovirt.cluster }}
|
||||
register: ovirt_vm_info_result
|
||||
until:
|
||||
- ovirt_vm_info_result.ovirt_vms is defined
|
||||
- ovirt_vm_info_result.ovirt_vms|length > 0
|
||||
- ovirt_vm_info_result.ovirt_vms[0].status == 'down'
|
||||
delay: 5
|
||||
retries: 30
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
|
||||
- name: wait for vm status to be poweredoff
|
||||
ovirt_vm_facts:
|
||||
auth: "{{ ovirt_auth }}"
|
||||
pattern: name={{ template.name }} and cluster={{ providers.ovirt.cluster }}
|
||||
until:
|
||||
- ovirt_vms is defined
|
||||
- ovirt_vms|length > 0
|
||||
- ovirt_vms[0].status == 'down'
|
||||
delay: 5
|
||||
retries: 30
|
||||
@@ -0,0 +1,404 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
<settings pass="windowsPE">
|
||||
<!-- look for drivers on floppy -->
|
||||
<component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<DriverPaths>
|
||||
<PathAndCredentials wcm:keyValue="1" wcm:action="add">
|
||||
<Path>E:\</Path>
|
||||
</PathAndCredentials>
|
||||
</DriverPaths>
|
||||
</component>
|
||||
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<SetupUILanguage>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
</SetupUILanguage>
|
||||
<InputLocale>en-US</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UILanguageFallback>en-US</UILanguageFallback>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<DiskConfiguration>
|
||||
<Disk wcm:action="add">
|
||||
{% if template_vm_efi is undefined or not template_vm_efi|bool %}
|
||||
<ModifyPartitions>
|
||||
<ModifyPartition wcm:action="modify">
|
||||
<Active>true</Active>
|
||||
<Format>NTFS</Format>
|
||||
<Label>boot</Label>
|
||||
<Order>1</Order>
|
||||
<PartitionID>1</PartitionID>
|
||||
</ModifyPartition>
|
||||
<ModifyPartition wcm:action="modify">
|
||||
<Format>NTFS</Format>
|
||||
<Label>{{ windows_distro_name[0:31] }}</Label>
|
||||
<Letter>C</Letter>
|
||||
<Order>2</Order>
|
||||
<PartitionID>2</PartitionID>
|
||||
</ModifyPartition>
|
||||
</ModifyPartitions>
|
||||
<DiskID>0</DiskID>
|
||||
<WillWipeDisk>true</WillWipeDisk>
|
||||
<CreatePartitions>
|
||||
<CreatePartition wcm:action="add">
|
||||
<Type>Primary</Type>
|
||||
<Order>1</Order>
|
||||
<Size>350</Size>
|
||||
</CreatePartition>
|
||||
<CreatePartition wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Type>Primary</Type>
|
||||
<Extend>true</Extend>
|
||||
</CreatePartition>
|
||||
</CreatePartitions>
|
||||
{% else %}
|
||||
<ModifyPartitions>
|
||||
<ModifyPartition wcm:action="modify">
|
||||
<Order>1</Order>
|
||||
<Format>NTFS</Format>
|
||||
<PartitionID>1</PartitionID>
|
||||
<Label>WINRE</Label>
|
||||
</ModifyPartition>
|
||||
<ModifyPartition wcm:action="modify">
|
||||
<Order>2</Order>
|
||||
<Format>FAT32</Format>
|
||||
<PartitionID>2</PartitionID>
|
||||
<Label>System</Label>
|
||||
</ModifyPartition>
|
||||
<ModifyPartition wcm:action="modify">
|
||||
<Order>3</Order>
|
||||
<PartitionID>3</PartitionID>
|
||||
</ModifyPartition>
|
||||
<ModifyPartition wcm:action="modify">
|
||||
<Format>NTFS</Format>
|
||||
<Letter>C</Letter>
|
||||
<Order>4</Order>
|
||||
<PartitionID>4</PartitionID>
|
||||
<Label>{{ windows_distro_name[0:31] }}</Label>
|
||||
</ModifyPartition>
|
||||
</ModifyPartitions>
|
||||
<DiskID>0</DiskID>
|
||||
<WillWipeDisk>true</WillWipeDisk>
|
||||
<CreatePartitions>
|
||||
<CreatePartition wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Type>Primary</Type>
|
||||
<Size>300</Size>
|
||||
</CreatePartition>
|
||||
<CreatePartition wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Type>EFI</Type>
|
||||
<Size>100</Size>
|
||||
</CreatePartition>
|
||||
<CreatePartition wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<Type>MSR</Type>
|
||||
<Size>128</Size>
|
||||
</CreatePartition>
|
||||
<CreatePartition wcm:action="add">
|
||||
<Order>4</Order>
|
||||
<Type>Primary</Type>
|
||||
<Extend>true</Extend>
|
||||
</CreatePartition>
|
||||
</CreatePartitions>
|
||||
{% endif %}
|
||||
</Disk>
|
||||
</DiskConfiguration>
|
||||
<ImageInstall>
|
||||
<OSImage>
|
||||
<InstallFrom>
|
||||
<MetaData wcm:action="add">
|
||||
<Key>/IMAGE/INDEX </Key>
|
||||
<Value>{{ iso_image_index }}</Value>
|
||||
</MetaData>
|
||||
</InstallFrom>
|
||||
<InstallTo>
|
||||
<DiskID>0</DiskID>
|
||||
{% if template_vm_efi is undefined or not template_vm_efi|bool %}
|
||||
<PartitionID>2</PartitionID>
|
||||
{% else %}
|
||||
<PartitionID>4</PartitionID>
|
||||
{% endif %}
|
||||
</InstallTo>
|
||||
</OSImage>
|
||||
</ImageInstall>
|
||||
<UserData>
|
||||
<AcceptEula>true</AcceptEula>
|
||||
<FullName>Ansible</FullName>
|
||||
<Organization>Your Org.</Organization>
|
||||
<ProductKey>
|
||||
{% if unattend.product_key is defined and unattend.product_key|length %}
|
||||
<Key>{{ unattend.product_key }}</Key>
|
||||
{% endif %}
|
||||
<WillShowUI>OnError</WillShowUI>
|
||||
</ProductKey>
|
||||
</UserData>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="generalize">
|
||||
<component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<SkipRearm>1</SkipRearm>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<PersistAllDeviceInstalls>false</PersistAllDeviceInstalls>
|
||||
<DoNotCleanUpNonPresentDevices>false</DoNotCleanUpNonPresentDevices>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<InputLocale>en-US</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
{% if not '2008' in windows_distro_name %}
|
||||
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||
<HideLocalAccountScreen>true</HideLocalAccountScreen>
|
||||
{% endif %}
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
<NetworkLocation>Home</NetworkLocation>
|
||||
<ProtectYourPC>1</ProtectYourPC>
|
||||
</OOBE>
|
||||
<TimeZone>{{ settings.time_zone | default('UTC') }}</TimeZone>
|
||||
<UserAccounts>
|
||||
{% if unattend.administrator_password is defined %}
|
||||
<AdministratorPassword>
|
||||
<Value>{{ unattend.administrator_password }}</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
{% endif %}
|
||||
{% if unattend.local_accounts is defined %}
|
||||
<LocalAccounts>
|
||||
{% for local_account in unattend.local_accounts %}
|
||||
<LocalAccount wcm:action="add">
|
||||
{% if local_account.password is defined %}
|
||||
<Password>
|
||||
<Value>{{ local_account.password }}</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
{% endif %}
|
||||
{% if local_account.description is defined %}
|
||||
<Description>{{ local_account.description }}</Description>
|
||||
{% endif %}
|
||||
{% if local_account.display_name is defined %}
|
||||
<DisplayName>{{ local_account.display_name }}</DisplayName>
|
||||
{% endif %}
|
||||
{% if local_account.group is defined %}
|
||||
<Group>{{ local_account.group }}</Group>
|
||||
{% endif %}
|
||||
{% if local_account.name is defined %}
|
||||
<Name>{{ local_account.name }}</Name>
|
||||
{% endif %}
|
||||
</LocalAccount>
|
||||
{% endfor %}
|
||||
</LocalAccounts>
|
||||
{% endif %}
|
||||
</UserAccounts>
|
||||
{% if enable_auto_logon and unattend.local_accounts and unattend.local_accounts[0].name and unattend.local_accounts[0].password %}
|
||||
<AutoLogon>
|
||||
<Password>
|
||||
<Value>{{ unattend.local_accounts[0].password }}</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
<Username>{{ unattend.local_accounts[0].name }}</Username>
|
||||
<Enabled>true</Enabled>
|
||||
</AutoLogon>
|
||||
{% endif %}
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-NetConnectionProfile -NetworkCategory Private"</CommandLine>
|
||||
<Description>Set network connection profile to private</Description>
|
||||
<Order>1</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine>
|
||||
<Description>Set Execution Policy 64 Bit</Description>
|
||||
<Order>2</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% if '2008' in windows_distro_name %}
|
||||
<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>
|
||||
{% endif %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "& $([scriptblock]::Create((New-Object Net.WebClient).DownloadString('{{ winrm_enable_script_url }}'))) -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>
|
||||
{% if template.networks is defined and template.networks[0].ip is defined and template.networks[0].gateway is defined and template.networks[0].netmask is defined %}
|
||||
{% if not '2008' in windows_distro_name %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "New-NetIPAddress –IPAddress {{ template.networks[0].ip }} -DefaultGateway {{ template.networks[0].gateway }} -PrefixLength {{ (template.networks[0].ip + '/' + template.networks[0].netmask) | ipaddr('prefix') }} -InterfaceIndex (Get-NetAdapter).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 {{ template.networks[0].ip }} {{ template.networks[0].netmask }} {{ template.networks[0].gateway }}</CommandLine>
|
||||
<Description>Set static ip</Description>
|
||||
<Order>50</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% endif %}
|
||||
{% if template.networks[0].dns_servers is defined %}
|
||||
{% if not '2008' in windows_distro_name %}
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<CommandLine>cmd.exe /c powershell -Command "Set-DNSClientServerAddress –InterfaceIndex (Get-NetAdapter).InterfaceIndex –ServerAddresses {{ template.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 {{ template.networks[0].dns_servers[0] }}</CommandLine>
|
||||
<Description>Set static ip</Description>
|
||||
<Order>51</Order>
|
||||
<RequiresUserInput>true</RequiresUserInput>
|
||||
</SynchronousCommand>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="specialize">
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>
|
||||
</component>
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<IEHardenAdmin>false</IEHardenAdmin>
|
||||
<IEHardenUser>false</IEHardenUser>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<SearchScopes>
|
||||
<Scope wcm:action="add">
|
||||
<ScopeDefault>true</ScopeDefault>
|
||||
<ScopeDisplayName>Google</ScopeDisplayName>
|
||||
<ScopeKey>Google</ScopeKey>
|
||||
<ScopeUrl>http://www.google.com/search?q={searchTerms}</ScopeUrl>
|
||||
</Scope>
|
||||
</SearchScopes>
|
||||
<DisableAccelerators>true</DisableAccelerators>
|
||||
<DisableFirstRunWizard>true</DisableFirstRunWizard>
|
||||
<Home_Page>about:blank</Home_Page>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<fDenyTSConnections>false</fDenyTSConnections>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<UserAuthentication>0</UserAuthentication>
|
||||
</component>
|
||||
<component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<FirewallGroups>
|
||||
<FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop">
|
||||
<Active>true</Active>
|
||||
<Group>Remote Desktop</Group>
|
||||
<Profile>all</Profile>
|
||||
</FirewallGroup>
|
||||
</FirewallGroups>
|
||||
</component>
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-OutOfBoxExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>
|
||||
</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>{{ settings.skip_auto_activation | default('true') }}</SkipAutoActivation>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="offlineServicing">
|
||||
<component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<EnableLUA>false</EnableLUA>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
1
roles/oatakan.windows_ovirt_template/tests/inventory
Normal file
1
roles/oatakan.windows_ovirt_template/tests/inventory
Normal file
@@ -0,0 +1 @@
|
||||
localhost
|
||||
7
roles/oatakan.windows_ovirt_template/tests/test.yml
Normal file
7
roles/oatakan.windows_ovirt_template/tests/test.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- hosts: localhost
|
||||
gather_facts: False
|
||||
connection: local
|
||||
become: no
|
||||
roles:
|
||||
- ../.
|
||||
71
roles/oatakan.windows_ovirt_template/vars/main.yml
Normal file
71
roles/oatakan.windows_ovirt_template/vars/main.yml
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
|
||||
temp_directory: tmp{{ awx_job_id | default('') }}
|
||||
|
||||
iso_file: "windows_{{ windows_distro_name }}_autounattend{{ awx_job_id | default('') }}.iso"
|
||||
|
||||
export_dir: "{{ playbook_dir }}/{{ temp_directory }}"
|
||||
|
||||
unattend:
|
||||
administrator_password: "{{ local_administrator_password }}"
|
||||
local_accounts:
|
||||
- name: "{{ local_account_username }}"
|
||||
display_name: "{{ local_account_username }}"
|
||||
description: "{{ local_account_username }} user"
|
||||
group: Administrators
|
||||
password: "{{ local_account_password }}"
|
||||
settings:
|
||||
computer_name: wintemp
|
||||
time_zone: UTC
|
||||
skip_auto_activation: true
|
||||
product_key: "{{ iso_product_key | default('') }}"
|
||||
|
||||
providers:
|
||||
ovirt:
|
||||
datacenter: "{{ ovirt_datacenter }}"
|
||||
cluster: "{{ ovirt_cluster }}"
|
||||
data_domain: "{{ ovirt_data_domain }}"
|
||||
export_domain: "{{ ovirt_export_domain }}"
|
||||
iso_domain: "{{ ovirt_iso_domain }}"
|
||||
|
||||
template:
|
||||
name: "{{ template_vm_name }}"
|
||||
role: windows_template
|
||||
app_name: windows_template_generate
|
||||
domain: "{{ template_vm_domain }}"
|
||||
disks:
|
||||
- name: "{{ template_vm_name }}"
|
||||
size: "{{ template_vm_root_disk_size }}GiB"
|
||||
format: "{{ template_vm_root_disk_format }}"
|
||||
interface: "{{ template_vm_root_disk_interface | default('virtio') }}"
|
||||
bootable: yes
|
||||
storage_domain: "{{ providers.ovirt.data_domain | default('data_domain') }}"
|
||||
memory: "{{ template_vm_memory }}"
|
||||
cpu: "{{ template_vm_cpu }}"
|
||||
networks:
|
||||
- name: "{{ template_vm_network_name }}"
|
||||
ip: "{{ template_vm_ip_address }}"
|
||||
netmask: "{{ template_vm_netmask }}"
|
||||
gateway: "{{ template_vm_gateway }}"
|
||||
domain: "{{ template_vm_domain }}"
|
||||
device_type: e1000
|
||||
dns_servers: "{{ template_vm_dns_servers }}"
|
||||
cd_iso: "{{ iso_file_id | default(iso_file_name) }}" # if using data domain, file name does not work, need to use id
|
||||
|
||||
qemu_cmdline_second_iso:
|
||||
- -device
|
||||
- ide-cd,bus=ide.3,unit=0,drive=drive-ua-0001,id=ua-0001,bootindex=3
|
||||
- -drive
|
||||
- format=raw,if=none,id=drive-ua-0001,werror=report,rerror=report,readonly=on,file=/rhev/data-center/{{ ovirt_datacenter_id }}/{{ ovirt_datastore_id }}/images/{{ ks_iso_file_disk_id }}/{{ ks_iso_file_image_id }}
|
||||
|
||||
qemu_cmdline_efi:
|
||||
- -drive
|
||||
- if=pflash,format=raw,readonly,file=/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd
|
||||
|
||||
custom_properties:
|
||||
- name: qemu_cmdline
|
||||
value: "{{ ((qemu_cmdline_second_iso + qemu_cmdline_efi) | to_json) if template_vm_efi|bool else (qemu_cmdline_second_iso | to_json) }}"
|
||||
|
||||
custom_properties_efi:
|
||||
- name: qemu_cmdline
|
||||
value: "{{ qemu_cmdline_efi | to_json }}"
|
||||
Reference in New Issue
Block a user