diff --git a/builder/osc/bsu/builder.go b/builder/osc/bsu/builder.go index dc7ce678c..2184b5b30 100644 --- a/builder/osc/bsu/builder.go +++ b/builder/osc/bsu/builder.go @@ -131,6 +131,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Comm: &b.config.RunConfig.Comm, DebugKeyPath: fmt.Sprintf("oapi_%s", b.config.PackerBuildName), }, + &osccommon.StepPublicIp{ + AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, + Debug: b.config.PackerDebug, + }, &osccommon.StepSecurityGroup{ SecurityGroupFilter: b.config.SecurityGroupFilter, SecurityGroupIds: b.config.SecurityGroupIds, @@ -141,7 +145,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack BlockDevices: b.config.BlockDevices, }, &osccommon.StepRunSourceVm{ - AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, BlockDevices: b.config.BlockDevices, Comm: &b.config.RunConfig.Comm, Ctx: b.config.ctx, diff --git a/builder/osc/bsusurrogate/builder.go b/builder/osc/bsusurrogate/builder.go index 3669c3952..e532b11e6 100644 --- a/builder/osc/bsusurrogate/builder.go +++ b/builder/osc/bsusurrogate/builder.go @@ -154,6 +154,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Comm: &b.config.RunConfig.Comm, DebugKeyPath: fmt.Sprintf("oapi_%s", b.config.PackerBuildName), }, + &osccommon.StepPublicIp{ + AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, + Debug: b.config.PackerDebug, + }, &osccommon.StepSecurityGroup{ SecurityGroupFilter: b.config.SecurityGroupFilter, SecurityGroupIds: b.config.SecurityGroupIds, @@ -164,7 +168,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack BlockDevices: b.config.BlockDevices, }, &osccommon.StepRunSourceVm{ - AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, BlockDevices: b.config.BlockDevices, Comm: &b.config.RunConfig.Comm, Ctx: b.config.ctx, diff --git a/builder/osc/bsuvolume/builder.go b/builder/osc/bsuvolume/builder.go index 44873cfd2..ffb5f13f1 100644 --- a/builder/osc/bsuvolume/builder.go +++ b/builder/osc/bsuvolume/builder.go @@ -111,7 +111,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack log.Printf("[DEBUG] launch block devices %#v", b.config.launchBlockDevices) instanceStep := &osccommon.StepRunSourceVm{ - AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, BlockDevices: b.config.launchBlockDevices, Comm: &b.config.RunConfig.Comm, Ctx: b.config.ctx, @@ -148,6 +147,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Comm: &b.config.RunConfig.Comm, DebugKeyPath: fmt.Sprintf("oapi_%s.pem", b.config.PackerBuildName), }, + &osccommon.StepPublicIp{ + AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, + Debug: b.config.PackerDebug, + }, &osccommon.StepSecurityGroup{ SecurityGroupFilter: b.config.SecurityGroupFilter, SecurityGroupIds: b.config.SecurityGroupIds, diff --git a/builder/osc/common/ssh.go b/builder/osc/common/ssh.go index f00c7710e..829165d0c 100644 --- a/builder/osc/common/ssh.go +++ b/builder/osc/common/ssh.go @@ -3,7 +3,6 @@ package common import ( "errors" "fmt" - "sort" "time" "github.com/hashicorp/packer/helper/multistep" @@ -29,41 +28,35 @@ func SSHHost(e oapiDescriber, sshInterface string) func(multistep.StateBag) (str var host string i := state.Get("vm").(oapi.Vm) - if len(i.Nics) <= 0 { - return "", errors.New("couldn't determine address for vm, nics are empty") - } - - nic := i.Nics[0] - if sshInterface != "" { switch sshInterface { case "public_ip": - if nic.LinkPublicIp.PublicIp != "" { - host = nic.LinkPublicIp.PublicIp + if i.PublicIp != "" { + host = i.PublicIp } case "public_dns": - if nic.LinkPublicIp.PublicDnsName != "" { - host = nic.LinkPublicIp.PublicDnsName + if i.PublicDnsName != "" { + host = i.PublicDnsName } case "private_ip": - if privateIP, err := getPrivateIP(nic); err != nil { - host = privateIP.PrivateIp + if i.PrivateIp != "" { + host = i.PrivateIp } case "private_dns": - if privateIP, err := getPrivateIP(nic); err != nil { - host = privateIP.PrivateDnsName + if i.PrivateDnsName != "" { + host = i.PrivateDnsName } default: panic(fmt.Sprintf("Unknown interface type: %s", sshInterface)) } } else if i.NetId != "" { - if nic.LinkPublicIp.PublicIp != "" { - host = nic.LinkPublicIp.PublicIp - } else if privateIP, err := getPrivateIP(nic); err != nil { - host = privateIP.PrivateIp + if i.PublicIp != "" { + host = i.PublicIp + } else if i.PrivateIp != "" { + host = i.PrivateIp } - } else if nic.LinkPublicIp.PublicDnsName != "" { - host = nic.LinkPublicIp.PublicDnsName + } else if i.PublicDnsName != "" { + host = i.PublicDnsName } if host != "" { @@ -90,20 +83,3 @@ func SSHHost(e oapiDescriber, sshInterface string) func(multistep.StateBag) (str return "", errors.New("couldn't determine address for vm") } } - -func getPrivateIP(nic oapi.NicLight) (oapi.PrivateIpLightForVm, error) { - isPrimary := true - - i := sort.Search(len(nic.PrivateIps), func(i int) bool { return nic.PrivateIps[i].IsPrimary == isPrimary }) - - if i < len(nic.PrivateIps) && nic.PrivateIps[i].IsPrimary == isPrimary { - return nic.PrivateIps[i], nil - } - - if len(nic.PrivateIps) > 0 { - return nic.PrivateIps[0], nil - } - - return oapi.PrivateIpLightForVm{}, fmt.Errorf("couldn't determine private address for vm") - -} diff --git a/builder/osc/common/state.go b/builder/osc/common/state.go index 2cc475123..b1d5bebaa 100644 --- a/builder/osc/common/state.go +++ b/builder/osc/common/state.go @@ -88,7 +88,7 @@ func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) e func waitUntilVmStateFunc(conn *oapi.Client, id string) stateRefreshFunc { return func() (string, error) { - log.Printf("[Debug] Check if SG with id %s exists", id) + log.Printf("[Debug] Retrieving state for VM with id %s", id) resp, err := conn.POST_ReadVms(oapi.ReadVmsRequest{ Filters: oapi.FiltersVm{ VmIds: []string{id}, @@ -102,7 +102,7 @@ func waitUntilVmStateFunc(conn *oapi.Client, id string) stateRefreshFunc { } if resp.OK == nil { - return "", fmt.Errorf("Vm with ID %s. Not Found", id) + return "", fmt.Errorf("Vm with ID %s not Found", id) } if len(resp.OK.Vms) == 0 { diff --git a/builder/osc/common/step_public_ip.go b/builder/osc/common/step_public_ip.go new file mode 100644 index 000000000..9f26efb12 --- /dev/null +++ b/builder/osc/common/step_public_ip.go @@ -0,0 +1,68 @@ +package common + +import ( + "context" + "fmt" + + "github.com/hashicorp/packer/helper/communicator" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" + "github.com/outscale/osc-go/oapi" +) + +type StepPublicIp struct { + AssociatePublicIpAddress bool + Comm *communicator.Config + publicIpId string + Debug bool + + doCleanup bool +} + +func (s *StepPublicIp) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packer.Ui) + oapiconn := state.Get("oapi").(*oapi.Client) + netId := state.Get("net_id").(string) + subnetId := state.Get("subnet_id").(string) + + if netId == "" || subnetId == "" || !s.AssociatePublicIpAddress { + // In this case, we are in the public Cloud, so we'll + // not explicitely allocate a public IP. + return multistep.ActionContinue + } + + ui.Say(fmt.Sprintf("Creating temporary PublicIp for instance in subnet %s (net %s)", subnetId, netId)) + + publicIpResp, err := oapiconn.POST_CreatePublicIp(oapi.CreatePublicIpRequest{}) + if err != nil { + state.Put("error", fmt.Errorf("Error creating temporary PublicIp: %s", err)) + return multistep.ActionHalt + } + + // From there, we have a Public Ip to destroy. + s.doCleanup = true + + // Set some data for use in future steps + s.publicIpId = publicIpResp.OK.PublicIp.PublicIpId + state.Put("publicip_id", publicIpResp.OK.PublicIp.PublicIpId) + + return multistep.ActionContinue +} + +func (s *StepPublicIp) Cleanup(state multistep.StateBag) { + if !s.doCleanup { + return + } + + oapiconn := state.Get("oapi").(*oapi.Client) + ui := state.Get("ui").(packer.Ui) + + // Remove the Public IP + ui.Say("Deleting temporary PublicIp...") + _, err := oapiconn.POST_DeletePublicIp(oapi.DeletePublicIpRequest{PublicIpId: s.publicIpId}) + if err != nil { + ui.Error(fmt.Sprintf( + "Error cleaning up PublicIp. Please delete the PublicIp manually: %s", s.publicIpId)) + } + +} diff --git a/builder/osc/common/step_run_source_vm.go b/builder/osc/common/step_run_source_vm.go index a0f92a6a5..abcda0316 100644 --- a/builder/osc/common/step_run_source_vm.go +++ b/builder/osc/common/step_run_source_vm.go @@ -23,7 +23,6 @@ const ( ) type StepRunSourceVm struct { - AssociatePublicIpAddress bool BlockDevices BlockDevices Comm *communicator.Config Ctx interpolate.Context @@ -158,20 +157,8 @@ func (s *StepRunSourceVm) Run(ctx context.Context, state multistep.StateBag) mul subnetId := state.Get("subnet_id").(string) - if subnetId != "" && s.AssociatePublicIpAddress { - runOpts.Nics = []oapi.NicForVmCreation{ - { - DeviceNumber: 0, - //AssociatePublicIpAddress: s.AssociatePublicIpAddress, - SubnetId: subnetId, - SecurityGroupIds: securityGroupIds, - DeleteOnVmDeletion: true, - }, - } - } else { - runOpts.SubnetId = subnetId - runOpts.SecurityGroupIds = securityGroupIds - } + runOpts.SubnetId = subnetId + runOpts.SecurityGroupIds = securityGroupIds if s.ExpectedRootDevice == "bsu" { runOpts.VmInitiatedShutdownBehavior = s.VmInitiatedShutdownBehavior @@ -224,7 +211,15 @@ func (s *StepRunSourceVm) Run(ctx context.Context, state multistep.StateBag) mul } } - //TODO: LinkPublicIp i + if publicip_id, ok := state.Get("publicip_id").(string); ok { + ui.Say(fmt.Sprintf("Linking temporary PublicIp %s to instance %s", publicip_id, vmId)) + _, err := oapiconn.POST_LinkPublicIp(oapi.LinkPublicIpRequest{PublicIpId: publicip_id, VmId: vmId}) + if err != nil { + state.Put("error", fmt.Errorf("Error linking PublicIp to VM: %s", err)) + ui.Error(err.Error()) + return multistep.ActionHalt + } + } resp, err := oapiconn.POST_ReadVms(request)