Revision 176894c1

b/kamaki/cli.py
75 75
from optparse import OptionParser
76 76
from os.path import abspath, basename, exists
77 77
from pwd import getpwuid
78
from sys import argv, exit
78
from sys import argv, exit, stdout
79 79

  
80 80
from kamaki import clients
81 81
from kamaki.config import Config, ConfigError
......
641 641
        self.client.set_members(image_id, member)
642 642

  
643 643

  
644
@command(api='storage')
645
class store_container(object):
646
    """get container info"""
644
class store_command(object):
645
    """base class for all store_* commands"""
647 646
    
648 647
    @classmethod
649 648
    def update_parser(cls, parser):
......
655 654
    def main(self):
656 655
        self.config.override('storage_account', self.options.account)
657 656
        self.config.override('storage_container', self.options.container)
657
        
658
        # Use the more efficient Pithos client if available
659
        if 'pithos' in self.config.get('apis').split():
660
            self.client = clients.PithosClient(self.config)
661

  
662

  
663
@command(api='storage')
664
class store_container(store_command):
665
    """get container info"""
666
    
667
    def main(self):
668
        store_command.main(self)
658 669
        reply = self.client.get_container_meta()
659 670
        print_dict(reply)
660 671

  
661 672

  
662 673
@command(api='storage')
663
class store_upload(object):
674
class store_upload(store_command):
664 675
    """upload a file"""
665 676
    
666
    @classmethod
667
    def update_parser(cls, parser):
668
        parser.add_option('--account', dest='account', metavar='ACCOUNT',
669
                help='use account ACCOUNT')
670
        parser.add_option('--container', dest='container', metavar='CONTAINER',
671
                help='use container CONTAINER')
672
    
673 677
    def main(self, path, remote_path=None):
674
        self.config.override('storage_account', self.options.account)
675
        self.config.override('storage_container', self.options.container)
676
        
677
        # Use the more efficient Pithos client if available
678
        if 'pithos' in self.config.get('apis').split():
679
            self.client = clients.PithosClient(self.config)
680
        
678
        store_command.main(self)
681 679
        if remote_path is None:
682 680
            remote_path = basename(path)
683 681
        with open(path) as f:
......
685 683

  
686 684

  
687 685
@command(api='storage')
688
class store_delete(object):
689
    """delete a file"""
686
class store_download(store_command):
687
    """download a file"""
690 688
    
691
    @classmethod
692
    def update_parser(cls, parser):
693
        parser.add_option('--account', dest='account', metavar='ACCOUNT',
694
                help='use account ACCOUNT')
695
        parser.add_option('--container', dest='container', metavar='CONTAINER',
696
                help='use container CONTAINER')
689
    def main(self, remote_path, local_path):
690
        store_command.main(self)
691
        f = self.client.get_object(remote_path)
692
        out = open(local_path, 'w') if local_path != '-' else stdout
693
        block = 4096
694
        data = f.read(block)
695
        while data:
696
            out.write(data)
697
            data = f.read(block)
698

  
699

  
700
@command(api='storage')
701
class store_delete(store_command):
702
    """delete a file"""
697 703
    
698 704
    def main(self, path):
699
        self.config.override('storage_account', self.options.account)
700
        self.config.override('storage_container', self.options.container)
705
        store_command.main(self)
701 706
        self.client.delete_object(path)
702 707

  
703 708

  
b/kamaki/clients/http.py
62 62
        return token
63 63
    
64 64
    def raw_http_cmd(self, method, path, body=None, headers=None, success=200,
65
                     json_reply=False):
65
                     json_reply=False, skip_read=False):
66 66
        p = urlparse(self.url)
67 67
        path = p.path + path
68 68
        if p.scheme == 'http':
......
89 89
        conn.request(method, path, body, headers)
90 90
        
91 91
        resp = conn.getresponse()
92
        reply = resp.read()
92
        reply = '' if skip_read else resp.read()
93 93
        
94 94
        log.debug('<' * 50)
95 95
        log.info('%d %s', resp.status, resp.reason)
b/kamaki/clients/storage.py
82 82
        data = f.read()
83 83
        self.http_put(path, data, success=201)
84 84

  
85
    def get_object(self, object):
86
        path = '/%s/%s/%s' % (self.account, self.container, object)
87
        resp, reply = self.raw_http_cmd('GET', path, success=200,
88
                skip_read=True)
89
        return resp.fp
90

  
85 91
    def delete_object(self, object):
86 92
        path = '/%s/%s/%s' % (self.account, self.container, object)
87 93
        self.http_delete(path)

Also available in: Unified diff