---
# Copyright kubeinit contributors
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Deploy a Windows server guest
block:
- name: Print Windows EULA so users accept it
ansible.builtin.debug:
msg: |
*********************************************************************************************************************
* Please read: https://docs.microsoft.com/en-us/legal/windows-server/system-insights-eula *
*********************************************************************************************************************
* MICROSOFT.WINDOWSSERVER.SYSTEMINSIGHTS *
* These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). *
* They apply to the software named above and any Microsoft services or software updates (except to the *
* extent such services or updates are accompanied by new or additional terms, in which case those *
* different terms apply prospectively and do not alter your or Microsoft's rights relating to pre-updated *
* software or services). *
* IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. *
*********************************************************************************************************************
* If you do not comply with these license terms, please stop this deployment right now. *
*********************************************************************************************************************
- name: Wait 1 minute for displaying the EULA text
ansible.builtin.pause:
minutes: 1
- name: Remove old disk images
ansible.builtin.file:
path: "{{ kubeinit_libvirt_target_image_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}.qcow2"
state: absent
- name: Create the config data folder
ansible.builtin.file:
path: "{{ kubeinit_libvirt_hypervisor_tmp_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}/config/"
state: directory
mode: 0775
recurse: yes
- name: Create the config data folder template
ansible.builtin.template:
src: "autounattend.xml.j2"
dest: "{{ kubeinit_libvirt_hypervisor_tmp_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}/config/autounattend.xml"
mode: "0644"
- name: Render the authorized keys file
ansible.builtin.template:
src: "authorized_keys.j2"
dest: "{{ kubeinit_libvirt_hypervisor_tmp_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}/config/authorized_keys"
mode: "0644"
- name: Render the setup scripts
ansible.builtin.template:
src: "{{ item }}.j2"
dest: "{{ kubeinit_libvirt_hypervisor_tmp_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}/config/{{ item }}"
mode: "0644"
loop:
- SetNet.ps1
- Install-Openssh.ps1
- PrepareRequirements.ps1
- Install-Containerd.ps1
- PrepareNode.ps1
- PrepareFlannel.ps1
- name: Create the .iso disk with the install assets
ansible.builtin.shell: |
# We create an iso file with the config unnatended data
mkisofs -o {{ kubeinit_libvirt_target_image_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}_config.iso -r -J {{ kubeinit_libvirt_hypervisor_tmp_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}/config/
args:
executable: /bin/bash
register: _result
changed_when: "_result.rc == 0"
- name: Create a qcow empty disk to install the OS
ansible.builtin.shell: |
# We create the server disk image
qemu-img create -f qcow2 {{ kubeinit_libvirt_target_image_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}.qcow2 {{ hostvars[kubeinit_deployment_node_name].disk }}
args:
executable: /bin/bash
register: _result
changed_when: "_result.rc == 0"
- name: Install Windows
ansible.builtin.shell: |
virt-install \
--name={{ hostvars[kubeinit_deployment_node_name].guest_name }} \
--memory memory={{ hostvars[kubeinit_deployment_node_name].ram|int // 1024 }} \
--vcpus={{ hostvars[kubeinit_deployment_node_name].vcpus }},maxvcpus={{ hostvars[kubeinit_deployment_node_name].maxvcpus }} \
--network network={{ kubeinit_cluster_hostvars.network_name }},mac={{ hostvars[kubeinit_deployment_node_name].mac }},virtualport.parameters.interfaceid={{ hostvars[kubeinit_deployment_node_name].interfaceid }},target.dev=veth0-{{ hostvars[kubeinit_deployment_node_name].ansible_host | ansible.utils.ip4_hex }},model=virtio \
--disk path={{ kubeinit_libvirt_target_image_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}.qcow2,format=qcow2,bus=virtio \
--cdrom {{ kubeinit_libvirt_target_image_dir }}/SERVER_EVAL_x64FRE_en-us.iso \
--disk path={{ kubeinit_libvirt_target_image_dir }}/{{ kubeinit_libvirt_virtio_image_name }},device=cdrom \
--disk path={{ kubeinit_libvirt_target_image_dir }}/{{ hostvars[kubeinit_deployment_node_name].guest_name }}_config.iso,device=cdrom \
--os-variant win2k8 \
--vnc \
--autostart \
--console pty \
--connect qemu:///system \
--import \
--noautoconsole
args:
executable: /bin/bash
register: _result
changed_when: "_result.rc == 0"
- name: "Wait until is running {{ hostvars[kubeinit_deployment_node_name].guest_name }}"
community.libvirt.virt:
command: list_vms
state: running
register: _result
retries: 30
delay: 10
until: hostvars[kubeinit_deployment_node_name].guest_name in _result.list_vms
- name: "Wait until setup finish and the guest is shut down for {{ hostvars[kubeinit_deployment_node_name].guest_name }}"
community.libvirt.virt:
command: list_vms
state: shutdown
register: _result
retries: 100
delay: 10
until: hostvars[kubeinit_deployment_node_name].guest_name in _result.list_vms
- name: "Re-start {{ hostvars[kubeinit_deployment_node_name].guest_name }}"
community.libvirt.virt:
name: "{{ hostvars[kubeinit_deployment_node_name].guest_name }}"
state: running
- name: "Wait until is running {{ hostvars[kubeinit_deployment_node_name].guest_name }}"
community.libvirt.virt:
command: list_vms
state: running
register: _result
retries: 30
delay: 10
until: hostvars[kubeinit_deployment_node_name].guest_name in _result.list_vms
- name: Show some information for connecting with VNC
ansible.builtin.debug:
msg: |
Make sure the VNC session is up and running with:
virsh vncdisplay {{ hostvars[kubeinit_deployment_node_name].guest_name }}
Create a tunnel from your machine to the hypervisor hosting the Windows guest
ssh root@tyto -L 5900:127.0.0.1:5900
from your machine connect to the VNC server at 127.0.0.1
- name: "Make sure we can execute SSH remote commands in {{ hostvars[kubeinit_deployment_node_name].guest_name }}"
ansible.builtin.shell: |
set -o pipefail
ssh {{ hostvars[kubeinit_deployment_node_name].ansible_ssh_common_args }} \
{{ _param_guest_user | default('root') }}@{{ hostvars[kubeinit_deployment_node_name].ansible_host }} 'echo connected' || true
args:
executable: /bin/bash
register: _result
retries: 60
delay: 10
until: "'connected' in _result.stdout"
changed_when: "_result.rc == 0"
delegate_to: "{{ kubeinit_deployment_delegate }}"
- name: Configure common requirements in Windows guests
block:
- name: Make sure there is enough RAM for Windows computes
ansible.builtin.assert:
that:
- compute_node_ram_size | int >= 16777216
fail_msg: "'compute_node_ram_size' must be greater than 16777216, that is, 16GB RAM"
success_msg: "'compute_node_ram_size' is more than 16GB RAM, OK"
- name: Ping
ansible.windows.win_ping:
- name: Create the k folder
ansible.windows.win_file:
path: C:\k
state: directory
- name: Copy all the ISO resources to a writable folder
ansible.windows.win_copy:
src: F:\
dest: C:\k
remote_src: yes
- name: Install KB5012637
ansible.windows.win_powershell:
script: |
$patchFile = "windows10.0-kb5012637-x64_6a7459b60e226b0ad0d30b34a4be069bee4d2867.msu"
$url = "https://catalog.s.download.windowsupdate.com/c/msdownload/update/software/updt/2022/04/$patchFile"
$dest = "C:\Windows\Temp\$patchFile"
Invoke-WebRequest -Uri $url -OutFile $dest
# Install the patch, bypassing any prompts
cmd.exe /c wusa.exe $dest /quiet /norestart
register: _result
changed_when: "_result.host_err == ''"
- name: Enable the required container features and required modules
ansible.windows.win_powershell:
script: |
Install-WindowsFeature Containers
Install-WindowsFeature Hyper-V
Install-WindowsFeature Hyper-V-PowerShell
register: _result
changed_when: "_result.host_err == ''"
- name: Reboot the server after installing the new features
# This might take a lot of time depending on updates,
# and finishing to enable the container features.
ansible.windows.win_reboot:
reboot_timeout: 3600
- name: Configure Overlay HNSNetwork for the overlay network
# This task MUST be executed after the initial guest reboot
ansible.windows.win_powershell:
script: |
# We do this when there is no network created, this will create a network glitch
# as there must be created a new virtual switch where each pod will be connected to
# Note: RDP connection will hiccup when running this command (New-HNSNetwork).
New-Item C:\k -Force -ItemType Directory | Out-Null
curl.exe --silent --fail -Lo C:\k\hns.psm1 https://github.com/Microsoft/SDN/raw/master/Kubernetes/windows/hns.psm1
Import-Module "c:\k\hns.psm1"
# There is no need to remove the nhs nets as this is a new environment
# get-hnsnetwork | remove-hnsnetwork
New-HNSNetwork -Type "Overlay" `
-AddressPrefix "10.244.0.0/16" `
-Gateway "10.244.0.1" `
-Name "vxlan0" `
-AdapterName "$((Get-NetAdapter -Physical).Name)" `
-SubnetPolicies @(@{Type = "VSID"; VSID = 4096; }) `
-Verbose
# This task will make Ansible to hang, there is a connection hiccup
# and then we are not able to continue, so we trigger this as async
# and then we ping again the machine to see we can communicate over SSH
async: 60
poll: 0
- name: Ping
ansible.windows.win_ping:
# TODO:FIXME: The following variables should be
# added as group vars for those compute nodes which the
# os is equals to 'windows'
# TODO:FIXME: The usage of ansible_shell_type might
# be different depending on the win_* task, the
# supported values are [cmd | powershell]
vars:
ansible_shell_type: 'cmd'
ansible_remote_tmp: 'C:\Windows\Temp'
delegate_to: "{{ kubeinit_deployment_node_name }}"
# TODO:FIXME: Do we need a Windows gather facts?
# - name: Gather guest network facts
# block:
# - name: Gather network and host facts for guest
# ansible.builtin.include_role:
# name: kubeinit.kubeinit.kubeinit_prepare
# tasks_from: gather_host_facts.yml
# public: yes
# vars:
# _param_gather_host: "{{ kubeinit_deployment_node_name }}"
# tags: omit_from_grapher