Model generator from cookiecutter-templates

Change-Id: I1ae23b812125b975849f0ba8fadeca2844547970
diff --git a/tcp_tests/templates/cookied-bm-mcp-ocata-contrail/salt-context-environment.yaml b/tcp_tests/templates/cookied-bm-mcp-ocata-contrail/salt-context-environment.yaml
index 98eaa56..6f29def 100644
--- a/tcp_tests/templates/cookied-bm-mcp-ocata-contrail/salt-context-environment.yaml
+++ b/tcp_tests/templates/cookied-bm-mcp-ocata-contrail/salt-context-environment.yaml
@@ -235,11 +235,11 @@
         ens3:

           role: single_ctl

 

-    bmk01.cookied-bm-mcp-ocata-contrail.local:

-      reclass_storage_name: openstack_benchmark_node01

-      roles:

-      - openstack_benchmark

-      - linux_system_codename_xenial

-      interfaces:

-        ens3:

-          role: single_ctl

+#    bmk01.cookied-bm-mcp-ocata-contrail.local:

+#      reclass_storage_name: openstack_benchmark_node01

+#      roles:

+#      - openstack_benchmark

+#      - linux_system_codename_xenial

+#      interfaces:

+#        ens3:

+#          role: single_ctl

diff --git a/tcp_tests/templates/cookied-model-generator/run_test.sh b/tcp_tests/templates/cookied-model-generator/run_test.sh
new file mode 100755
index 0000000..213afea
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/run_test.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+. /home/jenkins/fuel-devops30/bin/activate
+
+export ENV_NAME=model-generator
+export VENV_PATH=/home/jenkins/fuel-devops30
+# Image must be uploaded to the storage pool
+export CFG01_DAY01_VOLUME_NAME=cfg01-day01.qcow2
+export SHUTDOWN_ENV_ON_TEARDOWN=true
+export PYTHONIOENCODING=UTF-8
+export REPOSITORY_SUITE=testing
+
+export LAB_CONFIG_NAME=cookied-model-generator
+export LAB_CONTEXT_NAME=cookied-mcp-ocata-dop-sl2
+#export LAB_CONTEXT_NAME=cookied-mcp-ocata-dvr-vxlan
+#export LAB_CONTEXT_NAME=cookied-bm-mcp-dvr-vxlan
+#export LAB_CONTEXT_NAME=cookied-bm-mcp-ocata-contrail
+
+export DOMAIN_NAME=${LAB_CONTEXT_NAME}.local
+export SALT_STEPS_PATH=templates/${LAB_CONFIG_NAME}/salt_${LAB_CONTEXT_NAME}.yaml
+
+export TEST_GROUP=test_generate_model
+
+export STORAGE_POOL_NAME=second_pool
+
+export MAKE_SNAPSHOT_STAGES=false
+
+dos.py erase ${ENV_NAME}
+
+cd tcp_tests
+py.test -vvv -s -p no:django -p no:ipdb --junit-xml=nosetests.xml -k ${TEST_GROUP}
diff --git a/tcp_tests/templates/cookied-model-generator/salt_cookied-bm-mcp-dvr-vxlan.yaml b/tcp_tests/templates/cookied-model-generator/salt_cookied-bm-mcp-dvr-vxlan.yaml
new file mode 100644
index 0000000..1dad209
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/salt_cookied-bm-mcp-dvr-vxlan.yaml
@@ -0,0 +1,63 @@
+{% from 'cookied-model-generator/underlay.yaml' import HOSTNAME_CFG01 with context %}
+{% from 'cookied-model-generator/underlay.yaml' import DOMAIN_NAME with context %}
+
+{% set LAB_CONFIG_NAME = 'cookied-bm-mcp-dvr-vxlan' %}
+# Name of the context file (without extension, that is fixed .yaml) used to render the Environment model
+{% set ENVIRONMENT_MODEL_INVENTORY_NAME = os_env('ENVIRONMENT_MODEL_INVENTORY_NAME','cookied-bm-mcp-dvr-vxlan') %}
+# Path to the context files used to render Cluster and Environment models
+{%- set CLUSTER_CONTEXT_NAME = 'salt-context-cookiecutter-openstack_ovs_dvr_vxlan.yaml' %}
+{%- set ENVIRONMENT_CONTEXT_NAMES = ['salt-context-vcp-environment.yaml', 'salt-context-lab03-environment.yaml'] %}
+{%- set CONTROL_VLAN = os_env('CONTROL_VLAN', '2416') %}
+{%- set TENANT_VLAN = os_env('TENANT_VLAN', '2417') %}
+
+{% import 'shared-salt.yaml' as SHARED with context %}
+
+{{ SHARED.MACRO_GENERATE_COOKIECUTTER_MODEL(CONTROL_VLAN=CONTROL_VLAN, TENANT_VLAN=TENANT_VLAN) }}
+
+{{ SHARED.MACRO_GENERATE_AND_ENABLE_ENVIRONMENT_MODEL() }}
+
+- description: Temporary WR for cinder backend defined by default in reclass.system
+  cmd: |
+    sed -i 's/backend\:\ {}//g' /srv/salt/reclass/classes/system/cinder/control/cluster.yml;
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: false
+
+- description: "Workaround for rack01 compute generator"
+  cmd: |
+    set -e;
+    . /root/venv-reclass-tools/bin/activate;
+    # Remove rack01 key
+    reclass-tools del-key parameters.reclass.storage.node.openstack_compute_rack01 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+
+    # Add openstack_compute_node definition from system
+    reclass-tools add-key 'classes' 'system.reclass.storage.system.openstack_compute_multi' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml --merge;
+
+    # Set ipaddresses for our nodes
+    reclass-tools add-key parameters._param.openstack_compute_node01_control_address 10.167.4.3 /srv/salt/reclass/classes/cluster/cookied-bm-mcp-dvr-vxlan/infra/config.yml;
+    reclass-tools add-key parameters._param.openstack_compute_node02_control_address 10.167.4.31 /srv/salt/reclass/classes/cluster/cookied-bm-mcp-dvr-vxlan/infra/config.yml;
+    reclass-tools add-key parameters._param.openstack_compute_node01_tenant_address 10.167.6.3 /srv/salt/reclass/classes/cluster/cookied-bm-mcp-dvr-vxlan/infra/config.yml;
+    reclass-tools add-key parameters._param.openstack_compute_node02_tenant_address 10.167.6.31 /srv/salt/reclass/classes/cluster/cookied-bm-mcp-dvr-vxlan/infra/config.yml;
+
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 10}
+  skip_fail: false
+
+- description: Temporary workaround for removing cinder-volume from CTL nodes
+  cmd: |
+    sed -i 's/\-\ system\.cinder\.volume\.single//g' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/openstack/control.yml;
+    sed -i 's/\-\ system\.cinder\.volume\.notification\.messagingv2//g' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/openstack/control.yml;
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: true
+
+#- description: Refresh pillars and install dependencies for salt-master
+#  cmd: |
+#    salt '*' saltutil.refresh_pillar; sleep 5;
+#    salt '*' state.sls salt.master;
+#    salt '*' saltutil.refresh_pillar; sleep 5;
+#  node_name: {{ HOSTNAME_CFG01 }}
+#  retry: {count: 1, delay: 5}
+#  skip_fail: false
+
+{{ SHARED.MACRO_GENERATE_INVENTORY(RERUN_SALTMASTER_STATE=true) }}
diff --git a/tcp_tests/templates/cookied-model-generator/salt_cookied-bm-mcp-ocata-contrail.yaml b/tcp_tests/templates/cookied-model-generator/salt_cookied-bm-mcp-ocata-contrail.yaml
new file mode 100644
index 0000000..f8714ff
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/salt_cookied-bm-mcp-ocata-contrail.yaml
@@ -0,0 +1,64 @@
+{% from 'cookied-model-generator/underlay.yaml' import HOSTNAME_CFG01 with context %}
+{% from 'cookied-model-generator/underlay.yaml' import DOMAIN_NAME with context %}
+
+{% set LAB_CONFIG_NAME = 'cookied-bm-mcp-ocata-contrail' %}
+# Name of the context file (without extension, that is fixed .yaml) used to render the Environment model
+{% set ENVIRONMENT_MODEL_INVENTORY_NAME = os_env('ENVIRONMENT_MODEL_INVENTORY_NAME','physical-cookied-bm-mcp-ocata-contrail') %}
+# Path to the context files used to render Cluster and Environment models
+{%- set CLUSTER_CONTEXT_NAME = 'salt-context-cookiecutter-contrail-dpdk.yaml' %}
+{%- set ENVIRONMENT_CONTEXT_NAMES = ['salt-context-environment.yaml','lab04-physical-inventory.yaml'] %}
+{%- set CONTROL_VLAN = os_env('CONTROL_VLAN', '2422') %}
+{%- set TENANT_VLAN = os_env('TENANT_VLAN', '2423') %}
+
+{% import 'shared-salt.yaml' as SHARED with context %}
+
+{{ SHARED.MACRO_GENERATE_COOKIECUTTER_MODEL(CONTROL_VLAN=CONTROL_VLAN, TENANT_VLAN=TENANT_VLAN) }}
+
+{{ SHARED.MACRO_GENERATE_AND_ENABLE_ENVIRONMENT_MODEL() }}
+
+- description: Temporary WR for cinder backend defined by default in reclass.system
+  cmd: |
+    sed -i 's/backend\:\ {}//g' /srv/salt/reclass/classes/system/cinder/control/cluster.yml;
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: false
+
+- description: "Workaround for rack01 compute generator"
+  cmd: |
+    set -e;
+    . /root/venv-reclass-tools/bin/activate;
+    # Remove rack01 key
+    reclass-tools del-key parameters.reclass.storage.node.openstack_compute_rack01 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    # Add openstack_compute_node definition from system
+    reclass-tools add-key 'classes' 'system.reclass.storage.system.openstack_compute_multi' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml --merge;
+
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 10}
+  skip_fail: false
+
+
+- description: Temporary workaround for removing cinder-volume from CTL nodes
+  cmd: |
+    sed -i 's/\-\ system\.cinder\.volume\.single//g' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/openstack/control.yml;
+    sed -i 's/\-\ system\.cinder\.volume\.notification\.messagingv2//g' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/openstack/control.yml;
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: true
+
+{{ SHARED.MACRO_GENERATE_INVENTORY(RERUN_SALTMASTER_STATE=true) }}
+
+- description: "Workaround for PROD-14060"
+  cmd: |
+    set -e;
+    # Add tenant and single addresses for computes
+    salt-call reclass.cluster_meta_set deploy_address 172.16.49.72 /srv/salt/reclass/nodes/_generated/cmp001.cookied-bm-mcp-ocata-contrail.local.yml
+    salt-call reclass.cluster_meta_set tenant_address 192.168.0.101 /srv/salt/reclass/nodes/_generated/cmp001.cookied-bm-mcp-ocata-contrail.local.yml
+    salt-call reclass.cluster_meta_set single_address 10.167.8.101 /srv/salt/reclass/nodes/_generated/cmp001.cookied-bm-mcp-ocata-contrail.local.yml
+
+    salt-call reclass.cluster_meta_set deploy_address 172.16.49.74 /srv/salt/reclass/nodes/_generated/cmp002.cookied-bm-mcp-ocata-contrail.local.yml
+    salt-call reclass.cluster_meta_set tenant_address 192.168.0.102 /srv/salt/reclass/nodes/_generated/cmp002.cookied-bm-mcp-ocata-contrail.local.yml
+    salt-call reclass.cluster_meta_set single_address 10.167.8.102 /srv/salt/reclass/nodes/_generated/cmp002.cookied-bm-mcp-ocata-contrail.local.yml
+
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 10}
+  skip_fail: false
diff --git a/tcp_tests/templates/cookied-model-generator/salt_cookied-mcp-ocata-dop-sl2.yaml b/tcp_tests/templates/cookied-model-generator/salt_cookied-mcp-ocata-dop-sl2.yaml
new file mode 100644
index 0000000..9dd5f9a
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/salt_cookied-mcp-ocata-dop-sl2.yaml
@@ -0,0 +1,44 @@
+{% from 'cookied-model-generator/underlay.yaml' import HOSTNAME_CFG01 with context %}
+{% from 'cookied-model-generator/underlay.yaml' import DOMAIN_NAME with context %}
+
+{% set SALT_MODELS_REPOSITORY = os_env('SALT_MODELS_REPOSITORY','https://gerrit.mcp.mirantis.net/salt-models/mcp-virtual-lab') %}
+# Other salt model repository parameters see in shared-salt.yaml
+
+{% set LAB_CONFIG_NAME = 'cookied-mcp-ocata-dop-sl2' %}
+# Name of the context file (without extension, that is fixed .yaml) used to render the Environment model
+{% set ENVIRONMENT_MODEL_INVENTORY_NAME = os_env('ENVIRONMENT_MODEL_INVENTORY_NAME', LAB_CONFIG_NAME) %}
+# Path to the context files used to render Cluster and Environment models
+{%- set CLUSTER_CONTEXT_NAME = 'salt-context-cookiecutter-cicd_oss.yaml' %}
+{%- set ENVIRONMENT_CONTEXT_NAMES = ['salt-context-environment.yaml'] %}
+
+{% import 'shared-salt.yaml' as SHARED with context %}
+
+{{ SHARED.MACRO_GENERATE_COOKIECUTTER_MODEL() }}
+
+{{ SHARED.MACRO_GENERATE_AND_ENABLE_ENVIRONMENT_MODEL() }}
+
+- description: "Workaround for combined roles: remove unnecessary classes"
+  cmd: |
+    set -e;
+    sed -i '/system.reclass.storage.system.physical_control_cluster/d' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    sed -i '/system.reclass.storage.system.openstack_database_cluster/d' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    sed -i '/system.reclass.storage.system.openstack_message_queue_cluster/d' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    sed -i '/system.reclass.storage.system.stacklight_telemetry_cluster/d' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    sed -i '/system.reclass.storage.system.stacklight_log_cluster/d' /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+
+    . /root/venv-reclass-tools/bin/activate;
+    reclass-tools del-key parameters.reclass.storage.node.infra_kvm_node01 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.infra_kvm_node02 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.infra_kvm_node03 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.openstack_database_node01 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.openstack_database_node02 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.openstack_database_node03 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.openstack_message_queue_node01 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.openstack_message_queue_node02 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.openstack_message_queue_node03 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+    reclass-tools del-key parameters.reclass.storage.node.stacklight_log_node01 /srv/salt/reclass/classes/cluster/{{ LAB_CONFIG_NAME }}/infra/config.yml;
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: false
+
+{{ SHARED.MACRO_GENERATE_INVENTORY(RERUN_SALTMASTER_STATE=true) }}
diff --git a/tcp_tests/templates/cookied-model-generator/salt_cookied-mcp-ocata-dvr-vxlan.yaml b/tcp_tests/templates/cookied-model-generator/salt_cookied-mcp-ocata-dvr-vxlan.yaml
new file mode 100644
index 0000000..d404b3a
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/salt_cookied-mcp-ocata-dvr-vxlan.yaml
@@ -0,0 +1,17 @@
+{% from 'cookied-model-generator/underlay.yaml' import HOSTNAME_CFG01 with context %}
+{% from 'cookied-model-generator/underlay.yaml' import DOMAIN_NAME with context %}
+
+{% set LAB_CONFIG_NAME = 'cookied-mcp-ocata-dvr-vxlan' %}
+# Name of the context file (without extension, that is fixed .yaml) used to render the Environment model
+{% set ENVIRONMENT_MODEL_INVENTORY_NAME = os_env('ENVIRONMENT_MODEL_INVENTORY_NAME', LAB_CONFIG_NAME) %}
+# Path to the context files used to render Cluster and Environment models
+{%- set CLUSTER_CONTEXT_NAME = 'salt-context-cookiecutter-openstack_ovs_dvr_vxlan.yaml' %}
+{%- set ENVIRONMENT_CONTEXT_NAMES = ['salt-context-environment.yaml'] %}
+
+{% import 'shared-salt.yaml' as SHARED with context %}
+
+{{ SHARED.MACRO_GENERATE_COOKIECUTTER_MODEL() }}
+
+{{ SHARED.MACRO_GENERATE_AND_ENABLE_ENVIRONMENT_MODEL() }}
+
+{{ SHARED.MACRO_GENERATE_INVENTORY(RERUN_SALTMASTER_STATE=true) }}
diff --git a/tcp_tests/templates/cookied-model-generator/underlay--meta-data.yaml b/tcp_tests/templates/cookied-model-generator/underlay--meta-data.yaml
new file mode 100644
index 0000000..3699401
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/underlay--meta-data.yaml
@@ -0,0 +1,4 @@
+| # All the data below will be stored as a string object
+  instance-id: iid-local1
+  hostname: {hostname}
+  local-hostname: {hostname}
diff --git a/tcp_tests/templates/cookied-model-generator/underlay--user-data-cfg01.yaml b/tcp_tests/templates/cookied-model-generator/underlay--user-data-cfg01.yaml
new file mode 100644
index 0000000..1b5c90d
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/underlay--user-data-cfg01.yaml
@@ -0,0 +1,96 @@
+| # All the data below will be stored as a string object
+  #cloud-config, see http://cloudinit.readthedocs.io/en/latest/topics/examples.html
+
+  ssh_pwauth: True
+  users:
+   - name: root
+     sudo: ALL=(ALL) NOPASSWD:ALL
+     shell: /bin/bash
+     ssh_authorized_keys:
+     {% for key in config.underlay.ssh_keys %}
+      - ssh-rsa {{ key['public'] }}
+     {% endfor %}
+
+  disable_root: false
+  chpasswd:
+   list: |
+    root:r00tme
+   expire: False
+
+  bootcmd:
+   # Block access to SSH while node is preparing
+   - cloud-init-per once sudo iptables -A INPUT -p tcp --dport 22 -j DROP
+   # Enable root access
+   - sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin yes/' /etc/ssh/sshd_config
+   - service sshd restart
+  output:
+    all: '| tee -a /var/log/cloud-init-output.log /dev/tty0'
+
+  runcmd:
+   # Prepare network connection
+   - sudo ifdown ens3
+   - sudo ifup ens3
+   #- sudo route add default gw {gateway} {interface_name}
+
+   # Configure dhclient
+   - sudo echo "nameserver {gateway}" >> /etc/resolvconf/resolv.conf.d/base
+   - sudo resolvconf -u
+
+   # Enable grub menu using updated config below
+   - update-grub
+
+   # Create swap
+   #- fallocate -l 16G /swapfile
+   #- chmod 600 /swapfile
+   #- mkswap /swapfile
+   #- swapon /swapfile
+   #- echo "/swapfile   none    swap    defaults    0   0" >> /etc/fstab
+
+   ############## TCP Cloud cfg01 node ##################
+   - echo "Preparing base OS"
+
+   - echo "nameserver 172.18.208.44" >> /etc/resolv.conf;
+   - echo "nameserver 8.8.8.8" >> /etc/resolv.conf;
+
+   - apt-get clean
+   - apt-get update
+
+   # Ensure that the salt-master service is ready to receive requests
+   - salt-key -y -D
+   - service salt-master restart
+   - service salt-minion restart
+   - salt-call --timeout=180 test.ping
+
+   ########################################################
+   # Node is ready, allow SSH access
+   - echo "Allow SSH access ..."
+   - sudo iptables -D INPUT -p tcp --dport 22 -j DROP
+   ########################################################
+
+  write_files:
+   - path: /etc/default/grub.d/97-enable-grub-menu.cfg
+     content: |
+         GRUB_RECORDFAIL_TIMEOUT=30
+         GRUB_TIMEOUT=3
+         GRUB_TIMEOUT_STYLE=menu
+
+   - path: /etc/network/interfaces
+     content: |
+          auto ens3
+          iface ens3 inet dhcp
+
+   - path: /root/.ssh/config
+     owner: root:root
+     permissions: '0600'
+     content: |
+          Host *
+            ServerAliveInterval 300
+            ServerAliveCountMax 10
+            StrictHostKeyChecking no
+            UserKnownHostsFile /dev/null
+
+   # Fix hardcoded IP address in the minion.conf
+   - path: /etc/salt/minion.d/minion.conf
+     content: |
+          master: 127.0.0.1
+          id: cfg01.{{ DOMAIN_NAME }}
diff --git a/tcp_tests/templates/cookied-model-generator/underlay.yaml b/tcp_tests/templates/cookied-model-generator/underlay.yaml
new file mode 100644
index 0000000..6a3ceff
--- /dev/null
+++ b/tcp_tests/templates/cookied-model-generator/underlay.yaml
@@ -0,0 +1,86 @@
+# Set the repository suite, one of the: 'nightly', 'testing', 'stable', or any other required
+{% set REPOSITORY_SUITE = os_env('REPOSITORY_SUITE', 'testing') %}
+
+{% set LAB_CONFIG_NAME = os_env('LAB_CONFIG_NAME', 'cookied-model-generator') %}
+{% set DOMAIN_NAME = os_env('DOMAIN_NAME', LAB_CONFIG_NAME + '.local') %}
+{% set HOSTNAME_CFG01 = os_env('HOSTNAME_CFG01', 'cfg01.' + DOMAIN_NAME) %}
+
+{% import 'cookied-model-generator/underlay--meta-data.yaml' as CLOUDINIT_META_DATA with context %}
+{% import 'cookied-model-generator/underlay--user-data-cfg01.yaml' as CLOUDINIT_USER_DATA_CFG01 with context %}
+
+---
+aliases:
+ - &interface_model {{ os_env('INTERFACE_MODEL', 'virtio') }}
+ - &cloudinit_meta_data {{ CLOUDINIT_META_DATA }}
+ - &cloudinit_user_data_cfg01 {{ CLOUDINIT_USER_DATA_CFG01 }}
+
+template:
+  devops_settings:
+    env_name: {{ os_env('ENV_NAME', LAB_CONFIG_NAME + '_' + REPOSITORY_SUITE + "_" + os_env('BUILD_NUMBER', '')) }}
+
+    address_pools:
+      admin-pool01:
+        net: {{ os_env('ADMIN_ADDRESS_POOL01', '10.70.0.0/16:24') }}
+        params:
+          ip_reserved:
+            gateway: +1
+            l2_network_device: +1
+            default_{{ HOSTNAME_CFG01 }}: +15
+          ip_ranges:
+            dhcp: [+90, -10]
+
+    groups:
+      - name: default
+        driver:
+          name: devops.driver.libvirt
+          params:
+            connection_string: {{ os_env('CONNECTION_STRING', 'qemu:///system') }}
+            storage_pool_name: {{ os_env('STORAGE_POOL_NAME', 'default') }}
+            stp: False
+            hpet: False
+            enable_acpi: true
+            use_host_cpu: {{ os_env('DRIVER_USE_HOST_CPU', true) }}
+            use_hugepages: {{ os_env('DRIVER_USE_HUGEPAGES', false) }}
+
+        network_pools:
+          admin: admin-pool01
+
+        l2_network_devices:
+          admin:
+            address_pool: admin-pool01
+            dhcp: true
+            forward:
+              mode: nat
+
+        nodes:
+          - name: {{ HOSTNAME_CFG01 }}
+            role: salt_master
+            params:
+              vcpu: {{ os_env('CFG_NODE_CPU', 4) }}
+              memory: {{ os_env('CFG_NODE_MEMORY', 4096) }}
+              boot:
+                - hd
+              cloud_init_volume_name: iso
+              cloud_init_iface_up: ens3
+              volumes:
+                - name: system
+                  capacity: {{ os_env('CFG_NODE_VOLUME_SIZE', 150) }}
+                  shared_backing_store_name: {{ os_env('CFG01_DAY01_VOLUME_NAME') }}
+                  format: qcow2
+                - name: iso  # Volume with name 'iso' will be used
+                             # for store image with cloud-init metadata.
+                  capacity: 1
+                  format: raw
+                  device: cdrom
+                  bus: ide
+                  cloudinit_meta_data: *cloudinit_meta_data
+                  cloudinit_user_data: *cloudinit_user_data_cfg01
+
+              interfaces:
+                - label: ens3
+                  l2_network_device: admin
+                  interface_model: *interface_model
+              network_config:
+                ens3:
+                  networks:
+                    - admin
diff --git a/tcp_tests/templates/shared-salt.yaml b/tcp_tests/templates/shared-salt.yaml
index 33abf12..0ad2ac0 100644
--- a/tcp_tests/templates/shared-salt.yaml
+++ b/tcp_tests/templates/shared-salt.yaml
@@ -407,6 +407,14 @@
   retry: {count: 1, delay: 1}
   skip_fail: false
 
+- description: Refresh pillars for environment class
+  cmd: |
+    set -e;
+    salt-call saltutil.refresh_pillar; sleep 5;
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: false
+
 {%- endmacro %}
 
 
@@ -599,8 +607,15 @@
   skip_fail: false
 {%- endmacro %}
 
-{%- macro MACRO_GENERATE_INVENTORY() %}
-{#####################################}
+{%- macro MACRO_GENERATE_INVENTORY(RERUN_SALTMASTER_STATE=false) %}
+{#################################################################}
+
+- description: Refresh pillars before generating nodes
+  cmd: salt --hard-crash --state-output=mixed --state-verbose=False '*' saltutil.refresh_pillar
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: false
+
 - description: Generate inventory for all the nodes to the /srv/salt/reclass/nodes/_generated
   cmd: salt --hard-crash --state-output=mixed --state-verbose=False
     -C 'I@salt:master' state.sls reclass
@@ -608,8 +623,19 @@
   retry: {count: 1, delay: 5}
   skip_fail: false
 
+{%- if RERUN_SALTMASTER_STATE %}
+- description: Regenerate salt.master states for the newly uploaded/created model
+  cmd: |
+    # Need to refresh installed formulas that are required in the model
+    salt --hard-crash --state-output=mixed --state-verbose=False '*' saltutil.refresh_pillar; sleep 5;
+    salt --hard-crash --state-output=mixed --state-verbose=False -C 'I@salt:master' state.sls salt.master;
+  node_name: {{ HOSTNAME_CFG01 }}
+  retry: {count: 1, delay: 5}
+  skip_fail: false
+{%- endif %}
+
 - description: Refresh pillars on all minions
-  cmd: salt --hard-crash --state-output=mixed --state-verbose=False '*' saltutil.refresh_pillar
+  cmd: salt --hard-crash --state-output=mixed --state-verbose=False '*' saltutil.refresh_pillar; sleep 5
   node_name: {{ HOSTNAME_CFG01 }}
   retry: {count: 1, delay: 5}
   skip_fail: false
diff --git a/tcp_tests/tests/environment/test_generate_model.py b/tcp_tests/tests/environment/test_generate_model.py
new file mode 100644
index 0000000..a936bb5
--- /dev/null
+++ b/tcp_tests/tests/environment/test_generate_model.py
@@ -0,0 +1,79 @@
+#    Copyright 2017 Mirantis, Inc.
+#
+#    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.
+
+import pytest
+import os
+
+from tcp_tests import logger
+from tcp_tests import settings
+from tcp_tests.helpers import ext
+
+LOG = logger.logger
+
+
+class TestGenerateModel(object):
+    """Test class that generates and checks a cluster model"""
+
+    @pytest.mark.fail_snapshot
+    def test_generate_model(self, config, underlay, salt_actions):
+        config.salt.salt_master_host = \
+            underlay.host_by_node_role(
+                node_role=ext.UNDERLAY_NODE_ROLES.salt_master)
+
+        commands = underlay.read_template(config.salt_deploy.salt_steps_path)
+        salt_actions.install(commands)
+
+        node_name = underlay.get_target_node_names('cfg01.')[0]
+        arch_model_name = 'model_{0}.tar.gz'.format(settings.ENV_NAME)
+        commands = [
+            {
+                'description': "Copy generated model to /root/reclass",
+                'node_name': node_name,
+                'cmd': ('cp -r /srv/salt/reclass/ /root/;'
+                        'rm -rf /root/reclass/classes/service/;'
+                        'rm -rf /root/reclass/classes/system/;')},
+            {
+                'description': ("Archive the model to the /root/{0}"
+                                .format(arch_model_name)),
+                'node_name': node_name,
+                'cmd': ('cd /root/reclass/;'
+                        'tar --warning=no-file-changed -czf /root/{0} ./'
+                        .format(arch_model_name))},
+            {
+                'description': "Download the model to the host",
+                'node_name': node_name,
+                'download': {
+                    'remote_path': '/root/',
+                    'remote_filename': arch_model_name,
+                    'local_path': os.getcwd()
+                }},
+        ]
+
+        salt_actions.execute_commands(commands=commands,
+                                      label="Get the model from the cfg01")
+
+
+#        tar_cmd = (
+#            'cp -r /srv/salt/reclass/ /root/;'
+#            'rm -rf /root/reclass/classes/service/;'
+#            'rm -rf /root/reclass/classes/system/;'
+#            'cd /root/reclass/;'
+#            'tar --warning=no-file-changed -czf /root/model_{0}.tar.gz ./'
+#            .format(settings.ENV_NAME))
+#        with underlay.remote(host=config.salt.salt_master_host) as r:
+#            r.check_call(tar_cmd, verbose=True)
+#            r.download('model_{0}.tar.gz'.format(settings.ENV_NAME),
+#                       os.getcwd())
+
+        LOG.info("*************** DONE **************")