예제 #1
0
    def extend_volume(self, connection_properties):
        """Update the local kernel's size information.

        Try and update the local kernel's size information
        for a ScaleIO volume.
        """

        LOG.info("ScaleIO rescan volumes: %(cmd)s",
                 {'cmd': self.RESCAN_VOLS_CMD})

        try:
            (out, err) = self._execute(*self.RESCAN_VOLS_CMD,
                                       run_as_root=True,
                                       root_helper=self._root_helper)

            LOG.debug("Rescan volumes %(cmd)s: stdout=%(out)s", {
                'cmd': self.RESCAN_VOLS_CMD,
                'out': out
            })

        except putils.ProcessExecutionError as e:
            msg = (_("Error querying volumes: %(err)s") % {'err': e.stderr})
            LOG.error(msg)
            raise exception.BrickException(message=msg)

        volume_paths = self.get_volume_paths(connection_properties)
        if volume_paths:
            return self.get_device_size(volume_paths[0])

        # if we got here, the volume is not mapped
        msg = (_("Error extending ScaleIO volume"))
        LOG.error(msg)
        raise exception.BrickException(message=msg)
예제 #2
0
    def _wait_for_volume_path(self, path):
        if not os.path.isdir(path):
            msg = (_("ScaleIO volume %(volume_id)s not found at "
                     "expected path.") % {
                         'volume_id': self.volume_id
                     })

            LOG.debug(msg)
            raise exception.BrickException(message=msg)

        disk_filename = None
        filenames = os.listdir(path)
        LOG.info("Files found in %(path)s path: %(files)s ", {
            'path': path,
            'files': filenames
        })

        for filename in filenames:
            if (filename.startswith("emc-vol")
                    and filename.endswith(self.volume_id)):
                disk_filename = filename
                break

        if not disk_filename:
            msg = (_("ScaleIO volume %(volume_id)s not found.") % {
                'volume_id': self.volume_id
            })
            LOG.debug(msg)
            raise exception.BrickException(message=msg)

        return disk_filename
예제 #3
0
    def _get_client_id(self):
        request = ("https://%(server_ip)s:%(server_port)s/"
                   "api/types/Client/instances/getByIp::%(sdc_ip)s/" % {
                       'server_ip': self.server_ip,
                       'server_port': self.server_port,
                       'sdc_ip': self.local_sdc_ip
                   })

        LOG.info("ScaleIO get client id by ip request: %(request)s",
                 {'request': request})

        r = requests.get(request,
                         auth=(self.server_username, self.server_token),
                         verify=False)

        r = self._check_response(r, request)
        sdc_id = r.json()
        if not sdc_id:
            msg = (_("Client with ip %(sdc_ip)s was not found.") % {
                'sdc_ip': self.local_sdc_ip
            })
            raise exception.BrickException(message=msg)

        if r.status_code != 200 and "errorCode" in sdc_id:
            msg = (_("Error getting sdc id from ip %(sdc_ip)s: %(err)s") % {
                'sdc_ip': self.local_sdc_ip,
                'err': sdc_id['message']
            })

            LOG.error(msg)
            raise exception.BrickException(message=msg)

        LOG.info("ScaleIO sdc id is %(sdc_id)s.", {'sdc_id': sdc_id})
        return sdc_id
예제 #4
0
    def get_volume_paths(self, connection_properties):
        """Return the list of existing paths for a volume.

        The job of this method is to find out what paths in
        the system are associated with a volume as described
        by the connection_properties.

        :param connection_properties: The dictionary that describes all
                                      of the target volume attributes;
                                      it needs to contain 'volume' and
                                      'device_path' values.
        :type connection_properties: dict
        """
        volume_id = connection_properties.get('volume', None)
        if volume_id is None:
            raise exception.BrickException(
                'Invalid StorPool connection data, no volume ID specified.')
        volume = self._attach.volumeName(volume_id)
        path = '/dev/storpool/' + volume
        dpath = connection_properties.get('device_path', None)
        if dpath is not None and dpath != path:
            raise exception.BrickException(
                'Internal error: StorPool volume path {path} does not '
                'match device path {dpath}', {
                    path: path,
                    dpath: dpath
                })
        return [path]
예제 #5
0
    def connect_volume(self, connection_properties):
        """Connect to a volume.

        :param connection_properties: The dictionary that describes all
                                      of the target volume attributes;
                                      it needs to contain the StorPool
                                      'client_id' and the common 'volume' and
                                      'access_mode' values.
        :type connection_properties: dict
        :returns: dict
        """
        client_id = connection_properties.get('client_id', None)
        if client_id is None:
            raise exception.BrickException(
                'Invalid StorPool connection data, no client ID specified.')
        volume_id = connection_properties.get('volume', None)
        if volume_id is None:
            raise exception.BrickException(
                'Invalid StorPool connection data, no volume ID specified.')
        volume = self._attach.volumeName(volume_id)
        mode = connection_properties.get('access_mode', None)
        if mode is None or mode not in ('rw', 'ro'):
            raise exception.BrickException(
                'Invalid access_mode specified in the connection data.')
        req_id = 'brick-%s-%s' % (client_id, volume_id)
        self._attach.add(
            req_id, {
                'volume': volume,
                'type': 'brick',
                'id': req_id,
                'rights': 1 if mode == 'ro' else 2,
                'volsnap': False
            })
        self._attach.sync(req_id, None)
        return {'type': 'block', 'path': '/dev/storpool/' + volume}
예제 #6
0
파일: hgst.py 프로젝트: chengtcli/os-brick
 def _find_vgc_host(self):
     """Finds vgc-cluster hostname for this box."""
     params = [self.VGCCLUSTER, "domain-list", "-1"]
     try:
         out, unused = self._execute(*params,
                                     run_as_root=True,
                                     root_helper=self._root_helper)
     except putils.ProcessExecutionError as err:
         self._log_cli_err(err)
         msg = _("Unable to get list of domain members, check that "
                 "the cluster is running.")
         raise exception.BrickException(message=msg)
     domain = out.splitlines()
     params = ["ip", "addr", "list"]
     try:
         out, unused = self._execute(*params, run_as_root=False)
     except putils.ProcessExecutionError as err:
         self._log_cli_err(err)
         msg = _("Unable to get list of IP addresses on this host, "
                 "check permissions and networking.")
         raise exception.BrickException(message=msg)
     nets = out.splitlines()
     for host in domain:
         try:
             ip = socket.gethostbyname(host)
             for l in nets:
                 x = l.strip()
                 if x.startswith("inet %s/" % ip):
                     return host
         except socket.error:
             pass
     msg = _("Current host isn't part of HGST domain.")
     raise exception.BrickException(message=msg)
예제 #7
0
    def disconnect_volume(self, connection_properties, device_info):
        """Disconnect a volume from an instance."""
        volume_name = None

        if 'name' in connection_properties.keys():
            volume_name = connection_properties['name']

        if volume_name is None or len(volume_name) != GUID_STR_LEN:
            msg = _("Failed to disconnect volume: invalid volume name")
            raise exception.BrickException(message=msg)

        cmd_arg = {'operation': 'disconnect_volume'}
        cmd_arg['volume_guid'] = volume_name
        cmdarg_json = json.dumps(cmd_arg)

        LOG.debug("HyperScale command hscli: %(cmd_arg)s",
                  {'cmd_arg': cmdarg_json})
        try:
            (out, err) = self._execute('hscli',
                                       cmdarg_json,
                                       run_as_root=True,
                                       root_helper=self._root_helper)

        except putils.ProcessExecutionError as e:
            msg = (_("Error executing hscli: %(err)s") % {'err': e.stderr})
            raise exception.BrickException(message=msg)

        if err:
            msg = (_("Failed to connect volume: stdout=%(out)s "
                     "stderr=%(err)s") % {
                         'out': out,
                         'err': err
                     })
            raise exception.BrickException(message=msg)
예제 #8
0
    def connect_volume(self, connection_properties):
        """Connect to a volume.

        :param connection_properties: The dictionary that describes all
                                      of the target volume attributes.
        :type connection_properties: dict
        :returns: dict
        """
        LOG.debug("Connect_volume connection properties: %s.",
                  connection_properties)
        out = self._attach_volume(connection_properties['volume_id'])
        if not out or int(out['ret_code']) not in (self.attached_success_code,
                                                   self.has_been_attached_code,
                                                   self.attach_mnid_done_code):
            msg = (_("Attach volume failed, "
                     "error code is %s") % out['ret_code'])
            raise exception.BrickException(message=msg)

        try:
            volume_path = self._get_volume_path(connection_properties)
        except Exception:
            msg = _("query attached volume failed or volume not attached.")
            LOG.error(msg)
            raise exception.BrickException(message=msg)

        device_info = {'type': 'block', 'path': volume_path}
        return device_info
예제 #9
0
파일: hgst.py 프로젝트: chengtcli/os-brick
    def disconnect_volume(self, connection_properties, device_info):
        """Detach and flush the volume.

        :param connection_properties: The dictionary that describes all
               of the target volume attributes.
               For HGST must include:
               name - Name of space to detach
               noremovehost - Host which should never be removed
        :type connection_properties: dict
        :param device_info: historical difference, but same as connection_props
        :type device_info: dict
        """
        if connection_properties is None:
            msg = _("Connection properties passed in as None.")
            raise exception.BrickException(message=msg)
        if 'name' not in connection_properties:
            msg = _("Connection properties missing 'name' field.")
            raise exception.BrickException(message=msg)
        if 'noremovehost' not in connection_properties:
            msg = _("Connection properties missing 'noremovehost' field.")
            raise exception.BrickException(message=msg)
        if connection_properties['noremovehost'] != self._hostname():
            params = [self.VGCCLUSTER, 'space-set-apphosts']
            params += ['-n', connection_properties['name']]
            params += ['-A', self._hostname()]
            params += ['--action', 'DELETE']
            try:
                self._execute(*params,
                              run_as_root=True,
                              root_helper=self._root_helper)
            except putils.ProcessExecutionError as err:
                self._log_cli_err(err)
                msg = (_("Unable to set apphost for space %s") %
                       connection_properties['name'])
                raise exception.BrickException(message=msg)
예제 #10
0
    def disconnect_volume(self, connection_properties, device_info):
        """Disconnect a volume from the local host.

        The connection_properties are the same as from connect_volume.
        The device_info is returned from connect_volume.

        :param connection_properties: The dictionary that describes all
                                      of the target volume attributes;
                                      it needs to contain the StorPool
                                      'client_id' and the common 'volume'
                                      values.
        :type connection_properties: dict
        :param device_info: historical difference, but same as connection_props
        :type device_info: dict
        """
        client_id = connection_properties.get('client_id', None)
        if client_id is None:
            raise exception.BrickException(
                _LE('Invalid StorPool connection data, no client ID specified.'
                    ))
        volume_id = connection_properties.get('volume', None)
        if volume_id is None:
            raise exception.BrickException(
                _LE('Invalid StorPool connection data, no volume ID specified.'
                    ))
        volume = self._attach.volumeName(volume_id)
        req_id = 'brick-%s-%s' % (client_id, volume_id)
        self._attach.sync(req_id, volume)
        self._attach.remove(req_id)
    def connect_volume(self, connection_properties):
        # NOTE(e0ne): sanity check if ceph-common is installed.
        self._setup_rbd_class()

        # Extract connection parameters and generate config file
        try:
            user = connection_properties['auth_username']
            pool, volume = connection_properties['name'].split('/')
            cluster_name = connection_properties.get('cluster_name')
            monitor_ips = connection_properties.get('hosts')
            monitor_ports = connection_properties.get('ports')
            keyring = connection_properties.get('keyring')
        except IndexError:
            msg = 'Malformed connection properties'
            raise exception.BrickException(msg)

        conf = self._create_ceph_conf(monitor_ips, monitor_ports,
                                      str(cluster_name), user, keyring)

        link_name = self.get_rbd_device_name(pool, volume)
        real_path = os.path.realpath(link_name)

        try:
            # Map RBD volume if it's not already mapped
            if not os.path.islink(link_name) or not os.path.exists(real_path):
                cmd = ['rbd', 'map', volume, '--pool', pool, '--conf', conf]
                cmd += self._get_rbd_args(connection_properties)
                stdout, stderr = self._execute(*cmd,
                                               root_helper=self._root_helper,
                                               run_as_root=True)
                real_path = stdout.strip()
                # The host may not have RBD installed, and therefore won't
                # create the symlinks, ensure they exist
                if self.containerized:
                    self._ensure_link(real_path, link_name)
        except Exception as exec_exception:
            try:
                try:
                    self._unmap(real_path, conf, connection_properties)
                finally:
                    fileutils.delete_if_exists(conf)
            except Exception:
                exc = traceback.format_exc()
                print(
                    'Exception occurred while cleaning up after connection '
                    'error\n%s', exc)
            finally:
                raise exception.BrickException('Error connecting volume: %s' %
                                               six.text_type(exec_exception))

        return {'path': real_path, 'conf': conf, 'type': 'block'}
예제 #12
0
파일: scaleio.py 프로젝트: dr4Ke/os-brick
    def _get_volume_id(self):
        volname_encoded = urllib.parse.quote(self.volume_name, '')
        volname_double_encoded = urllib.parse.quote(volname_encoded, '')
        LOG.debug(_(
            "Volume name after double encoding is %(volume_name)s."),
            {'volume_name': volname_double_encoded}
        )

        request = (
            "https://%(server_ip)s:%(server_port)s/api/types/Volume/instances"
            "/getByName::%(encoded_volume_name)s" %
            {
                'server_ip': self.server_ip,
                'server_port': self.server_port,
                'encoded_volume_name': volname_double_encoded
            }
        )

        LOG.info(
            "ScaleIO get volume id by name request: %(request)s",
            {'request': request}
        )

        r = requests.get(request,
                         auth=(self.server_username, self.server_token),
                         verify=False)

        r = self._check_response(r, request)

        volume_id = r.json()
        if not volume_id:
            msg = (_("Volume with name %(volume_name)s wasn't found.") %
                   {'volume_name': self.volume_name})

            LOG.error(msg)
            raise exception.BrickException(message=msg)

        if r.status_code != self.OK_STATUS_CODE and "errorCode" in volume_id:
            msg = (
                _("Error getting volume id from name %(volume_name)s: "
                  "%(err)s") %
                {'volume_name': self.volume_name, 'err': volume_id['message']}
            )

            LOG.error(msg)
            raise exception.BrickException(message=msg)

        LOG.info("ScaleIO volume id is %(volume_id)s.",
                 {'volume_id': volume_id})
        return volume_id
예제 #13
0
    def _create_ceph_conf(self, monitor_ips, monitor_ports, cluster_name, user,
                          keyring_path):
        monitors = [
            "%s:%s" % (ip, port) for ip, port in zip(
                self._sanitize_mon_hosts(monitor_ips), monitor_ports)
        ]
        mon_hosts = "mon_host = %s" % (','.join(monitors))

        client_section = "[client.%s]" % user

        if keyring_path is None:
            keyring = ("keyring = /etc/ceph/%s.client.%s.keyring" %
                       (cluster_name, user))
        else:
            keyring = "keyring = %s" % keyring_path

        try:
            fd, ceph_conf_path = tempfile.mkstemp(prefix="brickrbd_")
            with os.fdopen(fd, 'w') as conf_file:
                conf_file.writelines(
                    [mon_hosts, "\n", client_section, "\n", keyring, "\n"])
            return ceph_conf_path
        except IOError:
            msg = (_("Failed to write data to %s.") % (ceph_conf_path))
            raise exception.BrickException(msg=msg)
예제 #14
0
    def _get_rbd_handle(self, connection_properties):
        try:
            user = connection_properties['auth_username']
            pool, volume = connection_properties['name'].split('/')
            cluster_name = connection_properties['cluster_name']
            monitor_ips = connection_properties['hosts']
            monitor_ports = connection_properties['ports']
            # NOTE: cinder no longer passes keyring data in the connection
            # properties as of the victoria release.  See OSSN-0085.  But
            # cinderlib does, so we must keep the code related to the keyring.
            keyring = connection_properties.get('keyring')
        except (KeyError, ValueError):
            msg = _("Connect volume failed, malformed connection properties.")
            raise exception.BrickException(msg=msg)

        conf = self._create_ceph_conf(monitor_ips, monitor_ports,
                                      str(cluster_name), user, keyring)
        try:
            rbd_client = linuxrbd.RBDClient(user,
                                            pool,
                                            conffile=conf,
                                            rbd_cluster_name=str(cluster_name))
            rbd_volume = linuxrbd.RBDVolume(rbd_client, volume)
            rbd_handle = linuxrbd.RBDVolumeIOWrapper(
                linuxrbd.RBDImageMetadata(rbd_volume, pool, user, conf))
        except Exception:
            fileutils.delete_if_exists(conf)
            raise

        return rbd_handle
예제 #15
0
    def disconnect_volume(self, connection_properties, device_info,
                          force=False, ignore_errors=False):
        tmp_file_path = device_info['path']
        if not os.path.exists(tmp_file_path):
            msg = _("Vmdk: %s not found.") % tmp_file_path
            raise exception.NotFound(message=msg)

        session = None
        try:
            # We upload the temporary file to vCenter server only if it is
            # modified after connect_volume.
            if os.path.getmtime(tmp_file_path) > device_info['last_modified']:
                self._load_config(connection_properties)
                session = self._create_session()
                backing = vim_util.get_moref(connection_properties['volume'],
                                             "VirtualMachine")
                # Currently there is no way we can restore the volume if it
                # contains redo-log based snapshots (bug 1599026).
                if self._snapshot_exists(session, backing):
                    msg = (_("Backing of volume: %s contains one or more "
                             "snapshots; cannot disconnect.") %
                           connection_properties['volume_id'])
                    raise exception.BrickException(message=msg)

                ds_ref = vim_util.get_moref(
                    connection_properties['datastore'], "Datastore")
                dc_ref = vim_util.get_moref(
                    connection_properties['datacenter'], "Datacenter")
                vmdk_path = connection_properties['vmdk_path']
                self._disconnect(
                    backing, tmp_file_path, session, ds_ref, dc_ref, vmdk_path)
        finally:
            os.remove(tmp_file_path)
            if session:
                session.logout()
예제 #16
0
파일: rbd.py 프로젝트: etaivan/os-brick
    def _get_rbd_handle(self, connection_properties):
        try:
            user = connection_properties['auth_username']
            pool, volume = connection_properties['name'].split('/')
            cluster_name = connection_properties['cluster_name']
            monitor_ips = connection_properties['hosts']
            monitor_ports = connection_properties['ports']
            keyring = connection_properties.get('keyring')
        except (KeyError, ValueError):
            msg = _("Connect volume failed, malformed connection properties.")
            raise exception.BrickException(msg=msg)

        conf = self._create_ceph_conf(monitor_ips, monitor_ports,
                                      str(cluster_name), user, keyring)
        try:
            rbd_client = linuxrbd.RBDClient(user,
                                            pool,
                                            conffile=conf,
                                            rbd_cluster_name=str(cluster_name))
            rbd_volume = linuxrbd.RBDVolume(rbd_client, volume)
            rbd_handle = linuxrbd.RBDVolumeIOWrapper(
                linuxrbd.RBDImageMetadata(rbd_volume, pool, user, conf))
        except Exception:
            fileutils.delete_if_exists(conf)
            raise

        return rbd_handle
예제 #17
0
    def test_detach_volume_fail_disconnect(self, mock_cinder_api_cls,
                                           mock_get_connector_prprts,
                                           mock_get_volume_connector):
        volume = mock.MagicMock()
        volume.volume_id = self.fake_volume_id
        volume.connection_info = jsonutils.dumps(self.fake_conn_info)
        mock_cinder_api = mock.MagicMock()
        mock_cinder_api_cls.return_value = mock_cinder_api
        mock_connector = mock.MagicMock()
        mock_get_connector_prprts.return_value = self.fake_conn_prprts
        mock_get_volume_connector.return_value = mock_connector
        mock_connector.disconnect_volume.side_effect = \
            os_brick_exception.BrickException()

        cinder = cinder_workflow.CinderWorkflow(self.context)
        self.assertRaises(os_brick_exception.BrickException,
                          cinder.detach_volume, volume)

        mock_cinder_api.begin_detaching.assert_called_once_with(
            self.fake_volume_id)
        mock_connector.disconnect_volume.assert_called_once_with(
            self.fake_conn_info['data'], None)
        mock_cinder_api.terminate_connection.assert_not_called()
        mock_cinder_api.detach.assert_not_called()
        mock_cinder_api.roll_detaching.assert_called_once_with(
            self.fake_volume_id)
예제 #18
0
    def _get_rbd_handle(self, connection_properties):
        try:
            user = connection_properties['auth_username']
            pool, volume = connection_properties['name'].split('/')
            cluster_name = connection_properties.get('cluster_name')
            monitor_ips = connection_properties.get('hosts')
            monitor_ports = connection_properties.get('ports')
        except IndexError:
            msg = _("Connect volume failed, malformed connection properties")
            raise exception.BrickException(msg=msg)

        conf = self._create_ceph_conf(monitor_ips, monitor_ports,
                                      str(cluster_name), user)
        rbd_client = linuxrbd.RBDClient(user,
                                        pool,
                                        conffile=conf,
                                        rbd_cluster_name=str(cluster_name))
        rbd_volume = linuxrbd.RBDVolume(rbd_client, volume)
        rbd_handle = linuxrbd.RBDVolumeIOWrapper(
            linuxrbd.RBDImageMetadata(rbd_volume, pool, user, conf))

        if os.path.exists(conf):
            os.remove(conf)

        return rbd_handle
예제 #19
0
    def _mount_nfs(self, nfs_share, mount_path, flags=None):
        """Mount nfs share using present mount types."""
        mnt_errors = {}

        # This loop allows us to first try to mount with NFS 4.1 for pNFS
        # support but falls back to mount NFS 4 or NFS 3 if either the client
        # or server do not support it.
        for mnt_type in sorted(self._nfs_mount_type_opts.keys(), reverse=True):
            options = self._nfs_mount_type_opts[mnt_type]
            try:
                self._do_mount('nfs', nfs_share, mount_path, options, flags)
                LOG.debug('Mounted %(sh)s using %(mnt_type)s.', {
                    'sh': nfs_share,
                    'mnt_type': mnt_type
                })
                return
            except Exception as e:
                mnt_errors[mnt_type] = str(e)
                LOG.debug('Failed to do %s mount.', mnt_type)
        raise exception.BrickException(
            _("NFS mount failed for share %(sh)s. "
              "Error - %(error)s") % {
                  'sh': nfs_share,
                  'error': mnt_errors
              })
예제 #20
0
    def disconnect_volume(self, connection_properties, device_info):
        """Disconnect the  volume.

        :param connection_properties: The dictionary that describes all
                                      of the target volume attributes.
        :type connection_properties: dict
        :param device_info: historical difference, but same as connection_props
        :type device_info: dict
        """
        LOG.info("Connection Properties : %s", connection_properties)
        self.DETACH_VOLUME.append(connection_properties['provider_id'])
        try:
            (out, err) = self._execute(*self.DETACH_VOLUME,
                                       run_as_root=True,
                                       root_helper=self._root_helper)
            LOG.info("DeMap volume %(cmd)s: stdout=%(out)s "
                     "stderr=%(err)s", {
                         'cmd': self.ATTACH_VOLUME,
                         'out': out,
                         'err': err
                     })
            self._wait_for_disconnect(connection_properties['provider_id'])
        except putils.ProcessExecutionError as e:
            msg = (_("Error querying pxctl host detach: %(err)s") % {
                'err': e.stderr
            })
            LOG.error(msg)
            raise exception.BrickException(message=msg)
        finally:
            self.DETACH_VOLUME.pop()
        return '/dev/pxd/pxd' + connection_properties['provider_id']
예제 #21
0
파일: remotefs.py 프로젝트: deiter/os-brick
    def _do_mount(self, mount_type, vz_share, mount_path,
                  mount_options=None, flags=None):
        m = re.search(r"(?:(\S+):\/)?([a-zA-Z0-9_-]+)(?::(\S+))?", vz_share)
        if not m:
            msg = (_("Invalid Virtuozzo Storage share specification: %r."
                     "Must be: [MDS1[,MDS2],...:/]<CLUSTER NAME>[:PASSWORD].")
                   % vz_share)
            raise exception.BrickException(msg)

        mdss = m.group(1)
        cluster_name = m.group(2)
        passwd = m.group(3)

        if mdss:
            mdss = mdss.split(',')
            self._vzstorage_write_mds_list(cluster_name, mdss)

        if passwd:
            self._execute('pstorage', '-c', cluster_name, 'auth-node', '-P',
                          process_input=passwd,
                          root_helper=self._root_helper, run_as_root=True)

        mnt_cmd = ['pstorage-mount', '-c', cluster_name]
        if flags:
            mnt_cmd.extend(flags)
        mnt_cmd.extend([mount_path])

        self._execute(*mnt_cmd, root_helper=self._root_helper,
                      run_as_root=True, check_exit_code=0)
예제 #22
0
 def _get_volume_path(self, connection_properties):
     out = self._query_attached_volume(connection_properties['volume_id'])
     if not out or int(out['ret_code']) != 0:
         msg = _("Couldn't find attached volume.")
         LOG.error(msg)
         raise exception.BrickException(message=msg)
     return out['dev_addr']
예제 #23
0
파일: base.py 프로젝트: hemna/os-brick-1
 def _check_device_paths(self, device_paths):
     if len(device_paths) > 1:
         err_msg = _("Multiple volume paths were found: %s. This can "
                     "occur if multipath is used and MPIO is not "
                     "properly configured, thus not claiming the device "
                     "paths. This issue must be addressed urgently as "
                     "it can lead to data corruption.")
         raise exception.BrickException(err_msg % device_paths)
    def __init__(self, root_helper, driver=None, *args, **kwargs):

        super(StorPoolConnector, self).__init__(root_helper,
                                                driver=driver,
                                                *args,
                                                **kwargs)

        if storpool is None:
            raise exception.BrickException(
                'Could not import the StorPool API bindings')

        try:
            self._attach = spopenstack.AttachDB(log=LOG)
            self._attach.api()
        except Exception as e:
            raise exception.BrickException(
                'Could not initialize the StorPool API bindings: %s' % (e))
예제 #25
0
파일: scaleio.py 프로젝트: dr4Ke/os-brick
 def _get_guid(self):
     try:
         guid = priv_scaleio.get_guid(self.GET_GUID_OP_CODE)
         LOG.info("Current sdc guid: %s", guid)
         return guid
     except (IOError, OSError, ValueError) as e:
         msg = _("Error querying sdc guid: %s") % e
         LOG.error(msg)
         raise exception.BrickException(message=msg)
예제 #26
0
 def _extract_snapshot_name(self, volume_and_snap):
     tokens = volume_and_snap.split("@")
     if len(tokens) == 1:
         return tokens[0], None
     if len(tokens) == 2:
         return tokens[0], tokens[1]
     else:
         msg = _('Wrong volume or snapshot name %s') % volume_and_snap
         raise exception.BrickException(msg=msg)
예제 #27
0
파일: scaleio.py 프로젝트: dr4Ke/os-brick
    def _rescan_vols(self):
        LOG.info("ScaleIO rescan volumes")

        try:
            priv_scaleio.rescan_vols(self.RESCAN_VOLS_OP_CODE)
        except (IOError, OSError) as e:
            msg = _("Error querying volumes: %s") % e
            LOG.error(msg)
            raise exception.BrickException(message=msg)
예제 #28
0
 def _wait_for_disconnect(self, volume_id):
     path = "/dev/pxd/pxd" + volume_id
     if os.path.exists(path):
         msg = (_("PX volume %(volume_id)s  found at "
                  "not expected path.") % {
                      'volume_id': self.volume_id
                  })
         LOG.debug(msg)
         raise exception.BrickException(message=msg)
예제 #29
0
 def get_volume_paths(self, connection_properties):
     volume_path = None
     try:
         volume_path = self._get_volume_path(connection_properties)
     except Exception:
         msg = _("Couldn't find a volume.")
         LOG.warning(msg)
         raise exception.BrickException(message=msg)
     return [volume_path]
예제 #30
0
    def _local_attach_volume(self, connection_properties):
        # NOTE(e0ne): sanity check if ceph-common is installed.
        try:
            self._execute('which', 'rbd')
        except putils.ProcessExecutionError:
            msg = _("ceph-common package is not installed.")
            LOG.error(msg)
            raise exception.BrickException(message=msg)

        # NOTE(e0ne): map volume to a block device
        # via the rbd kernel module.
        pool, volume = connection_properties['name'].split('/')
        rbd_dev_path = self.get_rbd_device_name(pool, volume)
        # If we are not running on OpenStack, create config file
        conf = self.create_non_openstack_config(connection_properties)
        try:
            if (not os.path.islink(rbd_dev_path)
                    or not os.path.exists(os.path.realpath(rbd_dev_path))):
                # TODO(stephenfin): Update to the unified 'rbd device map'
                # command introduced in ceph 13.0 (commit 6a57358add1157629a6d)
                # when we drop support earlier versions
                cmd = ['rbd', 'map', volume, '--pool', pool]
                cmd += self._get_rbd_args(connection_properties, conf)
                self._execute(*cmd,
                              root_helper=self._root_helper,
                              run_as_root=True)
            else:
                LOG.debug(
                    'Volume %(vol)s is already mapped to local device %(dev)s',
                    {
                        'vol': volume,
                        'dev': os.path.realpath(rbd_dev_path)
                    })

            if (not os.path.islink(rbd_dev_path)
                    or not os.path.exists(os.path.realpath(rbd_dev_path))):
                LOG.warning(
                    'Volume %(vol)s has not been mapped to local device '
                    '%(dev)s; is the udev daemon running and are the '
                    'ceph-renamer udev rules configured? See bug #1884114 for '
                    'more information.',
                    {
                        'vol': volume,
                        'dev': rbd_dev_path
                    },
                )
        except Exception:
            # Cleanup conf file on failure
            with excutils.save_and_reraise_exception():
                if conf:
                    rbd_privsep.delete_if_exists(conf)

        res = {'path': rbd_dev_path, 'type': 'block'}
        if conf:
            res['conf'] = conf
        return res