// 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 cmdb import ( "fmt" "net" "strings" "github.rackspace.com/DCM/netparse" "github.rackspace.com/DCM/tools" "github.rackspace.com/gorax/clients/dcxAutohost" "github.rackspace.com/gorax/passkey" ) const ( // Datapipe is a reference for the New function to specify that we // are going to implement legacy Datapipe as a backend system. Datapipe CMDB = iota ) type ( // CMDB represents the types of systems where we will make the device+network association. This // system will have some identifiable item to associate a network configuration with the // representation in the system. CMDB int // Getter interface is the implementation of a set of methods that we can call on a device. This // abstraction allows us to use multiple methods of Get on a Record depending // on the interface implementation type. Getter interface { Get(uniqueID string) (Model, error) Map(r *Model) error } // Device is the model used to embed the abstracted device // types. Model struct { tools.Device IsGateway bool `json:"is_gateway"` Region string `json:"region"` PortMap dcxAutohost.DevicePortMap `json:"device_port_maps"` Vlans []netparse.Vlan `json:"device_vlans"` Routes []netparse.IPRoute `json:"-"` NATs map[string]NAT `json:"-"` MACs []string `json:"mac_addresses"` IPs []IPAssignment `json:"ip_assignments"` Blocks []Block `json:"-"` } // Block defines the private IP space behind a network device Block struct { CIDR string `json:"cidr"` Vlan *int `json:"vlan"` } // NAT is an over simplified NAT struct { Real net.IP `json:"real_ip"` Mapped net.IP `json:"mapped_ip"` MAC string `json:"mac_address"` } // IPAssignment defines a list of public/private IPs associated with a device IPAssignment struct { Public string `json:"public"` Private string `json:"private"` } ) // New function will take a credential to create a discover client func New(key *passkey.Client, cmdb CMDB) (Getter, error) { // Perform a switch on the type of system that is passed in to initialize the // correct implementation of the CMDB system. switch cmdb { case Datapipe: // If the system is admin.mydatapipe.com, initialize the clients we'll need, // then return the DP implementation back as the Client return dpClient(key) default: return nil, fmt.Errorf("%d system is not supported", cmdb) } } // DeviceType is used in conjunction with the DCX Join device to determine if the device // should be considered a physical or a virtual device func (d *Model) DeviceType() string { // If the device has switchports, then consider is a physical device. if len(d.Environment.Current.SwitchPorts) > 0 { return "physical" } // Else if the make_model or config_type contains virtual, consider it a virtual device. if strings.Contains(strings.ToLower(d.Device.Device.MakeModel), "virtual") { return "virtual" } if strings.Contains(strings.ToLower(d.Device.Device.ComponentConfigType), "virtual") { return "virtual" } // Finally, default to a physical device. return "physical" } // HasMAC will check if a device has a given mac-address shown on any of it's switch-ports. func (d *Model) HasMAC(mac string) bool { for i := range d.MACs { if d.MACs[i] == mac { return true } } return false } func mustString(s *string) string { if s == nil { return "" } return *s }