// 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 primary import ( "fmt" "net" "github.com/jokelyo/argparse" "github.com/sirupsen/logrus" "github.rackspace.com/DCM/discover/common" "github.rackspace.com/DCM/gomigrate/core" "github.rackspace.com/DCM/gomigrate/shared" "github.rackspace.com/DCM/tools" "github.rackspace.com/gorax/clients/dcxAutohost" "github.rackspace.com/gorax/clients/mydp" "github.rackspace.com/gorax/gokeys" ) var ( argD *[]int ) // SubPlugin function will return a argparse.Command type back to the parent parser // nolint:typecheck func SubPlugin(p *argparse.Command) core.Plugin { // Create a command and argument for the ip audit cmd := p.NewCommand("primary", "Assign primary IP addresses to devices.") argD = shared.ArgDevices(cmd) return core.Plugin{CMD: cmd, Func: pluginFunc} } type ( client struct { dcx *dcxAutohost.Client mydp *mydp.Client devices []int ctk gokeys.Credential raxID gokeys.Credential sso gokeys.Credential envVlans map[string][]dcxAutohost.EnvironmentVlan } ) // pluginFunc function is executed from the gomigrate caller func pluginFunc(cfg gokeys.Settings) { c := initClient(cfg) // Get the device list from a list of move-groups or devices. devices, err := shared.MongoDevices([]string{}, nil, c.devices, "", c.ctk.Password, make(map[string]interface{})) if err != nil { logrus.Fatal(err) } // Stop here if we did not find any devices. if len(devices) == 0 { logrus.Fatalf("no DB devices found in devices:(%v)", c.devices) } logrus.Infof("Assigning Primary IP on %d devices...", len(devices)) for _, d := range devices { if d.Linked.ID == 0 { logrus.Errorf("[%d] %s Missing Linked ID Record", d.ID, d.Device.HostName) continue } dcxDevice, err := c.dcx.DeviceIPs(d.ID) if err != nil { logrus.Errorf("[%d] dcx.DeviceIPs:%s", d.ID, err) continue } assignedIP := "" for _, dcxIP := range dcxDevice.Items { for _, ip := range dcxIP.PublicIPs { if ip.Label == "primary" { assignedIP = ip.IPAddress continue } } for _, ip := range dcxIP.PrivateIPs { if ip.Label == "primary" { assignedIP = ip.IPAddress continue } } } if assignedIP != "" { logrus.Infof("[%d] PrimaryIP Public [%s] already assigned", d.ID, assignedIP) continue } if err := c.allocatePrimaryIP(d); err != nil { logrus.Error(err) } } } func (c *client) allocatePrimaryIP(d tools.Device) error { dpDevice, err := c.mydp.DeviceByDeviceID(d.Linked.ID) if err != nil { return fmt.Errorf("mydp.DeviceByDeviceID:%s", err) } ip := net.ParseIP(dpDevice.PrimaryIP) if ip == nil { return fmt.Errorf("net.ParseIP:Missing Primary IP") } if !isValidIP(ip) { return fmt.Errorf("[%s] Smells like an invalid IP to me", ip.String()) } ipType := func() string { if !common.IsPublicIP(ip) { return "exnet" } return "publicnet" }() payload := []dcxAutohost.IPAssign{{ Addresses: []dcxAutohost.Address{{Type: ipType, Address: ip.String(), Role: "primary"}}, DeviceID: d.ID, }} resp, err := c.dcx.IPAddressAssign(payload) if err != nil { return fmt.Errorf("dcx.IPAddressAssign:%s", err) } logrus.Infof("[%d] Assigned: %v as %s", d.ID, resp[0].Addresses, ipType) return nil } func isValidIP(ip net.IP) bool { if ip.String() == "0.0.0.0" { return false } v4 := ip.To4() if v4[0] == 0 { return false } if v4[0] == v4[1] && v4[1] == v4[2] && v4[2] == v4[3] && ip.String() == "10.10.10.10" { return false } return true } func initClient(cfg gokeys.Settings) *client { // Set all the key from the arg parser c := client{ devices: *argD, envVlans: make(map[string][]dcxAutohost.EnvironmentVlan), } // Pull an identity token from the users gokeys keychain var err error if c.raxID, err = cfg.Identity(false); err != nil { logrus.Fatal(err) } // Pull a core token from the gokeys keychain if c.ctk, err = cfg.Core(false); err != nil { logrus.Fatal(err) } if c.sso, err = cfg.SSO(); err != nil { logrus.Fatal(err) } // Grab the client for the DCX API if c.dcx, err = dcxAutohost.New(dcxAutohost.WithToken(c.raxID.Password), false); err != nil { logrus.Fatal(err) } if c.mydp, err = shared.MyDPClient(c.sso.Username, c.sso.Password); err != nil { logrus.Fatal(err) } return &c }