Update OpenStack run and push support

This commit updates the support for pushing images into OpenStack by
inheriting environment variables for endpoint and authentication
information, when available.

It also attempts to make the `openstack run` support more consistent
with other providers (specifically GCP and AWS), i.e just take the name
of the image as the argument and launch an instance using that.

Finally, it also updates the relevant documentation for OpenStack
support.

Signed-off-by: Nick Jones <nick@dischord.org>
This commit is contained in:
Nick Jones 2017-08-02 22:26:28 +01:00
parent 550bf41d0b
commit f65a4e803d
No known key found for this signature in database
GPG Key ID: F6D24C8669938334
3 changed files with 102 additions and 46 deletions

View File

@ -1,13 +1,25 @@
# LinuxKit with OpenStack
LinuxKit interacts with OpenStack through its native APIs and requires access
to both an OpenStack Keystone server for authentication and an OpenStack image
service (Glance) in order to host the LinuxKit images.
LinuxKit interacts with OpenStack through its native APIs and requires access and provides basic support for pushing images and launching virtual instances.
Supported (tested) versions of the relevant OpenStack APIs:
Supported (tested) versions of the relevant OpenStack APIs are:
- Keystone v3
- Glance v2
- Nova v2
- Neutron v2
## Authentication
LinuxKit's support for OpenStack handles two ways of providing the endpoint and authentication details. You can either set the standard set of environment variables and the commands detailed below will inherit those, or you can explicitly provide them on the command-line as options to `push` and `run`. The examples below use the latter, but if you prefer the former then you'll need to set the following:
```shell
OS_USERNAME="admin"
OS_PASSWORD="xxx"
OS_TENANT_NAME="linuxkit"
OS_AUTH_URL="https://keystone.com:5000/v3"
OS_USER_DOMAIN_NAME=default
```
## Push
@ -20,27 +32,52 @@ Supported (tested) versions of the relevant OpenStack APIs:
- **qcow2** (Qemu disk image)
- **iso** (ISO9660 compatible CD-ROM image)
A compatible image needs to have the correct extension (must match
one from above) in order to be supported by the `linuxkit push openstack`
command. The `openstack` backend will use the filename extension to determine
the image type, and use the filename as a label for the new image.
A compatible image needs to have the correct extension (must match one from above) in order to be supported by the `linuxkit push openstack` command. The `openstack` backend will use the filename extension to determine the image type, and use the filename as a label for the new image.
### Usage
Images generated with Moby can be uploaded into OpenStack's image service with `linuxkit push openstack`, plus a few options. For example:
The `openstack` backend uses the password authentication method in order to
retrieve a token that can be used to interact with the various components of
OpenStack. Example usage:
```
```shell
./linuxkit push openstack \
-authurl=http://keystone.com:5000/v3 \
-username=admin \
-password=XXXXXXXXXXX \
-project=linuxkit \
./linuxkit.iso
-authurl=https://keystone.example.com:5000/v3 \
-username=admin \
-password=XXXXXXXXXXX \
-project=linuxkit \
-img-name=LinuxKitTest
./linuxkit.iso
```
### Execution Flow
1. Authenticate with OpenStack's identity service
2. Create a "queued" image in Glance and retrieve its UUID
3. Use this new image ID to upload the LinuxKit image
If successful, this will return the image's UUID. If you've set your environment variables up as described above, this command can then be simplified:
```shell
./linuxkit push openstack \
-img-name "LinuxKitTest" \
~/Desktop/linuxkitmage.qcow2
```
## Run
Virtual machines can be launched using `linuxkit run openstack`. As an example:
```shell
linuxkit run openstack \
-authurl https://keystone.example.com:5000/v3 \
-username=admin \
-password=xxx \
-project=linuxkit \
-network c5d02c5f-c625-4539-8aed-1dab3aa85a0a \
LinuxKitTest
```
This will create a new instance with the same name as the image, and if successful will return the newly-created instance's UUID. You can then check the boot logs as follows, e.g:
```shell
$ openstack console log show 7cdd4d53-78b3-47c7-9a77-ba8a3f60548d
[..]
linuxkit-fa163ec840c9 login: root (automatic login)
Welcome to LinuxKit!
NOTE: This system is namespaced.
The namespace you are currently in may not be the root.
[..]
```

View File

@ -25,13 +25,12 @@ func pushOpenstack(args []string) {
fmt.Printf("Options:\n\n")
flags.PrintDefaults()
}
authurl := flags.String("authurl", "", "The URL of the OpenStack identity service, i.e https://keystone.example.com:5000/v3")
usernameFlag := flags.String("username", "", "Username with permissions to upload image")
passwordFlag := flags.String("password", "", "Password for the Username")
projectName := flags.String("project", "", "Name of the Project (aka Tenant) to be used")
userDomainFlag := flags.String("domain", "Default", "Domain name")
authurlFlag := flags.String("authurl", "", "The URL of the OpenStack identity service, i.e https://keystone.example.com:5000/v3")
imageName := flags.String("img-name", "", "A unique name for the image, if blank the filename will be used")
passwordFlag := flags.String("password", "", "Password for the specified username")
projectNameFlag := flags.String("project", "", "Name of the Project (aka Tenant) to be used")
userDomainFlag := flags.String("domain", "Default", "Domain name")
usernameFlag := flags.String("username", "", "Username with permissions to upload image")
if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args")
@ -47,12 +46,18 @@ func pushOpenstack(args []string) {
// Check that the file both exists, and can be read
checkFile(filePath)
authurl := getStringValue(authurlVar, *authurlFlag, "")
password := getStringValue(passwordVar, *passwordFlag, "")
projectName := getStringValue(projectNameVar, *projectNameFlag, "")
userDomain := getStringValue(userDomainVar, *userDomainFlag, "")
username := getStringValue(usernameVar, *usernameFlag, "")
authOpts := gophercloud.AuthOptions{
IdentityEndpoint: *authurl,
Username: *usernameFlag,
Password: *passwordFlag,
DomainName: *userDomainFlag,
TenantName: *projectName,
DomainName: userDomain,
IdentityEndpoint: authurl,
Password: password,
TenantName: projectName,
Username: username,
}
provider, err := openstack.AuthenticatedClient(authOpts)
if err != nil {

View File

@ -25,35 +25,49 @@ func runOpenStack(args []string) {
flags := flag.NewFlagSet("openstack", flag.ExitOnError)
invoked := filepath.Base(os.Args[0])
flags.Usage = func() {
fmt.Printf("USAGE: %s run openstack [options]\n\n", invoked)
fmt.Printf("USAGE: %s run openstack [options] [name]\n\n", invoked)
fmt.Printf("'name' is the name of an OpenStack image that has already been\n")
fmt.Printf(" uploaded using 'linuxkit push'\n\n")
fmt.Printf("Options:\n\n")
flags.PrintDefaults()
}
authurlFlag := flags.String("authurl", "", "The URL of the OpenStack identity service, i.e https://keystone.example.com:5000/v3")
usernameFlag := flags.String("username", "", "Username with permissions to create an instance")
flavorName := flags.String("flavor", defaultOSFlavor, "Instance size (flavor)")
instanceName := flags.String("instancename", "", "Name of instance. Defaults to the name of the image if not specified")
networkID := flags.String("network", "", "The ID of the network to attach the instance to")
passwordFlag := flags.String("password", "", "Password for the specified username")
projectNameFlag := flags.String("project", "", "Name of the Project (aka Tenant) to be used")
userDomainFlag := flags.String("domain", "Default", "Domain name")
imageID := flags.String("img-ID", "", "The ID of the image to boot the instance from")
networkID := flags.String("network", "", "The ID of the network to attach the instance to")
flavorName := flags.String("flavor", defaultOSFlavor, "Instance size (flavor)")
name := flags.String("name", "", "Name of the instance")
usernameFlag := flags.String("username", "", "Username with permissions to create an instance")
if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args")
}
remArgs := flags.Args()
if len(remArgs) == 0 {
fmt.Printf("Please specify the name of the image to boot\n")
flags.Usage()
os.Exit(1)
}
name := remArgs[0]
if *instanceName == "" {
*instanceName = name
}
authurl := getStringValue(authurlVar, *authurlFlag, "")
username := getStringValue(usernameVar, *usernameFlag, "")
password := getStringValue(passwordVar, *passwordFlag, "")
projectName := getStringValue(projectNameVar, *projectNameFlag, "")
userDomain := getStringValue(userDomainVar, *userDomainFlag, "")
username := getStringValue(usernameVar, *usernameFlag, "")
authOpts := gophercloud.AuthOptions{
IdentityEndpoint: authurl,
Username: username,
Password: password,
DomainName: userDomain,
IdentityEndpoint: authurl,
Password: password,
TenantName: projectName,
Username: username,
}
provider, err := openstack.AuthenticatedClient(authOpts)
if err != nil {
@ -71,8 +85,8 @@ func runOpenStack(args []string) {
serverOpts := &servers.CreateOpts{
FlavorName: *flavorName,
ImageRef: *imageID,
Name: *name,
ImageName: name,
Name: *instanceName,
Networks: []servers.Network{network},
ServiceClient: client,
}