From Fedora Project Wiki
No edit summary
No edit summary
Line 350: Line 350:
         )
         )


--
1.8.3.1
__EOF__
</pre>
<pre>
[stack@oscloud5 ~]$ (cd /usr/lib/python2.7/site-packages/tripleo_common/; cat << '__EOF__' | sudo git am)
From 9b8312d8940fdda85e5049629f860d9a4c19110d Mon Sep 17 00:00:00 2001
From: root <root@oscloud5.stglabs.ibm.com>
Date: Wed, 1 Nov 2017 16:56:35 +0000
Subject: [PATCH] tripleo_common
---
actions/baremetal.py  |  9 ++-------
actions/validations.py | 45 ++++++++++++++++++++++++++++++++++++++-------
utils/nodes.py        | 37 +++++++++++++++++++++++++++----------
3 files changed, 67 insertions(+), 24 deletions(-)
diff --git a/actions/baremetal.py b/actions/baremetal.py
index dc73355..979752c 100644
--- a/actions/baremetal.py
+++ b/actions/baremetal.py
@@ -43,14 +43,11 @@ class RegisterOrUpdateNodes(base.TripleOAction):
    :return: list of node objects representing the new nodes.
    """
-    def __init__(self, nodes_json, remove=False, kernel_name=None,
-                ramdisk_name=None, instance_boot_option='local'):
+    def __init__(self, nodes_json, remove=False, instance_boot_option='local'):
        super(RegisterOrUpdateNodes, self).__init__()
        self.nodes_json = nodes_json
        self.remove = remove
        self.instance_boot_option = instance_boot_option
-        self.kernel_name = kernel_name
-        self.ramdisk_name = ramdisk_name
    def run(self, context):
        for node in self.nodes_json:
@@ -67,9 +64,7 @@ class RegisterOrUpdateNodes(base.TripleOAction):
                self.nodes_json,
                client=baremetal_client,
                remove=self.remove,
-                glance_client=image_client,
-                kernel_name=self.kernel_name,
-                ramdisk_name=self.ramdisk_name)
+                glance_client=image_client)
        except Exception as err:
            LOG.exception("Error registering nodes with ironic.")
            return actions.Result(error=six.text_type(err))
diff --git a/actions/validations.py b/actions/validations.py
index 017f99d..28ae86c 100644
--- a/actions/validations.py
+++ b/actions/validations.py
@@ -265,31 +265,62 @@ class CheckNodeBootConfigurationAction(base.TripleOAction):
    # TODO(bcrochet): The validation actions are temporary. This logic should
    #                move to the tripleo-validations project eventually.
-    def __init__(self, node, kernel_id, ramdisk_id):
+    def __init__(self, node, images):
        super(CheckNodeBootConfigurationAction, self).__init__()
        self.node = node
-        self.kernel_id = kernel_id
-        self.ramdisk_id = ramdisk_id
+        self.images = images
+
+    def _check_for_image(self, name):
+        found_images = [item['id'] for item in self.images
+                        if item['name'] == name]
+        if len(found_images) == 1:
+            return found_images[0]
+        else:
+            return None
    def run(self, context):
        warnings = []
        errors = []
+
+        cpu_arch = None
+        if self.node is None:
+            errors.append("self.node is None ")
+        elif 'properties' in self.node:
+            if 'cpu_arch' in self.node['properties']:
+                cpu_arch = self.node['properties']['cpu_arch']
+            else:
+                errors.append("cpu_arch not in properties (%s) " % self.node['properties'])
+        else:
+            errors.append("properties not in node (%s)" % self.node)
+
+        kernel_name = 'bm-deploy-kernel'
+        ramdisk_name = 'bm-deploy-ramdisk'
+        if cpu_arch is not None:
+            kernel_name = cpu_arch+'-bm-deploy-kernel'
+            ramdisk_name = cpu_arch+'-bm-deploy-ramdisk'
+        kernel_id = self._check_for_image(kernel_name)
+        ramdisk_id = self._check_for_image(ramdisk_name)
+        if kernel_id is None:
+            errors.append("kernel_id = %s, kernel_name = %s" % (kernel_id,kernel_name,))
+        if ramdisk_id is None:
+            errors.append("ramdisk_id = %s, ramdisk_name= %s" % (ramdisk_id,ramdisk_name,))
+
        message = ("Node {uuid} has an incorrectly configured "
                    "{property}. Expected \"{expected}\" but got "
                    "\"{actual}\".")
-        if self.node['driver_info'].get('deploy_ramdisk') != self.ramdisk_id:
+        if self.node['driver_info'].get('deploy_ramdisk') != ramdisk_id:
            errors.append(message.format(
                uuid=self.node['uuid'],
                property='driver_info/deploy_ramdisk',
-                expected=self.ramdisk_id,
+                expected=ramdisk_id,
                actual=self.node['driver_info'].get('deploy_ramdisk')
            ))
-        if self.node['driver_info'].get('deploy_kernel') != self.kernel_id:
+        if self.node['driver_info'].get('deploy_kernel') != kernel_id:
            errors.append(message.format(
                uuid=self.node['uuid'],
                property='driver_info/deploy_kernel',
-                expected=self.kernel_id,
+                expected=kernel_id,
                actual=self.node['driver_info'].get('deploy_kernel')
            ))
        capabilities = nodeutils.capabilities_to_dict(
diff --git a/utils/nodes.py b/utils/nodes.py
index 0d93804..edad508 100644
--- a/utils/nodes.py
+++ b/utils/nodes.py
@@ -23,6 +23,9 @@ from oslo_concurrency import processutils
from tripleo_common import exception
from tripleo_common.utils import glance
+from glanceclient.v2.client import Client as real_glance_client
+from glanceclient import exc as exceptions
+
LOG = logging.getLogger(__name__)
_KNOWN_INTERFACE_FIELDS = [
@@ -449,8 +452,7 @@ def _clean_up_extra_nodes(seen, client, remove=False):
            LOG.debug('Extra registered node %s found.' % node)
-def register_all_nodes(nodes_list, client, remove=False, glance_client=None,
-                      kernel_name=None, ramdisk_name=None):
+def register_all_nodes(nodes_list, client, remove=False, glance_client=None):
    """Register all nodes in nodes_list in the baremetal service.
    :param nodes_list: The list of nodes to register.
@@ -465,17 +467,32 @@ def register_all_nodes(nodes_list, client, remove=False, glance_client=None,
    LOG.debug('Registering all nodes.')
    node_map = _populate_node_mapping(client)
-    glance_ids = {'kernel': None, 'ramdisk': None}
-    if kernel_name and ramdisk_name:
-        glance_ids = glance.create_or_find_kernel_and_ramdisk(
-            glance_client, kernel_name, ramdisk_name)
+    def find_image(name, format):
+        if not isinstance(glance_client, real_glance_client):
+            raise exceptions.NotFound("MARK1")
+
+        images = glance_client.images.list(name=name,
+                                          disk_format=format)
+        for img in images:
+            if img['name'] == name and img['disk_format'] == format:
+                return img['id']
+        return None
    seen = []
    for node in nodes_list:
-        if glance_ids['kernel'] and 'kernel_id' not in node:
-            node['kernel_id'] = glance_ids['kernel']
-        if glance_ids['ramdisk'] and 'ramdisk_id' not in node:
+
+        kernel_id = find_image(name=node['arch']+'-bm-deploy-kernel',
+                              format='aki')
+        if not kernel_id:
+            raise exceptions.NotFound("No image found for "+kernel_name)
+
+        ramdisk_id = find_image(name=node['arch']+'-bm-deploy-ramdisk',
+                                format='ari')
+        if not ramdisk_id:
+            raise exceptions.NotFound("No image found for "+ramdisk_name)
+
+        node['kernel_id'] = kernel_id
+        node['ramdisk_id'] = ramdisk_id
        node = _update_or_register_ironic_node(node, node_map, client=client)
        seen.append(node)
--  
--  
1.8.3.1
1.8.3.1

Revision as of 15:53, 3 November 2017

On a CentOS7 system

[hamzy@oscloud5 ~]$ lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description:    CentOS Linux release 7.3.1611 (Core) 
Release:        7.3.1611
Codename:       Core
[stack@oscloud5 ~]$ uname -a
Linux oscloud5.stglabs.ibm.com 3.10.0-514.16.1.el7.x86_64 #1 SMP Wed Apr 12 15:04:24 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Unfortunately, it seems that Environment setup for baremetal environment does not explain how to install the undercloud. There are three machines in this scenario:

arch use portname1 MAC1 IP1 portname2 MAC2 IP2
x86_64 undercloud eno2 6c:ae:8b:29:2a:02 9.114.219.30 eno4 6c:ae:8b:29:2a:04 9.114.118.98
x86_64 overcloud control eth??? 00:0a:f7:73:3c:c3 9.114.219.134 eth??? 6c:ae:8b:29:27:fa 9.114.118.??? 13?
ppc64le overcloud compute enP3p5s0f2 00:90:fa:74:05:52 9.114.219.49 enP3p5s0f3 00:90:fa:74:05:53 9.114.118.154

So, following Undercloud installation, I perform the following:

[hamzy@oscloud5 ~]$ sudo useradd stack
[hamzy@oscloud5 ~]$ sudo passwd stack
[hamzy@oscloud5 ~]$ echo "stack ALL=(root) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/stack
[hamzy@oscloud5 ~]$ sudo chmod 0440 /etc/sudoers.d/stack
[hamzy@oscloud5 ~]$ sudo su - stack
[stack@oscloud5 ~]$ sudo hostnamectl set-hostname oscloud5.stglabs.ibm.com
[stack@oscloud5 ~]$ sudo hostnamectl set-hostname --transient oscloud5.stglabs.ibm.com
[stack@oscloud5 ~]$ sudo curl -L -o /etc/yum.repos.d/delorean.repo https://trunk.rdoproject.org/centos7-master/current-passed-ci/delorean.repo
[stack@oscloud5 ~]$ sudo curl -L -o /etc/yum.repos.d/delorean-deps.repo https://trunk.rdoproject.org/centos7/delorean-deps.repo
[stack@oscloud5 ~]$ sudo yum install -y python-tripleoclient
[stack@oscloud5 ~]$ cp /usr/share/instack-undercloud/undercloud.conf.sample ~/undercloud.conf
[stack@oscloud5 ~]$ cat << '__EOF__' > instackenv.json
{
    "nodes": [
        {
            "pm_type":"pxe_ipmitool",
            "mac":[
                "5c:f3:fc:36:dd:68"
            ],
            "cpu":"2",
            "memory":"1048576",
            "disk":"1000",
            "arch":"x86_64",
            "pm_user":"user",
            "pm_password":"update",
            "pm_addr":"9.114.219.33"
        },
        {
            "pm_type":"pxe_ipmitool",
            "mac":[
                "00:90:fa:74:05:53"
            ],
            "cpu":"16",
            "memory":"1048576",
            "disk":"1000",
            "arch":"ppc64le",
            "pm_password":"update",
            "pm_addr":"9.114.118.155"
        }
    ]
}
__EOF__

I transfer over the built ppc64le overcloud images:

[hamzy@pkvmci853 ~]$ (OCB=$(dig @192.168.122.1 -4 +short Overcloud.virbr0); UC=9.114.118.98; ssh-keygen -f ~/.ssh/known_hosts -R ${UC}; ssh-keyscan ${UC} >> ~/.ssh/known_hosts; scp -3 hamzy@${OCB}:~/ironic-python-agent.initramfs stack@${UC}:~/ppc64le-bm-deploy-ramdisk; scp -3 hamzy@${OCB}:~/ironic-python-agent.kernel stack@${UC}:~/ppc64le-bm-deploy-kernel; scp -3 hamzy@${OCB}:~/overcloud-full.qcow2 stack@${UC}:~/ppc64le-overcloud-full.qcow2; scp -3 hamzy@${OCB}:~/overcloud-full.initrd stack@${UC}:~/ppc64le-overcloud-full.initrd; scp -3 hamzy@${OCB}:~/overcloud-full.kernel stack@${UC}:~/ppc64le-overcloud-full.kernel)

I then transfer over the built x86_64 overcloud images:

[stack@oscloud5 ~]$ wget --quiet -O - https://images.rdoproject.org/pike/rdo_trunk/d558d6173970736fde63526da6824d391ada6042_89d45961/ironic-python-agent.tar | tar xvf -
[stack@oscloud5 ~]$ wget --quiet -O - https://images.rdoproject.org/pike/rdo_trunk/d558d6173970736fde63526da6824d391ada6042_89d45961/overcloud-full.tar | tar xvf -
[stack@oscloud5 ~]$ for FILE in ironic-python-agent.initramfs ironic-python-agent.kernel overcloud-full.initrd overcloud-full.vmlinuz overcloud-full.qcow2; do mv ${FILE} x86_64-${FILE}; done

I then modify undercloud.conf as follows:

[stack@oscloud5 ~]$ cat << __EOF__ | patch -p0
--- undercloud.conf.orig        2017-08-25 12:04:54.935063830 +0000
+++ undercloud.conf 2017-08-25 12:05:17.561063576 +0000
@@ -17,21 +17,25 @@
 # defined by local_interface, with the netmask defined by the prefix
 # portion of the value. (string value)
 #local_ip = 192.168.24.1/24
+local_ip = 9.114.118.98/24
 
 # Network gateway for the Neutron-managed network for Overcloud
 # instances. This should match the local_ip above when using
 # masquerading. (string value)
 #network_gateway = 192.168.24.1
+network_gateway = 9.114.118.98
 
 # Virtual IP or DNS address to use for the public endpoints of
 # Undercloud services. Only used with SSL. (string value)
 # Deprecated group/name - [DEFAULT]/undercloud_public_vip
 #undercloud_public_host = 192.168.24.2
+undercloud_public_host = 9.114.118.98
 
 # Virtual IP or DNS address to use for the admin endpoints of
 # Undercloud services. Only used with SSL. (string value)
 # Deprecated group/name - [DEFAULT]/undercloud_admin_vip
 #undercloud_admin_host = 192.168.24.3
+undercloud_admin_host = 9.114.118.98
 
 # DNS nameserver(s) to use for the undercloud node. (list value)
 #undercloud_nameservers =
@@ -74,6 +78,7 @@
 # Network interface on the Undercloud that will be handling the PXE
 # boots and DHCP for Overcloud instances. (string value)
 #local_interface = eth1
+local_interface = eno4
 
 # MTU to use for the local_interface. (integer value)
 #local_mtu = 1500
@@ -82,18 +87,22 @@
 # instances. This should be the subnet used for PXE booting. (string
 # value)
 #network_cidr = 192.168.24.0/24
+network_cidr = 9.114.118.0/24
 
 # Network that will be masqueraded for external access, if required.
 # This should be the subnet used for PXE booting. (string value)
 #masquerade_network = 192.168.24.0/24
+masquerade_network = 9.114.118.0/24
 
 # Start of DHCP allocation range for PXE and DHCP of Overcloud
 # instances. (string value)
 #dhcp_start = 192.168.24.5
+dhcp_start = 9.114.118.240
 
 # End of DHCP allocation range for PXE and DHCP of Overcloud
 # instances. (string value)
 #dhcp_end = 192.168.24.24
+dhcp_end = 9.114.118.248
 
 # Path to hieradata override file. If set, the file will be copied
 # under /etc/puppet/hieradata and set as the first file in the hiera
@@ -112,12 +121,14 @@
 # doubt, use the default value. (string value)
 # Deprecated group/name - [DEFAULT]/discovery_interface
 #inspection_interface = br-ctlplane
+inspection_interface = br-ctlplane
 
 # Temporary IP range that will be given to nodes during the inspection
 # process.  Should not overlap with the range defined by dhcp_start
 # and dhcp_end, but should be in the same network. (string value)
 # Deprecated group/name - [DEFAULT]/discovery_iprange
 #inspection_iprange = 192.168.24.100,192.168.24.120
+inspection_iprange = 9.114.118.249,9.114.118.250
 
 # Whether to enable extra hardware collection during the inspection
 # process. Requires python-hardware or python-hardware-detect package
__EOF__

And install the undercloud:

[stack@oscloud5 ~]$ time openstack undercloud install 2>&1 | tee output.undercloud.install
...
Undercloud install complete.
...

Prepare your system for some patches...

[stack@oscloud5 ~]$ (cd /usr/share/openstack-tripleo-common/; sudo git init .; sudo find . | xargs sudo git add; sudo git commit -m "base")
[stack@oscloud5 ~]$ (cd /usr/lib/python2.7/site-packages/tripleoclient/; sudo git init .; sudo find . -not -iname \*.pyc -and -not -iname \*.pyo | xargs sudo git add; sudo git commit -m "base")
[stack@oscloud5 ~]$ (cd /usr/lib/python2.7/site-packages/tripleo_common/; sudo git init .; sudo find . -not -iname \*.pyc -and -not -iname \*.pyo | xargs sudo git add; sudo git commit -m "base")

There is a bug for needing the userid for machines using ipmi that needs to be patched around.

[stack@oscloud5 ~]$ (cd /usr/lib/python2.7/site-packages/tripleo_common/; cat << '__EOF__' | sudo git am)
From ceb4796a442990dc99917a83a2c6bf502fe71fbf Mon Sep 17 00:00:00 2001
From: root <root@oscloud5.stglabs.ibm.com>
Date: Fri, 3 Nov 2017 15:31:41 +0000
Subject: [PATCH] fix usernameless IPMI

---
 utils/nodes.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/utils/nodes.py b/utils/nodes.py
index d160a00..0d93804 100644
--- a/utils/nodes.py
+++ b/utils/nodes.py
@@ -105,7 +105,7 @@ class PrefixedDriverInfo(DriverInfo):
             'pm_user': '%s_username' % prefix,
             'pm_password': '%s_password' % prefix,
         }
-        mandatory_fields = list(mapping)
+        mandatory_fields = ['pm_addr', 'pm_password'] # list(mapping)
 
         if has_port:
             mapping['pm_port'] = '%s_port' % prefix
-- 
1.8.3.1
__EOF__

There is a bug for hardcoded ironic-python-agent and overcloud names:

[stack@oscloud5 ~]$ (cd /usr/share/openstack-tripleo-common/; cat << '__EOF__' | sudo git am)
From 139ca1ef0fc589da608edde67f66c4b398b7bff0 Mon Sep 17 00:00:00 2001
From: root <root@oscloud5.stglabs.ibm.com>
Date: Wed, 1 Nov 2017 16:52:00 +0000
Subject: [PATCH] openstack-tripleo-common

---
 workbooks/baremetal.yaml   |  4 ----
 workbooks/validations.yaml | 13 ++++++++-----
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/workbooks/baremetal.yaml b/workbooks/baremetal.yaml
index 90bca8a..e1f978d 100644
--- a/workbooks/baremetal.yaml
+++ b/workbooks/baremetal.yaml
@@ -147,8 +147,6 @@ workflows:
      - nodes_json
      - remove: False
      - queue_name: tripleo
-     - kernel_name: null
-     - ramdisk_name: null
      - instance_boot_option: local
      - initial_state: manageable

@@ -181,8 +179,6 @@ workflows:
         input:
            nodes_json: <% $.nodes_json %>
            remove: <% $.remove %>
-           kernel_name: <% $.kernel_name %>
-           ramdisk_name: <% $.ramdisk_name %>
            instance_boot_option: <% $.instance_boot_option %>
         publish:
           registered_nodes: <% task(register_or_update_nodes).result %>
diff --git a/workbooks/validations.yaml b/workbooks/validations.yaml
index 5cb9ad7..1799ee5 100644
--- a/workbooks/validations.yaml
+++ b/workbooks/validations.yaml
@@ -400,8 +400,6 @@ workflows:

   check_ironic_boot_configuration:
     input:
-      - kernel_id: null
-      - ramdisk_id: null
       - run_validations: true
       - queue_name: tripleo
     output:
@@ -419,7 +417,7 @@ workflows:

       get_ironic_nodes:
         action: ironic.node_list
-        on-success: check_node_boot_configuration
+        on-success: get_images
         on-error: failed_get_ironic_nodes
         input:
           provision_state: available
@@ -434,12 +432,17 @@ workflows:
           status: FAILED
           message: <% task(get_ironic_nodes).result %>

+      get_images:
+        action: glance.images_list
+        on-success: check_node_boot_configuration
+        publish:
+          images: <% task(get_images).result %>
+
       check_node_boot_configuration:
         action: tripleo.validations.check_node_boot_configuration
         input:
           node: <% $.node %>
-          kernel_id: <% $.kernel_id %>
-          ramdisk_id: <% $.ramdisk_id %>
+          images: <% $.images %>
         with-items: node in <% $.nodes %>
         on-success: send_message
         on-error: fail_check_node_boot_configuration
-- 
1.8.3.1
__EOF__
[stack@oscloud5 ~]$ (cd /usr/lib/python2.7/site-packages/tripleoclient/; cat << '__EOF__' | sudo git am)
From 475ed6c45a9f63b6596ce155f4aeb19ad8e135a0 Mon Sep 17 00:00:00 2001
From: root <root@oscloud5.stglabs.ibm.com>
Date: Wed, 1 Nov 2017 16:56:13 +0000
Subject: [PATCH] tripleoclient

---
 v1/overcloud_node.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/v1/overcloud_node.py b/v1/overcloud_node.py
index e354f8e..13d60af 100644
--- a/v1/overcloud_node.py
+++ b/v1/overcloud_node.py
@@ -221,8 +221,6 @@ class ImportNode(command.Command):
             self.app.client_manager,
             nodes_json=nodes_config,
             queue_name=queue_name,
-            kernel_name=deploy_kernel,
-            ramdisk_name=deploy_ramdisk,
             instance_boot_option=parsed_args.instance_boot_option
         )

-- 
1.8.3.1
__EOF__
[stack@oscloud5 ~]$ (cd /usr/lib/python2.7/site-packages/tripleo_common/; cat << '__EOF__' | sudo git am)
From 9b8312d8940fdda85e5049629f860d9a4c19110d Mon Sep 17 00:00:00 2001
From: root <root@oscloud5.stglabs.ibm.com>
Date: Wed, 1 Nov 2017 16:56:35 +0000
Subject: [PATCH] tripleo_common

---
 actions/baremetal.py   |  9 ++-------
 actions/validations.py | 45 ++++++++++++++++++++++++++++++++++++++-------
 utils/nodes.py         | 37 +++++++++++++++++++++++++++----------
 3 files changed, 67 insertions(+), 24 deletions(-)

diff --git a/actions/baremetal.py b/actions/baremetal.py
index dc73355..979752c 100644
--- a/actions/baremetal.py
+++ b/actions/baremetal.py
@@ -43,14 +43,11 @@ class RegisterOrUpdateNodes(base.TripleOAction):
     :return: list of node objects representing the new nodes.
     """

-    def __init__(self, nodes_json, remove=False, kernel_name=None,
-                 ramdisk_name=None, instance_boot_option='local'):
+    def __init__(self, nodes_json, remove=False, instance_boot_option='local'):
         super(RegisterOrUpdateNodes, self).__init__()
         self.nodes_json = nodes_json
         self.remove = remove
         self.instance_boot_option = instance_boot_option
-        self.kernel_name = kernel_name
-        self.ramdisk_name = ramdisk_name

     def run(self, context):
         for node in self.nodes_json:
@@ -67,9 +64,7 @@ class RegisterOrUpdateNodes(base.TripleOAction):
                 self.nodes_json,
                 client=baremetal_client,
                 remove=self.remove,
-                glance_client=image_client,
-                kernel_name=self.kernel_name,
-                ramdisk_name=self.ramdisk_name)
+                glance_client=image_client)
         except Exception as err:
             LOG.exception("Error registering nodes with ironic.")
             return actions.Result(error=six.text_type(err))
diff --git a/actions/validations.py b/actions/validations.py
index 017f99d..28ae86c 100644
--- a/actions/validations.py
+++ b/actions/validations.py
@@ -265,31 +265,62 @@ class CheckNodeBootConfigurationAction(base.TripleOAction):

     # TODO(bcrochet): The validation actions are temporary. This logic should
     #                 move to the tripleo-validations project eventually.
-    def __init__(self, node, kernel_id, ramdisk_id):
+    def __init__(self, node, images):
         super(CheckNodeBootConfigurationAction, self).__init__()

         self.node = node
-        self.kernel_id = kernel_id
-        self.ramdisk_id = ramdisk_id
+        self.images = images
+
+    def _check_for_image(self, name):
+        found_images = [item['id'] for item in self.images
+                        if item['name'] == name]
+        if len(found_images) == 1:
+            return found_images[0]
+        else:
+            return None

     def run(self, context):
         warnings = []
         errors = []
+
+        cpu_arch = None
+        if self.node is None:
+            errors.append("self.node is None ")
+        elif 'properties' in self.node:
+            if 'cpu_arch' in self.node['properties']:
+                cpu_arch = self.node['properties']['cpu_arch']
+            else:
+                errors.append("cpu_arch not in properties (%s) " % self.node['properties'])
+        else:
+            errors.append("properties not in node (%s)" % self.node)
+
+        kernel_name = 'bm-deploy-kernel'
+        ramdisk_name = 'bm-deploy-ramdisk'
+        if cpu_arch is not None:
+            kernel_name = cpu_arch+'-bm-deploy-kernel'
+            ramdisk_name = cpu_arch+'-bm-deploy-ramdisk'
+        kernel_id = self._check_for_image(kernel_name)
+        ramdisk_id = self._check_for_image(ramdisk_name)
+        if kernel_id is None:
+            errors.append("kernel_id = %s, kernel_name = %s" % (kernel_id,kernel_name,))
+        if ramdisk_id is None:
+            errors.append("ramdisk_id = %s, ramdisk_name= %s" % (ramdisk_id,ramdisk_name,))
+
         message = ("Node {uuid} has an incorrectly configured "
                    "{property}. Expected \"{expected}\" but got "
                    "\"{actual}\".")
-        if self.node['driver_info'].get('deploy_ramdisk') != self.ramdisk_id:
+        if self.node['driver_info'].get('deploy_ramdisk') != ramdisk_id:
             errors.append(message.format(
                 uuid=self.node['uuid'],
                 property='driver_info/deploy_ramdisk',
-                expected=self.ramdisk_id,
+                expected=ramdisk_id,
                 actual=self.node['driver_info'].get('deploy_ramdisk')
             ))
-        if self.node['driver_info'].get('deploy_kernel') != self.kernel_id:
+        if self.node['driver_info'].get('deploy_kernel') != kernel_id:
             errors.append(message.format(
                 uuid=self.node['uuid'],
                 property='driver_info/deploy_kernel',
-                expected=self.kernel_id,
+                expected=kernel_id,
                 actual=self.node['driver_info'].get('deploy_kernel')
             ))
         capabilities = nodeutils.capabilities_to_dict(
diff --git a/utils/nodes.py b/utils/nodes.py
index 0d93804..edad508 100644
--- a/utils/nodes.py
+++ b/utils/nodes.py
@@ -23,6 +23,9 @@ from oslo_concurrency import processutils
 from tripleo_common import exception
 from tripleo_common.utils import glance

+from glanceclient.v2.client import Client as real_glance_client
+from glanceclient import exc as exceptions
+
 LOG = logging.getLogger(__name__)

 _KNOWN_INTERFACE_FIELDS = [
@@ -449,8 +452,7 @@ def _clean_up_extra_nodes(seen, client, remove=False):
             LOG.debug('Extra registered node %s found.' % node)


-def register_all_nodes(nodes_list, client, remove=False, glance_client=None,
-                       kernel_name=None, ramdisk_name=None):
+def register_all_nodes(nodes_list, client, remove=False, glance_client=None):
     """Register all nodes in nodes_list in the baremetal service.

     :param nodes_list: The list of nodes to register.
@@ -465,17 +467,32 @@ def register_all_nodes(nodes_list, client, remove=False, glance_client=None,
     LOG.debug('Registering all nodes.')
     node_map = _populate_node_mapping(client)

-    glance_ids = {'kernel': None, 'ramdisk': None}
-    if kernel_name and ramdisk_name:
-        glance_ids = glance.create_or_find_kernel_and_ramdisk(
-            glance_client, kernel_name, ramdisk_name)
+    def find_image(name, format):
+        if not isinstance(glance_client, real_glance_client):
+            raise exceptions.NotFound("MARK1")
+
+        images = glance_client.images.list(name=name,
+                                           disk_format=format)
+        for img in images:
+            if img['name'] == name and img['disk_format'] == format:
+                return img['id']
+        return None

     seen = []
     for node in nodes_list:
-        if glance_ids['kernel'] and 'kernel_id' not in node:
-            node['kernel_id'] = glance_ids['kernel']
-        if glance_ids['ramdisk'] and 'ramdisk_id' not in node:
+
+        kernel_id = find_image(name=node['arch']+'-bm-deploy-kernel',
+                               format='aki')
+        if not kernel_id:
+            raise exceptions.NotFound("No image found for "+kernel_name)
+
+        ramdisk_id = find_image(name=node['arch']+'-bm-deploy-ramdisk',
+                                format='ari')
+        if not ramdisk_id:
+            raise exceptions.NotFound("No image found for "+ramdisk_name)
+
+        node['kernel_id'] = kernel_id
+        node['ramdisk_id'] = ramdisk_id

         node = _update_or_register_ironic_node(node, node_map, client=client)
         seen.append(node)
-- 
1.8.3.1
__EOF__
[stack@undercloud ~]$ (for SERVICE in openstack-mistral-api.service openstack-mistral-engine.service openstack-mistral-executor.service; do sudo systemctl restart ${SERVICE}; done)

Ironic needs some different settings to be able to support PXE for ppc64le:

[stack@oscloud5 ~]$ (cd /etc/ironic; cat << '__EOF__' | sudo patch -p0)
--- ironic.conf.orig    2017-11-03 13:54:06.440644679 +0000
+++ ironic.conf 2017-11-03 15:01:47.584431653 +0000
@@ -343,6 +343,7 @@
 # for this option to be unset. (string value)
 # Allowed values: debug, info, warning, error, critical
 #notification_level = <None>
+notification_level = debug
 
 # Directory where the ironic python module is installed.
 # (string value)
@@ -3506,7 +3507,7 @@
 # On ironic-conductor node, template file for PXE
 # configuration. (string value)
 #pxe_config_template = $pybasedir/drivers/modules/pxe_config.template
-pxe_config_template=$pybasedir/drivers/modules/ipxe_config.template
+pxe_config_template=$pybasedir/drivers/modules/pxe_config.template
 
 # On ironic-conductor node, template file for PXE
 # configuration for UEFI boot loader. (string value)
@@ -3517,6 +3518,7 @@
 # configuration per node architecture. For example:
 # aarch64:/opt/share/grubaa64_pxe_config.template (dict value)
 #pxe_config_template_by_arch =
+pxe_config_template_by_arch = ppc64le:$pybasedir/drivers/modules/pxe_config.template
 
 # IP address of ironic-conductor node's TFTP server. (string
 # value)
@@ -3547,7 +3549,7 @@
 
 # Bootfile DHCP parameter. (string value)
 #pxe_bootfile_name = pxelinux.0
-pxe_bootfile_name=undionly.kpxe
+pxe_bootfile_name=pxelinux.0
 
 # Bootfile DHCP parameter for UEFI boot mode. (string value)
 #uefi_pxe_bootfile_name = bootx64.efi
@@ -3556,10 +3558,11 @@
 # Bootfile DHCP parameter per node architecture. For example:
 # aarch64:grubaa64.efi (dict value)
 #pxe_bootfile_name_by_arch =
+pxe_bootfile_name_by_arch = ppc64le:config
 
 # Enable iPXE boot. (boolean value)
 #ipxe_enabled = false
-ipxe_enabled=True
+ipxe_enabled = false
 
 # On ironic-conductor node, the path to the main iPXE script
 # file. (string value)
__EOF__
[stack@oscloud5 ~]$ for I in openstack-ironic-conductor.service openstack-ironic-inspector.service openstack-ironic-inspector-dnsmasq.service; do sudo systemctl restart ${I}; done

I then go through the process of installing the overcloud:

[stack@oscloud5 ~]$ source stackrc
(undercloud) [stack@oscloud5 ~]$ time openstack overcloud image upload
...

The overcloud-full qcow2 image needs to be recreated in glance so that it loses both the kernel_id and the ramdisk_id. This way a full disk image can be deployed.

(undercloud) [stack@oscloud5 ~]$ (FILE="overcloud-full.qcow2"; UUID=$(openstack image list -f value | grep 'overcloud-full ' | awk '{print $1;}'); openstack image delete ${UUID}; openstack image create --container-format bare --disk-format qcow2 --min-disk 0 --min-ram 0 --file ${FILE} --public overcloud-full)

Now import the baremetal nodes and assign them profiles.

(undercloud) [stack@oscloud5 ~]$ time openstack overcloud node import --provide instackenv.json 2>&1 | tee output.overcloud.node.import
...
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| Node UUID                            | Node Name | Provision State | Current Profile | Possible Profiles |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| ff2fdac5-6cc5-47a9-a095-d942b3960795 |           | available       | None            |                   |
| ef3d7b3b-97b8-42ab-b501-896474df658f |           | available       | None            |                   |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
(undercloud) [stack@oscloud5 ~]$ (COMPUTE=""; CONTROL=""; while IFS=$' ' read -r -a PROFILES; do NODE=${PROFILES[0]}; ARCH=$(openstack baremetal node show --fields properties --format shell ${NODE} | sed -r -e "s,^.*cpu_arch': u'([^']*).*$,\1,"); echo "ARCH=${ARCH} NODE=${NODE}"; if [ -z "${COMPUTE}" -a "${ARCH}" == "ppc64le" ]; then COMPUTE=${NODE}; echo "Compute:"; ironic node-update ${COMPUTE} replace properties/capabilities=profile:compute,boot_option:local; continue; elif [ -z "${CONTROL}" -a "${ARCH}" == "x86_64" ]; then CONTROL=${PROFILES[0]}; echo "Control:"; ironic node-update ${CONTROL} replace properties/capabilities=profile:control,boot_option:local; continue; else echo "Error: ${NODE}"; openstack baremetal node show --fields properties --format shell ${NODE}; fi; done < <(openstack overcloud profiles list -f value))
(undercloud) [stack@oscloud5 ~]$ openstack overcloud profiles list
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| Node UUID                            | Node Name | Provision State | Current Profile | Possible Profiles |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| ff2fdac5-6cc5-47a9-a095-d942b3960795 |           | available       | compute         |                   |
| ef3d7b3b-97b8-42ab-b501-896474df658f |           | available       | control         |                   |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+

Patch the openstack-tripleo-heat-templates locally with our configuration and then do the deploy.

(undercloud) [stack@oscloud5 ~]$ cp -r /usr/share/openstack-tripleo-heat-templates templates
(undercloud) [stack@oscloud5 ~]$ (cd templates/; curl --silent -o - https://hamzy.fedorapeople.org/openstack-tripleo-heat-templates.patch | patch -p1)
(undercloud) [stack@oscloud5 ~]$ time openstack overcloud deploy --debug --templates /home/stack/templates -e /home/stack/templates/environments/network-environment.yaml -e /home/stack/templates/environments/network-isolation-custom.yaml --control-scale 1 --compute-scale 1 --control-flavor control --compute-flavor compute 2>&1 | tee output.overcloud.deploy