From 5071e85493894290cb11d020cd146b5753dac63c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= <cmartins@fdi.ucm.es>
Date: Tue, 22 Mar 2011 16:12:12 +0100
Subject: [PATCH] Features #539, #407: Consistency checks for Hosts and Images

---
 src/host/HostPool.cc   | 54 ++++++++++++++++++++++++++++++++++++-----
 src/image/Image.cc     | 53 +++++++++++++++++++++++++++++++---------
 src/image/ImagePool.cc | 55 ++++++++++++++++++++++++++----------------
 3 files changed, 123 insertions(+), 39 deletions(-)

diff --git a/src/host/HostPool.cc b/src/host/HostPool.cc
index 6df3fb827a..1f86f438b0 100644
--- a/src/host/HostPool.cc
+++ b/src/host/HostPool.cc
@@ -143,17 +143,33 @@ int HostPool::allocate (
     string& error_str)
 {
     Host *        host;
+    ostringstream oss;
+
+    if ( hostname.empty() )
+    {
+        goto error_name;
+    }
+
+    if ( im_mad_name.empty() )
+    {
+        goto error_im;
+    }
+
+    if ( vmm_mad_name.empty() )
+    {
+        goto error_vmm;
+    }
+
+    if ( tm_mad_name.empty() )
+    {
+        goto error_tm;
+    }
 
     host = get(hostname,false);
 
     if ( host !=0)
     {
-        ostringstream oss;
-
-        oss << "NAME is already taken by HOST " << host->get_oid() << ".";
-        error_str = oss.str();
-
-        *oid = -1;
+        goto error_duplicated;
     }
     else
     {
@@ -172,6 +188,32 @@ int HostPool::allocate (
     }
 
     return *oid;
+
+
+error_name:
+    oss << "NAME cannot be empty.";
+    goto error_common;
+
+error_im:
+    oss << "IM_MAD_NAME cannot be empty.";
+    goto error_common;
+
+error_vmm:
+    oss << "VMM_MAD_NAME cannot be empty.";
+    goto error_common;
+
+error_tm:
+    oss << "TM_MAD_NAME cannot be empty.";
+    goto error_common;
+
+error_duplicated:
+    oss << "NAME is already taken by HOST " << host->get_oid() << ".";
+
+error_common:
+    *oid = -1;
+    error_str = oss.str();
+
+    return *oid;
 }
 
 /* -------------------------------------------------------------------------- */
diff --git a/src/image/Image.cc b/src/image/Image.cc
index 280cca8ca9..69599e9395 100644
--- a/src/image/Image.cc
+++ b/src/image/Image.cc
@@ -82,7 +82,7 @@ int Image::insert(SqlDB *db, string& error_str)
 {
     int rc;
 
-    string source_att;
+    string path_attr;
     string type_att;
     string public_attr;
     string persistent_attr;
@@ -96,11 +96,6 @@ int Image::insert(SqlDB *db, string& error_str)
 
     get_template_attribute("NAME", name);
 
-    if ( name.empty() == true )
-    {
-        goto error_name;
-    }
-
     // ------------ TYPE --------------------
 
     get_template_attribute("TYPE", type_att);
@@ -156,10 +151,32 @@ int Image::insert(SqlDB *db, string& error_str)
         image_template->set(dev_att);
     }
 
-    // ------------ SOURCE (path to store the image)--------------------
+    // ------------ PATH --------------------
+    get_template_attribute("PATH", path_attr);
 
+    // ------------ SOURCE (path to store the image) --------------------
     get_template_attribute("SOURCE", source);
 
+    // The template should contain PATH or SOURCE
+    if ( source.empty() && path_attr.empty() )
+    {
+        string size_attr;
+        string fstype_attr;
+
+        get_template_attribute("SIZE",   size_attr);
+        get_template_attribute("FSTYPE", fstype_attr);
+
+        // It could be an empty DATABLOCK image, if it declares SIZE and FSTYPE
+        if ( type_att != "DATABLOCK" || size_attr.empty() || fstype_attr.empty() )
+        {
+            goto error_no_path;
+        }
+    }
+    else if ( !source.empty() && !path_attr.empty() )
+    {
+        goto error_path_and_source;
+    }
+
     if (source.empty())
     {
         ostringstream tmp_hashstream;
@@ -188,18 +205,30 @@ int Image::insert(SqlDB *db, string& error_str)
 
     return rc;
 
-error_name:
-    error_str = "NAME not present in image template.";
-    goto error_common;
-
 error_type:
-    error_str = "Incorrect TYPE in image template.";
+    error_str = "Incorrect TYPE in template.";
     goto error_common;
 
 error_public_and_persistent:
     error_str = "Image cannot be public and persistent.";
     goto error_common;
 
+error_no_path:
+    if ( type_att == "DATABLOCK" )
+    {
+        error_str = "A DATABLOCK type IMAGE has to declare a PATH, or both "
+                    "SIZE and FSTYPE.";
+    }
+    else
+    {
+        error_str = "No PATH in template.";
+    }
+    goto error_common;
+
+error_path_and_source:
+    error_str = "Template malformed, PATH and SOURCE are mutuallly exclusive.";
+    goto error_common;
+
 error_common:
     NebulaLog::log("IMG", Log::ERROR, error_str);
     return -1;
diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc
index 64a5518807..cfa733f923 100644
--- a/src/image/ImagePool.cc
+++ b/src/image/ImagePool.cc
@@ -63,40 +63,53 @@ int ImagePool::allocate (
         int *          oid,
         string&        error_str)
 {
-    Image * img;
-    Image * img_aux;
-    string  name;
+    Image *         img;
+    Image *         img_aux;
+    string          name;
+    ostringstream   oss;
 
     // ---------------------------------------------------------------------
     // Build a new Image object
     // ---------------------------------------------------------------------
     img = new Image(uid, user_name, img_template);
 
-    // ---------------------------------------------------------------------
-    // Check for duplicates
-    // ---------------------------------------------------------------------
+    // Check name
     img->get_template_attribute("NAME", name);
+
+    if ( name.empty() )
+    {
+        goto error_name;
+    }
+
+    // Check for duplicates
     img_aux = get(name,uid,false);
 
     if( img_aux != 0 )
     {
-        ostringstream oss;
-
-        oss << "NAME is already taken by IMAGE " << img_aux->get_oid() << ".";
-        error_str = oss.str();
-
-        *oid = -1;
-
-        delete img;
-    }
-    else
-    {
-        // ---------------------------------------------------------------------
-        // Insert the Object in the pool
-        // ---------------------------------------------------------------------
-        *oid = PoolSQL::allocate(img, error_str);
+        goto error_duplicated;
     }
 
+    // ---------------------------------------------------------------------
+    // Insert the Object in the pool
+    // ---------------------------------------------------------------------
+    *oid = PoolSQL::allocate(img, error_str);
+
+    return *oid;
+
+
+error_name:
+    oss << "NAME cannot be empty.";
+    goto error_common;
+
+error_duplicated:
+    oss << "NAME is already taken by IMAGE " << img_aux->get_oid() << ".";
+
+error_common:
+    delete img;
+
+    *oid = -1;
+    error_str = oss.str();
+
     return *oid;
 }