From 1dccc3dd3c6ad61890ec67e9fcb5eaf6fd71817a Mon Sep 17 00:00:00 2001 From: BasiliusCarver Date: Wed, 1 Jun 2022 22:32:23 +1200 Subject: [PATCH] Add a janky way of running a WPR trace to capture some HCS calls --- Data/HnsDatasource.cs | 50 +++++++++- SummaryForm.Designer.cs | 73 ++++++++++---- SummaryForm.cs | 214 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 312 insertions(+), 25 deletions(-) diff --git a/Data/HnsDatasource.cs b/Data/HnsDatasource.cs index 4f61435..862bb75 100644 --- a/Data/HnsDatasource.cs +++ b/Data/HnsDatasource.cs @@ -18,17 +18,19 @@ public class HnsDatasource public string ExportDataSnapshot { get; private set; } public TreeNode RoutesNode { get; private set; } + public TreeNode ContainerdNode { get; private set; } public TreeNode ActivitiesNode { get; private set; } public TreeNode OrphansNode { get; private set; } public HnsDatasource() { NumberOfStepsLoaded = 0; - NumberOfStepsTotal = 20; + NumberOfStepsTotal = 21; LoadingState = "Initialised"; SummaryOutput = "No data"; ExportDataSnapshot = "{}"; RoutesNode = new TreeNode(); + ContainerdNode = new TreeNode(); ActivitiesNode = new TreeNode(); OrphansNode = new TreeNode(); } @@ -48,6 +50,7 @@ public void Reset() SummaryOutput = "No data"; ExportDataSnapshot = "{}"; RoutesNode = new TreeNode(); + ContainerdNode = new TreeNode(); ActivitiesNode = new TreeNode(); OrphansNode = new TreeNode(); } @@ -91,6 +94,44 @@ public void Load() Tag = hostRouteList }; + UpdateLoadingState("Getting containerd config..."); + var config = "C:\\Program Files\\containerd\\config.toml"; + var log = "C:\\ProgramData\\containerd\\root\\panic.log"; + if (File.Exists(config) || File.Exists(log)) + { + ContainerdNode = new TreeNode + { + Text = "ContainerD", + Tag = "ContainerD config and logging" + }; + + if(File.Exists(config)) + { + using (var fileStream = new FileStream(config, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (var textReader = new StreamReader(fileStream)) + { + ContainerdNode.Nodes.Add(new TreeNode + { + Text = "Config", + Tag = textReader.ReadToEnd() + }); + } + } + + if (File.Exists(log)) + { + using (var fileStream = new FileStream(log, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (var textReader = new StreamReader(fileStream)) + { + ContainerdNode.Nodes.Add(new TreeNode + { + Text = "Logging", + Tag = string.Join("\n\n", textReader.ReadToEnd().Split('\n')) + }); + } + } + } + ActivitiesNode = new TreeNode { Text = "Activities", @@ -129,7 +170,11 @@ public void Load() orphanedCompute = ActivitiesNode.Nodes.InsertChildrenWithMatchingParentReference(orphanedCompute, endpointData, "Id", "ID", "SharedContainers", "Container", "Owner"); UpdateLoadingState("Building orphan tree..."); - OrphansNode = new TreeNode("Orphaned Data"); + OrphansNode = new TreeNode + { + Text = "Orphaned Data", + Tag = "Data that can't easily be mapped to a node in the HNS activity list" + }; OrphansNode.Nodes.InsertChildren(orphanedNamesaces, "ID", "Namespace", "ID"); OrphansNode.Nodes.InsertChildren(orphanedActivities, "ID", "Activities", "Allocators.Tag"); OrphansNode.Nodes.InsertChildren(orphanedNetworks, "ID", "Network", "Name"); @@ -154,6 +199,7 @@ public void Load() { allData.Add("Routes", routeJsonElement); } + // not exporting config cbf ExportDataSnapshot = JsonSerializer.Serialize(allData); UpdateLoadingState("Done"); } diff --git a/SummaryForm.Designer.cs b/SummaryForm.Designer.cs index 30c0d81..46ecc89 100644 --- a/SummaryForm.Designer.cs +++ b/SummaryForm.Designer.cs @@ -35,6 +35,8 @@ protected override void OnLoad(EventArgs e) this.button3.BackColor = Program.ACTIVE_COLOR_BACKGROUND_WINDOW; this.button4.ForeColor = Program.ACTIVE_COLOR_FOREGROUND; this.button4.BackColor = Program.ACTIVE_COLOR_BACKGROUND_WINDOW; + this.button5.ForeColor = Program.ACTIVE_COLOR_FOREGROUND; + this.button5.BackColor = Program.ACTIVE_COLOR_BACKGROUND_WINDOW; this.button1.FlatAppearance.BorderColor = Program.ACTIVE_COLOR_FOREGROUND; this.button1.FlatAppearance.MouseOverBackColor = Program.ACTIVE_COLOR_BUTTON_HOVER; @@ -52,6 +54,10 @@ protected override void OnLoad(EventArgs e) this.button4.FlatAppearance.MouseOverBackColor = Program.ACTIVE_COLOR_BUTTON_HOVER; this.button4.FlatAppearance.MouseDownBackColor = Program.ACTIVE_COLOR_BUTTON_DOWN; + this.button5.FlatAppearance.BorderColor = Program.ACTIVE_COLOR_FOREGROUND; + this.button5.FlatAppearance.MouseOverBackColor = Program.ACTIVE_COLOR_BUTTON_HOVER; + this.button5.FlatAppearance.MouseDownBackColor = Program.ACTIVE_COLOR_BUTTON_DOWN; + this.BackColor = Program.ACTIVE_COLOR_BACKGROUND_WINDOW; this.treeView1.ForeColor = Program.ACTIVE_COLOR_FOREGROUND; @@ -85,6 +91,7 @@ private void InitializeComponent() this.button2 = new System.Windows.Forms.Button(); this.button3 = new System.Windows.Forms.Button(); this.button4 = new System.Windows.Forms.Button(); + this.button5 = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); @@ -99,9 +106,10 @@ private void InitializeComponent() this.button1.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74))))); this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.button1.ForeColor = System.Drawing.Color.White; - this.button1.Location = new System.Drawing.Point(384, 14); + this.button1.Location = new System.Drawing.Point(581, 19); + this.button1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.button1.Name = "button1"; - this.button1.Size = new System.Drawing.Size(110, 23); + this.button1.Size = new System.Drawing.Size(126, 31); this.button1.TabIndex = 0; this.button1.Text = "Reload HNS Data"; this.button1.UseVisualStyleBackColor = false; @@ -114,8 +122,9 @@ private void InitializeComponent() this.treeView1.Dock = System.Windows.Forms.DockStyle.Fill; this.treeView1.ForeColor = System.Drawing.SystemColors.Window; this.treeView1.Location = new System.Drawing.Point(0, 0); + this.treeView1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.treeView1.Name = "treeView1"; - this.treeView1.Size = new System.Drawing.Size(367, 472); + this.treeView1.Size = new System.Drawing.Size(419, 629); this.treeView1.TabIndex = 2; this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect); // @@ -128,16 +137,18 @@ private void InitializeComponent() this.richTextBox1.Font = new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.richTextBox1.ForeColor = System.Drawing.SystemColors.Window; this.richTextBox1.Location = new System.Drawing.Point(0, 0); + this.richTextBox1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.richTextBox1.Name = "richTextBox1"; this.richTextBox1.ReadOnly = true; - this.richTextBox1.Size = new System.Drawing.Size(730, 472); + this.richTextBox1.Size = new System.Drawing.Size(834, 629); this.richTextBox1.TabIndex = 3; this.richTextBox1.Text = ""; this.richTextBox1.TextChanged += new System.EventHandler(this.richTextBox1_TextChanged); // // splitContainer1 // - this.splitContainer1.Location = new System.Drawing.Point(12, 51); + this.splitContainer1.Location = new System.Drawing.Point(14, 68); + this.splitContainer1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 @@ -147,18 +158,19 @@ private void InitializeComponent() // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.richTextBox1); - this.splitContainer1.Size = new System.Drawing.Size(1101, 472); - this.splitContainer1.SplitterDistance = 367; + this.splitContainer1.Size = new System.Drawing.Size(1258, 629); + this.splitContainer1.SplitterDistance = 419; + this.splitContainer1.SplitterWidth = 5; this.splitContainer1.TabIndex = 4; // // textBox1 // this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.textBox1.CausesValidation = false; - this.textBox1.Location = new System.Drawing.Point(510, 14); - this.textBox1.Margin = new System.Windows.Forms.Padding(30, 3, 3, 3); + this.textBox1.Location = new System.Drawing.Point(722, 19); + this.textBox1.Margin = new System.Windows.Forms.Padding(34, 4, 3, 4); this.textBox1.Name = "textBox1"; - this.textBox1.Size = new System.Drawing.Size(277, 23); + this.textBox1.Size = new System.Drawing.Size(316, 27); this.textBox1.TabIndex = 5; this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged_1); // @@ -170,9 +182,10 @@ private void InitializeComponent() this.button2.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74))))); this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.button2.ForeColor = System.Drawing.Color.White; - this.button2.Location = new System.Drawing.Point(14, 14); + this.button2.Location = new System.Drawing.Point(16, 19); + this.button2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(110, 23); + this.button2.Size = new System.Drawing.Size(126, 31); this.button2.TabIndex = 6; this.button2.Text = "Expand All"; this.button2.UseVisualStyleBackColor = false; @@ -186,9 +199,10 @@ private void InitializeComponent() this.button3.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74))))); this.button3.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.button3.ForeColor = System.Drawing.Color.White; - this.button3.Location = new System.Drawing.Point(137, 14); + this.button3.Location = new System.Drawing.Point(157, 19); + this.button3.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.button3.Name = "button3"; - this.button3.Size = new System.Drawing.Size(110, 23); + this.button3.Size = new System.Drawing.Size(126, 31); this.button3.TabIndex = 7; this.button3.Text = "Dump to JSON"; this.button3.UseVisualStyleBackColor = false; @@ -202,20 +216,39 @@ private void InitializeComponent() this.button4.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74))))); this.button4.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.button4.ForeColor = System.Drawing.Color.White; - this.button4.Location = new System.Drawing.Point(261, 14); + this.button4.Location = new System.Drawing.Point(298, 19); + this.button4.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.button4.Name = "button4"; - this.button4.Size = new System.Drawing.Size(110, 23); + this.button4.Size = new System.Drawing.Size(126, 31); this.button4.TabIndex = 8; this.button4.Text = "Packet Capture"; this.button4.UseVisualStyleBackColor = false; this.button4.Click += new System.EventHandler(this.button4_Click); // + // button5 + // + this.button5.BackColor = System.Drawing.Color.DimGray; + this.button5.FlatAppearance.BorderColor = System.Drawing.Color.LightGray; + this.button5.FlatAppearance.MouseDownBackColor = System.Drawing.Color.DimGray; + this.button5.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74))))); + this.button5.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.button5.ForeColor = System.Drawing.Color.White; + this.button5.Location = new System.Drawing.Point(439, 19); + this.button5.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); + this.button5.Name = "button5"; + this.button5.Size = new System.Drawing.Size(126, 31); + this.button5.TabIndex = 9; + this.button5.Text = "HCS Capture"; + this.button5.UseVisualStyleBackColor = false; + this.button5.Click += new System.EventHandler(this.button5_Click); + // // SummaryForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.SystemColors.WindowFrame; - this.ClientSize = new System.Drawing.Size(1234, 553); + this.ClientSize = new System.Drawing.Size(1410, 737); + this.Controls.Add(this.button5); this.Controls.Add(this.button4); this.Controls.Add(this.button3); this.Controls.Add(this.button2); @@ -223,7 +256,8 @@ private void InitializeComponent() this.Controls.Add(this.splitContainer1); this.Controls.Add(this.button1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MinimumSize = new System.Drawing.Size(815, 0); + this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); + this.MinimumSize = new System.Drawing.Size(929, 47); this.Name = "SummaryForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Form1"; @@ -247,4 +281,5 @@ private void InitializeComponent() private Button button2; private Button button3; private Button button4; + private Button button5; } diff --git a/SummaryForm.cs b/SummaryForm.cs index fbaaf36..fdcd936 100644 --- a/SummaryForm.cs +++ b/SummaryForm.cs @@ -50,6 +50,11 @@ private void LoadTreeview() { treeView1.Nodes.Add(datasource.OrphansNode); } + + if (datasource.ContainerdNode.Nodes.Count > 0) + { + treeView1.Nodes.Add(datasource.ContainerdNode); + } } private void button1_Click(object sender, EventArgs e) @@ -97,6 +102,7 @@ private void HighlightSearchTerms(RichTextBox richTextBox) return; } richTextBox.SelectAll(); + richTextBox.SelectionColor = richTextBox.ForeColor; richTextBox.SelectionBackColor = richTextBox.BackColor; var searchIndex = richTextBox.Text.IndexOf(textBox1.Text, StringComparison.OrdinalIgnoreCase); var firstSearchIndex = searchIndex; @@ -135,6 +141,7 @@ private void CheckEnterKeyPress(object? sender, KeyPressEventArgs e) ClearSearchResults(treeView1.Nodes); SearchRecursive(treeView1.Nodes, textBox1.Text); SelectFirst(treeView1.Nodes, textBox1.Text); + HighlightSearchTerms(richTextBox1); } } @@ -252,7 +259,7 @@ private void button4_Click(object sender, EventArgs e) if($null -eq $pktmon) { Write-Host -ForegroundColor Red 'The executable pktmon is not available in the PATH on this system' Write-Host -ForegroundColor Red 'https://docs.microsoft.com/en-us/windows-server/networking/technologies/pktmon/pktmon' - Write-Host -ForegroundColor Red -NoNewline ""`nPress ENTER to close this window"" + Write-Host -ForegroundColor Red -NoNewline ""`nPress ENTER to close this window "" Read-Host exit } @@ -260,7 +267,7 @@ private void button4_Click(object sender, EventArgs e) while ($pktmonBusy) { Write-Warning 'There is already a pktmon trace running, try again when this one is complete' Write-Host -ForegroundColor Yellow (Invoke-Expression 'pktmon status' | Out-String) - Write-Host -ForegroundColor Yellow -NoNewline ""`nPress ENTER to try again"" + Write-Host -ForegroundColor Yellow -NoNewline ""`nPress ENTER to try again "" Read-Host $pktmonBusy = pktmon status | Where-Object { $_ -notlike '*not running*' } } @@ -287,7 +294,7 @@ private void button4_Click(object sender, EventArgs e) Write-Host ""Running '$command'"" Invoke-Expression $command - Write-Host -ForegroundColor Cyan -NoNewline ""`nTrace is recording, press ENTER to stop"" + Write-Host -ForegroundColor Cyan -NoNewline ""`nTrace is recording, press ENTER to stop "" Read-Host $command = 'pktmon stop' Write-Host ""Running '$command'"" @@ -298,7 +305,7 @@ private void button4_Click(object sender, EventArgs e) Invoke-Expression $command Write-Host -ForegroundColor Cyan ""`nTrace data is available at:`n '$($filename -replace '\.etl$', '.pcapng')'"" - Write-Host -ForegroundColor Cyan -NoNewline ""`nPress ENTER to close this window"" + Write-Host -ForegroundColor Cyan -NoNewline ""`nPress ENTER to close this window "" Read-Host "; ProcessStartInfo startInfo = new ProcessStartInfo(path); @@ -308,4 +315,203 @@ private void button4_Click(object sender, EventArgs e) startInfo.UseShellExecute = true; Process.Start(startInfo); } + + private void button5_Click(object sender, EventArgs e) + { + var path = @"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"; + var hcsTraceScript = @" + Write-Host -ForegroundColor DarkRed ' __ __ _____ _ ' + Write-Host -ForegroundColor DarkRed ' /\ /\/\ \ \/ _\ / ___/ ___ __ | | ___ _ __ ___ _ __ ' + Write-Host -ForegroundColor Red ' / /_/ / \/ /\ \ / __\ \/ / ''_ \| |/ _ \| ''__/ _ \ ''__|' + Write-Host -ForegroundColor Red '/ __ / /\ / _\ \ / /___> <| |_) | | (_) | | | __/ | ' + Write-Host -ForegroundColor White '\/ /_/\_\ \/ \__/ \ ___/_/\_\ .__/|_|\___/|_| \___|_| ' + Write-Host -ForegroundColor White ' |_| ' + + Write-Host -ForegroundColor DarkRed 'Using Windows Performance Recorder to capture an ETL trace' + $wpr = Get-Command 'wpr.exe' -ErrorAction 'SilentlyContinue' + if($null -eq $wpr) { + Write-Host -ForegroundColor Red 'The executable wpr.exe is not available in the PATH on this system' + Write-Host -ForegroundColor Red 'https://docs.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-recorder' + Write-Host -ForegroundColor Red -NoNewline ""`nPress ENTER to close this window "" + Read-Host + exit + } + $wprAvailable = wpr.exe -status | Where-Object { $_ -like '*is not recording*' } + while (!$wprAvailable) { + Write-Warning 'There is already a wpr.exe session running, try again when this one is complete' + Write-Host -ForegroundColor Yellow (Invoke-Expression 'wpr.exe -status' | Out-String) + Write-Host -ForegroundColor Yellow -NoNewline ""`nPress ENTER to try again "" + Read-Host + $wprAvailable = wpr.exe -status | Where-Object { $_ -like '*is not recording*' } + } + + $traceConfig = "" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"" + $profilePath = ""$(pwd)\wpr_profile.wprp"" + Set-Content -Force -Path $profilePath -Value $traceConfig + + $filename = ""$(pwd)\wpr_$((Get-Date).ToFileTime()).etl"" + $command = ""wpr.exe -start $profilePath!HcsArgon -start $profilePath!HcsWithHvSocket -start $profilePath!HcsWer -filemode"" + Write-Host ""Trace command is:`n'$command'"" + Write-Host -NoNewline ""Press ENTER to start the trace "" + Read-Host + Invoke-Expression $command + + Write-Host -ForegroundColor DarkRed -NoNewline ""`nTrace is recording, press ENTER to stop "" + Read-Host + $command = ""wpr.exe -stop `""$filename`"" `""Automated HCS trace from HNS explorer`"""" + Write-Host ""Running '$command'"" + Invoke-Expression $command + + if((Get-Command 'wpa.exe' -ErrorAction 'SilentlyContinue')) { + $command = ""wpa.exe `""$filename`"""" + Write-Host ""Running '$command'"" + Invoke-Expression $command + } else { + Write-Host 'Windows Performance Analyzer is not installed, you need to install it to view the trace file' + Write-Host 'https://docs.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-analyzer' + } + + Write-Host -ForegroundColor DarkRed ""`nTrace is saved at '$filename' to be opened by Windows Performance Analyzer"" + Write-Host -ForegroundColor DarkRed -NoNewline ""`nPress ENTER to close this window "" + Read-Host + "; + + ProcessStartInfo startInfo = new ProcessStartInfo(path); + startInfo.WorkingDirectory = Directory.GetCurrentDirectory(); + startInfo.ArgumentList.Add("-C"); + startInfo.ArgumentList.Add(hcsTraceScript); + startInfo.UseShellExecute = true; + Process.Start(startInfo); + } }