Code Monkey home page Code Monkey logo

gophercloud's Introduction

Gophercloud: an OpenStack SDK for Go

Coverage Status

Reference documentation

Gophercloud is a Go SDK for OpenStack.

Join us on kubernetes slack, on #gophercloud. Visit slack.k8s.io for an invitation.

Note This branch contains the current stable branch of Gophercloud: v2. The legacy stable version can be found in the v1 branch.

How to install

Reference a Gophercloud package in your code:

import "github.com/gophercloud/gophercloud/v2"

Then update your go.mod:

go mod tidy

Getting started

Credentials

Because you'll be hitting an API, you will need to retrieve your OpenStack credentials and either store them in a clouds.yaml file, as environment variables, or in your local Go files. The first method is recommended because it decouples credential information from source code, allowing you to push the latter to your version control system without any security risk.

You will need to retrieve the following:

  • A valid Keystone identity URL
  • Credentials. These can be a username/password combo, a set of Application Credentials, a pre-generated token, or any other supported authentication mechanism.

For users who have the OpenStack dashboard installed, there's a shortcut. If you visit the project/api_access path in Horizon and click on the "Download OpenStack RC File" button at the top right hand corner, you can download either a clouds.yaml file or an openrc bash file that exports all of your access details to environment variables. To use the clouds.yaml file, place it at ~/.config/openstack/clouds.yaml. To use the openrc file, run source openrc and you will be prompted for your password.

Gophercloud authentication

Gophercloud authentication is organized into two layered abstractions:

  • ProviderClient holds the authentication token and can be used to build a ServiceClient.
  • ServiceClient specializes against one specific OpenStack module and can directly be used to make API calls.

A provider client is a top-level client that all of your OpenStack service clients derive from. The provider contains all of the authentication details that allow your Go code to access the API - such as the base URL and token ID.

One single Provider client can be used to build as many Service clients as needed.

With clouds.yaml

package main

import (
	"context"

	"github.com/gophercloud/gophercloud/v2/openstack"
	"github.com/gophercloud/gophercloud/v2/openstack/config"
	"github.com/gophercloud/gophercloud/v2/openstack/config/clouds"
)

func main() {
	ctx := context.Background()

	// Fetch coordinates from a `cloud.yaml` in the current directory, or
	// in the well-known config directories (different for each operating
	// system).
	authOptions, endpointOptions, tlsConfig, err := clouds.Parse()
	if err != nil {
		panic(err)
	}

	// Call Keystone to get an authentication token, and use it to
	// construct a ProviderClient. All functions hitting the OpenStack API
	// accept a `context.Context` to enable tracing and cancellation.
	providerClient, err := config.NewProviderClient(ctx, authOptions, config.WithTLSConfig(tlsConfig))
	if err != nil {
		panic(err)
	}

	// Use the ProviderClient and the endpoint options fetched from
	// `clouds.yaml` to build a service client: a compute client in this
	// case. Note that the contructor does not accept a `context.Context`:
	// no further call to the OpenStack API is needed at this stage.
	computeClient, err := openstack.NewComputeV2(providerClient, endpointOptions)
	if err != nil {
		panic(err)
	}

	// use the computeClient
}

With environment variables (openrc)

Gophercloud can parse the environment variables set by running source openrc:

package main

import (
	"context"
	"os"

	"github.com/gophercloud/gophercloud/v2"
	"github.com/gophercloud/gophercloud/v2/openstack"
)

func main() {
	ctx := context.Background()

	opts, err := openstack.AuthOptionsFromEnv()
	if err != nil {
		panic(err)
	}

	providerClient, err := openstack.AuthenticatedClient(ctx, opts)
	if err != nil {
		panic(err)
	}

	computeClient, err := openstack.NewComputeV2(providerClient, gophercloud.EndpointOpts{
		Region: os.Getenv("OS_REGION_NAME"),
	})
	if err != nil {
		panic(err)
	}

	// use the computeClient
}

Manually

You can also generate a "Provider" by passing in your credentials explicitly:

package main

import (
	"context"

	"github.com/gophercloud/gophercloud/v2"
	"github.com/gophercloud/gophercloud/v2/openstack"
)

func main() {
	ctx := context.Background()

	providerClient, err := openstack.AuthenticatedClient(ctx, gophercloud.AuthOptions{
		IdentityEndpoint: "https://openstack.example.com:5000/v2.0",
		Username:         "username",
		Password:         "password",
	})
	if err != nil {
		panic(err)
	}

	computeClient, err := openstack.NewComputeV2(providerClient, gophercloud.EndpointOpts{
		Region: "RegionName",
	})
	if err != nil {
		panic(err)
	}

	// use the computeClient
}

Provision a server

We can use the Compute service client generated above for any Compute API operation we want. In our case, we want to provision a new server. To do this, we invoke the Create method and pass in the flavor ID (hardware specification) and image ID (operating system) we're interested in:

import "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers"

func main() {
    // [...]

    server, err := servers.Create(context.TODO(), computeClient, servers.CreateOpts{
        Name:      "My new server!",
        FlavorRef: "flavor_id",
        ImageRef:  "image_id",
    }).Extract()

    // [...]

The above code sample creates a new server with the parameters, and returns a servers.Server.

Supported Services

Service Name Module 1.x 2.x
Baremetal Ironic openstack/baremetal
Baremetal Introspection Ironic Inspector openstack/baremetalintrospection
Block Storage Cinder openstack/blockstorage
Clustering Senlin openstack/clustering
Compute Nova openstack/compute
Container Zun openstack/container
Container Infrastructure Magnum openstack/containerinfra
Database Trove openstack/db
DNS Designate openstack/dns
Identity Keystone openstack/identity
Image Glance openstack/image
Key Management Barbican openstack/keymanager
Load Balancing Octavia openstack/loadbalancer
Messaging Zaqar openstack/messaging
Networking Neutron openstack/networking
Object Storage Swift openstack/objectstorage

Advanced Usage

Have a look at the FAQ for some tips on customizing the way Gophercloud works.

Backwards-Compatibility Guarantees

Gophercloud versioning follows semver.

Before v1.0.0, there were no guarantees. Starting with v1, there will be no breaking changes within a major release.

See the Release instructions.

Contributing

See the contributing guide.

Help and feedback

If you're struggling with something or have spotted a potential bug, feel free to submit an issue to our bug tracker.

gophercloud's People

Contributors

alex avatar bison avatar dependabot[bot] avatar dklyle avatar dkt26111 avatar dstdfx avatar dtantsur avatar ehdou avatar emilienm avatar emilmaruszczak avatar ggiamarchi avatar jackkuei avatar jrperritt avatar jtopjian avatar kayrus avatar lingxiankong avatar mandre avatar markpeek avatar maxlinc avatar nikparasyr avatar ozerovandrei avatar pierreprinetti avatar problemv avatar sam-falvo avatar simonre avatar smashwilson avatar stbenjam avatar stephenfin avatar tommylike avatar zhangzujian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gophercloud's Issues

Updates to acceptance test environment scripts

There's some missing information from the acceptance test environment scripts that would enable someone to run them and have a fully functional devstack environment to run the acceptance tests on.

`ChooseVersion` doesn't match recent Keystone builds

Hi,

ChooseVersion, as it is used in Authenticate tries to explicitly match the ID field of the Keystone response to v2.0 and v3.0.

However, my Keystone API returns the following:

{
    "versions": {
        "values": [
            {
                "status": "stable",
                "updated": "2016-10-06T00:00:00Z",
                "media-types": [
                    {
                        "base": "application/json",
                        "type": "application/vnd.openstack.identity-v3+json"
                    }
                ],
                "id": "v3.7",
                "links": [
                    {
                        "href": "http://identity.openstack.cluster:30080/v3/",
                        "rel": "self"
                    }
                ]
            },
            {
                "status": "deprecated",
                "updated": "2016-08-04T00:00:00Z",
                "media-types": [
                    {
                        "base": "application/json",
                        "type": "application/vnd.openstack.identity-v2.0+json"
                    }
                ],
                "id": "v2.0",
                "links": [
                    {
                        "href": "http://identity.openstack.cluster:30080/v2.0/",
                        "rel": "self"
                    },
                    {
                        "href": "http://docs.openstack.org/",
                        "type": "text/html",
                        "rel": "describedby"
                    }
                ]
            }
        ]
    }
}

The v3 API can't be matched due to the ID being v3.7 and the v2 API can't either as it is deprecated.

Unmarshal error when copying object

I'm seeing the following error when trying to extract the results of a copy:

json: cannot unmarshal string into Go value of type int64

Here's the code I'm using:

copyResult := objects.Copy(client, containerName, objectName, copyOpts)
copyHeader, err := copyResult.Extract()

Here's what copyResult looks like:

objects.CopyResult{HeaderResult:gophercloud.HeaderResult{Result:gophercloud.Result{Body:interface {}(nil), Header:http.Header{"Last-Modified":[]string{"Sun, 14 Aug 2016 23:11:50 GMT"}, "Etag":[]string{"4cb9bc8724551e6c7415f1080df84869"}, "X-Copied-From-Account":[]string{"AUTH_a54442e26ad8409a905659a268197eae"}, "Content-Type":[]string{"text/html; charset=UTF-8"}, "X-Trans-Id":[]string{"tx76234fbd166a462ca6e84-0057b0fab5"}, "Date":[]string{"Sun, 14 Aug 2016 23:11:49 GMT"}, "Content-Length":[]string{"0"}, "X-Copied-From":[]string{"test-container-Jy8w56q9/test-object-chsLSwuc"}, "X-Copied-From-Last-Modified":[]string{"Sun, 14 Aug 2016 23:11:50 GMT"}}, Err:error(nil)}}}

ContentLength is triggering the error

This is probably the same as the other unmarshal errors, but I'm not sure what to do since CopyResult is of type gophercloud.HeaderResult. Doing it incorrectly is probably going to break more things down the chain.

As well, ContentLength is defined as a string for the other structs. So maybe changing int64 to string is the solution?

New Branch to Support Magnum Bays

The magnum API isn't solidified yet. I will have access to an environment this week and will update the ticket with additional details on each action.

  • POST /bays - create a cluster
  • GET /bays/[id] - get cluster info
  • PUT /bays/[id] - update a cluster, currently that only means increasing the node count
  • DELETE /bays - delete a cluster

Boot From Volume Updates

I'm pretty sure DestinationType is required because I'm getting errors returned whenever it's omitted.

Additionally, there are only two DestinationTypes possible, volume and local, so it might be worthwhile to have them as defined types. However, I'm not sure what to do since there's an existing SourceType of Volume -- have a combined type of SourceDestinationType and then check for the allowable ones in the ToServersCreateMap?

Also, VolumeSize can be omitted in certain situations.

The different combinations of allowed block device options are described here.

Compute Acceptance Test Issues

I tried running the TestListFlavor acceptance test and had to fix a lot of errors in the acceptance/openstack/compute/v2 directory to just get the test to run. The test passed, but incorrectly -- no flavors were printed.

Here's the diff of what needed to be changed just to get the test to run:

jtopjian@74cd982

It looks like there have been a good amount of changes that have happened to the code base - are these the types of things that should be documented in the MIGRATING doc?

I'd be happy to submit PRs to fix the tests, but having no flavors printed is throwing me off. It looks like there might be some auth issues and I have no doubt that someone else can figure that one out quicker than me.

Nice work on this new repo, by the way!

networks.Up missing

I'm using gophercloud for the first time and note the recent transition from the rackspace repository to this one. Firstly, am I supposed to be using this version of the API?

I'm going through the various docs at http://gophercloud.io/docs/networking/ and the create code references networks.UP, which for some reason is no longer defined in the gophercloud/gophercloud version of https://github.com/rackspace/gophercloud/blob/master/openstack/networking/v2/networks/requests.go
It got removed in e3cb7e4 on Mar 7 https://github.com/gophercloud/gophercloud/blob/e3cb7e45cd599c4a14838e81ffa5175f203c2340/openstack/networking/v2/networks/requests.go
Why is it missing, and surely this would break people's code?

use interfaces for errors

Instead of exporting custom error types, I think it'd be better to not export them, and instead have them implement an interface (e.g. InvalidInput, MissingInput).

Needs more thought.

Error 400 while disassociating floating IP

When disassociating a floating IP from a Neutron port, I receive a 400 error: "Invalid request due to incorrect syntax or missing required parameters."

import "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
floatingips.Update(client, floatingIP.ID, floatingips.UpdateOpts{})

I dumped the request and I saw that the PortID attribute of UpdateOpts is serialized as an empty string. The Neutron API reference states that it should be a null value.

I'm not sure what could be a proper fix for this, but when I convert PortID to a pointer, it works fine:

type UpdateOpts struct {
     PortID *string `json:"port_id"`
}

Is there a way to debug by printing all api calls?

I'm having a problem where if I create a network and a server on that network, I can't ssh to the server for over 5 (sometimes 30) minutes. If the network has been up for long enough, ssh'ing to new servers works in < 1 minute as expected.

If I create the network with seemingly the same settings using the python 'openstack' command line tool, however, I have no problems with new networks.

So I'm trying to debug if this is a gophercloud-specific issue.

Is there a way to print out all the api calls that gophercloud makes (like a debug switch I can turn on somewhere), and if not, which places in which files can I temporarily hack to ensure I capture all outgoing api requests?

investigate unit test coverage stats

After briefly looking at coveralls, it looked like the coverage profile was mostly over fixtures.go files, which isn't what we want. Might need to re-add build tags. In addition, gotestcover (which we're currently using to aggregate unit test coverage statistics) has been deprecated, so that'll need to be changed.

identity/v2: Error when adding role to user

When adding a role to a user, the following error is seen:

Unable to grant role to user: Expected HTTP response code [201 202] when accessing [PUT http://10.1.7.61:35357/v2.0/tenants/20e0168198504ef6bb77844b23df18aa/users/11d01713fd874ae4bf20
55b2a8023147/roles/OS-KSADM/017257e31a1e421b8b533afc27882521], but got 200 instead

AFAICT, which isn't saying much, unless an explicit status is given, and the request is successful, a 200 response is returned:

https://github.com/openstack/keystone/blob/94e83aff172feee3874604ab1a92d4038be4965f/keystone/common/wsgi.py#L732-L733

And I don't see an explicit status set here:

https://github.com/openstack/keystone/blob/94e83aff172feee3874604ab1a92d4038be4965f/keystone/assignment/controllers.py#L150

Network Provider SegmentationID type error

Even though segmentation_id is defined as a string, it's actually being returned as a number.

Examples can be seen here as well as throughout the Neutron code where it's defined as Int.

So I think SegmentationID needs to be updated as an int. VXLAN allows for 16 million vxlans, and thus 16 million VXLAN IDs, which int can handle, but maybe there's another network type that goes past an int's max number and this should be int64? Or deal with that if it arises?

Issue creating server with metadata

When creating a server with metadata in the Create request, the metadata is not being recognized.

Upon digging into why, I've found a few metadata inconsistencies but am not sure what the best overall fix would be:

  1. Metadata is defined in the request as a map[string]string but is a map[string]interface{} in the result. This has not changed from the Rackspace code, but should either one or the other be used in both places?
  2. The JSON tag in the request is declaring to omit the metadata field. This is used in some other areas of the request, but I believe that is so those fields can be given extra attention in the ToServerCreateMap.

I believe it is the addition of this JSON tag that is ultimately causing the metadata to not be recognized during the creation. But should the CreateOpts be changed to:

Metadata map[string]string `json:"metadata,omitempty"`

Or should something like the following be added to ToServerCreateMap:

if len(opts.Metadata) > 0 {
  metadata := make(map[string]string, len(opts.Metadata))
  for k, v := range opts.Metadata {
    metadata[k] = v
  }
  b["metadata"] = metadata
}

I'm inclined to go with just the JSON tag, but wanted to ask in case there's a reason for the latter.

TenantID not required in LBaaS Members

The TenantID attribute is currently marked as being required. It's only required when an admin user wants to create a member on behalf of another tenant.

Making it not required matches the other TenantID attributes found in other Create calls.

Acceptance Test Ideas

I started working on the Block Storage acceptance tests and wanted to reuse some of the work done in the Compute acceptance tests. This ranged from something as simple as initializing a client to creating a server to attach a volume.

Would it be worthwhile to make further changes to the tests (and test file structure) to do this?

Migration

Is there currently ability to migrate server using gophercloud?

Block Storage Acceptance Tests

In the same way that the Compute tests were reviewed and cleaned up, it would be beneficial for the Block Storage tests to have the same done.

compute/v2/flavors: error parsing empty swap

A flavor being returned by OpenStack looks like:

    {
      "OS-FLV-DISABLED:disabled": false,
      "OS-FLV-EXT-DATA:ephemeral": 0,
      "disk": 160,
      "id": "5",
      "links": [
        {
          "href": "http://10.1.11.212:8774/v2.1/80839b1b20aa41a3a4bf32718bae67cb/flavors/5",
          "rel": "self"
        },
        {
          "href": "http://10.1.11.212:8774/80839b1b20aa41a3a4bf32718bae67cb/flavors/5",
          "rel": "bookmark"
        }
      ],
      "name": "m1.xlarge",
      "os-flavor-access:is_public": true,
      "ram": 16384,
      "rxtx_factor": 1,
      "swap": "",
      "vcpus": 8
    },

When no swap is set, the returned value is "" which triggers the error:

Unable to retrieve flavors: json: cannot unmarshal string into Go value of type int

Swap is defined in Gophercloud as an int, as it should, because Nova defines it as an int as well.

Was mapstructure doing more lenient casting of values?

Sometimes No ImageRef is OK

Currently, server creation will fail if neither ImageRef and ImageName are provided, but sometimes it's OK for the ImageRef to be empty. Notably when booting from a volume.

What's the best way to modify the ToServerCreateMap to account for this? Does opts have access to BlockDevice (or block_device_mapping) inside servers.ToServerCreateMap?

If it doesn't, is the next option to modify the check for ImageRef and ImageName to not fail when neither are provided?

making all times `time.Time`

Currently some operation results use string while others use Gophercloud custom types (e.g. gophercloud.JSONUnix). Creating an Unmarshal method on each result and doing the conversion there. One benefit would be not having to export all the custom time types.

LBaaS doesn't return vip_port_id

The LBaaSv2 code returns all the loadbalancer details, including vip_subnet_id and vip_address, but doesn't return vip_port_id. When creating a loadbalancer, neutron only applies the default security group. If you wish to expose a loadbalancer externally through a floating ip, you'll want to attach another security group which is applied to the vip_port. As of right now, the workaround is the port is named loadbalancer-<loadbalancer_id> so you can get the id and then work the port that way, but it would be much cleaner to return the vip_port_id when querying a loadbalancer.

network deletion fails with NetworkInUse, if it was recently used

I set up networking for server, launch the server, kill the server after 10 seconds (this is for a test), and want to immediately delete the networking things as well, but it fails unless I sleep for another 10 seconds after deleting my server. How can I avoid this?

In outline (error checking removed), I create like this:

externalNetworkId, err := networks.IDFromName(networkClient, poolName)
//...
network, err := networks.Create(networkClient, networks.CreateOpts{Name: resourceName, AdminStateUp: gophercloud.Enabled}).Extract()
networkID = network.ID
var gip = new(string)
*gip = "192.168.0.1"
subnet, err := subnets.Create(networkClient, subnets.CreateOpts{
    NetworkID: networkID,
    CIDR:      "192.168.0.0/16",
    GatewayIP: gip,
    IPVersion: 4,
    Name: subnetName,
}).Extract()
//...
router, err := routers.Create(networkClient, routers.CreateOpts{
    Name:         resourceName,
    GatewayInfo:  &routers.GatewayInfo{NetworkID: externalNetworkId},
    AdminStateUp: gophercloud.Enabled,
}).Extract()
_, err = routers.AddInterface(networkClient, router.ID, routers.AddInterfaceOpts{SubnetID: subnet.ID}).Extract()
//...
server, err := servers.Create(client, keypairs.CreateOptsExt{
    servers.CreateOpts{
        Name:           resourceName,
        FlavorRef:      flavorId,
        ImageRef:       imageId,
        SecurityGroups: []string{resourceName},
        Networks:       []servers.Network{servers.Network{UUID: networkID}},
    },
    resourceName, // keypair name
}).Extract()
err = servers.WaitForStatus(client, server.ID, "ACTIVE", 60)
//...
allFloatingIPPages, err := floatingips.List(client).AllPages()
allFloatingIPs, err := floatingips.ExtractFloatingIPs(allFloatingIPPages)
var floatingIP string
for _, fIP := range allFloatingIPs {
    if fIP.InstanceID == "" {
        floatingIP = fIP.IP
        break
    }
}
if floatingIP == "" {
    // create a new one
    fIP, err := floatingips.Create(client, floatingips.CreateOpts{
        Pool: poolName,
    }).Extract()
    floatingIP = fIP.IP
}
err = floatingips.AssociateInstance(client, server.ID, floatingips.AssociateOpts{
    FloatingIP: floatingIP,
}).ExtractErr()

And I try to delete like this:

<-time.After(10 * time.Second)
err = floatingips.DisassociateInstance(client, server.ID, floatingips.DisassociateOpts{FloatingIP: floatingIP}).ExtractErr() // must explicitly do this first, or can't delete router
err = servers.Delete(client, server.ID).ExtractErr()
//...
_, err = routers.RemoveInterface(networkClient, router.ID, routers.RemoveInterfaceOpts{SubnetID: subnet.ID}).Extract() // must do this or can't delete router
err = routers.Delete(networkClient, router.ID).ExtractErr()
// <-time.After(10 * time.Second) // this is required to make the following line work
err = networks.Delete(networkClient, networkID).ExtractErr()

Without waiting a few seconds before trying to delete my network, I get:

Expected HTTP response code [202 204] when accessing [DELETE http://172.31.0.18:9696/v2.0/networks/a2c5835d-f1e7-4def-9abe-d7e996caf24d], but got 409 instead
{"NeutronError": {"message": "Unable to complete operation on network a2c5835d-f1e7-4def-9abe-d7e996caf24d. There are one or more ports still in use on the network.", "type": "NetworkInUse", "detail": ""}}

If I try to explicitly delete my subnet first with:

err = subnets.Delete(networkClient, subnet.ID).ExtractErr()

I instead get:

Expected HTTP response code [202 204] when accessing [DELETE http://172.31.0.18:9696/v2.0/subnets/8ab18cac-add7-4328-9f29-0771111a6378], but got 409 instead
{"NeutronError": {"message": "Unable to complete operation on subnet 8ab18cac-add7-4328-9f29-0771111a6378. One or more ports have an IP allocation from this subnet.", "type": "SubnetInUse", "detail": ""}}

Firstly, is this the right approach to setting up to launch a server so you can ssh to it, and is the right way to tear everything down afterwards?

What do I need to delete or alter to let me cleanly delete my network without waiting for some arbitrary and unknown time?

reorganize unit tests

The coverage stats are getting thrown off because go cover assumes the tests are testing the package they're in. Though I'd prefer to keep all the test files together, the easiest thing to do for now is move the requests_test.go files back into the package they test.

Keystoneless Client

If it's not already possible, what's the general outline for making a client that bypasses Keystone? In particular, this would be for Swift clients that authenticate directly with Swift. It would resemble this:

https://github.com/ncw/swift/blob/master/auth.go#L85-L94

Is this something that would make sense to have in Gophercloud or is there a requirement to have all clients go through Keystone?

Unable to parse Block Storage v1 Volume.CreatedAt

When trying to create a volume, the following error is returned:

parsing time "2016-07-26T01:21:26.911126" as "2006-01-02T15:04:05.999999Z": cannot parse "" as "Z"

It looks like the CreatedAt type needs changed to gophercloud.JSONRFC3339MilliNoZ.

Can't list servers when one is booted from volume

When I list server instances, it fails when an instance is booted from volume with the following error: json: cannot unmarshal string into Go value of type map[string]interface {}

This code will trigger the bug, provided you have proper environment variables and at least one volume booted server:

package main

import (
    "log"
    "os"

    "github.com/gophercloud/gophercloud"
    "github.com/gophercloud/gophercloud/openstack"
    "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)

func main() {
    opts, _ := openstack.AuthOptionsFromEnv()
    provider, _ := openstack.AuthenticatedClient(opts)
    client, _ := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{Region: os.Getenv("OS_REGION_NAME")})
    listopts := servers.ListOpts{}
    pager := servers.List(client, listopts)
    _, err := pager.AllPages()
    if err != nil {
        log.Fatalln(err)
    }

}

The JSON returned in that case contains: image: "" and ExtractInto tries to convert this empty JSON string to a map[string]interface{} which fails.

I reproduced it on a Juno and a Liberty release.

How do you use keypairs?

I can create and get a keypair using github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs create() and get(), but how do I associate that keypair with a server? As far as I can see, github.com/gophercloud/gophercloud/openstack/compute/v2/servers CreateOpts does not have any keypair-related field.

ListAddressesByNetwork().AllPages() panic

I have a code path that checks to see if a server exists by its Name. If it doesn't, it creates it. Then I see what ip addresses the server has, to figure out if it has a floating ip:

pager = servers.List(client, servers.ListOpts{Name: resourceName, Status: "ACTIVE"})
var server *servers.Server
err = pager.EachPage(func(page pagination.Page) (bool, error) {
    serverList, err := servers.ExtractServers(page)
    if err != nil {
        return false, err
    }
    server = &serverList[0]
    fmt.Printf("got pre-existing server %+v\n", server)
    return true, nil
})
if err != nil {
    panic(err)
}
if server == nil {
    server, err := servers.Create(client, keypairs.CreateOptsExt{
        servers.CreateOpts{
            Name:           resourceName,
            FlavorRef:      flavorId,
            ImageRef:       imageId,
            SecurityGroups: []string{resourceName},
            Networks:       []servers.Network{servers.Network{UUID: networkID}},
            // UserData []byte (will be base64-encoded for me)
            // Metadata map[string]string
        },
        resourceName, // keypair name
    }).Extract()
    if err != nil {
        panic(err)
    }

    fmt.Printf("created server %+v\n", server)

    // wait for it to come up
    err = servers.WaitForStatus(client, server.ID, "ACTIVE", 60) //*** not sure this timeout really works...
    if err != nil {
        panic(err)
    }

    fmt.Println("server now ACTIVE")
}
// check if the server has a floating ip; if not, get one and associate with
// server
allNetworkAddressPages, err := servers.ListAddressesByNetwork(client, server.ID, resourceName).AllPages() // panics here (no error returned) without a router
if err != nil {
    fmt.Printf("ListAddressesByNetwork error: %s\n", err)
    os.Exit(1)
}
allNetworkAddresses, err := servers.ExtractNetworkAddresses(allNetworkAddressPages)
if err != nil {
    panic(err)
}
var floatingIP string
for _, address := range allNetworkAddresses {
    if address.Version == 4 && !strings.HasPrefix(address.Address, "192.168") {
        floatingIP = address.Address
        fmt.Printf("server already has floating ip %s\n", floatingIP)
        break
    }
}
if floatingIP == "" {
    fmt.Println("server has no floating ip")
    // [...]
}

The first time I run my code, I create the server and get this from my debugging:

created server &{ID:97586552-1c7c-47ab-8816-cd3816e99d7a TenantID: UserID: Name: Updated: Created: HostID: Status: Progress:0 AccessIPv4: AccessIPv6: Image:map[] Flavor:map[] Addresses:map[] Metadata:map[] Links:[map[href:http://172.31.0.18:8774/v2/ad5e4867d0174c8b8850e426ef5b215d/servers/97586552-1c7c-47ab-8816-cd3816e99d7a rel:self] map[href:http://172.31.0.18:8774/ad5e4867d0174c8b8850e426ef5b215d/servers/97586552-1c7c-47ab-8816-cd3816e99d7a rel:bookmark]] KeyName: AdminPass:AJvxG7v8BxDd SecurityGroups:[map[name:vrpipe-deployment]]}
server now ACTIVE
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x403c81]

The stack trace points to the line that I call ListAddressesByNetwork().AllPages() (and not the err check).

If I run my code again, changing nothing (except that now the server is already running), I get:

got pre-existing server &{ID:97586552-1c7c-47ab-8816-cd3816e99d7a TenantID:ad5e4867d0174c8b8850e426ef5b215d UserID:0bdadd0bb3da45509d56c40dc98d73a5 Name:vrpipe-deployment Updated:2016-08-12T14:55:15Z Created:2016-08-12T14:54:57Z HostID:1d35adc28d9b40f4fb5e3cd869cfab8a3c119ecd051b0bd847429c72 Status:ACTIVE Progress:0 AccessIPv4: AccessIPv6: Image:map[id:002ca5be-3934-43d3-9d2c-eda816b57019 links:[map[href:http://172.31.0.18:8774/ad5e4867d0174c8b8850e426ef5b215d/images/002ca5be-3934-43d3-9d2c-eda816b57019 rel:bookmark]]] Flavor:map[id:2 links:[map[href:http://172.31.0.18:8774/ad5e4867d0174c8b8850e426ef5b215d/flavors/2 rel:bookmark]]] Addresses:map[vrpipe-deployment:[map[OS-EXT-IPS-MAC:mac_addr:fa:16:3e:84:30:2c OS-EXT-IPS:type:fixed addr:192.168.0.6 version:4]]] Metadata:map[] Links:[map[rel:self href:http://172.31.0.18:8774/v2/ad5e4867d0174c8b8850e426ef5b215d/servers/97586552-1c7c-47ab-8816-cd3816e99d7a] map[href:http://172.31.0.18:8774/ad5e4867d0174c8b8850e426ef5b215d/servers/97586552-1c7c-47ab-8816-cd3816e99d7a rel:bookmark]] KeyName:vrpipe-deployment AdminPass: SecurityGroups:[map[name:vrpipe-deployment]]}
server has no floating ip

ie. it works perfectly. Am I doing something wrong? I just want to find out if my server has a floating ip associated with it. What's the best way to do that?

Subnet Gateway Behavior

When creating a subnet, there are three different actions that can happen:

  1. When gateway_ip is omitted, Neutron will provision a default gateway.
  2. When gateway_ip is specified with a value of nil/None, no gateway is provisioned.
  3. When gateway_ip is specified and is a valid IP, that IP is used for the gateway.

Currently, gophercloud can do 1 and 3, but not 2.

reference

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.