Add Hyper-V role

Implement an ansible role that adds Hyper-V as a compute node for
OpenStack using Kolla.

This will install and configure the Nova Compute service, the
Hyper-V Neutron agent and FreeRDP-WebConnect.
https://docs.openstack.org/ocata/config-reference/compute/hypervisor-hyper-v.html

Change-Id: I601835b0769c5ff173a980a05a752391ae8cc82f
Implements: blueprint hyperv-ansible-role
Co-Authored-By: Alessandro Pilotti <apilotti@cloudbasesolutions.com>
This commit is contained in:
Dan Ardelean 2017-05-30 14:16:34 +03:00
parent d8fe3ea780
commit 58ce2b54ea
20 changed files with 426 additions and 0 deletions

View File

@ -162,6 +162,8 @@ rabbitmq_management_port: "15672"
rabbitmq_cluster_port: "25672" rabbitmq_cluster_port: "25672"
rabbitmq_epmd_port: "4369" rabbitmq_epmd_port: "4369"
rdp_port: "8001"
outward_rabbitmq_port: "5674" outward_rabbitmq_port: "5674"
outward_rabbitmq_management_port: "15674" outward_rabbitmq_management_port: "15674"
outward_rabbitmq_cluster_port: "25674" outward_rabbitmq_cluster_port: "25674"
@ -347,6 +349,7 @@ enable_horizon_solum: "{{ enable_solum | bool }}"
enable_horizon_tacker: "{{ enable_tacker | bool }}" enable_horizon_tacker: "{{ enable_tacker | bool }}"
enable_horizon_trove: "{{ enable_trove | bool }}" enable_horizon_trove: "{{ enable_trove | bool }}"
enable_horizon_watcher: "{{ enable_watcher | bool }}" enable_horizon_watcher: "{{ enable_watcher | bool }}"
enable_hyperv: "no"
enable_influxdb: "no" enable_influxdb: "no"
enable_ironic: "no" enable_ironic: "no"
enable_iscsid: "{{ enable_cinder_backend_iscsi | bool or enable_cinder_backend_lvm | bool or enable_ironic | bool }}" enable_iscsid: "{{ enable_cinder_backend_iscsi | bool or enable_cinder_backend_lvm | bool or enable_ironic | bool }}"

View File

@ -60,6 +60,16 @@ control
[haproxy:children] [haproxy:children]
network network
[hyperv]
#hyperv_host
[hyperv:vars]
#ansible_user=user
#ansible_password=password
#ansible_port=5986
#ansible_connection=winrm
#ansible_winrm_server_cert_validation=ignore
[mariadb:children] [mariadb:children]
control control

View File

@ -81,6 +81,16 @@ control
[haproxy:children] [haproxy:children]
network network
[hyperv]
#hyperv_host
[hyperv:vars]
#ansible_user=user
#ansible_password=password
#ansible_port=5986
#ansible_connection=winrm
#ansible_winrm_server_cert_validation=ignore
[mariadb:children] [mariadb:children]
control control

View File

@ -3,6 +3,9 @@
{% if enable_ironic | bool %} {% if enable_ironic | bool %}
tenant_network_types = vxlan, flat tenant_network_types = vxlan, flat
mechanism_drivers = openvswitch mechanism_drivers = openvswitch
{% elif enable_hyperv | bool %}
type_drivers = flat,vlan,vxlan
tenant_network_types = flat,vlan
{% else %} {% else %}
# Changing type_drivers after bootstrap can lead to database inconsistencies # Changing type_drivers after bootstrap can lead to database inconsistencies
type_drivers = flat,vlan,vxlan type_drivers = flat,vlan,vxlan
@ -10,13 +13,19 @@ tenant_network_types = vxlan
{% endif %} {% endif %}
{% if neutron_plugin_agent == "openvswitch" %} {% if neutron_plugin_agent == "openvswitch" %}
{% if enable_hyperv | bool %}
mechanism_drivers = openvswitch,hyperv
{% else %}
mechanism_drivers = openvswitch,l2population mechanism_drivers = openvswitch,l2population
{% endif %}
{% elif neutron_plugin_agent == "linuxbridge" %} {% elif neutron_plugin_agent == "linuxbridge" %}
mechanism_drivers = linuxbridge,l2population mechanism_drivers = linuxbridge,l2population
{% endif %} {% endif %}
{% if neutron_extension_drivers %} {% if neutron_extension_drivers %}
extension_drivers = {{ neutron_extension_drivers|map(attribute='name')|join(',') }} extension_drivers = {{ neutron_extension_drivers|map(attribute='name')|join(',') }}
{% elif enable_hyperv | bool %}
extension_drivers = port_security
{% endif %} {% endif %}
[ml2_type_vlan] [ml2_type_vlan]
@ -33,9 +42,11 @@ flat_networks = *
flat_networks = {% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index0 + 1 }}{% if not loop.last %},{% endif %}{% endfor %} flat_networks = {% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index0 + 1 }}{% if not loop.last %},{% endif %}{% endfor %}
{% endif %} {% endif %}
{% if not enable_hyperv | bool %}
[ml2_type_vxlan] [ml2_type_vxlan]
vni_ranges = 1:1000 vni_ranges = 1:1000
vxlan_group = 239.1.1.1 vxlan_group = 239.1.1.1
{% endif %}
[securitygroup] [securitygroup]
{% if neutron_plugin_agent == "openvswitch" %} {% if neutron_plugin_agent == "openvswitch" %}
@ -45,10 +56,12 @@ firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
{% endif %} {% endif %}
{% if neutron_plugin_agent == "openvswitch" %} {% if neutron_plugin_agent == "openvswitch" %}
{% if not enable_hyperv | bool %}
[agent] [agent]
tunnel_types = vxlan tunnel_types = vxlan
l2_population = true l2_population = true
arp_responder = true arp_responder = true
{% endif %}
{% if enable_neutron_dvr | bool %} {% if enable_neutron_dvr | bool %}
enable_distributed_routing = True enable_distributed_routing = True
@ -71,7 +84,9 @@ integration_bridge = br-int-{{ item }}
[linux_bridge] [linux_bridge]
physical_interface_mappings = physnet1:{{ neutron_external_interface }} physical_interface_mappings = physnet1:{{ neutron_external_interface }}
{% if not enable_hyperv | bool %}
[vxlan] [vxlan]
l2_population = true l2_population = true
{% endif %} {% endif %}
{% endif %}
local_ip = {{ tunnel_interface_address }} local_ip = {{ tunnel_interface_address }}

View File

@ -0,0 +1,7 @@
---
placement_keystone_user: "placement"
msi_dir: "%SYSTEMDRIVE%\\OpenStack\\MSIs"
log_dir: "%SYSTEMDRIVE%\\OpenStack\\Log"
freerdp_msi_url: "https://cloudbase.it/downloads/FreeRDPWebConnect.msi"
hyperv_compute_msi: "HyperVNovaCompute.msi"
freerdp_webconnect_msi: "FreeRDPWebConnect.msi"

View File

@ -0,0 +1,15 @@
---
- name: Restart nova-compute
win_service:
name: nova-compute
state: restarted
- name: Restart neutron-hyperv-agent
win_service:
name: neutron-hyperv-agent
state: restarted
- name: Restart FreeRDP-WebConnect
win_service:
name: wsgate
state: restarted

View File

@ -0,0 +1 @@
---

View File

@ -0,0 +1,35 @@
---
- name: Create log directory
win_command: "cmd /c mkdir {{ log_dir }}"
args:
creates: "{{ log_dir }}"
- name: Configure nova-compute
win_template:
src: "{{ item }}"
dest: "%PROGRAMFILES%\\Cloudbase Solutions\\OpenStack\\Nova\\etc\\nova.conf"
with_first_found:
- "{{ node_custom_config }}/nova-hyperv/{{ inventory_hostname }}/nova_hyperv.conf"
- "{{ node_custom_config }}/nova-hyperv/nova_hyperv.conf"
- "nova_hyperv.conf.j2"
notify: Restart nova-compute
- name: Configure neutron-hyperv-agent
win_template:
src: "{{ item }}"
dest: "%PROGRAMFILES%\\Cloudbase Solutions\\OpenStack\\Nova\\etc\\neutron_hyperv_agent.conf"
with_first_found:
- "{{ node_custom_config }}/nova-hyperv/{{ inventory_hostname }}/neutron_hyperv_agent.conf"
- "{{ node_custom_config }}/nova-hyperv/neutron_hyperv_agent.conf"
- "neutron_hyperv_agent.conf.j2"
notify: Restart neutron-hyperv-agent
- name: Configure FreeRDP-WebConnect
win_template:
src: "{{ item }}"
dest: "%PROGRAMFILES%\\Cloudbase Solutions\\FreeRDP-WebConnect\\etc\\wsgate.ini"
with_first_found:
- "{{ node_custom_config }}/nova-hyperv/{{ inventory_hostname }}/wsgate.ini"
- "{{ node_custom_config }}/nova-hyperv/wsgate.ini"
- "wsgate.ini.j2"
notify: Restart FreeRDP-WebConnect

View File

@ -0,0 +1,6 @@
---
- include: install.yml
when: inventory_hostname in groups['hyperv']
- include: config.yml
when: inventory_hostname in groups['hyperv']

View File

@ -0,0 +1,26 @@
---
- name: Create MSIs download directory
win_command: "cmd /c mkdir {{ msi_dir }}"
args:
creates: "{{ msi_dir }}"
- name: Download Nova and FreeRDP-WebConnect MSIs
win_get_url:
url: "{{ item.name }}"
dest: "{{ item.destination }}"
force: no
with_items:
- { name: "{{ nova_msi_url }}", destination: "{{ msi_dir }}\\{{ hyperv_compute_msi }}" }
- { name: "{{ freerdp_msi_url }}", destination: "{{ msi_dir }}\\{{ freerdp_webconnect_msi }}" }
- name: Install the Compute MSI
win_command: "msiexec /i {{ hyperv_compute_msi }} SKIPNOVACONF=0"
args:
chdir: "{{ msi_dir }}"
creates: "%PROGRAMFILES%\\Cloudbase Solutions\\OpenStack\\Nova\\bin"
- name: Install the FreeRDP-WebConnect MSI
win_command: "msiexec.exe /i {{ freerdp_webconnect_msi }}"
args:
chdir: "{{ msi_dir }}"
creates: "%PROGRAMFILES%\\Cloudbase Solutions\\FreeRDP-WebConnect\\Binaries"

View File

@ -0,0 +1,2 @@
---
- include: "{{ action }}.yml"

View File

@ -0,0 +1,2 @@
---
- include: "deploy.yml"

View File

@ -0,0 +1,18 @@
[DEFAULT]
debug = {{ openstack_logging_debug }}
control_exchange = neutron
rpc_backend = rabbit
log_dir = C:\OpenStack\Log
log_file = neutron-hyperv-agent.log
transport_url = rabbit://{% for host in groups['rabbitmq'] %}{{ rabbitmq_user }}:{{ rabbitmq_password }}@{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ rabbitmq_port }}{% if not loop.last %},{% endif %}{% endfor %}
[AGENT]
polling_interval = 2
physical_network_vswitch_mappings = *:{{ vswitch_name }}
enable_metrics_collection = false
enable_qos_extension = false
[SECURITYGROUP]
firewall_driver = hyperv
enable_security_group = true

View File

@ -0,0 +1,61 @@
[DEFAULT]
compute_driver = compute_hyperv.driver.HyperVDriver
instances_path = C:\OpenStack\Instances
use_cow_images = true
flat_injected = true
mkisofs_cmd = C:\Program Files\Cloudbase Solutions\OpenStack\Nova\bin\mkisofs.exe
debug = {{ openstack_logging_debug }}
allow_resize_to_same_host = true
running_deleted_instance_action = reap
running_deleted_instance_poll_interval = 120
resize_confirm_window = 5
resume_guests_state_on_host_boot = true
rpc_response_timeout = 1800
lock_path = C:\OpenStack\Log
vif_plugging_is_fatal = false
vif_plugging_timeout = 60
rpc_backend = rabbit
log_dir = C:\OpenStack\Log
log_file = nova-compute.log
force_config_drive = True
transport_url = rabbit://{% for host in groups['rabbitmq'] %}{{ rabbitmq_user }}:{{ rabbitmq_password }}@{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ rabbitmq_port }}{% if not loop.last %},{% endif %}{% endfor %}
[placement]
auth_type = password
auth_url = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }}/v3
project_name = service
username = {{ placement_keystone_user }}
password = {{ placement_keystone_password }}
project_domain_name = default
user_domain_name = default
os_region_name = {{ openstack_region_name }}
[glance]
api_servers = {{ internal_protocol }}://{% for host in groups['glance-api'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ glance_api_port }}{% if not loop.last %},{% endif %}{% endfor %}
[hyperv]
vswitch_name = {{ vswitch_name }}
limit_cpu_features = false
config_drive_inject_password = true
qemu_img_cmd = C:\Program Files\Cloudbase Solutions\OpenStack\Nova\bin\qemu-img.exe
config_drive_cdrom = true
dynamic_memory_ratio = 1
enable_instance_metrics_collection = false
[rdp]
enabled = true
html5_proxy_base_url = {{ public_protocol }}://{{ ansible_fqdn }}:{{ rdp_port }}
[neutron]
url = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ neutron_server_port }}
auth_strategy = keystone
project_domain_name = default
project_name = service
user_domain_name = default
username = {{ neutron_keystone_user }}
password = {{ neutron_keystone_password }}
auth_url = {{ keystone_admin_url }}/v3
auth_plugin = v3password

View File

@ -0,0 +1,28 @@
[global]
debug = {{ openstack_logging_debug }}
redirect = false
port = {{ rdp_port }}
bindaddr = {% for host in groups['hyperv'] %}{% for ip in hostvars[inventory_hostname]['ansible_ip_addresses'] %}{% if host == ip %}{{ ip }}{% endif %}{% endfor %}{% endfor %}
[http]
documentroot = C:\Program Files\Cloudbase Solutions\FreeRDP-WebConnect\WebRoot\
[ssl]
port=4430
bindaddr = {% for host in groups['hyperv'] %}{% for ip in hostvars[inventory_hostname]['ansible_ip_addresses'] %}{% if host == ip %}{{ ip }}{% endif %}{% endfor %}{% endfor %}
certfile = C:\Program Files\Cloudbase Solutions\FreeRDP-WebConnect\etc\server.cer
[rdpoverride]
nofullwindowdrag = true
[openstack]
authurl = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }}/v2.0
tenantname = service
username = {{ nova_keystone_user }}
password = {{ nova_keystone_password }}
[hyperv]
hostusername = {{ hyperv_username }}
hostpassword = {{ hyperv_password }}

View File

@ -307,6 +307,16 @@
tags: openvswitch, tags: openvswitch,
when: enable_openvswitch | bool } when: enable_openvswitch | bool }
- name: Apply nova-hyperv role
gather_facts: false
hosts:
- hyperv
serial: '{{ serial|default("0") }}'
roles:
- { role: nova-hyperv,
tags: nova-hyperv,
when: enable_hyperv | bool }
# (gmmaha): Please do not change the order listed here. The current order is a # (gmmaha): Please do not change the order listed here. The current order is a
# workaround to fix the bug https://bugs.launchpad.net/kolla/+bug/1546789 # workaround to fix the bug https://bugs.launchpad.net/kolla/+bug/1546789
- name: Apply role neutron - name: Apply role neutron

163
doc/hyperv-guide.rst Normal file
View File

@ -0,0 +1,163 @@
.. _hyperv-guide:
====================
Nova-HyperV in Kolla
====================
Overview
========
Currently, Kolla can deploy the following OpenStack services for Hyper-V:
* nova-compute
* neutron-hyperv-agent
* wsgate
It is possible to use Hyper-V as a compute node within an OpenStack Deployment.
The nova-compute service runs as openstack-compute, a 64-bit service directly
upon the Windows platform with the Hyper-V role enabled. The necessary Python
components as well as the nova-compute service are installed directly onto
the Windows platform. Windows Clustering Services are not needed for
functionality within the OpenStack infrastructure.
The wsgate is the FreeRDP-WebConnect service that is used for accessing
virtual machines from Horizon web interface.
.. note::
HyperV services are not currently deployed as containers. This functionality
is in development. The current implementation installs OpenStack services
via MSIs.
.. note::
HyperV services do not currently support outside the box upgrades. Manual
upgrades are required for this process. MSI release versions can be found
`here
<https://cloudbase.it/openstack-hyperv-driver/>`__.
To upgrade an existing MSI to a newer version, simply uninstall the current
MSI and install the newer one. This will not delete the configuration files.
To preserve the configuration files, check the Skip configuration checkbox
during installation.
Preparation for Hyper-V node
============================
Ansible communicates with Hyper-V host via WinRM protocol. An HTTPS WinRM
listener needs to be configured on the Hyper-V host, which can be easily
created with
`this PowerShell script
<https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1>`__.
A virtual switch has to be created with which Hyper-V virtual machines
communicate with OpenStack. To quickly enable an interface to be used as a
Virtual Interface the following PowerShell may be used:
.. code-block:: console
PS C:\> $if = Get-NetIPAddress -IPAddress 192* | Get-NetIPInterface
PS C:\> New-VMSwitch -NetAdapterName $if.ifAlias -Name YOUR_BRIDGE_NAME -AllowManagementOS $false
.. note::
It is very important to make sure that when you are using a Hyper-V node with only 1 NIC the
-AllowManagementOS option is set on True, otherwise you will lose connectivity to the Hyper-V node.
To prepare the Hyper-V node to be able to attach to volumes provided by cinder you must
first make sure the Windows iSCSI initiator service is running and started automatically.
.. code-block:: console
PS C:\> Set-Service -Name MSiSCSI -StartupType Automatic
PS C:\> Start-Service MSiSCSI
Preparation for Kolla deployer node
===================================
Hyper-V role is required, enable it in ``/etc/kolla/globals.yml``:
.. code-block:: console
enable_hyperv: "yes"
Hyper-V options are also required in ``/etc/kolla/globals.yml``:
.. code-block:: console
hyperv_username: <HyperV username>
hyperv_password: <HyperV password>
vswitch_name: <HyperV virtual switch name>
nova_msi_url: "https://www.cloudbase.it/downloads/HyperVNovaCompute_Beta.msi"
The virtual switch is the same one created on the HyperV setup part.
For nova_msi_url, different Nova MSI (Mitaka/Newton/Ocata) versions can be found on
`Cloudbase website
<https://cloudbase.it/openstack-hyperv-driver/>`__.
Add the Hyper-V node in ``ansible/inventory`` file:
.. code-block:: console
[hyperv]
<HyperV IP>
[hyperv:vars]
ansible_user=<HyperV user>
ansible_password=<HyperV password>
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
pywinrm package needs to be installed in order for Ansible to work on the HyperV node:
.. code-block:: console
pip install "pywinrm>=0.2.2"
.. note::
In case of a test deployment with controller and compute nodes as virtual machines
on Hyper-V, if VLAN tenant networking is used, trunk mode has to be enabled on the
VMs:
.. code-block:: console
Set-VMNetworkAdapterVlan -Trunk -AllowedVlanIdList <VLAN ID> -NativeVlanId 0 <VM name>
networking-hyperv mechanism driver is needed for neutron-server to communicate with
HyperV nova-compute. This can be built with source images by default. Manually it
can be intalled in neutron-server container with pip:
.. code-block:: console
pip install "networking-hyperv>=4.0.0"
For neutron_extension_drivers, ``port_security`` and ``qos`` are currently supported by the networking-hyperv
mechanism driver. By default only ``port_security`` is set.
Verify Operations
=================
OpenStack HyperV services can be inspected and managed from PowerShell:
.. code-block:: console
PS C:\> Get-Service nova-compute
PS C:\> Get-Service neutron-hyperv-agent
.. code-block:: console
PS C:\> Restart-Service nova-compute
PS C:\> Restart-Service neutron-hyperv-agent
For more information on OpenStack HyperV, see
`Hyper-V virtualization platform
<https://docs.openstack.org/ocata/config-reference/compute/hypervisor-hyper-v.html>`__.

View File

@ -63,6 +63,7 @@ Services
cinder-guide cinder-guide
cinder-guide-hnas cinder-guide-hnas
designate-guide designate-guide
hyperv-guide
ironic-guide ironic-guide
manila-guide manila-guide
manila-hnas-guide manila-hnas-guide

View File

@ -158,6 +158,7 @@ kolla_internal_vip_address: "10.10.10.254"
#enable_horizon_tacker: "{{ enable_tacker | bool }}" #enable_horizon_tacker: "{{ enable_tacker | bool }}"
#enable_horizon_trove: "{{ enable_trove | bool }}" #enable_horizon_trove: "{{ enable_trove | bool }}"
#enable_horizon_watcher: "{{ enable_watcher | bool }}" #enable_horizon_watcher: "{{ enable_watcher | bool }}"
#enable_hyperv: "no"
#enable_influxdb: "no" #enable_influxdb: "no"
#enable_ironic: "no" #enable_ironic: "no"
#enable_karbor: "no" #enable_karbor: "no"
@ -302,6 +303,15 @@ designate_ns_record: "sample.openstack.org"
######################### #########################
#nova_backend_ceph: "{{ enable_ceph }}" #nova_backend_ceph: "{{ enable_ceph }}"
###################
# Hyper-V options
###################
# Hyper-V can be used as hypervisor
#hyperv_username: "user"
#hyperv_password: "password"
#vswitch_name: "vswitch"
# URL from which Nova Hyper-V MSI is downloaded
#nova_msi_url: "https://www.cloudbase.it/downloads/HyperVNovaCompute_Beta.msi"
############################## ##############################
# Horizon - Dashboard Options # Horizon - Dashboard Options

View File

@ -0,0 +1,3 @@
---
features:
- Implement Nova-HyperV ansible role