configurationengine/source/cone/storage/webstorage.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
equal deleted inserted replaced
2:87cfa131b535 3:e7e0ae78773e
    26 import urllib, urllib2
    26 import urllib, urllib2
    27 import simplejson
    27 import simplejson
    28 import posixpath
    28 import posixpath
    29 
    29 
    30 from cone.public import *
    30 from cone.public import *
    31 from cone.carbon import persistentjson, model
    31 from cone.carbon import persistentjson, model, resourcemapper
    32 from cone.storage import authenticate
    32 from cone.storage import authenticate
    33 
    33 
    34 class WebStorage(api.Storage):
    34 class WebStorage(api.Storage):
    35     """
    35     """
    36     A general base class for all storage type classes
    36     A general base class for all storage type classes
    53         """
    53         """
    54         # Test the path, whether it is a featurelist or configuration
    54         # Test the path, whether it is a featurelist or configuration
    55         try:
    55         try:
    56             object_type = object.meta.get('type')
    56             object_type = object.meta.get('type')
    57         except (TypeError,AttributeError):
    57         except (TypeError,AttributeError):
    58             logging.getLogger('cone').error('Cannot dump configuration %s to webstorage without a type.' % path)
    58             logging.getLogger('cone').info('Cannot dump configuration %s to webstorage without a type.' % path)
    59             return False
    59             return False
    60         carbonpath = persistentjson.CarbonResourceMapper().map_confml_resource(object_type, path)
    60         carbonpath = resourcemapper.CarbonResourceMapper().map_confml_resource(object_type, path)
    61         if object_type == 'featurelist':
    61         if object_type == 'featurelist':
    62             # Create a featurelist 
    62             # Create a featurelist 
    63             success = self.extapi.create_featurelist(carbonpath, object)
    63             success = self.extapi.create_featurelist(carbonpath, object)
    64             if success:
    64             if success:
    65                 self.resource_cache.add_resource_link(path, carbonpath)
    65                 self.resource_cache.add_resource_link(path, carbonpath)
    91         solution to link Configuration project concepts to Carbon storage
    91         solution to link Configuration project concepts to Carbon storage
    92         
    92         
    93         """
    93         """
    94         if not self._resource_cache: 
    94         if not self._resource_cache: 
    95             self._resource_cache = ResourceCache()
    95             self._resource_cache = ResourceCache()
    96             reslist = self.extapi.list_resources("/", True)
    96             try:
       
    97                 reslist = self.extapi.list_resources("/", True)
       
    98             except urllib2.HTTPError, e:
       
    99                 print e
       
   100                 return []
    97             # Append all resources to resource cache
   101             # Append all resources to resource cache
    98             for res in reslist:
   102             for res in reslist:
    99                 self._resource_cache.add_resource(res)
   103                 self._resource_cache.add_resource(res)
   100 #                    if isinstance(res, model.ConfigurationResource):
   104 #                    if isinstance(res, model.ConfigurationResource):
   101 #                        self._resource_cache.add_configuration(res)
   105 #                        self._resource_cache.add_configuration(res)
   102 #                    elif isinstance(res, model.FeatureListResource):
   106 #                    elif isinstance(res, model.FeatureListResource):
   103 #                        self._resource_cache.add_featurelist(res)
   107 #                        self._resource_cache.add_featurelist(res)
   104         return self._resource_cache
   108         return self._resource_cache
   105 
   109 
   106     def list_resources(self,path, recurse=False, empty_folders=False):
   110     def list_resources(self,path, **kwargs):
   107         """
   111         """
   108         find the resources under certain path/path 
   112         find the resources under certain path/path 
   109         @param path : reference to path where resources are searched
   113         @param path : reference to path where resources are searched
   110         @param recurse : defines whether to return resources directly under the path or does the listing recurse to subfolders. 
   114         @param recurse : defines whether to return resources directly under the path or does the listing recurse to subfolders. 
   111         Default value is False. Set to True to enable recursion.
   115         Default value is False. Set to True to enable recursion.
   112         @param empty_folders: parameters that defined whether empty folders are included. This parameter is ignored 
   116         @param empty_folders: parameters that defined whether empty folders are included. This parameter is ignored 
   113         in WebStorage. 
   117         in WebStorage. 
   114         """
   118         """
   115         return self.resource_cache.list_resources(path,recurse)
   119         return self.resource_cache.list_resources(path, kwargs.get('recurse', False))
   116 
   120 
   117 
   121 
   118     def open_resource(self,path,mode="r"):
   122     def open_resource(self,path,mode="r"):
   119         path = utils.resourceref.remove_begin_slash(path)
   123         path = utils.resourceref.remove_begin_slash(path)
   120         if self.resource_cache.get_resource_object(path):
   124         if self.resource_cache.get_resource_object(path):
   139             return res
   143             return res
   140         except KeyError:
   144         except KeyError:
   141             raise exceptions.NotResource("The given resource is not found %s" % path)
   145             raise exceptions.NotResource("The given resource is not found %s" % path)
   142 
   146 
   143     def is_resource(self,path):
   147     def is_resource(self,path):
   144         return self.resource_cache.is_resource(path)
   148         ret= self.resource_cache.is_resource(path)
       
   149         if not ret:
       
   150             try:
       
   151                 mapped = self.resource_cache.get_mapped_resource(path)
       
   152                 ret = self.extapi.is_resource(mapped)
       
   153             except Exception:
       
   154                 pass
       
   155         return ret
   145 #        path = path.replace(".confml", ".configuration")
   156 #        path = path.replace(".confml", ".configuration")
   146 #        path = utils.resourceref.join_refs([self.get_current_path(), path])
   157 #        path = utils.resourceref.join_refs([self.get_current_path(), path])
   147 #        try:
   158 #        try:
   148 #            query = urllib.quote(self._get_action_url('is_resource', path))
   159 #            query = urllib.quote(self._get_action_url('is_resource', path))
   149 #            self.conn.request("GET", query)
   160 #            self.conn.request("GET", query)
   189             raise exceptions.StorageException("Cannot dump object type %s" % object.__class__)
   200             raise exceptions.StorageException("Cannot dump object type %s" % object.__class__)
   190         # Skip the unload storing to storage if the storage is opened in read mode
   201         # Skip the unload storing to storage if the storage is opened in read mode
   191         if self.get_mode(self.mode) != api.Storage.MODE_READ:
   202         if self.get_mode(self.mode) != api.Storage.MODE_READ:
   192             if self.resource_cache.get_resource_link(path):
   203             if self.resource_cache.get_resource_link(path):
   193                 path = self.resource_cache.get_resource_link(path)
   204                 path = self.resource_cache.get_resource_link(path)
       
   205             elif self.is_resource(path):
       
   206                  path = self.resource_cache.get_mapped_resource(path)
   194             else:
   207             else:
   195                 """ otherwise create the new resource first before update"""
   208                 """ otherwise create the new resource first before update"""
   196                 if self._create_resource(path, object):
   209                 if self._create_resource(path, object):
   197                     path = self.resource_cache.get_resource_link(path)
   210                     path = self.resource_cache.get_resource_link(path)
   198                 else:
   211                 else:
   199                     # Creation failed
   212                     # Creation failed
   200                     logging.getLogger('cone').error('Creation of %s resource failed' % path)
   213                     logging.getLogger('cone').info('Creation of %s resource failed' % path)
   201                     return 
   214                     return 
   202             data = persistentjson.dumps(object)
   215             data = persistentjson.dumps(object)
   203             self.extapi.update_resource(path, data)
   216             self.extapi.update_resource(path, data)
   204         else:
   217         else:
   205             raise exceptions.StorageException("Cannot dump object to readonly storage")
   218             raise exceptions.StorageException("Cannot dump object to readonly storage")
   206         return
   219         return
       
   220     
       
   221     
   207 
   222 
   208     def load(self, path):
   223     def load(self, path):
   209         """
   224         """
   210         Load resource from a path.
   225         Load resource from a path.
   211         """
   226         """
   296         pathelems = path.split('/',1)
   311         pathelems = path.split('/',1)
   297         self.server_path = pathelems[0]
   312         self.server_path = pathelems[0]
   298         if len(pathelems) > 1: 
   313         if len(pathelems) > 1: 
   299             self.service_path = pathelems[1]
   314             self.service_path = pathelems[1]
   300         self._username = kwargs.get('username', None)
   315         self._username = kwargs.get('username', None)
   301         self._password = kwargs.get('password', None)
   316         self._password = kwargs.get('password', None)     
   302         authhandler = authenticate.CarbonAuthHandler()
   317         authhandler = authenticate.CarbonAuthHandler()
   303         authhandler.add_password(self.username, self.password)
   318         authhandler.add_username_func(self.get_username)
       
   319         authhandler.add_password_func(self.get_password)
   304         self.conn = urllib2.build_opener(urllib2.HTTPCookieProcessor, authhandler, urllib2.ProxyHandler({}))
   320         self.conn = urllib2.build_opener(urllib2.HTTPCookieProcessor, authhandler, urllib2.ProxyHandler({}))
   305         
   321         
   306     @property
   322     def get_username(self):
   307     def username(self):
       
   308         if self._username == None:
   323         if self._username == None:
   309             self._username = getpass.getuser()
   324             self._username = getpass.getuser()
   310         return self._username 
   325         return self._username 
   311 
   326 
   312     @property
   327     def get_password(self):
   313     def password(self):
       
   314         if self._password == None:
   328         if self._password == None:
   315             self._password = getpass.getpass()
   329             self._password = getpass.getpass("Password (%s):" % self._username)
   316         return self._password
   330         return self._password
   317 
   331 
   318     def checklogin(self):
   332     def checklogin(self):
   319         """
   333         """
   320         Checks that we are logged in by loading the main page.
   334         Checks that we are logged in by loading the main page.
   387             query = self._get_action_url('list_resources', path)
   401             query = self._get_action_url('list_resources', path)
   388             req = urllib2.Request(query)
   402             req = urllib2.Request(query)
   389             resp = self.conn.open(req)
   403             resp = self.conn.open(req)
   390             if resp.code == httplib.OK:
   404             if resp.code == httplib.OK:
   391                 bytes = resp.read()
   405                 bytes = resp.read()
   392                 reslist = simplejson.loads(bytes)
   406                 if bytes:
   393                 return reslist.get('resources',[])
   407                     reslist = simplejson.loads(bytes)
       
   408                     return reslist.get('resources',[])
   394             else:
   409             else:
   395                 return []
   410                 return []
   396         except exceptions.NotFound:
   411         except exceptions.NotFound:
   397             return []
   412             return []
   398 
   413 
   399 
   414     def is_resource(self, path):
       
   415         try:
       
   416             query = self._get_action_url('is_resource', path)
       
   417             req = urllib2.Request(query)
       
   418             resp = self.conn.open(req)
       
   419             if resp.code == httplib.OK:
       
   420                 reader = persistentjson.HasResourceReader()
       
   421                 ret = resp.read()
       
   422                 return reader.loads(ret)
       
   423             else:
       
   424                 return False
       
   425         except exceptions.NotFound:
       
   426             return False
       
   427 
       
   428         
   400     def update_resource(self, path, data):
   429     def update_resource(self, path, data):
   401         """
   430         """
   402         Update a resource to carbon. The resource can be a CarbonConfiguration or FeatureList object.
   431         Update a resource to carbon. The resource can be a CarbonConfiguration or FeatureList object.
   403         @param object: The object which is dumped to dict with persistentjson and then updated to server. 
   432         @param object: The object which is dumped to dict with persistentjson and then updated to server. 
   404         """
   433         """
   415                 respdata = simplejson.loads(bytes)
   444                 respdata = simplejson.loads(bytes)
   416                 success = respdata.get('success') == True
   445                 success = respdata.get('success') == True
   417                 if success:
   446                 if success:
   418                     logging.getLogger('cone').info('Carbon update succeeds to path %s.' % (respdata.get('path')))
   447                     logging.getLogger('cone').info('Carbon update succeeds to path %s.' % (respdata.get('path')))
   419                 else:
   448                 else:
   420                     logging.getLogger('cone').error('Carbon update %s failed %s' % (path,respdata.get('errors')))
   449                     logging.getLogger('cone').error('Carbon update %s failed!' % (path))
       
   450                 if respdata.get('errors'):
       
   451                     formatted_err = "" 
       
   452                     for error in respdata.get('errors'):
       
   453                         formatted_err += "%s: %s\n" % (error,respdata.get('errors')[error])
       
   454                     logging.getLogger('cone').info('Carbon update to path %s returned %s' % (respdata.get('path'),formatted_err))
   421                 return success
   455                 return success
   422             else:
   456             else:
   423                 logging.getLogger('cone').error('Carbon update %s failed %s: %s' % (path,resp.code, resp))
   457                 logging.getLogger('cone').error('Carbon update %s failed %s: %s' % (path,resp.code, resp))
   424                 return False
   458                 return False
   425         except urllib2.HTTPError,e:
   459         except urllib2.HTTPError,e:
   556 
   590 
   557     def add_resource(self, resourcepath):
   591     def add_resource(self, resourcepath):
   558         """
   592         """
   559         Add a resource 
   593         Add a resource 
   560         """
   594         """
   561         confmlpath = persistentjson.CarbonResourceMapper().map_carbon_resource(resourcepath)
   595         confmlpath = resourcemapper.CarbonResourceMapper().map_carbon_resource(resourcepath)
   562         self._cache[confmlpath] = resourcepath 
   596         self._cache[confmlpath] = resourcepath 
   563 
   597 
   564     def list_resources(self, path, recurse=False):
   598     def list_resources(self, path, recurse=False):
   565         """
   599         """
   566         List ConE resources under certain path 
   600         List ConE resources under certain path 
   597             object_type = 'featurelist'
   631             object_type = 'featurelist'
   598         elif path.endswith('/root.confml'):
   632         elif path.endswith('/root.confml'):
   599             object_type = 'configurationlayer'
   633             object_type = 'configurationlayer'
   600         else:
   634         else:
   601             object_type = 'configurationroot'
   635             object_type = 'configurationroot'
   602         carbonpath = persistentjson.CarbonResourceMapper().map_confml_resource(object_type, path)
   636         carbonpath = resourcemapper.CarbonResourceMapper().map_confml_resource(object_type, path)
   603         return carbonpath
   637         return carbonpath
   604 
   638 
   605     def add_resource_link(self,link, path):
   639     def add_resource_link(self,link, path):
   606         """
   640         """
   607         Add a actual Carbon resource link. The link is the key which returns path when asked from get_resource_link.
   641         Add a actual Carbon resource link. The link is the key which returns path when asked from get_resource_link.