virtual interfaces operations & unit tests; networks unit tests
diff --git a/rackspace/networking/v2/networks/delegate.go b/rackspace/networking/v2/networks/delegate.go
deleted file mode 100644
index e040d58..0000000
--- a/rackspace/networking/v2/networks/delegate.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package networks
-
-import (
-  "github.com/rackspace/gophercloud"
-  os "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
-)
-
-// Delete accepts a unique ID and deletes the network associated with it.
-func Delete(c *gophercloud.ServiceClient, id string) os.DeleteResult {
-  return os.Delete(c, id)
-}
diff --git a/rackspace/networking/v2/networks/delegate_test.go b/rackspace/networking/v2/networks/delegate_test.go
deleted file mode 100644
index 83c4a6a..0000000
--- a/rackspace/networking/v2/networks/delegate_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package networks
diff --git a/rackspace/networking/v2/networks/requests.go b/rackspace/networking/v2/networks/requests.go
index f7896b8..f55aa6c 100644
--- a/rackspace/networking/v2/networks/requests.go
+++ b/rackspace/networking/v2/networks/requests.go
@@ -1,33 +1,34 @@
 package networks
 
 import (
-  "errors"
+	"errors"
 
-  "github.com/rackspace/gophercloud"
-  "github.com/rackspace/gophercloud/pagination"
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
 
-  "github.com/racker/perigee"
+	"github.com/racker/perigee"
 )
 
 // List returns a Pager which allows you to iterate over a collection of
 // networks. It accepts a ListOpts struct, which allows you to filter and sort
 // the returned collection for greater efficiency.
 func List(c *gophercloud.ServiceClient) pagination.Pager {
-  url := listURL(c)
-  return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
-    return NetworkPage{pagination.SinglePageBase{PageResult: r}}
-  })
+	createPage := func(r pagination.PageResult) pagination.Page {
+		return NetworkPage{pagination.SinglePageBase(r)}
+	}
+
+	return pagination.NewPager(c, listURL(c), createPage)
 }
 
 // Get retrieves a specific network based on its unique ID.
 func Get(c *gophercloud.ServiceClient, id string) GetResult {
-  var res GetResult
-  _, res.Err = perigee.Request("GET", getURL(c, id), perigee.Options{
-    MoreHeaders: c.Provider.AuthenticatedHeaders(),
-    Results:     &res.Body,
-    OkCodes:     []int{200},
-  })
-  return res
+	var res GetResult
+	_, res.Err = perigee.Request("GET", getURL(c, id), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		Results:     &res.Body,
+		OkCodes:     []int{200},
+	})
+	return res
 }
 
 // CreateOptsBuilder is the interface options structs have to satisfy in order
@@ -35,32 +36,32 @@
 // extensions decorate or modify the common logic, it is useful for them to
 // satisfy a basic interface in order for them to be used.
 type CreateOptsBuilder interface {
-  ToNetworkCreateMap() (map[string]interface{}, error)
+	ToNetworkCreateMap() (map[string]interface{}, error)
 }
 
 // CreateOpts is the common options struct used in this package's Create
 // operation.
-type CreateOpts struct{
-  // REQUIRED. See Network object for more info.
-  CIDR string
-  // REQUIRED. See Network object for more info.
-  Label string
+type CreateOpts struct {
+	// REQUIRED. See Network object for more info.
+	CIDR string
+	// REQUIRED. See Network object for more info.
+	Label string
 }
 
 // ToNetworkCreateMap casts a CreateOpts struct to a map.
 func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
-  n := make(map[string]interface{})
+	n := make(map[string]interface{})
 
-  if opts.CIDR == "" {
-    return nil, errors.New("Required field CIDR not set.")
-  }
-  if opts.Label == "" {
-    return nil, errors.New("Required field Label not set.")
-  }
+	if opts.CIDR == "" {
+		return nil, errors.New("Required field CIDR not set.")
+	}
+	if opts.Label == "" {
+		return nil, errors.New("Required field Label not set.")
+	}
 
-  n["label"] = opts.Label
-  n["cidr"] = opts.CIDR
-  return map[string]interface{}{"network": n}, nil
+	n["label"] = opts.Label
+	n["cidr"] = opts.CIDR
+	return map[string]interface{}{"network": n}, nil
 }
 
 // Create accepts a CreateOpts struct and creates a new network using the values
@@ -71,20 +72,30 @@
 // network. An admin user, however, has the option of specifying another tenant
 // ID in the CreateOpts struct.
 func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
-  var res CreateResult
+	var res CreateResult
 
-  reqBody, err := opts.ToNetworkCreateMap()
-  if err != nil {
-    res.Err = err
-    return res
-  }
+	reqBody, err := opts.ToNetworkCreateMap()
+	if err != nil {
+		res.Err = err
+		return res
+	}
 
-  // Send request to API
-  _, res.Err = perigee.Request("POST", createURL(c), perigee.Options{
-    MoreHeaders: c.Provider.AuthenticatedHeaders(),
-    ReqBody:     &reqBody,
-    Results:     &res.Body,
-    OkCodes:     []int{201},
-  })
-  return res
+	// Send request to API
+	_, res.Err = perigee.Request("POST", createURL(c), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		ReqBody:     &reqBody,
+		Results:     &res.Body,
+		OkCodes:     []int{201, 202},
+	})
+	return res
+}
+
+// Delete accepts a unique ID and deletes the network associated with it.
+func Delete(c *gophercloud.ServiceClient, networkID string) DeleteResult {
+	var res DeleteResult
+	_, res.Err = perigee.Request("DELETE", deleteURL(c, networkID), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		OkCodes:     []int{204},
+	})
+	return res
 }
diff --git a/rackspace/networking/v2/networks/requests_test.go b/rackspace/networking/v2/networks/requests_test.go
index 83c4a6a..441c450 100644
--- a/rackspace/networking/v2/networks/requests_test.go
+++ b/rackspace/networking/v2/networks/requests_test.go
@@ -1 +1,160 @@
 package networks
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/rackspace/gophercloud/pagination"
+	th "github.com/rackspace/gophercloud/testhelper"
+	fake "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func TestList(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/os-networksv2", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+    "networks": [
+        {
+            "label": "test-network-1",
+            "cidr": "192.168.100.0/24",
+            "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
+        },
+        {
+            "label": "test-network-2",
+            "cidr": "192.30.250.00/18",
+            "id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324"
+        }
+    ]
+}
+      `)
+	})
+
+	client := fake.ServiceClient()
+	count := 0
+
+	List(client).EachPage(func(page pagination.Page) (bool, error) {
+		count++
+		actual, err := ExtractNetworks(page)
+		if err != nil {
+			t.Errorf("Failed to extract networks: %v", err)
+			return false, err
+		}
+
+		expected := []Network{
+			Network{
+				Label: "test-network-1",
+				CIDR:  "192.168.100.0/24",
+				ID:    "d32019d3-bc6e-4319-9c1d-6722fc136a22",
+			},
+			Network{
+				Label: "test-network-2",
+				CIDR:  "192.30.250.00/18",
+				ID:    "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
+			},
+		}
+
+		th.CheckDeepEquals(t, expected, actual)
+
+		return true, nil
+	})
+
+	if count != 1 {
+		t.Errorf("Expected 1 page, got %d", count)
+	}
+}
+
+func TestGet(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/os-networksv2/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+    "network": {
+        "label": "test-network-1",
+        "cidr": "192.168.100.0/24",
+        "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
+    }
+}
+      `)
+	})
+
+	n, err := Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
+	th.AssertNoErr(t, err)
+
+	th.AssertEquals(t, n.CIDR, "192.168.100.0/24")
+	th.AssertEquals(t, n.Label, "test-network-1")
+	th.AssertEquals(t, n.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
+}
+
+func TestCreate(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/os-networksv2", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+		th.TestHeader(t, r, "Content-Type", "application/json")
+		th.TestHeader(t, r, "Accept", "application/json")
+		th.TestJSONRequest(t, r, `
+{
+    "network": {
+        "label": "test-network-1",
+        "cidr": "192.168.100.0/24"
+    }
+}
+      `)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusCreated)
+
+		fmt.Fprintf(w, `
+{
+    "network": {
+        "label": "test-network-1",
+        "cidr": "192.168.100.0/24",
+        "id": "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
+    }
+}
+    `)
+	})
+
+	options := CreateOpts{Label: "test-network-1", CIDR: "192.168.100.0/24"}
+	n, err := Create(fake.ServiceClient(), options).Extract()
+	th.AssertNoErr(t, err)
+
+	th.AssertEquals(t, n.Label, "test-network-1")
+	th.AssertEquals(t, n.ID, "4e8e5957-649f-477b-9e5b-f1f75b21c03c")
+}
+
+func TestDelete(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/os-networksv2/4e8e5957-649f-477b-9e5b-f1f75b21c03c", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "DELETE")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	s := fake.ServiceClient()
+	t.Logf("fake.serviceclient: %+v\n", s)
+	res := Delete(s, "4e8e5957-649f-477b-9e5b-f1f75b21c03c")
+	th.AssertNoErr(t, res.Err)
+}
diff --git a/rackspace/networking/v2/networks/results.go b/rackspace/networking/v2/networks/results.go
index 2334faf..823c56e 100644
--- a/rackspace/networking/v2/networks/results.go
+++ b/rackspace/networking/v2/networks/results.go
@@ -1,38 +1,38 @@
 package networks
 
 import (
-  "github.com/mitchellh/mapstructure"
-  "github.com/rackspace/gophercloud"
-  "github.com/rackspace/gophercloud/pagination"
+	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
 )
 
 type commonResult struct {
-  gophercloud.Result
+	gophercloud.Result
 }
 
 // Extract is a function that accepts a result and extracts a network resource.
 func (r commonResult) Extract() (*Network, error) {
-  if r.Err != nil {
-    return nil, r.Err
-  }
+	if r.Err != nil {
+		return nil, r.Err
+	}
 
-  var res struct {
-    Network *Network `json:"network"`
-  }
+	var res struct {
+		Network *Network `json:"network"`
+	}
 
-  err := mapstructure.Decode(r.Body, &res)
+	err := mapstructure.Decode(r.Body, &res)
 
-  return res.Network, err
+	return res.Network, err
 }
 
 // CreateResult represents the result of a create operation.
 type CreateResult struct {
-  commonResult
+	commonResult
 }
 
 // GetResult represents the result of a get operation.
 type GetResult struct {
-  commonResult
+	commonResult
 }
 
 // DeleteResult represents the result of a delete operation.
@@ -40,31 +40,40 @@
 
 // Network represents, well, a network.
 type Network struct {
-  // UUID for the network
-  ID string `mapstructure:"id" json:"id"`
+	// UUID for the network
+	ID string `mapstructure:"id" json:"id"`
 
-  // Human-readable name for the network. Might not be unique.
-  Label string `mapstructure:"label" json:"label"`
+	// Human-readable name for the network. Might not be unique.
+	Label string `mapstructure:"label" json:"label"`
 
-  // Classless Inter-Domain Routing
-  CIDR string `mapstructure:"cidr" json:"cidr"`
+	// Classless Inter-Domain Routing
+	CIDR string `mapstructure:"cidr" json:"cidr"`
 }
 
 // NetworkPage is the page returned by a pager when traversing over a
 // collection of networks.
 type NetworkPage struct {
-  pagination.SinglePageBase
+	pagination.SinglePageBase
+}
+
+// IsEmpty returns true if the NetworkPage contains no Networks.
+func (r NetworkPage) IsEmpty() (bool, error) {
+	networks, err := ExtractNetworks(r)
+	if err != nil {
+		return true, err
+	}
+	return len(networks) == 0, nil
 }
 
 // ExtractNetworks accepts a Page struct, specifically a NetworkPage struct,
 // and extracts the elements into a slice of Network structs. In other words,
 // a generic collection is mapped into a relevant slice.
 func ExtractNetworks(page pagination.Page) ([]Network, error) {
-  var resp struct {
-    Networks []Network `mapstructure:"networks" json:"networks"`
-  }
+	var resp struct {
+		Networks []Network `mapstructure:"networks" json:"networks"`
+	}
 
-  err := mapstructure.Decode(page.(NetworkPage).Body, &resp)
+	err := mapstructure.Decode(page.(NetworkPage).Body, &resp)
 
-  return resp.Networks, err
+	return resp.Networks, err
 }
diff --git a/rackspace/networking/v2/networks/urls.go b/rackspace/networking/v2/networks/urls.go
index 65d843b..19a21aa 100644
--- a/rackspace/networking/v2/networks/urls.go
+++ b/rackspace/networking/v2/networks/urls.go
@@ -3,25 +3,25 @@
 import "github.com/rackspace/gophercloud"
 
 func resourceURL(c *gophercloud.ServiceClient, id string) string {
-  return c.ServiceURL("os-networksv2", id)
+	return c.ServiceURL("os-networksv2", id)
 }
 
 func rootURL(c *gophercloud.ServiceClient) string {
-  return c.ServiceURL("networks")
+	return c.ServiceURL("os-networksv2")
 }
 
 func getURL(c *gophercloud.ServiceClient, id string) string {
-  return resourceURL(c, id)
+	return resourceURL(c, id)
 }
 
 func listURL(c *gophercloud.ServiceClient) string {
-  return rootURL(c)
+	return rootURL(c)
 }
 
 func createURL(c *gophercloud.ServiceClient) string {
-  return rootURL(c)
+	return rootURL(c)
 }
 
 func deleteURL(c *gophercloud.ServiceClient, id string) string {
-  return resourceURL(c, id)
+	return resourceURL(c, id)
 }
diff --git a/rackspace/networking/v2/networks/urls_test.go b/rackspace/networking/v2/networks/urls_test.go
index 2e064b0..983992e 100644
--- a/rackspace/networking/v2/networks/urls_test.go
+++ b/rackspace/networking/v2/networks/urls_test.go
@@ -1,38 +1,38 @@
 package networks
 
 import (
-  "testing"
+	"testing"
 
-  "github.com/rackspace/gophercloud"
-  th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/rackspace/gophercloud"
+	th "github.com/rackspace/gophercloud/testhelper"
 )
 
-const endpoint = "http://localhost:57909"
+const endpoint = "http://localhost:57909/"
 
 func endpointClient() *gophercloud.ServiceClient {
-  return &gophercloud.ServiceClient{Endpoint: endpoint}
+	return &gophercloud.ServiceClient{Endpoint: endpoint}
 }
 
 func TestGetURL(t *testing.T) {
-  actual := getURL(endpointClient(), "foo")
-  expected := endpoint + "os-networksv2/foo"
-  th.AssertEquals(t, expected, actual)
+	actual := getURL(endpointClient(), "foo")
+	expected := endpoint + "os-networksv2/foo"
+	th.AssertEquals(t, expected, actual)
 }
 
 func TestCreateURL(t *testing.T) {
-  actual := createURL(endpointClient())
-  expected := endpoint + "os-networksv2"
-  th.AssertEquals(t, expected, actual)
+	actual := createURL(endpointClient())
+	expected := endpoint + "os-networksv2"
+	th.AssertEquals(t, expected, actual)
 }
 
 func TestListURL(t *testing.T) {
-  actual := createURL(endpointClient())
-  expected := endpoint + "os-networksv2"
-  th.AssertEquals(t, expected, actual)
+	actual := createURL(endpointClient())
+	expected := endpoint + "os-networksv2"
+	th.AssertEquals(t, expected, actual)
 }
 
 func TestDeleteURL(t *testing.T) {
-  actual := deleteURL(endpointClient(), "foo")
-  expected := endpoint + "os-networksv2/foo"
-  th.AssertEquals(t, expected, actual)
+	actual := deleteURL(endpointClient(), "foo")
+	expected := endpoint + "os-networksv2/foo"
+	th.AssertEquals(t, expected, actual)
 }
diff --git a/rackspace/networking/v2/virtualinterfaces/requests.go b/rackspace/networking/v2/virtualinterfaces/requests.go
index 4f91359..adb3184 100644
--- a/rackspace/networking/v2/virtualinterfaces/requests.go
+++ b/rackspace/networking/v2/virtualinterfaces/requests.go
@@ -1 +1,51 @@
 package virtualinterfaces
+
+import (
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
+
+	"github.com/racker/perigee"
+)
+
+// List returns a Pager which allows you to iterate over a collection of
+// networks. It accepts a ListOpts struct, which allows you to filter and sort
+// the returned collection for greater efficiency.
+func List(c *gophercloud.ServiceClient, instanceID string) pagination.Pager {
+	createPage := func(r pagination.PageResult) pagination.Page {
+		return VirtualInterfacePage{pagination.SinglePageBase(r)}
+	}
+
+	return pagination.NewPager(c, listURL(c, instanceID), createPage)
+}
+
+// Create creates a new virtual interface for a network and attaches the network
+// to the server instance.
+func Create(c *gophercloud.ServiceClient, instanceID, networkID string) CreateResult {
+	var res CreateResult
+
+	reqBody := map[string]map[string]string{
+		"virtual_interface": {
+			"network_id": networkID,
+		},
+	}
+
+	// Send request to API
+	_, res.Err = perigee.Request("POST", createURL(c, instanceID), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		ReqBody:     &reqBody,
+		Results:     &res.Body,
+		OkCodes:     []int{201, 202},
+	})
+	return res
+}
+
+// Delete deletes the interface with interfaceID attached to the instance with
+// instanceID.
+func Delete(c *gophercloud.ServiceClient, instanceID, interfaceID string) DeleteResult {
+	var res DeleteResult
+	_, res.Err = perigee.Request("DELETE", deleteURL(c, instanceID, interfaceID), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		OkCodes:     []int{204},
+	})
+	return res
+}
diff --git a/rackspace/networking/v2/virtualinterfaces/requests_test.go b/rackspace/networking/v2/virtualinterfaces/requests_test.go
index 4f91359..c3487d2 100644
--- a/rackspace/networking/v2/virtualinterfaces/requests_test.go
+++ b/rackspace/networking/v2/virtualinterfaces/requests_test.go
@@ -1 +1,167 @@
 package virtualinterfaces
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/rackspace/gophercloud/pagination"
+	th "github.com/rackspace/gophercloud/testhelper"
+	fake "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func TestList(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/servers/12345/os-virtual-interfacesv2", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+    "virtual_interfaces": [
+        {
+            "id": "de7c6d53-b895-4b4a-963c-517ccb0f0775",
+            "ip_addresses": [
+                {
+                    "address": "192.168.0.2",
+                    "network_id": "f212726e-6321-4210-9bae-a13f5a33f83f",
+                    "network_label": "superprivate_xml"
+                }
+            ],
+            "mac_address": "BC:76:4E:04:85:20"
+        },
+        {
+            "id": "e14e789d-3b98-44a6-9c2d-c23eb1d1465c",
+            "ip_addresses": [
+                {
+                    "address": "10.181.1.30",
+                    "network_id": "3b324a1b-31b8-4db5-9fe5-4a2067f60297",
+                    "network_label": "private"
+                }
+            ],
+            "mac_address": "BC:76:4E:04:81:55"
+        }
+    ]
+}
+      `)
+	})
+
+	client := fake.ServiceClient()
+	count := 0
+
+	List(client, "12345").EachPage(func(page pagination.Page) (bool, error) {
+		count++
+		actual, err := ExtractVirtualInterfaces(page)
+		if err != nil {
+			t.Errorf("Failed to extract networks: %v", err)
+			return false, err
+		}
+
+		expected := []VirtualInterface{
+			VirtualInterface{
+				MACAddress: "BC:76:4E:04:85:20",
+				IPAddresses: []IPAddress{
+					IPAddress{
+						Address:      "192.168.0.2",
+						NetworkID:    "f212726e-6321-4210-9bae-a13f5a33f83f",
+						NetworkLabel: "superprivate_xml",
+					},
+				},
+				ID: "de7c6d53-b895-4b4a-963c-517ccb0f0775",
+			},
+			VirtualInterface{
+				MACAddress: "BC:76:4E:04:81:55",
+				IPAddresses: []IPAddress{
+					IPAddress{
+						Address:      "10.181.1.30",
+						NetworkID:    "3b324a1b-31b8-4db5-9fe5-4a2067f60297",
+						NetworkLabel: "private",
+					},
+				},
+				ID: "e14e789d-3b98-44a6-9c2d-c23eb1d1465c",
+			},
+		}
+
+		th.CheckDeepEquals(t, expected, actual)
+
+		return true, nil
+	})
+
+	if count != 1 {
+		t.Errorf("Expected 1 page, got %d", count)
+	}
+}
+
+func TestCreate(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/servers/12345/os-virtual-interfacesv2", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+		th.TestHeader(t, r, "Content-Type", "application/json")
+		th.TestHeader(t, r, "Accept", "application/json")
+		th.TestJSONRequest(t, r, `
+{
+    "virtual_interface": {
+        "network_id": "6789"
+    }
+}
+      `)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusCreated)
+
+		fmt.Fprintf(w, `{
+      "virtual_interfaces": [
+        {
+          "id": "de7c6d53-b895-4b4a-963c-517ccb0f0775",
+          "ip_addresses": [
+            {
+              "address": "192.168.0.2",
+              "network_id": "f212726e-6321-4210-9bae-a13f5a33f83f",
+              "network_label": "superprivate_xml"
+            }
+          ],
+          "mac_address": "BC:76:4E:04:85:20"
+        }
+      ]
+    }`)
+	})
+
+	expected := &VirtualInterface{
+		MACAddress: "BC:76:4E:04:85:20",
+		IPAddresses: []IPAddress{
+			IPAddress{
+				Address:      "192.168.0.2",
+				NetworkID:    "f212726e-6321-4210-9bae-a13f5a33f83f",
+				NetworkLabel: "superprivate_xml",
+			},
+		},
+		ID: "de7c6d53-b895-4b4a-963c-517ccb0f0775",
+	}
+
+	actual, err := Create(fake.ServiceClient(), "12345", "6789").Extract()
+	th.AssertNoErr(t, err)
+
+	th.CheckDeepEquals(t, expected, actual)
+}
+
+func TestDelete(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/servers/12345/os-virtual-interfacesv2/6789", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "DELETE")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	res := Delete(fake.ServiceClient(), "12345", "6789")
+	th.AssertNoErr(t, res.Err)
+}
diff --git a/rackspace/networking/v2/virtualinterfaces/results.go b/rackspace/networking/v2/virtualinterfaces/results.go
index 4f91359..6818fcb 100644
--- a/rackspace/networking/v2/virtualinterfaces/results.go
+++ b/rackspace/networking/v2/virtualinterfaces/results.go
@@ -1 +1,79 @@
 package virtualinterfaces
+
+import (
+	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+type commonResult struct {
+	gophercloud.Result
+}
+
+// Extract is a function that accepts a result and extracts a network resource.
+func (r commonResult) Extract() (*VirtualInterface, error) {
+	if r.Err != nil {
+		return nil, r.Err
+	}
+
+	var res struct {
+		VirtualInterfaces []VirtualInterface `mapstructure:"virtual_interfaces" json:"virtual_interfaces"`
+	}
+
+	err := mapstructure.Decode(r.Body, &res)
+
+	return &res.VirtualInterfaces[0], err
+}
+
+// CreateResult represents the result of a create operation.
+type CreateResult struct {
+	commonResult
+}
+
+// DeleteResult represents the result of a delete operation.
+type DeleteResult commonResult
+
+// IPAddress represents a vitual address attached to a VirtualInterface.
+type IPAddress struct {
+	Address      string `mapstructure:"address" json:"address"`
+	NetworkID    string `mapstructure:"network_id" json:"network_id"`
+	NetworkLabel string `mapstructure:"network_label" json:"network_label"`
+}
+
+// VirtualInterface represents a virtual interface.
+type VirtualInterface struct {
+	// UUID for the virtual interface
+	ID string `mapstructure:"id" json:"id"`
+
+	MACAddress string `mapstructure:"mac_address" json:"mac_address"`
+
+	IPAddresses []IPAddress `mapstructure:"ip_addresses" json:"ip_addresses"`
+}
+
+// VirtualInterfacePage is the page returned by a pager when traversing over a
+// collection of virtual interfaces.
+type VirtualInterfacePage struct {
+	pagination.SinglePageBase
+}
+
+// IsEmpty returns true if the NetworkPage contains no Networks.
+func (r VirtualInterfacePage) IsEmpty() (bool, error) {
+	networks, err := ExtractVirtualInterfaces(r)
+	if err != nil {
+		return true, err
+	}
+	return len(networks) == 0, nil
+}
+
+// ExtractVirtualInterfaces accepts a Page struct, specifically a VirtualInterfacePage struct,
+// and extracts the elements into a slice of VirtualInterface structs. In other words,
+// a generic collection is mapped into a relevant slice.
+func ExtractVirtualInterfaces(page pagination.Page) ([]VirtualInterface, error) {
+	var resp struct {
+		VirtualInterfaces []VirtualInterface `mapstructure:"virtual_interfaces" json:"virtual_interfaces"`
+	}
+
+	err := mapstructure.Decode(page.(VirtualInterfacePage).Body, &resp)
+
+	return resp.VirtualInterfaces, err
+}
diff --git a/rackspace/networking/v2/virtualinterfaces/urls.go b/rackspace/networking/v2/virtualinterfaces/urls.go
index 4f91359..9e5693e 100644
--- a/rackspace/networking/v2/virtualinterfaces/urls.go
+++ b/rackspace/networking/v2/virtualinterfaces/urls.go
@@ -1 +1,15 @@
 package virtualinterfaces
+
+import "github.com/rackspace/gophercloud"
+
+func listURL(c *gophercloud.ServiceClient, instanceID string) string {
+	return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2")
+}
+
+func createURL(c *gophercloud.ServiceClient, instanceID string) string {
+	return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2")
+}
+
+func deleteURL(c *gophercloud.ServiceClient, instanceID, interfaceID string) string {
+	return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2", interfaceID)
+}
diff --git a/rackspace/networking/v2/virtualinterfaces/urls_test.go b/rackspace/networking/v2/virtualinterfaces/urls_test.go
index 4f91359..6732e4e 100644
--- a/rackspace/networking/v2/virtualinterfaces/urls_test.go
+++ b/rackspace/networking/v2/virtualinterfaces/urls_test.go
@@ -1 +1,32 @@
 package virtualinterfaces
+
+import (
+	"testing"
+
+	"github.com/rackspace/gophercloud"
+	th "github.com/rackspace/gophercloud/testhelper"
+)
+
+const endpoint = "http://localhost:57909/"
+
+func endpointClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{Endpoint: endpoint}
+}
+
+func TestCreateURL(t *testing.T) {
+	actual := createURL(endpointClient(), "12345")
+	expected := endpoint + "servers/12345/os-virtual-interfacesv2"
+	th.AssertEquals(t, expected, actual)
+}
+
+func TestListURL(t *testing.T) {
+	actual := createURL(endpointClient(), "12345")
+	expected := endpoint + "servers/12345/os-virtual-interfacesv2"
+	th.AssertEquals(t, expected, actual)
+}
+
+func TestDeleteURL(t *testing.T) {
+	actual := deleteURL(endpointClient(), "12345", "6789")
+	expected := endpoint + "servers/12345/os-virtual-interfacesv2/6789"
+	th.AssertEquals(t, expected, actual)
+}