// 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 portaudit import ( "bytes" "strconv" "strings" "text/template" "github.com/sirupsen/logrus" ) type ( // QueryParams defines the options available to pass into // Data warehouse SQL queries QueryParams struct { Account string CageID int RackID int DC string } // DWDevice is a type returned from the DWH SQL query DWDevice struct { ID int AccountNumber int AccountName string SpecificDeviceType string SpecificDeviceID int RackID int LocationID int DatacenterName string RSShortName string RackName string Disabled bool } ) const deviceSQL = `SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DISTINCT DV.[CustomerID] AS [AccountNumber] ,CU.[customer_name] AS [AccountName] ,DV.[DeviceID] ,DV.[SpecificDeviceType] ,DV.[SpecificDeviceID] ,DV.[RackID] ,RK.[LocationID] ,DC.[Title] AS [DatacenterName] ,DC.[RSShortname] ,RK.[Title] AS [RackName] ,DV.[Disabled] FROM [MyDatapipe_ODS].[dbo].[Device] AS DV LEFT JOIN [MyDatapipe_ODS].[dbo].[Rack] AS RK ON DV.[RackID] = RK.[RackID] LEFT JOIN [MyDatapipe_ODS].[dbo].[customers] AS CU ON DV.[CustomerID] = CU.[CustomerID] LEFT JOIN [MyDatapipe_ODS].[dbo].[Cage] AS CG ON RK.[CageID] = CG.[CageID] LEFT JOIN [MyDatapipe_ODS].[dbo].[Room] AS RM ON CG.[RoomID] = RM.[RoomID] LEFT JOIN [MyDatapipe_ODS].[dbo].[Datacenter] AS DC ON RM.[DatacenterID] = DC.[DatacenterID] WHERE DV.[Disabled] = '0' AND DV.[CustomerID] > '0' AND CU.[customer_name] IS NOT NULL AND DV.[SpecificDeviceType] NOT IN('PDU', 'serial console server') {{ if .DC }}AND DC.[RSShortname] IN('{{ .DC }}'){{ end }} {{ if .CageID }}AND CG.[CageID] IN('{{ .CageID }}'){{ end }} {{ if .RackID }}AND DV.[RackID] IN('{{ .RackID }}'){{ end }}` // QueryString will return the actual query to send to SQL with the resolved // values in the QueryParams. func QueryString(params QueryParams) (string, error) { var buff = new(bytes.Buffer) t, err := template.New("sql_query").Parse(deviceSQL) if err != nil { return "", err } if err := t.Execute(buff, params); err != nil { return "", err } return buff.String(), nil } // DatapipeDevices method will gather all device information from DWH for Datapipe devices. func (c *Client) DatapipeDevices(params QueryParams) (deviceList []DWDevice, err error) { deviceList = make([]DWDevice, 0) params.DC = strings.ToUpper(params.DC) logrus.Infof("querying DMart for the device information...") qry, err := QueryString(params) if err != nil { return } devices, err := c.sql.QueryInterface(qry) if err != nil { return } for _, item := range devices { var d DWDevice // Do some checks to make sure the device number can be found if _, ok := item["DeviceID"]; !ok { logrus.Errorf("SQL:DatapipeDevices:DeviceID not found [%v]", item) continue } n, err := strconv.Atoi(item["DeviceID"]) if err != nil { logrus.Errorf("SQL:DatapipeDevices:Unable to convert %s", item["DeviceID"]) continue } d.ID = n if val, ok := item["AccountNumber"]; ok { if n, err := strconv.Atoi(val); err == nil { d.AccountNumber = n } } if val, ok := item["AccountName"]; ok { d.AccountName = val } if val, ok := item["SpecificDeviceType"]; ok { d.SpecificDeviceType = val } if val, ok := item["SpecificDeviceID"]; ok { if n, err := strconv.Atoi(val); err == nil { d.SpecificDeviceID = n } } if val, ok := item["RackID"]; ok { if n, err := strconv.Atoi(val); err == nil { d.RackID = n } } if val, ok := item["LocationID"]; ok { if n, err := strconv.Atoi(val); err == nil { d.LocationID = n } } if val, ok := item["DatacenterName"]; ok { d.DatacenterName = val } if val, ok := item["RSShortName"]; ok { d.RSShortName = val } if val, ok := item["RackName"]; ok { d.RackName = val } if val, ok := item["Disabled"]; ok { d.Disabled = val == "1" } deviceList = append(deviceList, d) } logrus.Infof("Found %d devices in MyDatapipe_ODS Tables", len(deviceList)) return }