Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Unified Diff: go/src/infra/crimson/server/crimsondb/crimsondb.go

Issue 2108643006: crimson server: Implemented SelectHost and InsertHost (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@mactohex
Patch Set: Added NULL support for boot class Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « go/src/infra/crimson/proto/pb.discovery.go ('k') | go/src/infra/crimson/server/crimsondb/crimsondb_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: go/src/infra/crimson/server/crimsondb/crimsondb.go
diff --git a/go/src/infra/crimson/server/crimsondb/crimsondb.go b/go/src/infra/crimson/server/crimsondb/crimsondb.go
index 752e6bcfa22c4c7aae9f398ae6224769702b6239..a781036bc878fb793289e1e49ff16430064e6d1e 100644
--- a/go/src/infra/crimson/server/crimsondb/crimsondb.go
+++ b/go/src/infra/crimson/server/crimsondb/crimsondb.go
@@ -275,6 +275,210 @@ func SelectIPRange(ctx context.Context, req *crimson.IPRangeQuery) ([]IPRange, e
return ipRanges, nil
}
+// scanHosts is a low-level function to scan sql results.
+// Rows must contain site, hostname, mac_addr, ip, boot_class in that order.
+func scanHosts(ctx context.Context, rows *sql.Rows) (*crimson.HostList, error) {
+ hostList := crimson.HostList{}
+
+ for rows.Next() {
+ var ipString, macString string
+ var hw net.HardwareAddr
+ var ip net.IP
+ var bootClass sql.NullString
+
+ host := crimson.Host{}
+ err := rows.Scan(&host.Site, &host.Hostname, &macString, &ipString,
+ &bootClass)
+ if bootClass.Valid {
+ host.BootClass = bootClass.String
+ }
+ if err != nil { // Users can't trigger that.
+ logging.Errorf(ctx, "%s", err)
+ return nil, err
+ }
+ if macString != "" {
+ hw, err = HexStringToHardwareAddr(macString)
+ if err != nil {
+ return nil, err
+ }
+ host.MacAddr = hw.String()
+ }
+
+ if ipString != "" {
+ ip, err = HexStringToIP(ipString)
+ if err != nil {
+ return nil, err
+ }
+ host.Ip = ip.String()
+ }
+ hostList.Hosts = append(hostList.Hosts, &host)
+ }
+ err := rows.Err()
+ if err != nil {
+ logging.Errorf(ctx, "%s", err)
+ return nil, err
+ }
+ return &hostList, nil
+}
+
+// InsertHost adds new hosts in the corresponding table.
+func InsertHost(ctx context.Context, req *crimson.HostList) (err error) {
+ db := DB(ctx)
+
+ if len(req.Hosts) == 0 {
+ logging.Errorf(ctx, "Received empty list of hosts to create.")
+ return UserErrorf(InvalidArgument,
+ "Received empty list of hosts to create.")
+ }
+
+ statement := bytes.Buffer{}
+ params := []interface{}{}
+
+ statement.WriteString("INSERT INTO host " +
+ "(site, hostname, mac_addr, ip, boot_class) VALUES ")
+ delimiter := ""
+
+ // Check that all required fields have been provided.
+ // TODO(pgervais): autogenerate missing values instead.
+ for i, host := range req.Hosts {
+ if host.Site == "" {
+ err = UserErrorf(InvalidArgument,
+ "Received empty host in entry #%s", i+1)
+ return
+ }
+ if host.MacAddr == "" {
+ err = UserErrorf(InvalidArgument,
+ "Received empty MAC address in entry #%s", i+1)
+ return
+ }
+ if host.Ip == "" {
+ err = UserErrorf(InvalidArgument,
+ "Received empty IP address in entry #%s", i+1)
+ return
+ }
+ if host.Hostname == "" {
+ err = UserErrorf(InvalidArgument,
+ "Received empty hostname in entry #%s", i+1)
+ return
+ }
+
+ // Compose query
+ var ip, macAddr string
+ statement.WriteString(delimiter)
+ delimiter = ", \n"
+ statement.WriteString("(?, ?, ?, ?, ?)")
+
+ ip, err = IPStringToHexString(host.Ip)
+ if err != nil {
+ return
+ }
+
+ macAddr, err = MacAddrStringToHexString(host.MacAddr)
+ if err != nil {
+ return
+ }
+
+ if host.BootClass == "" {
+ params = append(
+ params,
+ host.Site, host.Hostname, macAddr, ip, nil)
+ } else {
+ params = append(
+ params,
+ host.Site, host.Hostname, macAddr, ip, host.BootClass)
+ }
+ }
+
+ _, err = db.Exec(statement.String(), params...)
+ if err != nil {
+ logging.Errorf(ctx, "Insertion of new hosts failed. %s", err)
+ return
+ }
+
+ return
+}
+
+func SelectHost(ctx context.Context, req *crimson.HostQuery) (*crimson.HostList, error) {
+ var err error
+
+ db := DB(ctx)
+ delimiter := ""
+
+ statement := bytes.Buffer{}
+ params := []interface{}{}
+
+ statement.WriteString("SELECT site, hostname, mac_addr, ip, boot_class FROM host")
+ delimiter = "\nWHERE "
+
+ if req.Site != "" {
+ statement.WriteString(delimiter)
+ delimiter = "\nAND "
+ statement.WriteString("site=?")
+ params = append(params, req.Site)
+ }
+
+ if req.Hostname != "" {
+ statement.WriteString(delimiter)
+ delimiter = "\nAND "
+ statement.WriteString("hostname=?")
+ params = append(params, req.Hostname)
+ }
+
+ if req.MacAddr != "" {
+ statement.WriteString(delimiter)
+ delimiter = "\nAND "
+ hw, err := MacAddrStringToHexString(req.MacAddr)
+ if err != nil {
+ return nil, UserErrorf(
+ InvalidArgument,
+ "parsing of Mac address failed: %s", req.MacAddr)
+ }
+ statement.WriteString("mac_addr=?")
+ params = append(params, hw)
+ }
+
+ if req.Ip != "" {
+ statement.WriteString(delimiter)
+ delimiter = "\nAND "
+ ip, err := IPStringToHexString(req.Ip)
+ if err != nil {
+ return nil, UserErrorf(
+ InvalidArgument,
+ "parsing of IP address failed: %s", req.Ip)
+ }
+ statement.WriteString("ip=?")
+ params = append(params, ip)
+ }
+
+ if req.BootClass != "" {
+ statement.WriteString(delimiter)
+ delimiter = "\nAND "
+ statement.WriteString("boot_class=?")
+ params = append(params, req.BootClass)
+ }
+
+ if req.Limit > 0 {
+ statement.WriteString("\nLIMIT ?")
+ params = append(params, req.Limit)
+ }
+
+ sqlRows, err := db.Query(statement.String(), params...)
+
+ if err != nil {
+ logging.Errorf(ctx, "%s", err)
+ return nil, err
+ }
+ defer sqlRows.Close()
+
+ var rows *crimson.HostList
+ rows, err = scanHosts(ctx, sqlRows)
+ if err != nil {
+ logging.Errorf(ctx, "%s", err)
+ return nil, err
+ }
+ return rows, nil
+}
+
// UseDB stores a db handle into a context.
func UseDB(ctx context.Context, db *sql.DB) context.Context {
return context.WithValue(ctx, "dbHandle", db)
« no previous file with comments | « go/src/infra/crimson/proto/pb.discovery.go ('k') | go/src/infra/crimson/server/crimsondb/crimsondb_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698