Seperate source client from destination client
authorStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 27 Feb 2013 11:12:59 +0000 (13:12 +0200)
committerStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 27 Feb 2013 11:12:59 +0000 (13:12 +0200)
Concerns store_copy operation and aims to clean up the code that
implements the account-to-account copy

kamaki/cli/commands/errors.py
kamaki/cli/commands/pithos_cli.py

index df88e80..105adb1 100644 (file)
@@ -417,6 +417,20 @@ class pithos(object):
         return generic._connection(foo, 'store.url')
 
     @classmethod
+    def account(this, foo):
+        def _raise(self, *args, **kwargs):
+            try:
+                return foo(self, *args, **kwargs)
+            except ClientError as ce:
+                if ce.status == 403:
+                    raiseCLIError(
+                        ce,
+                        'Invalid account credentials for this operation',
+                        details=['Check user account settings'])
+                raise
+        return _raise
+
+    @classmethod
     def quota(this, foo):
         def _raise(self, *args, **kwargs):
             try:
index 8e2ed10..049eaea 100644 (file)
@@ -218,25 +218,6 @@ class _store_container_command(_store_account_command):
             'Set container to work with (temporary)',
             '--container')
 
-    @errors.generic.all
-    def _dest_container_path(self, dest_container_path):
-        if self['destination_container']:
-            return (self['destination_container'], dest_container_path)
-        if dest_container_path:
-            dst = dest_container_path.split(':')
-            if len(dst) > 1:
-                try:
-                    self.client.container = dst[0]
-                    self.client.get_container_info(dst[0])
-                except ClientError as err:
-                    if err.status in (404, 204):
-                        raiseCLIError(
-                            'Destination container %s not found' % dst[0])
-                    raise
-                return (dst[0], dst[1])
-            return(None, dst[0])
-        raiseCLIError('No destination container:path provided')
-
     def extract_container_and_path(
             self,
             container_with_path,
@@ -529,7 +510,7 @@ class store_create(_store_container_command):
 class _source_destination_command(_store_container_command):
 
     arguments = dict(
-        source_account=ValueArgument('', '--src-account'),
+        destination_account=ValueArgument('', '--dst-account'),
         recursive=FlagArgument('', ('-r', '--recursive')),
         prefix=FlagArgument('', '--with-prefix', default=''),
         suffix=ValueArgument('', '--with-suffix', default=''),
@@ -543,14 +524,44 @@ class _source_destination_command(_store_container_command):
         self.arguments.update(arguments)
         super(_source_destination_command, self).__init__(self.arguments)
 
+    def _run(self, source_container___path, path_is_optional=False):
+        super(_source_destination_command, self)._run(
+            source_container___path,
+            path_is_optional)
+        self.dst_client = PithosClient(
+            base_url=self.client.base_url,
+            token=self.client.token,
+            account=self['destination_account'] or self.client.account)
+
+    @errors.generic.all
+    @errors.pithos.account
+    def _dest_container_path(self, dest_container_path):
+        if self['destination_container']:
+            self.dst_client.container = self['destination_container']
+            return (self['destination_container'], dest_container_path)
+        if dest_container_path:
+            dst = dest_container_path.split(':')
+            if len(dst) > 1:
+                try:
+                    self.dst_client.container = dst[0]
+                    self.dst_client.get_container_info(dst[0])
+                except ClientError as err:
+                    if err.status in (404, 204):
+                        raiseCLIError(
+                            'Destination container %s not found' % dst[0])
+                    raise
+                else:
+                    self.dst_client.container = dst[0]
+                return (dst[0], dst[1])
+            return(None, dst[0])
+        raiseCLIError('No destination container:path provided')
+
     def _get_all(self, prefix):
         return self.client.container_get(prefix=prefix).json
 
-    def _get_src_objects(self, src_cnt, src_path):
+    def _get_src_objects(self, src_path):
         """Get a list of the source objects to be called
 
-        :param src_cnt: (str) source container
-
         :param src_path: (str) source path
 
         :returns: (method, params) a method that returns a list when called
@@ -558,7 +569,6 @@ class _source_destination_command(_store_container_command):
         """
         if src_path and src_path[-1] == '/':
             src_path = src_path[:-1]
-        self.client.container = src_cnt
 
         if self['prefix']:
             return (self._get_all, dict(prefix=src_path))
@@ -567,31 +577,35 @@ class _source_destination_command(_store_container_command):
         except ClientError as srcerr:
             if srcerr.status == 404:
                 raiseCLIError(
-                    'Source object %s not in cont. %s' % (src_path, src_cnt),
+                    'Source object %s not in source container %s' % (
+                        src_path,
+                        self.client.container),
                     details=['Hint: --with-prefix to match multiple objects'])
             elif srcerr.status not in (204,):
                 raise
             return (self.client.list_objects, {})
+
         if self._is_dir(srcobj):
             if not self['recursive']:
                 raiseCLIError(
-                    'Object %s of cont. %s is a dir' % (src_path, src_cnt),
+                    'Object %s of cont. %s is a dir' % (
+                        src_path,
+                        self.client.container),
                     details=['Use --recursive to access directories'])
             return (self._get_all, dict(prefix=src_path))
         srcobj['name'] = src_path
         return srcobj
 
-    def src_dst_pairs(self, dst_cont, dst_path):
-        src_iter = self._get_src_objects(self.container, self.path)
+    def src_dst_pairs(self, dst_path):
+        src_iter = self._get_src_objects(self.path)
         src_N = isinstance(src_iter, tuple)
         add_prefix = self['add_prefix'].strip('/')
 
         if dst_path and dst_path.endswith('/'):
             dst_path = dst_path[:-1]
 
-        self.client.container = dst_cont
         try:
-            dstobj = self.client.get_object_info(dst_path)
+            dstobj = self.dst_client.get_object_info(dst_path)
         except ClientError as trgerr:
             if trgerr.status in (404,):
                 if src_N:
@@ -614,7 +628,6 @@ class _source_destination_command(_store_container_command):
                         'or create the destination dir (/store mkdir)',
                         'or use a single object as source'])
 
-        self.client.container = self.container
         if src_N:
             (method, kwargs) = src_iter
             for obj in method(**kwargs):
@@ -655,7 +668,9 @@ class store_copy(_source_destination_command):
     """
 
     arguments = dict(
-        source_account=ValueArgument('Account to copy from', '--src-account'),
+        destination_account=ValueArgument(
+            'Account to copy to',
+            '--dst-account'),
         destination_container=ValueArgument(
             'use it if destination container name contains a : character',
             '--dst-container'),
@@ -692,16 +707,19 @@ class store_copy(_source_destination_command):
     @errors.generic.all
     @errors.pithos.connection
     @errors.pithos.container
-    def _run(self, dst_cont, dst_path):
+    @errors.pithos.account
+    def _run(self, dst_path):
         no_source_object = True
-        for src_obj, dst_obj in self.src_dst_pairs(dst_cont, dst_path):
+        src_account = self.client.account if (
+            self['destination_account']) else None
+        for src_obj, dst_obj in self.src_dst_pairs(dst_path):
             no_source_object = False
-            self.client.copy_object(
-                src_container=self.container,
+            self.dst_client.copy_object(
+                src_container=self.client.container,
                 src_object=src_obj,
-                dst_container=dst_cont,
-                dst_object=self.client.account,
-                source_account=self['source_account'],
+                dst_container=self.dst_client.container,
+                dst_object=dst_obj,
+                source_account=src_account,
                 source_version=self['source_version'],
                 public=self['public'],
                 content_type=self['content_type'])
@@ -714,12 +732,13 @@ class store_copy(_source_destination_command):
             self,
             source_container___path,
             destination_container___path=None):
-        super(self.__class__, self)._run(
+        super(store_copy, self)._run(
             source_container___path,
             path_is_optional=False)
         (dst_cont, dst_path) = self._dest_container_path(
             destination_container___path)
-        self._run(dst_cont=dst_cont or self.container, dst_path=dst_path or '')
+        self.dst_client.container = dst_cont or self.container
+        self._run(dst_path=dst_path or '')
 
 
 @command(pithos_cmds)
@@ -740,6 +759,9 @@ class store_move(_source_destination_command):
     """
 
     arguments = dict(
+        destination_account=ValueArgument(
+            'Account to move to',
+            '--dst-account'),
         destination_container=ValueArgument(
             'use it if destination container name contains a : character',
             '--dst-container'),
@@ -776,15 +798,18 @@ class store_move(_source_destination_command):
     @errors.generic.all
     @errors.pithos.connection
     @errors.pithos.container
-    def _run(self, dst_cont, dst_path):
+    def _run(self, dst_path):
         no_source_object = True
-        for src_object, dst_object in self.src_dst_pairs(dst_cont, dst_path):
+        src_account = self.client.account if (
+            self['destination_account']) else None
+        for src_obj, dst_obj in self.src_dst_pairs(dst_path):
             no_source_object = False
-            self.client.move_object(
+            self.dst_client.move_object(
                 src_container=self.container,
-                src_object=src_object,
-                dst_container=dst_cont,
-                dst_object=dst_object,
+                src_object=src_obj,
+                dst_container=self.dst_client.container,
+                dst_object=dst_obj,
+                #source_account=src_account,
                 source_version=self['source_version'],
                 public=self['public'],
                 content_type=self['content_type'])
@@ -802,7 +827,10 @@ class store_move(_source_destination_command):
             path_is_optional=False)
         (dst_cont, dst_path) = self._dest_container_path(
             destination_container___path)
-        self._run(dst_cont=dst_cont or self.container, dst_path=dst_path or '')
+        (dst_cont, dst_path) = self._dest_container_path(
+            destination_container___path)
+        self.dst_client.container = dst_cont or self.container
+        self._run(dst_path=dst_path or '')
 
 
 @command(pithos_cmds)