You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by el...@apache.org on 2018/07/06 17:22:51 UTC

[trafficcontrol] 01/02: Add TO Go deliveryservices/servers/eligible

This is an automated email from the ASF dual-hosted git repository.

elsloo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git

commit faa010c4f99b6e0fdbe0a720e2ca885250b8cb24
Author: Robert Butts <ro...@apache.org>
AuthorDate: Wed Jun 20 17:43:23 2018 -0600

    Add TO Go deliveryservices/servers/eligible
---
 .../deliveryservice/deliveryservicesv12.go         |  13 ++
 .../traffic_ops_golang/deliveryservice/eligible.go | 189 +++++++++++++++++++++
 traffic_ops/traffic_ops_golang/routes.go           |   1 +
 3 files changed, 203 insertions(+)

diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go
index a84a14f..d80b7b1 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go
@@ -88,6 +88,19 @@ func getDSTenantIDByID(tx *sql.Tx, id int) (*int, bool, error) {
 	return tenantID, true, nil
 }
 
+// GetDSTenantIDByIDTx returns the tenant ID, whether the delivery service exists, and any error.
+// Note the id may be nil, even if true is returned, if the delivery service exists but its tenant_id field is null.
+func GetDSTenantIDByIDTx(tx *sql.Tx, id int) (*int, bool, error) {
+	tenantID := (*int)(nil)
+	if err := tx.QueryRow(`SELECT tenant_id FROM deliveryservice where id = $1`, id).Scan(&tenantID); err != nil {
+		if err == sql.ErrNoRows {
+			return nil, false, nil
+		}
+		return nil, false, fmt.Errorf("querying tenant ID for delivery service ID '%v': %v", id, err)
+	}
+	return tenantID, true, nil
+}
+
 // getDSTenantIDByName returns the tenant ID, whether the delivery service exists, and any error.
 // Note the id may be nil, even if true is returned, if the delivery service exists but its tenant_id field is null.
 func getDSTenantIDByName(tx *sql.Tx, name string) (*int, bool, error) {
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go
new file mode 100644
index 0000000..494e4c7
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go
@@ -0,0 +1,189 @@
+package deliveryservice
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import (
+	"database/sql"
+	"errors"
+	"net/http"
+	"strconv"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+)
+
+func GetServersEligible(w http.ResponseWriter, r *http.Request) {
+	inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"id"}, []string{"id"})
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, errCode, userErr, sysErr)
+		return
+	}
+	defer inf.Close()
+
+	// TODO create a helper function to check all this in a single line.
+	ok, err := tenant.IsTenancyEnabledTx(inf.Tx.Tx)
+	if err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("checking tenancy enabled: "+err.Error()))
+		return
+	}
+	if ok {
+		dsTenantID, ok, err := GetDSTenantIDByIDTx(inf.Tx.Tx, inf.IntParams["id"])
+		if err != nil {
+			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("checking tenant: "+err.Error()))
+			return
+		}
+		if !ok {
+			api.HandleErr(w, r, http.StatusNotFound, errors.New("delivery service "+inf.Params["id"]+" not found"), nil)
+			return
+		}
+		if dsTenantID != nil {
+			if authorized, err := tenant.IsResourceAuthorizedToUserTx(*dsTenantID, inf.User, inf.Tx.Tx); err != nil {
+				api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("checking tenant: "+err.Error()))
+				return
+			} else if !authorized {
+				api.HandleErr(w, r, http.StatusForbidden, errors.New("not authorized on this tenant"), nil)
+				return
+			}
+		}
+	}
+
+	servers, err := getEligibleServers(inf.Tx.Tx, inf.IntParams["id"])
+	if err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("getting eligible servers: "+err.Error()))
+		return
+	}
+	api.WriteResp(w, r, servers)
+}
+
+const JumboFrameBPS = 9000
+
+func getEligibleServers(tx *sql.Tx, dsID int) ([]tc.DSServer, error) {
+	q := `
+WITH ds_id as (SELECT $1::bigint as v)
+SELECT
+cg.name as cachegroup,
+s.cachegroup as cachegroup_id,
+s.cdn_id,
+cdn.name as cdn_name,
+s.domain_name,
+s.guid,
+s.host_name,
+s.https_port,
+s.id,
+s.ilo_ip_address,
+s.ilo_ip_gateway,
+s.ilo_ip_netmask,
+s.ilo_password,
+s.ilo_username,
+COALESCE(s.interface_mtu, ` + strconv.Itoa(JumboFrameBPS) + `) as interface_mtu,
+s.interface_name,
+s.ip6_address,
+s.ip6_gateway,
+s.ip_address,
+s.ip_gateway,
+s.ip_netmask,
+s.last_updated,
+s.mgmt_ip_address,
+s.mgmt_ip_gateway,
+s.mgmt_ip_netmask,
+s.offline_reason,
+pl.name as phys_location,
+s.phys_location as phys_location_id,
+p.name as profile,
+p.description as profile_desc,
+s.profile as profile_id,
+s.rack,
+s.router_host_name,
+s.router_port_name,
+st.name as status,
+s.status as status_id,
+s.tcp_port,
+t.name as server_type,
+s.type as server_type_id,
+s.upd_pending as upd_pending
+FROM server s
+JOIN cachegroup cg ON s.cachegroup = cg.id
+JOIN cdn cdn ON s.cdn_id = cdn.id
+JOIN phys_location pl ON s.phys_location = pl.id
+JOIN profile p ON s.profile = p.id
+JOIN status st ON s.status = st.id
+JOIN type t ON s.type = t.id
+WHERE s.cdn_id = (SELECT cdn_id from deliveryservice where id = (select v from ds_id))
+AND (t.name LIKE 'EDGE%' OR t.name LIKE 'ORG%')
+`
+	rows, err := tx.Query(q, dsID)
+	if err != nil {
+		return nil, errors.New("querying delivery service eligible servers: " + err.Error())
+	}
+	defer rows.Close()
+
+	servers := []tc.DSServer{}
+	for rows.Next() {
+		s := tc.DSServer{}
+		err := rows.Scan(
+			&s.Cachegroup,
+			&s.CachegroupID,
+			&s.CDNID,
+			&s.CDNName,
+			&s.DomainName,
+			&s.GUID,
+			&s.HostName,
+			&s.HTTPSPort,
+			&s.ID,
+			&s.ILOIPAddress,
+			&s.ILOIPGateway,
+			&s.ILOIPNetmask,
+			&s.ILOPassword,
+			&s.ILOUsername,
+			&s.InterfaceMtu,
+			&s.InterfaceName,
+			&s.IP6Address,
+			&s.IP6Gateway,
+			&s.IPAddress,
+			&s.IPGateway,
+			&s.IPNetmask,
+			&s.LastUpdated,
+			&s.MgmtIPAddress,
+			&s.MgmtIPGateway,
+			&s.MgmtIPNetmask,
+			&s.OfflineReason,
+			&s.PhysLocation,
+			&s.PhysLocationID,
+			&s.Profile,
+			&s.ProfileDesc,
+			&s.ProfileID,
+			&s.Rack,
+			&s.RouterHostName,
+			&s.RouterPortName,
+			&s.Status,
+			&s.StatusID,
+			&s.TCPPort,
+			&s.Type,
+			&s.TypeID,
+			&s.UpdPending,
+		)
+		if err != nil {
+			return nil, errors.New("scanning delivery service eligible servers: " + err.Error())
+		}
+		servers = append(servers, s)
+	}
+	return servers, nil
+}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index cd6b623..c33e666 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -355,6 +355,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		{1.1, http.MethodPut, `deliveryservices/{id}/?(\.json)?$`, deliveryservice.UpdateV12(), auth.PrivLevelOperations, Authenticated, nil},
 		{1.3, http.MethodDelete, `deliveryservices/{id}/?(\.json)?$`, api.DeleteHandler(deliveryservice.GetTypeV13Factory()), auth.PrivLevelOperations, Authenticated, nil},
 		{1.1, http.MethodDelete, `deliveryservices/{id}/?(\.json)?$`, api.DeleteHandler(deliveryservice.GetTypeV12Factory()), auth.PrivLevelOperations, Authenticated, nil},
+		{1.1, http.MethodGet, `deliveryservices/{id}/servers/eligible/?(\.json)?$`, deliveryservice.GetServersEligible, auth.PrivLevelReadOnly, Authenticated, nil},
 
 		//System
 		{1.1, http.MethodGet, `system/info/?(\.json)?$`, systeminfo.Handler(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},