// 2020 Rackspace, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package migrate import ( "fmt" "log" "os" "strings" "github.rackspace.com/DCM/tools" "github.rackspace.com/gorax/clients/migrationAPI" "github.com/jedib0t/go-pretty/table" "github.com/sirupsen/logrus" "github.com/jokelyo/argparse" "github.rackspace.com/DCM/gomigrate/core" "github.rackspace.com/DCM/gomigrate/shared" "github.rackspace.com/gorax/gokeys" ) type ( deallocateResult struct { ID int MoveGroup string Result *migrationAPI.DeallocateIPsResponse } ) func fromDeallocateIPsPlugin(p *argparse.Command) core.Plugin { cmd := p.NewCommand("ips", "deallocate all source DRACNet, ServiceNet, and VMNet IPs") argDeallocateDevices = shared.ArgDevices(cmd) argDeallocateMG = shared.ArgMoveGroup(cmd) argDeallocateYes = cmd.Flag("y", "yes", &argparse.Options{Help: "auto-confirm changes"}) return core.Plugin{CMD: cmd, Func: deallocateIPs} } // deallocateIPs will prompt for a list of device, then run deallocate_ips func deallocateIPs(cfg gokeys.Settings) { // Pull an Identity token from the users gokeys keychain iKey, err := cfg.Identity(false) if err != nil { log.Fatal(err) } // Pull a core token from the users gokeys keychain coreKey, err := cfg.Core(false) if err != nil { log.Fatal(err) } mgList := make(map[string][]tools.Device) if *argDeallocateMG != "" { devices, err := shared.MongoDevices([]string{*argDeallocateMG}, nil, nil, "", coreKey.Password, make(map[string]interface{})) if err != nil { log.Fatalf("error retrieving devices for move group: %s", err) } logrus.Infof("%s: found %d devices", *argDeallocateMG, len(devices)) mgList[*argDeallocateMG] = devices } else { devices, err := shared.MongoDevices(nil, nil, *argDeallocateDevices, "", coreKey.Password, make(map[string]interface{})) if err != nil { log.Fatalf("error retrieving devices: %s", err) } logrus.Infof("found %d devices", len(devices)) for _, d := range devices { if _, ok := mgList[d.MoveGroup]; !ok { mgList[d.MoveGroup] = make([]tools.Device, 0) } mgList[d.MoveGroup] = append(mgList[d.MoveGroup], d) } } fmt.Println() m := migrationAPI.New(iKey.Password, false) for mg, devices := range mgList { for _, d := range devices { if confirmDeallocate(d) { r := deallocateResult{ ID: d.ID, MoveGroup: mg, Result: new(migrationAPI.DeallocateIPsResponse), } r.Result, err = m.DeallocateIPs(mg, d.ID) if err != nil { errString := err.Error() if r.Result.Error != nil { errString = errString + " " + *r.Result.Error } r.Result = &migrationAPI.DeallocateIPsResponse{ Error: &errString, } } if r.Result.Error == nil { deallocated := "none" if r.Result.Data != nil && len(r.Result.Data.DeallocatedIPs) > 0 { deallocated = strings.Join(r.Result.Data.DeallocatedIPs, ", ") } fmt.Printf("%d deallocated IPs: %s\n", r.ID, deallocated) } else { fmt.Printf("%d Error: %s\n", r.ID, *r.Result.Error) } //pPrintDeallocate(r) } fmt.Println() } } } func confirmDeallocate(d tools.Device) bool { if *argDeallocateYes { return true } t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendHeader(table.Row{fmt.Sprintf("%s - %d Source IPs", d.MoveGroup, d.ID)}) for _, x := range d.Network.Address.DracIPs.Source { t.AppendRow(table.Row{fmt.Sprintf("DRACNet: %s", x.IPAddress)}) } for _, x := range d.Network.Address.ServiceNetIPs.Source { t.AppendRow(table.Row{fmt.Sprintf("ServiceNet: %s", x.IPAddress)}) } for _, x := range d.Network.Address.VMNetMgmt.Source { t.AppendRow(table.Row{fmt.Sprintf("VMNet: %s", x.IPAddress)}) } for _, x := range d.Network.Address.VMNetVMotion.Source { t.AppendRow(table.Row{fmt.Sprintf("VMNet: %s", x.IPAddress)}) } t.SetStyle(table.StyleLight) t.Style().Options.SeparateRows = false t.Render() fmt.Println() return shared.ConfirmPrompt(fmt.Sprintf("Deallocate above IPs for %d?", d.ID)) } /* func pPrintDeallocate(r deallocateResult) { t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendRow(table.Row{fmt.Sprintf("%d - %s", r.ID, r.MoveGroup)}) if r.Result.Error != nil { header := "Error" t.AppendRow(table.Row{fmt.Sprintf("%s: %s", header, *r.Result.Error)}) } else if r.Result.Data != nil { out := "IPs Deallocated: " if len(r.Result.Data.DeallocatedIPs) < 1 { out += "none" } else { out += strings.Join(r.Result.Data.DeallocatedIPs, ", ") } t.AppendRow(table.Row{out}) } t.SetStyle(table.StyleLight) t.Style().Options.SeparateRows = true t.Render() } */