Decouple OpenStack implementation from Rackspace provider
diff --git a/openstack/db/v1/instances/doc.go b/openstack/db/v1/instances/doc.go
new file mode 100644
index 0000000..98a1bb3
--- /dev/null
+++ b/openstack/db/v1/instances/doc.go
@@ -0,0 +1 @@
+package instances
diff --git a/openstack/db/v1/instances/fixtures.go b/openstack/db/v1/instances/fixtures.go
new file mode 100644
index 0000000..8f7d1b7
--- /dev/null
+++ b/openstack/db/v1/instances/fixtures.go
@@ -0,0 +1,92 @@
+package instances
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	th "github.com/rackspace/gophercloud/testhelper"
+	fake "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func HandleCreateInstanceSuccessfully(t *testing.T) {
+	th.Mux.HandleFunc("/instances", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Set("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		th.TestJSONRequest(t, r, `
+{
+  "instance": {
+    "databases": [
+      {
+        "character_set": "utf8",
+        "collate": "utf8_general_ci",
+        "name": "sampledb"
+      },
+      {
+        "name": "nextround"
+      }
+    ],
+    "flavorRef": "1",
+    "name": "json_rack_instance",
+    "users": [
+      {
+        "databases": [
+          {
+            "name": "sampledb"
+          }
+        ],
+        "name": "demouser",
+        "password": "demopassword"
+      }
+    ],
+    "volume": {
+      "size": 2
+    }
+  }
+}
+`)
+
+		fmt.Fprintf(w, `
+{
+  "instance": {
+    "created": "2014-02-13T21:47:13",
+    "datastore": {
+      "type": "mysql",
+      "version": "5.6"
+    },
+    "flavor": {
+      "id": "1",
+      "links": [
+        {
+          "href": "https://my-openstack.com/v1.0/1234/flavors/1",
+          "rel": "self"
+        },
+        {
+          "href": "https://my-openstack.com/v1.0/1234/flavors/1",
+          "rel": "bookmark"
+        }
+      ]
+    },
+		"links": [
+			{
+				"href": "https://my-openstack.com/v1.0/1234/instances/1",
+				"rel": "self"
+			}
+		],
+    "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.my-openstack.com",
+    "id": "d4603f69-ec7e-4e9b-803f-600b9205576f",
+    "name": "json_rack_instance",
+    "status": "BUILD",
+    "updated": "2014-02-13T21:47:13",
+    "volume": {
+      "size": 2
+    }
+  }
+}
+`)
+	})
+}
diff --git a/openstack/db/v1/instances/pkg.go b/openstack/db/v1/instances/pkg.go
new file mode 100644
index 0000000..98a1bb3
--- /dev/null
+++ b/openstack/db/v1/instances/pkg.go
@@ -0,0 +1 @@
+package instances
diff --git a/openstack/db/v1/instances/requests.go b/openstack/db/v1/instances/requests.go
new file mode 100644
index 0000000..914c593
--- /dev/null
+++ b/openstack/db/v1/instances/requests.go
@@ -0,0 +1,190 @@
+package instances
+
+import (
+	"fmt"
+
+	"github.com/racker/perigee"
+	"github.com/rackspace/gophercloud"
+)
+
+// CreateOptsBuilder is the top-level interface for create options.
+type CreateOptsBuilder interface {
+	ToInstanceCreateMap() (map[string]interface{}, error)
+}
+
+// DatabaseOpts is the struct responsible for configuring a database; often in
+// the context of an instance.
+type DatabaseOpts struct {
+	// Specifies the name of the database. Optional.
+	Name string
+
+	// Set of symbols and encodings. Optional; the default character set is utf8.
+	CharSet string
+
+	// Set of rules for comparing characters in a character set. Optional; the
+	// default value for collate is utf8_general_ci.
+	Collate string
+}
+
+func (opts DatabaseOpts) ToMap() (map[string]string, error) {
+	db := map[string]string{}
+	if opts.Name != "" {
+		db["name"] = opts.Name
+	}
+	if opts.CharSet != "" {
+		db["character_set"] = opts.CharSet
+	}
+	if opts.Collate != "" {
+		db["collate"] = opts.Collate
+	}
+	return db, nil
+}
+
+type DatabasesOpts []DatabaseOpts
+
+func (opts DatabasesOpts) ToMap() ([]map[string]string, error) {
+	var dbs []map[string]string
+	for _, db := range opts {
+		dbMap, err := db.ToMap()
+		if err != nil {
+			return dbs, err
+		}
+		dbs = append(dbs, dbMap)
+	}
+	return dbs, nil
+}
+
+// UserOpts is the struct responsible for configuring a user; often in the
+// context of an instance.
+type UserOpts struct {
+	// Specifies a name for the user.
+	Name string
+
+	// Specifies a password for the user.
+	Password string
+
+	// An array of databases that this user will connect to. The `name` field is
+	// the only requirement for each option.
+	Databases []DatabaseOpts
+
+	// Specifies the host from which a user is allowed to connect to the database.
+	// Possible values are a string containing an IPv4 address or "%" to allow
+	// connecting from any host. Optional; the default is "%".
+	Host string
+}
+
+func (opts UserOpts) ToMap() (map[string]interface{}, error) {
+	user := map[string]interface{}{}
+
+	if opts.Name != "" {
+		user["name"] = opts.Name
+	}
+	if opts.Password != "" {
+		user["password"] = opts.Password
+	}
+	if opts.Host != "" {
+		user["host"] = opts.Host
+	}
+
+	var dbs []map[string]string
+	for _, db := range opts.Databases {
+		dbs = append(dbs, map[string]string{"name": db.Name})
+	}
+	if len(dbs) > 0 {
+		user["databases"] = dbs
+	}
+
+	return user, nil
+}
+
+type UsersOpts []UserOpts
+
+func (opts UsersOpts) ToMap() ([]map[string]interface{}, error) {
+	var users []map[string]interface{}
+	for _, opt := range opts {
+		user, err := opt.ToMap()
+		if err != nil {
+			return users, err
+		}
+		users = append(users, user)
+	}
+	return users, nil
+}
+
+// CreateOpts is the struct responsible for configuring a new database instance.
+type CreateOpts struct {
+	// Either the integer UUID (in string form) of the flavor, or its URI
+	// reference as specified in the response from the List() call. Required.
+	FlavorRef string
+
+	// Specifies the volume size in gigabytes (GB). The value must be between 1
+	// and 300. Required.
+	Size int
+
+	// Name of the instance to create. The length of the name is limited to
+	// 255 characters and any characters are permitted. Optional.
+	Name string
+
+	// A slice of database information options.
+	Databases DatabasesOpts
+
+	// A slice of user information options.
+	Users UsersOpts
+}
+
+func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
+	if opts.Size > 300 || opts.Size < 1 {
+		return nil, fmt.Errorf("Size (GB) must be between 1-300")
+	}
+	if opts.FlavorRef == "" {
+		return nil, fmt.Errorf("FlavorRef is a required field")
+	}
+
+	instance := map[string]interface{}{
+		"volume":    map[string]int{"size": opts.Size},
+		"flavorRef": opts.FlavorRef,
+	}
+
+	if opts.Name != "" {
+		instance["name"] = opts.Name
+	}
+	if len(opts.Databases) > 0 {
+		dbs, err := opts.Databases.ToMap()
+		if err != nil {
+			return nil, err
+		}
+		instance["databases"] = dbs
+	}
+	if len(opts.Users) > 0 {
+		users, err := opts.Users.ToMap()
+		if err != nil {
+			return nil, err
+		}
+		instance["users"] = users
+	}
+
+	return map[string]interface{}{"instance": instance}, nil
+}
+
+// Create will provision a new Database instance.
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
+	var res CreateResult
+
+	reqBody, err := opts.ToInstanceCreateMap()
+	if err != nil {
+		res.Err = err
+		return res
+	}
+
+	resp, err := perigee.Request("POST", createURL(client), perigee.Options{
+		MoreHeaders: client.AuthenticatedHeaders(),
+		ReqBody:     &reqBody,
+		Results:     &res.Body,
+		OkCodes:     []int{200},
+	})
+
+	res.Header = resp.HttpResponse.Header
+	res.Err = err
+
+	return res
+}
diff --git a/openstack/db/v1/instances/requests_test.go b/openstack/db/v1/instances/requests_test.go
new file mode 100644
index 0000000..18ba928
--- /dev/null
+++ b/openstack/db/v1/instances/requests_test.go
@@ -0,0 +1,60 @@
+package instances
+
+import (
+	"testing"
+
+	"github.com/rackspace/gophercloud"
+	th "github.com/rackspace/gophercloud/testhelper"
+	fake "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func TestCreate(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	HandleCreateInstanceSuccessfully(t)
+
+	opts := CreateOpts{
+		Name:      "json_rack_instance",
+		FlavorRef: "1",
+		Databases: DatabasesOpts{
+			DatabaseOpts{CharSet: "utf8", Collate: "utf8_general_ci", Name: "sampledb"},
+			DatabaseOpts{Name: "nextround"},
+		},
+		Users: UsersOpts{
+			UserOpts{
+				Name:     "demouser",
+				Password: "demopassword",
+				Databases: DatabasesOpts{
+					DatabaseOpts{Name: "sampledb"},
+				},
+			},
+		},
+		Size: 2,
+	}
+
+	instance, err := Create(fake.ServiceClient(), opts).Extract()
+
+	expected := &Instance{
+		Created: "2014-02-13T21:47:13",
+		Updated: "2014-02-13T21:47:13",
+		Flavor: Flavor{
+			ID: "1",
+			Links: []gophercloud.Link{
+				gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "self"},
+				gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "bookmark"},
+			},
+		},
+		Hostname: "e09ad9a3f73309469cf1f43d11e79549caf9acf2.my-openstack.com",
+		ID:       "d4603f69-ec7e-4e9b-803f-600b9205576f",
+		Links: []gophercloud.Link{
+			gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/instances/1", Rel: "self"},
+		},
+		Name:   "json_rack_instance",
+		Status: "BUILD",
+		Volume: Volume{Size: 2},
+	}
+
+	th.AssertNoErr(t, err)
+	th.AssertDeepEquals(t, expected, instance)
+}
diff --git a/openstack/db/v1/instances/results.go b/openstack/db/v1/instances/results.go
new file mode 100644
index 0000000..c3319e0
--- /dev/null
+++ b/openstack/db/v1/instances/results.go
@@ -0,0 +1,46 @@
+package instances
+
+import (
+	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud"
+)
+
+type Flavor struct {
+	ID    string
+	Links []gophercloud.Link
+}
+
+type Volume struct {
+	Size int
+}
+
+type Instance struct {
+	Created  string //time.Time
+	Updated  string //time.Time
+	Flavor   Flavor
+	Hostname string
+	ID       string
+	Links    []gophercloud.Link
+	Name     string
+	Status   string
+	Volume   Volume
+}
+
+// CreateResult represents the result of a Create operation.
+type CreateResult struct {
+	gophercloud.Result
+}
+
+func (r CreateResult) Extract() (*Instance, error) {
+	if r.Err != nil {
+		return nil, r.Err
+	}
+
+	var response struct {
+		Instance Instance `mapstructure:"instance"`
+	}
+
+	err := mapstructure.Decode(r.Body, &response)
+
+	return &response.Instance, err
+}
diff --git a/openstack/db/v1/instances/urls.go b/openstack/db/v1/instances/urls.go
new file mode 100644
index 0000000..bb6edf2
--- /dev/null
+++ b/openstack/db/v1/instances/urls.go
@@ -0,0 +1,11 @@
+package instances
+
+import "github.com/rackspace/gophercloud"
+
+func baseURL(c *gophercloud.ServiceClient) string {
+	return c.ServiceURL("instances")
+}
+
+func createURL(c *gophercloud.ServiceClient) string {
+	return baseURL(c)
+}