<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title><![CDATA[TheGeekery]]></title>
  <link href="http://jon.netdork.net/atom.xml" rel="self"/>
  <link href="http://jon.netdork.net/"/>
  <updated>2013-04-30T13:28:58-07:00</updated>
  <id>http://jon.netdork.net/</id>
  <author>
    <name><![CDATA[Jonathan Angliss]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
    <entry>
      




<title type="html"><![CDATA[Cross domain execution of Lync commands]]></title>
<link href="http://jon.netdork.net/2013/04/30/cross-domain-execution-of-lync-commands/"/>
<updated>2013-04-30T09:00:00-07:00</updated>
<id>http://jon.netdork.net/2013/04/30/cross-domain-execution-of-lync-commands</id>
<category term="Lync" /><category term="PowerShell" />

      <content type="html"><![CDATA[<p>For the last few weeks I’ve been performing all the preparation work for Lync 2013 in our organization.  We’ve had a very successful Lync 2010 pilot, and instead of expanding the 2010 to production, and later having to do a full environment replace for 2013, we decided to jump straight to 2013. Part of the steps, whether a fresh install or an upgrade, is some Active Directory Forest and Domain preperations.  These can either be done using the installation wizard, or via PowerShell.</p>

<p>One of these commands is <code>Grant-CsOUPermission</code>.  This command is required if you don’t keep your users/servers/computers in the standard containers in AD (I.e, Users in the Users container).  In our environment, we move the users into a People OU, so we needed to run the <code>Grant-CsOUPermission</code> command to update some container permissions for Lync to work properly, and allow us to delegate user management.  To save some time, I was executing all the commands from one domain, to one of the other child domains in the forest. This was because I didn’t have access to a 64bit machine in that environment without spending additional time spinning up a client to test with.  The Lync PowerShell cmdlets allow for this, and this is what I was doing, and having issues with.</p>

<p>I’d first start a PowerShell prompt as a domain admin in the other domain using the <code>runas</code> command:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">runas /profile /user:OTHERCHILD\myadmin powershell</div></pre></td></table></div></figure>

<p>Next is to import the Lync modules:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nb">Import-Module</span> <span class="n">Lync</span>
</div></pre></td></table></div></figure>

<p>Then the final step is to enable the domain, and grant the necessary permissions to the OUs I needed to modify.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nb">Enable-CsAdDomain</span> <span class="n">-Domain</span> <span class="n">otherchild</span><span class="p">.</span><span class="n">domain</span><span class="p">.</span><span class="n">tld</span>
</div><div class="line"><span class="n">Grant-CsOUPermission</span> <span class="n">-ObjectType</span> <span class="s2">&quot;User&quot;</span> <span class="n">-OU</span> <span class="s2">&quot;CN=People,DC=OtherChild,DC=Domain,DC=tld</span>
</div></pre></td></table></div></figure>

<p>This is where I was hitting a road block, the first command would execute just fine, but the second command would result in a permissions error.</p>

<blockquote><p>The user is not a member of "Domain Admins or Enterprise Admins" group.</p></blockquote>

<p>This was a weird error because I know I am a domain admin in the other domain, it wouldn’t have let me execute the <code>Enable-CsAdAdmin</code> if I wasn’t, and that went fine.</p>

<p>After some bashing of my head, and a good nights sleep, I realized the issue when I started looking at it this morning.  I’d failed to specify the domain for the <code>Grant-CsOUPermission</code> command.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="n">Grant-CsOUPermission</span> <span class="n">-Domain</span> <span class="n">otherchild</span><span class="p">.</span><span class="n">domain</span><span class="p">.</span><span class="n">tld</span> <span class="n">-ObjectType</span> <span class="s2">&quot;User&quot;</span> <span class="n">-OU</span> <span class="s2">&quot;CN=People,DC=otherchild,DC=domain,DC=tld&quot;</span>
</div></pre></td></table></div></figure>

<p>Adding the domain allowed execution.  The problem here was that it was trying to bind to mychild.domain.tld and then access the OU through the link to otherchild.domain.tld. The problem here was that my account in otherchild.domain.tld didn’t have domain admin access in mychild.domain.tld, and hence the error.</p>

<p>So, learning lesson of the day, either execute all the commands on a server in the domain you are worknig on, or remember to specify the domain.  As a side note, the Microsoft documentation is a little fuzzy around this area because it says you must sign in to a domain member on the domain you wish to execute the commands, but then specifies that you can execute the commands in a different domain. It gets a little confusing, but once you get your head wrapped around the fact that you can do this across domains, and that you must specify the domain, even if the OU hints at a different domain, things are a little easier to work with.</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Remote Registry, handle leaks, and objects not found]]></title>
<link href="http://jon.netdork.net/2013/03/21/remote-registry/"/>
<updated>2013-03-21T08:49:00-07:00</updated>
<id>http://jon.netdork.net/2013/03/21/remote-registry</id>


      <content type="html"><![CDATA[<p>Earlier today while updating some documentation, I noticed 2 of the servers being monitored in <a href="http://www.solarwinds.com/server-application-monitor.aspx" title="SolarWinds Server and Application Monitor">SolarWinds SAM</a> were reporting applications in an “unknown” state.  When I pulled up the display, and looked at the details of the state, it was throwing an error:</p>

<blockquote><p>Bad input parameter. HResult: The specified object is not found on the system.</p></blockquote>

<p>I thought this was a little weird, as the monitors used to work, and the server hadn’t been patched, or any changes made recently.</p>

<p>First step was verifying that the counters it was looking for really existed.  Logging onto the server, I opened the performance monitor, and tracked down the supposidly missing performance counters.  They were there.  Maybe it was an issue with accessing remotely, so I jumped on the SolarWinds server, and tested remote counter access from there, repeating the same process, but specifying the remote server name.  Again, no issue.</p>

<p>This is when I decided to do some searching, and stumbled across a <a href="http://thwack.solarwinds.com" title="Thwack Community of SolarWinds">Thwack</a> <a href="http://thwack.solarwinds.com/thread/48542" title="Thwack; Exchange 2010 Application Issue">post</a> that mentioned the same error, but related to Exchange.  They had basically done the same testing as I had, but were urged to open a support ticket for more troubleshooting help with their support department.</p>

<p>The last post, before mine, in that thread was the answer I was looking for.  They were experiencing an issue with the <em>Remote Registry</em> service, and a simple restart fixed the issue.  I took a look at the services on both the servers I was seeing issues with and the issue jumped out immediately.  Both servers were using about 600MB and 50k handles.  This is <em>very</em> unusual for a service such as the <em>Remote Registry</em>.  This tripped a light bulb, as I was working on an issue with a coworker, and he had identified a bug and hotfix for memory leaks in the <em>Remote Registry</em>.  In <a href="http://support.microsoft.com/kb/2699780" title="Microsoft KB; Memory leak in Remote Registry service on a computer that is running Windows 7 or Windows Server 2008R2">KB2699780</a> it details the same behavior, and we were scheduled to deploy this hotfix on a different set of servers for a similar issue.</p>

<p>A quick restart of the <em>Remote Registry</em> service had the applications successfully polling again, now to just schedule some maintenance to get the hotfix applied to these servers.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Exchange 2007/2010 and Hiding Mailboxes]]></title>
<link href="http://jon.netdork.net/2013/02/11/exchange-2007-slash-2010-and-hiding-mailboxes/"/>
<updated>2013-02-11T19:56:00-08:00</updated>
<id>http://jon.netdork.net/2013/02/11/exchange-2007-slash-2010-and-hiding-mailboxes</id>
<category term="PowerShell" />

      <content type="html"><![CDATA[<p>Like any large organization, we have automated processes that go and happily disable user accounts on termination.  This process looks in our HR database for certain flags, and reacts accordingly.  As part of the termination/disabling process, it’ll also flag their email account to be hidden from the Exchange Global Address List (GAL).</p>

<p>In Exchange 2003 hiding accounts from the GAL used to handled by an Active Directory (AD) user attribute called <code>msExchHideFromAddressLists</code>.  When this was set to <code>TRUE</code>, the user would be hidden from the GAL.  Our HR applications toggle this flag for users that are disabled to hide them away from other users.</p>

<p>This process all worked fine for a long time, until Exchange 2007 rolled around.  I guess there was plenty of push to allow you to hide a user from all the GALs, but still allow specific GALs to have those users in.  So Microsoft introduced a new AD user attribute called <code>showInAddressBook</code>.  The problem now appears that if you toggle the <code>msExchHideFromAddressList</code>, but have a value set for <code>showInAddressBook</code>, the user accounts are no longer hidden in the GAL mentioned in the latter attribute.</p>

<p>Can anybody see where this is going?  Yup, it appears that all the user accounts were getting the default GALs assigned to the <code>showInAddressBook</code> attribute, so even when they were having the option to hide the user, they were still showing up<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.  This was causing problems as people that were disabled/terminated were still showing up, and causing some confusions and concerns.</p>

<p>I started to poke around, and bashed together a quick PowerShell script that will walk through all disabled users that have a <code>showInAddressBook</code> attribute, it’ll then wipe out that attribute.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nv">$ldapFilter</span> <span class="p">=</span> <span class="s1">&#39;(&amp;(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2)(showInAddressBook=*))&#39;</span>
</div><div class="line"><span class="nv">$ldap</span><span class="p">=</span><span class="no">[ADSI]</span><span class="s2">&quot;LDAP://OU=Disabled Accounts,DC=DOMAIN,DC=TLD,DC=PVT&quot;</span>
</div><div class="line"> </div><div class="line"><span class="nv">$srch</span> <span class="p">=</span> <span class="nb">New-Object</span> <span class="n">DirectoryServices</span><span class="p">.</span><span class="n">DirectorySearcher</span><span class="p">(</span><span class="nv">$ldap</span><span class="p">)</span>
</div><div class="line"><span class="nv">$srch</span><span class="p">.</span><span class="k">Filter</span> <span class="p">=</span> <span class="nv">$ldapFilter</span>
</div><div class="line"><span class="nv">$foundUsers</span> <span class="p">=</span> <span class="nv">$srch</span><span class="p">.</span><span class="n">findAll</span><span class="p">()</span>
</div><div class="line"> </div><div class="line"><span class="nv">$foundUsers</span> <span class="p">|</span> <span class="p">%</span> <span class="p">{</span>
</div><div class="line">       <span class="nv">$adUser</span> <span class="p">=</span> <span class="nv">$_</span>
</div><div class="line">       <span class="nv">$props</span> <span class="p">=</span> <span class="nv">$adUser</span><span class="p">.</span><span class="n">Properties</span>
</div><div class="line">       <span class="nv">$objUser</span> <span class="p">=</span> <span class="no">[ADSI]</span><span class="p">$(</span><span class="s2">&quot;LDAP://{0}&quot;</span> <span class="o">-f</span> <span class="nv">$props</span><span class="p">.</span><span class="n">get_Item</span><span class="p">(</span><span class="s1">&#39;distinguishedName&#39;</span><span class="p">).</span><span class="n">Item</span><span class="p">(</span><span class="n">0</span><span class="p">))</span>
</div><div class="line">       <span class="nv">$objUser</span><span class="p">.</span><span class="n">PutEX</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="s1">&#39;ShowInAddressBook&#39;</span><span class="p">,</span> <span class="nv">$null</span><span class="p">)</span>
</div><div class="line">       <span class="nv">$objUser</span><span class="p">.</span><span class="n">SetInfo</span><span class="p">()</span>
</div><div class="line"><span class="p">}</span>
</div></pre></td></table></div></figure>

<p>If you’ve not seen LDAP queries before, they work by starting with the operator (and, or, etc), and then the objects that they apply to.  So in the example above, it reads as such:</p>

<blockquote>
  <p>(objectClass=user) AND (userAccountControl:1.2.840.113556.1.4.803:=2) AND (showInAddressBook=*)</p>
</blockquote>

<p>It can get a little more complicated when you start stringing together multiple options such as AND and OR operators, and various combinations of them.  In this example, we’re going for pretty simple.</p>

<p>I then used the .NET libraries <a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.aspx" title="MSDN; Directory Searcher Class">System.DirectoryServices.DirectorySearcher</a>.  This uses the LDAP query specified, and returns all matching results.  Next was a case of walking through the results, and fetching a <a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx" title="MSDN; DirectoryEntry Class">DirectoryEntry</a> object to edit the properties.  In this case we’re setting it to <code>$null</code> which removes it.</p>

<p>After letting this script run over about 25k users disabled users, it cleared up the fluff in the GAL, and made HR happy.</p>

<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>As a weird side-note to this, if you check the box to hide the user in the Exchange management suite, it removes the <code>showInAddressBook</code> flag on its own, same for the PowerShell options too.<a href="#fnref:1" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Octopress and OpenID]]></title>
<link href="http://jon.netdork.net/2013/02/07/octopress-and-openid/"/>
<updated>2013-02-07T19:08:00-08:00</updated>
<id>http://jon.netdork.net/2013/02/07/octopress-and-openid</id>
<category term="octopress" /><category term="openid" />

      <content type="html"><![CDATA[<p>One of the things I had completely forgotten about during my migration from WordPress to Octopress was OpenID.  I had used one of the few OpenID plugins that tied into WordPress, and allowed you to use WordPress as an OpenID provider, giving me the ability to login to sites using my WordPress site.</p>

<p>This was great, and I’d completely forgotten about it because I rarely used it. That was until yesterday when somebody on the <a href="irc://chat.freenode.net/nagios" title="Freenode #Nagios">#Nagios</a> IRC channel had asked a question, and then posted the same question to <a href="http://stackoverflow.com/questions/14742807/nagios-polling-arbitrary-metrics-and-remote-security/" title="stackoverflow; Nagios - Polling arbitrary metrics and remote security">stackoverflow</a>. I decided to answer the question over there, and remembered I had signed up for an account using OpenID, so I dutifully typed in my site URL, and was stumped because I wasn’t redirected.</p>

<p>This is where I did a little face-meets-desk action.  I’d killed my OpenID account by killing off my WordPress site.  I tried to think of a way around this, and did some quick searching, and stumbled upon a post by Darrin Mison, on the exact <a href="http://shinysparkly.com/blog/2012/09/03/openid-and-octopress/" title="Adding OpenID delegation to an Octopress blog">same topic</a>.  Darrin had left his WordPress site active over on Wordpress.com, but had migrated to his URL else where.  Because of this, Darrin was able to use what is called a deligate, and tell anybody making a request to look elsewhere to authenticate.</p>

<p>This sparked a vague memory, and reminded me that when I first started tinkering with OpenID, I used a different site for the authentication, so a quick check, and I was able to login there.  Now I just needed to edit my Octopress site to provide the delegate information.</p>

<p>I used <a href="http://www.myopenid.com" title="myOpenID">myOpenID.com</a> as my delegate, and they have a <a href="https://www.myopenid.com/help#own_domain" title="myOpenID; Using your own URL">help</a> article on how to handle using your own URL.  Following what Darrin had done, I edited <code>source/_includes/custom/head.html</code> and added the lines that the were mentioned in the help doc.  So now my <code>head.html</code> template looks like this:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div></pre></td><td class="main  html"><pre><div class="line"><span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;openid.server&quot;</span> <span class="na">href=</span><span class="s">&quot;http://www.myopenid.com/server&quot;</span> <span class="nt">/&gt;</span>
</div><div class="line"><span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;openid.delegate&quot;</span> <span class="na">href=</span><span class="s">&quot;http://jonangliss.myopenid.com/&quot;</span> <span class="nt">/&gt;</span>
</div><div class="line"><span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;openid2.local_id&quot;</span> <span class="na">href=</span><span class="s">&quot;http://jonangliss.myopenid.com&quot;</span> <span class="nt">/&gt;</span>
</div><div class="line"><span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;openid2.provider&quot;</span> <span class="na">href=</span><span class="s">&quot;http://www.myopenid.com/server&quot;</span> <span class="nt">/&gt;</span>
</div><div class="line"><span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">&quot;X-XRDS-Location&quot;</span> <span class="na">content=</span><span class="s">&quot;http://www.myopenid.com/xrds?username=jonangliss.myopenid.com&quot;</span> <span class="nt">/&gt;</span>
</div><div class="line"><span class="c">&lt;!--Fonts from Google&quot;s Web font directory at http://google.com/webfonts --&gt;</span>
</div><div class="line"><span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;http://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span> <span class="na">type=</span><span class="s">&quot;text/css&quot;</span><span class="nt">&gt;</span>
</div><div class="line"><span class="nt">&lt;link</span> <span class="na">href=</span><span class="s">&quot;http://fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic&quot;</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span> <span class="na">type=</span><span class="s">&quot;text/css&quot;</span><span class="nt">&gt;</span>
</div></pre></td></table></div></figure>

<p>Pretty simple, and a rebuild of the blog, and my page now includes the delegate headers required to redirect OpenID requests.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Adding XML Elements using PowerShell]]></title>
<link href="http://jon.netdork.net/2013/01/11/adding-xml-elements-using-powershell/"/>
<updated>2013-01-11T18:06:00-08:00</updated>
<id>http://jon.netdork.net/2013/01/11/adding-xml-elements-using-powershell</id>
<category term="PowerShell" />

      <content type="html"><![CDATA[<p>In a follow-up to my previous post on <a href="http://jon.netdork.net/2013/01/09/removing-xml-elements-using-powershell/" title="TheGeekery; Removing XML elements using PowerShell">removing XML elements using PowerShell</a>, I decided to figure out how to add elements using PowerShell.  I’m working with the same file from <a href="http://remotedesktopmanager.com/" title="Remote Desktop Manager">Remote Desktop Manager (RDM)</a> and adding remote management configurations based on DNS checks.</p>

<p>In the enterprise licensed version of RDM you are given the ability to add “remote management” interface details to a host configuration.  In our environment, that remote management interface is <abbr title="Integrated Lights Out">iLO</abbr>, and is available from a dedicated IP address, over HTTPS, giving you access to a remote console as well as power management features.  RDM handles this with a small tweak to the XML file adding another element under the connection meta information.</p>

<p>The XML that RDM is looking for is like this:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div></pre></td><td class="main  xml"><pre><div class="line"><span class="nt">&lt;Connection&gt;</span>
</div><div class="line">  <span class="nt">&lt;MetaInformation&gt;</span>
</div><div class="line">    <span class="nt">&lt;ServerRemoteManagementUrl&gt;</span>https://hostname-ilo<span class="nt">&lt;/ServerRemoteManagementUrl&gt;</span>
</div><div class="line">  <span class="nt">&lt;/MetaInformation&gt;</span>
</div><div class="line"><span class="nt">&lt;/Connection&gt;</span>
</div></pre></td></table></div></figure>

<p>I’ve removed most of the information, which you can see in the previous post.</p>

<p>As we’re trying to be careful with the file, we need to first validate the XML has a <code>MetaInformation</code> element, and then an existing <code>ServerRemoteManagementUrl</code> element.  If one, or neither, exist, then they get created. Not all hosts have iLO interfaces, such as virtual machines, so we need to verify the presence of a DNS record first, and then only create the entry if it exists.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div><div data-line="16" class="line-number"></div><div data-line="17" class="line-number"></div><div data-line="18" class="line-number"></div><div data-line="19" class="line-number"></div><div data-line="20" class="line-number"></div><div data-line="21" class="line-number"></div><div data-line="22" class="line-number"></div><div data-line="23" class="line-number"></div><div data-line="24" class="line-number"></div><div data-line="25" class="line-number"></div><div data-line="26" class="line-number"></div><div data-line="27" class="line-number"></div><div data-line="28" class="line-number"></div><div data-line="29" class="line-number"></div><div data-line="30" class="line-number"></div><div data-line="31" class="line-number"></div><div data-line="32" class="line-number"></div><div data-line="33" class="line-number"></div><div data-line="34" class="line-number"></div><div data-line="35" class="line-number"></div><div data-line="36" class="line-number"></div><div data-line="37" class="line-number"></div><div data-line="38" class="line-number"></div><div data-line="39" class="line-number"></div><div data-line="40" class="line-number"></div><div data-line="41" class="line-number"></div><div data-line="42" class="line-number"></div><div data-line="43" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nv">$ilo_str</span> <span class="p">=</span> <span class="s2">&quot;https://{0}-ilo&quot;</span>
</div><div class="line"><span class="nv">$ilo_host</span> <span class="p">=</span> <span class="s2">&quot;{0}-ilo&quot;</span>
</div><div class="line"> </div><div class="line"><span class="no">[XML]</span><span class="nv">$conns</span> <span class="p">=</span> <span class="nb">Get-Content</span> <span class="n">c</span><span class="err">:</span><span class="p">\</span><span class="n">temp</span><span class="p">\</span><span class="n">connections</span><span class="p">.</span><span class="n">xml</span>
</div><div class="line"> </div><div class="line"><span class="nv">$nodes</span> <span class="p">=</span> <span class="nv">$conns</span><span class="p">.</span><span class="n">ArrayOfConnection</span><span class="p">.</span><span class="n">SelectNodes</span><span class="p">(</span><span class="s2">&quot;Connection[ConnectionType[.=&#39;RDPConfigured&#39;]]&quot;</span><span class="p">)</span>
</div><div class="line"> </div><div class="line"><span class="k">if</span> <span class="p">(</span><span class="nv">$nodes</span> <span class="o">-eq</span> <span class="nv">$null</span><span class="p">)</span> <span class="p">{</span>
</div><div class="line">     <span class="k">continue</span><span class="err">;</span>
</div><div class="line"><span class="p">}</span>
</div><div class="line"> </div><div class="line"><span class="nv">$nodes</span> <span class="p">|</span> <span class="p">%{</span>
</div><div class="line">     <span class="nv">$node_name</span> <span class="p">=</span> <span class="nv">$_</span><span class="p">.</span><span class="n">Name</span>
</div><div class="line">     <span class="nv">$meta</span> <span class="p">=</span> <span class="nv">$_</span><span class="p">.</span><span class="n">SelectSingleNode</span><span class="p">(</span><span class="s2">&quot;./MetaInformation&quot;</span><span class="p">)</span>
</div><div class="line">     <span class="k">if</span> <span class="p">(</span><span class="nv">$meta</span> <span class="o">-eq</span> <span class="nv">$null</span><span class="p">)</span> <span class="p">{</span>
</div><div class="line">          <span class="nv">$meta</span> <span class="p">=</span> <span class="nv">$conns</span><span class="p">.</span><span class="n">CreateElement</span><span class="p">(</span><span class="s2">&quot;MetaInformation&quot;</span><span class="p">)</span>
</div><div class="line">          <span class="nv">$_</span><span class="p">.</span><span class="n">AppendChild</span><span class="p">(</span><span class="nv">$meta</span><span class="p">)</span>
</div><div class="line">     <span class="p">}</span>
</div><div class="line"> </div><div class="line">     <span class="nv">$ilo</span> <span class="p">=</span> <span class="nv">$meta</span><span class="p">.</span><span class="n">SelectSingleNode</span><span class="p">(</span><span class="s2">&quot;./ServerRemoteManagementUrl&quot;</span><span class="p">)</span>
</div><div class="line"> </div><div class="line">     <span class="k">if</span> <span class="p">(</span><span class="nv">$ilo</span> <span class="o">-eq</span> <span class="nv">$null</span><span class="p">)</span> <span class="p">{</span>
</div><div class="line"> </div><div class="line">          <span class="nv">$dns</span> <span class="p">=</span> <span class="nv">$null</span><span class="err">;</span>
</div><div class="line">          <span class="k">try</span> <span class="p">{</span>
</div><div class="line">               <span class="nv">$dns</span> <span class="p">=</span> <span class="no">[System.Net.Dns]</span><span class="err">::</span><span class="n">GetHostAddresses</span><span class="p">($(</span><span class="nv">$ilo_host</span> <span class="o">-f</span> <span class="nv">$node_name</span><span class="p">))</span>
</div><div class="line">          <span class="p">}</span>
</div><div class="line">          <span class="k">catch</span> <span class="no">[System.Exception]</span>
</div><div class="line">          <span class="p">{</span>
</div><div class="line">            <span class="c">## Doing Nothing ##</span>
</div><div class="line">          <span class="p">}</span>
</div><div class="line"> </div><div class="line">          <span class="k">if</span> <span class="p">(</span><span class="nv">$dns</span> <span class="o">-ne</span> <span class="nv">$null</span><span class="p">)</span> <span class="p">{</span>
</div><div class="line">               <span class="nv">$ilo</span> <span class="p">=</span> <span class="nv">$conns</span><span class="p">.</span><span class="n">CreateElement</span><span class="p">(</span><span class="s2">&quot;ServerRemoteManagementUrl&quot;</span><span class="p">)</span>
</div><div class="line">               <span class="nv">$ilo</span><span class="p">.</span><span class="n">InnerText</span> <span class="p">=</span> <span class="nv">$ilo_str</span> <span class="o">-f</span> <span class="nv">$node_name</span>
</div><div class="line">               <span class="nv">$meta</span><span class="p">.</span><span class="n">AppendChild</span><span class="p">(</span><span class="nv">$ilo</span><span class="p">)</span>
</div><div class="line">          <span class="p">}</span>
</div><div class="line"> </div><div class="line">     <span class="p">}</span>
</div><div class="line"> </div><div class="line"><span class="p">}</span>
</div><div class="line"> </div><div class="line"><span class="nv">$conns</span><span class="p">.</span><span class="n">Save</span><span class="p">(</span><span class="s2">&quot;C:\temp\connections_2.xml&quot;</span><span class="p">)</span>
</div></pre></td></table></div></figure>

<p>Again, working with a copy of the original file, I use some crafty XPath queries again to only select connections that are RDP.  I then loop through the connections/nodes, and extract the name. Lines 14-18 test for the presence of the MetaInformation element, and create it if it doesn’t exist.  Line 20 checks for the ServerRemoteManagementUrl element, if it’s not there, it creates it proceeds with DNS validation.</p>

<p>Lines 24-31 perform a DNS lookup, unfortunately it returns an exception rather than a <code>$null</code> or empty object, so I had to throw in some quick dummy catch code that doesn’t really do anything.  If a DNS record is returned it creates the new element, and adds it to the MetaInformation element. For the final step, I saved it to a second file so I could do a comparison between the files to make sure it did as I expected.</p>

<p>One thing to note about adding elements to an XML document is that the CreateElement function (lines 16 and 34) are not executed against the node you are adding the element to, they are executed against the document root.  This is so that the element gets all the correct name space information.  You then append your element to the existing element.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Removing XML Elements using PowerShell]]></title>
<link href="http://jon.netdork.net/2013/01/09/removing-xml-elements-using-powershell/"/>
<updated>2013-01-09T19:35:00-08:00</updated>
<id>http://jon.netdork.net/2013/01/09/removing-xml-elements-using-powershell</id>
<category term="PowerShell" />

      <content type="html"><![CDATA[<p>Every now and again I have to strip out elements from an XML file.  In this case, I was doing some cleanup of my <a href="http://remotedesktopmanager.com/" title="Remote Desktop Manager">Remote Desktop Manager</a> configuration file.  When I first started my current job, to save a lot of discovery, my boss shared his configuration file.  Unfortunately the configuration file had a lot of hosts that had duplicate configuration information that wasn’t relevant because the “duplicate” option had been used to copy existing hosts.  This meant stuff like host description had been copied.</p>

<p>Remote Desktop Manager (RDM) uses an XML file for its configuration, which makes editing it really easy.  To clean up the invalid descriptions, I used a little PowerShell and some XML know-how.  Here is an example entry I need to clean up…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div></pre></td><td class="main  xml"><pre><div class="line">  <span class="nt">&lt;Connection&gt;</span>
</div><div class="line">    <span class="nt">&lt;ConnectionType&gt;</span>RDPConfigured<span class="nt">&lt;/ConnectionType&gt;</span>
</div><div class="line">    <span class="nt">&lt;Events</span> <span class="nt">/&gt;</span>
</div><div class="line">    <span class="nt">&lt;Group&gt;</span>MyDomain\App Servers\DEV<span class="nt">&lt;/Group&gt;</span>
</div><div class="line">    <span class="nt">&lt;ID&gt;</span>73146eeb-caf9-4579-a146-41f7330261a6<span class="nt">&lt;/ID&gt;</span>
</div><div class="line">    <span class="nt">&lt;MetaInformation</span> <span class="nt">/&gt;</span>
</div><div class="line">    <span class="nt">&lt;Name&gt;</span>SERVER1<span class="nt">&lt;/Name&gt;</span>
</div><div class="line">    <span class="nt">&lt;ScreenSize&gt;</span>R1280x800<span class="nt">&lt;/ScreenSize&gt;</span>
</div><div class="line">    <span class="nt">&lt;Stamp&gt;</span>5f8a9830-fc2e-440e-a72b-f889d5b17a5b<span class="nt">&lt;/Stamp&gt;</span>
</div><div class="line">    <span class="nt">&lt;Url&gt;</span>SERVER1<span class="nt">&lt;/Url&gt;</span>
</div><div class="line">    <span class="nt">&lt;Description&gt;</span>HP Command View EVA<span class="nt">&lt;/Description&gt;</span>
</div><div class="line">  <span class="nt">&lt;/Connection&gt;</span>
</div></pre></td></table></div></figure>

<p>And here is the PowerShell that is used to cleanup the file.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="no">[xml]</span><span class="nv">$xml</span> <span class="p">=</span> <span class="nb">Get-Content</span> <span class="n">C</span><span class="err">:</span><span class="p">\</span><span class="n">Temp</span><span class="p">\</span><span class="n">Connections</span><span class="p">.</span><span class="n">XML</span>
</div><div class="line"> </div><div class="line"><span class="nv">$node</span> <span class="p">=</span> <span class="nv">$conns</span><span class="p">.</span><span class="n">SelectSingleNode</span><span class="p">(</span><span class="s2">&quot;//Description[.=&#39;HP Command View EVA&#39;]&quot;</span><span class="p">)</span>
</div><div class="line"><span class="k">while</span> <span class="p">(</span><span class="nv">$node</span> <span class="o">-ne</span> <span class="nv">$null</span><span class="p">)</span> <span class="p">{</span>
</div><div class="line">    <span class="nv">$node</span><span class="p">.</span><span class="n">ParentNode</span><span class="p">.</span><span class="n">RemoveChild</span><span class="p">(</span><span class="nv">$node</span><span class="p">)</span>
</div><div class="line">    <span class="nv">$node</span> <span class="p">=</span> <span class="nv">$conns</span><span class="p">.</span><span class="n">SelectSingleNode</span><span class="p">(</span><span class="s2">&quot;//Description[.=&#39;HP Command View EVA&#39;]&quot;</span><span class="p">)</span>
</div><div class="line"><span class="p">}</span>
</div><div class="line"> </div><div class="line"><span class="nv">$xml</span><span class="p">.</span><span class="n">save</span><span class="p">(</span><span class="s2">&quot;C:\Temp\Connections.XML&quot;</span><span class="p">)</span>
</div></pre></td></table></div></figure>

<p>Pretty simple, but here is how it works.  The first line is pretty obvious, it’s getting the content of the file<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.  It then explicitly converts the array object into XML using <code>[xml]</code>.  The next bit is where it gets a little harder, and requires a little knowledge of <a href="http://en.wikipedia.org/wiki/XPath" title="Wikipedia; XPath">XPath</a> syntax.  The code is looking to select a single node, that has the name “Description”, with the data in it that says ‘HP Command View EVA’.  If it’s found, it’ll return a XMLElement object, otherwise <code>$node</code> ends up being <code>$null</code>.  This gives us the ability to wrap the search in a loop, and remove the elements we don’t need.  To remove the element, you have to tell the parent node to remove it, so you ask the node to go back to the parent to remove itself, a little weird, but it works.  The final step is to go back and save it to a file.</p>

<p>The hardest bit about handling XML is knowing how XPath stuff works, once that is understood, the rest is usually pretty easy.  PowerShell treats XML as an object, so it’s easy to figure out what you can do with the objects using <code>Get-Member</code>.</p>

<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>Which I had copied to C:\Temp to make a backup of, instead of working on the real file.<a href="#fnref:1" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Updating iLO firmware using hponcfg and XML]]></title>
<link href="http://jon.netdork.net/2013/01/06/updating-ilo-firmware-using-hponcfg-and-xml/"/>
<updated>2013-01-06T20:10:00-08:00</updated>
<id>http://jon.netdork.net/2013/01/06/updating-ilo-firmware-using-hponcfg-and-xml</id>
<category term="Automation" /><category term="HP" /><category term="iLO" />

      <content type="html"><![CDATA[<p>In the course of updating all of our HP BladeSystem blades (BL465c) servers over the last few weeks, I’ve stumbled across some interesting things.  For example, you can updated all the iLO cards at once if you have an Onboard Administrator (OA), a TFTP server, and a little XML knowhow…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div></pre></td><td class="main  xml"><pre><div class="line"><span class="nt">&lt;RIBCL</span> <span class="na">VERSION=</span><span class="s">&quot;2.0&quot;</span><span class="nt">&gt;</span>
</div><div class="line">        <span class="nt">&lt;LOGIN</span> <span class="na">USER_LOGIN=</span><span class="s">&quot;Administrator&quot;</span> <span class="na">PASSWORD=</span><span class="s">&quot;UsingAutoLogin&quot;</span><span class="nt">&gt;</span>
</div><div class="line">                <span class="nt">&lt;RIB_INFO</span> <span class="na">MODE=</span><span class="s">&quot;write&quot;</span><span class="nt">&gt;</span>
</div><div class="line">                        <span class="nt">&lt;UPDATE_RIB_FIRMWARE</span> <span class="na">IMAGE_LOCATION=</span><span class="s">&quot;tftp://TFTP_SERVER/ilo3_150.bin&quot;</span> <span class="nt">/&gt;</span>
</div><div class="line">                <span class="nt">&lt;/RIB_INFO&gt;</span>
</div><div class="line">        <span class="nt">&lt;/LOGIN&gt;</span>
</div><div class="line"><span class="nt">&lt;/RIBCL&gt;</span>
</div></pre></td></table></div></figure>

<p>This gets saved as an XML file on the TFTP server, I named it update_firmware.xml.  The <code>USER_LOGIN</code> and <code>PASSWORD</code> fields do not matter as single sign-on is used from the OA.  The iLO update binary is put on the TFTP server as well (you should use the version applicable to the hardware you’re updating).  Then comes the easy bit.  SSH to the Onboard Administrator, and execute the hponcfg command as such:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">hponcfg ALL tftp://TFTP_SERVER/update_firmware.xml</div></pre></td></table></div></figure>

<p>If you only need to update a single blade, change <code>ALL</code> to the blade number.  Otherwise, this will download the iLO firmware update, push it to each of the iLO cards in the BladeSystem chassis, and then restart them.  This will not impact the running server.  You should see output like this once it has started:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div><div data-line="16" class="line-number"></div><div data-line="17" class="line-number"></div><div data-line="18" class="line-number"></div><div data-line="19" class="line-number"></div><div data-line="20" class="line-number"></div><div data-line="21" class="line-number"></div><div data-line="22" class="line-number"></div><div data-line="23" class="line-number"></div><div data-line="24" class="line-number"></div><div data-line="25" class="line-number"></div><div data-line="26" class="line-number"></div><div data-line="27" class="line-number"></div><div data-line="28" class="line-number"></div><div data-line="29" class="line-number"></div><div data-line="30" class="line-number"></div><div data-line="31" class="line-number"></div><div data-line="32" class="line-number"></div><div data-line="33" class="line-number"></div><div data-line="34" class="line-number"></div></pre></td><td class="main  xml"><pre><div class="line"><span class="c">&lt;!-- Transfering image: 0% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 10% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 20% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 30% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 40% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 50% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 60% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 70% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 80% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 90% complete --&gt;</span>
</div><div class="line"><span class="c">&lt;!-- Transfering image: 100% complete --&gt;</span>
</div><div class="line"> </div><div class="line">Bay 15: RIBCL results retrieved.
</div><div class="line"><span class="c">&lt;!-- ======== START RIBCL RESULTS ======== --&gt;</span>
</div><div class="line"> </div><div class="line"><span class="c">&lt;!--more output here--&gt;</span>
</div><div class="line"> </div><div class="line"><span class="cp">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
</div><div class="line"><span class="nt">&lt;RIBCL</span> <span class="na">VERSION=</span><span class="s">&quot;2.22&quot;</span><span class="nt">&gt;</span>
</div><div class="line"><span class="nt">&lt;RESPONSE</span>
</div><div class="line">    <span class="na">STATUS=</span><span class="s">&quot;0x0000&quot;</span>
</div><div class="line">    <span class="na">MESSAGE=</span><span class="s">&#39;No error&#39;</span>
</div><div class="line">     <span class="nt">/&gt;</span>
</div><div class="line"><span class="nt">&lt;INFORM&gt;</span>Firmware flash in progress [100%].<span class="nt">&lt;/INFORM&gt;</span>
</div><div class="line"><span class="nt">&lt;/RIBCL&gt;</span>
</div><div class="line"><span class="cp">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
</div><div class="line"><span class="nt">&lt;RIBCL</span> <span class="na">VERSION=</span><span class="s">&quot;2.22&quot;</span><span class="nt">&gt;</span>
</div><div class="line"><span class="nt">&lt;RESPONSE</span>
</div><div class="line">    <span class="na">STATUS=</span><span class="s">&quot;0x0000&quot;</span>
</div><div class="line">    <span class="na">MESSAGE=</span><span class="s">&#39;No error&#39;</span>
</div><div class="line">     <span class="nt">/&gt;</span>
</div><div class="line"><span class="nt">&lt;INFORM&gt;</span>Firmware flash completed successfully. iLO 3 reset
</div><div class="line">initiated.<span class="nt">&lt;/INFORM&gt;</span>
</div><div class="line"><span class="nt">&lt;/RIBCL&gt;</span>
</div></pre></td></table></div></figure>

<p>And that’s it, the magic is done.  Using hponcfg is possible from Windows as well when updating the local machines, so it’s quite possible to use the same XML (though I’ve not tested it).</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Five Saturdays]]></title>
<link href="http://jon.netdork.net/2013/01/05/five-saturdays/"/>
<updated>2013-01-05T18:50:00-08:00</updated>
<id>http://jon.netdork.net/2013/01/05/five-saturdays</id>


      <content type="html"><![CDATA[<p><em>Note</em>: I started writing this post at the beginning of December, but due to time issues, and working on blog migrations, I never got around to posting.  I’ve still decided to post because it throws in some PowerShell goodies.</p>

<p>The internet is such a gullable place.  Really it is. People post to Facebook nearly everything they see anywhere because it sounds like it’s quite possible, and usually accompanying some cool picture to make it seem more important.</p>

<p>An example of one that keeps coming up…</p>

<blockquote><p>This year, December has 5 Saturdays, 5 Sundays, and 5 Mondays. This only happens once every 824 years.</p></blockquote>

<p>Along with some blah blah crap about money, and Chinese superstitions.  I’m not sure why people don’t stop and think for just a second, and wonder how that could be possible.</p>

<p>Lets do some mental math, and see what happens.  December has 31 days, so regardless of what year it is, there will always be 3 days that occur 5 times that month. What are the chances that any other month with 31 days, would start on a Saturday?  You’d think pretty high, and I’m guessing a little more frequently than once every 824 years.</p>

<p>To prove the point, I threw together some PowerShell to figure out how many might occur within the next 20 years.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nv">$date</span> <span class="p">=</span> <span class="nb">Get-Date</span> <span class="s2">&quot;00:00:00 11/01/12&quot;</span>
</div><div class="line"> </div><div class="line"><span class="n">1</span><span class="p">..</span><span class="n">300</span> <span class="p">|</span> <span class="p">%{</span>
</div><div class="line">     <span class="nv">$date</span> <span class="p">=</span> <span class="nv">$date</span><span class="p">.</span><span class="n">AddMonths</span><span class="p">(</span><span class="n">1</span><span class="p">)</span>
</div><div class="line"> </div><div class="line">     <span class="nv">$mo</span> <span class="p">=</span> <span class="nv">$date</span><span class="p">.</span><span class="n">Month</span>
</div><div class="line">     <span class="nv">$yr</span> <span class="p">=</span> <span class="nv">$date</span><span class="p">.</span><span class="n">Year</span>
</div><div class="line">     <span class="nv">$dy</span> <span class="p">=</span> <span class="nv">$date</span><span class="p">.</span><span class="n">DayOfWeek</span>
</div><div class="line"> </div><div class="line">     <span class="nv">$dim</span> <span class="p">=</span> <span class="no">[System.DateTime]</span><span class="err">::</span><span class="n">DaysInMonth</span><span class="p">(</span><span class="nv">$yr</span><span class="p">,</span> <span class="nv">$mo</span><span class="p">)</span>
</div><div class="line"> </div><div class="line">     <span class="k">if</span> <span class="p">((</span><span class="nv">$dim</span> <span class="o">-eq</span> <span class="n">31</span><span class="p">)</span> <span class="o">-and</span> <span class="p">(</span><span class="nv">$dy</span> <span class="o">-eq</span> <span class="no">[System.DayOfWeek]</span><span class="err">::</span><span class="n">Saturday</span><span class="p">))</span> <span class="p">{</span>
</div><div class="line">          <span class="s2">&quot;{0}`t{1}&quot;</span> <span class="o">-f</span> <span class="nv">$yr</span><span class="p">,</span> <span class="nv">$mo</span>
</div><div class="line">     <span class="p">}</span>
</div><div class="line"><span class="p">}</span>
</div></pre></td></table></div></figure>

<p>So what is this doing?  The first line is grabbing November 1st, and the it loops 300 times.  Each loop it adds a month, and figures out what day it is, and the number of days in the month.  If there are 31 days in the month, and the day is Saturday, it outputs the year and the month.  So how did it look? Did I get no results because I’m inside the 824 years?  Far from it…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div><div data-line="16" class="line-number"></div><div data-line="17" class="line-number"></div><div data-line="18" class="line-number"></div><div data-line="19" class="line-number"></div><div data-line="20" class="line-number"></div><div data-line="21" class="line-number"></div><div data-line="22" class="line-number"></div><div data-line="23" class="line-number"></div><div data-line="24" class="line-number"></div><div data-line="25" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">2012     12
</div><div class="line">2014     3
</div><div class="line">2015     8
</div><div class="line">2016     10
</div><div class="line">2017     7
</div><div class="line">2018     12
</div><div class="line">2020     8
</div><div class="line">2021     5
</div><div class="line">2022     1
</div><div class="line">2022     10
</div><div class="line">2023     7
</div><div class="line">2025     3
</div><div class="line">2026     8
</div><div class="line">2027     5
</div><div class="line">2028     1
</div><div class="line">2028     7
</div><div class="line">2029     12
</div><div class="line">2031     3
</div><div class="line">2032     5
</div><div class="line">2033     1
</div><div class="line">2033     10
</div><div class="line">2034     7
</div><div class="line">2035     12
</div><div class="line">2036     3
</div><div class="line">2037     8</div></pre></td></table></div></figure>

<p>So it looks like it occurs quite frequently. Lets also assume just for a second that they meant only December, if we look at the results, we can see it’s pretty consistent. 6 years until the next even, then 11 years, then another 6 years, much more frequently than 824 years.</p>

<p>As a side note, Snopes covers this issue as <a href="http://www.snopes.com/inboxer/trivia/fivedays.asp" title="Snopes; An August Event">well</a>.</p>

<p>So my tip of the day, if you feel the urge to repost somebody’s random image and something doesn’t seem right, hit Google or Bing, and search for part of the phrase and see what you come up with.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[WordPress to Octopress]]></title>
<link href="http://jon.netdork.net/2013/01/04/wordpress-to-octopress/"/>
<updated>2013-01-04T19:42:00-08:00</updated>
<id>http://jon.netdork.net/2013/01/04/wordpress-to-octopress</id>


      <content type="html"><![CDATA[<p>Well, it’s only taken me about 3 months of on-off messing about, but I’ve finally cut my blog over to using <a href="http://octopress.org" title="Octopress; A blogging framework for hackers">Octopress</a>.  It’s been a long ride with Wordpress but the overhead and all the fluff were more than I needed.  <a href="http://octopress.org" title="Octopress; A blogging framework for hackers">Octopress</a> is nice and simple, and just gets stuff done.</p>

<p>The hardest part was exporting and converting. The 6 years of Wordpress usage had me tinkering with all sorts of plugins to get various fun things working, but ultimately ended up being abandoned. Unfortunately after abandoning them, I nearly played clean-up and fixed all the data it left floating around.  One major example is the 4+ different code formatting plugins I’ve used.</p>

<p>I don’t remember all the steps I took to get it done, but have most of it documented. I’ll write it up some day.  For now, let <a href="http://twitter.com/j_angliss" title="Twitter; j_angliss">me</a> know if you spot anything terribly wrong.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Lync, Federation, and DNS]]></title>
<link href="http://jon.netdork.net/2012/07/18/lync-federation-and-dns/"/>
<updated>2012-07-18T00:00:00-07:00</updated>
<id>http://jon.netdork.net/2012/07/18/lync-federation-and-dns</id>
<category term="Lync" /><category term="Microsoft" /><category term="Work" />

      <content type="html"><![CDATA[<p>Over the last few weeks, I’ve been working on a Microsoft Lync pilot at work. One of the requirements was external federation.  This feature basically allows us to use instant messenger (IM) between users in both locations.  So for example, you are CompanyA and you do business on a regular basis with CompanyB and are both using Lync.  Federation allows you to add each other to your Lync clients, and talk to each other.</p>

<p>The configuration and implementation went pretty smoothly, but I was having intermittent issues with federation. The problem came up when adding an external company that hadn’t explicitly added us to their federated domains list.  Initially we had dismissed the issue as a firewall issue because we got federation working with some consultants, however I was later asked to add a vendor and started seeing the same issues.</p>

<p>After some testing, I wasn’t getting any closer, so I enabled the client logging options in the Lync client. Those are found under Options, General, and “Turn on Logging in Lync”.  This writes a log file to a Tracing folder under your user profile directory (C:\Users\username\Tracing).  When I started digging into the logs, some errors popped out at me.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">ms-diagnostics: 1027;reason="Cannot route this type of SIP request to or from federated partners";
</div></pre></td></table></div></figure>

<p>The other error that popped out at me was:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">ms-diagnostics:  1034;reason="Previous hop federated peer did not report diagnostic information";
</div></pre></td></table></div></figure>

<p>Without doing much digging, the first suggests the request I’d sent to the vendor couldn’t be routed, and the second reports that no error explaining why it couldn’t be routed was returned from the remote side.  This made me think it was a potential firewall issue again.  Doing the basic testing of validating that our Edge server was accepting incoming connections, and I could connect to the vendors edge server, I eliminted the firewall being an issue. This got me really scratching my brain.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7600549710/" title="Flickr; j_angliss - Lync SIP Stack Trace"><img src="http://farm9.staticflickr.com/8427/7600549710_2bbd84b352_q.jpg" width="150" height="150" style="border: 0px; padding-right: 5px;" align="left" /></a> I ran a SIP stack trace from the Lync Edge server and saw more unusual errors, such as “504 Server time-out”. This was beginning to frustrate me, I had confirmed that both servers could talk to each other, why were they getting timeouts?</p>

<p>I decided to go back to basics, start at the very bottom.  First thing was connectivity, that we already established by using telnet to the servers. The next was DNS. Lync, like a lot of Microsoft products, takes advantage of Service Records (SRV) in DNS.  This record tells the requesting client the protocol, port, and host to connect to.  In this case, the Edge server is looking for the SRV record for the entry _sipfederatiltls._tcp.sipdomain.com.  The response should look something like this:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">_sipfederationtls._tcp.sipdomain.com. 300 IN SRV 0 0 5061 sipexternal.sipdomain.com.
</div></pre></td></table></div></figure>

<p>So the protocol is TCP, the port is 5061, and the server I need to connect to is sipexternal.sipdomain.com.  I ran a check against our domain, and the vendors domain, and both came back with records. Except, with them being so close together on the screen, I immediately spotted an issue.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">_sipfederationtls._tcp.sipdomain.com. 300 IN SRV 0 0 5601 sipexternal.mysipdomain.com.
</div><div class="line">_sipfederationtls._tcp.sipdomain.com. 3600 IN SRV 0 0 5061 sipexternal.vendorsipdomain.com.
</div></pre></td></table></div></figure>

<p>Ignoring the different in 300 and 3600, the Time-To-Live of the record, the next difference was the port numbers.  Looks like I made a simple transposition of numbers. I did a quick test from outside the firewall, and confirmed that 5601 was not open. I went back through the firewall change tickets, and confirmed I had requested 5061, and the Lync configuration was also set to 5061.</p>

<p>A quick DNS change for the SRV record, fixing the port, and within 10 minutes I received 3 notifications from the vendor that they had staff adding me to their contact lists.</p>

<p>One of the things I’ve come to learn over the years, whenever there is something awfully quirky going on, and you cannot quite figure out what’s causing it, take a look at DNS.  I’ve had a number of issues that have resulted in being a simple DNS issue. In this case, it was simple human error, but boiled down to be DNS saying one thing, and it should have been something else.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Lync, Exchange Unified Messaging, and TLS]]></title>
<link href="http://jon.netdork.net/2012/07/18/lync-exchange-unified-messaging-and-tls/"/>
<updated>2012-07-18T00:00:00-07:00</updated>
<id>http://jon.netdork.net/2012/07/18/lync-exchange-unified-messaging-and-tls</id>
<category term="Lync" /><category term="Microsoft" />

      <content type="html"><![CDATA[<p>One of the cool things about Exchange is a role called Unified Messaging (UM).  This role allows you to bridge voice messaging, call routing, and emails, all into a convenient package. What’s even better, you can get Lync to integrate right into that feature set too, giving your Lync system a voicemail system.</p>

<p>Part of our pilot program was to setup Lync and Exchange UM. This was to allow us to demonstrate that Lync and our existing Exchange infrastructure could potentially replace the older PBX style system, while giving us cost savings across the board.  Configuring the Lync and UM integration is pretty easy, <a href="http://www.lynclog.com/2011/04/integrating-exchange-um-with-lync-2010.html" title="Unified Communications with Microsoft; Integrating Exchange UM with Lync 2010">this site</a> gives a great step-by-step walk through of the process. As we were working with consultants during the installation, they walked us through the steps, with a minor deviation to the instructions on that site.</p>

<p>When it came time to test, we called the UM extension number, and got a fast busy.  Because it was close to end of day, we thought about giving it time to perform replication at the AD level as contacts and AD records are created as part of the process.  Unfortunately the next morning, the issue was still around.  Digging about, we confirmed all the settings were correct, however we were seeing weird errors regarding TLS and certificate names in the Application log on the UM server…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">The Unified Messaging server failed to exchange the required certificates with an IP gateway to enable Transport Layer Security
</div><div class="line">(TLS) for an incoming call. Please check that this is a configured TLS peer and that the certificates being used are correct. More
</div><div class="line">information: A TLS failure occurred because the target name specified in the certificate isn't correct. The error code = 0x1 and the message = Incorrect function.. Remote certificate:
</div><div class="line">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</div><div class="line">(Lyncpool.internaldomain.local). Remote end point: 10.10.10.17:50574.
</div><div class="line">Local end point: 10.10.102.27:5061.
</div></pre></td></table></div></figure>

<p>The error suggested we were seeing an issue with the SSL certificate on the Lync pool front end server.  The first thing to check was that the Subject Name (SN) for the SSL certificate was the same as the name used for the UM IP gateway (Lync pool).</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7600743842/" title="UMDialPlan_01 by Jon Angliss, on Flickr"><img src="http://farm8.staticflickr.com/7278/7600743842_13bb70219d_t.jpg" width="100" height="33" alt="UMDialPlan_01" align="left" style="border: 0px; padding-right: 5px;" /></a> We verified that the SN matched the UM IP gateway, and that the fingerprint reported by the error message above (which I changed if you didn’t guess) matched.  Next was to make sure the certificate chain wasn’t broken. Both servers had a correct certificate chain, and because they were internal certificates issued from our own CA server, the full chain of trust was available. We verified that both servers could open the others’ certificate and also saw the full chain.</p>

<p>We then went back and revalidated all the configurations again, and we didn’t spot anything obvious, the consultants were stumped.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7600743848/" title="UMDialPlan_03 by Jon Angliss, on Flickr"><img src="http://farm9.staticflickr.com/8423/7600743848_240dee84b9_t.jpg" width="100" height="60" alt="UMDialPlan_03" align="right" style="padding-left: 9px; border: 0px;" /></a> After several hours of bashing our heads against it, the consultants started throwing out some wild ideas, such as us using an unrecommended TLD in the cert, and some other bits and pieces too. I found those a little hard to follow, but continued to research. Going back over the post we’d discovered on UM configuration, I scoured the images looking for something we may have missed.  It wasn’t until I got to the very last image that I spotted the issue…</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7600743842/" title="UMDialPlan_01 by Jon Angliss, on Flickr"><img src="http://farm8.staticflickr.com/7278/7600743842_13bb70219d_t.jpg" width="100" height="33" alt="UMDialPlan_01" align="left" style="padding-right: 5px; border: 0px" /></a> The output of the script reports the pool name, associated dial plan, and the UM IP Gateway.  When I looked in the Exchange Management console, the “Associated UM IP gateways” field was empty (highlighted with red border as filled in), suggesting that the dial plan had no gateway assigned. When I discussed it with the other team member we remembered that the step to run the ExchUCUtil.ps1 script was done <em>before</em> executing the OcsUmUtil.exe process.  We believe that the order of execution resulted in some entries not being updated with the correct information, which in turn made Exchange UM have issues matching an UM IP gateway to a dial plan.  After re-executing the ExchUCUtil.ps1 script on the UM server, the UM IP Gateway field was populated with “1:1”, which matched the UM IP Gateway tab for the Lync Front End server.</p>

<p>Less than a minute after we confirmed the field had been populated with information, we ran a test call to the UM extension, and was greeted with the friendly UM voicemail system.</p>

<p>This is a weird case where an error message took us down the wrong path, if it had been a little clearer, it may have steered us in the right direction.  A better error, obviously, would be to report that the inbound call was not matched to the calling UM IP Gateway. We probably would have had the issue resolved in about 10 minutes, instead of 2 days.</p>

<p>As a side note, the SSL certificates must be configured correctly as well, otherwise you will get exactly the same error message.  This is why we went down the path of examining the certificates very closely. The UM server SN must be the Fully Qualified Domain Name (FQDN) of the server, and the UM IP Gateway SN has to be that of the Lync Front End server.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[DL585, Hardware Monitors, and Progress]]></title>
<link href="http://jon.netdork.net/2012/07/17/dl585-hardware-monitors-and-progress/"/>
<updated>2012-07-17T00:00:00-07:00</updated>
<id>http://jon.netdork.net/2012/07/17/dl585-hardware-monitors-and-progress</id>
<category term="General Ramblings" />

      <content type="html"><![CDATA[<p>A couple of weeks ago, I <a href="https://twitter.com/j_angliss/status/223087931525570560" title="Twitter; j_angliss">tweeted</a> about a server that had a blinking health light. After some poking around, I discovered that WBEM was reporting everything was A-OK with the server, but flipping the management tools to using SNMP reported a memory failure.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7594107290/" title="Flickr; j_angliss - DL585 Health Status Board"><img src="http://farm9.staticflickr.com/8165/7594107290_19c1e711b0_q.jpg" style="border: 0; padding-right: 5px; width: 150; height: 150;" align="left" /></a>After scheduling some down time to replace the memory, I went to slide the server out on the rails, and discovered that the HP ProLiant DL585 G1 series servers has the health status board on the top of the chassis. This confused me because all the other servers we have have either a pop out tray with the information on, or some kind of LCD up from that reports the status.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7594106164/" title="Flickr; j_angliss - DL585 Instructions"><img src="http://farm9.staticflickr.com/8025/7594106164_f95e2e60fc_q.jpg" style="border: 0; padding-left: 5px; width: 150; height: 150;" align="right" /></a> What caught me by surprise was the fact that the server had the full hardware layout instructions on the top of the server.  It’s been a long time since I’ve seen this. Granted it is an old server (G1 class servers are getting a little long in the tooth), but it was nice to see the full details right where I needed them, and not having to go hunting through HPs terrible support site for the details.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7594103888/" title="Flickr; j_angliss - DL585 Hardware Health Board"><img src="http://farm8.staticflickr.com/7277/7594103888_14851a4128_q.jpg" style="border:0; padding-right: 5px; width: 150; height: 150;" align="left" /></a>What’s even more interesting to me was the hardware health status board.  On the newer servers, this is usually smaller than a credit card, and about as thick as 3 quarters stacked on top of each other.  In this DL585, the board is the size of a large network card, with multiple LEDs feeding clear plastic shafts that pipe to another set on the bottom of the chassis top.</p>

<p>I find it interesting to see how hardware configurations have grown, and changed over time, even the very small things.  I don’t see many servers with instructions on any more, probably a money saver for the vendors. I also don’t see much in the way of big health boards any more, managing to squeeze so much into a tiny board now. The advancement in chips and technologies has made the server realm quite interesting to poke around in.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Move-VM and Explicit Destination]]></title>
<link href="http://jon.netdork.net/2012/07/08/move-vm-and-explicit-destination/"/>
<updated>2012-07-08T00:00:00-07:00</updated>
<id>http://jon.netdork.net/2012/07/08/move-vm-and-explicit-destination</id>
<category term="PowerShell" /><category term="Work" />

      <content type="html"><![CDATA[<p>Due to a weird BIOS error, most of our ESX hosts have thrown a memory warning. This is a known issue, and HP want you to update the BIOS before doing any further troubleshooting, so I scheduled a change window to upgrade all the hosts in our cluster (12 in this cluster). While working on the upgrades, I stumbled across a weird issue with Move-VM.</p>

<p>Our clusters run <a href="http://www.vmware.com/products/drs/overview.html" title="VMware vSphere; Distributed Resource Scheduler">Distributed Resource Scheduler (DRS)</a>, which allows the cluster to migrate guests seamlessly between the hosts when resources become constrained. One of the handy features is when you put a host into maintenance mode, it automatically moves all the guests off of that host. However, because I wanted to make sure all the guests migrated, and manage the alerts in our monitoring system, I threw together a quick script using PowerCLI so I could move all the dev/test/stage machines (lower monitoring thresholds), and then move the production servers after so I could see which boxes I had to mark as “unmanaged” in our monitoring software.</p>

<p>Moving the VMs is really easy with PowerCLI, for example, here is the basics of my script:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nv">$creds</span> <span class="p">=</span> <span class="nb">Get-Credentials</span>
</div><div class="line"><span class="nv">$conn</span> <span class="p">=</span> <span class="nb">Connect-ViServer</span> <span class="n">-Credentials</span> <span class="nv">$creds</span> <span class="n">vcenter</span><span class="p">.</span><span class="n">domain</span><span class="p">.</span><span class="n">tld</span>
</div><div class="line"><span class="nb">Move-VM</span> <span class="n">-Destination</span> <span class="n">newhost</span> <span class="n">-Name</span> <span class="n">guestname</span>
</div></pre></td></table></div></figure>

<p>Pretty simple, however I was noticing an oddity. When the guests were moving, they were losing the resource pools they were part of. Looking at the documentation for <a href="http://www.vmware.com/support/developer/windowstoolkit/wintk40u1/html/Move-VM.html" title="VMware PowerCLI; Move-VM">Move-VM</a>, the destination supports a folder, cluster, resource pool, or host. Because I wasn’t explicitly specifying the type as a host, it looks like all the other options were being set to null and the guest moved. So for the next batch of guests to move, I explicitly defined the type:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nv">$creds</span> <span class="p">=</span> <span class="nb">Get-Credentials</span>
</div><div class="line"><span class="nv">$conn</span> <span class="p">=</span> <span class="nb">Connect-ViServer</span> <span class="n">-Credentials</span> <span class="nv">$creds</span> <span class="n">vcenter</span><span class="p">.</span><span class="n">domain</span><span class="p">.</span><span class="n">tld</span>
</div><div class="line"><span class="nv">$dst_host</span> <span class="p">=</span> <span class="nb">Get-VMHost</span> <span class="n">-Name</span> <span class="n">newhost</span>
</div><div class="line"><span class="nb">Move-VM</span> <span class="n">-Destination</span> <span class="nv">$dst_host</span> <span class="n">-Name</span> <span class="n">guestname</span>
</div></pre></td></table></div></figure>

<p>After explicitly defining the type of destination, the guest moved host, but retained it’s resource pool allocations. Much better!  Obviously this only moves one guest, and each of our hosts has quite a few guests on it, so I used a Get-VM combination, some pipes, and such.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nv">$creds</span> <span class="p">=</span> <span class="nb">Get-Credentials</span>
</div><div class="line"><span class="nv">$conn</span> <span class="p">=</span> <span class="nb">Connect-ViServer</span> <span class="n">-Credentials</span> <span class="nv">$creds</span> <span class="n">vcenter</span><span class="p">.</span><span class="n">domain</span><span class="p">.</span><span class="n">tld</span>
</div><div class="line"><span class="nv">$dst_host</span> <span class="p">=</span> <span class="nb">Get-VMHost</span> <span class="n">-Name</span> <span class="n">newhost</span>
</div><div class="line"> </div><div class="line"><span class="nb">Get-VM</span> <span class="n">-Location</span> <span class="p">(</span><span class="nb">Get-VMHost</span> <span class="n">-Name</span> <span class="n">oldhost</span><span class="p">)</span> <span class="p">|</span> <span class="p">?{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">Name</span> <span class="o">-match</span> <span class="s2">&quot;DAL[DST]+.*&quot;</span> <span class="p">}</span> <span class="p">|</span> <span class="p">%{</span>
</div><div class="line">	<span class="nb">Move-VM</span> <span class="n">-Destination</span> <span class="nv">$dst_host</span> <span class="n">-Name</span> <span class="nv">$_</span>
</div><div class="line"><span class="p">}</span>
</div></pre></td></table></div></figure>

<p>The above code happily moves all our dev, stage, and test, machines off of oldhost onto newhost. From there, it was a case of finding the hosts in the monitoring software, unmanaging them all, and repeating the same code without the conditional name check.</p>

<p>So lesson learned, if a function accepts multiple input types, always explicitly define the type, as you cannot tell what might happen.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Downloading Files with PowerShell]]></title>
<link href="http://jon.netdork.net/2012/07/08/downloading-files-with-powershell/"/>
<updated>2012-07-08T00:00:00-07:00</updated>
<id>http://jon.netdork.net/2012/07/08/downloading-files-with-powershell</id>
<category term="PowerShell" />

      <content type="html"><![CDATA[<p>While messing around trying to diagnose an issue with IIS and compression yesterday I had a need to download a whole bunch of files all at once (or at least in quick succession).</p>

<p>Calling in the libraries from the .NET framework; this task is actually really easy.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nv">$src</span> <span class="p">=</span> <span class="s2">&quot;http://localhost/test.cmp&quot;</span>
</div><div class="line"><span class="nv">$dst</span> <span class="p">=</span> <span class="s2">&quot;F:\Downloads\junk\test_{0}.cmp&quot;</span>
</div><div class="line"><span class="nv">$web</span> <span class="p">=</span> <span class="nb">New-Object</span> <span class="n">System</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">WebClient</span>
</div><div class="line"> </div><div class="line"><span class="nv">$web</span><span class="p">.</span><span class="n">Headers</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="no">[System.Net.HttpRequestHeader]</span><span class="err">::</span><span class="n">AcceptEncoding</span><span class="p">,</span> <span class="s2">&quot;gzip&quot;</span><span class="p">)</span>
</div><div class="line"> </div><div class="line"><span class="n">1</span><span class="p">..</span><span class="n">100</span> <span class="p">|</span> <span class="p">%{</span>
</div><div class="line">	<span class="nv">$web</span><span class="p">.</span><span class="n">DownloadFile</span><span class="p">(</span><span class="nv">$src</span><span class="p">,</span> <span class="nv">$dst</span> <span class="o">-f</span> <span class="nv">$_</span> <span class="p">)</span>
</div><div class="line"><span class="p">}</span>
</div></pre></td></table></div></figure>

<p>The script is relatively self-explanatory. $src and $dst are the source and destination files.  For the destination I’ve used a formatted string allowing me to inject values into the string using C# style formatting.  I create a new object using the <a href="http://msdn.microsoft.com/en-us/library/tt0f69eh" title="MSDN Documentation; WebClient Class">System.Net.WebClient</a> type.  I then loop 100 times and download the same file, saving it to a different destination name each time.</p>

<p>The above code includes setting an “Accept-Encoding” header to the request.  Because I was testing a gzip compression issue on IIS I needed this header, otherwise <a href="http://msdn.microsoft.com/en-us/library/tt0f69eh" title="MSDN Documentation; WebClient Class">WebClient</a> just requests the raw data.  The caveat to this is that the file being written out to the $dst path is actually a gzip compressed file and not the actual data. This is fine for my testing because it made it quick and easy to see if compression had worked.  I was downloading a file containing 300KB of <a href="http://www.lipsum.com/" title="Lorem Ipsum">Lorem Ipsum</a> text. If it the IIS compression worked the file would be much smaller.  I’ll do another blog post soon about handling the gzip data and turning it back to the same as the source file.</p>

<p>I could have done the same using the <a href="http://jon.netdork.net/2010/07/08/powershell-and-bits/" title="The Geekery; Powershell and BITS">BITS service</a>, but BITS would probably have fixed the gzip’d file so I’d have to do more work to determine if compression had actually worked (examining logs, network trace, IIS trace, etc).  This worked out nicely.</p>

<p>As a side note, the “1..100” code is a shortcut for generating a sequence of numbers from 1 to 100.  If you opened a powershell prompt, typed “1..100” and hit enter it’d spew out all the digits from 1 through to 100.  Passing this on to foreach-object we can turn it into a loop.  The other way to do this would be to use a for, do, or while loop.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="k">for</span><span class="p">(</span> <span class="nv">$i</span><span class="p">=</span><span class="n">0</span><span class="err">;</span> <span class="nv">$i</span> <span class="o">-lt</span> <span class="n">100</span><span class="err">;</span> <span class="nv">$i</span><span class="p">++)</span> <span class="p">{</span>
</div><div class="line">  <span class="nv">$web</span><span class="p">.</span><span class="n">DownloadFile</span><span class="p">(</span><span class="nv">$src</span><span class="p">,</span> <span class="nv">$dst</span> <span class="o">-f</span> <span class="nv">$i</span><span class="p">)</span>
</div><div class="line"><span class="p">}</span>
</div><div class="line"> </div><div class="line"><span class="nv">$i</span><span class="p">=</span><span class="n">0</span>
</div><div class="line"><span class="k">do</span> <span class="p">{</span>
</div><div class="line">  <span class="nv">$web</span><span class="p">.</span><span class="n">DownloadFile</span><span class="p">(</span><span class="nv">$src</span><span class="p">,</span><span class="nv">$dst</span> <span class="o">-f</span> <span class="nv">$i</span><span class="p">)</span>
</div><div class="line">  <span class="nv">$i</span><span class="p">++</span>
</div><div class="line"><span class="p">}</span> <span class="k">until</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">-eq</span> <span class="n">100</span><span class="p">)</span>
</div><div class="line"> </div><div class="line"><span class="nv">$i</span> <span class="p">=</span> <span class="n">0</span>
</div><div class="line"><span class="k">while</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">-lt</span> <span class="n">100</span><span class="p">)</span> <span class="p">{</span>
</div><div class="line">  <span class="nv">$web</span><span class="p">.</span><span class="n">DownloadFile</span><span class="p">(</span><span class="nv">$src</span><span class="p">,</span> <span class="nv">$dst</span> <span class="o">-f</span> <span class="nv">$i</span><span class="p">)</span>
</div><div class="line">  <span class="nv">$i</span><span class="p">++</span>
</div><div class="line"><span class="p">}</span>
</div></pre></td></table></div></figure>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[DL365 G5 battery location]]></title>
<link href="http://jon.netdork.net/2012/05/31/dl365-g5-battery-location/"/>
<updated>2012-05-31T00:00:00-07:00</updated>
<id>http://jon.netdork.net/2012/05/31/dl365-g5-battery-location</id>
<category term="Work" />

      <content type="html"><![CDATA[<p>Sometimes it’s hard to understand hardware design (no pun intended). I can understand there are complex requirements, depending on what’s being designed.  Today I stumbled on what I’d call a pretty odd design flaw, but can see why it was done with poor foresight.</p>

<p>In this case, I’m referring to the design of HPs DL365 G5 servers.  Particularly the decision for the location of the storage controller’s battery. I understand that 1U servers have some very specific, and complex requirements, such as:</p>

<ul>
  <li>Must fit all the stuff in a small space</li>
  <li>Must have good air flow</li>
  <li>Must provide easy access to hot-swap parts</li>
</ul>

<p>Earlier this month we got an alarm on a server that the battery had gone bad, and was no longer holding a charge. I scheduled downtime, made sure we had a battery on hand, put in a change ticket, and set to work.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7311553406/in/set-72157629990979024"><img style="border:0; padding-right: 5px;" src="http://farm9.staticflickr.com/8166/7311553406_ce01f8289e_q.jpg" alt="DL365 Fan" title="DL365 Fans" align="left" /></a> After powering down the server, and removing the top cover, I set out to find the battery. The storage controller was next to the memory banks, and had 3 cables coming from it. 2 were obviously for the HDD back planes, the third, a little thinner, disappeared behind some fans, and into the front of the case.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7311533668/in/set-72157629990979024/"><img style="border:0; padding-left: 5px;" src="http://farm8.staticflickr.com/7078/7311533668_06a4a64494_q.jpg" alt="DL365 Fan" title="DL365" align="right" /></a> If you take a look at the picture to the right, and look above the center fan bank, you can see a thin black cable disappearing under the chassis. A closer look is in <a href="http://www.flickr.com/photos/j_angliss/7311551912/in/set-72157629990979024/">this picture</a>. From the front, it’s hiding right above the middle drive behind <a href="http://www.flickr.com/photos/j_angliss/7311532232/in/set-72157629990979024/">this grill</a>.</p>

<p>To remove the fan bank is a project on its own. Dell uses nice quick release containers, squeeze some colored tabs, and stuff just pops apart. To get these out, I had to use a flathead screwdriver to pry the metal tabs out the way. Well, they’re not really tabs. They were about 2 inches long, and about the same deep, and not flexible in the slightest.</p>

<p><a href="http://www.flickr.com/photos/j_angliss/7311558268/in/set-72157629990979024/"><img style="border:0; padding-right: 5px;" src="http://farm8.staticflickr.com/7084/7311558268_6712e0d3c4_q.jpg" alt="DL365 Storage Controller Batter" align="left" /></a> Once removed, it should be a simple case of pulling on a small black tab.  This is where the design flaw comes in (as if the fact its hidden in there to begin with isn’t bad enough).  These storage batteries have a tendency to swell as they get older, even more so as they reach the end of their life. If you look at the picture to the left, you can see the bulge already.  Why is this a problem? Well 2 reasons, the first being fairly obvious… If it’s bulging, there is a chance for it to explode, or leak, all over the inside of the server, in particular onto the hard drives below it.  The second, is the design flaw, the battery is nicely wedged between 2 sheets of rivited metal, and when the battery swells, it does NOT want to come out.</p>

<p>It can take some ‘gentle’ pursuasion to evict the battery from it’s sanctuary without puncturing the first cell on the little board. In this case, I had to use a flat head screwdriver, and go through the grill at the front of the chassis above the drives to push it, while I carefully pulled from the other side at the same time.  There is a few more pictures of the swollen battery <a href="http://www.flickr.com/photos/j_angliss/sets/72157629990979024/">here</a>, but this <a href="http://www.flickr.com/photos/j_angliss/7311527148/in/set-72157629990979024/">one</a> shows it pretty well.</p>

<p>The battery was probably put in that location because it was the only free space left. Little consideration was taken for maintenance, or hardware faults, such as swelling batteries. I believe the G7 series has this issue resolved though.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Still Alive...]]></title>
<link href="http://jon.netdork.net/2012/05/15/still-alive/"/>
<updated>2012-05-15T00:00:00-07:00</updated>
<id>http://jon.netdork.net/2012/05/15/still-alive</id>
<category term="General Ramblings" />

      <content type="html"><![CDATA[<p>It has been a while since I’ve posted.  The last was on my string vs bash match up.  It got a fair bit of attention, with some great feedback, so I learnt some new stuff.  I’m going to try getting back to posting more regular posts, even if they aren’t always techy related<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.  For now, here’s what has been going on…</p>

<ul>
  <li>New job</li>
  <li>More volunteer work with CERT</li>
  <li>More volunteer work at school</li>
</ul>

<p>Generally as busy as before, but at the same time, a different kind of busy.</p>

<h2 id="job">Job</h2>
<p>The transition to a new job was probably one of the harder decisions I’ve had to make in a long time, but now I’ve settled in, I don’t regret it at all.  I’m getting my hands on a lot more stuff I didn’t have access to before, as well as taking lead on projects that were originally left to HQ folk. </p>

<p>The environment is a lot larger. I’ve gone from a handful of few racks with gear to 20+ full racks, not counting the volume of VM guests we have running.</p>

<p>Documentation is pretty limited, so I’m working on updating it all, starting with a full data center audit.  I’m also working on a Lync pilot, as well as updating monitoring and other projects.</p>

<h2 id="cert">CERT</h2>
<p>I’ll have a complete post on this one later.  In the meantime, you can read Christopher Webber’s post on <a href="http://cwebber.ucr.edu/2012/01/cert-and-operations-a-disaster-made-in-heaven/">CERT and Sys Admins</a>. </p>

<p>With tornadoes striking the DFW metroplex recently, we were asked to help with some cleanup operations. Post and pictures on that later.</p>

<p>So lots of new exciting stuff floating around, learning new stuff, getting my fingers into new toys and such. I’ll post more stuff as it comes up.</p>

<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>I do have some in the works on CERT and Emergency management.<a href="#fnref:1" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[PowerShell vs Bash... String processing face off]]></title>
<link href="http://jon.netdork.net/2012/03/07/powershell-vs-bash-string-processing-face-off/"/>
<updated>2012-03-07T00:00:00-08:00</updated>
<id>http://jon.netdork.net/2012/03/07/powershell-vs-bash-string-processing-face-off</id>
<category term="Bash" /><category term="Linux" /><category term="Optimization" /><category term="Performance" /><category term="PowerShell" />

      <content type="html"><![CDATA[<p>While working on a file cleanup project today, I had to work with a text file containing close to 2 million lines. I had to extract file names with a specific string within it.  I figured I could do it relatively quickly in PowerShell, but also realized it’d be a good opportunity to flex my Bash skills.  To say the results were interesting is an understatement (to me at least).  I picked up some tuning tricks while tinkering, which made some massive improvements.</p>

<!--more-->

<p>So we’ll set the grounds for the <em>battle</em>.</p>

<ul>
  <li>The script has to parse the file with ~2 million records</li>
  <li>It has to output to a file containing the file names to remove (all files with <em>02</em> in them)</li>
  <li>It has to output SQL statements to a file for cleaning a temporary table.</li>
  <li>The quickest processor wins.</li>
</ul>

<p>An example of the data in the file:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">Vehicle_ID,URL,DateDeleted,PhotoDeletedID
</div><div class="line">58331549,\3860\1111111174WC448544WC44854279176192.jpg,2012-03-03 11:37:35.080000000,224516659
</div><div class="line">58331549,\3860\1111111174WC448544WC44854279176194.jpg,2012-03-03 11:37:38.420000000,224516660
</div><div class="line">58331995,\2635\1111111199E1648779E164877279175843.jpg,2012-03-03 11:41:35.510000000,224516661
</div><div class="line">58050027,\5524\56840113_02_222222225WF265239_9.jpg,2012-03-03 12:42:41.537000000,224516931
</div></pre></td></table></div></figure>

<p>So the basic idea is to loop through the file, and find all lines that have <em>_02_</em> in them.  I then want to extract that file name (URL column) and the PhotoDeletedID.</p>

<p>Before I started scripting this in PowerShell, I realized that using <em>Get-Content</em> was completely out of the question. This is because <em>Get-Content</em> reads the entire file into memory, creates objects for each line, and then continues with the script.  Similarly, the use of <em>Import-CSV</em> will result in the same issue.  Similarly, I couldn’t cat the entire file in Bash, as it’d do the same kind of thing. This meant reading the file line by line.</p>

<p>So here are my initial Bash, and PowerShell scripts…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div><div data-line="16" class="line-number"></div><div data-line="17" class="line-number"></div><div data-line="18" class="line-number"></div><div data-line="19" class="line-number"></div><div data-line="20" class="line-number"></div><div data-line="21" class="line-number"></div><div data-line="22" class="line-number"></div><div data-line="23" class="line-number"></div><div data-line="24" class="line-number"></div><div data-line="25" class="line-number"></div><div data-line="26" class="line-number"></div><div data-line="27" class="line-number"></div><div data-line="28" class="line-number"></div><div data-line="29" class="line-number"></div><div data-line="30" class="line-number"></div><div data-line="31" class="line-number"></div><div data-line="32" class="line-number"></div><div data-line="33" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">$ck = [System.Diagnostics.Stopwatch]::StartNew()
</div><div class="line"> </div><div class="line">$base = "E:\Photos"
</div><div class="line">$file = "C:\Temp\photos\deleted_imgs.csv"
</div><div class="line">$sql = "delete from photo_deleted where PhotoDeletedID = {0}"
</div><div class="line"> </div><div class="line">$p_file = "C:\Temp\photos\ps_file.txt"
</div><div class="line">$p_sql = "C:\Temp\photos\ps_sql.txt"
</div><div class="line"> </div><div class="line">$fh = [System.IO.File]::OpenText($file)
</div><div class="line">try {
</div><div class="line">    for (;;)
</div><div class="line">    {
</div><div class="line">        $line = $fh.ReadLine()
</div><div class="line">        if ($line -eq $null) { break; }
</div><div class="line"> </div><div class="line">        if ($line -like '*_02_*') {
</div><div class="line">            $data = $line.Split(',')
</div><div class="line"> </div><div class="line">            $file = $base + $data[1]
</div><div class="line">            $rem = $sql -f $data[3]
</div><div class="line"> </div><div class="line">            Add-Content -Path $p_file $file
</div><div class="line">            Add-Content -Path $s_file $rem
</div><div class="line"> </div><div class="line">        }
</div><div class="line">    }
</div><div class="line">}finally {
</div><div class="line">    $fh.Close()
</div><div class="line">}
</div><div class="line"> </div><div class="line">$ck.Stop()
</div><div class="line">$ck.Elapsed
</div></pre></td></table></div></figure>

<p>On line 10, I am using .Net libraries to open the file, and loop through each line.  I’m then searching for <em>_02_</em> in the string (line 17), splitting the line, and writing it to the 2 files (line 23 and 24).</p>

<p>I used the following in bash…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">#!/bin/sh
</div><div class="line"> </div><div class="line">while read line
</div><div class="line">do
</div><div class="line">    if [[ "${line}" == *_02_* ]];
</div><div class="line">    then
</div><div class="line">        ID=`echo "${line}" | cut -d, -f4`
</div><div class="line">        URL=`echo "${line}" | cut -d, -f2,
</div><div class="line">        echo "delete from photo_deleted where PhotoDeletedID = ${ID}" &gt;&gt; bash_sql.txt
</div><div class="line">        echo "E:\images${URL}" &gt;&gt; bash_files.txt
</div><div class="line">    fi
</div><div class="line">done &lt; "deleted_imgs.csv"
</div><div class="line"> </div></pre></td></table></div></figure>

<p>This is the same kind of thing, it reads the file line by line (line 3 &amp; 12), looks for <em>_02_</em> line (line 5), uses the cut command to find the field it needs (line 7 &amp; 8), and writes them out to a file.</p>

<p>I then did a head to head execution. I kicked them both off before I headed to lunch.  I was gone for about an hour, and on return, the PowerShell script was still running, the bash script just finished.  The results of the bash script:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">$ time sh ./cleanup.sh
</div><div class="line"> </div><div class="line">real    60m12.949s
</div><div class="line">user    8m55.905s
</div><div class="line">sys     6m22.320s
</div></pre></td></table></div></figure>

<p>I gave the PowerShell script another 45 mins, and it still hadn’t finished.  In fact, comparison of the file size output showed that the PowerShell script was well behind the Bash script.  This shocked me, I was expecting better performance from PowerShell that this paltry showing.  I stopped the script, and started looking for ways to improve the speed.</p>

<p>One of the things I pointed out at the beginning (from experience) is that I just couldn’t use Get-Content or Import-CSV because of the memory usage required to load the nearly 2 million rows from the file.  I wondered if the issue was also reversed when writing out the file. The <em>Add-Content</em> command is opening the file, seeking the end of the file, writing the new line, and closing it… 2 million times.  This is a <em>very</em> expensive operation, so we need to tweak the way this runs.  Falling back to some .Net, I decided to use [System.IO.File] again, and create a file handle to use.</p>

<p>This is the modified PowerShell script…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div><div data-line="16" class="line-number"></div><div data-line="17" class="line-number"></div><div data-line="18" class="line-number"></div><div data-line="19" class="line-number"></div><div data-line="20" class="line-number"></div><div data-line="21" class="line-number"></div><div data-line="22" class="line-number"></div><div data-line="23" class="line-number"></div><div data-line="24" class="line-number"></div><div data-line="25" class="line-number"></div><div data-line="26" class="line-number"></div><div data-line="27" class="line-number"></div><div data-line="28" class="line-number"></div><div data-line="29" class="line-number"></div><div data-line="30" class="line-number"></div><div data-line="31" class="line-number"></div><div data-line="32" class="line-number"></div><div data-line="33" class="line-number"></div><div data-line="34" class="line-number"></div><div data-line="35" class="line-number"></div><div data-line="36" class="line-number"></div><div data-line="37" class="line-number"></div><div data-line="38" class="line-number"></div><div data-line="39" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">$ck = [System.Diagnostics.Stopwatch]::StartNew()
</div><div class="line"> </div><div class="line">$base = "E:\Photos"
</div><div class="line">$file = "C:\Temp\photos\deleted_imgs.csv"
</div><div class="line">$sql = "delete from photo_deleted where PhotoDeletedID = {0}"
</div><div class="line"> </div><div class="line">$p_file = "C:\Temp\photos\ps_file.txt"
</div><div class="line">$p_sql = "C:\Temp\photos\ps_sql.txt"
</div><div class="line"> </div><div class="line">$pf = [System.IO.File]::CreateText($p_file)
</div><div class="line">$ps = [System.IO.File]::CreateText($p_sql)
</div><div class="line"> </div><div class="line">$fh = [System.IO.File]::OpenText($file)
</div><div class="line">try {
</div><div class="line">    for (;;)
</div><div class="line">    {
</div><div class="line">        $line = $fh.ReadLine()
</div><div class="line">        if ($line -eq $null) { break; }
</div><div class="line"> </div><div class="line">        if ($line -like '*_02_*') {
</div><div class="line">            $data = $line.Split(',')
</div><div class="line"> </div><div class="line">            $file = $base + $data[1]
</div><div class="line">            $rem = $sql -f $data[3]
</div><div class="line"> </div><div class="line">            $pf.WriteLine($file)
</div><div class="line">            $ps.WriteLine($rem)
</div><div class="line"> </div><div class="line">        }
</div><div class="line">    }
</div><div class="line">}finally {
</div><div class="line">    $fh.Close()
</div><div class="line">}
</div><div class="line"> </div><div class="line">$pf.Close()
</div><div class="line">$ps.Close()
</div><div class="line"> </div><div class="line">$ck.Stop()
</div><div class="line">$ck.Elapsed
</div></pre></td></table></div></figure>

<p>The changes I made were really simple, I added line 10-11, to open the text file in write mode. I then changed the <em>Add-Content</em> line to WriteLine on line 26-27. I finally closed the file handles on line 35-36. I then re-executed the script…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">Days              : 0
</div><div class="line">Hours             : 0
</div><div class="line">Minutes           : 1
</div><div class="line">Seconds           : 59
</div><div class="line">Milliseconds      : 742
</div><div class="line">Ticks             : 1197426621
</div><div class="line">TotalDays         : 0.00138591044097222
</div><div class="line">TotalHours        : 0.0332618505833333
</div><div class="line">TotalMinutes      : 1.995711035
</div><div class="line">TotalSeconds      : 119.7426621
</div><div class="line">TotalMilliseconds : 119742.6621
</div></pre></td></table></div></figure>

<p>When I saw the results I practically fell off my chair. I couldn’t believe the actual numbers.  To compare, I verified the file sizes between the Linux batch…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">$ wc -l ps_*
</div><div class="line">  1018490 ps_file.txt
</div><div class="line">  1018490 ps_sql.txt
</div><div class="line"> </div><div class="line">$ wc -l bash_*
</div><div class="line">  1018490 bash_files.txt
</div><div class="line">  1018490 bash_sql.txt
</div></pre></td></table></div></figure>

<p><strong>Wow!</strong> The file sizes were the same, the row count was the same, and the execution time was about 1/30th the time.  Could we say PowerShell wins this? I think so!</p>

<p>But, I stepped back and looked at the Bash script, and wondered if it too could be optimized.  Maybe it was having the same issue with open/seek/write/close? How much of an impact is using echo/cut having on the script execution? Is there a better way to split strings?</p>

<p>I did some hunting around, and stumbled across 2 resources that gave me some ideas.  The first was on string splitting.  I’d completely forgotten about $IFS, and how strings get handled by bash, and <a href="http://stackoverflow.com/questions/918886/split-string-based-on-delimiter-in-bash" title="StackOverflow; linux - splitting string based on delimiter">this</a> little post reminded me.  <em><a href="http://tldp.org/LDP/abs/html/internalvariables.html#IFSREF" title="TLDP; Advanced Bash Scripting - Internal Variables">$IFS</a></em> is an internal variable in Bash, which tells bash on what character to consider a field delimiter. By default it’s white space, and new line.  This can be changed, and Bash will consider a different field delimiter.  This is a really quick change.</p>

<p>The second was file handles.  This was a little harder to track down, but I stumbled across <a href="http://forums.devshed.com/unix-help-35/bash-scripting-using-file-descriptors-154812.html" title="BASH Scripting; Using File Descriptors">this</a> gem.  I’ve never used file descriptors before, but this post pointed me in the right direction.  So the tweaked script now looks like this:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div><div data-line="16" class="line-number"></div><div data-line="17" class="line-number"></div><div data-line="18" class="line-number"></div><div data-line="19" class="line-number"></div><div data-line="20" class="line-number"></div><div data-line="21" class="line-number"></div><div data-line="22" class="line-number"></div><div data-line="23" class="line-number"></div><div data-line="24" class="line-number"></div><div data-line="25" class="line-number"></div><div data-line="26" class="line-number"></div><div data-line="27" class="line-number"></div><div data-line="28" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">#!/bin/sh
</div><div class="line"> </div><div class="line">exec 5&lt;&gt; "bash_sql2.txt"
</div><div class="line">exec 6&lt;&gt; "bash_files2.txt"
</div><div class="line"> </div><div class="line">OIFS=${IFS}
</div><div class="line">IFS=","
</div><div class="line">while read line
</div><div class="line">do
</div><div class="line">#       echo "${line}"
</div><div class="line">        if [[ "${line}" == *_02_* ]];
</div><div class="line">        then
</div><div class="line">                DATA=(${line})
</div><div class="line">                ID="${DATA[3]}"
</div><div class="line">                URL="${DATA[1]}"
</div><div class="line">#               ID=`echo "${line}" | cut -d, -f4`
</div><div class="line">#               URL=`echo "${line}" | cut -d, -f2`
</div><div class="line"> </div><div class="line">                echo "delete from photo_deleted where PhotoDeletedID = ${ID}" &gt;&amp;5
</div><div class="line">                echo "E:\Images${URL}" &gt;&amp;6
</div><div class="line">        fi
</div><div class="line"> </div><div class="line">done &lt; "deleted_imgs.csv"
</div><div class="line"> </div><div class="line">IFS=${OIFS}
</div><div class="line"> </div><div class="line">exec 5&gt;&amp;-
</div><div class="line">exec 6&gt;&amp;-
</div></pre></td></table></div></figure>

<p>I made a copy of the existing <em>$IFS</em> string, and then changed it to a “,” character (line6-7).  I opened 2 new file handles descriptors to the files I wanted to write to (line 3-4).  On lines 13-15, I use the power of the <em>$IFS</em>, and get Bash to split the string into an array.  Lines 19-20 were tweaked to write to the file descriptors, and then they were closed in line 27-28.</p>

<p>So what’s the results?</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div></pre></td><td class="main  bash"><pre><div class="line"><span class="nv">$ </span><span class="nb">time </span>sh ./cleanup.sh
</div><div class="line"> </div><div class="line">real    5m8.391s
</div><div class="line">user    4m42.090s
</div><div class="line">sys     0m18.369s
</div></pre></td></table></div></figure>

<p>Another <strong>Wow!</strong>. Execution is down to about 8% of the original time, another massive improvement. Just to make sure I had the same results, I double checked the numbers:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div></pre></td><td class="main  plain"><pre><div class="line">$ wc -l bash_*.txt
</div><div class="line">  1018490 bash_files2.txt
</div><div class="line">  1018490 bash_files.txt
</div><div class="line">  1018490 bash_sql2.txt
</div><div class="line">  1018490 bash_sql.txt
</div></pre></td></table></div></figure>

<p>So same results, 8% execution time. I’d say those changes were a good improvement.</p>

<h2 id="conclusion">Conclusion</h2>
<p>So who do we call winner? Well, something I failed to disclose at the start was the platforms.  Initially my plan was to use Cygwin to do the Linux execution side of this. When I attempted to run the initial Linux script, execution was so slow, I could have gone back home, had dinner, come back, and it still wouldn’t have been done.</p>

<p>The initial PowerShell script had gone through about 10x the file in half the time the Cygwin execution had taken.  This meant I needed to run the Linux script else where, so I fell back to my personal Linux server. For comparison, my laptop (PowerShell) is running Intel Core2 Duo T7520 (2x 2Ghz) with 4GB RAM, while my server is running an older Intel Core2 6300 (2x 1.86Ghz) with 1GB RAM.</p>

<p>So, there is a little bit of difference. I’ll leave it up to you guys to decide who should be the winner, but I will probably call it a tie.  The differences in the hardware probably allow for one script to execute faster than the other.</p>

<p>I don’t often spend a lot of time tinkering with some of the scripts I throw together, but this was a fun exercise in performance tweaking, and shows how simple 1-5 line changes can make a substantial improvement over execution. Next time you throw together a script, see what performance tweaks you can do.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[eclipse, TFS Everywhere, and new files]]></title>
<link href="http://jon.netdork.net/2012/01/22/eclipse-tfs-everywhere-and-new-files/"/>
<updated>2012-01-22T00:00:00-08:00</updated>
<id>http://jon.netdork.net/2012/01/22/eclipse-tfs-everywhere-and-new-files</id>
<category term="General Ramblings" />

      <content type="html"><![CDATA[<p>I work in a mostly windows environment, until relatively recently, where we acquired a new company.  The new company was mostly Mac, so I acquired myself a Mac Air.  With that, I decided to see how much of my Windows life I could transport over there.  I use Microsoft’s Team Foundation Server for managing source control, so I had to find a good alternative to trying to get Visual Studio working on a Mac platform.  Fortunately back in 2009, Microsoft acquired a company called Teamprise, which developer a client that worked on a variety of platforms.  Microsoft re-released that as TFS Anywhere.  I use TFS Anywhere to edit a lot of the files in TFS on my Mac, via <a href="http://www.eclipse.org">Eclipse</a>.</p>

<p>A few weeks ago I stumbled on an odd issue where Eclipse wasn’t keeping in-sync with what TFS Anywhere was doing.  For example, we keep our Nagios configs checked into TFS for version control.  I was using the Mac, and had added several new contact files.  When I was back using my Windows machine, I told Eclipse to trigger the “Get Latest” function on TFS Anywhere, which it dutifully did, then threw an error…</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  bash"><pre><div class="line">The item <span class="nv">$/</span>infrastructure/Nagios/etc/objects/contacts/newcontact.cfg already exists
</div></pre></td></table></div></figure>

<p>It repeated this error for each of the new contacts I had added.  What appeared to be happening is TFS Anywhere was getting the files, notifying Eclipse the files were there, which triggered the project to add them to the file list, which then in turn triggered Eclipse to try an add them to TFS.  A nice little circle going there. I thought maybe it was just a quirk and closed the project.  When I reopened the project, the same error occurred again, this time I didn’t even tell Eclipse to do any updates, this occurred just on opening the project.</p>

<p>After some skimming around, I discovered this is likely a bug in TFS Anywhere, and the simple solution is to tell Eclipse to update the server information.  This is done using the “Team” context menu (right click the project), then selecting “Refresh Server Information”. Here is the <a href="http://social.msdn.microsoft.com/Forums/en-US/tee/thread/3377bf49-0dfc-4c0c-959b-203717bc6787/" title="MSDM Forums; Some files in project not attached to TFS">reference</a> post I found the details on.</p>

]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Linux Journal, digital editions, and Apple]]></title>
<link href="http://jon.netdork.net/2012/01/20/linux-journal-digital-editions-and-apple/"/>
<updated>2012-01-20T00:00:00-08:00</updated>
<id>http://jon.netdork.net/2012/01/20/linux-journal-digital-editions-and-apple</id>
<category term="Open Source" /><category term="Rantings" />

      <content type="html"><![CDATA[<p>I’ve been a long time subscriber to <a href="http://www.linuxjournal.org">Linux Journal</a>, my closest has a box filled with old editions, and my bookshelf no longer has space, so I was glad to see they were going fully digital. I know they had a digital edition before, but it was one format. I was hoping the switch would mean they would expand the formats.</p>

<!--more-->

<p>I was excited to see them finally publish formats in PDF, Mobi, and ePub. I was more interested in the latter because I have a Sony reader that handles ePub nicely. I get a nice email once a month with links to each of the formats. Quite handy.</p>

<p>Before I left on a trip to the corporate office in New York, I discovered there was an iPad app for Linux Journal, which allowed you to read the digital editions, so I decided to check it out. Installed easily, pretty easy to use, and looked good too. I opened the app, skimmed a few pages in the latest edition, it seemed a little slow at first, I assumed because it was still downloading some of the content. Once I’d visited a page, it loaded pretty quick afterwards. It displayed nicely, looked just like the old print magazine did. So I was happy.</p>

<p>I was happy until I was about 10k feet in the air, and was granted permission to use air-safe electronics. I opened up the edition I quickly skimmed at home, swipe past the first few pages, then get a pop-up telling me that I couldn’t read any more because it wasn’t online.</p>

<p>This is quite frustrating, fortunately I had planned the trip, and had several forms of entertainment planned out. I could pay the $25 for the flight to use the in-flight wifi, but that seems stupid, and expensive.</p>

<p>I’m not sure if the issue is with the app itself, or with Apple’s restrictions on publishers, but this limitation makes the iPad app rather useless, especially as I have the wifi only edition. Maybe I’m just not using it right. Does anybody else have any experience with it? Have you tried using it with Airplane mode?</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[PowerShell and SQLite]]></title>
<link href="http://jon.netdork.net/2011/11/27/powershell-and-sqlite/"/>
<updated>2011-11-27T00:00:00-08:00</updated>
<id>http://jon.netdork.net/2011/11/27/powershell-and-sqlite</id>
<category term="PowerShell" />

      <content type="html"><![CDATA[
<p>A while back I mentioned I was using SQLite with PowerShell.  I was doing this because I had to access the database for <a href="http://gpodder.org/" title="gPodder, a free podcast aggregator">gPodder</a> to tweak some of the subscriptions. A need came up again today after upgrading <a href="http://gpodder.org/" title="gPodder, a free podcast aggregator">gPodder</a> to the latest release, and having issues with it.</p>

<!--more-->

<p>The first task is to get the ADO.Net provider, which I found over <a href="http://sqlite.phxsoftware.com/" title="System.Data.SQLite ADO.NET Provider">here</a>.  The provider hasn’t been updated in a while, but still seems to work just fine. Next is loading the libraries, this is a case of calling the Assembly loader, so the code looks like this:</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="no">[void][System.Reflection.Assembly]</span><span class="err">::</span><span class="n">LoadFrom</span><span class="p">(</span><span class="s2">&quot;C:\Temp\System.Data.SQLite.DLL&quot;</span><span class="p">)</span>
</div></pre></td></table></div></figure>

<p>Remember to update the path to reflect the actual location.  I have <code>[void]</code> at the beginning to hide the output of the library being loaded. If you are having issues, try removing it to see any errors.</p>

<p>Next is just like using any data object.</p>

<figure class="code"><div class="highlight"><table><td class="line-numbers" aria-hidden="true"><pre><div data-line="1" class="line-number"></div><div data-line="2" class="line-number"></div><div data-line="3" class="line-number"></div><div data-line="4" class="line-number"></div><div data-line="5" class="line-number"></div><div data-line="6" class="line-number"></div><div data-line="7" class="line-number"></div><div data-line="8" class="line-number"></div><div data-line="9" class="line-number"></div><div data-line="10" class="line-number"></div><div data-line="11" class="line-number"></div><div data-line="12" class="line-number"></div><div data-line="13" class="line-number"></div><div data-line="14" class="line-number"></div><div data-line="15" class="line-number"></div><div data-line="16" class="line-number"></div><div data-line="17" class="line-number"></div><div data-line="18" class="line-number"></div><div data-line="19" class="line-number"></div><div data-line="20" class="line-number"></div><div data-line="21" class="line-number"></div><div data-line="22" class="line-number"></div><div data-line="23" class="line-number"></div><div data-line="24" class="line-number"></div><div data-line="25" class="line-number"></div><div data-line="26" class="line-number"></div><div data-line="27" class="line-number"></div><div data-line="28" class="line-number"></div><div data-line="29" class="line-number"></div><div data-line="30" class="line-number"></div><div data-line="31" class="line-number"></div></pre></td><td class="main  powershell"><pre><div class="line"><span class="nb">Add-Type</span> <span class="sh">@&#39;</span>
</div><div class="line"><span class="sh">public class Subscription</span>
</div><div class="line"><span class="sh">{</span>
</div><div class="line"><span class="sh">	public string url;</span>
</div><div class="line"><span class="sh">	public string title;</span>
</div><div class="line"><span class="sh">}</span>
</div><div class="line"><span class="sh">&#39;@</span>
</div><div class="line"> </div><div class="line"><span class="no">[Void][System.Reflection.Assembly]</span><span class="err">::</span><span class="n">LoadFrom</span><span class="p">(</span><span class="s2">&quot;C:\temp\System.Data.SQLite.DLL&quot;</span><span class="p">)</span>
</div><div class="line"><span class="nv">$cn</span> <span class="p">=</span> <span class="nb">New-Object</span> <span class="n">-TypeName</span> <span class="n">System</span><span class="p">.</span><span class="n">Data</span><span class="p">.</span><span class="n">SQLite</span><span class="p">.</span><span class="n">SQLiteConnection</span>
</div><div class="line"><span class="nv">$cn</span><span class="p">.</span><span class="n">ConnectionString</span> <span class="p">=</span> <span class="s2">&quot;Data Source=C:\temp\config\database.sqlite&quot;</span>
</div><div class="line"><span class="nv">$cn</span><span class="p">.</span><span class="n">Open</span><span class="p">()</span>
</div><div class="line"> </div><div class="line"><span class="nv">$cm</span> <span class="p">=</span> <span class="nb">New-Object</span> <span class="n">-TypeName</span> <span class="n">System</span><span class="p">.</span><span class="n">Data</span><span class="p">.</span><span class="n">Sqlite</span><span class="p">.</span><span class="n">SQLiteCommand</span>
</div><div class="line"><span class="nv">$sql</span> <span class="p">=</span> <span class="s2">&quot;select title,url from channels&quot;</span>
</div><div class="line"><span class="nv">$cm</span><span class="p">.</span><span class="n">Connection</span> <span class="p">=</span> <span class="nv">$cn</span>
</div><div class="line"><span class="nv">$cm</span><span class="p">.</span><span class="n">CommandText</span> <span class="p">=</span> <span class="nv">$sql</span>
</div><div class="line"> </div><div class="line"><span class="nv">$dr</span> <span class="p">=</span> <span class="nv">$cm</span><span class="p">.</span><span class="n">ExecuteReader</span><span class="p">()</span>
</div><div class="line"> </div><div class="line"><span class="nv">$subs</span> <span class="p">=</span> <span class="err">@</span><span class="p">()</span>
</div><div class="line"> </div><div class="line"><span class="k">while</span> <span class="p">(</span><span class="nv">$dr</span><span class="p">.</span><span class="n">Read</span><span class="p">())</span> <span class="p">{</span>
</div><div class="line">    <span class="nv">$sub</span> <span class="p">=</span> <span class="nb">New-Object</span> <span class="n">Subscription</span>
</div><div class="line">	<span class="nv">$sub</span><span class="p">.</span><span class="n">url</span> <span class="p">=</span> <span class="nv">$dr</span><span class="p">.</span><span class="n">GetString</span><span class="p">(</span><span class="n">1</span><span class="p">)</span>
</div><div class="line">	<span class="nv">$sub</span><span class="p">.</span><span class="n">title</span> <span class="p">=</span> <span class="nv">$dr</span><span class="p">.</span><span class="n">GetString</span><span class="p">(</span><span class="n">0</span><span class="p">)</span>
</div><div class="line"> </div><div class="line">	<span class="nv">$subs</span> <span class="p">+</span> <span class="nv">$sub</span>
</div><div class="line"><span class="p">}</span>
</div><div class="line"> </div><div class="line"><span class="nv">$subs</span>
</div></pre></td></table></div></figure>

<p>In this code, I’m creating a custom object to hold the subscription data in it, loading the libraries, and querying the “channels” table from the file <code>c:\temp\config\database.sqlite</code>, and then outputting the Title, and URL for the feed.</p>

<p>The great thing about PowerShell is it’s ability to pull in, and use any of the .NET libraries, making it incredibly flexible for quick scripts, as well as more in-depth work. The above script took all of about 5 minutes, and got my podcast list back.</p>
]]></content>
    </entry>
  
</feed>
