Add getting_started tutorial for Gophercloud SDK
Add getting_started tutorial for Gophercloud SDK, code had been tested on a openstack cloud with neutron. Change-Id: Ife8bc23671ddff175a5ff424e08893c746d97482
This commit is contained in:
parent
ed11113c62
commit
7f6e20ae5c
294
firstapp/samples/gophercloud/getting_started.go
Normal file
294
firstapp/samples/gophercloud/getting_started.go
Normal file
@ -0,0 +1,294 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/images"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// step-1
|
||||
var authUsername string = "your_auth_username"
|
||||
var authPassword string = "your_auth_password"
|
||||
var authUrl string = "http://controller:5000"
|
||||
var projectName string = "your_project_id"
|
||||
var regionName string = "your_region_name"
|
||||
|
||||
authOpts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: authUrl,
|
||||
Username: authUsername,
|
||||
Password: authPassword,
|
||||
TenantID: projectName,
|
||||
}
|
||||
provider, _ := openstack.AuthenticatedClient(authOpts)
|
||||
client, _ := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
|
||||
Region: regionName,
|
||||
})
|
||||
|
||||
// step-2
|
||||
pager := images.ListDetail(client, images.ListOpts{})
|
||||
page, _ := pager.AllPages()
|
||||
imageList, _ := images.ExtractImages(page)
|
||||
fmt.Println(imageList)
|
||||
|
||||
// step-3
|
||||
pager = flavors.ListDetail(client, flavors.ListOpts{})
|
||||
page, _ = pager.AllPages()
|
||||
flavorList, _ := flavors.ExtractFlavors(page)
|
||||
fmt.Println(flavorList)
|
||||
|
||||
// step-4
|
||||
imageID := "74e6d1ec-9a08-444c-8518-4f232446386d"
|
||||
image, _ := images.Get(client, imageID).Extract()
|
||||
fmt.Println(image)
|
||||
|
||||
// step-5
|
||||
flavorID := "1"
|
||||
flavor, _ := flavors.Get(client, flavorID).Extract()
|
||||
fmt.Println(flavor)
|
||||
|
||||
// step-6
|
||||
instanceName := "testing"
|
||||
testingInstance, _ := servers.Create(client, servers.CreateOpts{
|
||||
Name: instanceName,
|
||||
ImageRef: imageID,
|
||||
FlavorRef: flavorID,
|
||||
}).Extract()
|
||||
fmt.Println(testingInstance)
|
||||
|
||||
// step-7
|
||||
pager = servers.List(client, servers.ListOpts{})
|
||||
page, _ = pager.AllPages()
|
||||
serverList, _ := servers.ExtractServers(page)
|
||||
fmt.Println(serverList)
|
||||
|
||||
// step-8
|
||||
servers.Delete(client, testingInstance.ID)
|
||||
|
||||
// step-9
|
||||
fmt.Println("Checking for existing SSH key pair...")
|
||||
keyPairName := "demokey"
|
||||
pubKeyFile := "~/.ssh/id_rsa.pub"
|
||||
keyPairExists := false
|
||||
|
||||
pager = keypairs.List(client)
|
||||
page, _ = pager.AllPages()
|
||||
keypairList, _ := keypairs.ExtractKeyPairs(page)
|
||||
for _, k := range keypairList {
|
||||
if k.Name == keyPairName {
|
||||
keyPairExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if keyPairExists {
|
||||
fmt.Println("Keypair " + keyPairName + " already exists. Skipping import.")
|
||||
} else {
|
||||
fmt.Println("adding keypair...")
|
||||
bs, _ := ioutil.ReadFile(pubKeyFile)
|
||||
keypairs.Create(client, keypairs.CreateOpts{
|
||||
Name: keyPairName,
|
||||
PublicKey: string(bs),
|
||||
}).Extract()
|
||||
}
|
||||
|
||||
pager = keypairs.List(client)
|
||||
page, _ = pager.AllPages()
|
||||
keypairList, _ = keypairs.ExtractKeyPairs(page)
|
||||
fmt.Println(keypairList)
|
||||
|
||||
// step-10
|
||||
fmt.Println("Checking for existing security group...")
|
||||
var allInOneSecurityGroup secgroups.SecurityGroup
|
||||
securityGroupName := "all-in-one"
|
||||
securityGroupExists := false
|
||||
|
||||
pager = secgroups.List(client)
|
||||
page, _ = pager.AllPages()
|
||||
secgroupList, _ := secgroups.ExtractSecurityGroups(page)
|
||||
for _, secGroup := range secgroupList {
|
||||
if secGroup.Name == securityGroupName {
|
||||
allInOneSecurityGroup = secGroup
|
||||
securityGroupExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if securityGroupExists {
|
||||
fmt.Println("Security Group " + allInOneSecurityGroup.Name + " already exists. Skipping creation.")
|
||||
} else {
|
||||
allInOneSecurityGroup, _ := secgroups.Create(client, secgroups.CreateOpts{
|
||||
Name: securityGroupName,
|
||||
Description: "network access for all-in-one application.",
|
||||
}).Extract()
|
||||
secgroups.CreateRule(client, secgroups.CreateRuleOpts{
|
||||
ParentGroupID: allInOneSecurityGroup.ID,
|
||||
FromPort: 80,
|
||||
ToPort: 80,
|
||||
IPProtocol: "TCP",
|
||||
CIDR: "0.0.0.0/0",
|
||||
}).Extract()
|
||||
secgroups.CreateRule(client, secgroups.CreateRuleOpts{
|
||||
ParentGroupID: allInOneSecurityGroup.ID,
|
||||
FromPort: 22,
|
||||
ToPort: 22,
|
||||
IPProtocol: "TCP",
|
||||
CIDR: "0.0.0.0/0",
|
||||
}).Extract()
|
||||
}
|
||||
|
||||
pager = secgroups.List(client)
|
||||
page, _ = pager.AllPages()
|
||||
secgroupList, _ = secgroups.ExtractSecurityGroups(page)
|
||||
fmt.Println(secgroupList)
|
||||
|
||||
// step-11
|
||||
userData := `#!/usr/bin/env bash
|
||||
curl -L -s https://git.openstack.org/cgit/openstack/faafo/plain/contrib/install.sh | bash -s -- \
|
||||
-i faafo -i messaging -r api -r worker -r demo
|
||||
`
|
||||
|
||||
// step-12
|
||||
fmt.Println("Checking for existing instance...")
|
||||
instanceName = "all-in-one"
|
||||
instanceExists := false
|
||||
|
||||
pager = servers.List(client, servers.ListOpts{})
|
||||
page, _ = pager.AllPages()
|
||||
serverList, _ = servers.ExtractServers(page)
|
||||
for _, s := range serverList {
|
||||
if s.Name == instanceName {
|
||||
testingInstance = &s
|
||||
instanceExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if instanceExists {
|
||||
fmt.Println("Instance " + testingInstance.Name + " already exists. Skipping creation.")
|
||||
} else {
|
||||
opts := servers.CreateOpts{
|
||||
Name: instanceName,
|
||||
ImageRef: image.ID,
|
||||
FlavorRef: flavor.ID,
|
||||
SecurityGroups: []string{securityGroupName},
|
||||
UserData: []byte(userData),
|
||||
}
|
||||
testingInstance, _ = servers.Create(client, keypairs.CreateOptsExt{
|
||||
CreateOptsBuilder: opts,
|
||||
KeyName: keyPairName,
|
||||
}).Extract()
|
||||
}
|
||||
servers.WaitForStatus(client, testingInstance.ID, "ACTIVE", 300)
|
||||
|
||||
pager = servers.List(client, servers.ListOpts{})
|
||||
page, _ = pager.AllPages()
|
||||
serverList, _ = servers.ExtractServers(page)
|
||||
fmt.Println(serverList)
|
||||
|
||||
// step-13
|
||||
var privateIP string
|
||||
for t, addrs := range testingInstance.Addresses {
|
||||
if t != "private" || len(privateIP) != 0 {
|
||||
continue
|
||||
}
|
||||
addrs, ok := addrs.([]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
a, ok := addr.(map[string]interface{})
|
||||
if !ok || a["version"].(float64) != 4 {
|
||||
continue
|
||||
}
|
||||
ip, ok := a["addr"].(string)
|
||||
if ok && len(ip) != 0 {
|
||||
privateIP = ip
|
||||
fmt.Println("Private IP found: " + privateIP)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step-14
|
||||
var publicIP string
|
||||
for t, addrs := range testingInstance.Addresses {
|
||||
if t != "public" || len(publicIP) != 0 {
|
||||
continue
|
||||
}
|
||||
addrs, ok := addrs.([]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
a, ok := addr.(map[string]interface{})
|
||||
if !ok || a["version"].(float64) != 4 {
|
||||
continue
|
||||
}
|
||||
ip, ok := a["addr"].(string)
|
||||
if ok && len(ip) != 0 {
|
||||
publicIP = ip
|
||||
fmt.Println("Public IP found: " + publicIP)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step-15
|
||||
fmt.Println("Checking for unused Floating IP...")
|
||||
var unusedFloatingIP string
|
||||
pager = floatingip.List(client)
|
||||
page, _ = pager.AllPages()
|
||||
floatingIPList, _ := floatingip.ExtractFloatingIPs(page)
|
||||
for _, ip := range floatingIPList {
|
||||
if ip.InstanceID == "" {
|
||||
unusedFloatingIP = ip.IP
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
networkClient, _ := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
|
||||
Region: regionName,
|
||||
})
|
||||
|
||||
pager = networks.List(networkClient, networks.ListOpts{})
|
||||
page, _ = pager.AllPages()
|
||||
poolList, _ := external.ExtractList(page)
|
||||
for _, pool := range poolList {
|
||||
if len(unusedFloatingIP) != 0 || !pool.External {
|
||||
continue
|
||||
}
|
||||
fmt.Println("Allocating new Floating IP from pool: " + pool.Name)
|
||||
f, _ := floatingip.Create(client, floatingip.CreateOpts{Pool: pool.Name}).Extract()
|
||||
unusedFloatingIP = f.IP
|
||||
}
|
||||
|
||||
// step-16
|
||||
if len(publicIP) != 0 {
|
||||
fmt.Println("Instance " + testingInstance.Name + " already has a public ip. Skipping attachment.")
|
||||
} else {
|
||||
floatingip.Associate(client, testingInstance.ID, unusedFloatingIP)
|
||||
}
|
||||
|
||||
// step-17
|
||||
var actualIPAddress string
|
||||
if len(publicIP) != 0 {
|
||||
actualIPAddress = publicIP
|
||||
} else if len(unusedFloatingIP) != 0 {
|
||||
actualIPAddress = unusedFloatingIP
|
||||
} else {
|
||||
actualIPAddress = privateIP
|
||||
}
|
||||
|
||||
fmt.Println("The Fractals app will be deployed to http://" + actualIPAddress)
|
||||
}
|
@ -96,6 +96,11 @@ and toolkits with the OpenStack cloud:
|
||||
- A .NET-based library.
|
||||
Use it to write C++ or C# code for Microsoft applications.
|
||||
- https://www.nuget.org/packages/openstack.net
|
||||
* - Go
|
||||
- `gophercloud <https://github.com/rackspace/gophercloud>`_
|
||||
- A go-based SDK.
|
||||
Use it with multiple clouds.
|
||||
- http://gophercloud.io/
|
||||
|
||||
For a list of available SDKs, see `Software Development Kits <https://wiki.openstack.org/wiki/SDKs>`_.
|
||||
|
||||
@ -181,6 +186,11 @@ To interact with the cloud, you must also have
|
||||
|
||||
.. note:: Before proceeding, install the latest version of shade.
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
`a recent version of gophercloud installed <https://godoc.org/github.com/rackspace/gophercloud>`_
|
||||
|
||||
|
||||
Obtain the following information from your cloud provider:
|
||||
|
||||
* auth URL
|
||||
@ -307,6 +317,18 @@ to run code snippets in your language of choice.
|
||||
of the following API calls please double-check your
|
||||
credentials.
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
To try it, add the following code to go file
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-1
|
||||
:end-before: step-2
|
||||
|
||||
.. note:: The client object accesses the Compute v2.0 service,
|
||||
so that version is in this tutorial.
|
||||
|
||||
Flavors and images
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -425,6 +447,20 @@ To list the images that are available in your cloud, run some API calls:
|
||||
openstack.image.v1.image.Image(attrs={u'name': u'ubuntu-14.04', u'container_format': u'bare', u'disk_format': u'qcow2', u'checksum': u'6d8f1c8cf05e1fbdc8b543fda1a9fa7f', u'id': u'cb6b7936-d2c5-4901-8678-c88b3a6ed84c', u'size': 258540032}, loaded=True)
|
||||
...
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-2
|
||||
:end-before: step-3
|
||||
|
||||
This code returns output like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[{74e6d1ec-9a08-444c-8518-4f232446386d 2016-02-01T07:20:31Z 0 0 cirros-0.3.4-x86_64-uec 100 ACTIVE 2016-02-01T07:20:32Z}
|
||||
{f70b7fb0-348a-4519-b358-0f239dc64dc5 2016-02-01T07:20:30Z 0 0 cirros-0.3.4-x86_64-uec-ramdisk 100 ACTIVE 2016-02-01T07:20:31Z}
|
||||
{e92f5e17-60d2-4cb5-b893-d605b136afab 2016-02-01T07:20:29Z 0 0 cirros-0.3.4-x86_64-uec-kernel 100 ACTIVE 2016-02-01T07:20:30Z}]
|
||||
|
||||
You can also get information about available flavors:
|
||||
|
||||
@ -545,6 +581,22 @@ You can also get information about available flavors:
|
||||
|
||||
...
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-3
|
||||
:end-before: step-4
|
||||
|
||||
This code returns output like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[{1 1 512 m1.tiny 1 0 1}
|
||||
{2 20 2048 m1.small 1 0 1}
|
||||
{3 40 4096 m1.medium 1 0 2}
|
||||
...
|
||||
{84 0 128 m1.micro 1 0 1}]
|
||||
|
||||
Your images and flavors will be different, of course.
|
||||
|
||||
@ -656,6 +708,19 @@ image that you picked in the previous section:
|
||||
|
||||
openstack.image.v1.image.Image(attrs={u'name': u'ubuntu-14.04', u'container_format': u'bare', u'disk_format': u'qcow2', u'checksum': u'6d8f1c8cf05e1fbdc8b543fda1a9fa7f', u'id': u'cb6b7936-d2c5-4901-8678-c88b3a6ed84c', u'size': 258540032}, loaded=True)
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-4
|
||||
:end-before: step-5
|
||||
|
||||
You should see output like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
&{74e6d1ec-9a08-444c-8518-4f232446386d 2016-02-01T07:20:31Z 0 0 cirros-0.3.4-x86_64-uec 100 ACTIVE 2016-02-01T07:20:32Z}
|
||||
|
||||
Next, tell the script which flavor you want to use:
|
||||
|
||||
.. only:: fog
|
||||
@ -755,6 +820,19 @@ Next, tell the script which flavor you want to use:
|
||||
|
||||
openstack.compute.v2.flavor.Flavor(attrs={u'name': u'm1.small', u'links': [{u'href': u'http://controller:8774/v2/96ff6aa79e60423d9848b70d5475c415/flavors/2', u'rel': u'self'}, {u'href': u'http://controller:8774/96ff6aa79e60423d9848b70d5475c415/flavors/2', u'rel': u'bookmark'}], u'ram': 2048, u'OS-FLV-DISABLED:disabled': False, u'vcpus': 1, u'swap': u'', u'os-flavor-access:is_public': True, u'rxtx_factor': 1.0, u'OS-FLV-EXT-DATA:ephemeral': 0, u'disk': 20, 'id': u'2'}, loaded=True)
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-5
|
||||
:end-before: step-6
|
||||
|
||||
You should see output like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
&{1 1 512 m1.tiny 1 0 1}
|
||||
|
||||
Now, you can launch the instance.
|
||||
|
||||
Launch an instance
|
||||
@ -836,6 +914,19 @@ Create the instance.
|
||||
:start-after: step-6
|
||||
:end-before: step-7
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-6
|
||||
:end-before: step-7
|
||||
|
||||
You should see output like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
&{739dd964-ae88-461d-9746-f8f1139d20f6 0 map[] map[] map[] map[] ... RPUkTFM8fynn [map[name:default]]}
|
||||
|
||||
If you list existing instances:
|
||||
|
||||
.. only:: fog
|
||||
@ -878,6 +969,13 @@ If you list existing instances:
|
||||
:start-after: step-7
|
||||
:end-before: step-8
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-7
|
||||
:end-before: step-8
|
||||
|
||||
The new instance appears.
|
||||
|
||||
.. only:: libcloud
|
||||
@ -982,6 +1080,14 @@ The new instance appears.
|
||||
updated: '2015-07-20T20:31:10Z'
|
||||
user_id: bfd3dbf1c8a242cd90884408de547bb9
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[...
|
||||
{739dd964-ae88-461d-9746-f8f1139d20f6 061fdb617b6c4bdf8694bf5b0d8eefdd bb210009e42c4b509ba75893a757c8e5 testing 2016-02-16T07:16:52Z 2016-02-16T07:16:52Z 2d2f4bba90498fd46c72e7d019dde9189c36637b73e71e1e652d75db BUILD 0 ... [map[name:default]]}
|
||||
...]
|
||||
|
||||
Before you continue, you must do one more thing.
|
||||
|
||||
Destroy an instance
|
||||
@ -1029,6 +1135,13 @@ cost money. To avoid unexpected expenses, destroy cloud resources.
|
||||
:start-after: step-8
|
||||
:end-before: step-9
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-8
|
||||
:end-before: step-9
|
||||
|
||||
If you list the instances again, the instance disappears.
|
||||
|
||||
Leave your shell open to use it for another instance deployment in this
|
||||
@ -1101,6 +1214,13 @@ your public SSH key file.
|
||||
|
||||
openstack.compute.v2.keypair.Keypair(attrs={u'public_key': u'ssh-rsa ABAAABAQCyyzkyaPf.....', u'name': u'demokey', u'fingerprint': aa:bb:cc:... '}, loaded=True)
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-9
|
||||
:end-before: step-10
|
||||
|
||||
* Network access. By default, OpenStack filters all traffic. You must create
|
||||
a security group and apply it to your instance. The security group allows HTTP
|
||||
and SSH access. We will go into more detail in :doc:`/introduction`.
|
||||
@ -1136,6 +1256,13 @@ your public SSH key file.
|
||||
:start-after: step-10
|
||||
:end-before: step-11
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-10
|
||||
:end-before: step-11
|
||||
|
||||
* Userdata. During instance creation, you can provide userdata to OpenStack to
|
||||
configure instances after they boot. The cloud-init service applies the
|
||||
user data to an instance. You must pre-install the cloud-init service on your
|
||||
@ -1174,6 +1301,13 @@ your public SSH key file.
|
||||
:start-after: step-11
|
||||
:end-before: step-12
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-11
|
||||
:end-before: step-12
|
||||
|
||||
Now, you can boot and configure the instance.
|
||||
|
||||
Boot and configure an instance
|
||||
@ -1215,6 +1349,13 @@ After you request the instance, wait for it to build.
|
||||
:start-after: step-12
|
||||
:end-before: step-13
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-12
|
||||
:end-before: step-13
|
||||
|
||||
When the instance boots, the `ex_userdata` variable value instructs the
|
||||
instance to deploy the Fractals application.
|
||||
|
||||
@ -1339,6 +1480,45 @@ instance.
|
||||
:start-after: step-14
|
||||
:end-before: step-15
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
To see whether a private IP address is assigned to your instance:
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-13
|
||||
:end-before: step-14
|
||||
|
||||
|
||||
|
||||
If one is assigned, users can use this address to access the instance on
|
||||
some OpenStack clouds.
|
||||
|
||||
To determine whether a public IP address is assigned to your instance:
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-14
|
||||
:end-before: step-15
|
||||
|
||||
If one is assigned, users can use this address to access the instance.
|
||||
|
||||
To create a floating IP address to use with your instance:
|
||||
|
||||
Use network service client to select the first floating IP address pool.
|
||||
Allocate this pool to your project and use it to get a floating IP address.
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-15
|
||||
:end-before: step-16
|
||||
|
||||
Attach the floating IP address to the instance:
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-16
|
||||
:end-before: step-17
|
||||
|
||||
Run the script to start the deployment.
|
||||
|
||||
@ -1376,6 +1556,12 @@ interface at the following link.
|
||||
.. literalinclude:: ../samples/openstacksdk/getting_started.py
|
||||
:start-after: step-15
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
:start-after: step-17
|
||||
|
||||
.. note:: If you do not use floating IP addresses, substitute another IP
|
||||
address, as appropriate.
|
||||
|
||||
@ -1442,3 +1628,8 @@ information, the flavor ID, and image ID.
|
||||
|
||||
.. literalinclude:: ../samples/openstacksdk/getting_started.py
|
||||
:language: python
|
||||
|
||||
.. only:: gophercloud
|
||||
|
||||
.. literalinclude:: ../samples/gophercloud/getting_started.go
|
||||
:language: go
|
||||
|
@ -9,7 +9,7 @@ for tag in libcloud; do
|
||||
done
|
||||
|
||||
# Draft documents
|
||||
for tag in dotnet fog openstacksdk pkgcloud shade jclouds; do
|
||||
for tag in dotnet fog openstacksdk pkgcloud shade jclouds gophercloud; do
|
||||
tools/build-rst.sh firstapp \
|
||||
--tag ${tag} --target "api-ref/draft/firstapp-${tag}"
|
||||
done
|
||||
|
3
tox.ini
3
tox.ini
@ -161,6 +161,9 @@ commands = sphinx-build -E -W -t libcloud firstapp/source firstapp/build/html
|
||||
[testenv:firstapp-shade]
|
||||
commands = sphinx-build -E -W -t shade firstapp/source firstapp/build-shade/html
|
||||
|
||||
[testenv:firstapp-gophercloud]
|
||||
commands = sphinx-build -E -W -t gophercloud firstapp/source firstapp/build-gophercloud/html
|
||||
|
||||
[testenv:api-quick-start]
|
||||
commands =
|
||||
{toxinidir}/tools/build-api-quick-start.sh
|
||||
|
Loading…
Reference in New Issue
Block a user