Possible to make shell-access app start on a compute node via "srun --pty bash"?

Scenario: classroom/workshop of 40 pretty novice users that we’d like to introduce to our cluster via OOD and it would be advantageous if we prevented any accidental, unreasonable loading on the ood login node.

To this end, we could ask that they all start the shell access app normally, then execute “srun --pty --qos=sandbox /bin/bash” themselves, but it would be even nicer if we could modify the shell app to do this in some way automatically. (And if possible, add an additional entry to the Clusters menu to indicate this additional special shell option.)

Does anyone know of a semi-elegant way to do this/these modifications?

Thank you!
Jason Buechler / NAU Monsoon

This is how I achieved it. Since I don’t have Slurm, for testing purposes I start zsh instead of the default bash, so it should translate.

cd /var/www/ood/apps/sys
sudo cp -r shell shellzsh
cd shellzsh
sudo sed -i 's/Shell/Shell with Z shell/g' manifest.yml
  • so manifest has role: shell and name: Shell with Z shell

Edit this line in app.js:

   cmd = 'ssh';
-  args = dir ? [host, '-t', 'cd \'' + dir.replace(/\'/g, "'\\''") + '\' ; exec ${SHELL} -l'] : [host];
+  args = [host, '-t', 'zsh']
  • note that in this case I’m not adding support for cd-ing to a subdirectory if dir is set but you can probably figure out the control flow to do that if necessary
  • you would use something like args = [host, '-t', 'srun', '--pty', '--qos=sandbox', '/bin/bash']

Edit the dashboard /var/www/ood/apps/sys/dashboard/app/apps/ood_app.rb in the def links method there is this block under elsif role == "shell":

      if login_clusters.none?
        [
          OodAppLink.new(
-           title: "Shell Access",
+           title: "#{title} Access",
            description: manifest.description,
            url: OodAppkit::Urls::Shell.new(base_url: url).url,
            icon_uri: "fas://terminal",
            caption: caption,
            new_tab: true
          )
        ]
      else
        login_clusters.map do |cluster|
          OodAppLink.new(
-           title: "#{cluster.metadata.title || cluster.id.to_s.titleize} Shell Access",
+           title: "#{cluster.metadata.title || cluster.id.to_s.titleize} #{title} Access",
            description: manifest.description,
            url: OodAppkit::Urls::Shell.new(base_url: url).url(host: cluster.login.host),
            icon_uri: "fas://terminal",
            caption: caption,
            new_tab: true
          )
        end.sort_by { |lnk| lnk.title }
      end
  • Click Help => Restart web server to pick up the changes.

The result is a menu that looks like this:

And clicking “Owens Shell with Z shell Access” actually starts zsh instead of bash (or the users default shell).

I’ll open an issue to make changes similar the above so this type of thing is easier to do, without actually having to copy the shell app.

1 Like

Tracking https://github.com/OSC/ondemand/issues/109

1 Like

@efranz wow, this was exactly what I was looking for, thank you!!!

I have a few notes for future visitors to this thread:

  • Additional shells load the Clusters menu in what looks like lexicographical order.
  • Addressing a minor typo, the dashboard ood_app.rb file is located at /var/www/ood/apps/sys/dashboard/app/apps/ood_app.rb (with ‘dashboard’ between sys//app).
  • Until I started digging into the code the other day, I didn’t even realize cd-ing to a specific dir was a (neat!) feature, so losing that support in editing args= was no biggie.

Additionally, thank you again, @efranz for submitting that feature request to github! One quick question: while we’re making this modification manually – is it safe to assume that the newer shell app and modified dashboard .rb file may not survive a yum update?

The copied shell app should remain untouched. The modified dashboard .rb file would be replaced by a yum update. Though I would hope that the rpm install process would see your change and add a .new to the file that would be the one to replace it. Regardless I’d save your change to a backup in case you lose it on update.

My apologies for necroing this thread, but now that I’m planning to get v2 ready for production, I noticed there’s now a good bit of difference in the ood_app.rb code for the shell app, and I’m not good with Ruby.

(And it looks like Enable shell app to have variations on the command it runs after connecting · Issue #109 · OSC/ondemand · GitHub is still in the works.)

It looks like I’ll lose localization (which is fine) but this is what I’ve successfully (but obviously naively) done, so far by simply ignoring the current title: code and using the old suggestion verbatim:

if login_clusters.none?
        [
          OodAppLink.new(
-           title: I18n.t('dashboard.shell_app_title', cluster_title: nil).to_s.strip,
+           title: "#{title} Access",
            description: manifest.description,
            url: OodAppkit::Urls::Shell.new(base_url: url).url,
            icon_uri: "fas://terminal",
            caption: caption,
            new_tab: open_in_new_window?
          )
        ]
      else
        login_clusters.map do |cluster|
          OodAppLink.new(
-           title: I18n.t('dashboard.shell_app_title', cluster_title: cluster.metadata.title || cluster.id.to_s.titleize),
+           title: "#{cluster.metadata.title || cluster.id.to_s.titleize} #{title} Access",
            description: manifest.description,
            url: OodAppkit::Urls::Shell.new(base_url: url).url(host: cluster.login.host),
            icon_uri: "fas://terminal",
            caption: caption,
            new_tab: open_in_new_window?
          )
        end.sort_by { |lnk| lnk.title }
      end

But… is this TOO naive?

I could well be wrong, but since the localization for shell_app_title is coming from the dashboard ymls, I don’t think there is a way to keep utilizing it. And since my Ruby skills aren’t great, I wasn’t sure how to artfully modify those lines.

Thank you for any advice!

I think that should work for you, just applying the same delta.

Though I have to admit I sat for 10 minutes or so thinking there has to be a better way for this - though I do not yet know what it is.

1 Like