Esempio n. 1
0
def create_user(user_name, user_id, group_name=None, group_id=None):
    group_name = group_name or user_name
    group_id = group_id or user_id

    try:
        execute_shell_cmd('groupadd', [],
                          '--gid',
                          group_id,
                          group_name,
                          as_root=True)
    except exception.ProcessExecutionError as err:
        if 'already exists' not in err.stderr:
            raise exception.UnprocessableEntity(
                'Failed to add group %s, error: %s' % (group_name, err.stderr))

    try:
        execute_shell_cmd('useradd', [],
                          '--uid',
                          user_id,
                          '--gid',
                          group_id,
                          '-M',
                          user_name,
                          as_root=True)
    except exception.ProcessExecutionError as err:
        if 'already exists' not in err.stderr:
            raise exception.UnprocessableEntity(
                'Failed to add user %s, error: %s' % (user_name, err.stderr))
Esempio n. 2
0
def copy(source, destination, force=False, preserve=False, recursive=True,
         **kwargs):
    """Copy a given file or directory to another location.
    Copy does NOT attempt to preserve ownership, permissions and timestamps
    unless the 'preserve' option is enabled.

    :seealso: _execute_shell_cmd for valid optional keyword arguments.

    :param source:          Path to the source location.
    :type source:           string

    :param destination:     Path to the destination location.
    :type destination:      string

    :param force:           If an existing destination file cannot be
                            opened, remove it and try again.
    :type force:            boolean

    :param preserve:        Preserve mode, ownership and timestamps.
    :type preserve:         boolean

    :param recursive:       Copy directories recursively.
    :type recursive:        boolean

    :raises:                :class:`UnprocessableEntity` if source or
                            destination not given.
    """

    if not source:
        raise exception.UnprocessableEntity(_("Missing source path."))
    elif not destination:
        raise exception.UnprocessableEntity(_("Missing destination path."))

    options = (('f', force), ('p', preserve), ('R', recursive))
    _execute_shell_cmd('cp', options, source, destination, **kwargs)
Esempio n. 3
0
def chown(path, user, group, recursive=True, force=False, **kwargs):
    """Changes the owner and group of a given file.

    seealso:: _execute_shell_cmd for valid optional keyword arguments.

    :param path:         Path to the modified file.
    :type path:          string

    :param user:         Owner.
    :type user:          string

    :param group:        Group.
    :type group:         string

    :param recursive:    Operate on files and directories recursively.
    :type recursive:     boolean

    :param force:        Suppress most error messages.
    :type force:         boolean

    :raises:             :class:`UnprocessableEntity` if path not given.
    :raises:             :class:`UnprocessableEntity` if owner/group not given.
    """

    if not path:
        raise exception.UnprocessableEntity(
            _("Cannot change ownership of a blank file or directory."))
    if not user and not group:
        raise exception.UnprocessableEntity(
            _("Please specify owner or group, or both."))

    owner_group_modifier = _build_user_group_pair(user, group)
    options = (('f', force), ('R', recursive))
    _execute_shell_cmd('chown', options, owner_group_modifier, path, **kwargs)
Esempio n. 4
0
def change_user_group(user, group, append=True, add_group=True, **kwargs):
    """Adds a user to groups by using the usermod linux command with -a and
    -G options.

    seealso:: _execute_shell_cmd for valid optional keyword arguments.

    :param user:            Username.
    :type user:             string

    :param group:           Group names.
    :type group:            comma separated string

    :param  append:         Adds user to a group.
    :type append:           boolean

    :param add_group:       Lists the groups that the user is a member of.
                            While adding a new groups to an existing user
                            with '-G' option alone, will remove all existing
                            groups that user belongs. Therefore, always add
                            the '-a' (append) with '-G' option to add or
                            append new groups.
    :type add_group:        boolean

    :raises:                :class:`UnprocessableEntity` if user or group not
                            given.
    """

    if not user:
        raise exception.UnprocessableEntity(_("Missing user."))
    elif not group:
        raise exception.UnprocessableEntity(_("Missing group."))

    options = (('a', append), ('G', add_group))
    _execute_shell_cmd('usermod', options, group, user, **kwargs)
Esempio n. 5
0
def move(source, destination, force=False, **kwargs):
    """Move a given file or directory to a new location.
    Move attempts to preserve the original ownership, permissions and
    timestamps.

    :seealso: _execute_shell_cmd for valid optional keyword arguments.

    :param source:          Path to the source location.
    :type source:           string

    :param destination:     Path to the destination location.
    :type destination:      string

    :param force:           Do not prompt before overwriting.
    :type force:            boolean

    :raises:                :class:`UnprocessableEntity` if source or
                            destination not given.
    """

    if not source:
        raise exception.UnprocessableEntity(_("Missing source path."))
    elif not destination:
        raise exception.UnprocessableEntity(_("Missing destination path."))

    options = (('f', force), )
    _execute_shell_cmd('mv', options, source, destination, **kwargs)
Esempio n. 6
0
    def add_shard(self):

        if self.db_info.task_status != ClusterTasks.NONE:
            current_task = self.db_info.task_status.name
            msg = _("This action cannot be performed on the cluster while "
                    "the current cluster task is '%s'.") % current_task
            LOG.error(msg)
            raise exception.UnprocessableEntity(msg)

        db_insts = inst_models.DBInstance.find_all(cluster_id=self.id,
                                                   type='member').all()
        num_unique_shards = len(set([db_inst.shard_id for db_inst
                                     in db_insts]))
        if num_unique_shards == 0:
            msg = _("This action cannot be performed on the cluster as no "
                    "reference shard exists.")
            LOG.error(msg)
            raise exception.UnprocessableEntity(msg)

        arbitrary_shard_id = db_insts[0].shard_id
        members_in_shard = [db_inst for db_inst in db_insts
                            if db_inst.shard_id == arbitrary_shard_id]
        num_members_per_shard = len(members_in_shard)
        a_member = inst_models.load_any_instance(self.context,
                                                 members_in_shard[0].id)
        deltas = {'instances': num_members_per_shard}
        volume_size = a_member.volume_size
        if volume_size:
            deltas['volumes'] = volume_size * num_members_per_shard
        check_quotas(self.context.tenant, deltas)
        new_replica_set_name = "rs" + str(num_unique_shards + 1)
        new_shard_id = utils.generate_uuid()
        dsv_manager = (datastore_models.DatastoreVersion.
                       load_by_uuid(db_insts[0].datastore_version_id).manager)
        manager = task_api.load(self.context, dsv_manager)
        key = manager.get_key(a_member)
        member_config = {"id": self.id,
                         "shard_id": new_shard_id,
                         "instance_type": "member",
                         "replica_set_name": new_replica_set_name,
                         "key": key}
        for i in range(1, num_members_per_shard + 1):
            instance_name = "%s-%s-%s" % (self.name, new_replica_set_name,
                                          str(i))
            inst_models.Instance.create(self.context, instance_name,
                                        a_member.flavor_id,
                                        a_member.datastore_version.image_id,
                                        [], [], a_member.datastore,
                                        a_member.datastore_version,
                                        volume_size, None,
                                        availability_zone=None,
                                        nics=None,
                                        configuration_id=None,
                                        cluster_config=member_config)

        self.update_db(task_status=ClusterTasks.ADDING_SHARD)
        manager.mongodb_add_shard_cluster(
            self.id,
            new_shard_id,
            new_replica_set_name)
Esempio n. 7
0
    def _validate_configuration(values, datastore_manager=None):
        rules = configurations.get_validation_rules(
            datastore_manager=datastore_manager)

        LOG.info(_("Validating configuration values"))
        for k, v in values.iteritems():
            # get the validation rule dictionary, which will ensure there is a
            # rule for the given key name. An exception will be thrown if no
            # valid rule is located.
            rule = ConfigurationsController._get_item(
                k, rules['configuration-parameters'])

            if rule.get('deleted_at'):
                raise exception.ConfigurationParameterDeleted(
                    parameter_name=rule.get('name'),
                    parameter_deleted_at=rule.get('deleted_at'))

            # type checking
            valueType = rule.get('type')

            if not isinstance(v, ConfigurationsController._find_type(
                    valueType)):
                output = {"key": k, "type": valueType}
                msg = _("The value provided for the configuration "
                        "parameter %(key)s is not of type %(type)s.") % output
                raise exception.UnprocessableEntity(message=msg)

            # integer min/max checking
            if isinstance(v, int):
                try:
                    min_value = int(rule.get('min'))
                except ValueError:
                    raise exception.TroveError(_(
                        "Invalid or unsupported min value defined in the "
                        "configuration-parameters configuration file. "
                        "Expected integer."))
                if v < min_value:
                    output = {"key": k, "min": min_value}
                    message = _("The value for the configuration parameter "
                                "%(key)s is less than the minimum allowed: "
                                "%(min)s") % output
                    raise exception.UnprocessableEntity(message=message)

                try:
                    max_value = int(rule.get('max'))
                except ValueError:
                    raise exception.TroveError(_(
                        "Invalid or unsupported max value defined in the "
                        "configuration-parameters configuration file. "
                        "Expected integer."))
                if v > max_value:
                    output = {"key": k, "max": max_value}
                    message = _("The value for the configuration parameter "
                                "%(key)s is greater than the maximum "
                                "allowed: %(max)s") % output
                    raise exception.UnprocessableEntity(message=message)
Esempio n. 8
0
    def create_user(self, context, users):
        if len(users) > 1:
            raise exception.UnprocessableEntity(
                _("Only a single user can be created on the instance."))

        user_list = self._list_buckets()
        if user_list:
            raise exception.UnprocessableEntity(
                _("There already is a user on this instance: %s") %
                user_list[0].name)

        self._create_bucket(models.CouchbaseUser.deserialize_user(users[0]))
Esempio n. 9
0
    def _validate_configuration(values, datastore_version=None):
        LOG.info(_("Validating configuration values"))
        for k, v in values.iteritems():
            rule = DatastoreConfigurationParameters.load_parameter_by_name(
                datastore_version.id, k)

            if not rule or rule.deleted:
                output = {"key": k}
                msg = _("The parameter provided for the configuration "
                        "%(key)s is not available.") % output
                raise exception.UnprocessableEntity(message=msg)

            # type checking
            value_type = rule.data_type

            if not isinstance(v,
                              ConfigurationsController._find_type(value_type)):
                output = {"key": k, "type": value_type}
                msg = _("The value provided for the configuration "
                        "parameter %(key)s is not of type %(type)s.") % output
                raise exception.UnprocessableEntity(message=msg)

            # integer min/max checking
            if isinstance(v, (int, long)) and not isinstance(v, bool):
                try:
                    min_value = int(rule.min_size)
                except ValueError:
                    raise exception.TroveError(
                        _("Invalid or unsupported min value defined in the "
                          "configuration-parameters configuration file. "
                          "Expected integer."))
                if v < min_value:
                    output = {"key": k, "min": min_value}
                    message = _("The value for the configuration parameter "
                                "%(key)s is less than the minimum allowed: "
                                "%(min)s") % output
                    raise exception.UnprocessableEntity(message=message)

                try:
                    max_value = int(rule.max_size)
                except ValueError:
                    raise exception.TroveError(
                        _("Invalid or unsupported max value defined in the "
                          "configuration-parameters configuration file. "
                          "Expected integer."))
                if v > max_value:
                    output = {"key": k, "max": max_value}
                    message = _("The value for the configuration parameter "
                                "%(key)s is greater than the maximum "
                                "allowed: %(max)s") % output
                    raise exception.UnprocessableEntity(message=message)
Esempio n. 10
0
def chmod(path, mode, recursive=True, force=False, **kwargs):
    """Changes the mode of a given file.

    :seealso: Modes for more information on the representation of modes.
    :seealso: _execute_shell_cmd for valid optional keyword arguments.

    :param path:            Path to the modified file.
    :type path:             string

    :param mode:            File permissions (modes).
                            The modes will be applied in the following order:
                            reset (=), add (+), remove (-)
    :type mode:             FileMode

    :param recursive:       Operate on files and directories recursively.
    :type recursive:        boolean

    :param force:           Suppress most error messages.
    :type force:            boolean

    :raises:                :class:`UnprocessableEntity` if path not given.
    :raises:                :class:`UnprocessableEntity` if no mode given.
    """

    if path:
        options = (('f', force), ('R', recursive))
        shell_modes = _build_shell_chmod_mode(mode)
        _execute_shell_cmd('chmod', options, shell_modes, path, **kwargs)
    else:
        raise exception.UnprocessableEntity(
            _("Cannot change mode of a blank file."))
Esempio n. 11
0
def create_directory(dir_path, user=None, group=None, force=True, **kwargs):
    """Create a given directory and update its ownership
    (recursively) to the given user and group if any.

    seealso:: _execute_shell_cmd for valid optional keyword arguments.

    :param dir_path:        Path to the created directory.
    :type dir_path:         string

    :param user:            Owner.
    :type user:             string

    :param group:           Group.
    :type group:            string

    :param force:           No error if existing, make parent directories
                            as needed.
    :type force:            boolean

    :raises:                :class:`UnprocessableEntity` if dir_path not given.
    """

    if dir_path:
        _create_directory(dir_path, force, **kwargs)
        if user or group:
            chown(dir_path, user, group, **kwargs)
    else:
        raise exception.UnprocessableEntity(
            _("Cannot create a blank directory."))
Esempio n. 12
0
def read_file(path, codec=IdentityCodec(), as_root=False, decode=True):
    """
    Read a file into a Python data structure
    digestible by 'write_file'.

    :param path:            Path to the read config file.
    :type path:             string

    :param codec:           A codec used to transform the data.
    :type codec:            StreamCodec

    :param as_root:         Execute as root.
    :type as_root:          boolean

    :param decode:          Should the codec decode the data.
    :type decode:           boolean

    :returns:               A dictionary of key-value pairs.

    :raises:                :class:`UnprocessableEntity` if file doesn't exist.
    :raises:                :class:`UnprocessableEntity` if codec not given.
    """
    if path and exists(path, is_directory=False, as_root=as_root):
        if as_root:
            return _read_file_as_root(path, codec, decode=decode)

        with open(path, 'r') as fp:
            if decode:
                return codec.deserialize(fp.read())
            return codec.serialize(fp.read())

    raise exception.UnprocessableEntity(_("File does not exist: %s") % path)
Esempio n. 13
0
def write_file(path, data, codec=IdentityCodec(), as_root=False, encode=True):
    """Write data into file using a given codec.
    Overwrite any existing contents.
    The written file can be read back into its original
    form by 'read_file'.

    :param path                Path to the written config file.
    :type path                 string

    :param data:               An object representing the file contents.
    :type data:                object

    :param codec:              A codec used to transform the data.
    :type codec:               StreamCodec

    :param as_root:            Execute as root.
    :type as_root:             boolean

    :param encode:             Should the codec encode the data.
    :type encode:              boolean

    :raises:                   :class:`UnprocessableEntity` if path not given.
    """
    if path:
        if as_root:
            _write_file_as_root(path, data, codec, encode=encode)
        else:
            with open(path, 'w') as fp:
                if encode:
                    fp.write(codec.serialize(data))
                else:
                    fp.write(codec.deserialize(data))
                fp.flush()
    else:
        raise exception.UnprocessableEntity(_("Invalid path: %s") % path)
Esempio n. 14
0
 def _delete_resources():
     backup = cls.get_by_id(context, backup_id)
     if backup.is_running:
         msg = _("Backup %s cannot be deleted because it is running.")
         raise exception.UnprocessableEntity(msg % backup_id)
     cls.verify_swift_auth_token(context)
     api.API(context).delete_backup(backup_id)
Esempio n. 15
0
def load_instance(cls, context, id, needs_server=False):
    db_info = get_db_info(context, id)
    if not needs_server:
        # TODO(tim.simpson): When we have notifications this won't be
        # necessary and instead we'll just use the server_status field from
        # the instance table.
        load_simple_instance_server_status(context, db_info)
        server = None
    else:
        try:
            server = load_server(context, db_info.id,
                                 db_info.compute_instance_id)
            #TODO(tim.simpson): Remove this hack when we have notifications!
            db_info.server_status = server.status
            db_info.addresses = server.addresses
        except exception.ComputeInstanceNotFound:
            LOG.error(_LE("Could not load compute instance %s."),
                      db_info.compute_instance_id)
            raise exception.UnprocessableEntity("Instance %s is not ready." %
                                                id)

    service_status = InstanceServiceStatus.find_by(instance_id=id)
    LOG.debug("Instance %(instance_id)s service status is %(service_status)s.",
              {
                  'instance_id': id,
                  'service_status': service_status.status
              })
    return cls(context, db_info, server, service_status)
Esempio n. 16
0
def read_file(path, codec=IdentityCodec(), as_root=False):
    """
    Read a file into a Python data structure
    digestible by 'write_file'.

    :param path             Path to the read config file.
    :type path              string

    :param codec:           A codec used to deserialize the data.
    :type codec:            StreamCodec

    :returns:               A dictionary of key-value pairs.

    :param as_root:         Execute as root.
    :type as_root:          boolean

    :raises:                :class:`UnprocessableEntity` if file doesn't exist.
    :raises:                :class:`UnprocessableEntity` if codec not given.
    """
    if path and os.path.exists(path):
        if as_root:
            return _read_file_as_root(path, codec)
        with open(path, 'r') as fp:
            return codec.deserialize(fp.read())

    raise exception.UnprocessableEntity(_("File does not exist: %s") % path)
Esempio n. 17
0
 def config_set(self, name, value):
     response = self.execute(
         '%s %s' % (self.__config_cmd_name, 'SET'), name, value)
     if not self._is_ok_response(response):
         raise exception.UnprocessableEntity(
             _("Could not set configuration property '%(name)s' to "
               "'%(value)s'.") % {'name': name, 'value': value})
Esempio n. 18
0
File: api.py Progetto: liuchin/trove
    def _prep_resize(self):
        """Get information about the cluster's current state."""
        if self.db_info.task_status != ClusterTasks.NONE:
            current_task = self.db_info.task_status.name
            log_fmt = ("This action cannot be performed on the cluster while "
                       "the current cluster task is '%s'.")
            exc_fmt = _("This action cannot be performed on the cluster while "
                        "the current cluster task is '%s'.")
            LOG.error(log_fmt, current_task)
            raise exception.UnprocessableEntity(exc_fmt % current_task)

        def _instances_of_type(instance_type):
            return [
                db_inst for db_inst in self.db_instances
                if db_inst.type == instance_type
            ]

        self.config_svrs = _instances_of_type('config_server')
        self.query_routers = _instances_of_type('query_router')
        self.members = _instances_of_type('member')
        self.shard_ids = set([member.shard_id for member in self.members])
        self.arbitrary_query_router = inst_models.load_any_instance(
            self.context, self.query_routers[0].id)
        self.manager = task_api.load(self.context,
                                     self.datastore_version.manager)
Esempio n. 19
0
 def validate_cluster_available(self, valid_states=[ClusterTasks.NONE]):
     if self.db_info.task_status not in valid_states:
         msg = (_("This action cannot be performed on the cluster while "
                  "the current cluster task is '%s'.") %
                self.db_info.task_status.name)
         LOG.error(msg)
         raise exception.UnprocessableEntity(msg)
Esempio n. 20
0
    def execute(self, query, identifiers=None, data_values=None, timeout=None):
        """
        Execute a query with a given sequence or dict of data values to bind.
        If a sequence is used, '%s' should be used the placeholder for each
        argument. If a dict is used, '%(name)s' style placeholders must
        be used.
        Only data values should be supplied this way. Other items,
        such as keyspaces, table names, and column names should be set
        ahead of time. Use the '{}' style placeholders and
        'identifiers' parameter for those.
        Raise an exception if the operation exceeds the given timeout (sec).
        There is no timeout if set to None.
        Return a set of rows or an empty list if None.
        """
        if self.__is_active():
            try:
                rows = self.__session.execute(self.__bind(query, identifiers),
                                              data_values, timeout)
                return rows or []
            except OperationTimedOut:
                LOG.error(_("Query execution timed out."))
                raise

        LOG.debug("Cannot perform this operation on a closed connection.")
        raise exception.UnprocessableEntity()
Esempio n. 21
0
    def validate_can_perform_action(self):
        """
        Raises exception if an instance action cannot currently be performed.
        """
        # cases where action cannot be performed
        if self.db_info.server_status != 'ACTIVE':
            status = self.db_info.server_status
        elif (self.db_info.task_status != InstanceTasks.NONE
              and self.db_info.task_status != InstanceTasks.RESTART_REQUIRED):
            status = self.db_info.task_status
        elif not self.datastore_status.status.action_is_allowed:
            status = self.status
        elif Backup.running(self.id):
            status = InstanceStatus.BACKUP
        else:
            # action can be performed
            return

        msg = (_("Instance %(instance_id)s is not currently available for an "
                 "action to be performed (status was %(action_status)s).") % {
                     'instance_id': self.id,
                     'action_status': status
                 })
        LOG.error(msg)
        raise exception.UnprocessableEntity(msg)
Esempio n. 22
0
def _build_shell_chmod_mode(mode):
    """
    Build a shell representation of given mode.

    :seealso: Modes for more information on the representation of modes.

    :param mode:            File permissions (modes).
    :type mode:             FileModes

    :raises:                :class:`UnprocessableEntity` if no mode given.

    :returns: Following string for any non-empty modes:
              '=<reset mode>,+<add mode>,-<remove mode>'
    """

    # Handle methods passed in as constant fields.
    if inspect.ismethod(mode):
        mode = mode()

    if mode and mode.has_any():
        text_modes = (('=', mode.get_reset_mode()), ('+', mode.get_add_mode()),
                      ('-', mode.get_remove_mode()))
        return ','.join([
            '{0:s}{1:03o}'.format(item[0], item[1]) for item in text_modes
            if item[1]
        ])
    else:
        raise exception.UnprocessableEntity(_("No file mode specified."))
Esempio n. 23
0
def load_and_verify(context, instance_id):
    # Load InstanceServiceStatus to verify if its running
    instance = base_models.Instance.load(context, instance_id)
    if not instance.is_datastore_running:
        raise exception.UnprocessableEntity("Instance %s is not ready." %
                                            instance.id)
    else:
        return instance
Esempio n. 24
0
    def update_attributes(self, context, username, hostname, user_attrs):
        new_name = user_attrs.get('name')
        if new_name:
            raise exception.UnprocessableEntity(_("Users cannot be renamed."))

        new_password = user_attrs.get('password')
        if new_password:
            user = models.CouchbaseUser(username, password=new_password)
            self._edit_bucket(user)
Esempio n. 25
0
 def _delete_resources():
     if self.is_building:
         raise exception.UnprocessableEntity("Instance %s is not ready."
                                             % self.id)
     LOG.debug(_("  ... deleting compute id = %s") %
               self.db_info.compute_instance_id)
     LOG.debug(_(" ... setting status to DELETING."))
     self.update_db(task_status=InstanceTasks.DELETING)
     task_api.API(self.context).delete_instance(self.id)
Esempio n. 26
0
def get_validation_rules(datastore_manager='mysql'):
    try:
        config_location = ("%s/validation-rules.json" % datastore_manager)
        template = ENV.get_template(config_location)
        return json.loads(template.render())
    except Exception:
        msg = "This operation is not supported for this datastore at this time"
        LOG.exception(msg)
        raise exception.UnprocessableEntity(message=msg)
Esempio n. 27
0
 def max_num_overrides(self, value):
     """
     Maximum number of configuration overrides that can be attached to this
     instance.
     """
     if value and value < 0:
         raise exception.UnprocessableEntity(
             _("The maximum number of attached Configuration Groups "
               "cannot be negative."))
     self._max_num_overrides = value
Esempio n. 28
0
 def instance_root_index(self, req, tenant_id, instance_id):
     LOG.info(_LI("Getting root enabled for instance '%s'.") % instance_id)
     LOG.info(_LI("req : '%s'\n\n") % req)
     context = req.environ[wsgi.CONTEXT_KEY]
     try:
         is_root_enabled = models.ClusterRoot.load(context, instance_id)
     except exception.UnprocessableEntity:
         raise exception.UnprocessableEntity(
             _("Cluster %s is not ready.") % instance_id)
     return wsgi.Result(views.RootEnabledView(is_root_enabled).data(), 200)
Esempio n. 29
0
def load_and_verify(context,
                    instance_id,
                    enabled_datastore=['mysql', 'mariadb']):
    """Check instance datastore.

    Some API operations are only supported for some specific datastores.
    """
    instance = base_models.Instance.load(context, instance_id)

    if instance.datastore_version.manager not in enabled_datastore:
        raise exception.UnprocessableEntity(
            "Operation not supported for datastore "
            f"{instance.datastore_version.manager}.")

    if not instance.is_datastore_running:
        raise exception.UnprocessableEntity(
            "Instance %s is not ready, status: %s." %
            (instance.id, instance.datastore_status.status))

    return instance
Esempio n. 30
0
 def _execute_stmt(self, statement, identifiers, data_values, fetch):
     if statement:
         with psycopg2.connect(**self._connection_args) as connection:
             connection.autocommit = self._autocommit
             with connection.cursor() as cursor:
                 cursor.execute(self._bind(statement, identifiers),
                                data_values)
                 if fetch:
                     return cursor.fetchall()
     else:
         raise exception.UnprocessableEntity(
             _("Invalid SQL statement: %s") % statement)