Esempio n. 1
0
    def test_no_retry_on_success(self):
        fd, tmpfilename = tempfile.mkstemp()
        _, tmpfilename2 = tempfile.mkstemp()
        try:
            fp = os.fdopen(fd, 'w+')
            fp.write('''#!/bin/sh
# If we've already run, bail out.
grep -q foo "$1" && exit 1
# Mark that we've run before.
echo foo > "$1"
# Check that stdin gets passed correctly.
grep foo
''')
            fp.close()
            os.chmod(tmpfilename, 0o755)
            try:
                utils.execute(tmpfilename,
                              tmpfilename2,
                              process_input=b'foo',
                              attempts=2)
            except OSError as e:
                if e.errno == errno.EACCES:
                    self.skipTest("Permissions error detected. "
                                  "Are you running with a noexec /tmp?")
                else:
                    raise
        finally:
            os.unlink(tmpfilename)
            os.unlink(tmpfilename2)
Esempio n. 2
0
    def activate_bootloader(self, context, node, instance):
        """Configure Tilera boot loader for an instance

        Kernel and ramdisk images are downloaded by cache_tftp_images,
        and stored in /tftpboot/{uuid}/

        This method writes the instances config file, and then creates
        symlinks for each MAC address in the instance.

        By default, the complete layout looks like this:

        /tftpboot/
            ./{uuid}/
                 kernel
            ./fs_node_id/
        """
        (root_mb, swap_mb) = get_partition_sizes(instance)
        tilera_nfs_path = get_tilera_nfs_path(node['id'])
        image_file_path = get_image_file_path(instance)

        deployment_key = utils.random_alnum(32)
        db.bm_node_update(context, node['id'],
                {'deploy_key': deployment_key,
                 'image_path': image_file_path,
                 'pxe_config_path': tilera_nfs_path,
                 'root_mb': root_mb,
                 'swap_mb': swap_mb})

        if os.path.exists(image_file_path) and \
           os.path.exists(tilera_nfs_path):
            utils.execute('mount', '-o', 'loop', image_file_path,
                tilera_nfs_path, run_as_root=True)
Esempio n. 3
0
def mkswap(dev, label='swap1'):
    """Execute mkswap on a device."""
    utils.execute('mkswap',
                  '-L', label,
                  dev,
                  run_as_root=True,
                  check_exit_code=[0])
Esempio n. 4
0
def _allow_iscsi_tgtadm(tid, address):
    utils.execute('tgtadm', '--lld', 'iscsi',
                  '--mode', 'target',
                  '--op', 'bind',
                  '--tid', tid,
                  '--initiator-address', address,
                  run_as_root=True)
Esempio n. 5
0
def _prepare_floppy_image(task, params):
    """Prepares the floppy image for passing the parameters.

    This method prepares a temporary vfat filesystem image, which
    contains the parameters to be passed to the ramdisk.
    Then it uploads the file NFS or CIFS server.

    :param task: a TaskManager instance containing the node to act on.
    :param params: a dictionary containing 'parameter name'->'value' mapping
        to be passed to the deploy ramdisk via the floppy image.
    :returns: floppy image filename
    :raises: ImageCreationFailed, if it failed while creating the floppy image.
    :raises: IRMCOperationError, if copying floppy image file failed.
    """
    floppy_filename = _get_floppy_image_name(task.node)
    floppy_fullpathname = os.path.join(
        CONF.irmc.remote_image_share_root, floppy_filename)

    with tempfile.NamedTemporaryFile() as vfat_image_tmpfile_obj:
        images.create_vfat_image(vfat_image_tmpfile_obj.name,
                                 parameters=params)
        try:
            utils.execute('cp', vfat_image_tmpfile_obj.name,
                          floppy_fullpathname, check_exit_code=[0])
        except Exception as e:
            operation = _("Copying floppy image file")
            raise exception.IRMCOperationError(
                operation=operation, error=e)

    return floppy_filename
Esempio n. 6
0
def convert_image(source, dest, out_format, run_as_root=False):
    """Convert image to other format."""
    # NOTE(jlvillal): This function has been moved to ironic-lib. And is
    # planned to be deleted here. If need to modify this function, please also
    # do the same modification in ironic-lib
    cmd = ('qemu-img', 'convert', '-O', out_format, source, dest)
    utils.execute(*cmd, run_as_root=run_as_root)
Esempio n. 7
0
 def test_execute_get_root_helper(self):
     with mock.patch.object(
             processutils, 'execute', autospec=True) as execute_mock:
         helper = utils._get_root_helper()
         utils.execute('foo', run_as_root=True)
         execute_mock.assert_called_once_with('foo', run_as_root=True,
                                              root_helper=helper)
Esempio n. 8
0
 def test_execute_use_standard_locale_with_env_variables(self,
                                                         execute_mock):
     utils.execute('foo', use_standard_locale=True,
                   env_variables={'foo': 'bar'})
     execute_mock.assert_called_once_with('foo',
                                          env_variables={'LC_ALL': 'C',
                                                         'foo': 'bar'})
Esempio n. 9
0
def awake_amt_interface(node):
    """Wake up AMT interface.

    AMT interface goes to sleep after a period of time if the host is off.
    This method will ping AMT interface to wake it up. Because there is
    no guarantee that the AMT address in driver_info is correct, only
    ping the IP five times which is enough to wake it up.

    :param node: an Ironic node object.
    :raises: AMTConnectFailure if unable to connect to the server.
    """
    awake_interval = CONF.amt.awake_interval
    if awake_interval == 0:
        return

    now = time.time()
    last_awake = AMT_AWAKE_CACHE.get(node.uuid, 0)
    if now - last_awake > awake_interval:
        cmd_args = ['ping', '-i', 0.2, '-c', 5,
                    node.driver_info['amt_address']]
        try:
            utils.execute(*cmd_args)
        except processutils.ProcessExecutionError as err:
            LOG.error(_LE('Unable to awake AMT interface on node '
                          '%(node_id)s. Error: %(error)s'),
                      {'node_id': node.uuid, 'error': err})
            raise exception.AMTConnectFailure()
        else:
            LOG.debug(('Successfully awakened AMT interface on node '
                       '%(node_id)s.'), {'node_id': node.uuid})
            AMT_AWAKE_CACHE[node.uuid] = now
Esempio n. 10
0
    def test_exec_ipmitool(self):
        pw_file = "/tmp/password_file"

        self.mox.StubOutWithMock(ipmi, "_make_password_file")
        self.mox.StubOutWithMock(utils, "execute")
        self.mox.StubOutWithMock(utils, "delete_if_exists")
        ipmi._make_password_file(self.ipmi.password).AndReturn(pw_file)
        args = [
            "ipmitool",
            "-I",
            "lanplus",
            "-H",
            self.ipmi.address,
            "-U",
            self.ipmi.user,
            "-f",
            pw_file,
            "A",
            "B",
            "C",
        ]
        utils.execute(*args, attempts=3).AndReturn(("", ""))
        utils.delete_if_exists(pw_file).AndReturn(None)
        self.mox.ReplayAll()

        self.ipmi._exec_ipmitool("A B C")
        self.mox.VerifyAll()
Esempio n. 11
0
def discovery(portal_address, portal_port):
    """Do iSCSI discovery on portal."""
    utils.execute('iscsiadm',
                  '-m', 'discovery',
                  '-t', 'st',
                  '-p', '%s:%s' % (portal_address, portal_port),
                  run_as_root=True,
                  check_exit_code=[0])
Esempio n. 12
0
 def _exec(self, *args):
     # NOTE(lucasagomes): utils.execute() is already a wrapper on top
     #                    of processutils.execute() which raises specific
     #                    exceptions. It also logs any failure so we don't
     #                    need to log it again here.
     utils.execute('parted', '-a', self._alignment, '-s', self._device,
                   '--', 'unit', 'MiB', *args, check_exit_code=[0],
                   run_as_root=True)
Esempio n. 13
0
 def stop_console(self):
     console_pid = _get_console_pid(self.node_id)
     if console_pid:
         # Allow exitcode 99 (RC_UNAUTHORIZED)
         utils.execute('kill', '-TERM', str(console_pid),
                       run_as_root=True,
                       check_exit_code=[0, 99])
     utils.delete_if_exists(_get_console_pid_path(self.node_id))
Esempio n. 14
0
def delete_iscsi(portal_address, portal_port, target_iqn):
    """Delete the iSCSI target."""
    utils.execute('iscsiadm',
                  '-m', 'node',
                  '-p', '%s:%s' % (portal_address, portal_port),
                  '-T', target_iqn,
                  '-o', 'delete',
                  run_as_root=True,
                  check_exit_code=[0])
Esempio n. 15
0
def create_isolinux_image_for_bios(output_file, kernel, ramdisk, kernel_params=None):
    """Creates an isolinux image on the specified file.

    Copies the provided kernel, ramdisk to a directory, generates the isolinux
    configuration file using the kernel parameters provided, and then generates
    a bootable ISO image.

    :param output_file: the path to the file where the iso image needs to be
        created.
    :param kernel: the kernel to use.
    :param ramdisk: the ramdisk to use.
    :param kernel_params: a list of strings(each element being a string like
        'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
        as the kernel cmdline.
    :raises: ImageCreationFailed, if image creation failed while copying files
        or while running command to generate iso.
    """
    ISOLINUX_BIN = "isolinux/isolinux.bin"
    ISOLINUX_CFG = "isolinux/isolinux.cfg"

    options = {"kernel": "/vmlinuz", "ramdisk": "/initrd"}

    with utils.tempdir() as tmpdir:
        files_info = {kernel: "vmlinuz", ramdisk: "initrd", CONF.isolinux_bin: ISOLINUX_BIN}
        try:
            _create_root_fs(tmpdir, files_info)
        except (OSError, IOError) as e:
            LOG.exception(_LE("Creating the filesystem root failed."))
            raise exception.ImageCreationFailed(image_type="iso", error=e)

        cfg = _generate_cfg(kernel_params, CONF.isolinux_config_template, options)

        isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG)
        utils.write_to_file(isolinux_cfg, cfg)

        try:
            utils.execute(
                "mkisofs",
                "-r",
                "-V",
                "VMEDIA_BOOT_ISO",
                "-cache-inodes",
                "-J",
                "-l",
                "-no-emul-boot",
                "-boot-load-size",
                "4",
                "-boot-info-table",
                "-b",
                ISOLINUX_BIN,
                "-o",
                output_file,
                tmpdir,
            )
        except processutils.ProcessExecutionError as e:
            LOG.exception(_LE("Creating ISO image failed."))
            raise exception.ImageCreationFailed(image_type="iso", error=e)
Esempio n. 16
0
def logout_iscsi(portal_address, portal_port, target_iqn):
    """Logout from an iSCSI target."""
    utils.execute('iscsiadm',
                  '-m', 'node',
                  '-p', '%s:%s' % (portal_address, portal_port),
                  '-T', target_iqn,
                  '--logout',
                  run_as_root=True,
                  check_exit_code=[0])
Esempio n. 17
0
def dd(src, dst):
    """Execute dd from src to dst."""
    utils.execute('dd',
                  'if=%s' % src,
                  'of=%s' % dst,
                  'bs=1M',
                  'oflag=direct',
                  run_as_root=True,
                  check_exit_code=[0])
Esempio n. 18
0
    def _iptables_set(self, node_ip, user_data):
        """Sets security setting (iptables:port) if needed.

        iptables -A INPUT -p tcp ! -s $IP --dport $PORT -j DROP
        /tftpboot/iptables_rule script sets iptables rule on the given node.
        """
        rule_path = CONF.tftp_root + "/iptables_rule"
        if user_data is not None:
            open_ip = base64.b64decode(user_data)
            utils.execute(rule_path, node_ip, open_ip)
Esempio n. 19
0
def force_iscsi_lun_update(target_iqn):
    """force iSCSI initiator to re-read luns."""
    LOG.debug("Re-reading iSCSI luns.")

    utils.execute('iscsiadm',
                  '-m', 'node',
                  '-T', target_iqn,
                  '-R',
                  run_as_root=True,
                  check_exit_code=[0])
Esempio n. 20
0
def destroy_disk_metadata(dev, node_uuid):
    """Destroy metadata structures on node's disk.

       Ensure that node's disk appears to be blank without zeroing the entire
       drive. To do this we will zero:
       - the first 18KiB to clear MBR / GPT data
       - the last 18KiB to clear GPT and other metadata like: LVM, veritas,
         MDADM, DMRAID, ...
    """
    # NOTE(NobodyCam): This is needed to work around bug:
    # https://bugs.launchpad.net/ironic/+bug/1317647
    LOG.debug("Start destroy disk metadata for node %(node)s.", {"node": node_uuid})
    try:
        utils.execute("dd", "if=/dev/zero", "of=%s" % dev, "bs=512", "count=36", run_as_root=True, check_exit_code=[0])
    except processutils.ProcessExecutionError as err:
        with excutils.save_and_reraise_exception():
            LOG.error(
                _LE("Failed to erase beginning of disk for node " "%(node)s. Command: %(command)s. Error: %(error)s."),
                {"node": node_uuid, "command": err.cmd, "error": err.stderr},
            )

    # now wipe the end of the disk.
    # get end of disk seek value
    try:
        block_sz = get_dev_block_size(dev)
    except processutils.ProcessExecutionError as err:
        with excutils.save_and_reraise_exception():
            LOG.error(
                _LE("Failed to get disk block count for node %(node)s. " "Command: %(command)s. Error: %(error)s."),
                {"node": node_uuid, "command": err.cmd, "error": err.stderr},
            )
    else:
        seek_value = block_sz - 36
        try:
            utils.execute(
                "dd",
                "if=/dev/zero",
                "of=%s" % dev,
                "bs=512",
                "count=36",
                "seek=%d" % seek_value,
                run_as_root=True,
                check_exit_code=[0],
            )
        except processutils.ProcessExecutionError as err:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    _LE(
                        "Failed to erase the end of the disk on node "
                        "%(node)s. Command: %(command)s. "
                        "Error: %(error)s."
                    ),
                    {"node": node_uuid, "command": err.cmd, "error": err.stderr},
                )
Esempio n. 21
0
def login_iscsi(portal_address, portal_port, target_iqn):
    """Login to an iSCSI target."""
    utils.execute('iscsiadm',
                  '-m', 'node',
                  '-p', '%s:%s' % (portal_address, portal_port),
                  '-T', target_iqn,
                  '--login',
                  run_as_root=True,
                  check_exit_code=[0])
    # Ensure the login complete
    time.sleep(3)
Esempio n. 22
0
 def setUp(self):
     super(RealFilePartitioningTestCase, self).setUp()
     # NOTE(dtantsur): no parted utility on gate-ironic-python26
     try:
         common_utils.execute('parted', '--version')
     except OSError as exc:
         self.skipTest('parted utility was not found: %s' % exc)
     self.file = tempfile.NamedTemporaryFile()
     self.addCleanup(lambda: self.file.close())
     # NOTE(dtantsur): 20 MiB file with zeros
     common_utils.execute('dd', 'if=/dev/zero', 'of=%s' % self.file.name,
                          'bs=1', 'count=0', 'seek=20MiB')
Esempio n. 23
0
def stop_shellinabox_console(node_uuid):
    """Close the serial console for a node."""

    try:
        console_pid = _get_console_pid(node_uuid)
    except exception.NoConsolePid:
        LOG.warning(_("No console pid found for node %s" " while trying to stop shellinabox console.") % node_uuid)
    else:
        # Allow exitcode 99 (RC_UNAUTHORIZED)
        utils.execute("kill", str(console_pid), check_exit_code=[0, 99])
    finally:
        utils.unlink_without_raise(_get_console_pid_file(node_uuid))
def make_partitions(dev, root_mb, swap_mb):
    """Create partitions for root and swap on a disk device."""
    # Lead in with 1MB to allow room for the partition table itself, otherwise
    # the way sfdisk adjusts doesn't shift the partition up to compensate, and
    # we lose the space.
    # http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/raring/util-linux/
    # raring/view/head:/fdisk/sfdisk.c#L1940
    stdin_command = ('1,%d,83;\n,%d,82;\n0,0;\n0,0;\n' % (root_mb, swap_mb))
    utils.execute('sfdisk', '-uM', dev, process_input=stdin_command,
            run_as_root=True,
            check_exit_code=[0])
    # avoid "device is busy"
    time.sleep(3)
Esempio n. 25
0
def discovery(portal_address, portal_port):
    """Do iSCSI discovery on portal."""
    utils.execute(
        "iscsiadm",
        "-m",
        "discovery",
        "-t",
        "st",
        "-p",
        "%s:%s" % (portal_address, portal_port),
        run_as_root=True,
        check_exit_code=[0],
    )
Esempio n. 26
0
def delete_iscsi(portal_address, portal_port, target_iqn):
    """Delete the iSCSI target."""
    # Retry delete until it succeeds (exit code 0) or until there is
    # no longer a target to delete (exit code 21).
    utils.execute('iscsiadm',
                  '-m', 'node',
                  '-p', '%s:%s' % (portal_address, portal_port),
                  '-T', target_iqn,
                  '-o', 'delete',
                  run_as_root=True,
                  check_exit_code=[0, 21],
                  attempts=5,
                  delay_on_retry=True)
Esempio n. 27
0
def logout_iscsi(portal_address, portal_port, target_iqn):
    """Logout from an iSCSI target."""
    utils.execute(
        "iscsiadm",
        "-m",
        "node",
        "-p",
        "%s:%s" % (portal_address, portal_port),
        "-T",
        target_iqn,
        "--logout",
        run_as_root=True,
        check_exit_code=[0],
    )
Esempio n. 28
0
def _create_iscsi_export_tgtadm(path, tid, iqn):
    utils.execute('tgtadm', '--lld', 'iscsi',
                  '--mode', 'target',
                  '--op', 'new',
                  '--tid', tid,
                  '--targetname', iqn,
                  run_as_root=True)
    utils.execute('tgtadm', '--lld', 'iscsi',
                  '--mode', 'logicalunit',
                  '--op', 'new',
                  '--tid', tid,
                  '--lun', '1',
                  '--backing-store', path,
                  run_as_root=True)
Esempio n. 29
0
 def setUp(self):
     super(RealFilePartitioningTestCase, self).setUp()
     # NOTE(dtantsur): no parted utility on gate-ironic-python26
     try:
         common_utils.execute('parted', '--version')
     except OSError as exc:
         self.skipTest('parted utility was not found: %s' % exc)
     self.file = tempfile.NamedTemporaryFile(delete=False)
     # NOTE(ifarkas): the file needs to be closed, so fuser won't report
     #                any usage
     self.file.close()
     # NOTE(dtantsur): 20 MiB file with zeros
     common_utils.execute('dd', 'if=/dev/zero', 'of=%s' % self.file.name,
                          'bs=1', 'count=0', 'seek=20MiB')
Esempio n. 30
0
    def create_database(self):
        """Create database if required for this server."""
        # FIXME(jlvillal) to work with Ironic
        raise Exception("Does not work")

        if self.needs_database:
            conf_dir = os.path.join(self.test_dir, 'etc')
            safe_mkdirs(conf_dir)
            conf_filepath = os.path.join(conf_dir, 'ironic-manage.conf')

            with open(conf_filepath, 'w') as conf_file:
                conf_file.write('[DEFAULT]\n')
                conf_file.write('sql_connection = %s' % self.sql_connection)
                conf_file.flush()

            ironic_db_env = 'IRONIC_DB_TEST_SQLITE_FILE'
            if ironic_db_env in os.environ:
                # use the empty db created and cached as a tempfile
                # instead of spending the time creating a new one
                db_location = os.environ[ironic_db_env]
                os.system('cp %s %s/tests.sqlite' %
                          (db_location, self.test_dir))
            else:
                # FIXME(jlvillal) what is the correct command????
                cmd = ('%s -m ironic.cmd.manage --config-file %s db sync' %
                       (sys.executable, conf_filepath))
                utils.execute(cmd)

                # copy the clean db to a temp location so that it
                # can be reused for future tests
                (osf, db_location) = tempfile.mkstemp()
                os.close(osf)
                os.system('cp %s/tests.sqlite %s' %
                          (self.test_dir, db_location))
                os.environ[ironic_db_env] = db_location

                # cleanup the temp file when the test suite is
                # complete
                def _delete_cached_db():
                    try:
                        os.remove(os.environ[ironic_db_env])
                    except Exception:
                        # FIXME(jlvillal) We should log this
                        raise NotImplementedError
                        # logger.exception(
                        #    "Error cleaning up the file %s" %
                        #    os.environ[ironic_db_env])

                atexit.register(_delete_cached_db)
Esempio n. 31
0
def create_isolinux_image(output_file, kernel, ramdisk, kernel_params=None):
    """Creates an isolinux image on the specified file.

    Copies the provided kernel, ramdisk to a directory, generates the isolinux
    configuration file using the kernel parameters provided, and then generates
    a bootable ISO image.

    :param output_file: the path to the file where the iso image needs to be
        created.
    :param kernel: the kernel to use.
    :param ramdisk: the ramdisk to use.
    :param kernel_params: a list of strings(each element being a string like
        'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
        as the kernel cmdline.
    :raises: ImageCreationFailed, if image creation failed while copying files
        or while running command to generate iso.
    """
    ISOLINUX_BIN = 'isolinux/isolinux.bin'
    ISOLINUX_CFG = 'isolinux/isolinux.cfg'

    with utils.tempdir() as tmpdir:

        files_info = {
            kernel: 'vmlinuz',
            ramdisk: 'initrd',
            CONF.isolinux_bin: ISOLINUX_BIN,
        }

        try:
            _create_root_fs(tmpdir, files_info)
        except (OSError, IOError) as e:
            LOG.exception(_LE("Creating the filesystem root failed."))
            raise exception.ImageCreationFailed(image_type='iso', error=e)

        cfg = _generate_isolinux_cfg(kernel_params)

        isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG)
        utils.write_to_file(isolinux_cfg, cfg)

        try:
            utils.execute('mkisofs', '-r', '-V', "BOOT IMAGE", '-cache-inodes',
                          '-J', '-l', '-no-emul-boot', '-boot-load-size', '4',
                          '-boot-info-table', '-b', ISOLINUX_BIN, '-o',
                          output_file, tmpdir)
        except processutils.ProcessExecutionError as e:
            LOG.exception(_LE("Creating ISO image failed."))
            raise exception.ImageCreationFailed(image_type='iso', error=e)
Esempio n. 32
0
def make_partitions(dev, root_mb, swap_mb):
    """Create partitions for root and swap on a disk device."""
    # Lead in with 1MB to allow room for the partition table itself, otherwise
    # the way sfdisk adjusts doesn't shift the partition up to compensate, and
    # we lose the space.
    # http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/raring/util-linux/
    # raring/view/head:/fdisk/sfdisk.c#L1940
    stdin_command = ('1,%d,83;\n,%d,82;\n0,0;\n0,0;\n' % (root_mb, swap_mb))
    utils.execute('sfdisk',
                  '-uM',
                  dev,
                  process_input=stdin_command,
                  run_as_root=True,
                  attempts=3,
                  check_exit_code=[0])
    # avoid "device is busy"
    time.sleep(3)
Esempio n. 33
0
def get_dev_block_size(dev):
    """Get the device size in 512 byte sectors."""
    block_sz, cmderr = utils.execute('blockdev',
                                     '--getsz',
                                     dev,
                                     run_as_root=True,
                                     check_exit_code=[0])
    return int(block_sz)
Esempio n. 34
0
def _stop_console(node_uuid):
    """Close the serial console for a node

    Kills the console process and deletes the PID file.

    :param node_uuid: the UUID of the node
    :raises: NoConsolePid if no console PID was found
    :raises: processutils.ProcessExecutionError if unable to stop the process
    """

    try:
        console_pid = _get_console_pid(node_uuid)

        # Allow exitcode 99 (RC_UNAUTHORIZED)
        utils.execute('kill', str(console_pid), check_exit_code=[0, 99])
    finally:
        utils.unlink_without_raise(_get_console_pid_file(node_uuid))
Esempio n. 35
0
def qemu_img_info(path):
    """Return an object containing the parsed output from qemu-img info."""
    if not os.path.exists(path):
        return imageutils.QemuImgInfo()

    out, err = utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
                             path)
    return imageutils.QemuImgInfo(out)
Esempio n. 36
0
def delete_iscsi(portal_address, portal_port, target_iqn):
    """Delete the iSCSI target."""
    # Retry delete until it succeeds (exit code 0) or until there is
    # no longer a target to delete (exit code 21).
    utils.execute('iscsiadm',
                  '-m',
                  'node',
                  '-p',
                  '%s:%s' % (portal_address, portal_port),
                  '-T',
                  target_iqn,
                  '-o',
                  'delete',
                  run_as_root=True,
                  check_exit_code=[0, 21],
                  attempts=5,
                  delay_on_retry=True)
Esempio n. 37
0
def login_iscsi(portal_address, portal_port, target_iqn):
    """Login to an iSCSI target."""
    utils.execute('iscsiadm',
                  '-m',
                  'node',
                  '-p',
                  '%s:%s' % (portal_address, portal_port),
                  '-T',
                  target_iqn,
                  '--login',
                  run_as_root=True,
                  check_exit_code=[0],
                  attempts=5,
                  delay_on_retry=True)
    # Ensure the login complete
    verify_iscsi_connection(target_iqn)
    # force iSCSI initiator to re-read luns
    force_iscsi_lun_update(target_iqn)
Esempio n. 38
0
def _exec_ipmitool(driver_info, command):
    """Execute the ipmitool command.

    This uses the lanplus interface to communicate with the BMC device driver.

    :param driver_info: the ipmitool parameters for accessing a node.
    :param command: the ipmitool command to be executed.
    :returns: (stdout, stderr) from executing the command.
    :raises: PasswordFileFailedToCreate from creating or writing to the
             temporary file.
    :raises: processutils.ProcessExecutionError from executing the command.

    """
    args = ['ipmitool',
            '-I',
            'lanplus',
            '-H',
            driver_info['address'],
            '-L', driver_info['priv_level']
            ]
    if driver_info['username']:
        args.append('-U')
        args.append(driver_info['username'])

    for name, option in BRIDGING_OPTIONS:
        if driver_info[name] is not None:
            args.append(option)
            args.append(driver_info[name])

    # specify retry timing more precisely, if supported
    if _is_option_supported('timing'):
        num_tries = max(
            (CONF.ipmi.retry_timeout // CONF.ipmi.min_command_interval), 1)
        args.append('-R')
        args.append(str(num_tries))

        args.append('-N')
        args.append(str(CONF.ipmi.min_command_interval))

    # 'ipmitool' command will prompt password if there is no '-f' option,
    # we set it to '\0' to write a password file to support empty password
    with _make_password_file(driver_info['password'] or '\0') as pw_file:
        args.append('-f')
        args.append(pw_file)
        args.extend(command.split(" "))
        # NOTE(deva): ensure that no communications are sent to a BMC more
        #             often than once every min_command_interval seconds.
        time_till_next_poll = CONF.ipmi.min_command_interval - (
                time.time() - LAST_CMD_TIME.get(driver_info['address'], 0))
        if time_till_next_poll > 0:
            time.sleep(time_till_next_poll)
        try:
            out, err = utils.execute(*args)
        finally:
            LAST_CMD_TIME[driver_info['address']] = time.time()
        return out, err
Esempio n. 39
0
def _show_tgtadm():
    out, _ = utils.execute('tgtadm',
                           '--lld',
                           'iscsi',
                           '--mode',
                           'target',
                           '--op',
                           'show',
                           run_as_root=True)
    return out
Esempio n. 40
0
def get_partition_table(device):
    """Get partitions information from given device.

    :param device: The device path.
    :returns: If a partition table is present.
    """
    output = utils.execute('parted', '-s', '-m', device, 'print')[0]
    header = [line for line in output.split('\n') if line.strip()][1]
    match = _PARTED_PRINT_HEADER_RE.match(header)
    return match.groups()[0]
Esempio n. 41
0
def qemu_img_info(path):
    """Return an object containing the parsed output from qemu-img info."""
    # NOTE(jlvillal): This function has been moved to ironic-lib. And is
    # planned to be deleted here. If need to modify this function, please also
    # do the same modification in ironic-lib
    if not os.path.exists(path):
        return imageutils.QemuImgInfo()

    out, err = utils.execute('env', 'LC_ALL=C', 'LANG=C',
                             'qemu-img', 'info', path)
    return imageutils.QemuImgInfo(out)
Esempio n. 42
0
def _exec_ipmitool(driver_info, command):
    args = [
        'ipmitool', '-I', 'lanplus', '-H', driver_info['address'], '-U',
        driver_info['username'], '-f'
    ]
    with _make_password_file(driver_info['password']) as pw_file:
        args.append(pw_file)
        args.extend(command.split(" "))
        out, err = utils.execute(*args, attempts=3)
        LOG.debug(_("ipmitool stdout: '%(out)s', stderr: '%(err)s'"), locals())
        return out, err
Esempio n. 43
0
def block_uuid(dev):
    """Get UUID of a block device."""
    out, _err = utils.execute('blkid',
                              '-s',
                              'UUID',
                              '-o',
                              'value',
                              dev,
                              run_as_root=True,
                              check_exit_code=[0])
    return out.strip()
def _send_signal(node_uuid, signum):
    """send a signal to the console server.

    Kills the console process and deletes the PID file.

    :param node_uuid: the UUID of the node
    :param signum: signal number to send
    :raises: NoConsolePid if no console PID was found
    :raises: processutils.ProcessExecutionError if unable to stop the process
    """

    try:
        console_pid = _get_console_pid(node_uuid)

        # Allow exitcode 99 (RC_UNAUTHORIZED)
        utils.execute('kill',
                      '-%s' % signum,
                      str(console_pid),
                      check_exit_code=[0, 99])
    finally:
        pass
Esempio n. 45
0
    def _exec_pdutool(self, mode):
        """Changes power state of the given node.

        According to the mode (1-ON, 2-OFF, 3-REBOOT), power state can be
        changed. /tftpboot/pdu_mgr script handles power management of
        PDU (Power Distribution Unit).
        """
        if mode == CONF.tile_pdu_status:
            try:
                utils.execute('ping', '-c1', self.address,
                       check_exit_code=True)
                return CONF.tile_pdu_on
            except exception.ProcessExecutionError:
                return CONF.tile_pdu_off
        else:
            try:
                utils.execute(CONF.tile_pdu_mgr,
                              CONF.tile_pdu_ip, mode)
                time.sleep(CONF.tile_power_wait)
                return mode
            except exception.ProcessExecutionError:
                LOG.exception(_("PDU failed"))
Esempio n. 46
0
    def test_no_retry_on_success(self):
        fd, tmpfilename = tempfile.mkstemp()
        _, tmpfilename2 = tempfile.mkstemp()
        try:
            fp = os.fdopen(fd, 'w+')
            fp.write('''#!/bin/sh
# If we've already run, bail out.
grep -q foo "$1" && exit 1
# Mark that we've run before.
echo foo > "$1"
# Check that stdin gets passed correctly.
grep foo
''')
            fp.close()
            os.chmod(tmpfilename, 0o755)
            utils.execute(tmpfilename,
                          tmpfilename2,
                          process_input='foo',
                          attempts=2)
        finally:
            os.unlink(tmpfilename)
            os.unlink(tmpfilename2)
Esempio n. 47
0
def login_iscsi(portal_address, portal_port, target_iqn):
    """Login to an iSCSI target."""
    utils.execute('iscsiadm',
                  '-m',
                  'node',
                  '-p',
                  '%s:%s' % (utils.wrap_ipv6(portal_address), portal_port),
                  '-T',
                  target_iqn,
                  '--login',
                  run_as_root=True,
                  check_exit_code=[0],
                  attempts=5,
                  delay_on_retry=True)

    error_occurred = False
    try:
        # Ensure the login complete
        verify_iscsi_connection(target_iqn)
        # force iSCSI initiator to re-read luns
        force_iscsi_lun_update(target_iqn)
        # ensure file system sees the block device
        check_file_system_for_iscsi_device(portal_address, portal_port,
                                           target_iqn)
    except (exception.InstanceDeployFailure,
            processutils.ProcessExecutionError) as e:
        with excutils.save_and_reraise_exception():
            error_occurred = True
            LOG.error("Failed to login to an iSCSI target due to %s", e)
    finally:
        if error_occurred:
            try:
                logout_iscsi(portal_address, portal_port, target_iqn)
                delete_iscsi(portal_address, portal_port, target_iqn)
            except processutils.ProcessExecutionError as e:
                LOG.warning(
                    "An error occurred when trying to cleanup "
                    "failed ISCSI session error %s", e)
Esempio n. 48
0
 def _exec_ipmitool(self, command):
     args = [
         'ipmitool', '-I', 'lanplus', '-H', self.address, '-U', self.user,
         '-f'
     ]
     pwfile = _make_password_file(self.password)
     try:
         args.append(pwfile)
         args.extend(command.split(" "))
         out, err = utils.execute(*args, attempts=3)
         LOG.debug(_("ipmitool stdout: '%(out)s', stderr: '%(err)s'"),
                   locals())
         return out, err
     finally:
         utils.delete_if_exists(pwfile)
Esempio n. 49
0
    def start_console(self):
        if not self.port:
            return
        args = []
        args.append(CONF.terminal)
        if CONF.terminal_cert_dir:
            args.append("-c")
            args.append(CONF.terminal_cert_dir)
        else:
            args.append("-t")
        args.append("-p")
        args.append(str(self.port))
        args.append("--background=%s" % _get_console_pid_path(self.node_id))
        args.append("-s")

        try:
            pwfile = _make_password_file(self.password)
            ipmi_args = "/:%(uid)s:%(gid)s:HOME:ipmitool -H %(address)s" \
                    " -I lanplus -U %(user)s -f %(pwfile)s sol activate" \
                    % {'uid': os.getuid(),
                       'gid': os.getgid(),
                       'address': self.address,
                       'user': self.user,
                       'pwfile': pwfile,
                       }

            args.append(ipmi_args)
            # Run shellinaboxd without pipes. Otherwise utils.execute() waits
            # infinitely since shellinaboxd does not close passed fds.
            x = ["'" + arg.replace("'", "'\\''") + "'" for arg in args]
            x.append('</dev/null')
            x.append('>/dev/null')
            x.append('2>&1')
            utils.execute(' '.join(x), shell=True)
        finally:
            utils.delete_if_exists(pwfile)
Esempio n. 50
0
    def deactivate_bootloader(self, context, node, instance):
        """Delete Tilera bootloader images and config."""
        try:
            db.bm_node_update(context, node['id'],
                    {'deploy_key': None,
                     'image_path': None,
                     'pxe_config_path': None,
                     'root_mb': 0,
                     'swap_mb': 0})
        except exception.NodeNotFound:
            pass

        tilera_nfs_path = get_tilera_nfs_path(node['id'])

        if os.path.ismount(tilera_nfs_path):
            utils.execute('rpc.mountd', run_as_root=True)
            utils.execute('umount', '-f', tilera_nfs_path, run_as_root=True)

        try:
            image_info = get_tftp_image_info(instance)
        except exception.NovaException:
            pass
        else:
            for label in image_info.keys():
                (uuid, path) = image_info[label]
                utils.unlink_without_raise(path)

        try:
            self._collect_mac_addresses(context, node)
        except db_exc.DBError:
            pass

        if os.path.exists(os.path.join(CONF.tftp_root,
                instance['uuid'])):
            utils.rmtree_without_raise(
                os.path.join(CONF.tftp_root, instance['uuid']))
Esempio n. 51
0
    def test_mkfs(self):
        self.mox.StubOutWithMock(utils, 'execute')
        utils.execute('mkfs', '-t', 'ext4', '-F', '/my/block/dev')
        utils.execute('mkfs', '-t', 'msdos', '/my/msdos/block/dev')
        utils.execute('mkswap', '/my/swap/block/dev')
        self.mox.ReplayAll()

        utils.mkfs('ext4', '/my/block/dev')
        utils.mkfs('msdos', '/my/msdos/block/dev')
        utils.mkfs('swap', '/my/swap/block/dev')
Esempio n. 52
0
def _delete_iscsi_export_tgtadm(tid):
    try:
        utils.execute('tgtadm',
                      '--lld',
                      'iscsi',
                      '--mode',
                      'logicalunit',
                      '--op',
                      'delete',
                      '--tid',
                      tid,
                      '--lun',
                      '1',
                      run_as_root=True)
    except exception.ProcessExecutionError:
        pass
    try:
        utils.execute('tgtadm',
                      '--lld',
                      'iscsi',
                      '--mode',
                      'target',
                      '--op',
                      'delete',
                      '--tid',
                      tid,
                      run_as_root=True)
    except exception.ProcessExecutionError:
        pass
    # Check if the tid is deleted, that is, check the tid no longer exists.
    # If the tid dose not exist, tgtadm returns with exit_code 22.
    # utils.execute() can check the exit_code if check_exit_code parameter is
    # passed. But, regardless of whether check_exit_code contains 0 or not,
    # if the exit_code is 0, the function dose not report errors. So we have to
    # catch a ProcessExecutionError and test its exit_code is 22.
    try:
        utils.execute('tgtadm',
                      '--lld',
                      'iscsi',
                      '--mode',
                      'target',
                      '--op',
                      'show',
                      '--tid',
                      tid,
                      run_as_root=True)
    except exception.ProcessExecutionError as e:
        if e.exit_code == 22:
            # OK, the tid is deleted
            return
        raise
    raise exception.NovaException(
        _('baremetal driver was unable to delete tid %s') % tid)
Esempio n. 53
0
def _run_playbook(node, name, extra_vars, key, tags=None, notags=None):
    """Execute ansible-playbook."""
    root = _get_playbooks_path(node)
    playbook = os.path.join(root, name)
    inventory = os.path.join(root, 'inventory')
    ironic_vars = {'ironic': extra_vars}
    python_interpreter = _get_python_interpreter(node)
    if python_interpreter:
        ironic_vars['ansible_python_interpreter'] = python_interpreter
    args = [
        CONF.ansible.ansible_playbook_script,
        playbook,
        '-i',
        inventory,
        '-e',
        json.dumps(ironic_vars),
    ]

    if CONF.ansible.config_file_path:
        env = ['env', 'ANSIBLE_CONFIG=%s' % CONF.ansible.config_file_path]
        args = env + args

    if tags:
        args.append('--tags=%s' % ','.join(tags))

    if notags:
        args.append('--skip-tags=%s' % ','.join(notags))

    if key:
        args.append('--private-key=%s' % key)

    verbosity = CONF.ansible.verbosity
    if verbosity is None and CONF.debug:
        verbosity = 4
    if verbosity:
        args.append('-' + 'v' * verbosity)

    if CONF.ansible.ansible_extra_args:
        args.extend(shlex.split(CONF.ansible.ansible_extra_args))

    try:
        out, err = utils.execute(*args)
        return out, err
    except processutils.ProcessExecutionError as e:
        raise exception.InstanceDeployFailure(reason=e)
Esempio n. 54
0
def exec_xcatcmd(driver_info, command, args):
    """ excute xcat cmd """
    cmd = [command, driver_info['xcat_node']]
    cmd.extend(args.split(" "))
    # NOTE: ensure that no communications are excuted more
    #             often than once every min_command_interval seconds.
    time_till_next_poll = CONF.ipmi.min_command_interval - (
        time.time() - LAST_CMD_TIME.get(driver_info['xcat_node'], 0))
    if time_till_next_poll > 0:
        time.sleep(time_till_next_poll)
    try:
        out, err = utils.execute(*cmd)
        if err:
            raise xcat_exception.xCATCmdFailure(cmd=cmd,
                                                node=driver_info['xcat_node'],
                                                args=args)
    finally:
        LAST_CMD_TIME[driver_info['xcat_node']] = time.time()
    return out, err
Esempio n. 55
0
def get_disk_identifier(dev):
    """Get the disk identifier from the disk being exposed by the ramdisk.

    This disk identifier is appended to the pxe config which will then be
    used by chain.c32 to detect the correct disk to chainload. This is helpful
    in deployments to nodes with multiple disks.

    http://www.syslinux.org/wiki/index.php/Comboot/chain.c32#mbr:

    :param dev: Path for the already populated disk device.
    :returns The Disk Identifier.
    """
    disk_identifier = utils.execute('hexdump', '-s', '440', '-n', '4',
                                     '-e', '''\"0x%08x\"''',
                                     dev,
                                     run_as_root=True,
                                     check_exit_code=[0],
                                     attempts=5,
                                     delay_on_retry=True)
    return disk_identifier[0]
def get_ics_console_log(node_uuid):
    """Get the content of a console log of a node (ironic console server).

    :param node_uuid: the UUID of the node
    :raises: ConsoleError if unable to stop the console process
    """
    log_file = _get_console_log_file(node_uuid)

    args = ["tail", "-n", "100", log_file]
    try:
        LOG.debug('Running subprocess: %s', ' '.join(args))
        stdout, stderr = utils.execute(*args)
    except (OSError, ValueError) as e:
        error = _("%(exec_error)s\n"
                  "Command: %(command)s") % {
                      'exec_error': str(e),
                      'command': ' '.join(args)
                  }
        LOG.warning(error)
        raise exception.ConsoleSubprocessFailed(error=error)
    return stdout
Esempio n. 57
0
def verify_iscsi_connection(target_iqn):
    """Verify iscsi connection."""
    LOG.debug("Checking for iSCSI target to become active.")

    for attempt in range(CONF.deploy.iscsi_verify_attempts):
        out, _err = utils.execute('iscsiadm',
                  '-m', 'node',
                  '-S',
                  run_as_root=True,
                  check_exit_code=[0])
        if target_iqn in out:
            break
        time.sleep(1)
        LOG.debug("iSCSI connection not active. Rechecking. Attempt "
                  "%(attempt)d out of %(total)d", {"attempt": attempt,
                  "total": CONF.deploy.iscsi_verify_attempts})
    else:
        msg = _("Max attempts to verify a iSCSI connection is active reached "
                "and the connection didn't become active.")
        LOG.error(msg)
        raise exception.InstanceDeployFailure(msg)
Esempio n. 58
0
def verify_iscsi_connection(target_iqn):
    """Verify iscsi connection."""
    LOG.debug("Checking for iSCSI target to become active.")

    total_checks = CONF.iscsi.verify_attempts
    for attempt in range(total_checks):
        out, _err = utils.execute('iscsiadm',
                                  '-m', 'node',
                                  '-S',
                                  run_as_root=True,
                                  check_exit_code=[0])
        if target_iqn in out:
            break
        time.sleep(1)
        LOG.debug("iSCSI connection not active. Rechecking. Attempt "
                  "%(attempt)d out of %(total)d",
                  {"attempt": attempt + 1, "total": total_checks})
    else:
        msg = _("iSCSI connection did not become active after attempting to "
                "verify %d times.") % total_checks
        LOG.error(msg)
        raise exception.InstanceDeployFailure(msg)
Esempio n. 59
0
def _run_playbook(name, extra_vars, key, tags=None, notags=None):
    """Execute ansible-playbook."""
    playbook = os.path.join(CONF.ansible.playbooks_path, name)
    args = [
        CONF.ansible.ansible_playbook_script,
        playbook,
        '-i',
        INVENTORY_FILE,
        '-e',
        json.dumps(extra_vars),
    ]

    if CONF.ansible.config_file_path:
        env = ['env', 'ANSIBLE_CONFIG=%s' % CONF.ansible.config_file_path]
        args = env + args

    if tags:
        args.append('--tags=%s' % ','.join(tags))

    if notags:
        args.append('--skip-tags=%s' % ','.join(notags))

    if key:
        args.append('--private-key=%s' % key)

    verbosity = CONF.ansible.verbosity
    if verbosity is None and CONF.debug:
        verbosity = 4
    if verbosity:
        args.append('-' + 'v' * verbosity)

    if CONF.ansible.ansible_extra_args:
        args.extend(shlex.split(CONF.ansible.ansible_extra_args))

    try:
        out, err = utils.execute(*args)
        return out, err
    except processutils.ProcessExecutionError as e:
        raise exception.InstanceDeployFailure(reason=e)
Esempio n. 60
0
def _check_option_support(options):
    """Checks if the specific ipmitool options are supported on host.

    This method updates the module-level variables indicating whether
    an option is supported so that it is accessible by any driver
    interface class in this module. It is intended to be called from
    the __init__ method of such classes only.

    :param options: list of ipmitool options to be checked
    :raises: OSError
    """
    for opt in options:
        if _is_option_supported(opt) is None:
            try:
                cmd = ipmitool_command_options[opt]
                out, err = utils.execute(*cmd)
            except processutils.ProcessExecutionError:
                # the local ipmitool does not support the command.
                _is_option_supported(opt, False)
            else:
                # looks like ipmitool supports the command.
                _is_option_supported(opt, True)