github.phpd.cn/hashicorp/packer@v1.3.2/builder/openstack/step_get_password.go (about) 1 package openstack 2 3 import ( 4 "context" 5 "crypto/rsa" 6 "fmt" 7 "log" 8 "time" 9 10 "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" 11 "github.com/hashicorp/packer/helper/communicator" 12 "github.com/hashicorp/packer/helper/multistep" 13 "github.com/hashicorp/packer/packer" 14 "golang.org/x/crypto/ssh" 15 ) 16 17 // StepGetPassword reads the password from a booted OpenStack server and sets 18 // it on the WinRM config. 19 type StepGetPassword struct { 20 Debug bool 21 Comm *communicator.Config 22 } 23 24 func (s *StepGetPassword) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 25 config := state.Get("config").(*Config) 26 ui := state.Get("ui").(packer.Ui) 27 28 // Skip if we're not using winrm 29 if s.Comm.Type != "winrm" { 30 log.Printf("[INFO] Not using winrm communicator, skipping get password...") 31 return multistep.ActionContinue 32 } 33 34 // If we already have a password, skip it 35 if s.Comm.WinRMPassword != "" { 36 ui.Say("Skipping waiting for password since WinRM password set...") 37 return multistep.ActionContinue 38 } 39 40 // We need the v2 compute client 41 computeClient, err := config.computeV2Client() 42 if err != nil { 43 err = fmt.Errorf("Error initializing compute client: %s", err) 44 state.Put("error", err) 45 return multistep.ActionHalt 46 } 47 48 ui.Say("Waiting for password since WinRM password is not set...") 49 server := state.Get("server").(*servers.Server) 50 var password string 51 52 privateKey, err := ssh.ParseRawPrivateKey(s.Comm.SSHPrivateKey) 53 if err != nil { 54 err = fmt.Errorf("Error parsing private key: %s", err) 55 state.Put("error", err) 56 return multistep.ActionHalt 57 } 58 59 for ; password == "" && err == nil; password, err = servers.GetPassword(computeClient, server.ID).ExtractPassword(privateKey.(*rsa.PrivateKey)) { 60 61 // Check for an interrupt in between attempts. 62 if _, ok := state.GetOk(multistep.StateCancelled); ok { 63 return multistep.ActionHalt 64 } 65 66 log.Printf("Retrying to get a administrator password evry 5 seconds.") 67 time.Sleep(5 * time.Second) 68 } 69 70 ui.Message(fmt.Sprintf("Password retrieved!")) 71 s.Comm.WinRMPassword = password 72 73 // In debug-mode, we output the password 74 if s.Debug { 75 ui.Message(fmt.Sprintf( 76 "Password (since debug is enabled) \"%s\"", s.Comm.WinRMPassword)) 77 } 78 79 return multistep.ActionContinue 80 } 81 82 func (s *StepGetPassword) Cleanup(multistep.StateBag) {}