package pkg import ( "errors" "regexp" "strconv" "strings" "github.com/gofrs/uuid" "github.com/sirupsen/logrus" "github.rackspace.com/gorax/clients/coreAPI" "github.rackspace.com/gorax/clients/sshAPI" "github.rackspace.com/gorax/tools/util" ) type ( // F5 : Master structure F5 struct { Config *DevConfig `json:"configuration_items"` Device int `json:"device"` Failover *int `json:"failover_device"` Logs *Logs `json:"logs"` Management *Management `json:"management_items"` Status *DevStatus `json:"status_items"` changeLog []*sshAPI.Command coreapi *coreAPI.Client deviceInfo *coreAPI.DeviceInfo sshClient *sshAPI.SSHClient // New layout - David Patino // Not completely implemented as of 5/30/2018 LTM LTM `json:"ltm"` // Local Traffic Manager Security Security `json:"security"` // Global Security Policies Sys Sys `json:"system"` // General system configuration log *logrus.Entry } // LTM : Local Traffic Manager Module LTM struct { IRules map[string]IRule `json:"irules"` DataGroups struct { External map[string]ExternalDataGroup `json:"external"` Internal map[string]InternalDataGroup `json:"internal"` } `json:"data_groups"` } // InternalDataGroup : Internal Data Group InternalDataGroup struct { AppService string `json:"app_service"` Description string `json:"description"` Partition string `json:"partition"` Records map[string]DataGroupRecord `json:"records,omitempty"` Type string `json:"type,omitempty"` } ExternalDataGroup struct { AppService string `json:"app_service"` CachePath string `json:"cache_path,omitempty"` Contents []string `json:"contents,omitempty"` Description string `json:"description"` ExternalFileName string `json:"external_file_name,omitempty"` Name string `json:"name"` Partition string `json:"partition"` Type string `json:"type,omitempty"` } DataGroupRecord struct { Data string `json:"data,omitempty"` } // DevConfig : DevConfig structure DevConfig struct { AFMAddressLists []*AddressList `json:"security_address_lists"` AFMGlobalRules *GlobalRule `json:"security_global_rules"` AFMPolicyLists []*PolicyList `json:"security_policy_lists"` AFMRuleLists []*RuleList `json:"security_rule_lists"` CliSettings *CliGlobalSettings `json:"cli_settings"` CM *CMConfig `json:"central_management"` Interfaces []*IntHwConfig `json:"interfaces"` LTMMonitors *LTMMonitors `json:"monitors"` MasterKey struct { Key string `json:"master_key"` } Nat []*NAT `json:"nat"` Nodes map[string]*Node `json:"nodes"` PacketFilters []*PacketFilter `json:"packet_filters"` PasswordPolicy PasswordPolicy `json:"password_policy"` Pools map[string]*Pool `json:"pools"` Profiles Profiles `json:"profiles"` Provision *Provision `json:"provision"` RouteDomains []*RouteDomain `json:"route_domains"` Routes []*Route `json:"routes"` SelfAllow *SelfAllow `json:"self_allow"` SelfIPs []*SelfIP `json:"self_ips"` SNMPConfig SNMPConfig `json:"snmp_config"` SysDB []*DBItem `json:"sys_db"` VirtualAddresses []*VirtualAddress `json:"virtual_addresses"` Virtuals []*Virtual `json:"virtuals"` VLANs []*VLAN `json:"vlans"` } // CMConfig : Central Management DevConfig CMConfig struct { DeviceGroups *CmDeviceGroups `json:"device_group"` TrafficGroups []*CmTrafficGroup `json:"traffic_group"` } // Management : Management Structure Management struct { DfSpace DfSpace `json:"df_space"` DirectoryList []File `json:"directory_list"` Dumpe2fsInfo Dumpe2fsInfo `json:"dumpe2fs_info"` Filesystems Filesystems `json:"filesystems"` FSCK FSCK `json:"fsck"` IP *MgmtIP `json:"management_ip"` Routes []*MgmtRoute `json:"management_routes"` SoftwareHotfix []*SwHotfix `json:"hotfix_images"` SoftwareImages []*SwImage `json:"software_images"` } // Status : Status Structure DevStatus struct { ARP []*ArpEntry `json:"arp_table"` Version *SysVersion `json:"version"` Interfaces []*IntStats `json:"interfaces"` Vlans []*VlanStatus `json:"vlans"` Routes []*ShowRoute `json:"routes"` License *SysLicense `json:"license"` CmDevices *ShCmDevices `json:"cm_devices"` MasterKey *MasterKey `json:"master_key"` SyncState *SyncState `json:"sync_state"` SysPartitions *SysPartitions `json:"partitions"` SysSoftware []Volumes `json:"software"` } // Logs : Log Structure Logs struct { LtmLogs []LtmLogLine `json:"ltm_logs"` } SoftwareInstall struct { FileType string `json:"filetype"` Image string `json:"filename"` Volume string `json:"volume"` } ) // NewF5 : Generate a new F5 structure based on core token //func NewF5(token string, device int, public bool) (*F5, error) { // c, err := coreAPI.New(token) // if err != nil { // return nil, err // } // d, err := c.DeviceInfo("f5", device, false) // if err != nil { // return nil, err // } // // return NewCoreDevice(c, d, public) //} // Params : Parameters required for the New() function type Params struct { Core *coreAPI.Client Device int Public bool Debug bool Trace bool ConnID uuid.UUID } var ( debug, trace bool ) // New : Initialize and return a new F5 structure. This is the prefered method as of 10/2/2018 func New(params Params) (*F5, error) { di, err := params.Core.DeviceInfo("f5", params.Device, false) if err != nil { return nil, err } if di == nil { return nil, errors.New("empty coreapi device data") } if len(di.DracIPs) > 1 { ip := di.ActiveMgmt() if ip == "" { logrus.Errorf("f5Init:ActiveMgmt:error finding active mgmt IP address") } else { di.DracIP = ip } } sa, err := sshAPI.NewSSHAPIClient(params.Core, di, "f5", params.Public, params.ConnID) if err != nil { return nil, err } log := logrus.New() if params.Trace { log.SetLevel(logrus.TraceLevel) log.SetReportCaller(true) trace = true } else if params.Debug { log.SetLevel(logrus.DebugLevel) debug = true } else { log.SetLevel(logrus.InfoLevel) log.SetFormatter(&logrus.JSONFormatter{}) } f5 := &F5{ Config: &DevConfig{ CM: new(CMConfig), }, Status: new(DevStatus), Management: new(Management), Logs: new(Logs), sshClient: sa, Failover: func() *int { if di.FailoverDevice == nil { return nil } if i, err := strconv.Atoi(di.FailoverDevice.FailoverID); err == nil { return &i } return nil }(), Device: util.Atoi(di.ID), deviceInfo: di, log: log.WithField("device", di.ID), } if err := f5.DisablePaging(); err != nil { return f5, err } return f5, nil } // InitF5 : Generate a new F5 structure with an existing coreAPI.Client func InitF5(c *coreAPI.Client, device int, _ string, public bool) (*F5, error) { d, err := c.DeviceInfo("f5", device, false) if err != nil { return nil, err } return NewCoreDevice(c, d, public, nil) } func responseCleanup(s string) (string, error) { if strings.Contains(s, "Data Input Error") { // invalid partition name ERRORRE := regexp.MustCompile(`(Data Input Error.*?)\n`) return "", errors.New(util.RegexpFindString(ERRORRE, s)) } if strings.Contains(s, "01020036:3") { // object not found ERRORRE := regexp.MustCompile(`(01020036:3.*?)\n`) return "", errors.New(util.RegexpFindString(ERRORRE, s)) } return s, nil } // NewCoreDevice : Generate a new F5 structure with an existing coreAPI.Client and coreAPI.DeviceInfo func NewCoreDevice(c *coreAPI.Client, d *coreAPI.DeviceInfo, public bool, cid *uuid.UUID) (*F5, error) { if d == nil { return nil, errors.New("empty coreapi device data") } if cid == nil { id, err := uuid.NewV4() if err != nil { return nil, errors.New("error creating request-id") } cid = &id } sa, err := sshAPI.NewSSHAPIClient(c, d, "f5", public, *cid) if err != nil { return nil, err } log := logrus.New() log.SetLevel(logrus.InfoLevel) f5 := &F5{ Config: &DevConfig{ CM: new(CMConfig), }, Status: new(DevStatus), Management: new(Management), Logs: new(Logs), sshClient: sa, Failover: func() *int { if d.FailoverDevice == nil { return nil } if i, err := strconv.Atoi(d.FailoverDevice.FailoverID); err == nil { return &i } return nil }(), Device: util.Atoi(d.ID), deviceInfo: d, log: log.WithField("device", d.ID), } if err := f5.DisablePaging(); err != nil { return f5, err } return f5, nil } // NewDeviceWithUUID : Generate a new F5 structure with a given coreAPI.Client, coreAPI.DeviceInfo, and uuid.UUID //func NewDeviceWithUUID(c *coreAPI.Client, d *coreAPI.DeviceInfo, public bool, uid uuid.UUID) (*F5, error) { // if d == nil { // return nil, errors.New("empty coreapi device data") // } // // sa, err := sshAPI.NewSSHAPIClient(c, d, "f5", public, uid) // if err != nil { // return nil, err // } // // return &F5{ // Config: &DevConfig{ // CM: new(CMConfig), // }, // Status: new(DevStatus), // Management: new(Management), // Logs: new(Logs), // sshClient: sa, // Failover: func() *int { // if d.FailoverDevice == nil { // return nil // } // if i, err := strconv.Atoi(d.FailoverDevice.FailoverID); err == nil { // return &i // } // return nil // }(), // Device: util.Atoi(d.ID), // deviceInfo: d, // }, nil //}