Add --openstack-key-pair and --openstack-private-file-name so to
import and reuse existing nova keypairs. Signed-off-by: Fabrizio Soppelsa <fsoppelsa@mirantis.com>
This commit is contained in:
parent
2f482ac085
commit
7400e6f965
|
@ -28,10 +28,12 @@ Options:
|
|||
- `--openstack-floatingip-pool`: The IP pool that will be used to get a public IP can assign it to the machine. If there is an
|
||||
IP address already allocated but not assigned to any machine, this IP will be chosen and assigned to the machine. If
|
||||
there is no IP address already allocated a new IP will be allocated and assigned to the machine.
|
||||
- `--openstack-keypair-name`: Specify the existing Nova keypair to use.
|
||||
- `--openstack-insecure`: Explicitly allow openstack driver to perform "insecure" SSL (https) requests. The server's certificate will not be verified against any certificate authorities. This option should be used with caution.
|
||||
- `--openstack-ip-version`: If the instance has both IPv4 and IPv6 address, you can select IP version. If not provided `4` will be used.
|
||||
- `--openstack-net-name` or `--openstack-net-id`: Identify the private network the machine will be connected on. If your OpenStack project project contains only one private network it will be use automatically.
|
||||
- `--openstack-password`: User password. It can be omitted if the standard environment variable `OS_PASSWORD` is set.
|
||||
- `--openstack-private-key-file`: Used with `--openstack-keypair-name`, associates the private key to the keypair.
|
||||
- `--openstack-region`: The region to work on. Can be omitted if there is only one region on the OpenStack.
|
||||
- `--openstack-sec-groups`: If security groups are available on your OpenStack you can specify a comma separated list
|
||||
to use for the machine (e.g. `secgrp001,secgrp002`).
|
||||
|
@ -57,9 +59,11 @@ Environment variables and default values:
|
|||
| `--openstack-image-name` | `OS_IMAGE_NAME` | - |
|
||||
| `--openstack-insecure` | `OS_INSECURE` | `false` |
|
||||
| `--openstack-ip-version` | `OS_IP_VERSION` | `4` |
|
||||
| `--openstack-keypair-name` | `OS_KEYPAIR_NAME` | - |
|
||||
| `--openstack-net-id` | `OS_NETWORK_ID` | - |
|
||||
| `--openstack-net-name` | `OS_NETWORK_NAME` | - |
|
||||
| `--openstack-password` | `OS_PASSWORD` | - |
|
||||
| `--openstack-private-key-file` | `OS_PRIVATE_KEY_FILE` | - |
|
||||
| `--openstack-region` | `OS_REGION_NAME` | - |
|
||||
| `--openstack-sec-groups` | `OS_SECURITY_GROUPS` | - |
|
||||
| `--openstack-ssh-port` | `OS_SSH_PORT` | `22` |
|
||||
|
|
|
@ -38,6 +38,7 @@ type Client interface {
|
|||
DeleteInstance(d *Driver) error
|
||||
WaitForInstanceStatus(d *Driver, status string) error
|
||||
GetInstanceIPAddresses(d *Driver) ([]IPAddress, error)
|
||||
GetPublicKey(keyPairName string) ([]byte, error)
|
||||
CreateKeyPair(d *Driver, name string, publicKey string) error
|
||||
DeleteKeyPair(d *Driver, name string) error
|
||||
GetNetworkID(d *Driver) (string, error)
|
||||
|
@ -300,6 +301,14 @@ func (c *GenericClient) GetTenantID(d *Driver) (string, error) {
|
|||
return tenantId, err
|
||||
}
|
||||
|
||||
func (c *GenericClient) GetPublicKey(keyPairName string) ([]byte, error) {
|
||||
kp, err := keypairs.Get(c.Compute, keyPairName).Extract()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(kp.PublicKey), nil
|
||||
}
|
||||
|
||||
func (c *GenericClient) CreateKeyPair(d *Driver, name string, publicKey string) error {
|
||||
opts := keypairs.CreateOpts{
|
||||
Name: name,
|
||||
|
|
|
@ -37,6 +37,7 @@ type Driver struct {
|
|||
KeyPairName string
|
||||
NetworkName string
|
||||
NetworkId string
|
||||
PrivateKeyFile string
|
||||
SecurityGroups []string
|
||||
FloatingIpPool string
|
||||
ComputeNetwork bool
|
||||
|
@ -142,12 +143,24 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
|
|||
Usage: "OpenStack image name to use for the instance",
|
||||
Value: "",
|
||||
},
|
||||
mcnflag.StringFlag{
|
||||
EnvVar: "OS_KEYPAIR_NAME",
|
||||
Name: "openstack-keypair-name",
|
||||
Usage: "OpenStack keypair to use to SSH to the instance",
|
||||
Value: "",
|
||||
},
|
||||
mcnflag.StringFlag{
|
||||
EnvVar: "OS_NETWORK_ID",
|
||||
Name: "openstack-net-id",
|
||||
Usage: "OpenStack network id the machine will be connected on",
|
||||
Value: "",
|
||||
},
|
||||
mcnflag.StringFlag{
|
||||
EnvVar: "OS_PRIVATE_KEY_FILE",
|
||||
Name: "openstack-private-key-file",
|
||||
Usage: "Private keyfile to use for SSH (absolute path)",
|
||||
Value: "",
|
||||
},
|
||||
mcnflag.StringFlag{
|
||||
EnvVar: "OS_NETWORK_NAME",
|
||||
Name: "openstack-net-name",
|
||||
|
@ -255,6 +268,8 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
|||
d.ComputeNetwork = flags.Bool("openstack-nova-network")
|
||||
d.SSHUser = flags.String("openstack-ssh-user")
|
||||
d.SSHPort = flags.Int("openstack-ssh-port")
|
||||
d.KeyPairName = flags.String("openstack-keypair-name")
|
||||
d.PrivateKeyFile = flags.String("openstack-private-key-file")
|
||||
d.SwarmMaster = flags.Bool("swarm-master")
|
||||
d.SwarmHost = flags.String("swarm-host")
|
||||
d.SwarmDiscovery = flags.String("swarm-discovery")
|
||||
|
@ -339,13 +354,18 @@ func (d *Driver) GetState() (state.State, error) {
|
|||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
d.KeyPairName = fmt.Sprintf("%s-%s", d.MachineName, mcnutils.GenerateRandomID())
|
||||
|
||||
if err := d.resolveIds(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.createSSHKey(); err != nil {
|
||||
return err
|
||||
if d.KeyPairName != "" {
|
||||
if err := d.loadSSHKey(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
d.KeyPairName = fmt.Sprintf("%s-%s", d.MachineName, mcnutils.GenerateRandomID())
|
||||
if err := d.createSSHKey(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.createMachine(); err != nil {
|
||||
return err
|
||||
|
@ -397,6 +417,7 @@ func (d *Driver) Remove() error {
|
|||
return err
|
||||
}
|
||||
log.Debug("deleting key pair...", map[string]string{"Name": d.KeyPairName})
|
||||
// TODO (fsoppelsa) maybe we want to check this, in case of shared keypairs, before removal
|
||||
if err := d.client.DeleteKeyPair(d, d.KeyPairName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -422,6 +443,7 @@ const (
|
|||
errorMandatoryEnvOrOption string = "%s must be specified either using the environment variable %s or the CLI option %s"
|
||||
errorMandatoryOption string = "%s must be specified using the CLI option %s"
|
||||
errorExclusiveOptions string = "Either %s or %s must be specified, not both"
|
||||
errorBothOptions string = "Both %s and %s must be specified"
|
||||
errorMandatoryTenantNameOrID string = "Tenant id or name must be provided either using one of the environment variables OS_TENANT_ID and OS_TENANT_NAME or one of the CLI options --openstack-tenant-id and --openstack-tenant-name"
|
||||
errorWrongEndpointType string = "Endpoint type must be 'publicURL', 'adminURL' or 'internalURL'"
|
||||
errorUnknownFlavorName string = "Unable to find flavor named %s"
|
||||
|
@ -464,6 +486,9 @@ func (d *Driver) checkConfig() error {
|
|||
if d.EndpointType != "" && (d.EndpointType != "publicURL" && d.EndpointType != "adminURL" && d.EndpointType != "internalURL") {
|
||||
return fmt.Errorf(errorWrongEndpointType)
|
||||
}
|
||||
if (d.KeyPairName != "" && d.PrivateKeyFile == "") || (d.KeyPairName == "" && d.PrivateKeyFile != "") {
|
||||
return fmt.Errorf(errorBothOptions, "KeyPairName", "PrivateKeyFile")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -607,6 +632,30 @@ func (d *Driver) initNetwork() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) loadSSHKey() error {
|
||||
log.Debug("Loading Key Pair", d.KeyPairName)
|
||||
if err := d.initCompute(); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debug("Loading Private Key from", d.PrivateKeyFile)
|
||||
privateKey, err := ioutil.ReadFile(d.PrivateKeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
publicKey, err := d.client.GetPublicKey(d.KeyPairName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(d.privateSSHKeyPath(), privateKey, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(d.publicSSHKeyPath(), publicKey, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) createSSHKey() error {
|
||||
sanitizeKeyPairName(&d.KeyPairName)
|
||||
log.Debug("Creating Key Pair...", map[string]string{"Name": d.KeyPairName})
|
||||
|
@ -715,6 +764,10 @@ func (d *Driver) lookForIPAddress() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) privateSSHKeyPath() string {
|
||||
return d.GetSSHKeyPath()
|
||||
}
|
||||
|
||||
func (d *Driver) publicSSHKeyPath() string {
|
||||
return d.GetSSHKeyPath() + ".pub"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue