/// <summary> /// /// </summary> /// <param name="db"></param> /// <param name="lane"></param> /// <param name="host"></param> /// <param name="limit"></param> /// <param name="page">First page = 0, second page = 1, etc.</param> /// <returns></returns> public static List<DBRevisionWorkView> Query (DB db, DBLane lane, DBHost host, int limit, int page) { Console.WriteLine ("Query {0} {1} {2} {3}", lane, host, limit, page); List<DBRevisionWorkView> result = new List<DBRevisionWorkView> (); using (IDbTransaction transaction = db.BeginTransaction ()) { using (IDbCommand cmd = db.CreateCommand ()) { // copy&paste from CustomTypes.sql cmd.CommandText = @" SELECT RevisionWork.id, Revision.revision INTO TEMP revisionwork_temptable FROM RevisionWork INNER JOIN Revision on RevisionWork.revision_id = Revision.id WHERE RevisionWork.lane_id = @lane_id AND RevisionWork.host_id = @host_id ORDER BY Revision.date DESC LIMIT @limit OFFSET @offset; -- For some reason postgresql thinks the temp table has 1230 entries, while it usually has about 20 entries, -- and decides to do a sequential scan on the work tabe. Analyze it to make it realize its untrue presumptions. ANALYZE revisionwork_temptable; SELECT Work.id, Work.command_id, Work.state, Work.starttime, Work.endtime, Work.duration, Work.logfile, Work.summary, Host.host, Lane.lane, Revision.author, Revision.revision, Command.command, Command.nonfatal, Command.alwaysexecute, Command.sequence, Command.internal, RevisionWork.lane_id, RevisionWork.host_id, RevisionWork.revision_id, RevisionWork.state AS revisionwork_state, WorkHost.host AS workhost FROM Work INNER JOIN RevisionWork ON Work.revisionwork_id = RevisionWork.id INNER JOIN Revision ON RevisionWork.revision_id = Revision.id INNER JOIN Lane ON RevisionWork.lane_id = Lane.id INNER JOIN Host ON RevisionWork.host_id = Host.id LEFT JOIN Host AS WorkHost ON RevisionWork.workhost_id = WorkHost.id INNER JOIN Command ON Work.command_id = Command.id WHERE Work.revisionwork_id IN (SELECT id FROM revisionwork_temptable) ORDER BY Revision.date DESC; "; DB.CreateParameter (cmd, "lane_id", lane.id); DB.CreateParameter (cmd, "host_id", host.id); DB.CreateParameter (cmd, "limit", limit); DB.CreateParameter (cmd, "offset", page * limit); using (IDataReader reader = cmd.ExecuteReader ()) { while (reader.Read ()) { result.Add (new DBRevisionWorkView (reader)); } } } return result; } }
public string GenerateHeader (GetViewWorkTableDataResponse response, DBLane lane, DBHost host, DBCommand command) { if (!Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) { return string.Format (@" <h2>Step {4} on lane '{2}' on '{3}' (<a href='ViewTable.aspx?lane_id={0}&host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, command.command); } else { return string.Format (@" <h2>Step {4} on lane '<a href='EditLane.aspx?lane_id={0}'>{2}</a>' on '<a href='EditHost.aspx?host_id={1}'>{3}</a>' (<a href='ViewTable.aspx?lane_id={0}&host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, command.command); } }
/// <summary> /// Returns true if something was added to the database. /// </summary> /// <param name="db"></param> /// <param name="lane"></param> /// <param name="host"></param> /// <returns></returns> public static bool AddRevisionWork (DB db, DBLane lane, DBHost host) { StringBuilder sql = new StringBuilder (); int line_count = 0; Logger.Log ("AddRevisionWork ({0} (id: {1}), {2} (id: {3}))", lane.lane, lane.id, host.host, host.id); try { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = @" SELECT Lane.id AS lid, Revision.id AS rid, Host.id AS hid FROM Host, Lane INNER JOIN Revision ON Revision.lane_id = lane.id WHERE Lane.id = @lane_id AND Host.id = @host_id AND NOT EXISTS ( SELECT 1 FROM RevisionWork WHERE RevisionWork.lane_id = Lane.id AND RevisionWork.host_id = Host.id AND RevisionWork.revision_id = Revision.id ); "; DB.CreateParameter (cmd, "lane_id", lane.id); DB.CreateParameter (cmd, "host_id", host.id); using (IDataReader reader = cmd.ExecuteReader ()) { while (reader.Read ()) { int lane_id = reader.GetInt32 (reader.GetOrdinal ("lid")); int host_id = reader.GetInt32 (reader.GetOrdinal ("hid")); int revision_id = reader.GetInt32 (reader.GetOrdinal ("rid")); line_count++; sql.AppendFormat ("INSERT INTO RevisionWork (lane_id, host_id, revision_id) VALUES ({0}, {1}, {2});", lane_id, host_id, revision_id); } } } if (line_count > 0) { Logger.Log ("AddRevisionWork: Adding {0} records.", line_count); db.ExecuteScalar (sql.ToString ()); } else { Logger.Log ("AddRevisionWork: Nothing to add."); } Logger.Log ("AddRevisionWork [Done]"); return line_count > 0; } catch (Exception ex) { Logger.Log ("AddRevisionWork got an exception: {0}\n{1}", ex.Message, ex.StackTrace); return false; } }
string confirmViewLaneAction(DBLane lane, DBHost host, DBRevision dbr, string action, string command) { return String.Format("javascript:confirmViewLaneAction (\"ViewLane.aspx?lane_id={0}&host_id={2}&revision_id={1}&action={3}\", \"{4}\");", lane.id, dbr.id, host.id, action, command); }
public string GenerateHeader (GetViewTableDataResponse response, DBLane lane, DBHost host, bool horizontal) { string result; string format; string disabled_msg = string.Empty; if (!response.Enabled) disabled_msg = " (Disabled)"; if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) { format = @"<h2>Build Matrix for <a href='EditLane.aspx?lane_id={0}'>'{2}'</a> on <a href='EditHost.aspx?host_id={5}'>'{4}'</a>{6}</h2><br/>"; } else { format = @"<h2>Build Matrix for '{2}' on '{4}'{6}</h2><br/>"; } format += @"<a href='ViewTable.aspx?lane_id={0}&host_id={1}&horizontal={3}'>Reverse x/y axis</a><br/>"; if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) format += string.Format (@"<a href='javascript:clearRevisions ({0}, {1})'>Clear selected revisions</a><br/>", lane.id, host.id); format += "<br/>"; result = string.Format (format, lane.id, host.id, lane.lane, horizontal ? "false" : "true", host.host, host.id, disabled_msg); return result; }
private List<DBMasterHost> FindMasterHosts (DB db, DBHost host) { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT * FROM MasterHost WHERE host_id = @host_id"; DB.CreateParameter (cmd, "host_id", host.id); using (IDataReader reader = cmd.ExecuteReader ()) { return DBRecord.LoadMany<DBMasterHost> (reader); } } }
public int AddHost (WebServiceLogin login, string host) { using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.Administrator); if (string.IsNullOrEmpty (host)) throw new ArgumentNullException ("name"); for (int i = 0; i < host.Length; i++) { if (char.IsLetterOrDigit (host [i])) { continue; } else if (host [i] == '-' || host [i] == '_') { continue; } else { throw new ArgumentOutOfRangeException (string.Format ("The character '{0}' isn't valid.", host [i])); } } DBHost dbhost = new DBHost (); dbhost.host = host; dbhost.enabled = true; dbhost.Save (db); return dbhost.id; } }
public void EditHost (WebServiceLogin login, DBHost host) { //WebServiceResponse response = new WebServiceResponse (); using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.Administrator); var oldHost = FindHost (db, host.id, null); host.Save (db); Audit (login, "edited host `{0}` -> `{1}`", Newtonsoft.Json.JsonConvert.SerializeObject(oldHost), Newtonsoft.Json.JsonConvert.SerializeObject(host) ); } }
private List<DBMasterHost> FindMasterHosts (DB db, DBHost host) { List<DBMasterHost> result = null; using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT * FROM MasterHost WHERE host_id = @host_id"; DB.CreateParameter (cmd, "host_id", host.id); using (IDataReader reader = cmd.ExecuteReader ()) { while (reader.Read ()) { if (result == null) result = new List<DBMasterHost> (); result.Add (new DBMasterHost (reader)); } } } return result; }
public string GenerateLaneTable (GetViewTableDataResponse response, DBLane lane, DBHost host, bool horizontal, int page, int limit) { StringBuilder matrix = new StringBuilder (); DateTime beginning = new DateTime (2001, 1, 1, 0, 0, 0); bool new_revision = true; int revision_id = 0; int result_index; List<DBRevisionWorkView> views = response.RevisionWorkViews; List<List<string>> table = new List<List<string>> (); List<string> row = new List<string> (); List<string> header = new List<string> (); List<string> header_classes = new List<string> (); try { for (int i = 0; i < views.Count; i++) { while (header.Count <= views [i].sequence) { header.Add (null); } if (header [views [i].sequence] != null) continue; header [views [i].sequence] = string.Format ("<a href='ViewWorkTable.aspx?lane_id={0}&host_id={1}&command_id={2}'>{3}</a>", lane.id, host.id, views [i].command_id, views [i].command); } header.RemoveAll (delegate (string match) { return match == null; }); header.Insert (0, "Revision"); header.Insert (1, "Author"); if (Utils.IsInRole (MonkeyWrench.DataClasses.Logic.Roles.Administrator)) header.Insert (2, "Select"); header.Add ("Host"); header.Add ("Duration"); result_index = Utils.IsInRole (MonkeyWrench.DataClasses.Logic.Roles.Administrator) ? 3 : 2; table.Add (header); bool failed = false; double duration = 0; for (int i = 0; i < views.Count; i++) { DBRevisionWorkView view = views [i]; DBState revisionwork_state = (DBState) view.revisionwork_state; DBState state = (DBState) view.state; new_revision = revision_id != view.revision_id; revision_id = view.revision_id; if (new_revision) { if (i > 0) { // matrix.AppendLine ("</tr>"); table.Add (row); row [row.Count - 1] = TimeSpan.FromSeconds (duration).ToString (); } string revision = view.revision; long dummy; if (revision.Length > 16 && !long.TryParse (revision, out dummy)) revision = revision.Substring (0, 8); row = new List<string> (); row.Add (string.Format ("<a href='ViewLane.aspx?lane_id={0}&host_id={1}&revision_id={2}' title='{4}'>{3}</a></td>", lane.id, host.id, view.revision_id, revision, string.Format ("Author: {1} Build start date: {0}", view.starttime.ToUniversalTime ().ToString ("yyyy/MM/dd HH:mm:ss UTC"), view.author))); row.Add (string.Format ("<a href='GetRevisionLog.aspx?id={0}'>{1}</a></td>", view.revision_id, view.author)); if (Utils.IsInRole (MonkeyWrench.DataClasses.Logic.Roles.Administrator)) row.Add (string.Format ("<input type=checkbox id='id_revision_chk_{1}' name='revision_id_{0}' />", view.revision_id, i)); while (row.Count < header.Count - 2) row.Add ("-"); row.Add (view.workhost ?? ""); row.Add (""); header_classes.Add (revisionwork_state.ToString ().ToLower ()); failed = false; duration = 0; } if (view.endtime > view.starttime) duration += (view.endtime - view.starttime).TotalSeconds; if (state == DBState.Failed && !view.nonfatal) failed = true; // result string result; switch (state) { case DBState.NotDone: result = failed ? "skipped" : "queued"; break; case DBState.Executing: result = "running"; break; case DBState.Failed: result = view.nonfatal ? "issues" : "failure"; break; case DBState.Success: result = "success"; break; case DBState.Aborted: result = "aborted"; break; case DBState.Timeout: result = "timeout"; break; case DBState.Paused: result = "paused"; break; default: result = "unknown"; break; } for (int j = 2; j < header.Count; j++) { if (header [j].Contains (view.command)) { row [j] = result; break; } } } table.Add (row); row [row.Count - 1] = TimeSpan.FromSeconds (duration).ToString (); matrix.AppendLine ("<table class='buildstatus'>"); if (horizontal) { for (int i = 0; i < header.Count; i++) { matrix.Append ("<tr>"); for (int j = 0; j < table.Count; j++) { string td = j == 0 ? "th" : "td"; if ((i == 0 || i == row.Count - 1) && j > 0) { if (i == row.Count - 1) { matrix.AppendFormat ("<{0} class='{1}' style='white-space: nowrap;'>", td, header_classes [j - 1]); } else { matrix.AppendFormat ("<{0} class='{1}'>", td, header_classes [j - 1]); } } else if (i >= result_index && j > 1) { matrix.AppendFormat ("<{0} class='{1}'>", td, table [j] [i]); } else { matrix.AppendFormat ("<{0}>", td); } matrix.AppendFormat (table [j] [i]); matrix.AppendFormat ("</{0}>", td); } matrix.AppendLine ("</tr>"); } } else { for (int i = 0; i < table.Count; i++) { row = table [i]; matrix.Append ("<tr>\n"); for (int j = 0; j < row.Count; j++) { string td = j == 0 ? "th" : "td"; if ((j == 0 || j == row.Count - 1) & i > 0) { if (j == row.Count - 1) { matrix.AppendFormat ("\t<{0} class='{1}' style='white-space: nowrap;'>", td, header_classes [i - 1]); } else { matrix.AppendFormat ("\t<{0} class='{1}'>", td, header_classes [i - 1]); } } else if (j >= result_index && row [j] != "-" && i > 0) { matrix.AppendFormat ("\t<{0} class='{1}'>", td, row [j]); } else { matrix.AppendFormat ("\t<{0}>", td); } matrix.AppendFormat (row [j]); matrix.AppendFormat ("</{0}>\n", td); } matrix.AppendLine ("</tr>"); } } matrix.AppendLine ("</table>"); } catch (Exception ex) { matrix.Append (ex.ToString ().Replace ("\n", "</br>")); } return matrix.ToString (); }
public string GenerateLane (GetViewWorkTableDataResponse response, DBLane lane, DBHost host, DBCommand command) { StringBuilder matrix = new StringBuilder (); List<DBWorkView2> steps; steps = response.WorkViews; matrix.AppendLine ("<table class='buildstatus'>"); matrix.AppendLine ("<tr>"); matrix.AppendLine ("\t<th>Revision</th>"); matrix.AppendLine ("\t<th>Start Time</th>"); matrix.AppendLine ("\t<th>Duration</th>");; matrix.AppendLine ("\t<th>Html report</th>"); matrix.AppendLine ("\t<th>Summary</th>"); matrix.AppendLine ("\t<th>Files</th>"); matrix.AppendLine ("</tr>"); for (int i = 0; i < steps.Count; i++) { DBWorkView2 view = steps [i]; List<DBWorkFileView> files = response.WorkFileViews [i]; DBState state = (DBState) view.state; matrix.Append ("<tr>"); // revision string result; switch (state) { case DBState.NotDone: result = "queued"; break; case DBState.Executing: result = "running"; break; case DBState.Failed: result = view.nonfatal ? "issues" : "failure"; break; case DBState.Success: case DBState.Aborted: case DBState.Timeout: case DBState.Paused: default: result =state.ToString ().ToLowerInvariant (); break; } // result matrix.AppendFormat ("\t<td class='{0}'><a href='ViewLane.aspx?lane_id={2}&host_id={3}&revision_id={4}'>{1}</a></td>", result, view.revision, lane.id, host.id, view.revision_id); if (state > DBState.NotDone && state != DBState.Paused && state != DBState.Ignore) { matrix.AppendFormat ("<td>{0}</td>", view.starttime.ToString ("yyyy/MM/dd HH:mm:ss UTC")); } else { matrix.AppendLine ("<td>-</td>"); } // duration matrix.Append ("\t<td>"); if (state >= DBState.Executing && state != DBState.Paused && state != DBState.Ignore) { matrix.Append ("["); matrix.Append (MonkeyWrench.Utilities.GetDurationFromWorkView (view).ToString ()); matrix.Append ("]"); } else { matrix.Append ("-"); } matrix.AppendLine ("</td>"); // html report matrix.AppendLine ("<td>"); DBWorkFileView index_html = null; foreach (DBWorkFileView file in files) { if (file.filename == "index.html") { index_html = file; break; } } if (index_html != null) { matrix.AppendFormat ("<a href='ViewHtmlReport.aspx?workfile_id={0}'>View html report</a>", index_html.id); } else { matrix.AppendLine ("-"); } matrix.AppendLine ("</td>"); // summary matrix.AppendLine ("<td>"); matrix.AppendLine (view.summary); matrix.AppendLine ("</td>"); matrix.AppendLine ("</tr>"); } matrix.AppendLine ("</table>"); return matrix.ToString (); }
private Dictionary<String, Object> BuildStatusFrom(int laneId, int revId, DBRevisionWork work, DBHost host) { if (host == null) throw new HttpException(404, "Build has not been assigned yet, cannot generate status."); var buildView = Utils.LocalWebService.GetViewLaneData (login, laneId, "", host.id, "", revId, ""); var steps = new List<Dictionary<String, Object>>(); for (int sidx = 0; sidx < buildView.WorkViews.Count; sidx++) { var step = buildView.WorkViews [sidx]; var files = buildView.WorkFileViews [sidx]; var links = buildView.Links.Where (l => l.work_id == step.id); steps.Add (BuildStepStatus (sidx, step, files, links)); } return new Dictionary<String, Object> { { "build_host", buildView.WorkHost.host }, { "build_host_id", buildView.WorkHost.id }, { "branch", MaxRevisionToBranch (buildView.Lane.max_revision) }, { "commit", buildView.Revision.revision }, { "completed", buildView.RevisionWork.completed }, { "end_time", work.endtime }, { "host", host.host }, { "host_id", host.id }, { "lane_id", laneId }, { "lane_name", buildView.Lane.lane }, { "revision_id", revId }, { "repository", buildView.Lane.repository }, { "start_time", buildView.WorkViews [0].starttime }, { "status", work.State.ToString ().ToLowerInvariant () }, { "steps", steps }, { "url", BuildLink (laneId, revId, host.id) } }; }
void GenerateActionLink(StringBuilder header, DBLane lane, DBHost host, DBRevision dbr, string cmd, string short_label, string long_label, bool hidden = false) { var href = confirmViewLaneAction(lane, host, dbr, cmd, short_label); if (hidden) header.AppendFormat("- <a style='{0}' href='{1}'>{2}</a>", "display:none", href, long_label); else header.AppendFormat("- <a href='{0}'>{1}</a>", href, long_label); }
public void EditHost (WebServiceLogin login, DBHost host) { //WebServiceResponse response = new WebServiceResponse (); using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.Administrator); host.Save (db); } }
/// <summary> /// Sets workhost to the specified host and saves it to the db. /// </summary> /// <param name="db"></param> /// <param name="host"></param> public static bool SetWorkHost (this DBRevisionWork rw, DB db, DBHost host) { object result; string update_cmd = string.Format (@"UPDATE RevisionWork SET workhost_id = {0} WHERE id = {1} AND workhost_id IS NULL;", host.id, rw.id); using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = update_cmd; var rv = cmd.ExecuteNonQuery (); if (rv != 1) { Logger.Log ("{0}: {1} (failed)", cmd.CommandText, rv); return false; } } using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = @" SELECT workhost_id FROM RevisionWork where id = @id AND workhost_id = @workhost_id; "; DB.CreateParameter (cmd, "workhost_id", host.id); DB.CreateParameter (cmd, "id", rw.id); result = cmd.ExecuteScalar (); if (result != null && (result is int || result is long)) { rw.workhost_id = host.id; Logger.Log ("{0}: {1} (succeeded)", update_cmd, result); return true; } Logger.Log ("{0}: {1} (failed 2)", update_cmd, result); return false; } }
private List<DBHost> GetSlaveHosts (DB db, DBHost host) { List<DBHost> result = null; using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT Host.* FROM Host INNER JOIN MasterHost ON MasterHost.host_id = Host.id WHERE MasterHost.master_host_id = @host_id"; DB.CreateParameter (cmd, "host_id", host.id); using (IDataReader reader = cmd.ExecuteReader ()) { while (reader.Read ()) { if (result == null) result = new List<DBHost> (); result.Add (new DBHost (reader)); } } } return result; }
/// <summary> /// Will return a locked revision work. /// </summary> /// <param name="lane"></param> /// <param name="host"></param> /// <returns></returns> public DBRevisionWork GetRevisionWork (DBLane lane, DBHost host, DBHost workhost) { DBRevisionWork result = null; using (IDbCommand cmd = CreateCommand ()) { // sorting by RevisionWork.workhost_id ensures that we'll get // revisionwork which has been started at the top of the list. cmd.CommandText = @" SELECT RevisionWork.* FROM RevisionWork INNER JOIN Revision ON RevisionWork.revision_id = Revision.id WHERE RevisionWork.host_id = @host_id AND (RevisionWork.workhost_id = @workhost_id OR RevisionWork.workhost_id IS NULL) AND RevisionWork.lane_id = @lane_id AND RevisionWork.state <> @dependencynotfulfilled AND RevisionWork.state <> 10 AND RevisionWork.State <> @ignore AND RevisionWork.completed = false ORDER BY RevisionWork.workhost_id IS NULL ASC, Revision.date DESC LIMIT 1 ;"; DB.CreateParameter (cmd, "host_id", host.id); DB.CreateParameter (cmd, "lane_id", lane.id); DB.CreateParameter (cmd, "workhost_id", workhost.id); DB.CreateParameter (cmd, "dependencynotfulfilled", (int) DBState.DependencyNotFulfilled); DB.CreateParameter (cmd, "ignore", (int) DBState.Ignore); using (IDataReader reader = cmd.ExecuteReader ()) { if (reader.Read ()) result = new DBRevisionWork (reader); } } return result; }
public static string GenerateHeader (GetViewLaneDataResponse response, DBLane lane, DBHost host, DBRevision revision, string description) { if (!Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) { return string.Format (@" <h2>{4} revision <a href='ViewLane.aspx?lane_id={0}&host_id={1}&revision_id={6}'>{5}</a> on lane '{2}' on '<a href='ViewHostHistory.aspx?host_id={1}'>{3}</a>' (<a href='ViewTable.aspx?lane_id={0}&host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, description, revision.revision, revision.id); } else { return string.Format (@" <h2>{4} revision <a href='ViewLane.aspx?lane_id={0}&host_id={1}&revision_id={6}'>{5}</a> on lane '<a href='EditLane.aspx?lane_id={0}'>{2}</a>' on '<a href='ViewHostHistory.aspx?host_id={1}'>{3}</a>' (<a href='ViewTable.aspx?lane_id={0}&host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, description, revision.revision, revision.id); } }
public DBHost LookupHost (string host, bool throwOnError) { DBHost result = null; using (IDbCommand cmd = CreateCommand ()) { cmd.CommandText = "SELECT * FROM Host WHERE host = @host"; DB.CreateParameter (cmd, "host", host); using (IDataReader reader = cmd.ExecuteReader ()) { if (!reader.Read ()) { if (!throwOnError) return null; throw new Exception (string.Format ("Could not find the host '{0}'.", host)); } result = new DBHost (reader); if (reader.Read ()) { if (!throwOnError) return null; throw new Exception (string.Format ("Found more than one host named '{0}'.", host)); } } } return result; }
public void EditHostWithPassword (WebServiceLogin login, DBHost host, string password) { using (DB db = new DB ()) { using (IDbTransaction transaction = db.BeginTransaction ()) { VerifyUserInRole (db, login, Roles.Administrator); var oldHost = FindHost (db, host.id, null); host.Save (db); // NOTE: it is possible to change the password of an existing account by creating // a host with the same name and specify the password. Given that admin rights // are required to create/modify hosts, it shouldn't pose a security issue. // TODO: if host changed name, delete the old user account. DBPerson person = FindPerson (db, host.host); if (person == null) { person = new DBPerson (); person.login = host.host; person.roles = Roles.BuildBot; } else { if (person.roles != Roles.BuildBot) throw new ArgumentException ("The hosts entry in the person table must have its roles set to 'BuildBot'."); } person.password = password; person.Save (db); transaction.Commit (); Audit (login, "edited host `{0}` -> `{1}`", Newtonsoft.Json.JsonConvert.SerializeObject(oldHost), Newtonsoft.Json.JsonConvert.SerializeObject(host) ); } } }
/// <summary> /// Finds pending steps for the current revision /// </summary> /// <returns></returns> public static List<DBWorkView2> GetNextWork (this DBRevisionWork rw, DB db, DBLane lane, DBHost host, DBRevision revision, bool multiple_work) { List<DBWorkView2> result = new List<DBWorkView2> (); ; if (revision == null) throw new ArgumentNullException ("revision"); if (lane == null) throw new ArgumentNullException ("lane"); if (host == null) throw new ArgumentNullException ("host"); rw.FilterPendingWork (db, db.GetWork (rw), result, multiple_work); if (result.Count == 0 && !rw.completed) { rw.completed = true; rw.UpdateState (db); } return result; }
private List<DBHost> GetMasterHosts (DB db, DBHost host) { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT Host.* FROM Host INNER JOIN MasterHost ON MasterHost.master_host_id = Host.id WHERE MasterHost.host_id = @host_id"; DB.CreateParameter (cmd, "host_id", host.id); using (IDataReader reader = cmd.ExecuteReader ()) { return DBRecord.LoadMany<DBHost> (reader); } } }
public static DBRevisionWork Find (DB db, DBLane lane, DBHost host, DBRevision revision) { DBRevisionWork result; using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT * FROM RevisionWork WHERE lane_id = @lane_id AND revision_id = @revision_id "; if (host != null) { cmd.CommandText += " AND host_id = @host_id;"; DB.CreateParameter (cmd, "host_id", host.id); } DB.CreateParameter (cmd, "lane_id", lane.id); DB.CreateParameter (cmd, "revision_id", revision.id); using (IDataReader reader = cmd.ExecuteReader ()) { if (!reader.Read ()) return null; result = new DBRevisionWork (reader); if (reader.Read ()) throw new ApplicationException (string.Format ("Found more than one revision work for the specified lane/host/revision ({0}/{1}/{2})", lane.lane, host == null ? "null" : host.host, revision.revision)); return result; } } }
public string GeneratePager (GetViewTableDataResponse response, DBLane lane, DBHost host, int page, int limit) { StringBuilder pager = new StringBuilder (); int total = response.Count; int pages = total / limit; if (total % limit != 0) pages++; Console.WriteLine ("Pages: {0} total: {1}", pages, total); if (page > pages - 1) page = pages - 1; int range = 5; pager.AppendFormat ("<p> Page "); if (pages < (range * 2)) { for (int i = 0; i < pages; i++) { pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit)); } } else { if (page <= (range + 1)) { for (int i = 0; i < (page + range); i++) { if (page == i) pager.Append (string.Format ("<b>{0}</b>", i + 1)); else pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit)); } pager.AppendFormat ("..."); pager.Append (GeneratePageLink (host.id, lane.id, pages - 2, limit)); pager.Append (GeneratePageLink (host.id, lane.id, pages - 1, limit)); } else if (page > (pages - range - 4)) { pager.Append (GeneratePageLink (host.id, lane.id, 1, limit)); pager.Append (GeneratePageLink (host.id, lane.id, 2, limit)); pager.AppendFormat ("..."); for (int i = page - range; i < pages; i++) { if (page == i) pager.Append (string.Format ("<b>{0}</b>", i + 1)); else pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit)); } } else { pager.Append (GeneratePageLink (host.id, lane.id, 1, limit)); pager.Append (GeneratePageLink (host.id, lane.id, 2, limit)); pager.AppendFormat ("..."); for (int i = page - range; i < page + range; i++) { if (page == i) pager.Append (string.Format ("<b>{0}</b>", i + 1)); else pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit)); } pager.AppendFormat ("..."); pager.Append (GeneratePageLink (host.id, lane.id, pages - 2, limit)); pager.Append (GeneratePageLink (host.id, lane.id, pages - 1, limit)); } } pager.AppendFormat ("</p>"); return pager.ToString (); }
/// <summary> /// Sets workhost to the specified host and saves it to the db. /// </summary> /// <param name="db"></param> /// <param name="host"></param> public static bool SetWorkHost (this DBRevisionWork rw, DB db, DBHost host) { object result; using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = @" UPDATE RevisionWork SET workhost_id = @workhost_id WHERE id = @id AND workhost_id IS NULL; SELECT workhost_id FROM RevisionWork where id = @id AND workhost_id = @workhost_id; "; DB.CreateParameter (cmd, "workhost_id", host.id); DB.CreateParameter (cmd, "id", rw.id); result = cmd.ExecuteScalar (); if (result != null && (result is int || result is long)) { rw.workhost_id = host.id; return true; } return false; } }
public string GenerateLaneTable (GetViewTableDataResponse response, DBLane lane, DBHost host, bool horizontal, int page, int limit) { StringBuilder matrix = new StringBuilder (); StringBuilder tooltip = new StringBuilder (); bool new_revision = true; int revision_id = 0; List<DBRevisionWorkView> views = response.RevisionWorkViews; List<List<TableNode>> table = new List<List<TableNode>> (); List<TableNode> row = new List<TableNode> (); List<TableNode> header = new List<TableNode> (); for (int i = 0; i < views.Count; i++) { while (header.Count <= views [i].sequence) { header.Add (null); } if (header [views [i].sequence] != null) continue; var node = new TableNode (string.Format ("<a href='ViewWorkTable.aspx?lane_id={0}&host_id={1}&command_id={2}'>{3}</a>", lane.id, host.id, views [i].command_id, views [i].command)); node.command_id = views [i].command_id; header [views [i].sequence] = node; } header.RemoveAll (delegate (TableNode match) { return match == null; }); header.Insert (0, new TableNode ("Revision", true)); header.Insert (1, new TableNode ("Diff", true)); header.Insert (2, new TableNode ("Author", true)); //if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) { // header.Insert (3, new TableNode ("Select", true)); //} header.Add (new TableNode ("Host", true)); header.Add (new TableNode ("Duration", true)); table.Add (header); bool failed = false; double duration = 0; for (int i = 0; i < views.Count; i++) { DBRevisionWorkView view = views [i]; DBState revisionwork_state = (DBState) view.revisionwork_state; DBState state = (DBState) view.state; new_revision = revision_id != view.revision_id; revision_id = view.revision_id; if (new_revision) { if (i > 0) { table.Add (row); row [row.Count - 1] = new TableNode (TimeSpan.FromSeconds (duration).ToString (), row [0].@class); } string revision = view.revision; long dummy; if (revision.Length > 16 && !long.TryParse (revision, out dummy)) revision = revision.Substring (0, 8); string clazz = revisionwork_state.ToString ().ToLower (); clazz = clazz + " " + DarkenColor (clazz, table.Count); row = new List<TableNode> (); tooltip.Length = 0; tooltip.AppendFormat ("Author: {0}.", view.author); if (view.starttime.Date.Year > 2000) tooltip.AppendFormat (" Build start date: {0}.", view.starttime.ToUniversalTime ().ToString ("yyyy/MM/dd HH:mm:ss UTC")); row.Add (new TableNode (string.Format ("<a href='ViewLane.aspx?lane_id={0}&host_id={1}&revision_id={2}' title='{4}'>{3}</a>", lane.id, host.id, view.revision_id, revision, tooltip.ToString ()), clazz)); row.Add (new TableNode (string.Format ("<a href='GetRevisionLog.aspx?id={0}'>diff</a>", view.revision_id))); row.Add (new TableNode (view.author)); //if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) // row.Add (new TableNode (string.Format ("<input type=checkbox id='id_revision_chk_{1}' name='revision_id_{0}' />", view.revision_id, i))); while (row.Count < header.Count - 2) row.Add (new TableNode ("-")); row.Add (new TableNode (view.workhost ?? "")); row.Add (new TableNode ("")); failed = false; duration = 0; } if (view.endtime > view.starttime) duration += (view.endtime - view.starttime).TotalSeconds; if (state == DBState.Failed && !view.nonfatal) failed = true; else if (revisionwork_state == DBState.Failed) failed = true; // result string result; bool completed = true; switch (state) { case DBState.NotDone: completed = false; result = failed ? "skipped" : "queued"; break; case DBState.Executing: completed = false; result = "running"; break; case DBState.Failed: result = view.nonfatal ? "issues" : "failure"; break; case DBState.Success: result = "success"; break; case DBState.Aborted: result = "aborted"; break; case DBState.Timeout: result = "timeout"; break; case DBState.Paused: completed = false; result = "paused"; break; case DBState.Ignore: completed = false; result = "ignore"; break; default: completed = true; result = "unknown"; break; } for (int j = 2; j < header.Count; j++) { if (header [j].command_id == view.command_id) { if (completed) { row [j] = new TableNode (string.Format ("<a href='{0}'>{1}</a>", Utilities.CreateWebServiceDownloadUrl (Request, view.id, view.command + ".log", true), result)); } else { row [j] = new TableNode (result); } row [j].@class = result + " " + DarkenColor (result, table.Count); break; } } } table.Add (row); row [row.Count - 1] = new TableNode (TimeSpan.FromSeconds (duration).ToString (), row [0].@class); matrix.AppendLine ("<table class='buildstatus'>"); if (horizontal) { for (int i = 0; i < header.Count; i++) { matrix.Append ("<tr>"); for (int j = 0; j < table.Count; j++) { TableNode node = table [j] [i]; string td = node.is_header ? "th" : "td"; matrix.Append ('<'); matrix.Append (td); if (node.@class != null) { matrix.Append (" class='"); matrix.Append (node.@class); matrix.Append ("'"); } /* if (node.style != null) { matrix.Append (" style='"); matrix.Append (node.style); matrix.Append ("'"); }*/ matrix.Append (">"); matrix.Append (node.text); matrix.Append ("</"); matrix.Append (td); matrix.Append (">"); } matrix.AppendLine ("</tr>"); } } else { for (int i = 0; i < table.Count; i++) { matrix.Append ("<tr>"); for (int j = 0; j < row.Count; j++) { TableNode node = table [i] [j]; string td = node.is_header ? "th" : "td"; matrix.Append ('<'); matrix.Append (td); if (node.@class != null) { matrix.Append (" class='"); matrix.Append (node.@class); matrix.Append ("'"); } /* if (node.style != null) { matrix.Append (" style='"); matrix.Append (node.style); matrix.Append ("'"); }*/ matrix.Append (">"); matrix.Append (node.text); matrix.Append ("</"); matrix.Append (td); matrix.Append (">"); } matrix.AppendLine ("</tr>"); } } matrix.AppendLine ("</table>"); return matrix.ToString (); }
public string GenerateLane (GetViewWorkTableDataResponse response, DBLane lane, DBHost host, DBCommand command) { StringBuilder matrix = new StringBuilder (); List<DBWorkView2> steps; DateTime beginning = new DateTime (2001, 1, 1, 0, 0, 0); steps = response.WorkViews; matrix.AppendLine ("<table class='buildstatus'>"); matrix.AppendLine ("<tr>"); matrix.AppendLine ("\t<th>Revision</th>"); matrix.AppendLine ("\t<th>Start Time</th>"); matrix.AppendLine ("\t<th>Duration</th>");; matrix.AppendLine ("\t<th>Html report</th>"); matrix.AppendLine ("\t<th>Summary</th>"); matrix.AppendLine ("\t<th>Files</th>"); matrix.AppendLine ("</tr>"); for (int i = 0; i < steps.Count; i++) { DBWorkView2 view = steps [i]; List<DBWorkFileView> files = response.WorkFileViews [i]; DBState state = (DBState) view.state; matrix.Append ("<tr>"); // revision string result; switch (state) { case DBState.NotDone: result = "queued"; break; case DBState.Executing: result = "running"; break; case DBState.Failed: result = view.nonfatal ? "issues" : "failure"; break; case DBState.Success: case DBState.Aborted: case DBState.Timeout: case DBState.Paused: default: result =state.ToString ().ToLowerInvariant (); break; } // result int file_id = 0; foreach (DBWorkFileView file in files) { if (!file.filename.StartsWith (view.command)) continue; file_id = file.id; break; } if (file_id == 0) { matrix.AppendFormat ("\t<td class='{0}'>{1}</td>", result, view.revision); } else { matrix.AppendFormat ("\t<td class='{0}'><a href='GetFile.aspx?id={2}'>{1}</a></td>", result, view.revision, file_id); } if (state > DBState.NotDone && state != DBState.Paused) { matrix.AppendFormat ("<td>{0}</td>", view.starttime.ToString ("yyyy/MM/dd HH:mm:ss UTC")); } else { matrix.AppendLine ("<td>-</td>"); } // duration DateTime starttime = view.starttime.ToLocalTime (); DateTime endtime = view.endtime.ToLocalTime (); int duration = (int) (endtime - starttime).TotalSeconds; matrix.Append ("\t<td>"); if (state >= DBState.Executing && state != DBState.Paused) { matrix.Append ("["); matrix.Append (TimeSpan.FromSeconds (duration).ToString ()); matrix.Append ("]"); } else { matrix.Append ("-"); } matrix.AppendLine ("</td>"); // html report matrix.AppendLine ("<td>"); DBWorkFileView index_html = null; foreach (DBWorkFileView file in files) { if (file.filename == "index.html") { index_html = file; break; } } if (index_html != null) { matrix.AppendFormat ("<a href='ViewHtmlReport.aspx?workfile_id={0}'>View html report</a>", index_html.id); } else { matrix.AppendLine ("-"); } matrix.AppendLine ("</td>"); // summary matrix.AppendLine ("<td>"); matrix.AppendLine (view.summary); matrix.AppendLine ("</td>"); matrix.AppendLine ("</tr>"); } matrix.AppendLine ("</table>"); return matrix.ToString (); }