Thursday, February 21, 2013

How do I add a MongoDB replicaset/node with auth/credentials to MMS monitor on 10gen?

Want to get in on that sweet, sweet MMS MongoDB monitoring action?

image[20]

Of course you do! But are your mongo instances setup to require authentication? Bummer—the instructions won’t work for you out of the box. Here’s what you’re missing.

  1. Go ahead and setup the agent as instructed
  2. Go into the MMS management site
  3. Add your host manually

    image_thumb[8]
  4. Enter the hostname, db username, and db password. I suggest creating a new user for this (it must be a user on the admin database!)

    image_thumb[9]

Now frantically check the hosts, agents, and pings tabs for updates. It might take a few minutes. Check the Agent Log tab for errors :).

Once you get the one host working, it will add the other hosts in the replicaset, too. You can then install the agent on those machines and add a password with the pencil icon to each new row directly.

How do I add another group to my MongoDB MMS monitor on 10gen?

10gen has some seriously awesome (free) monitoring software: MMS.

image

You’re supposed to add your machines to a group, and use a different group for each logical grouping of machines. For instance, one group for one production cluster and another group for a different cluster. But how do you add a new group!?

I admit the obvious answer eluded me. You do it from the Admins page. Once there you’ll see a little “Add New Group” link:

image

Once you do that you can switch among your groups with the select list in the upper-left corner.

Tuesday, February 19, 2013

Building Dual-Screen Wallpapers for Windows 7 with PowerShell

If you have two monitors you have probably noticed that you can’t easily put a different wallpaper on each screen in Windows 7 (this works out of the box in Windows 8). This is annoying. Sure you can fix this with third party tools, but I want to go a different route.

The key to getting this to work is to recognize that if you choose a background image that is exactly the same size of your combined monitor real estate, it will automatically be stretched between the two screens. For instance, I have two screens, each running at 1280x1024. If I pick a wallpaper that is twice that width, 2560x1024, Windows will do what I want.

Of course the problem then is finding wallpapers that fit that size. Google can help with discovering sites that tailor specifically to this problem.

But what if you already have single-monitor wallpapers that you want to use? All you really need to do is combine them into a single image.



I did this recently to an entire collection of Calvin and Hobbes wallpapers. I wanted to show a different comic on each screen, but not always the same two at a time—I wanted to mimic the Windows 8 strategy of seemingly random wallpapers on random screens.

I combined two images manually, side by side at 2560x1024 once to confirm it would work, and then wrote a few lines of PowerShell to generate every possible combination with the help of the amazing ImageMagick library (specifically the montage command). The idea being that if I just pre-generate all the options, they will appear to be randomly assembled as they cycle through.

Run this script in the dirctory containing all your single wallpapers and it will combine them into the dual-screen variety.

Obviously this is crude--add your own flow control, resume support for large batches, etc....

$imgs = Get-ChildItem * -include *.jpg,*.png -exclude dual*

for ($i=0; $i -lt $imgs.Length; $i++){ 
    for ($j=0; $j -lt $imgs.Length; $j++){ 
        if($i -eq $j){ continue; }
        $left = $imgs[$i].Name
        $right = $imgs[$j].Name
        $extension = "jpg"

        $destination = [string]::Format("dual/dual-{0}-{1}.{2}", $i, $j, $extension)

        if(Test-Path $destination){
            echo "Skipping $destination"
        }
        else{
            echo "Running: montage -geometry 1280x1024 $left $right $destination"
            montage -geometry 1280x1024 $left $right $destination
        }
    }
}

Change that -geometry part to fit your system, obviously, and yeah... just loop over everything :).

Setting up a Samsung Wireless Laser Printer with a Phone or Tablet (i.e. Without a Computer)

We have finally ditched our money pit inkjet printer in favor of a slightly more economical laser printer. We opted for a very cheap, but capable Samsung ML-2165W. It's monochrome, fast, and supports wireless connectivity.

If you want builtin duplex or color be prepared to drop some extra coin.

Our goal was cheap, fast printing and laser printers seem to do the trick there with a much lower $/page cost than inkjet.

But enough about that. How do you get the damn thing setup? The instructions tell you to pop the CD into your computer and go to town. What if you don't have a CD-ROM drive? Or a computer? Luckily you can do it with just a web browser, though it's admittedly not the simplest process. Here's how I did it with my iPhone/iPad:

First, setup the printer and turn it on. Don't hook up the USB cable to anything.

Next, go get the Samsung print app for your phone or tablet. Do this before the next step because you need to be online to do it.

The printer will broadcast a WiFi network for ad-hoc printing. Connect to that with your phone or tablet--it'll be something like "PortThru". Just look for an open network with a good signal that looks like it was named by a corporation.

Once you're connected to the printer open the print app. We don't actually want to print anything yet (though you could!). Go through the motions like you are going to print something though, because we want to know the printer's IP address. This will show up when you go to select the printer.

Note the IP address and head over to your web browser. Enter the IP address in the address bar to get to the printer's management console.

Login with user "admin", password "sec00000". If that doesn't work, do a Google search for "default password <your printer model>" and try that.

Once you're logged in, go to the settings page and do the wireless setup. This will let you choose your WiFi network from a list. When complete, your printer (or at least its network) will reboot. Give it a minute.

Your phone or tablet will probably automatically reconnect to your usual WiFi network.

Launch that printer app again and go to print something else. This should allow you to choose your printer again, but this time with a normal network address (10.0.*.*, 192.168.*.*, etc.). This means that the printer is now on the network and available to everyone. Good job!

Now go kill some trees!



Automatically Connect to the Replica Set Primary with Mongo Shell

So you got your fancy MongoDB Replica Set running, did you, Mr. Fancypants? Before too long you might run into an issue: how do you connect to the primary node when the primary can change?

Luckily our applications don’t have this problem because their drivers are smart and automatically connect to the primary. The Mongo shell doesn’t do that, though.

Here’s a library to help with that. Throw this into a file called replicaSetConnector.js:

var ReplicaSetConnector = (function() { 
    var RSC = function(options) {
    
        // private method for handling the dirty work of connecting 
        // and authenticating to mongo
        var connectAndAuth = function(host) {
            if(options.debug){
                print("Connecting to " 
                    + host + "/" + options.database 
                    + " as " + options.username + ":" + options.password);
            }
            
            var connection = new Mongo(host);
            var database = connection.getDB(options.database);
            database.auth(options.username, options.password);    
            
            return database;    
        };
        
        this.connect = function() {
            // db needs to be a global variable for subsequent shell commands to work :)
            // connect to the given host, which could be any node of the replica set
            db = connectAndAuth(options.initialHost);
            
            // load some basic replica set information, which will tell us 
            // if we're on the primary, and if not where it is
            var rsInfo = db.isMaster();

            // if we're already on the primary, we're done. Otherwise, change our
            // connection to the primary
            if(!rsInfo.ismaster){
                if(options.debug) print("You're not on master...");
                db = connectAndAuth(rsInfo.primary);
                if(options.debug) print("...or are you ;)");
            }
        };
    };
        
    return RSC;
})();

That’s a library we’ll reuse bunches of times. Now make another file for your environment, e.g. prod.js with this in it:

(new ReplicaSetConnector({ 
    initialHost: 'one-of-your-replica-set-nodes:27017', 
    database: "database-name", 
    username: "user", 
    password: "secret...",
    debug: true})).connect();

And we’re finally read to connect with a mongo shell like so:

%> mongo --shell --nodb replicaSetConnector.js prod.js
MongoDB shell version: 2.2.2
type "help" for help
loading file: replicaSetConnector.js
loading file: prod.js
Connecting to one-of-your-replica-set-nodes:27017/database-name as user:secret...
You're not on master...
Connecting to another-one-of-your-replica-set-nodes:27017/database-name as user:secret
...or are you ;)
>

Yes, now you are on master and the db object is set for you to begin executing commands. If you want to be extra terse on the command line, you can alias that command to something shorter, add the library to your mongorc file, or make Windows shortcut.

Tuesday, February 5, 2013

Chef on Windows Error: tar: Cannot fork: Function not implemented (Solved)

I’m diving into the fun world of Chef. But I’m doing it on Windows, which has been…not smooth. Here’s my latest error:

C:\Users\mharen\Code\chef-repo>knife cookbook site install getting-started
Installing getting-started to C:/Users/mharen/Code/chef-repo/cookbooks
Checking out the master branch.
Pristine copy branch (chef-vendor-getting-started) exists, switching to it.
Downloading getting-started from the cookbooks site at version 0.4.0 to C:/Users/mharen/Code/chef-repo/cookbooks/getting-started.tar.gz
Cookbook saved: C:/Users/mharen/Code/chef-repo/cookbooks/getting-started.tar.gz
Removing pre-existing version.
Uncompressing getting-started version 0.4.0.
ERROR: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '2'
---- Begin output of tar zxvf C:/Users/mharen/Code/chef-repo/cookbooks/getting-started.tar.gz ----
STDOUT:
STDERR: tar: Cannot fork: Function not implemented
tar: Error is not recoverable: exiting now
---- End output of tar zxvf C:/Users/mharen/Code/chef-repo/cookbooks/getting-started.tar.gz ----
Ran tar zxvf C:/Users/mharen/Code/chef-repo/cookbooks/getting-started.tar.gz returned 2

Lame. After wasting an embarrassingly large amount of time on this issue, I figured it out: I had multiple installs of the `tar` command:

C:\Users\mharen\Code\chef-repo>which -a tar
C:\Program Files (x86)\Gow\bin\tar.EXE
C:\chef\bin\tar.EXE
c:\Git\bin\tar.EXE

And apparently some of them suck. Hard. Since I’m playing with Chef, let’s just use that one—it probably works. This was as easy as updating my PATH variable to place `c:\chef\bin` at the beginning instead of the end (really just before the others found by `which`):

image

Once you fix the path, close and reopen your cmd window and try the command again:

C:\Users\mharen\Code\chef-repo>which -a tar
C:\chef\bin\tar.EXE
c:\Git\bin\tar.EXE
C:\Program Files (x86)\Gow\bin\tar.EXE

C:\Users\mharen\Code\chef-repo>knife cookbook site install getting-started
Installing getting-started to C:/Users/mharen/Code/chef-repo/cookbooks
Checking out the master branch.
Pristine copy branch (chef-vendor-getting-started) exists, switching to it.
Downloading getting-started from the cookbooks site at version 0.4.0 to C:/Users/mharen/Code/chef-repo/cookbooks/getting-started.tar.gz
Cookbook saved: C:/Users/mharen/Code/chef-repo/cookbooks/getting-started.tar.gz
Removing pre-existing version.
Uncompressing getting-started version 0.4.0.
removing downloaded tarball
1 files updated, committing changes
Creating tag cookbook-site-imported-getting-started-0.4.0
Checking out the master branch.
Updating b5a1d0d..42a8168
Fast-forward
 cookbooks/getting-started/README.rdoc              |  4 +++
 cookbooks/getting-started/attributes/default.rb    |  1 +
 cookbooks/getting-started/metadata.json            | 29 ++++++++++++++++++++++
 cookbooks/getting-started/metadata.rb              |  6 +++++
 cookbooks/getting-started/recipes/default.rb       | 23 +++++++++++++++++
 .../templates/default/chef-getting-started.txt.erb |  5 ++++
 6 files changed, 68 insertions(+)
 create mode 100644 cookbooks/getting-started/README.rdoc
 create mode 100644 cookbooks/getting-started/attributes/default.rb
 create mode 100644 cookbooks/getting-started/metadata.json
 create mode 100644 cookbooks/getting-started/metadata.rb
 create mode 100644 cookbooks/getting-started/recipes/default.rb
 create mode 100644 cookbooks/getting-started/templates/default/chef-getting-started.txt.erb
Cookbook getting-started version 0.4.0 successfully installed

C:\Users\mharen\Code\chef-repo>

All fixed :)