#!/usr/bin/python # Copyright (c) 2016-2020 Dell Inc. or its subsidiaries. # # 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 argparse import json import logging import os import sys import subprocess import utils from arg_helper import ArgHelper from command_helper import Exec from ironic_helper import IronicHelper from logging_helper import LoggingHelper logging.basicConfig() logger = logging.getLogger(os.path.splitext(os.path.basename(sys.argv[0]))[0]) DOWNSTREAM_ATTRS = ["model", "provisioning_mac", "service_tag"] def parse_arguments(): parser = argparse.ArgumentParser( description="Loads nodes into ironic.", formatter_class=argparse.ArgumentDefaultsHelpFormatter) ArgHelper.add_instack_arg(parser) LoggingHelper.add_argument(parser) return parser.parse_args() def main(): args = parse_arguments() LoggingHelper.configure_logging(args.logging_level) # Load the nodes into ironic import_json = os.path.expanduser('~/nodes.json') content = json.load(open(args.node_definition)) for node in content['nodes']: for k in node.keys(): if k in DOWNSTREAM_ATTRS: node.pop(k) with open(import_json, 'w') as out: json.dump(content, out) logger.info("Importing {} into ironic".format(args.node_definition)) cmd = ["openstack", "overcloud", "node", "import", import_json] exit_code, stdin, stderr = Exec.execute_command(cmd) if exit_code != 0: logger.error("Failed to import nodes into ironic: {}, {}".format( stdin, stderr)) sys.exit(1) # Load the instack file try: json_file = os.path.expanduser(args.node_definition) with open(json_file, 'r') as instackenv_json: instackenv = json.load(instackenv_json) except (IOError, ValueError): logger.exception("Failed to load node definition file {}".format( args.node_definition)) sys.exit(1) nodes = instackenv["nodes"] # Loop thru the nodes for node in nodes: # Find the node in ironic ironic_client = IronicHelper.get_ironic_client() ironic_node = IronicHelper.get_ironic_node(ironic_client, node["pm_addr"]) # Set the model and service tag on the node logger.info("Setting model ({}), service tag ({}), and provisioning " "MAC ({}) on {}".format( node["model"] if "model" in node else "None", node["service_tag"], node["provisioning_mac"] if "provisioning_mac" in node else "None", node["pm_addr"])) patch = [{'op': 'add', 'value': node["service_tag"], 'path': '/properties/service_tag'}] if "model" in node: patch.append({'op': 'add', 'value': node["model"], 'path': '/properties/model'}) if "provisioning_mac" in node: patch.append({'op': 'add', 'value': node["provisioning_mac"], 'path': '/properties/provisioning_mac'}) if utils.Utils.is_enable_routed_networks(): logger.info("Adding port with physical address to node: %s", str(ironic_node.uuid)) kwargs = {'address': node["provisioning_mac"], 'physical_network': 'ctlplane', 'node_uuid': ironic_node.uuid} ironic_client.port.create(**kwargs) ironic_client.node.update(ironic_node.uuid, patch) if __name__ == "__main__": main()