Fixed length of some DB fields: path and name in table images, name in table flavors
[osm/openvim.git] / httpserver.py
index ecf878c..5d48beb 100644 (file)
@@ -26,7 +26,7 @@ This is the thread for the http server North API.
 Two thread will be launched, with normal and administrative permissions.
 '''
 
-__author__="Alfonso Tierno"
+__author__="Alfonso Tierno, Gerardo Garcia"
 __date__ ="$10-jul-2014 12:07:15$"
 
 import bottle
@@ -74,6 +74,11 @@ def md5(fname):
             hash_md5.update(chunk)
     return hash_md5.hexdigest()
 
+def md5_string(fname):
+    hash_md5 = hashlib.md5()
+    hash_md5.update(fname)
+    return hash_md5.hexdigest()
+
 def check_extended(extended, allow_net_attach=False):
     '''Makes and extra checking of extended input that cannot be done using jsonschema
     Attributes: 
@@ -1039,13 +1044,14 @@ def http_get_images(tenant_id):
         bottle.abort(result, content)
     #obtain data
     select_,where_,limit_ = filter_query_string(bottle.request.query, http2db_image,
-            ('id','name','description','path','public') )
+            ('id','name','checksum','description','path','public') )
     if tenant_id=='any':
         from_  ='images'
+        where_or_ = None
     else:
-        from_  ='tenants_images inner join images on tenants_images.image_id=images.uuid'
-        where_['tenant_id'] = tenant_id
-    result, content = my.db.get_table(SELECT=select_, FROM=from_, WHERE=where_, LIMIT=limit_)
+        from_  ='tenants_images right join images on tenants_images.image_id=images.uuid'
+        where_or_ = {'tenant_id': tenant_id, 'public': 'yes'}
+    result, content = my.db.get_table(SELECT=select_, DISTINCT=True, FROM=from_, WHERE=where_, WHERE_OR=where_or_, WHERE_AND_OR="AND", LIMIT=limit_)
     if result < 0:
         print "http_get_images Error", content
         bottle.abort(-result, content)
@@ -1064,14 +1070,15 @@ def http_get_image_id(tenant_id, image_id):
         bottle.abort(result, content)
     #obtain data
     select_,where_,limit_ = filter_query_string(bottle.request.query, http2db_image,
-            ('id','name','description','progress', 'status','path', 'created', 'updated','public') )
+            ('id','name','checksum','description','progress', 'status','path', 'created', 'updated','public') )
     if tenant_id=='any':
         from_  ='images'
+        where_or_ = None
     else:
-        from_  ='tenants_images as ti inner join images as i on ti.image_id=i.uuid'
-        where_['tenant_id'] = tenant_id
+        from_  ='tenants_images as ti right join images as i on ti.image_id=i.uuid'
+        where_or_ = {'tenant_id': tenant_id, 'public': "yes"}
     where_['uuid'] = image_id
-    result, content = my.db.get_table(SELECT=select_, FROM=from_, WHERE=where_, LIMIT=limit_)
+    result, content = my.db.get_table(SELECT=select_, DISTINCT=True, FROM=from_, WHERE=where_, WHERE_OR=where_or_, WHERE_AND_OR="AND", LIMIT=limit_)
 
     if result < 0:
         print "http_get_images error %d %s" % (result, content)
@@ -1106,15 +1113,26 @@ def http_post_images(tenant_id):
     if metadata_dict is not None: 
         http_content['image']['metadata'] = json.dumps(metadata_dict)
     #calculate checksum
-    host_test_mode = True if config_dic['mode']=='test' or config_dic['mode']=="OF only" else False
     try:
         image_file = http_content['image'].get('path',None)
-        if os.path.exists(image_file):
-            http_content['image']['checksum'] = md5(image_file)
-        elif is_url(image_file):
+        parsed_url = urlparse.urlparse(image_file)
+        if parsed_url.scheme == "" and parsed_url.netloc == "":
+            # The path is a local file
+            if os.path.exists(image_file):
+                http_content['image']['checksum'] = md5(image_file)
+        else:
+            # The path is a URL. Code should be added to download the image and calculate the checksum
+            #http_content['image']['checksum'] = md5(downloaded_image)
             pass
+        # Finally, only if we are in test mode and checksum has not been calculated, we calculate it from the path
+        host_test_mode = True if config_dic['mode']=='test' or config_dic['mode']=="OF only" else False
+        if host_test_mode:
+            if 'checksum' not in http_content['image']:
+                http_content['image']['checksum'] = md5_string(image_file)
         else:
-            if not host_test_mode:
+            # At this point, if the path is a local file and no chechsum has been obtained yet, an error is sent back.
+            # If it is a URL, no error is sent. Checksum will be an empty string
+            if parsed_url.scheme == "" and parsed_url.netloc == "" and 'checksum' not in http_content['image']:
                 content = "Image file not found"
                 print "http_post_images error: %d %s" % (HTTP_Bad_Request, content)
                 bottle.abort(HTTP_Bad_Request, content)
@@ -1225,10 +1243,11 @@ def http_put_image_id(tenant_id, image_id):
     where_={'uuid': image_id}
     if tenant_id=='any':
         from_  ='images'
+        where_or_ = None
     else:
-        from_  ='tenants_images as ti inner join images as i on ti.image_id=i.uuid'
-        where_['tenant_id'] = tenant_id
-    result, content = my.db.get_table(SELECT=('public',), FROM=from_, WHERE=where_)
+        from_  ='tenants_images as ti right join images as i on ti.image_id=i.uuid'
+        where_or_ = {'tenant_id': tenant_id, 'public': 'yes'}
+    result, content = my.db.get_table(SELECT=('public',), DISTINCT=True, FROM=from_, WHERE=where_, WHERE_OR=where_or_, WHERE_AND_OR="AND")
     if result==0:
         text_error="Image '%s' not found" % image_id
         if tenant_id!='any':
@@ -1356,8 +1375,9 @@ def http_post_server_id(tenant_id):
         return
     server['flavor']=content[0]
     #check image valid and take info
-    result, content = my.db.get_table(FROM='tenants_images as ti join images as i on ti.image_id=i.uuid',
-        SELECT=('path','metadata'), WHERE={'uuid':server['image_id'], 'tenant_id':tenant_id, "status":"ACTIVE"})
+    result, content = my.db.get_table(FROM='tenants_images as ti right join images as i on ti.image_id=i.uuid',
+        SELECT=('path','metadata'), WHERE={'uuid':server['image_id'], "status":"ACTIVE"},
+        WHERE_OR={'tenant_id':tenant_id, 'public': 'yes'}, WHERE_AND_OR="AND", DISTINCT=True)
     if result<=0:
         bottle.abort(HTTP_Not_Found, 'image_id %s not found or not ACTIVE' % server['image_id'])
         return
@@ -1499,8 +1519,9 @@ def http_server_action(server_id, tenant_id, action):
                 else: #result==1
                     image_id = content[0]['image_id']    
                 
-        result, content = my.db.get_table(FROM='tenants_images as ti join images as i on ti.image_id=i.uuid',
-            SELECT=('path','metadata'), WHERE={'uuid':image_id, 'tenant_id':tenant_id, "status":"ACTIVE"})
+        result, content = my.db.get_table(FROM='tenants_images as ti right join images as i on ti.image_id=i.uuid',
+            SELECT=('path','metadata'), WHERE={'uuid':image_id, "status":"ACTIVE"},
+            WHERE_OR={'tenant_id':tenant_id, 'public': 'yes'}, WHERE_AND_OR="AND", DISTINCT=True)
         if result<=0:
             bottle.abort(HTTP_Not_Found, 'image_id %s not found or not ACTIVE' % image_id)
             return