Beispiel #1
0
func (s *StepAllocateIp) Run(state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	config := state.Get("config").(Config)
	server := state.Get("server").(*servers.Server)

	// We need the v2 compute client
	client, err := config.computeV2Client()
	if err != nil {
		err = fmt.Errorf("Error initializing compute client: %s", err)
		state.Put("error", err)
		return multistep.ActionHalt
	}

	var instanceIp floatingips.FloatingIP

	// This is here in case we error out before putting instanceIp into the
	// statebag below, because it is requested by Cleanup()
	state.Put("access_ip", &instanceIp)

	if s.FloatingIp != "" {
		instanceIp.IP = s.FloatingIp
	} else if s.FloatingIpPool != "" {
		ui.Say(fmt.Sprintf("Creating floating IP..."))
		ui.Message(fmt.Sprintf("Pool: %s", s.FloatingIpPool))
		newIp, err := floatingips.Create(client, floatingips.CreateOpts{
			Pool: s.FloatingIpPool,
		}).Extract()
		if err != nil {
			err := fmt.Errorf("Error creating floating ip from pool '%s'", s.FloatingIpPool)
			state.Put("error", err)
			ui.Error(err.Error())
			return multistep.ActionHalt
		}

		instanceIp = *newIp
		ui.Message(fmt.Sprintf("Created floating IP: %s", instanceIp.IP))
	}

	if instanceIp.IP != "" {
		ui.Say(fmt.Sprintf("Associating floating IP with server..."))
		ui.Message(fmt.Sprintf("IP: %s", instanceIp.IP))
		err := floatingips.AssociateInstance(client, server.ID, floatingips.AssociateOpts{
			FloatingIP: instanceIp.IP,
		}).ExtractErr()
		if err != nil {
			err := fmt.Errorf(
				"Error associating floating IP %s with instance: %s",
				instanceIp.IP, err)
			state.Put("error", err)
			ui.Error(err.Error())
			return multistep.ActionHalt
		}

		ui.Message(fmt.Sprintf(
			"Added floating IP %s to instance!", instanceIp.IP))
	}

	state.Put("access_ip", &instanceIp)
	return multistep.ActionContinue
}
func associateFloatingIPToInstance(computeClient *gophercloud.ServiceClient, floatingIP string, instanceID string, fixedIP string) error {
	associateOpts := floatingips.AssociateOpts{
		FloatingIP: floatingIP,
		FixedIP:    fixedIP,
	}

	if err := floatingips.AssociateInstance(computeClient, instanceID, associateOpts).ExtractErr(); err != nil {
		return fmt.Errorf("Error associating floating IP: %s", err)
	}

	return nil
}
func TestAssociate(t *testing.T) {
	th.SetupHTTP()
	defer th.TeardownHTTP()
	HandleAssociateSuccessfully(t)

	associateOpts := floatingips.AssociateOpts{
		FloatingIP: "10.10.10.2",
	}

	err := floatingips.AssociateInstance(client.ServiceClient(), "4d8c3732-a248-40ed-bebc-539a6ffd25c0", associateOpts).ExtractErr()
	th.AssertNoErr(t, err)
}
Beispiel #4
0
// AssociateFloatingIP will associate a floating IP with an instance. An error
// will be returned if the floating IP was unable to be associated.
func AssociateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP, server *servers.Server) error {
	associateOpts := floatingips.AssociateOpts{
		FloatingIP: floatingIP.IP,
	}

	t.Logf("Attempting to associate floating IP %s to instance %s", floatingIP.IP, server.ID)
	err := floatingips.AssociateInstance(client, server.ID, associateOpts).ExtractErr()
	if err != nil {
		return err
	}

	return nil
}
Beispiel #5
0
// spawn achieves the aims of Spawn()
func (p *openstackp) spawn(resources *Resources, osPrefix string, flavorID string, externalIP bool, postCreationScript []byte) (serverID string, serverIP string, adminPass string, err error) {
	// get available images, pick the one that matches desired OS
	// *** rackspace API lets you filter on eg. os_distro=ubuntu and os_version=12.04; can we do the same here?
	pager := images.ListDetail(p.computeClient, images.ListOpts{Status: "ACTIVE"})
	var imageID string
	err = pager.EachPage(func(page pagination.Page) (bool, error) {
		imageList, err := images.ExtractImages(page)
		if err != nil {
			return false, err
		}

		for _, i := range imageList {
			if i.Progress == 100 && strings.HasPrefix(i.Name, osPrefix) {
				imageID = i.ID
				return false, nil
			}
		}

		return true, nil
	})
	if err != nil {
		return
	}

	// create the server with a unique name
	server, err := servers.Create(p.computeClient, keypairs.CreateOptsExt{
		CreateOptsBuilder: servers.CreateOpts{
			Name:           uniqueResourceName(resources.ResourceName),
			FlavorRef:      flavorID,
			ImageRef:       imageID,
			SecurityGroups: []string{p.securityGroup},
			Networks:       []servers.Network{{UUID: p.networkUUID}},
			UserData:       postCreationScript,
			// Metadata map[string]string
		},
		KeyName: resources.ResourceName,
	}).Extract()
	if err != nil {
		return
	}

	// wait for it to come up; servers.WaitForStatus has a timeout, but it
	// doesn't always work, so we roll our own
	waitForActive := make(chan error)
	go func() {
		timeout := time.After(60 * time.Second)
		ticker := time.NewTicker(1 * time.Second)
		for {
			select {
			case <-ticker.C:
				current, err := servers.Get(p.computeClient, server.ID).Extract()
				if err != nil {
					ticker.Stop()
					waitForActive <- err
					return
				}
				if current.Status == "ACTIVE" {
					ticker.Stop()
					waitForActive <- nil
					return
				}
				if current.Status == "ERROR" {
					ticker.Stop()
					waitForActive <- errors.New("there was an error in bringing up the new server")
					return
				}
				continue
			case <-timeout:
				ticker.Stop()
				waitForActive <- errors.New("timed out waiting for server to become ACTIVE")
				return
			}
		}
	}()
	err = <-waitForActive
	if err != nil {
		// since we're going to return an error that we failed to spawn, try and
		// delete the bad server in case it is still there
		servers.Delete(p.computeClient, server.ID)
		return
	}
	// *** NB. it can still take some number of seconds before I can ssh to it

	serverID = server.ID
	adminPass = server.AdminPass

	// get the servers IP; if we error for any reason we'll delete the server
	// first, because without an IP it's useless

	if externalIP {
		// give it a floating ip
		var floatingIP string
		floatingIP, err = p.getAvailableFloatingIP()
		if err != nil {
			p.destroyServer(serverID)
			return
		}

		// associate floating ip with server *** we have a race condition
		// between finding/creating free floating IP above, and using it here
		err = floatingips.AssociateInstance(p.computeClient, serverID, floatingips.AssociateOpts{
			FloatingIP: floatingIP,
		}).ExtractErr()
		if err != nil {
			p.destroyServer(serverID)
			return
		}

		serverIP = floatingIP
	} else {
		// find its auto-assigned internal ip *** there must be a better way of
		// doing this...
		allNetworkAddressPages, serr := servers.ListAddressesByNetwork(p.computeClient, serverID, p.networkName).AllPages()
		if serr != nil {
			p.destroyServer(serverID)
			err = serr
			return
		}
		allNetworkAddresses, serr := servers.ExtractNetworkAddresses(allNetworkAddressPages)
		if serr != nil {
			p.destroyServer(serverID)
			err = serr
			return
		}
		for _, address := range allNetworkAddresses {
			if address.Version == 4 && strings.HasPrefix(address.Address, "192.168") {
				serverIP = address.Address
				break
			}
		}
	}

	return
}