From a72bbc63e44f9ff7618315d402b835da287dc0dc Mon Sep 17 00:00:00 2001 From: Henry Camacho Date: Sat, 25 Mar 2017 20:33:09 -0500 Subject: [PATCH] Updated to support load balanced API Rest - system collects all the domains, servers, and stats. /domains - added support for a WSS state, displays on the UI - moved all server related domain structures to ServerDomain* etc. to avoid collision with Domains - create new Domains structure to handle Domains, Domain, Servers and Traffic at each level. - updated initial lastUpate to the connection time rather than 0 which gave a silly duration. - added properties for DomainTrack (Requests and Responses) --- html/admin/partials/servers.html | 6 +- rvpn/genericlistener/api_collect_domains.go | 103 ++++++++++-------- rvpn/genericlistener/api_collect_server.go | 21 ++-- .../api_collect_server_domains.go | 60 ++++++++++ rvpn/genericlistener/api_collect_servers.go | 26 +++-- rvpn/genericlistener/api_interface.go | 17 +-- rvpn/genericlistener/connection.go | 6 +- rvpn/genericlistener/domain_track.go | 10 ++ 8 files changed, 159 insertions(+), 90 deletions(-) create mode 100644 rvpn/genericlistener/api_collect_server_domains.go diff --git a/html/admin/partials/servers.html b/html/admin/partials/servers.html index 1c94ff5..9eed22e 100644 --- a/html/admin/partials/servers.html +++ b/html/admin/partials/servers.html @@ -27,8 +27,9 @@ Address Xfer (in/out) Req/Resp - Time - Idle + Duration + State + Idle
@@ -64,6 +65,7 @@ {{ s.duration | hfcduration }} + {{ s.server_state }} {{ s.idle | hfcduration }} diff --git a/rvpn/genericlistener/api_collect_domains.go b/rvpn/genericlistener/api_collect_domains.go index c0443dd..b8f5a28 100644 --- a/rvpn/genericlistener/api_collect_domains.go +++ b/rvpn/genericlistener/api_collect_domains.go @@ -1,60 +1,69 @@ package genericlistener -//DomainsAPI -- Structure to support the server API -type DomainsAPI struct { - DomainName string `json:"domain_name"` - ServerID int64 `json:"server_id"` - BytesIn int64 `json:"bytes_in"` - BytesOut int64 `json:"bytes_out"` - Requests int64 `json:"requests"` - Responses int64 `json:"responses"` +//DomainsAPI -- A collections of all the domains +//List of Domains -> DomainAPI +//DomainsAPI -> DomainServerAPI +// + +//DomainServerAPI -- Container for Server Stats related to a domain +type DomainServerAPI struct { + ServerName string `json:"server_name"` + Traffic TrafficAPI `json:"traffic"` } -//NewDomainsAPI - Constructor -func NewDomainsAPI(c *Connection, d *DomainTrack) (s *DomainsAPI) { - s = new(DomainsAPI) - s.DomainName = d.DomainName - s.ServerID = c.ConnectionID() - s.BytesIn = d.BytesIn() - s.BytesOut = d.BytesOut() - s.Requests = d.requests - s.Responses = d.responses +//NewDomainServerAPI -- Constructor +func NewDomainServerAPI(domain string, conn *Connection) (p *DomainServerAPI) { + p = new(DomainServerAPI) + dt := conn.DomainTrack[domain] + p.Traffic.BytesIn = dt.BytesIn() + p.Traffic.BytesOut = dt.BytesOut() + p.Traffic.Requests = dt.Requests() + p.Traffic.Responses = dt.Responses() + p.ServerName = conn.ServerName() return } -//DomainsAPIContainer -- Holder for all the Servers -type DomainsAPIContainer struct { - Domains []*DomainsAPI `json:"domains"` -} - -//NewDomainsAPIContainer -- Constructor -func NewDomainsAPIContainer() (p *DomainsAPIContainer) { - p = new(DomainsAPIContainer) - p.Domains = make([]*DomainsAPI, 0) - return p -} - -//DomainAPI -- Structure to support the server API +//DomainAPI -- Container for domain and related servers type DomainAPI struct { - DomainName string `json:"domain_name"` - ServerID int64 `json:"server_id"` - BytesIn int64 `json:"bytes_in"` - BytesOut int64 `json:"bytes_out"` - Requests int64 `json:"requests"` - Responses int64 `json:"responses"` - Source string `json:"source_addr"` + TotalServers int `json:"server_total"` + Servers []*DomainServerAPI `json:"servers"` + Traffic TrafficAPI `json:"traffic"` } -//NewDomainAPI - Constructor -func NewDomainAPI(c *Connection, d *DomainTrack) (s *DomainAPI) { - s = new(DomainAPI) - s.DomainName = d.DomainName - s.ServerID = c.ConnectionID() - s.BytesIn = d.BytesIn() - s.BytesOut = d.BytesOut() - s.Requests = d.requests - s.Responses = d.responses - s.Source = c.Source() +//NewDomainAPI -- Constructor +func NewDomainAPI(domain string, domainLoadBalance *DomainLoadBalance) (p *DomainAPI) { + p = new(DomainAPI) + for pos := range domainLoadBalance.connections { + ds := NewDomainServerAPI(domain, domainLoadBalance.connections[pos]) + p.Servers = append(p.Servers, ds) + p.TotalServers++ + p.Traffic.BytesIn += domainLoadBalance.connections[pos].BytesIn() + p.Traffic.BytesOut += domainLoadBalance.connections[pos].BytesOut() + p.Traffic.Requests += domainLoadBalance.connections[pos].requests + p.Traffic.Responses += domainLoadBalance.connections[pos].responses + } + return +} + +//DomainsAPI -- Container for Domains +type DomainsAPI struct { + TotalDomains int `json:"domain_total"` + Domains []*DomainAPI `json:"domains"` + Traffic TrafficAPI `json:"traffic"` +} + +//NewDomainsAPI -- Constructor +func NewDomainsAPI(domains map[string]*DomainLoadBalance) (p *DomainsAPI) { + p = new(DomainsAPI) + for domain := range domains { + d := NewDomainAPI(domain, domains[domain]) + p.Domains = append(p.Domains, d) + p.Traffic.BytesIn += d.Traffic.BytesIn + p.Traffic.BytesOut += d.Traffic.BytesOut + p.Traffic.Requests += d.Traffic.Requests + p.Traffic.Responses += d.Traffic.Responses + + } return } diff --git a/rvpn/genericlistener/api_collect_server.go b/rvpn/genericlistener/api_collect_server.go index 25bc150..9b9cd23 100644 --- a/rvpn/genericlistener/api_collect_server.go +++ b/rvpn/genericlistener/api_collect_server.go @@ -4,14 +4,15 @@ import "time" //ServerAPI -- Structure to support the server API type ServerAPI struct { - ServerName string `json:"server_name"` - ServerID int64 `json:"server_id"` - Domains []*DomainAPI `json:"domains"` - Duration float64 `json:"duration"` - Idle float64 `json:"idle"` - BytesIn int64 `json:"bytes_in"` - BytesOut int64 `json:"bytes_out"` - Source string `json:"source_address"` + ServerName string `json:"server_name"` + ServerID int64 `json:"server_id"` + Domains []*ServerDomainAPI `json:"domains"` + Duration float64 `json:"duration"` + Idle float64 `json:"idle"` + BytesIn int64 `json:"bytes_in"` + BytesOut int64 `json:"bytes_out"` + Source string `json:"source_address"` + State bool `json:"server_state"` } //NewServerAPI - Constructor @@ -19,7 +20,7 @@ func NewServerAPI(c *Connection) (s *ServerAPI) { s = new(ServerAPI) s.ServerName = c.ServerName() s.ServerID = c.ConnectionID() - s.Domains = make([]*DomainAPI, 0) + s.Domains = make([]*ServerDomainAPI, 0) s.Duration = time.Since(c.ConnectTime()).Seconds() s.Idle = time.Since(c.LastUpdate()).Seconds() s.BytesIn = c.BytesIn() @@ -28,7 +29,7 @@ func NewServerAPI(c *Connection) (s *ServerAPI) { for domainName := range c.DomainTrack { - domainAPI := NewDomainAPI(c, c.DomainTrack[domainName]) + domainAPI := NewServerDomainAPI(c, c.DomainTrack[domainName]) s.Domains = append(s.Domains, domainAPI) } return diff --git a/rvpn/genericlistener/api_collect_server_domains.go b/rvpn/genericlistener/api_collect_server_domains.go new file mode 100644 index 0000000..3a9b84c --- /dev/null +++ b/rvpn/genericlistener/api_collect_server_domains.go @@ -0,0 +1,60 @@ +package genericlistener + +//ServerDomainsAPI -- Structure to support the server API +type ServerDomainsAPI struct { + DomainName string `json:"domain_name"` + ServerID int64 `json:"server_id"` + BytesIn int64 `json:"bytes_in"` + BytesOut int64 `json:"bytes_out"` + Requests int64 `json:"requests"` + Responses int64 `json:"responses"` +} + +//NewServerDomainsAPI - Constructor +func NewServerDomainsAPI(c *Connection, d *DomainTrack) (s *ServerDomainsAPI) { + s = new(ServerDomainsAPI) + s.DomainName = d.DomainName + s.ServerID = c.ConnectionID() + s.BytesIn = d.BytesIn() + s.BytesOut = d.BytesOut() + s.Requests = d.requests + s.Responses = d.responses + + return +} + +//ServerDomainsAPIContainer -- Holder for all the Servers +type ServerDomainsAPIContainer struct { + Domains []*ServerDomainsAPI `json:"domains"` +} + +//NewServerDomainsAPIContainer -- Constructor +func NewServerDomainsAPIContainer() (p *ServerDomainsAPIContainer) { + p = new(ServerDomainsAPIContainer) + p.Domains = make([]*ServerDomainsAPI, 0) + return p +} + +//ServerDomainAPI -- Structure to support the server API +type ServerDomainAPI struct { + DomainName string `json:"domain_name"` + ServerID int64 `json:"server_id"` + BytesIn int64 `json:"bytes_in"` + BytesOut int64 `json:"bytes_out"` + Requests int64 `json:"requests"` + Responses int64 `json:"responses"` + Source string `json:"source_addr"` +} + +//NewServerDomainAPI - Constructor +func NewServerDomainAPI(c *Connection, d *DomainTrack) (s *ServerDomainAPI) { + s = new(ServerDomainAPI) + s.DomainName = d.DomainName + s.ServerID = c.ConnectionID() + s.BytesIn = d.BytesIn() + s.BytesOut = d.BytesOut() + s.Requests = d.requests + s.Responses = d.responses + s.Source = c.Source() + return +} diff --git a/rvpn/genericlistener/api_collect_servers.go b/rvpn/genericlistener/api_collect_servers.go index cb5648a..ed5b47c 100644 --- a/rvpn/genericlistener/api_collect_servers.go +++ b/rvpn/genericlistener/api_collect_servers.go @@ -4,16 +4,17 @@ import "time" //ServersAPI -- Structure to support the server API type ServersAPI struct { - ServerName string `json:"server_name"` - ServerID int64 `json:"server_id"` - Domains []*DomainAPI `json:"domains"` - Duration float64 `json:"duration"` - Idle float64 `json:"idle"` - BytesIn int64 `json:"bytes_in"` - BytesOut int64 `json:"bytes_out"` - Requests int64 `json:"requests"` - Responses int64 `json:"responses"` - Source string `json:"source_address"` + ServerName string `json:"server_name"` + ServerID int64 `json:"server_id"` + Domains []*ServerDomainAPI `json:"domains"` + Duration float64 `json:"duration"` + Idle float64 `json:"idle"` + BytesIn int64 `json:"bytes_in"` + BytesOut int64 `json:"bytes_out"` + Requests int64 `json:"requests"` + Responses int64 `json:"responses"` + Source string `json:"source_address"` + State bool `json:"server_state"` } //NewServersAPI - Constructor @@ -21,7 +22,7 @@ func NewServersAPI(c *Connection) (s *ServersAPI) { s = new(ServersAPI) s.ServerName = c.ServerName() s.ServerID = c.ConnectionID() - s.Domains = make([]*DomainAPI, 0) + s.Domains = make([]*ServerDomainAPI, 0) s.Duration = time.Since(c.ConnectTime()).Seconds() s.Idle = time.Since(c.LastUpdate()).Seconds() s.BytesIn = c.BytesIn() @@ -29,10 +30,11 @@ func NewServersAPI(c *Connection) (s *ServersAPI) { s.Requests = c.requests s.Responses = c.responses s.Source = c.Source() + s.State = c.State() for d := range c.DomainTrack { dt := c.DomainTrack[d] - domainAPI := NewDomainAPI(c, dt) + domainAPI := NewServerDomainAPI(c, dt) s.Domains = append(s.Domains, domainAPI) } return diff --git a/rvpn/genericlistener/api_interface.go b/rvpn/genericlistener/api_interface.go index a661477..b788a83 100644 --- a/rvpn/genericlistener/api_interface.go +++ b/rvpn/genericlistener/api_interface.go @@ -98,18 +98,7 @@ func getDomainsEndpoint(w http.ResponseWriter, r *http.Request) { serverStatus.AdminStats.IncRequests() - domainsContainer := NewDomainsAPIContainer() - - for domain := range connectionTable.domains { - domainLB := connectionTable.domains[domain] - conns := domainLB.Connections() - for pos := range conns { - conn := conns[pos] - domainAPI := NewDomainsAPI(conn, conn.DomainTrack[domain]) - domainsContainer.Domains = append(domainsContainer.Domains, domainAPI) - } - - } + domainsContainer := NewDomainsAPI(connectionTable.domains) w.Header().Set("Content-Type", "application/json; charset=UTF-8") @@ -139,11 +128,11 @@ func getDomainEndpoint(w http.ResponseWriter, r *http.Request) { env.ErrorURI = r.RequestURI env.ErrorDescription = "domain-name not found" } else { - var domainAPIContainer []*DomainAPI + var domainAPIContainer []*ServerDomainAPI conns := domainLB.Connections() for pos := range conns { conn := conns[pos] - domainAPI := NewDomainAPI(conn, conn.DomainTrack[domainName]) + domainAPI := NewServerDomainAPI(conn, conn.DomainTrack[domainName]) domainAPIContainer = append(domainAPIContainer, domainAPI) } env.Result = domainAPIContainer diff --git a/rvpn/genericlistener/connection.go b/rvpn/genericlistener/connection.go index a23aa07..d1045de 100755 --- a/rvpn/genericlistener/connection.go +++ b/rvpn/genericlistener/connection.go @@ -12,11 +12,6 @@ import ( "git.daplie.com/Daplie/go-rvpn-server/rvpn/packer" ) -var upgrader = websocket.Upgrader{ - ReadBufferSize: 4096, - WriteBufferSize: 4096, -} - // Connection track websocket and faciliates in and out data type Connection struct { mutex sync.Mutex @@ -91,6 +86,7 @@ func NewConnection(connectionTable *Table, conn *websocket.Conn, remoteAddress s p.initialDomains = initialDomains p.connectionTrack = connectionTrack p.DomainTrack = make(map[string]*DomainTrack) + p.lastUpdate = time.Now() for _, domain := range initialDomains { p.AddTrackedDomain(string(domain.(string))) diff --git a/rvpn/genericlistener/domain_track.go b/rvpn/genericlistener/domain_track.go index 6bf17c0..febf068 100644 --- a/rvpn/genericlistener/domain_track.go +++ b/rvpn/genericlistener/domain_track.go @@ -49,3 +49,13 @@ func (c *DomainTrack) AddRequests() { func (c *DomainTrack) AddResponses() { c.responses = c.responses + 1 } + +//Requests -- Property +func (c *DomainTrack) Requests() int64 { + return c.requests +} + +//Responses -- Property +func (c *DomainTrack) Responses() int64 { + return c.responses +}