Allow ImageRef to be empty when block device is present (#97)

This commit removes the requirement for ImageRef to be set when creating
a server. This is to enable booting from a volume to work properly.

A unit test was added to verify this is possible.

Acceptance tests were also modified to handle this.
diff --git a/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go b/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go
index dca1105..6724dab 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go
@@ -52,6 +52,49 @@
 	th.CheckJSONEquals(t, expected, actual)
 }
 
+func TestCreateOptsWithoutImageRef(t *testing.T) {
+	base := servers.CreateOpts{
+		Name:      "createdserver",
+		FlavorRef: "performance1-1",
+	}
+
+	ext := bootfromvolume.CreateOptsExt{
+		CreateOptsBuilder: base,
+		BlockDevice: []bootfromvolume.BlockDevice{
+			{
+				UUID:                "123456",
+				SourceType:          bootfromvolume.Image,
+				DestinationType:     "volume",
+				VolumeSize:          10,
+				DeleteOnTermination: false,
+			},
+		},
+	}
+
+	expected := `
+    {
+      "server": {
+        "name": "createdserver",
+        "imageRef": "",
+        "flavorRef": "performance1-1",
+        "block_device_mapping_v2":[
+          {
+            "uuid":"123456",
+            "source_type":"image",
+            "destination_type":"volume",
+            "boot_index": 0,
+            "delete_on_termination": false,
+            "volume_size": 10
+          }
+        ]
+      }
+    }
+  `
+	actual, err := ext.ToServerCreateMap()
+	th.AssertNoErr(t, err)
+	th.CheckJSONEquals(t, expected, actual)
+}
+
 func TestCreateMultiEphemeralOpts(t *testing.T) {
 	base := servers.CreateOpts{
 		Name:      "createdserver",
diff --git a/openstack/compute/v2/servers/requests.go b/openstack/compute/v2/servers/requests.go
index fcc8b2e..4ec2cf0 100644
--- a/openstack/compute/v2/servers/requests.go
+++ b/openstack/compute/v2/servers/requests.go
@@ -219,23 +219,21 @@
 		b["networks"] = networks
 	}
 
-	// If ImageRef isn't provided, use ImageName to ascertain the image ID.
+	// If ImageRef isn't provided, check if ImageName was provided to ascertain
+	// the image ID.
 	if opts.ImageRef == "" {
-		if opts.ImageName == "" {
-			err := ErrNeitherImageIDNorImageNameProvided{}
-			err.Argument = "ImageRef/ImageName"
-			return nil, err
+		if opts.ImageName != "" {
+			if sc == nil {
+				err := ErrNoClientProvidedForIDByName{}
+				err.Argument = "ServiceClient"
+				return nil, err
+			}
+			imageID, err := images.IDFromName(sc, opts.ImageName)
+			if err != nil {
+				return nil, err
+			}
+			b["imageRef"] = imageID
 		}
-		if sc == nil {
-			err := ErrNoClientProvidedForIDByName{}
-			err.Argument = "ServiceClient"
-			return nil, err
-		}
-		imageID, err := images.IDFromName(sc, opts.ImageName)
-		if err != nil {
-			return nil, err
-		}
-		b["imageRef"] = imageID
 	}
 
 	// If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID.
@@ -424,23 +422,21 @@
 		return nil, err
 	}
 
-	// If ImageRef isn't provided, use ImageName to ascertain the image ID.
+	// If ImageRef isn't provided, check if ImageName was provided to ascertain
+	// the image ID.
 	if opts.ImageID == "" {
-		if opts.ImageName == "" {
-			err := ErrNeitherImageIDNorImageNameProvided{}
-			err.Argument = "ImageRef/ImageName"
-			return nil, err
+		if opts.ImageName != "" {
+			if opts.ServiceClient == nil {
+				err := ErrNoClientProvidedForIDByName{}
+				err.Argument = "ServiceClient"
+				return nil, err
+			}
+			imageID, err := images.IDFromName(opts.ServiceClient, opts.ImageName)
+			if err != nil {
+				return nil, err
+			}
+			b["imageRef"] = imageID
 		}
-		if opts.ServiceClient == nil {
-			err := ErrNoClientProvidedForIDByName{}
-			err.Argument = "ServiceClient"
-			return nil, err
-		}
-		imageID, err := images.IDFromName(opts.ServiceClient, opts.ImageName)
-		if err != nil {
-			return nil, err
-		}
-		b["imageRef"] = imageID
 	}
 
 	return map[string]interface{}{"rebuild": b}, nil