From 047dbf12e04554c24ee9245284e0880d594ce68a Mon Sep 17 00:00:00 2001
From: Hui Kang <kangh@us.ibm.com>
Date: Mon, 28 Dec 2015 08:03:25 +0000
Subject: [PATCH] Enable nova fake driver in nova containers

- See instructions in doc/nova-fake-driver.rst

Implements: blueprint nova-fake-driver

Change-Id: I553a40c2df39bdcc391eb1b8b2b8fd5f4ed48c33
Signed-off-by: Hui Kang <kangh@us.ibm.com>
Signed-off-by: Marcio D. Silva <marcios@us.ibm.com>
---
 ansible/group_vars/all.yml                    |  3 ++
 .../neutron/tasks/config-neutron-fake.yml     | 47 +++++++++++++++++++
 ansible/roles/neutron/tasks/main.yml          |  5 ++
 ansible/roles/neutron/tasks/start.yml         | 34 +++++++++++++-
 .../roles/neutron/templates/ml2_conf.ini.j2   |  4 ++
 .../roles/neutron/templates/neutron.conf.j2   |  5 ++
 ansible/roles/nova/tasks/config-nova-fake.yml | 27 +++++++++++
 ansible/roles/nova/tasks/main.yml             |  5 ++
 ansible/roles/nova/tasks/start.yml            | 31 +++++++++++-
 ansible/roles/nova/templates/nova.conf.j2     |  4 ++
 doc/nova-fake-driver.rst                      | 34 ++++++++++++++
 11 files changed, 196 insertions(+), 3 deletions(-)
 create mode 100644 ansible/roles/neutron/tasks/config-neutron-fake.yml
 create mode 100644 ansible/roles/nova/tasks/config-nova-fake.yml
 create mode 100644 doc/nova-fake-driver.rst

diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index 3c5e41e0f1..1a5cf86fba 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -165,6 +165,9 @@ enable_magnum: "no"
 
 ironic_keystone_user: "ironic"
 
+# Nova fake driver and the number of fake driver per compute node
+enable_nova_fake: "no"
+num_nova_fake_per_node: 5
 
 ####################
 # RabbitMQ options
diff --git a/ansible/roles/neutron/tasks/config-neutron-fake.yml b/ansible/roles/neutron/tasks/config-neutron-fake.yml
new file mode 100644
index 0000000000..c04420cb0e
--- /dev/null
+++ b/ansible/roles/neutron/tasks/config-neutron-fake.yml
@@ -0,0 +1,47 @@
+---
+- name: Ensuring config directories exist
+  file:
+    path: "{{ node_config_directory }}/neutron-openvswitch-agent-fake-{{ item }}"
+    state: "directory"
+    recurse: yes
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+  when: inventory_hostname in groups['compute']
+
+- name: Copying over config.json files for services
+  template:
+    src: "roles/neutron/templates/neutron-openvswitch-agent.json.j2"
+    dest: "{{ node_config_directory }}/neutron-openvswitch-agent-fake-{{ item }}/config.json"
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+  when:
+    - inventory_hostname in groups['compute']
+    - enable_nova_fake | bool
+    - neutron_plugin_agent == "openvswitch"
+
+- name: Copying over neutron.conf
+  merge_configs:
+    sources:
+      - "{{ role_path }}/templates/neutron.conf.j2"
+      - "/etc/kolla/config/global.conf"
+      - "/etc/kolla/config/database.conf"
+      - "/etc/kolla/config/messaging.conf"
+      - "/etc/kolla/config/neutron.conf"
+      - "/etc/kolla/config/neutron/{{ item }}.conf"
+    dest: "{{ node_config_directory }}/neutron-openvswitch-agent-fake-{{ item }}/neutron.conf"
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+  when:
+    - inventory_hostname in groups['compute']
+    - neutron_plugin_agent == "openvswitch"
+    - enable_nova_fake | bool
+
+- name: Copying over ml2_conf.ini
+  merge_configs:
+    sources:
+      - "{{ role_path }}/templates/ml2_conf.ini.j2"
+      - "/etc/kolla/config/neutron/ml2_conf.ini"
+    dest: "{{ node_config_directory }}/neutron-openvswitch-agent-fake-{{ item }}/ml2_conf.ini"
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+  when:
+    - inventory_hostname in groups['compute']
+    - neutron_plugin_agent == "openvswitch"
+    - enable_nova_fake | bool
+
diff --git a/ansible/roles/neutron/tasks/main.yml b/ansible/roles/neutron/tasks/main.yml
index 82132ce494..19bf5d384e 100644
--- a/ansible/roles/neutron/tasks/main.yml
+++ b/ansible/roles/neutron/tasks/main.yml
@@ -10,6 +10,11 @@
         inventory_hostname in groups['neutron-agents'] or
         inventory_hostname in groups['neutron-server']
 
+- include: config-neutron-fake.yml
+  when:
+    - inventory_hostname in groups['compute']
+    - enable_nova_fake | bool
+
 - include: bootstrap.yml
   when: inventory_hostname in groups['neutron-server']
 
diff --git a/ansible/roles/neutron/tasks/start.yml b/ansible/roles/neutron/tasks/start.yml
index 5d8d3eaf32..76a19d305f 100644
--- a/ansible/roles/neutron/tasks/start.yml
+++ b/ansible/roles/neutron/tasks/start.yml
@@ -113,8 +113,38 @@
       - "/var/lib/kolla/dev/log:/dev/log"
     env:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
-  when: (inventory_hostname in groups['compute'] or inventory_hostname in groups['neutron-agents'])
-        and neutron_plugin_agent == "openvswitch"
+  when:
+    - neutron_plugin_agent == "openvswitch"
+    - ((inventory_hostname in groups['compute'] or inventory_hostname in groups['neutron-agents']) and not (enable_nova_fake | bool)) or
+      ((inventory_hostname in groups['neutron-agents']) and (enable_nova_fake | bool))
+
+- name: Starting Neutron-openvswitch-agent container for fake nova compute
+  docker:
+    tty: True
+    net: host
+    pull: "{{ docker_pull_policy }}"
+    restart_policy: "{{ docker_restart_policy }}"
+    restart_policy_retry: "{{ docker_restart_policy_retry }}"
+    state: reloaded
+    registry: "{{ docker_registry }}"
+    username: "{{ docker_registry_username }}"
+    password: "{{ docker_registry_password }}"
+    insecure_registry: "{{ docker_insecure_registry }}"
+    privileged: True
+    name: neutron_openvswitch_agent_fake_{{ item }}
+    image: "{{ neutron_openvswitch_agent_image_full }}"
+    volumes:
+      - "/run:/run"
+      - "/lib/modules:/lib/modules:ro"
+      - "{{ node_config_directory }}/neutron-openvswitch-agent-fake-{{ item }}/:{{ container_config_directory }}/:ro"
+      - "/var/lib/kolla/dev/log:/dev/log"
+    env:
+      KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+  when:
+    - inventory_hostname in groups['compute']
+    - neutron_plugin_agent == "openvswitch"
+    - enable_nova_fake | bool
 
 - name: Starting Neutron-linuxbridge-agent container
   docker:
diff --git a/ansible/roles/neutron/templates/ml2_conf.ini.j2 b/ansible/roles/neutron/templates/ml2_conf.ini.j2
index 061d4d52c9..90049c8b17 100644
--- a/ansible/roles/neutron/templates/ml2_conf.ini.j2
+++ b/ansible/roles/neutron/templates/ml2_conf.ini.j2
@@ -48,10 +48,14 @@ arp_responder = true
 
 [ovs]
 bridge_mappings = physnet1:{{ neutron_bridge_name }}
+{% if enable_nova_fake | bool %}
+ovs_integration_bridge = br-int-{{ item }}
+{% endif %}
 {% elif neutron_plugin_agent == "linuxbridge" %}
 [linux_bridge]
 physical_interface_mappings = physnet1:{{ neutron_external_interface }}
 
+
 [vxlan]
 l2_population = true
 {% endif %}
diff --git a/ansible/roles/neutron/templates/neutron.conf.j2 b/ansible/roles/neutron/templates/neutron.conf.j2
index a80349cc52..91e93cca63 100644
--- a/ansible/roles/neutron/templates/neutron.conf.j2
+++ b/ansible/roles/neutron/templates/neutron.conf.j2
@@ -20,6 +20,11 @@ interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
 interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver
 {% endif %}
 
+{% if enable_nova_fake | bool %}
+ovs_integration_bridge = br-int-{{ item }}
+host = {{ ansible_hostname }}_{{ item }}
+{% endif %}
+
 allow_overlapping_ips = true
 core_plugin = ml2
 service_plugins = router
diff --git a/ansible/roles/nova/tasks/config-nova-fake.yml b/ansible/roles/nova/tasks/config-nova-fake.yml
new file mode 100644
index 0000000000..9992932ac4
--- /dev/null
+++ b/ansible/roles/nova/tasks/config-nova-fake.yml
@@ -0,0 +1,27 @@
+---
+- name: Ensuring config directories exist
+  file:
+    path: "{{ node_config_directory }}/nova-compute-fake-{{ item }}"
+    state: "directory"
+    recurse: yes
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+
+- name: Copying over config.json files for services
+  template:
+    src: "roles/nova/templates/nova-compute.json.j2"
+    dest: "{{ node_config_directory }}/nova-compute-fake-{{ item }}/config.json"
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+
+- name: Copying over nova.conf
+  merge_configs:
+    vars:
+      service_name: "{{ item }}"
+    sources:
+      - "{{ role_path }}/templates/nova.conf.j2"
+      - "/etc/kolla/config/global.conf"
+      - "/etc/kolla/config/database.conf"
+      - "/etc/kolla/config/messaging.conf"
+      - "/etc/kolla/config/nova.conf"
+      - "/etc/kolla/config/nova/{{ item }}.conf"
+    dest: "{{ node_config_directory }}/nova-compute-fake-{{ item }}/nova.conf"
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
diff --git a/ansible/roles/nova/tasks/main.yml b/ansible/roles/nova/tasks/main.yml
index 748a19f843..f72e6e2193 100644
--- a/ansible/roles/nova/tasks/main.yml
+++ b/ansible/roles/nova/tasks/main.yml
@@ -21,6 +21,11 @@
         inventory_hostname in groups['nova-novncproxy'] or
         inventory_hostname in groups['nova-scheduler']
 
+- include: config-nova-fake.yml
+  when:
+    - enable_nova_fake | bool
+    - inventory_hostname in groups['compute']
+
 - include: bootstrap.yml
   when: inventory_hostname in groups['nova-api']
 
diff --git a/ansible/roles/nova/tasks/start.yml b/ansible/roles/nova/tasks/start.yml
index 277b0309ec..cc0a6632e1 100644
--- a/ansible/roles/nova/tasks/start.yml
+++ b/ansible/roles/nova/tasks/start.yml
@@ -201,7 +201,9 @@
       - nova_data
     env:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
-  when: inventory_hostname in groups['compute']
+  when:
+    - inventory_hostname in groups['compute']
+    - not enable_nova_fake | bool
 
 - name: Starting Nova-compute-ironic container
   docker:
@@ -226,3 +228,30 @@
   when:
     - inventory_hostname in groups['nova-compute-ironic']
     - enable_ironic | bool
+
+- name: Starting fake Nova-compute containers
+  docker:
+    tty: True
+    net: host
+    pull: "{{ docker_pull_policy }}"
+    restart_policy: "{{ docker_restart_policy }}"
+    restart_policy_retry: "{{ docker_restart_policy_retry }}"
+    state: reloaded
+    registry: "{{ docker_registry }}"
+    username: "{{ docker_registry_username }}"
+    password: "{{ docker_registry_password }}"
+    insecure_registry: "{{ docker_insecure_registry }}"
+    privileged: True
+    name: nova_compute_fake_{{ item }}
+    image: "{{ nova_compute_image_full }}"
+    volumes:
+      - "{{ node_config_directory }}/nova-compute-fake-{{ item }}/:{{ container_config_directory }}/:ro"
+      - "/lib/modules:/lib/modules:ro"
+      - "/run:/run"
+      - "/var/lib/kolla/dev/log:/dev/log"
+    env:
+      KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+  with_sequence: start=1 end={{ num_nova_fake_per_node }}
+  when:
+    - inventory_hostname in groups['compute']
+    - enable_nova_fake | bool
diff --git a/ansible/roles/nova/templates/nova.conf.j2 b/ansible/roles/nova/templates/nova.conf.j2
index 1d7e95772f..e9b60eb4d7 100644
--- a/ansible/roles/nova/templates/nova.conf.j2
+++ b/ansible/roles/nova/templates/nova.conf.j2
@@ -41,6 +41,10 @@ compute_driver = nova.virt.ironic.IronicDriver
 vnc_enabled = False
 ram_allocation_ratio = 1.0
 reserved_host_memory_mb = 0
+{% elif enable_nova_fake | bool %}
+scheduler_default_filters = RetryFilter,AvailabilityZoneFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter
+host = {{ ansible_hostname }}_{{ item }}
+compute_driver = fake.FakeDriver
 {% else %}
 compute_driver = libvirt.LibvirtDriver
 {% endif %}
diff --git a/doc/nova-fake-driver.rst b/doc/nova-fake-driver.rst
new file mode 100644
index 0000000000..33f46bead5
--- /dev/null
+++ b/doc/nova-fake-driver.rst
@@ -0,0 +1,34 @@
+Nova Fake Driver
+================
+
+One common question from OpenStack operators is that "how does the control plane
+(e.g., database, messaging queue, nova-scheduler ) scales?". To answer this
+question, operators setup Rally to drive workload to the OpenStack cloud.
+However, without a large number of nova-compute nodes, it becomes difficult to
+exercise the control performance.
+
+Given the built-in feature of Docker container, Kolla enables standing up many
+many of nova-compute nodes with nova fake driver on a single host. For example,
+we can create 100 nova-compute containers on a real host to simulate the
+100-hypervisor workload to the nova-conductor and the messaging queue.
+
+Use nova-fake driver
+---------------------
+
+Nova fake driver can not work with all-in-one deployment. This is because the
+fake neutron-openvswitch-agent for the fake nova-compute container conflicts
+with neutron-openvswitch-agent on the compute nodes. Therefore, in the inventory
+the network node must be different than the compute node.
+
+By default, Kolla uses libvirt driver on the compute node. To use nova-fake
+driver, edit the following parameters in ansible/group_vars or in the
+command line options.
+
+::
+
+  enable_nova_fake: "yes"
+  num_nova_fake_per_node: 5
+
+Each compute nodes will run 5 nova-compute containers and 5
+neutron-plugin-agent containers. When booting instance, there will be no
+real instances created. But "nova list" shows the fake instances.