Пример #1
0
    def mounted_on_same_shared_storage(self, context, instance_ref, dest):
        """Check if the src and dest host mount same shared storage.

        At first, dest host creates temp file, and src host can see
        it if they mounts same shared storage. Then src host erase it.

        :param context: security context
        :param instance_ref: cinder.db.sqlalchemy.models.Instance object
        :param dest: destination host

        """

        src = instance_ref['host']
        dst_t = rpc.queue_get_for(context, FLAGS.compute_topic, dest)
        src_t = rpc.queue_get_for(context, FLAGS.compute_topic, src)

        filename = rpc.call(context, dst_t,
                            {"method": 'create_shared_storage_test_file'})

        try:
            # make sure existence at src host.
            ret = rpc.call(context, src_t,
                        {"method": 'check_shared_storage_test_file',
                        "args": {'filename': filename}})

        finally:
            rpc.cast(context, dst_t,
                    {"method": 'cleanup_shared_storage_test_file',
                    "args": {'filename': filename}})

        return ret
Пример #2
0
    def test_cast_to_volume_host_update_db_with_volume_id(self):
        host = 'fake_host1'
        method = 'fake_method'
        fake_kwargs = {'volume_id': 31337, 'extra_arg': 'meow'}
        queue = 'fake_queue'

        self.mox.StubOutWithMock(timeutils, 'utcnow')
        self.mox.StubOutWithMock(db, 'volume_update')
        self.mox.StubOutWithMock(rpc, 'queue_get_for')
        self.mox.StubOutWithMock(rpc, 'cast')

        timeutils.utcnow().AndReturn('fake-now')
        db.volume_update(self.context, 31337, {
            'host': host,
            'scheduled_at': 'fake-now'
        })
        rpc.queue_get_for(self.context, FLAGS.volume_topic,
                          host).AndReturn(queue)
        rpc.cast(self.context, queue, {'method': method, 'args': fake_kwargs})

        self.mox.ReplayAll()
        driver.cast_to_volume_host(self.context,
                                   host,
                                   method,
                                   update_db=True,
                                   **fake_kwargs)
Пример #3
0
    def test_cast_to_volume_host_no_update_db(self):
        host = "fake_host1"
        method = "fake_method"
        fake_kwargs = {"extra_arg": "meow"}
        queue = "fake_queue"

        self.mox.StubOutWithMock(rpc, "queue_get_for")
        self.mox.StubOutWithMock(rpc, "cast")

        rpc.queue_get_for(self.context, FLAGS.volume_topic, host).AndReturn(queue)
        rpc.cast(self.context, queue, {"method": method, "args": fake_kwargs})

        self.mox.ReplayAll()
        driver.cast_to_volume_host(self.context, host, method, update_db=False, **fake_kwargs)
Пример #4
0
 def delete_backup(self, ctxt, host, backup_id):
     LOG.debug("delete_backup  rpcapi backup_id %s", backup_id)
     topic = rpc.queue_get_for(ctxt, self.topic, host)
     self.cast(ctxt,
               self.make_msg('delete_backup',
                             backup_id=backup_id),
               topic=topic)
Пример #5
0
 def create_export(self, ctxt, volume):
     return self.call(ctxt,
                      self.make_msg('create_export',
                                    volume_id=volume['id']),
                      topic=rpc.queue_get_for(ctxt, self.topic,
                                              volume['host']),
                      version='1.13')
Пример #6
0
 def copy_volume_to_image(self, ctxt, volume, image_id):
     self.cast(ctxt, self.make_msg('copy_volume_to_image',
                                   volume_id=volume['id'],
                                   image_id=image_id),
               topic=rpc.queue_get_for(ctxt,
                                       self.topic,
                                       volume['host']))
Пример #7
0
 def rename_volume(self, ctxt, volume, new_name_id):
     self.call(ctxt,
               self.make_msg('rename_volume',
                             volume_id=volume['id'],
                             new_name_id=new_name_id),
               topic=rpc.queue_get_for(ctxt, self.topic, volume['host']),
               version='1.8')
Пример #8
0
 def accept_transfer(self, ctxt, volume, new_user, new_project):
     self.cast(
         ctxt,
         self.make_msg("accept_transfer", volume_id=volume["id"], new_user=new_user, new_project=new_project),
         topic=rpc.queue_get_for(ctxt, self.topic, volume["host"]),
         version="1.9",
     )
Пример #9
0
 def remove_from_compute(self, context, volume, instance_id, host):
     """Remove volume from specified compute host."""
     rpc.call(context,
              rpc.queue_get_for(context, FLAGS.compute_topic, host),
              {"method": "remove_volume_connection",
               "args": {'instance_id': instance_id,
                        'volume_id': volume['id']}})
Пример #10
0
 def remove_from_compute(self, context, volume, instance_id, host):
     """Remove volume from specified compute host."""
     rpc.call(context,
              rpc.queue_get_for(context, FLAGS.compute_topic, host),
              {"method": "remove_volume_connection",
               "args": {'instance_id': instance_id,
                        'volume_id': volume['id']}})
Пример #11
0
 def rename_volume(self, ctxt, volume, new_name_id):
     self.call(ctxt,
               self.make_msg('rename_volume',
                             volume_id=volume['id'],
                             new_name_id=new_name_id),
               topic=rpc.queue_get_for(ctxt, self.topic, volume['host']),
               version='1.8')
Пример #12
0
    def _cast_create_volume(self, context, request_spec, filter_properties):

        # NOTE(Rongze Zhu): It is a simple solution for bug 1008866
        # If snapshot_id is set, make the call create volume directly to
        # the volume host where the snapshot resides instead of passing it
        # through the scheduler. So snapshot can be copy to new volume.

        volume_id = request_spec['volume_id']
        snapshot_id = request_spec['snapshot_id']
        image_id = request_spec['image_id']

        if snapshot_id and FLAGS.snapshot_same_host:
            snapshot_ref = self.db.snapshot_get(context, snapshot_id)
            src_volume_ref = self.db.volume_get(context,
                                                snapshot_ref['volume_id'])
            topic = rpc.queue_get_for(context,
                                      FLAGS.volume_topic,
                                      src_volume_ref['host'])
            # bypass scheduler and send request directly to volume
            rpc.cast(context,
                     topic,
                     {"method": "create_volume",
                      "args": {"volume_id": volume_id,
                               "snapshot_id": snapshot_id,
                               "image_id": image_id}})
        else:
            self.scheduler_rpcapi.create_volume(context,
                FLAGS.volume_topic,
                volume_id,
                snapshot_id,
                image_id,
                request_spec=request_spec,
                filter_properties=filter_properties)
Пример #13
0
 def create_backup(self, ctxt, host, backup_id, volume_id):
     LOG.debug("create_backup in rpcapi backup_id %s", backup_id)
     topic = rpc.queue_get_for(ctxt, self.topic, host)
     LOG.debug("create queue topic=%s", topic)
     self.cast(ctxt,
               self.make_msg('create_backup', backup_id=backup_id),
               topic=topic)
Пример #14
0
 def delete_replica(self, ctxt, secondary, relationship):
     return self.call(ctxt,
                      self.make_msg('delete_replica',
                                    relationship_id=relationship['id']),
                      topic=rpc.queue_get_for(ctxt, self.topic,
                                              secondary['host']),
                      version='1.12')
Пример #15
0
 def copy_volume_to_image(self, ctxt, volume, image_meta):
     self.cast(ctxt,
               self.make_msg('copy_volume_to_image',
                             volume_id=volume['id'],
                             image_meta=image_meta),
               topic=rpc.queue_get_for(ctxt, self.topic, volume['host']),
               version='1.3')
Пример #16
0
 def initialize_connection(self, ctxt, volume, connector):
     return self.call(ctxt, self.make_msg('initialize_connection',
                                          volume_id=volume['id'],
                                          connector=connector),
                      topic=rpc.queue_get_for(ctxt,
                                              self.topic,
                                              volume['host']))
Пример #17
0
 def initialize_connection(self, context, volume, connector):
     host = volume['host']
     queue = rpc.queue_get_for(context, FLAGS.volume_topic, host)
     return rpc.call(context, queue,
                     {"method": "initialize_connection",
                      "args": {"volume_id": volume['id'],
                               "connector": connector}})
Пример #18
0
 def initialize_connection(self, ctxt, volume, connector):
     return self.call(ctxt, self.make_msg('initialize_connection',
                                          volume_id=volume['id'],
                                          connector=connector),
                      topic=rpc.queue_get_for(ctxt,
                                              self.topic,
                                              volume['host']))
Пример #19
0
    def copy_volume_to_image(self, context, volume, metadata, force):
        """Create a new image from the specified volume."""
        self._check_volume_availability(context, volume, force)

        recv_metadata = self.image_service.create(context, metadata)
        self.update(context, volume, {'status': 'uploading'})
        rpc.cast(context,
                 rpc.queue_get_for(context,
                                   FLAGS.volume_topic,
                                   volume['host']),
                 {"method": "copy_volume_to_image",
                  "args": {"volume_id": volume['id'],
                           "image_id": recv_metadata['id']}})

        response = {"id": volume['id'],
               "updated_at": volume['updated_at'],
               "status": 'uploading',
               "display_description": volume['display_description'],
               "size": volume['size'],
               "volume_type": volume['volume_type'],
               "image_id": recv_metadata['id'],
               "container_format": recv_metadata['container_format'],
               "disk_format": recv_metadata['disk_format'],
               "image_name": recv_metadata.get('name', None)
        }
        return response
Пример #20
0
 def create_volume(
     self,
     ctxt,
     volume,
     host,
     request_spec,
     filter_properties,
     allow_reschedule=True,
     snapshot_id=None,
     image_id=None,
     source_volid=None,
 ):
     self.cast(
         ctxt,
         self.make_msg(
             "create_volume",
             volume_id=volume["id"],
             request_spec=request_spec,
             filter_properties=filter_properties,
             allow_reschedule=allow_reschedule,
             snapshot_id=snapshot_id,
             image_id=image_id,
             source_volid=source_volid,
         ),
         topic=rpc.queue_get_for(ctxt, self.topic, host),
         version="1.4",
     )
Пример #21
0
 def accept_transfer(self, ctxt, volume):
     self.cast(
         ctxt,
         self.make_msg("accept_transfer", volume_id=volume["id"]),
         topic=rpc.queue_get_for(ctxt, self.topic, volume["host"]),
         version="1.5",
     )
Пример #22
0
 def delete_backup(self, ctxt, host, backup_id):
     LOG.debug("delete_backup  rpcapi backup_id %s", backup_id)
     topic = rpc.queue_get_for(ctxt, self.topic, host)
     self.cast(ctxt,
               self.make_msg('delete_backup',
                             backup_id=backup_id),
               topic=topic)
Пример #23
0
 def initialize_connection(self, context, volume, connector):
     host = volume['host']
     queue = rpc.queue_get_for(context, FLAGS.volume_topic, host)
     return rpc.call(context, queue,
                     {"method": "initialize_connection",
                      "args": {"volume_id": volume['id'],
                               "connector": connector}})
Пример #24
0
 def replication_swap(self, ctxt, relationship):
     host = relationship['primary_volume']['host']
     return self.cast(ctxt,
                      self.make_msg('replication_swap',
                                    relationship_id=relationship['id']),
                      topic=rpc.queue_get_for(ctxt, self.topic, host),
                      version='1.12')
Пример #25
0
 def create_export(self, ctxt, volume):
     return self.call(
         ctxt,
         self.make_msg("create_export", volume_id=volume["id"]),
         topic=rpc.queue_get_for(ctxt, self.topic, volume["host"]),
         version="1.13",
     )
Пример #26
0
    def delete(self, context, volume, force=False):
        volume_id = volume['id']
        if not volume['host']:
            # NOTE(vish): scheduling failed, so delete it
            # Note(zhiteng): update volume quota reservation
            try:
                reservations = QUOTAS.reserve(context, volumes=-1,
                                              gigabytes=-volume['size'])
            except Exception:
                reservations = None
                LOG.exception(_("Failed to update quota for deleting volume"))

            self.db.volume_destroy(context, volume_id)

            if reservations:
                QUOTAS.commit(context, reservations)
            return
        if not force and volume['status'] not in ["available", "error"]:
            msg = _("Volume status must be available or error")
            raise exception.InvalidVolume(reason=msg)

        snapshots = self.db.snapshot_get_all_for_volume(context, volume_id)
        if len(snapshots):
            msg = _("Volume still has %d dependent snapshots") % len(snapshots)
            raise exception.InvalidVolume(reason=msg)

        now = timeutils.utcnow()
        self.db.volume_update(context, volume_id, {'status': 'deleting',
                                                   'terminated_at': now})
        host = volume['host']
        rpc.cast(context,
                 rpc.queue_get_for(context, FLAGS.volume_topic, host),
                 {"method": "delete_volume",
                  "args": {"volume_id": volume_id}})
Пример #27
0
    def _cast_create_volume(self, context, volume_id, snapshot_id,
                            image_id):

        # NOTE(Rongze Zhu): It is a simple solution for bug 1008866
        # If snapshot_id is set, make the call create volume directly to
        # the volume host where the snapshot resides instead of passing it
        # through the scheduer. So snapshot can be copy to new volume.

        if snapshot_id and FLAGS.snapshot_same_host:
            snapshot_ref = self.db.snapshot_get(context, snapshot_id)
            src_volume_ref = self.db.volume_get(context,
                                                snapshot_ref['volume_id'])
            topic = rpc.queue_get_for(context,
                                      FLAGS.volume_topic,
                                      src_volume_ref['host'])
            rpc.cast(context,
                     topic,
                     {"method": "create_volume",
                      "args": {"volume_id": volume_id,
                               "snapshot_id": snapshot_id,
                               "image_id": image_id}})
        else:
            rpc.cast(context,
                     FLAGS.scheduler_topic,
                     {"method": "create_volume",
                      "args": {"topic": FLAGS.volume_topic,
                               "volume_id": volume_id,
                               "snapshot_id": snapshot_id,
                               "image_id": image_id}})
Пример #28
0
 def extend_volume(self, ctxt, volume, new_size):
     self.cast(
         ctxt,
         self.make_msg("extend_volume", volume_id=volume["id"], new_size=new_size),
         topic=rpc.queue_get_for(ctxt, self.topic, volume["host"]),
         version="1.6",
     )
Пример #29
0
 def copy_volume_to_image(self, ctxt, volume, image_meta):
     self.cast(
         ctxt,
         self.make_msg("copy_volume_to_image", volume_id=volume["id"], image_meta=image_meta),
         topic=rpc.queue_get_for(ctxt, self.topic, volume["host"]),
         version="1.3",
     )
Пример #30
0
 def create_export(self, ctxt, volume):
     return self.call(ctxt, self.make_msg('create_export',
                                          volume_id=volume['id']),
                      topic=rpc.queue_get_for(ctxt,
                                              self.topic,
                                              volume['host']),
                      version='1.13')
Пример #31
0
    def _create_snapshot(self, context, volume, name, description,
                         force=False):
        check_policy(context, 'create_snapshot', volume)

        if ((not force) and (volume['status'] != "available")):
            msg = _("must be available")
            raise exception.InvalidVolume(reason=msg)

        options = {
            'volume_id': volume['id'],
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': "creating",
            'progress': '0%',
            'volume_size': volume['size'],
            'display_name': name,
            'display_description': description}

        snapshot = self.db.snapshot_create(context, options)
        host = volume['host']
        rpc.cast(context,
                 rpc.queue_get_for(context, FLAGS.volume_topic, host),
                 {"method": "create_snapshot",
                  "args": {"volume_id": volume['id'],
                           "snapshot_id": snapshot['id']}})
        return snapshot
Пример #32
0
    def _create_snapshot(self, context, volume, name, description,
                         force=False):
        check_policy(context, 'create_snapshot', volume)

        if ((not force) and (volume['status'] != "available")):
            msg = _("must be available")
            raise exception.InvalidVolume(reason=msg)

        options = {
            'volume_id': volume['id'],
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': "creating",
            'progress': '0%',
            'volume_size': volume['size'],
            'display_name': name,
            'display_description': description}

        snapshot = self.db.snapshot_create(context, options)
        host = volume['host']
        rpc.cast(context,
                 rpc.queue_get_for(context, FLAGS.volume_topic, host),
                 {"method": "create_snapshot",
                  "args": {"volume_id": volume['id'],
                           "snapshot_id": snapshot['id']}})
        return snapshot
Пример #33
0
 def extend_volume(self, ctxt, volume, new_size):
     self.cast(ctxt,
               self.make_msg('extend_volume',
                             volume_id=volume['id'],
                             new_size=new_size),
               topic=rpc.queue_get_for(ctxt, self.topic, volume['host']),
               version='1.6')
Пример #34
0
 def accept_transfer(self, ctxt, volume, new_user, new_project):
     self.cast(ctxt,
               self.make_msg('accept_transfer',
                             volume_id=volume['id'],
                             new_user=new_user,
                             new_project=new_project),
               topic=rpc.queue_get_for(ctxt, self.topic, volume['host']),
               version='1.9')
Пример #35
0
 def terminate_connection(self, ctxt, volume, connector, force=False):
     return self.call(ctxt, self.make_msg('terminate_connection',
                                          volume_id=volume['id'],
                                          connector=connector,
                                          force=force),
                      topic=rpc.queue_get_for(ctxt,
                                              self.topic,
                                              volume['host']))
Пример #36
0
 def create_backup(self, ctxt, host, backup_id, volume_id):
     LOG.debug("create_backup in rpcapi backup_id %s", backup_id)
     topic = rpc.queue_get_for(ctxt, self.topic, host)
     LOG.debug("create queue topic=%s", topic)
     self.cast(ctxt,
               self.make_msg('create_backup',
                             backup_id=backup_id),
               topic=topic)
Пример #37
0
 def attach_volume(self, ctxt, volume, instance_uuid, mountpoint):
     return self.call(ctxt,
                      self.make_msg('attach_volume',
                                    volume_id=volume['id'],
                                    instance_uuid=instance_uuid,
                                    mountpoint=mountpoint),
                      topic=rpc.queue_get_for(ctxt, self.topic,
                                              volume['host']))
Пример #38
0
 def attach(self, context, volume, instance_uuid, mountpoint):
     host = volume['host']
     queue = rpc.queue_get_for(context, FLAGS.volume_topic, host)
     return rpc.call(context, queue,
                     {"method": "attach_volume",
                      "args": {"volume_id": volume['id'],
                               "instance_uuid": instance_uuid,
                               "mountpoint": mountpoint}})
Пример #39
0
 def migrate_volume(self, ctxt, volume, dest_host, force_host_copy):
     host_p = {"host": dest_host.host, "capabilities": dest_host.capabilities}
     self.cast(
         ctxt,
         self.make_msg("migrate_volume", volume_id=volume["id"], host=host_p, force_host_copy=force_host_copy),
         topic=rpc.queue_get_for(ctxt, self.topic, volume["host"]),
         version="1.8",
     )
Пример #40
0
 def terminate_connection(self, context, volume, connector):
     self.unreserve_volume(context, volume)
     host = volume['host']
     queue = rpc.queue_get_for(context, FLAGS.volume_topic, host)
     return rpc.call(context, queue,
                     {"method": "terminate_connection",
                      "args": {"volume_id": volume['id'],
                               "connector": connector}})
Пример #41
0
 def attach_volume(self, ctxt, volume, instance_uuid, mountpoint):
     return self.call(ctxt, self.make_msg('attach_volume',
                                          volume_id=volume['id'],
                                          instance_uuid=instance_uuid,
                                          mountpoint=mountpoint),
                      topic=rpc.queue_get_for(ctxt,
                                              self.topic,
                                              volume['host']))
Пример #42
0
 def terminate_connection(self, context, volume, connector):
     self.unreserve_volume(context, volume)
     host = volume['host']
     queue = rpc.queue_get_for(context, FLAGS.volume_topic, host)
     return rpc.call(context, queue,
                     {"method": "terminate_connection",
                      "args": {"volume_id": volume['id'],
                               "connector": connector}})
Пример #43
0
 def terminate_connection(self, ctxt, volume, connector, force=False):
     return self.call(ctxt, self.make_msg('terminate_connection',
                                          volume_id=volume['id'],
                                          connector=connector,
                                          force=force),
                      topic=rpc.queue_get_for(ctxt,
                                              self.topic,
                                              volume['host']))
Пример #44
0
 def attach(self, context, volume, instance_uuid, mountpoint):
     host = volume['host']
     queue = rpc.queue_get_for(context, FLAGS.volume_topic, host)
     return rpc.call(context, queue,
                     {"method": "attach_volume",
                      "args": {"volume_id": volume['id'],
                               "instance_uuid": instance_uuid,
                               "mountpoint": mountpoint}})
Пример #45
0
 def detach(self, context, volume):
     host = volume['host']
     queue = rpc.queue_get_for(context, FLAGS.volume_topic, host)
     return rpc.call(context, queue, {
         "method": "detach_volume",
         "args": {
             "volume_id": volume['id']
         }
     })
Пример #46
0
 def migrate_volume_completion(self, ctxt, volume, new_volume, error):
     return self.call(ctxt,
                      self.make_msg('migrate_volume_completion',
                                    volume_id=volume['id'],
                                    new_volume_id=new_volume['id'],
                                    error=error),
                      topic=rpc.queue_get_for(ctxt, self.topic,
                                              volume['host']),
                      version='1.10')
Пример #47
0
    def test_cast_to_volume_host_no_update_db(self):
        host = 'fake_host1'
        method = 'fake_method'
        fake_kwargs = {'extra_arg': 'meow'}
        queue = 'fake_queue'

        self.mox.StubOutWithMock(rpc, 'queue_get_for')
        self.mox.StubOutWithMock(rpc, 'cast')

        rpc.queue_get_for(self.context, FLAGS.volume_topic,
                          host).AndReturn(queue)
        rpc.cast(self.context, queue, {'method': method, 'args': fake_kwargs})

        self.mox.ReplayAll()
        driver.cast_to_volume_host(self.context,
                                   host,
                                   method,
                                   update_db=False,
                                   **fake_kwargs)
Пример #48
0
 def migrate_volume(self, ctxt, volume, dest_host, force_host_copy):
     host_p = {'host': dest_host.host,
               'capabilities': dest_host.capabilities}
     self.cast(ctxt,
               self.make_msg('migrate_volume',
                             volume_id=volume['id'],
                             host=host_p,
                             force_host_copy=force_host_copy),
               topic=rpc.queue_get_for(ctxt, self.topic, volume['host']),
               version='1.8')
Пример #49
0
 def export_record(self, ctxt, host, backup_id):
     LOG.debug(
         "export_record in rpcapi backup_id %(id)s "
         "on host %(host)s.", {
             'id': backup_id,
             'host': host
         })
     topic = rpc.queue_get_for(ctxt, self.topic, host)
     LOG.debug("export queue topic=%s" % topic)
     return self.call(ctxt,
                      self.make_msg('export_record', backup_id=backup_id),
                      topic=topic)
Пример #50
0
 def delete_snapshot(self, context, snapshot, force=False):
     if not force and snapshot['status'] not in ["available", "error"]:
         msg = _("Volume Snapshot status must be available or error")
         raise exception.InvalidVolume(reason=msg)
     self.db.snapshot_update(context, snapshot['id'],
                             {'status': 'deleting'})
     volume = self.db.volume_get(context, snapshot['volume_id'])
     host = volume['host']
     rpc.cast(context,
              rpc.queue_get_for(context, FLAGS.volume_topic, host),
              {"method": "delete_snapshot",
               "args": {"snapshot_id": snapshot['id']}})
Пример #51
0
 def attach_volume(self, ctxt, volume, instance_uuid, host_name,
                   mountpoint, mode):
     return self.call(ctxt, self.make_msg('attach_volume',
                                          volume_id=volume['id'],
                                          instance_uuid=instance_uuid,
                                          host_name=host_name,
                                          mountpoint=mountpoint,
                                          mode=mode),
                      topic=rpc.queue_get_for(ctxt,
                                              self.topic,
                                              volume['host']),
                      version='1.11')
Пример #52
0
def cast_to_host(context, topic, host, method, update_db=True, **kwargs):
    """Generic cast to host"""

    topic_mapping = {"volume": cast_to_volume_host}

    func = topic_mapping.get(topic)
    if func:
        func(context, host, method, update_db=update_db, **kwargs)
    else:
        rpc.cast(context, rpc.queue_get_for(context, topic, host), {
            "method": method,
            "args": kwargs
        })
        LOG.debug(_("Casted '%(method)s' to %(topic)s '%(host)s'") % locals())
Пример #53
0
def cast_to_volume_host(context, host, method, update_db=True, **kwargs):
    """Cast request to a volume host queue"""

    if update_db:
        volume_id = kwargs.get('volume_id', None)
        if volume_id is not None:
            now = timeutils.utcnow()
            db.volume_update(context, volume_id, {
                'host': host,
                'scheduled_at': now
            })
    rpc.cast(context, rpc.queue_get_for(context, FLAGS.volume_topic, host), {
        "method": method,
        "args": kwargs
    })
    LOG.debug(_("Casted '%(method)s' to host '%(host)s'") % locals())