<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bharath Nelapatla</title>
    <description>The latest articles on DEV Community by Bharath Nelapatla (@bharath_nelapatla_trainer).</description>
    <link>https://dev.to/bharath_nelapatla_trainer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1519451%2Fb3502ef4-7072-4b41-93fd-dc3158a9aebd.png</url>
      <title>DEV Community: Bharath Nelapatla</title>
      <link>https://dev.to/bharath_nelapatla_trainer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bharath_nelapatla_trainer"/>
    <language>en</language>
    <item>
      <title>Reviving My Linux Mastery Game from a Merge Conflict — A Finish-Up-A-Thon Comeback</title>
      <dc:creator>Bharath Nelapatla</dc:creator>
      <pubDate>Mon, 25 May 2026 11:20:33 +0000</pubDate>
      <link>https://dev.to/bharath_nelapatla_trainer/eviving-my-linux-mastery-game-from-a-merge-conflict-a-finish-up-a-thon-comeback-kdo</link>
      <guid>https://dev.to/bharath_nelapatla_trainer/eviving-my-linux-mastery-game-from-a-merge-conflict-a-finish-up-a-thon-comeback-kdo</guid>
      <description>&lt;p&gt;*This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge*&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Enterprise Linux Mastery Game&lt;/strong&gt; — a local-first, AI-mentored terminal game for practicing real enterprise Linux administration. The mentor sets a scenario (a paging-hour incident, a permissions puzzle, a 5xx spike). You type Linux commands. They run inside a hardened Docker sandbox. An AI judge grades you on &lt;strong&gt;correctness, safety, and efficiency&lt;/strong&gt; and gives coaching feedback.&lt;/p&gt;

&lt;p&gt;I started it as a January side-project that I genuinely cared about — I work in enterprise IT training and I've watched too many engineers learn Linux the wrong way, by memorising commands instead of investigating systems. The game was meant to fix that for myself and the trainees I work with.&lt;/p&gt;

&lt;p&gt;Then I hit a wall. The repo sat for four months with a visible merge conflict in the README and a backend wired to a paid LLM API I'd lost access to. The Finish-Up-A-Thon was the push I needed to actually finish it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://www.google.com/url?sa=E&amp;amp;source=gmail&amp;amp;q=https://github.com/Bharathtrainer/Linux-game" rel="noopener noreferrer"&gt;https://github.com/Bharathtrainer/Linux-game&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture:&lt;/strong&gt; FastAPI + Ollama (Llama 3.1) + Docker sandbox + YAML scenarios + a CLI client. Everything runs locally. No cloud API key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;A real play session captured tonight. Player picks the &lt;strong&gt;entry&lt;/strong&gt; level, investigates a "/var disk filling up" scenario inside the sandbox, and gets a graded verdict from the AI judge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63qgvf1vloiz6h3fzsvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63qgvf1vloiz6h3fzsvm.png" alt="Judge verdict with three-axis scoring" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The judge scored this run 84/100 — three correct investigation commands, perfect safety, near-perfect efficiency. The coaching identifies one specific improvement: running &lt;code&gt;du&lt;/code&gt; on the directory directly instead of its contents.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;================================================================
================ ENTERPRISE LINUX MASTERY GAME =================
Local-first. AI-mentored. Sandboxed.
Levels:

entry
operator
engineer
sre
Pick a level number: 1
Starting mission for player1 @ level=entry...
Production server: disk filling fast
An alert just paged you. The /var partition on a production app server
is at 96% and climbing. The on-call engineer needs to know what's
eating the space before the disk fills and the application crashes.
You have shell access. No need to delete anything yet — first, find
the offender.
Objective: Identify which directory or file is consuming the most
space under /var.
Commands: type a shell command, or one of:
/hint    — ask the mentor for a Socratic hint
/done    — submit your attempts for grading
/quit    — give up and exit
[entry] $ ls -la /tmp/sandbox/var
total 20
drwxr-xr-x 5 sandbox sandbox 4096 May 25 08:31 .
drwxr-xr-x 3 sandbox sandbox 4096 May 25 08:31 ..
drwxr-xr-x 2 sandbox sandbox 4096 May 25 08:31 cache
drwxr-xr-x 2 sandbox sandbox 4096 May 25 08:31 lib
drwxr-xr-x 2 sandbox sandbox 4096 May 25 08:31 log
[exit 0]
[entry] $ du -sh /tmp/sandbox/var/*
8.0K    /tmp/sandbox/var/cache
8.0K    /tmp/sandbox/var/lib
81M     /tmp/sandbox/var/log
[exit 0]
[entry] $ du -h /tmp/sandbox/var/log/app.log
80M     /tmp/sandbox/var/log/app.log
[exit 0]
[entry] $ /done
Grading...

================================================================
============================ RESULT ============================
Verdict:     Good start, but you haven't yet identified the
largest file.
Solved:      False
Score:       84/100
Correctness: 8/10
Safety:      10/10
Efficiency:  9/10
Coaching:
Your first command was a good investigation step. The second
command effectively used du to find large directories under
/var/log. However, it would be more efficient to use du on
the log directory directly instead of its contents. Remember
that -h is not needed for this specific scenario.

Missed concepts: du, directory vs file

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The judge is appropriately strict — the player identified the large file but didn't actually confirm the answer with a more decisive command. That kind of nuanced grading is what makes this useful for training rather than just gamification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Bharathtrainer/Linux-game
&lt;span class="nb"&gt;cd &lt;/span&gt;Linux-game
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; linux-mastery-sandbox sandbox/
ollama pull llama3.1
&lt;span class="nb"&gt;cd &lt;/span&gt;backend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; uvicorn main:app &lt;span class="nt"&gt;--reload&lt;/span&gt;

&lt;span class="c"&gt;# In a second terminal:&lt;/span&gt;
python play.py

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Where the project was before this week:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;README.md had &lt;strong&gt;unresolved git merge conflict markers&lt;/strong&gt; visible right on the GitHub landing page (&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; and everything in between). Anyone clicking the repo saw raw conflict markup as the first thing.&lt;/li&gt;
&lt;li&gt;The backend was hard-wired to &lt;strong&gt;NVIDIA NIM&lt;/strong&gt;, a paid LLM service I'd lost access to. Without those env vars every endpoint 500'd.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;core/sandbox.py&lt;/code&gt; file — the literal heart of the game, the thing that runs user commands safely — &lt;strong&gt;did not exist&lt;/strong&gt;. The judge endpoint was scoring imaginary commands.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;api/mission.py&lt;/code&gt; was a single stub that returned &lt;code&gt;"Mission started"&lt;/code&gt; and did nothing.&lt;/li&gt;
&lt;li&gt;Two empty files named &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt; sat at the repo root, debris from a fat-fingered shell redirect months ago.&lt;/li&gt;
&lt;li&gt;Only one scenario YAML existed, with four fields. No challenge text, no setup script, no success criteria.&lt;/li&gt;
&lt;li&gt;The mentor and judge prompts were three lines each. No JSON schema. No grading rubric.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looked 30% done. It was actually closer to 10%, because the missing pieces were the load-bearing ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I changed, in commits that read like a story:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Resolve the merge conflict and clean up debris.&lt;/strong&gt; Fixed the README, deleted the empty artifact files, added a &lt;code&gt;THE_COMEBACK.md&lt;/code&gt; for the full revival log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap NVIDIA NIM for local Ollama.&lt;/strong&gt; Renamed &lt;code&gt;core/nim_client.py&lt;/code&gt; → &lt;code&gt;core/llm_client.py&lt;/code&gt;. Default provider is Ollama (free, local, no key). Kept NIM as a fallback via &lt;code&gt;LLM_PROVIDER=nim&lt;/code&gt;. Mapped legacy NIM model names to Llama 3.1 so older callers don't break.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add the missing sandbox runner.&lt;/strong&gt; Wrote &lt;code&gt;core/sandbox.py&lt;/code&gt; — a one-shot Docker runner with &lt;code&gt;--network=none&lt;/code&gt;, memory and CPU limits, a per-command timeout, and a non-root user (UID 1000). The security boundary of the entire game.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build the real game loop and ground the prompts.&lt;/strong&gt; Rewrote &lt;code&gt;api/mission.py&lt;/code&gt; as a proper orchestrator (&lt;code&gt;/start&lt;/code&gt;, &lt;code&gt;/run&lt;/code&gt;, &lt;code&gt;/finish&lt;/code&gt;). Pinned a three-axis grading rubric in the judge prompt. Added three new scenario YAMLs (&lt;code&gt;operator_runaway_process&lt;/code&gt;, &lt;code&gt;engineer_permissions&lt;/code&gt;, &lt;code&gt;sre_log_triage&lt;/code&gt;) with real challenge narratives — the part of this project no AI could write for me, because it requires actually knowing which enterprise Linux problems happen in the wild.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI client and polished README.&lt;/strong&gt; Wrote &lt;code&gt;play.py&lt;/code&gt; to make the game playable. Added an architecture diagram, quickstart, screenshots, and a transcript of a real play session.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can see the whole arc in &lt;a href="https://github.com/Bharathtrainer/Linux-game/commits/main" rel="noopener noreferrer"&gt;the commit history&lt;/a&gt;. Importantly, the unresolved merge conflict is still visible in &lt;a href="https://github.com/Bharathtrainer/Linux-game/blob/aed0242/README.md" rel="noopener noreferrer"&gt;the historical README at commit aed0242&lt;/a&gt; — anyone who wants to verify the "before" state was real can see it for themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Side projects die in the gap between &lt;em&gt;almost demoable&lt;/em&gt; and &lt;em&gt;actually playable&lt;/em&gt;. The commits above are mostly boring glue — subprocess wrappers, Pydantic models, JSON parsers, a CLI loop. None of it was hard. All of it was the kind of work I'd previously dropped because "the interesting part is done." The Finish-Up-A-Thon framing helped me see the gap for what it really was: not missing capability, just missing patience for the unglamorous middle.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;Three places Copilot did real, specific work — not generic autocomplete:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Resolving the merge conflict.&lt;/strong&gt; I opened the broken README in VS Code and asked Copilot Chat:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Resolve this Git merge conflict in this README. Keep the richer 'Enterprise Linux Mastery Game' content but make it the start of a real README — add sections for what it does, quickstart, and configuration."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It produced a clean draft I then edited for the Ollama specifics. Faster than reading both sides and hand-merging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Mapping the legacy NIM model names to Ollama tags.&lt;/strong&gt; I gave Copilot the original &lt;code&gt;model_router.py&lt;/code&gt; and asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"These three NIM-specific model identifiers need to map to Ollama tags. Generate a fallback mapping that defaults to llama3.1 when an exact match isn't available, and keep the level→model selection logic intact."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;_resolve_model_alias&lt;/code&gt; method in &lt;code&gt;llm_client.py&lt;/code&gt; came out of that interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Drafting the sandbox runner.&lt;/strong&gt; This was the most useful one. I described what I wanted:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Write a Python function that runs a shell command inside a one-shot Docker container using the docker CLI via subprocess. Hard timeout, no network, memory and CPU limits, runs as UID 1000. Return a dataclass with stdout, stderr, exit_code, and a &lt;code&gt;timed_out&lt;/code&gt; flag."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Copilot drafted the structure including the &lt;code&gt;subprocess.TimeoutExpired&lt;/code&gt; handling I would have forgotten. I added the &lt;code&gt;sandbox_image_exists()&lt;/code&gt; health check and the &lt;code&gt;FileNotFoundError&lt;/code&gt; branch for "Docker not installed."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where Copilot specifically didn't help — and I want to be honest about this:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It didn't write the scenario YAMLs.&lt;/strong&gt; Those needed domain knowledge about which enterprise Linux problems are pedagogically valuable. Generic AI-written scenarios would have read like textbook exercises. The disk-full, runaway-process, permissions-puzzle, and log-triage scenarios are based on real incidents I've coached trainees through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It didn't write the judge rubric.&lt;/strong&gt; The three-axis scoring (correctness 60% / safety 25% / efficiency 15%) reflects how I actually evaluate engineers, not how an LLM thinks grading should work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It didn't make the architectural call&lt;/strong&gt; to keep &lt;code&gt;NIMClient&lt;/code&gt; as a backward-compatible alias rather than ripping it out. That was a judgement call to keep the commit diff small and reviewable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest version of "how Copilot helped" is: it removed the friction of writing boilerplate — &lt;code&gt;subprocess&lt;/code&gt; glue, Pydantic models, JSON parsing helpers — so I could spend my limited attention on the parts only I could do. For a side project being revived under time pressure, that ratio of "boring code automated, judgement work preserved" is exactly the right one.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://github.com/Bharathtrainer/Linux-game/blob/main/THE_COMEBACK.md" rel="noopener noreferrer"&gt;&lt;code&gt;THE_COMEBACK.md&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>ai</category>
      <category>ghfinishupathon</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>OpenShift Virtualization Migration Advisor — Local-First, Powered by Gemma 4 26B MoE</title>
      <dc:creator>Bharath Nelapatla</dc:creator>
      <pubDate>Mon, 25 May 2026 07:07:29 +0000</pubDate>
      <link>https://dev.to/bharath_nelapatla_trainer/openshift-virtualization-migration-advisor-local-first-powered-by-gemma-4-26b-moe-1ohm</link>
      <guid>https://dev.to/bharath_nelapatla_trainer/openshift-virtualization-migration-advisor-local-first-powered-by-gemma-4-26b-moe-1ohm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OpenShift Virtualization Migration Advisor&lt;/strong&gt; — a local-first assessment tool that ingests legacy hypervisor configurations (VMware &lt;code&gt;.vmx&lt;/code&gt;, libvirt domain XML, OVF, RHV/oVirt exports) and produces a structured migration report for moving workloads to &lt;strong&gt;Red Hat OpenShift Virtualization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The problem it solves is specific and unglamorous: enterprises consolidating off vSphere and legacy KVM have a &lt;em&gt;discovery&lt;/em&gt; bottleneck. Their VM inventories live in config files that contain infrastructure secrets — storage paths, VLAN topology, encryption key references, FIPS posture, licence keys. Sending those to a hosted LLM is a non-starter for regulated workloads.&lt;/p&gt;

&lt;p&gt;So I built the assessment to run entirely on the host machine. Paste a config or upload an inventory → get a six-section migration report covering inventory mapping, OpenShift Virt primitive equivalents (&lt;code&gt;VirtualMachine&lt;/code&gt;, &lt;code&gt;DataVolume&lt;/code&gt;, &lt;code&gt;NetworkAttachmentDefinition&lt;/code&gt;, &lt;code&gt;StorageClass&lt;/code&gt;), compatibility risk flags, MTV-vs-&lt;code&gt;virt-v2v&lt;/code&gt; tooling recommendation, effort sizing, and security posture preservation. Nothing leaves the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;The tool generated this report from a single VMware &lt;code&gt;.vmx&lt;/code&gt; file, fully on-device using Gemma 4 26B MoE via Ollama. Screenshots below; full generated output included so judges can see the actual model output, not a curated highlight.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5oqehq5r2vgi81qnh1e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5oqehq5r2vgi81qnh1e.png" alt="Gradio UI with VMware sample loaded" width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Local Gradio UI. Pick a sample → click Generate → report streams in from local Gemma 4.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4ht9f56ynhlmb16td94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4ht9f56ynhlmb16td94.png" alt="Generated migration report" width="799" height="457"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Six-section migration report streamed from Gemma 4 26B MoE running locally. No cloud API calls.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Full Report (generated locally)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;From &lt;code&gt;samples/vmware-web-tier.vmx&lt;/code&gt; — 311.7s on a 16 GB-VRAM laptop with 85% CPU offload&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&amp;gt; &lt;strong&gt;Source detected:&lt;/strong&gt; &lt;code&gt;VMware vSphere (.vmx)&lt;/code&gt;&lt;br&gt;
&amp;gt; &lt;strong&gt;Model:&lt;/strong&gt; &lt;code&gt;gemma4:26b&lt;/code&gt;&lt;br&gt;
&amp;gt; &lt;strong&gt;Generated locally in:&lt;/strong&gt; 311.7s on a consumer laptop GPU + CPU offload&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Inventory Summary
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;vCPU&lt;/th&gt;
&lt;th&gt;Memory&lt;/th&gt;
&lt;th&gt;Disk(s)&lt;/th&gt;
&lt;th&gt;Network(s)&lt;/th&gt;
&lt;th&gt;Guest OS&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;web-tier-01&lt;/td&gt;
&lt;td&gt;4 (2 sockets × 2 cores)&lt;/td&gt;
&lt;td&gt;8192 MiB&lt;/td&gt;
&lt;td&gt;web-tier-01.vmdk&lt;/td&gt;
&lt;td&gt;VLAN-100-DMZ&lt;/td&gt;
&lt;td&gt;rhel9-64&lt;/td&gt;
&lt;td&gt;Production Nginx/PHP-FPM; requires UEFI Secure Boot; vSphere encrypted.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  2. OpenShift Virtualization Equivalents
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;OpenShift Virtualization Primitive&lt;/th&gt;
&lt;th&gt;Configuration Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compute&lt;/td&gt;
&lt;td&gt;&lt;code&gt;VirtualMachine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;spec.template.spec.domain.cpu&lt;/code&gt;: 2 sockets, 2 cores; &lt;code&gt;spec.template.spec.domain.resources.requests.memory: 8Gi&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firmware&lt;/td&gt;
&lt;td&gt;&lt;code&gt;VirtualMachine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;spec.template.spec.domain.firmware: efi&lt;/code&gt; (Secure Boot enabled)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DataVolume&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;storageClassName: [not specified in source]&lt;/code&gt;; requires conversion from &lt;code&gt;pvscsi&lt;/code&gt; to &lt;code&gt;virtio-scsi&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NetworkAttachmentDefinition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Target VLAN-100-DMZ via Multus CNI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  3. Compatibility &amp;amp; Risk Flags
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Critical — SCSI Controller Mismatch:&lt;/strong&gt; Source uses &lt;code&gt;pvscsi&lt;/code&gt;. OpenShift Virt requires &lt;code&gt;virtio-scsi&lt;/code&gt;. Driver injection or kernel reconfiguration may be necessary if the RHEL 9 initramfs lacks virtio drivers (unlikely for RHEL 9).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Critical — Encryption / KMS Breakage:&lt;/strong&gt; Source uses vSphere-specific KMS (&lt;code&gt;vsphere-kms-key-001&lt;/code&gt;). This encryption cannot be migrated. Data must be decrypted during migration or re-encrypted using OpenShift-native methods (encrypted PVCs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High — Network Driver Mismatch:&lt;/strong&gt; &lt;code&gt;vmxnet3&lt;/code&gt; must be replaced with &lt;code&gt;virtio&lt;/code&gt; for optimal performance and compatibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High — UEFI Secure Boot:&lt;/strong&gt; OpenShift Virt supports UEFI; the migration pipeline must ensure the &lt;code&gt;VirtualMachine&lt;/code&gt; object is correctly configured with &lt;code&gt;firmware: efi&lt;/code&gt; and a bootloader compatible with the new virtual hardware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Medium — CD-ROM dependency:&lt;/strong&gt; The &lt;code&gt;rhel-9.4.iso&lt;/code&gt; is attached. Must be manually re-attached via a &lt;code&gt;ConfigMap&lt;/code&gt; or &lt;code&gt;DataVolume&lt;/code&gt; if required for post-migration configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  4. Migration Path
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;web-tier-01:&lt;/strong&gt; MTV (Migration Toolkit for Virtualization).&lt;br&gt;
&lt;em&gt;Justification:&lt;/em&gt; MTV is the recommended path for vSphere-to-OpenShift migrations — it automates the conversion of VMDK to &lt;code&gt;DataVolume&lt;/code&gt; and handles the mapping of vSphere networks to &lt;code&gt;NetworkAttachmentDefinition&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Effort &amp;amp; TCO Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Effort (web-tier-01):&lt;/strong&gt; S
&lt;em&gt;Justification:&lt;/em&gt; Single, modern Linux guest (RHEL 9) with standard hardware requirements and no complex PCI passthrough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TCO / Licensing:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Requires OpenShift Container Platform (OCP) subscription&lt;/li&gt;
&lt;li&gt;RHEL guest licensing applies (standard RHEL / RHEL for Virtual Datacenters)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consolidation:&lt;/strong&gt; If other web-tier nodes exist in the source, migrate them in a single MTV plan to reduce migration window and operational overhead.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  6. Security &amp;amp; Compliance
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source Security Feature&lt;/th&gt;
&lt;th&gt;OpenShift Virtualization Equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;vSphere Encryption (KMS)&lt;/td&gt;
&lt;td&gt;Encrypted PVCs (via StorageClass / CSI) or &lt;code&gt;dm-crypt&lt;/code&gt; within the Guest OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VLAN-100-DMZ Isolation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;NetworkAttachmentDefinition&lt;/code&gt; + &lt;code&gt;NetworkPolicy&lt;/code&gt; for micro-segmentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UEFI Secure Boot&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;VirtualMachine&lt;/code&gt; spec &lt;code&gt;firmware: efi&lt;/code&gt; with Secure Boot enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production Workload Isolation&lt;/td&gt;
&lt;td&gt;Namespace-level isolation in OpenShift&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/Bharathtrainer/openshift-migration-advisor" rel="noopener noreferrer"&gt;https://github.com/Bharathtrainer/openshift-migration-advisor&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Gemma 4
&lt;/h2&gt;

&lt;p&gt;I chose &lt;strong&gt;Gemma 4 26B MoE&lt;/strong&gt; (&lt;code&gt;gemma4:26b&lt;/code&gt;) after starting on 31B Dense and discovering it was the wrong tool for this workload.&lt;/p&gt;

&lt;p&gt;The honest path: I picked 31B Dense first because the highest-quality reasoning seemed like the obvious choice for infrastructure assessment. Two problems surfaced on real-world inputs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ollama Flash Attention prefill stall on Dense&lt;/strong&gt; (&lt;a href="https://github.com/ollama/ollama/issues/15350" rel="noopener noreferrer"&gt;ollama#15350&lt;/a&gt;) hangs the 31B variant on prompts beyond ~3–4K tokens. A multi-VM datacenter inventory blows past that on the first VM. The bug is specific to Dense's hybrid sliding+global attention; MoE handles the same prompts cleanly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active-parameter efficiency.&lt;/strong&gt; 26B MoE activates ~4B parameters per token versus 31B for Dense. On a consumer laptop GPU, that's the difference between a model that works (with some CPU offload) and one that doesn't fit at all.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What I kept from picking MoE over Dense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;256K context window&lt;/strong&gt; — enough to ingest an entire small-datacenter inventory in one shot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable long-prompt prefill&lt;/strong&gt; on Ollama's current build&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native reasoning mode&lt;/strong&gt; via the &lt;code&gt;&amp;lt;|think|&amp;gt;&lt;/code&gt; system-prompt token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workable throughput on consumer hardware&lt;/strong&gt; — generation runs even when 85% of layers spill to CPU&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Honest performance note:&lt;/strong&gt; the report above generated in 311.7 seconds on a 16 GB-VRAM laptop GPU with 85% CPU offload (&lt;code&gt;ollama ps&lt;/code&gt; confirms the split). On a workstation with 24+ GB VRAM the same generation should land in 30–60 seconds. This is exactly the kind of detail you want a tool to expose, not hide — local AI's pitch is data sovereignty, and the tradeoff is hardware-dependent latency. Field engineers running this for offline assessment will accept 5 minutes for a report they can't legally send to a cloud API.&lt;/p&gt;

&lt;p&gt;When MoE is &lt;em&gt;not&lt;/em&gt; the right pick: short, single-turn, hard math/code reasoning where Dense's per-token capacity matters more than throughput. For long, structured, enterprise-document reasoning over large configs, &lt;strong&gt;MoE wins&lt;/strong&gt;. That's the call this build makes, and the rationale is documented in the README with the GitHub issue link, not vibes.&lt;/p&gt;

&lt;p&gt;One Gemma 4-specific detail worth flagging: I follow the recommended sampling (&lt;code&gt;temperature=1.0, top_p=0.95, top_k=64&lt;/code&gt;) and set &lt;code&gt;OLLAMA_FLASH_ATTENTION=1&lt;/code&gt; + &lt;code&gt;OLLAMA_KV_CACHE_TYPE=q4_0&lt;/code&gt; to keep the KV cache compact enough for a 16K context window. Those four config values are the difference between this running at usable speed and not running at all.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built entirely on a laptop. No cloud API key was used at any point in the construction of this submission. The report you see above was generated by Gemma 4 running on the same machine.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
