From: Stanislaw Kardach <stanislaw.kardach@caviumnetworks.com>
Date: Wed, 24 Feb 2016 20:11:54 +0100
Subject: [PATCH] Add arch to nailgun release and target image

This is required so that the TestVM image is created using a cirros
image that is compatible with the architecture of the deployment setup.
As a bonus, it is also used when building the target image.
---
 nailgun/nailgun/consts.py                          |  5 ++
 .../alembic_migrations/versions/armband.py         | 53 ++++++++++++++++++++++
 nailgun/nailgun/db/sqlalchemy/models/release.py    |  8 ++++
 nailgun/nailgun/fixtures/openstack.yaml            |  5 ++
 .../nailgun/orchestrator/deployment_serializers.py |  9 +++-
 .../orchestrator/provisioning_serializers.py       |  3 +-
 nailgun/nailgun/orchestrator/tasks_templates.py    |  5 +-
 .../integration/test_cluster_changes_handler.py    | 12 ++---
 .../integration/test_orchestrator_serializer.py    |  4 +-
 nailgun/nailgun/test/unit/test_tasks_templates.py  |  6 ++-
 10 files changed, 96 insertions(+), 14 deletions(-)
 create mode 100644 nailgun/nailgun/db/migration/alembic_migrations/versions/armband.py

diff --git a/nailgun/nailgun/consts.py b/nailgun/nailgun/consts.py
index 1ded0ba..5a1af0a 100644
--- a/nailgun/nailgun/consts.py
+++ b/nailgun/nailgun/consts.py
@@ -38,6 +38,11 @@ RELEASE_OS = Enum(
     )
 )
 
+RELEASE_ARCHS = Enum(
+    'amd64',
+    'arm64'
+)
+
 CLUSTER_MODES = Enum(
     'multinode',
     'ha_full',
diff --git a/nailgun/nailgun/db/migration/alembic_migrations/versions/armband.py b/nailgun/nailgun/db/migration/alembic_migrations/versions/armband.py
new file mode 100644
index 0000000..8cca69c
--- /dev/null
+++ b/nailgun/nailgun/db/migration/alembic_migrations/versions/armband.py
@@ -0,0 +1,53 @@
+#    Copyright 2016 Cavium, 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.
+
+"""Armband patches
+
+Revision ID: f9b7fd91ac19
+Revises: 43b2cb64dae6
+Create Date: 2016-03-01 23:18:58.712617
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'f9b7fd91ac19'
+down_revision = '43b2cb64dae6'
+
+from alembic import op
+from nailgun.utils.migration import drop_enum
+import sqlalchemy as sa
+
+ENUMS = (
+    'release_arch',
+)
+
+
+def upgrade():
+    add_release_arch()
+
+
+def downgrade():
+    remove_release_arch()
+    map(drop_enum, ENUMS)
+
+
+def add_release_arch():
+    arch_enum = sa.Enum('amd64', 'arm64', name='release_arch')
+    arch_enum.create(op.get_bind(), checkfirst=False)
+    op.add_column('releases', sa.Column('arch', arch_enum, nullable=False,
+                  server_default='amd64'))
+
+
+def remove_release_arch():
+    op.drop_column('releases', 'arch')
diff --git a/nailgun/nailgun/db/sqlalchemy/models/release.py b/nailgun/nailgun/db/sqlalchemy/models/release.py
index 1b47de4..e209e72 100644
--- a/nailgun/nailgun/db/sqlalchemy/models/release.py
+++ b/nailgun/nailgun/db/sqlalchemy/models/release.py
@@ -39,6 +39,14 @@ class Release(Base):
     id = Column(Integer, primary_key=True)
     name = Column(Unicode(100), nullable=False)
     version = Column(String(30), nullable=False)
+    arch = Column(
+        Enum(
+            *consts.RELEASE_ARCHS,
+            name='release_arch'
+        ),
+        nullable=False,
+        default=consts.RELEASE_ARCHS.amd64
+    )
     description = Column(Unicode)
     operating_system = Column(String(50), nullable=False)
     state = Column(
diff --git a/nailgun/nailgun/fixtures/openstack.yaml b/nailgun/nailgun/fixtures/openstack.yaml
index 9674d66..d3226da 100644
--- a/nailgun/nailgun/fixtures/openstack.yaml
+++ b/nailgun/nailgun/fixtures/openstack.yaml
@@ -1904,6 +1904,7 @@
     name: "Mitaka on CentOS 6.5"
     state: "unavailable"
     version: "mitaka-9.0"
+    arch: "amd64"
     operating_system: "CentOS"
     description: "This option will install the OpenStack Mitaka packages using a CentOS based operating system. With high availability features built in, you are getting a robust, enterprise-grade OpenStack deployment."
     attributes_metadata:
@@ -1978,6 +1979,7 @@
   fields:
     name: "Mitaka on Ubuntu 14.04"
     version: "mitaka-9.0"
+    arch: "amd64"
     operating_system: "Ubuntu"
     description: "This option will install the OpenStack Mitaka packages using Ubuntu as a base operating system. With high availability features built in, you are getting a robust, enterprise-grade OpenStack deployment."
     attributes_metadata:
@@ -2219,6 +2221,7 @@
   fields:
     name: "Mitaka on Ubuntu+UCA 14.04"
     version: "mitaka-9.0"
+    arch: "amd64"
     description: "This option will install the OpenStack Mitaka packages using Ubuntu as a base operating system, including Ubuntu Cloud Archive OpenStack packages. With high availability features built in, you are getting a robust, enterprise-grade OpenStack deployment."
     attributes_metadata:
       editable:
@@ -2320,6 +2323,7 @@
   fields:
     name: "Mitaka on Ubuntu 14.04 (aarch64)"
     version: "mitaka-9.0"
+    arch: "arm64"
     operating_system: "Ubuntu"
     description: "This option will install the OpenStack Mitaka packages using Ubuntu as a base operating system. With high availability features built in, you are getting a robust, enterprise-grade OpenStack deployment."
     attributes_metadata:
@@ -2506,6 +2510,7 @@
   fields:
     name: "Mitaka on Ubuntu+UCA 14.04 (aarch64)"
     version: "mitaka-9.0"
+    arch: "arm64"
     description: "This option will install the OpenStack Mitaka packages using Ubuntu as a base operating system, including Ubuntu Cloud Archive OpenStack packages. With high availability features built in, you are getting a robust, enterprise-grade OpenStack deployment."
     attributes_metadata:
       editable:
diff --git a/nailgun/nailgun/orchestrator/deployment_serializers.py b/nailgun/nailgun/orchestrator/deployment_serializers.py
index 699a599..6bb7990 100644
--- a/nailgun/nailgun/orchestrator/deployment_serializers.py
+++ b/nailgun/nailgun/orchestrator/deployment_serializers.py
@@ -300,7 +300,14 @@ class DeploymentMultinodeSerializer(object):
             img_dir = '/usr/share/cirros-testvm/'
         else:
             img_dir = '/opt/vm/'
-        image_data['img_path'] = '{0}cirros-x86_64-disk.img'.format(img_dir)
+        release = self.current_release(node.cluster)
+        arch = release.arch
+        if arch == "amd64":
+            arch = "x86_64"
+        elif arch == "arm64":
+            arch = "aarch64"
+        image_data['img_path'] = '{0}cirros-{1}-disk.img'.format(img_dir,
+            arch)
 
         glance_properties = []
 
diff --git a/nailgun/nailgun/orchestrator/provisioning_serializers.py b/nailgun/nailgun/orchestrator/provisioning_serializers.py
index 48a4753..b1f3ca6 100644
--- a/nailgun/nailgun/orchestrator/provisioning_serializers.py
+++ b/nailgun/nailgun/orchestrator/provisioning_serializers.py
@@ -307,7 +307,8 @@ class ProvisioningSerializer61(ProvisioningSerializer):
                     attrs['repo_setup']['repos'],
                     attrs['provision'],
                     cluster.id,
-                    packages))
+                    packages,
+                    cluster.release.arch))
 
         # NOTE(kozhukalov): This pre-provision task is going to be
         # removed by 7.0 because we need this only for classic way of
diff --git a/nailgun/nailgun/orchestrator/tasks_templates.py b/nailgun/nailgun/orchestrator/tasks_templates.py
index 51dfdf7..bc2bff9 100644
--- a/nailgun/nailgun/orchestrator/tasks_templates.py
+++ b/nailgun/nailgun/orchestrator/tasks_templates.py
@@ -210,7 +210,7 @@ def make_reboot_task(uids, task):
 
 
 def make_provisioning_images_task(
-        uids, repos, provision_data, cid, packages):
+        uids, repos, provision_data, cid, packages, arch):
     conf = {
         'repos': repos,
         'image_data': provision_data['image_data'],
@@ -232,7 +232,8 @@ def make_provisioning_images_task(
                     "--image_build_dir /var/lib/fuel/ibp "
                     "--log-file /var/log/fuel-agent-env-{0}.log "
                     "--data_driver nailgun_build_image "
-                    "--input_data '{1}'").format(cid, conf),
+                    "--target_arch {1} "
+                    "--input_data '{2}'").format(cid, arch, conf),
             'timeout': settings.PROVISIONING_IMAGES_BUILD_TIMEOUT,
             'retries': 1}})
 
diff --git a/nailgun/nailgun/test/integration/test_cluster_changes_handler.py b/nailgun/nailgun/test/integration/test_cluster_changes_handler.py
index 0f212e5..da50eac 100644
--- a/nailgun/nailgun/test/integration/test_cluster_changes_handler.py
+++ b/nailgun/nailgun/test/integration/test_cluster_changes_handler.py
@@ -153,7 +153,7 @@ class TestHandlers(BaseIntegrationTest):
         common_attrs['last_controller'] = controller_nodes[-1]['name']
         common_attrs['storage']['pg_num'] = 128
 
-        common_attrs['test_vm_image'] = {
+        common_attrs['test_vm_image'] = [{
             'container_format': 'bare',
             'public': 'true',
             'disk_format': 'qcow2',
@@ -165,7 +165,7 @@ class TestHandlers(BaseIntegrationTest):
                 """--property murano_image_info="""
                 """'{"title": "Murano Demo", "type": "cirros.demo"}'"""
             ),
-        }
+        }]
 
         critical_mapping = {
             'primary-controller': True,
@@ -565,7 +565,7 @@ class TestHandlers(BaseIntegrationTest):
         common_attrs['last_controller'] = controller_nodes[-1]['name']
         common_attrs['storage']['pg_num'] = 128
 
-        common_attrs['test_vm_image'] = {
+        common_attrs['test_vm_image'] = [{
             'container_format': 'bare',
             'public': 'true',
             'disk_format': 'qcow2',
@@ -577,7 +577,7 @@ class TestHandlers(BaseIntegrationTest):
                 """--property murano_image_info="""
                 """'{"title": "Murano Demo", "type": "cirros.demo"}'"""
             ),
-        }
+        }]
 
         critical_mapping = {
             'primary-controller': True,
@@ -1049,7 +1049,7 @@ class TestHandlers(BaseIntegrationTest):
         common_attrs['last_controller'] = controller_nodes[-1]['name']
         common_attrs['storage']['pg_num'] = 128
 
-        common_attrs['test_vm_image'] = {
+        common_attrs['test_vm_image'] = [{
             'container_format': 'bare',
             'public': 'true',
             'disk_format': 'qcow2',
@@ -1061,7 +1061,7 @@ class TestHandlers(BaseIntegrationTest):
                 """--property murano_image_info="""
                 """'{"title": "Murano Demo", "type": "cirros.demo"}'"""
             ),
-        }
+        }]
 
         critical_mapping = {
             'primary-controller': True,
diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py
index 5db8f4e..ef208cb 100644
--- a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py
+++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py
@@ -2584,12 +2584,12 @@ class BaseDeploymentSerializer(BaseSerializerTest):
 
     def check_no_murano_data(self):
         glance_properties = self.serializer.generate_test_vm_image_data(
-            self.env.nodes[0])['test_vm_image']['glance_properties']
+            self.env.nodes[0])['test_vm_image'][0]['glance_properties']
         self.assertNotIn('murano_image_info', glance_properties)
 
     def check_murano_data(self):
         glance_properties = self.serializer.generate_test_vm_image_data(
-            self.env.nodes[0])['test_vm_image']['glance_properties']
+            self.env.nodes[0])['test_vm_image'][0]['glance_properties']
         self.assertIn('murano_image_info', glance_properties)
 
 
diff --git a/nailgun/nailgun/test/unit/test_tasks_templates.py b/nailgun/nailgun/test/unit/test_tasks_templates.py
index 4e81a19..d657518 100644
--- a/nailgun/nailgun/test/unit/test_tasks_templates.py
+++ b/nailgun/nailgun/test/unit/test_tasks_templates.py
@@ -140,7 +140,8 @@ class TestMakeTask(base.BaseTestCase):
                     }
                 }},
             cid=123,
-            packages=packages
+            packages=packages,
+            arch='amd64'
         )
 
         fuel_image_conf = {
@@ -177,7 +178,8 @@ class TestMakeTask(base.BaseTestCase):
         cmd = result["parameters"]["cmd"].lstrip(
             "fa_build_image --image_build_dir /var/lib/fuel/ibp "
             "--log-file /var/log/fuel-agent-env-123.log "
-            "--data_driver nailgun_build_image --input_data '").rstrip("'")
+            "--data_driver nailgun_build_image --target_arch amd64"
+            " --input_data '").rstrip("'")
         self.assertEqual(jsonutils.loads(cmd), fuel_image_conf)
 
     def test_generate_ironic_bootstrap_keys_task(self):