# -*- coding: utf-8 -*- # # Copyright 2015 Red Hat, Inc. # All Rights Reserved. # # 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 os import time from oslo_concurrency import processutils from oslo_log import log from oslo_utils import uuidutils from ironic_python_agent import errors from ironic_python_agent.extensions import base from ironic_python_agent import hardware from ironic_python_agent import utils LOG = log.getLogger(__name__) def _execute(cmd, error_msg, check_exit_code=None): if check_exit_code is None: check_exit_code = [0] try: stdout, stderr = utils.execute(*cmd, check_exit_code=check_exit_code) except processutils.ProcessExecutionError as e: LOG.error(error_msg) raise errors.ISCSIError(error_msg, e.exit_code, e.stdout, e.stderr) def _wait_for_iscsi_daemon(interval=1, attempts=10): """Wait for the ISCSI daemon to start.""" for attempt in range(attempts): if os.path.exists("/var/run/tgtd.ipc_abstract_namespace.0"): break time.sleep(interval) else: error_msg = "ISCSI daemon didn't initialize" LOG.error(error_msg) raise errors.ISCSIError(error_msg, 1, '', error_msg) def _start_iscsi_daemon(iqn, device): """Start a ISCSI target for the device.""" LOG.debug("Starting ISCSI target on device %(device)s", {'device': device}) # Start ISCSI Target daemon _execute(['tgtd'], "Unable to start the ISCSI daemon") _wait_for_iscsi_daemon() cmd = ['tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'new', '--tid', '1', '--targetname', iqn] _execute(cmd, "Error when adding a new target for iqn %s" % iqn) cmd = ['tgtadm', '--lld', 'iscsi', '--mode', 'logicalunit', '--op', 'new', '--tid', '1', '--lun', '1', '--backing-store', device] _execute(cmd, "Error when adding a new logical unit for iqn %s" % iqn) cmd = ['tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'bind', '--tid', '1', '--initiator-address', 'ALL'] _execute(cmd, "Error when enabling the target to accept the specific " "initiators for iqn %s" % iqn) class ISCSIExtension(base.BaseAgentExtension): @base.sync_command('start_iscsi_target') def start_iscsi_target(self, iqn=None): """Expose the disk as an ISCSI target.""" # If iqn is not given, generate one if iqn is None: iqn = 'iqn-' + uuidutils.generate_uuid() device = hardware.dispatch_to_managers('get_os_install_device') _start_iscsi_daemon(iqn, device) return {"iscsi_target_iqn": iqn}