tag:blogger.com,1999:blog-42790577437650955932024-03-04T23:57:24.855-08:00The Evening ReadAndrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.comBlogger39125tag:blogger.com,1999:blog-4279057743765095593.post-35808895279441785682014-02-21T21:32:00.000-08:002014-02-21T21:32:18.425-08:00AWS RDS Operations Design Patterns (Part 1)Having recently come across this otherwise <a href="http://wblinks.com/notes/aws-tips-i-wish-id-known-before-i-started/">excellent collection of AWS usage tips</a>, I was a bit disappointed in the RDS guidance. To often I see the RDS service adopted as a solution to avoid hiring a full-time DBA or to outsource the operations overhead of EC2. While the latter is an excellent choice, expectations for what infrastructure level actions are available in a managed service is frequently overlooked, and the former is a complete misconception.<br />
<section class="post-content"><h1 id="whatrdsis">
What RDS is</h1>
RDS is, first and foremost, a managed infrastructure and common automation. It is the EC2 you know and love, geographicly distributed, and managed through an API. You get your choice of instance class within a certain subset of instance types, a stripe of EBS volumes to match your capacity needs, and a bunch of traditional metrics and alarms.<br />
<h1 id="whatrdsisnot">
What RDS is not</h1>
Many adoptors assume that with the above, they also have access to, or elimenate the need for, a DBA with expertise on their particular application's schema and performance profile. That's not the case and leads to early adoption failure, or worse yet, a production deployment dependent on an unsupported (yet unrestricted) engine feature.<br />
<h1 id="theopstoolsbox">
The Ops tools box</h1>
In light of the previous comments, it sounds like the wrong tool for the job. On the contrary, it's the right tool for the right jobs. The key is to understand what those jobs are and when the limitations of a managed service have been reached.<br />
Over the next few posts, I'll cover RDS features for high availability and disaster recovery, their impact, and key indicators for their use.<br />
<ul>
<li>Snapshot and Point-in-Time Restores</li>
<li>Multi-AZ</li>
<li>Read Replication</li>
<li>ETL</li>
</ul>
<h2 id="snapshotvspointintimerestores">
Snapshot vs Point-in-Time Restores</h2>
The first and most basic tool for any operations team is backup and restore. RDS provides two native facilities for this, <a href="http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateSnapshot.html">Manual Snapshots</a> and <a href="http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html">Automatic Backups</a>. Aside from the obvious difference in the name of the restore process and it's implied use, RTO is affected based on when you PITR.<br />
Consider this: restoring from a full backup is faster and more deterministic when compared to a peicemeal restore. There's just too many variables involved. Was there a large DML? Schema changes? How many transactions are included? What is the transaction throughput of write ahead logging based on transaction size? All of these affect restores in the same way that lest work is required for a snapshot restore than a point-in-time restore in RDS. <br />
<blockquote>
Restoring 23 hours and 59 minutes of transactions could take longer and have a higher production impact in terms of availability when compared to losing data by rolling back to the last daily snapshot. ETL can close the data gap between newly ingested data and restored data.</blockquote>
General guidelines thus include regular restore testing, manual snapshot creation prior to large loads or DDL, and aligning the <a href="http://aws.amazon.com/rds/faqs/#25">daily backup window</a> with the lowest period of WriteIOPS. (More on Snapshot impact next time.)<br />
If there's one thing I must stress, its that you should enable Automatic Backups. <em>Now</em>. Just stop and go enable it. (Preferably during your lowest daily WriteIOPS!) Seriously, no one's going to blame you if you opt in to a feature which <a href="http://aws.amazon.com/rds/pricing/">barely costs anything</a>. <br />
<blockquote>
In fact, this is so important, here's a link to help get your started: <a href="https://console.aws.amazon.com/rds/">AWS Console: RDS</a></blockquote>
If you're the DBA, Developer, DevOps, or SysAdmin data is your company's lifeblood. The only person to blame if you don't take backups is you. So go set it up now.<br />
<h1 id="nextupmultiaz">
Next Up: Multi-AZ</h1>
There's a time and a place for sychronous replication and that's a completly different article.</section>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-10552767944596870202014-01-31T22:25:00.000-08:002014-01-31T22:25:11.937-08:00Introduction to DynamoDB with Node.jsTo get started with DynamoDB and the <a href="http://aws.amazon.com/developers/getting-started/nodejs/">AWS SDK for Node.js</a>, leveraging IAM Roles in a simple t1.micro is a great place to start.<br />
<br />
First, <a href="http://docs.aws.amazon.com/IAM/latest/UserGuide/creating-role.html">create an IAM Role</a> with a policy which permits all DynamoDB APIs for now:<br />
<br />
<pre><code><span style="font-size: x-small;">{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"dynamodb:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}</span></code></pre>
<code>
</code><br />
Once an instance is launched in that role, <a href="https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager">install Node</a> and load the AWS SDK module:<br />
<br />
<pre><code><span style="font-size: x-small;">$ npm install aws-sdk
$ node
></span></code></pre>
<code>
</code><br />
Because we deployed the EC2 instance in a Role, the SDK automaticlly assumes the IAM Role for temporary credential management. So let's load the SDK and point to the desired region:<br />
<br />
<pre><code><span style="font-size: x-small;">> var AWS = require('aws-sdk');
undefined
> AWS.config.update({region: 'us-west-2'});
undefined</span> </code></pre>
<code>
</code><br />
Having already created the <a href="http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStartedCreateTables.html">sample tables from documentation</a> based on the public <a href="http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SampleTablesAndData.html">DynamoDB documentation</a>, it's fairly easy to use the quick sample to query the tables in the region:<br />
<br />
<pre><code><span style="font-size: x-small;">> var db = new AWS.DynamoDB();
undefined
> db.listTables(function(err, data) {
... console.log(data.TableNames);
... });
{ service: ... }
> [ 'Forum', 'ProductCatalog', 'Reply', 'Thread' ]</span></code></pre>
<code>
</code><br />
And there we go, a simple start to the use of Node.js with IAM Roles in EC2 instance to list existing tables in a specific region.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-79096765986133420072014-01-29T22:43:00.001-08:002014-01-29T22:43:32.653-08:00Zero to Build Failed in 20 minutesIn the process of learning Node.js, I elected to build some basic projects in the language, but also to leverage source control (GitHub, of course) and Continuous Integration. The obvious choice for this project is Travis CI, which provides free build testing for open source repositories.<br />
<br />
First, you'll need to setup a .travis.yml. I shamelessly reviewed a few favorite node project's configurations along with the <a href="http://docs.travis-ci.com/user/languages/javascript-with-nodejs/" target="_blank">Travis CI help</a> before settling on the simple, concise:<br />
<br />
<pre><code>language: node_js
node_js:
- "0.11"
- "0.10"
- "0.8"
- "0.6"
</code></pre>
<br />
That's more than enough testing, as I'll probably only use the <code>0.10</code> branch and <code>0.11</code> once it's released.<br />
So what does Travis CI do for Node builds? Well it executes <code>npm test</code>, by default. What on earth does that do? Well, there's really nothing helpful in the documentation, but again, by perusing a few favorite projects it executes a script in the root of the project named <code>test.js</code> or all scripts in a folder named test.<br />
<br />
Alright, so then just save an empty file named test right? Not so much. The easiest way to get started with some test driven development is to assert what you expect your functions to return for certain known values.<br />
Consider a simple Fibonacci series:<br />
<br />
<pre><code class=" ">module.exports = function fib(n) {
if ((n === 1) || (n === 0)) {
return n;
} else {
return fib(n-1) + fib(n-2);
}
}
</code></pre>
And then require the module and assert in test.js:<br />
<br />
<pre><code>// Import libraries
var fib = require('./fib.js');
var assert = require('assert');
// Exercise fib
assert.equal(fib(4),3);
assert.equal(fib(5),5);
assert.equal(fib(6),8);
assert.equal(fib(7),13);
</code></pre>
<br />
At this point, a git push to the repository, provided Travis CI is enabled for it, will result in the above code being executed in Travis CI's build environments and any uncaught exceptions will fail the build.<br />
But consider this, if I purposely throw an exception then catch it, does my build fail when the application experience isn't actually passing?<br />
<br />
<pre><code>module.exports = function buildHyjinx()
{
try
{
if(true) throw "empty";
}
catch(err)
{
console.log(err);
return -1;
}
}</code></pre>
<code>
</code><br />
Wait a minute! A build passes because we handled an exception appropriately? Yes. So build real life tests and include testing for functionality you don't yet have. Then fail your build, on purpose, or you'll never know what you haven't done yet.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-71836587551687681442013-07-19T23:21:00.001-07:002013-07-19T23:21:15.686-07:00Life with DRMSo my Sony Blu-Ray player can't play Netflix today. Wonder why? Well it's not Netflix, that works great on my PC. And my iPhone and my Wii. <span style="font-family: "Courier New", Courier, monospace;">tcpdump</span> to the rescue!<br />
<br />
That's all fine an dandy if my DD-WRT device was my router instead of just an AP, I'd have to mount a CIFS share and download a package in order to do a <span style="font-family: "Courier New", Courier, monospace;">tcpdump</span>.<br />
<br />
Instead, I've got a hand-me-down Juniper with ScreenOS. Not being intimately familiar, I did recall it had some equivalent facilities if using the CLI, so without further ado, here's a cheat sheet for working with <span style="font-family: "Courier New", Courier, monospace;">snoop</span>:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">ssg-> clear dbuf<br />ssg-> snoop info<br />Snoop: OFF<br />Filters Defined: 1, Active Filters 1<br />Detail: ON, Detail Display length: 96<br />Snoop tunnel traffic: ON<br />Snoop filter based on:<br />id 1(on): IP src-ip 172.16.37.101 dir(B)<br />ssg-> snoop filter ip src-ip 172.16.37.100 direction both<br />snoop filter added<br />ssg-> snoop<br />Start Snoop, type ESC or 'snoop off' to stop, continue? [y]/n y</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">clear dbuf</span> clears the in memory buffer, then <span style="font-family: "Courier New", Courier, monospace;">snoop info</span> shows the current snoop state. Then I use a <span style="font-family: "Courier New", Courier, monospace;">filter</span> to just watch one device, so I can determine what destination IPs are involved. Later, we can re-run with a different <span style="font-family: "Courier New", Courier, monospace;">filter</span> to get a better sampling. <br />
<br />
I did a quick <span style="font-family: "Courier New", Courier, monospace;">telnet</span> test to <a href="http://www.google.com/">www.google.com</a> then stopped the snoop trace.<br />
<br /><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">ssg-> snoop off<br />Snoop off</span><br />
To view the trace, we send the <span style="font-family: "Courier New", Courier, monospace;">dbuf</span> to stream output and page through results. If you're using a more detailed <span style="font-family: "Courier New", Courier, monospace;">filter</span> it will decode unencrypted HTTP requests a bit more.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">ssg-> get dbuf stream</span><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">91638.0: bgroup0(i) len=74:0019d28739e8->001db5ba738b/0800<br /> 172.16.37.100 -> 8.8.8.8/17<br /> vhl=45, tos=00, id=2844, frag=0000, ttl=128 tlen=60<br /> udp:ports 56461->53, len=40<br /> 00 1d b5 ba 73 8b 00 19 d2 87 39 e8 08 00 45 00 ....s.....9...E.<br /> 00 3c 0b 1c 00 00 80 11 4e 11 ac 10 25 64 08 08 .<......N...%d..<br /> 08 08 dc 8d 00 35 00 28 51 91 61 1e 01 00 00 01 .....5.(Q.a.....<br /> 00 00 00 00 00 00 03 77 77 77 06 67 6f 6f 67 6c .......www.googl<br /> 65 03 63 6f 6d 00 00 01 00 01 e.com..... </span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">91638.0: bgroup0(i) len=66:0019d28739e8->001db5ba738b/0800<br /> 172.16.37.100 -> 173.194.33.17/6<br /> vhl=45, tos=00, id=2845, frag=4000, ttl=128 tlen=52<br /> tcp:ports 49295->80, seq=787237732, ack=0, flag=8002/SYN<br /> 00 1d b5 ba 73 8b 00 19 d2 87 39 e8 08 00 45 00 ....s.....9...E.<br /> 00 34 0b 1d 40 00 80 06 4f 5f ac 10 25 64 ad c2 </span><a href="http://www.blogger.com/null"><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">.4..@...O_..%d</span></a><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">..<br /> 21 11 c0 8f 00 50 2e ec 4b 64 00 00 00 00 80 02 !....P..Kd......<br /> 20 00 73 98 00 00 02 04 05 b4 01 03 03 08 01 01 ..s.............<br /> 04 02 .. </span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">91638.0: bgroup0(i) len=60:0019d28739e8->001db5ba738b/0800<br /> 172.16.37.100 -> 173.194.33.17/6<br /> vhl=45, tos=00, id=2846, frag=4000, ttl=128 tlen=40<br /> tcp:ports 49295->80, seq=787237733, ack=1688811284, flag=5010/ACK<br /> 00 1d b5 ba 73 8b 00 19 d2 87 39 e8 08 00 45 00 ....s.....9...E.<br /> 00 28 0b 1e 40 00 80 06 4f 6a ac 10 25 64 ad c2 .(</span><a href="http://www.blogger.com/null"><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">..@...Oj..%d</span></a><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">..<br /> 21 11 c0 8f 00 50 2e ec 4b 65 64 a9 37 14 50 10 !....P..Ked.7.P.<br /> 00 43 38 5b 00 00 00 00 b7 3d 3e 89 .C8[.....=>. </span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">91641.0: bgroup0(i) len=60:0019d28739e8->001db5ba738b/0800<br /> 172.16.37.100 -> 173.194.33.17/6<br />ssg-> snoop filter delete<br />All filters removed<br />ssg-> clear dbuf<br />ssg-></span><br />
<br />
Lastly, I drop my filter and clear the in memory buffer to clean up. <br />
<br />
Later I facilitated this with a filter between my device and the device provisioning service over at Sony to determine why my Blu-Ray player couldn't play Netflix. Sure enough, the device makes a connection to <span style="font-family: "Courier New", Courier, monospace;">ssm1.internet.sony.tv</span> and does a <span style="font-family: "Courier New", Courier, monospace;">GET</span> for <span style="font-family: "Courier New", Courier, monospace;">/BDP/stv/STVgetTime/</span> and gets an <span style="font-family: "Courier New", Courier, monospace;">HTTP 404</span> response. Using IE10's F12 Developer Tools, I captured the response header and confirmed it's an Apache host. Beyond that reverse lookup tricks and <span style="font-family: "Courier New", Courier, monospace;">tracert</span> didn't tell me much.<br />
<br />
For fun, I also tested the Slacker radio plugin, and it fails hitting a similar host, <span style="font-family: "Courier New", Courier, monospace;">ssm.internet.sony.tv</span> and <span style="font-family: "Courier New", Courier, monospace;">ssm2.internet.sony.tv</span>, but there were also some exciting UDP packets going by on 1900.<br />
<br />
So after contacting Sony support, I was directed to call their support team as my issue couldn't be solved on chat. I feel sorry for the CS agent I spoke with because their first reaction after demonstrating my case was to use an HDMI cable instead. So much for the OSI model. This really points at how DRM can affect customer experience, especially if it's something the hardware vendor tacked on to their device on top of a 3rd party service that doesn't require it for other devices. Even though I was (and still am) a PlayStation 3 fanboy, I'm having second thoughts about Sony devices. <br />
<br />
I watched Netflix on Wii today. Because it just worked.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-89533415056029140452013-05-22T22:26:00.001-07:002013-05-22T22:26:48.394-07:00Troubleshooting 101: The Power of netstatI was reading up on <a href="http://msdn.microsoft.com/en-us/windows/hardware/gg487334" target="_blank">ETW</a>, and discovered the <a href="http://technet.microsoft.com/en-us/sysinternals/bb897437" target="_blank">TCPView</a> tool. Having recently worked with the joys of <span style="font-family: "Courier New", Courier, monospace;">ip_conntrack</span> on Linux hosts with <span style="font-family: "Courier New", Courier, monospace;">iptables</span> and bad PHP frameworks leaving TCP sessions in <span style="font-family: "Courier New", Courier, monospace;">TIME_WAIT</span>, this was a nice find for Windows.<br />
<br />
But in reviewing <a href="http://support.microsoft.com/kb/816944" target="_blank">this article</a>, its curious that Microsoft doesn't demonstrate the use of native OS tools to triage a simple port binding issue. So here's a quick example to help you find what's listening on TCP 80.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\> netstat -p TCP -on | find ":80 "</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"> TCP 172.16.37.100:80 157.56.98.83:443 ESTABLISHED 320</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"></span><br />
<span style="font-family: inherit;">This shows us a list of TCP ports with the numeric port value and the PID.</span><br />
<span style="font-family: Courier New; font-size: x-small;"></span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\> tasklist /FI "PID eq 320"</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Image Name PID Session Name Session# Mem Usage<br />========================= ======== ================ =========== ============<br />w3wp.exe 320 Services 0 99,344 K</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"></span><br />
<span style="font-family: inherit;">Pass the PID in a predicate filter to <span style="font-family: "Courier New", Courier, monospace;">tasklist</span>, and we find the process name. Since it's an IIS worker process, we must go a step further to identify the Application Pool:</span><br />
<span style="font-family: Courier New; font-size: x-small;"></span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\> %windir%\system32\inetsrv\appcmd.exe list wp<br />WP "320" (applicationPool:WsusPool)</span><br />
<br />
Another great feature of <span style="font-family: "Courier New", Courier, monospace;">netstat</span> is it's statistics feature, which a peer pointed out to me:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:> netstat -s</span><br />
<br />
It's left as an exercise to the reader to peruse the value that single command can have in troubleshooting down the stack before you worry about data link and the physical layer. You've already swapped out that crossover cable for a regular patch, right?Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-16835767799348232442013-04-07T21:53:00.001-07:002013-04-07T21:53:52.349-07:00Now on IPv6!On a whim, I configured <a href="https://www.cloudflare.com/" target="_blank">CloudFlare</a> today. Then happily discovered, it helps my site go into the future, <a href="http://www.cloudflare.com/features-cdn" target="_blank">and not just faster, but also with IPv6</a>. On a side note, since they'll be handling my name servers for the purposes as a CDN, I can eliminate my name server hosting costs, saving $12/year, unless I put those $12 towards premium features as the site grows.<br />
<br />
<h3>
But wait, there's more!</h3>
<br />
Looking at their apps, I found <a href="http://blitz.io/">Blitz.io</a>, which is a sweet simple load-testing service. After testing it out a bit, I misspelled Brazil, and found this fun fact:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcc9Ev_YxrraM5xZK7LyZ6nswPgPj9fSlSvn8DgDidQ4RhG466PSn2ApdbFTMeu4Y9kPCth7zaCq1GEWojKulSj3Z9imSTlVPKIXM5rLBlrJMNRaKcOBxQONo1j0G8wv9ZKvY1LZ33MlY/s1600/blitz-locations.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="117" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcc9Ev_YxrraM5xZK7LyZ6nswPgPj9fSlSvn8DgDidQ4RhG466PSn2ApdbFTMeu4Y9kPCth7zaCq1GEWojKulSj3Z9imSTlVPKIXM5rLBlrJMNRaKcOBxQONo1j0G8wv9ZKvY1LZ33MlY/s400/blitz-locations.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"s" isn't just British anymore</td></tr>
</tbody></table>
Hm, those <a href="http://aws.amazon.com/about-aws/globalinfrastructure/" target="_blank">regional mappings seem very familiar</a>. Quick to the <a href="http://www.eveningread.com/2013/04/from-whence.html" target="_blank">bat-lookup (or bat-dig, your preference):</a><br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup www.blitz.io<br />Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Non-authoritative answer:<br />Name: elb014717-1106725811.us-east-1.elb.amazonaws.com<br />Addresses: 54.243.112.187<br /> 54.243.77.105<br /> 54.243.229.217<br />Aliases: www.blitz.io<br /> mie-8036.herokussl.com</span><br />
<br />
Ha, I thought so. It looks like they're using <a href="https://www.heroku.com/" target="_blank">Heroku</a>, who's a well know user of <a href="http://aws.amazon.com/elasticloadbalancing/" target="_blank">AWS</a>.<br />
<br />
<h3>
That's not all, Bob. Tell 'em what they've won!</h3>
<br />
When I first ran the query, I mistakenly specified the apex zone:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup blitz.io<br />Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Non-authoritative answer:<br />Name: blitz.io<br />Address: 50.31.209.229</span><br />
<br />
They aren't using the ELB in their apex zone. I happen to know that feature is <a href="http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/using-domain-names-with-elb.html" target="_blank">an AWS specific implementation of Route 53</a>. So let's check name servers:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup -q=ns blitz.io<br />Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Non-authoritative answer:<br />blitz.io nameserver = ns4.dnsimple.com<br />blitz.io nameserver = ns2.dnsimple.com<br />blitz.io nameserver = ns3.dnsimple.com<br />blitz.io nameserver = ns1.dnsimple.com</span><br />
<br />
Yup, they're using name servers elsewhere. But why not use CloudFlare for the optimizations? Perhaps its something that only their engineers can answer.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-20771774487300842292013-04-02T23:15:00.000-07:002013-04-03T09:54:11.260-07:00From Whence?Ever wonder where a website's hosted? Or who's that strange IP in your logs came from? DNS can be more helpful than you think, if it was configured right. So, let's have some fun, shall we?<br />
<br />
<h2>
Who's there?</h2>
<br />
In lieu of know how a site is configured, or finding a reputable site with enough foresight to configure their site in a fashion to be interesting to look at. So who might we inspect? How about one of the popular open-source relational database systems, <a href="http://www.postgresql.org/" target="_blank">Postgresql</a>?<br />
<br />
Staring with the basics, let's do a quick A record lookup and check the name servers for the zone:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New", Courier, monospace;">C:\>nslookup </span><span style="font-family: "Courier New", Courier, monospace;">www.postgresql.org</span></span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New", Courier, monospace;">Non-authoritative answer:<br />Name: </span><span style="font-family: "Courier New", Courier, monospace;">www.mirrors.postgresql.org</span></span><span style="font-size: x-small;"><span style="font-family: "Courier New", Courier, monospace;">Addresses: 2001:4800:7903:4::126<br /> 2a02:c0:301:0:ffff::32<br /> 2a02:16a8:dc51::50<br /> 217.196.149.50<br /> 87.238.57.232<br /> 98.129.198.126<br />Aliases: </span><span style="font-family: "Courier New", Courier, monospace;">www.postgresql.org</span></span><br />
<br />
Ooooh, not only do we have six endpoints, it's a CNAME record with IPV6 addresses. It's left as an exercise to the reader to play with IPv6 and discuss the merits of CNAMES, so let's look at name servers.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup -query=ns postgresql.org<br />Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Non-authoritative answer:<br />postgresql.org nameserver = ns4.postgresql.org<br />postgresql.org nameserver = ns3.postgresql.org<br />postgresql.org nameserver = ns2.postgresql.org<br />postgresql.org nameserver = ns1.postgresql.org</span><br />
<br />
Looks like these guys are smart enough to host and manage their own name servers. Not something I'd personally want to spend my time on (thanks to <a href="http://dyn.com/" target="_blank">Dyn</a> and now <a href="http://aws.amazon.com/route53/" target="_blank">Route 53</a>).<br />
<br />
<h2>
Where are they coming from?</h2>
<br />
So obviously they're behind three endpoints, so a quick <a href="http://en.wikipedia.org/wiki/WHOIS" target="_blank">WHOIS</a> lookup should give us an idea of where they're at, right?<br />
<br />
217.196.149.50 : RIPE Network Coordination Centre<br />
87.238.57.232 : RIPE Network Coordination Centre<br />
98.129.198.126 : Rackspace Hosting RSCP-NET-4<br />
<br />
We all know who Rackspace is and that's about all I can get there short of inside knowledge of Rackspace's netblock allocation, but who on earth is <a href="http://www.ripe.net/" target="_blank">RIPE Network</a>? And why is <a href="http://xkcd.com/195/" target="_blank">this interesting</a>? So how can I know where those two IPs are hosted? tracert is always a nice idea, but sometimes it yields the same results.<br />
<br />
Six hops out of the interesting bits of my own network and we find:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"> 7 13 ms 13 ms 12 ms 208.178.58.89<br /> 8 193 ms 191 ms 193 ms 64.209.102.34<br /> 9 202 ms 201 ms 208 ms asr01-0-0-0.dc1.conova.com [195.70.99.142]<br /> 10 204 ms 198 ms 200 ms 217.196.158.12<br /> 11 198 ms 197 ms 197 ms 217.196.158.38<br /> 12 195 ms 198 ms 204 ms zalkon.postgresql.org [217.196.149.50]</span><br />
<br />
And also:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"> 11 80 ms 81 ms 88 ms xe-4-3-0-0.nyk2nqp1.us.ip.tdc.net<br /> 12 187 ms 188 ms 186 ms static-213.50.153.37.addr.tdcsong.se<br /> 13 191 ms 184 ms 192 ms ge-1-0-0.cr2-ksd1.n.bitbit.net [213.50.153.38]<br /> 14 187 ms 185 ms 192 ms vlan-1.cs1-ksd1.n.bitbit.net [87.238.62.145]<br /> 15 191 ms 186 ms 197 ms bond0.fw2-ksd1.n.bitbit.net [87.238.62.151]<br /> 16 189 ms 185 ms 187 ms zetar.postgresql.org [87.238.57.232]</span><br />
<br />
Certainly interesting and partially information. I'm guessing bitbit.net might be one hosting provider or ISP.<br />
<br />
<h2>
How do we find out more?</h2>
<br />
Let's have even more fun, courtesy of DNS. Reverse lookups were popularized a few weeks back by the <a href="http://www.theregister.co.uk/2013/02/15/star_wars_traceroute/" target="_blank">tracert replay of the intro to Star Wars: A New Hope</a>, but let's use this fact to our advantage.<br />
<br />
Since we know that a <a href="http://en.wikipedia.org/wiki/Reverse_DNS_lookup" target="_blank">reverse DNS lookup</a> will give us the name of an IP and given that in most cases ISPs or service providers allocate chunks of RIR networks in contiguous blocks, let's try looking up a CIDR block of the respective ARPA addresses of those IPs:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup -query=ptr 149.196.217.in-addr.arpa<br />Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">149.196.217.in-addr.arpa<br /> primary name server = adns001.dc1.conova.com<br /> responsible mail addr = domainadmin.conova.com<br /> serial = 2012092001<br /> refresh = 10800 (3 hours)<br /> retry = 3600 (1 hour)<br /> expire = 1814400 (21 days)<br /> default TTL = 86400 (1 day)</span><br />
<br />
And then:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup -query=ptr 57.238.87.in-addr.arpa<br />Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">57.238.87.in-addr.arpa<br /> primary name server = ns-foo.linpro.net<br /> responsible mail addr = hostmaster.linpro.no<br /> serial = 2013032700<br /> refresh = 10800 (3 hours)<br /> retry = 3600 (1 hour)<br /> expire = 2419200 (28 days)<br /> default TTL = 86400 (1 day)</span><br />
<br />
And that's a wrap. There's a good chance that the other two IPs are hosted by <a href="http://www.conova.com/" target="_blank">Conova</a> and <a href="http://linpro.no/" target="_blank">LinPro</a>, who's TXT record has this little nugget:<br />
<br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup -query=txt linpro.no</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Non-authoritative answer:<br />linpro.no text =</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"> "<a href="http://www.youtube.com/watch?v=wL-hNMJvcyI" target="_blank">never-gonna-give-you-up</a>"<br />linpro.no text =</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"> "google-site-verification=ChNtbQK1HLTM6oP5E3yV5SLo8NOQJmwJibARqdN0Ypo"</span>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-61070778879854075712013-03-18T21:04:00.000-07:002013-03-18T21:04:52.701-07:00Why I'm a PC UserI've been a prosumer of Apple products since my college graduation and have just sold my last <a href="http://support.apple.com/kb/SP35" target="_blank">Mac</a>, an early model Intel based iMac. I had saved up for the purchase for the purpose of getting the <a href="http://www.amd.com/us/products/desktop/graphics/other/Pages/x1600-specifications.aspx" target="_blank">256MB ATI Radeon X1600</a> and a 20" display. A huge upgrade from my vastly underpowered 1.4Ghz AMD Athlon with a <a href="http://www.nvidia.com/page/geforce4ti.html" target="_blank">nVidia GeForce 4600 8x AGP</a>.<br />
<br />
It was a the Golden Age of World of Warcraft, and with a peer running <a href="http://www.ventrilo.com/" target="_blank">Ventrilo</a> server, I was enjoying maxed out graphics (AAx4 aside) at 1680x1050. Next to my old 12" PowerBook G4 it was greased lightning.<br />
<br />
<h3>
I didn't leave Apple, Apple left me</h3>
<br />
When I started using Macs, the G5 had just come out and after taking my Java and Linux courses in college, I was apt to get my hands on something with UNIX frameworks under the hood. Everything was Fedora vs Mandriva back then, and SuSE was coming in strong with the YaST experience, but I choose Gentoo. There was <a href="http://forums.gentoo.org/viewforum-f-49.html" target="_blank">a fork of the portage tool</a> that ran under Mac OS X and it was a dream for playing with open source software.<br />
<br />
Indie developers like <a href="http://www.rogueamoeba.com/" target="_blank">Rogue Amoeba</a>, <a href="http://www.flyingmeat.com/" target="_blank">Flight Meat</a>, and <a href="http://www.delicious-monster.com/" target="_blank">Delicious Monster</a> were making waves, years ahead of the App Store market. I remember going to the MacWorld Expo just to have the chance to meet the guys behind the software. Never mind that I never wrote a lick of code myself.<br />
<br />
<h3>
Wither OS X</h3>
<br />
Fast forward a few years. Introduce the iPhone. iTunes is still making a killing. And now merge the two platforms together. And remove mouse buttons from track pads. <a href="http://www.wired.com/reviews/2011/07/osx-lion/" target="_blank">Flip scrolling directions</a>.<br />
<br />
Don't get me wrong, some of the apps being developed for the mobile platform are amazing. And conversely, some of my <a href="http://boxerapp.com/" target="_blank">favorite apps</a> are still awesome.<br />
<br />
And never mind that I've been supporting Microsoft infrastructure applications for the past eight years. I've done my fair share of USB-serial cables passed-thru to <a href="http://www.vmware.com/products/fusion/overview.html" target="_blank">VMware Fusion</a> to reprogram APC UPS equipment in <a href="http://technet.microsoft.com/en-us/library/bb457166.aspx" target="_blank">HyperTerminal</a> in third-world countries, but it's time to move on.<br />
<br />
<h3>
Going Blue, in the Cloud</h3>
<br />
The best Microsoft experience is on the Microsoft platform. Now that I'm a quintuplet MCITP and dual MCSA, I've clearly chosen my platform of choice. But given that most of that isn't on bare metal anymore, I do just about everything in <a href="http://aws.amazon.com/microsoft" target="_blank">The Cloud</a>.<br />
<br />
The only problem keeping me from switching to something like a Surface RT for the majority of my home life is storage (where do you put 40GB of music and 20GB of photos?) and x86 support. But I'm sure that'll come along shortly.<br />
<br />
<h3>
To be honest</h3>
<br />
Once the warchest is built up, I'll still probably get a replacement Mac at some point. But it'll have to be the right price and the right hardware. I've got my budget to stick to after all, and I can't stand Intel HD Graphics chips. I've experienced too many strange glitches and performance issues.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-59299942960873569172013-01-12T23:10:00.000-08:002013-01-12T23:10:25.655-08:00Troubleshooting 101: Resolution (Part 1 of 5)Resolution is the first stop when it comes to troubleshooting. If a user, application, or protocol can't determine the address of it's destination by name, then we'll never take the first step on a journey of hopefully <a href="http://www.map.meteoswiss.ch/map-doc/ftp-probleme.htm" target="_blank">less than 64 hops</a>.<br />
<br />
This troubleshooting step typically revolves around <a href="http://en.wikipedia.org/wiki/Domain_Name_System" target="_blank">DNS,</a> but could also refer to <a href="http://en.wikipedia.org/wiki/NetBIOS_Frames_protocol" target="_blank">NetBIOS</a>, or even at the application layer. Since you're already on the Internet, let's discuss DNS issues in particular.<br />
<br />
<h2>
Tools of the Trade</h2>
The most common tools used for testing DNS are <span style="font-family: "Courier New", Courier, monospace;"><a href="http://linux.die.net/man/1/dig" target="_blank">dig</a></span> and <span style="font-family: "Courier New", Courier, monospace;">nslookup</span>. Hailing from a Microsoft background, I usually find myself using <span style="font-family: "Courier New", Courier, monospace;">nslookup</span><span style="font-family: inherit;">:</span><br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Default Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span></blockquote>
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;"><span style="font-size: x-small;">> </span><a href="http://www.eveningread.com/"><span style="font-size: x-small;">www.eveningread.com</span></a><br /><span style="font-size: x-small;">Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span></span><br />
<span style="font-family: "Courier New", Courier, monospace;"><span style="font-size: x-small;">Non-authoritative answer:<br />Name: ghs.l.google.com<br />Addresses: 2607:f8b0:400e:c01::79<br /> 173.194.79.121<br />Aliases: </span><a href="http://www.eveningread.com/"><span style="font-size: x-small;">www.eveningread.com</span></a><br /><span style="font-size: x-small;"> ghs.google.com</span></span></blockquote>
From this short example, you can see several things. First, my laptop is configured to query <a href="https://developers.google.com/speed/public-dns/" target="_blank">Google's Public DNS</a> servers. I selected their secondary server as my primary name server based on performance testing with <a href="http://code.google.com/p/namebench/" target="_blank">namebench</a>. This tool identified the server as the fasted for my geographic location.<br />
<br />
Secondly, you'll see I requested this site's fully qualified domain name for my query which defaults to searching for <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=48090#H" target="_blank">A records</a>. This returns <span style="font-family: "Courier New", Courier, monospace;">ghs.l.google.com</span>, which in a second, automated lookup, returns the actual public IP address for this site.<br />
<br />
Over-riding this query is a farily simple task of appending a name server to a single line <span style="font-family: "Courier New", Courier, monospace;">nslookup</span> query:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\> nslookup </span><a href="http://www.eveningread.com/"><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">www.eveningread.com</span></a><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"> 8.8.8.8</span></blockquote>
Or interactively setting it in the session:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup<br />Default Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: Courier New; font-size: x-small;"></span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">> server 8.8.8.8<br />Default Server: google-public-dns-a.google.com<br />Address: 8.8.8.8</span> </blockquote>
Searching for different record types is similar:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\> nslookup -query-type=mx </span><a href="http://www.eveningread.com/"><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">www.eveningread.com</span></a></blockquote>
Or interactively setting it in the session:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup<br />Default Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;"> </span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">> set q=mx</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">> eveningread.com<br />Server: google-public-dns-b.google.com<br />Address: 8.8.4.4</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">Non-authoritative answer:<br />eveningread.com MX preference = 10, mail exchanger = 91b72d3b13b94f9d8f11a10f3e76c6.pamx1.hotmail.com</span></blockquote>
Here we see the results of an <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=33352" target="_blank">MX record</a> lookup. (Don't try to email me here, this is configured for demonstration purposes only. Email is a whole different topic.)<br />
<br />
To perform these queries to a name server, DNS clients typically initiate a connection to <a href="http://tools.ietf.org/html/rfc1035" target="_blank">UDP port 53</a> of a name server, though some uses of TCP port 53 have been seen. <br />
<br />
<blockquote class="tr_bq" style="background: #FFFF99; border-width: 2px; border-color: black; border-style: solid; padding: 5px;">
It's left as an exercise to the reader to leverage <a href="http://www.wireshark.org/" target="_blank">packet</a> <a href="http://www.microsoft.com/en-us/download/details.aspx?id=4865" target="_blank">capture</a> <a href="http://linux-firewall.org.ua/0672327716/ch11lev1sec3.html" target="_blank">utilities</a> to watch DNS traffic on their client workstation or DNS server.</blockquote>
<h2>
Example Use Case: Active Directory Specific DNS Records</h2>
One of the most common issues I run into is workstations failing to authenticate with Active Directory (unless they're unplugged from the network, in which case they use cached credentials), or computers that cannot outright join a domain.<br />
<br />
Active Directory Domain Services uses some unique records to locate a Domain Controller via the Netlogon process. Details on these records are outlined here, in <a href="http://technet.microsoft.com/en-us/library/cc961921.aspx" target="_blank">this ancient Windows Server 2000 documentation</a>.<br />
<br />
When we can't query Active Directory, I typically drop to a command prompt and run the following query (for the corp.contoso.com Active Directory forest, in this example):<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">C:\>nslookup -query-type=srv _ldap._tcp.dc._msdcs.corp.contoso.com<br />Default Server: dc1.corp.contoso.com <br />Address: 10.0.0.14 <br />_ldap._tcp.dc._msdcs.corp.contoso.com SRV service location: <br /> priority = 0 <br /> weight = 0 <br /> port = 389 <br /> svr hostname = dc1.corp.contoso.com <br />_ldap._tcp.dc._msdcs.corp.contoso.com SRV service location: <br /> priority = 0 <br /> weight = 0 <br /> port = 389 <br /> svr hostname = dc2.corp.contoso.com <br />dc1.corp.contoso.com internet address = 10.0.0.14 <br />dc2.corp.contoso.com internet address = 10.0.0.15</span> </blockquote>
Anything other than the above (provided those are the correct IP addresses), and I've got a resolution problem that's keeping Netlogon from finding a Domain Controller. Usually updating the DNS settings to query the appropriate name server does the trick at this point.<br />
<h2>
Caveat Emptor</h2>
Another issue I commonly see pertains to client side DNS caching. Let's say you connect to a highly available database server, which fails over by updating a <a href="http://support.google.com/a/bin/answer.py?hl=en&answer=112037" target="_blank">CNAME</a> for it's endpoint. One moment your clients are connecting to 10.0.0.20, the next <span style="font-family: "Courier New", Courier, monospace;">database.corp.contoso.com</span> points to 10.0.0.21. But if your client application didn't query database.corp.contoso.com a second time, it'll be using the cached 10.0.0.20 IP until <a href="http://en.wikipedia.org/wiki/Time_to_live#DNS_records" target="_blank">TTL expires</a>, <a href="http://stackoverflow.com/questions/1256556/any-way-to-make-java-honor-the-dns-caching-timeout-ttl" target="_blank">or worse never</a>!<br />
<h2>
Wrap Up</h2>
So what's so important about resolution from a troubleshooting perspective? Well, if it's not done right, you're talking to no one, a server that won't answer for your application, or stuck with <a href="http://en.wikipedia.org/wiki/DNS_hijacking" target="_blank">all your queries running to a malicious website</a>! Even if you don't know when or why resolution is a part of your problem, knowing how to test it and remediate it is key to narrowing down your list of issues.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-35624586233928964442012-10-10T14:10:00.000-07:002012-10-10T14:10:11.202-07:00IIS Wildcard SSL Certificate BindingRecently I had a customer who's HTTPS binding would only respond with HTTP 404 or HTTP 400 errors. They were configuring HTTPS on their Default Web Site with a wildcard certificate as follows.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZapdZsTKL9JBf2yVN9Jtva3y1gsZcv82JjahfIRq9J92NwMPyG3LYqcX_DdfX4Kfl1o6bvV-UV15GfsHPYXKXmDwp8QXV8u7mNrmZiyr3WDr3-L2oEbUFU1jfalu7nHPkChUjHfk3woQ/s1600/https-host-header.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZapdZsTKL9JBf2yVN9Jtva3y1gsZcv82JjahfIRq9J92NwMPyG3LYqcX_DdfX4Kfl1o6bvV-UV15GfsHPYXKXmDwp8QXV8u7mNrmZiyr3WDr3-L2oEbUFU1jfalu7nHPkChUjHfk3woQ/s400/https-host-header.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">One of these things doesn't belong.</td></tr>
</tbody></table>
A quick curl test revealed a distinct difference between the HTTP and HTTPS bindings:<br />
<blockquote class="tr_bq">
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">$ curl -vk http://www2.contoso.com/Login/Login.aspx >> /dev/null</span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;"><br /></span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">< HTTP/1.1 200 OK<br />< Cache-Control: private<br />< Content-Type: text/html; charset=utf-8<br />< Server: Microsoft-IIS/7.5</span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;"><br /></span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">$ curl -vk https://www2.contoso.com/Login/Login.aspx >> /dev/null</span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;"><br /></span></div>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">< HTTP/1.1 404 Not Found</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">< Content-Type: text/html; charset=us-ascii</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">< Server: Microsoft-HTTPAPI/2.0</span></span></blockquote>
<br />
You'll noted that the response headers included different responses from Server strings! But what on earth is Microsoft-HTTPAPI/2.0? A quick netstat reveals TCP 443 is bound to the System process at PID 4. Isn't that the kernel or something? Well, technically yes. You see, the HTTP protocol in Windows is served from the http.sys driver (which is a hidden device in Device Manager).<br />
<br />
It turns out that the way to avoid that server response is to remove the host name binding. When IIS can't match the request to a binding, it dumps out at the driver level with the above HTTP 404 from Microsoft-HTTPAPI/2.0.<br />
<br />
Lesson learned: if it isn't DNS, blame bindings.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-8361021367390556082012-03-14T18:33:00.002-07:002012-03-14T18:33:57.329-07:00Revenge of the LegacyExchDN<br />
After using the PST migration method to divest an Exchange deployment, we discovered that a user couldn't act as a delegate for old items in another user's calendar.<br />
<br />
Instead, we received this pleasant message from Microsoft:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ4jjBnp0lQT6XzaXz-L467FT7xxaxi9HoY-3f2PjljoJk5gMz20_9a6llNm8YslIX4KE8yDz9QDRCGFdmDCnA0ijfZxLw4uvYpVhXvWsKBqEoe-dGoSCg5fsYdLXVrCCf2HFeLeyqmms/s1600/permission-error.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="90" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ4jjBnp0lQT6XzaXz-L467FT7xxaxi9HoY-3f2PjljoJk5gMz20_9a6llNm8YslIX4KE8yDz9QDRCGFdmDCnA0ijfZxLw4uvYpVhXvWsKBqEoe-dGoSCg5fsYdLXVrCCf2HFeLeyqmms/s320/permission-error.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">No, it's not helpful, Microsoft.</td></tr>
</tbody></table>
Invoking the following didn't achieve the desired results:<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Set-Mailbox -Identity Cheryl -GrantSendOnBehalfTo Natalee</span></blockquote>
<span style="font-family: inherit;">And neither did:</span><br />
<blockquote class="tr_bq" style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small; text-align: -webkit-auto;">Set-MailboxPermissions -Identity Cheryl </span><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small; text-align: -webkit-auto;">-User Natalee -AccessRights SendAs</span><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></blockquote>
(Of course on Exchange 2010, you'll need to set the equivalent via AD Cmt-lets)<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Set-MailboxPermissions -Identity Cheryl </span><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">-User Natalee -AccessRights FullAccess</span></blockquote>
No go there either. How about delegate permissions?<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Add-MailboxFolderPermission -Identity Cheryl:\Calendar </span><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">-User Natalee -AccessRights Editor</span></blockquote>
Nope.<br />
<br />
So what's wrong and how do we go about finding out? Being a datahead, I grabbed the latest <a href="http://mfcmapi.codeplex.com/">MFCMAPI</a> build and deployed in on a machine with Outlook installed. With the proper permissions temporarily in place, I drilled into the user's information store, down to the calendar, then enumerated contents.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTM5ChpzMD-B9FwqpIuu1BkUhF8cZjfaNjhiewPInYGCUS827OphB5Bqla9QTTjSOK4h0lJjh_KH2ln5s_hBqmyygnXUqXTqCoSX00xFzbcBCvVwaEwzgh_h5-g42AJ6T42a9Morw3Mxk/s1600/calendar-object-creator.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTM5ChpzMD-B9FwqpIuu1BkUhF8cZjfaNjhiewPInYGCUS827OphB5Bqla9QTTjSOK4h0lJjh_KH2ln5s_hBqmyygnXUqXTqCoSX00xFzbcBCvVwaEwzgh_h5-g42AJ6T42a9Morw3Mxk/s400/calendar-object-creator.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Object DN resolution failure</td></tr>
</tbody></table>
There I located the troubled appointment by Subject, and found that the following properties were pointing at the legacy domain's DN.<br />
<br />
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/cc842405(office.12).aspx">PR_SENT_REPRESENTING_NAME_W</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/cc839552.aspx">PR_SENT_REPRESENTING_EMAIL_ADDRESS_W</a></li>
</ul>
<br />
I had heard rumors of a solution leveraging X500 addresses, a relic from long, long ago. <a href="http://blogs.technet.com/b/sbs/archive/2009/05/21/cannot-reply-to-old-emails-or-modify-old-calendar-items-after-pst-mail-migration.aspx">Updating X500s</a> would allow the metadata to resolve off of my modern Exchange 2010 deployment.<br />
<br />
Leveraging <a href="http://admodify.codeplex.com/">ADModify</a> as perscribed in the article resolved the issue. Now, if you didn't get your mailNickname property identical between domains, you'll have to modify users individually. Or if the old domain isn't available for reference, you'll need to use MFCMAPI to track down troublesome messages to find the exact DN that can't resolve off of the new AD deployment.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv5O1tvd0XKcz05f7Q3OcdXukzVjgiUuf6xdf2097FkVxVGrvySH3mgUr-_rOj6Mmf1mVvIXm1unK-9jRB10tcDAGrEY3kG5r8i0qOpePyAdtdE_H14rYhwFGF75nYXiqY30v44_0rNaM/s1600/mfcmapi-results.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv5O1tvd0XKcz05f7Q3OcdXukzVjgiUuf6xdf2097FkVxVGrvySH3mgUr-_rOj6Mmf1mVvIXm1unK-9jRB10tcDAGrEY3kG5r8i0qOpePyAdtdE_H14rYhwFGF75nYXiqY30v44_0rNaM/s400/mfcmapi-results.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Digging up legacy DNs on known bad calendar objects</td></tr>
</tbody></table>
<br />Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-11018734328703981292012-02-22T12:12:00.000-08:002012-02-22T12:12:16.405-08:00Forcefully Migrating a Public Folder Hierarchy<span style="font-size: large;">A Failed Inheritance</span><br />
<br />
A few days ago, I went to mail enable a public folder for a customer and found that while it showed up great in the EMC, we couldn't deliver mail to it. Rather, the server would respond:<br />
<br />
<blockquote class="tr_bq"><span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span style="color: grey;">#< #5.2.0 smtp;554 5.2.0 STOREDRV.Deliver.Exception:ObjectNotFoundException; Failed to process message due to a permanent exception with message The Active Directory user wasn't found. ObjectNotFoundException: The Active Directory user wasn't found.> #SMTP#</span></span></blockquote><br />
Knowing that we're talking about the GAL and/or OAB at this point, I went to rebuild the OAB ahead of schedule. But the OAB fired back, "I can't generate!" It was configured to generate in public folders and for web-based distribution. Doing some thinking, I jumped into ADSIEdit and discovered that my public folder hierarchy was still pointing at the legacy server in the Exchange administrative group.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXy9Vi1VvG3SSS8RgM2IN1OLbXnWNOVWq93XTBkVVrx_fHFhLASKC9-Cer2OghUI44GfDS2zHYJgnuqQ9JQy1CV46eEP9hwNYLcxdFgGu0QY1bqEaAtzSR8xVNhlOW-WcPbffIVE5nh_A/s1600/adsiedit-exch-admin-groups.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXy9Vi1VvG3SSS8RgM2IN1OLbXnWNOVWq93XTBkVVrx_fHFhLASKC9-Cer2OghUI44GfDS2zHYJgnuqQ9JQy1CV46eEP9hwNYLcxdFgGu0QY1bqEaAtzSR8xVNhlOW-WcPbffIVE5nh_A/s1600/adsiedit-exch-admin-groups.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Ruh-roo, Shaggy!</td></tr>
</tbody></table><br />
What's interesting is that the OAB generation was occurring on my new server and was targeting the public folders database on the new server. So what's wrong with this picture?<br />
<br />
<span style="font-size: large;">He's Responsible</span><br />
<br />
Sure enough, my legacy server isn't in the DN, but I wasn't like I could turn it back on. The object was deleted from the Exchange administrative group and the physical hardware had been sent to the dump months ago.<br />
<br />
Looking at the Folder Hierarchies in both administrative groups revealed that the hierarchy object was in the old administrative group, but not on the new one. That's right a server that didn't existing anymore was responsible for maintaining the MAPI PF tree for my new Exchange server.<br />
<br />
So what to do? Ideally, my old box would be on, with public folder replication completed and nothing but system objects in the public folders. One right click and I could migrate this via the UI. Checking some properties and running an Exchange Best Practices Analyzer, I discover I have the following condition: <a href="http://technet.microsoft.com/en-us/library/aa996485(EXCHG.80).aspx">http://technet.microsoft.com/en-us/library/aa996485(EXCHG.80).aspx</a><br />
<br />
Okay, so far so good. But now the MAPI tree doesn't yet exist on my new Exchange server. A little more digging and I discovered how my Configuration partition should look like this for a good migration: <a href="http://social.technet.microsoft.com/Forums/ar/exchangesvrmigration/thread/c0634d0e-80aa-4988-9a0f-67f1b02b3b50">http://social.technet.microsoft.com/Forums/ar/exchangesvrmigration/thread/c0634d0e-80aa-4988-9a0f-67f1b02b3b50</a><br />
<br />
<span style="font-size: large;">Who's On First?</span><br />
<br />
Now that I've survived the above article and bounced my Information Store service, I've got 2 MAPI trees and fail the Exchange Best Practices Analyzer. Oh, and Public Folders won't show up in Outlook Web Access. Microsoft's got that covered: <a href="http://technet.microsoft.com/en-us/library/dd535370(EXCHG.80).aspx">http://technet.microsoft.com/en-us/library/dd535370(EXCHG.80).aspx</a><br />
<br />
Once that's in place and I've confirmed I'm not getting NDR's things look great. Oh wait, Message Tracking shows that my message is received but never hits the mailbox store. A glance at the Queues, and my message is in the Unroutable Queue.<br />
<br />
Remember our screenshot above? There's still a routing group connector on the legacy administrative group side, but not on the production site. Yes, that'll be a delete in ADSIEdit. You backed up all of this first, right?<br />
<br />
<span style="font-size: large;">Final Absolution</span><br />
<br />
And now my public folders are managed by the new system and the old metadata is gone. Just one more email test. And:<br />
<blockquote class="tr_bq"><span style="color: grey; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">#< #5.2.0 smtp;554 5.2.0 STOREDRV.Deliver.Exception:ObjectNotFoundException; Failed to process message due to a permanent exception with message The Active Directory user wasn't found. ObjectNotFoundException: The Active Directory user wasn't found.> #SMTP#</span></blockquote>What? Still? Now we're back in familiar territory. This happens quite frequently in Exchange 2003 to Exchange 2010 migrations. It's a documented solution: <a href="http://blogs.dirteam.com/blogs/davestork/archive/2010/03/16/mail-enabled-public-folder-recipient-not-found.aspx">http://blogs.dirteam.com/blogs/davestork/archive/2010/03/16/mail-enabled-public-folder-recipient-not-found.aspx</a><br />
<br />
And with that, upgrading the GALs to the new 2010 format and an OAB update and I can finally use mail-enabled public folders in Exchange 2010.<br />
<br />
Remember, your mileage may vary! Backups are important, to the point of considering PST exports of the Public Folders as an additional failback. The best part is, this is documented, but there are several pieces we had to put together, but with a good understanding of the schema and using ADSIEdit and the issue became obvious and we had a path to resolution.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com1tag:blogger.com,1999:blog-4279057743765095593.post-6538361295314080402012-02-17T12:27:00.000-08:002012-02-17T15:45:35.285-08:00Slow Printer?Fighting with a slow printer? Here's some item to check that may improve your performance.<br />
<br />
<span style="font-size: large;">Drivers, Drivers, Drivers</span><br />
<br />
Are you running the latest driver from the manufacturer? If your PDF files are getting mangled or crashing your application, are you using a PostScript driver or PCL? Try a different flavor.<br />
<br />
<span style="font-size: large;">Memory</span><br />
<br />
Does your printer have expandable memory? You can consider adding memory, or using a front-end server for ripping. But, make certain your driver is configured to use the full memory of your device, or that your spooling options at the driver level rip appropriately for your configuration.<br />
<br />
<span style="font-size: large;">Print Processor</span><br />
<br />
A new technique I discovered is the importance of the print processor. Buried deep within the driver's Advanced settings, you'll find the Print Processor selection as show in the screenshot below.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzKH7yVHvc_TEoSUJdQTMhu4iO4qbDyx5yoW_W9H0kfL0nSvTHU_yJRzZWFMfHU0ViZKMNw0zLqfQ3lJ1o7Zevu6TXzjvFV-uEhlmTGxeMylBel0RUAk4N8i7_Z5GL5R4vjgb7asWJqVg/s1600/print-processor.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzKH7yVHvc_TEoSUJdQTMhu4iO4qbDyx5yoW_W9H0kfL0nSvTHU_yJRzZWFMfHU0ViZKMNw0zLqfQ3lJ1o7Zevu6TXzjvFV-uEhlmTGxeMylBel0RUAk4N8i7_Z5GL5R4vjgb7asWJqVg/s400/print-processor.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Deep within the print driver settings</td></tr>
</tbody></table><br />
I've recently had a driver default to the <i style="font-weight: bold;">winprint</i>. This slowed ripping significantly. Switching to one of the native HP based items improved rip speed significantly. Your mileage may vary.<br />
<div><br />
</div><div>Happy printing!</div>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-18611707769813198682011-12-16T07:51:00.000-08:002011-12-16T07:51:17.072-08:00SSL for SSRS Using a CNAME<div class="separator" style="clear: both; text-align: left;">Recently, I've been working on creating a basic reporting infrastructure. For simplicity's sake, we're leveraging Log Shipping on a relatively small application database using SQL Server 2008 R2. (Note: since this second instance is in active use, a second SQL Server license is required.)</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Since we have a server naming convention that states if the server's role is replaced, the new host must have a different name, I want to make that transition transparent in the future. I thought, let's leverage CNAMEs. I created a new CNAME record in our internal DNS and aliased the actual host name.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Now, we wanted to force clients to only use HTTPS when connecting to SSRS, so I needed to get a certificate issued and installed and setup bindings. Since this is for internal use and we have an Enterprise CA deployed, it was just a matter of requesting a certificate, except that I couldn't request a certificate based on the Web Server properties via the Computer certificate store.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg_uNKfQoIEk2mN6LGBGshens3HRVkG4akCXJ0abkIn5X85b4qYzlyf2ByHEW6Twpn4OiRNEux7WRiM8GXsLEVXG-eJ9Fdxp6fQUZaFw7q2vFsxMeEhLQLXylLhpjNzwyGsCVzIjSNGe4/s1600/cert-serv.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg_uNKfQoIEk2mN6LGBGshens3HRVkG4akCXJ0abkIn5X85b4qYzlyf2ByHEW6Twpn4OiRNEux7WRiM8GXsLEVXG-eJ9Fdxp6fQUZaFw7q2vFsxMeEhLQLXylLhpjNzwyGsCVzIjSNGe4/s400/cert-serv.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Certificate Templates on my Enterprise Certificate Authority</td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: left;">A quick hop over the the CA to adjust the security permissions to add Domain Computers for enrollment and I could request what I needed.</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibUN3OUWHd1aD_wT405Bp2bEZHwq7U7O062UMAS0vM2MbRZuELMpRxqs-MtGBOKN3BNsaVAn-eY087aM5W9H6-PtzWCeSp8VmxqtTCRd-1ACKtiUQIRJ_dekK9knYDRnluLEioJzJ4hDw/s1600/template-security.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibUN3OUWHd1aD_wT405Bp2bEZHwq7U7O062UMAS0vM2MbRZuELMpRxqs-MtGBOKN3BNsaVAn-eY087aM5W9H6-PtzWCeSp8VmxqtTCRd-1ACKtiUQIRJ_dekK9knYDRnluLEioJzJ4hDw/s400/template-security.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Adjusting security permissions for enrollment</td></tr>
</tbody></table><div class="" style="clear: both; text-align: left;"><br />
</div><div class="" style="clear: both; text-align: left;">And now I can finally get what I need:</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyteu6CIviRegvtsk_OU_I96yv9gr0h0xHKYvUNzikBOAdzHLUUh3DLlfBHS3Qg5j1J73PRRQ6GVMTXdvuYyQRYi6HQTOVoqERQJwWqAerkanM5qvBlXjS5V_fMo6wtMrbZj4eHiPgsss/s1600/new-certificate.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyteu6CIviRegvtsk_OU_I96yv9gr0h0xHKYvUNzikBOAdzHLUUh3DLlfBHS3Qg5j1J73PRRQ6GVMTXdvuYyQRYi6HQTOVoqERQJwWqAerkanM5qvBlXjS5V_fMo6wtMrbZj4eHiPgsss/s400/new-certificate.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Initiate a certificate request from the local Computer certificate store</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSTJn_U4UCmPr8Vahapiucf6nfkA74AWaH1Q-AfDFiPAJgewPlc5Tco6_MrJoTDqfT1vArEUUCZrsBC21DkQykgr9Lwml1NiKIB542kDZN8QWSr94yXuGerJes70sW23XAQnCTQ3D2IA/s1600/enrollment.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSTJn_U4UCmPr8Vahapiucf6nfkA74AWaH1Q-AfDFiPAJgewPlc5Tco6_MrJoTDqfT1vArEUUCZrsBC21DkQykgr9Lwml1NiKIB542kDZN8QWSr94yXuGerJes70sW23XAQnCTQ3D2IA/s400/enrollment.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Selecting a Web Server certificate</td></tr>
</tbody></table>This is the catch, I need to add my internal single-part CNAME DNS record and then add Subject Alternate Names for my current server which is hidden behind that CNAME. Currently, SSRS will bind the site to the primary name on the certificate by default. If I simply requested a computer certificate, my subject name would be the internal FQDN of my server, which would render my CNAME setup useless.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7e6IJfBCDsCv4cOS_nnVuhpU1nyIhjDW9k5oZIou15yi6vtb04o305yM4H47WLCqYZPiouNigYEb58ZLK6ETuDuWyhklKmadiNouPiD576Nc7_WfKD6_Mfn14BhxxJ_X3XOuihAyJacU/s1600/san-tastic.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="396" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7e6IJfBCDsCv4cOS_nnVuhpU1nyIhjDW9k5oZIou15yi6vtb04o305yM4H47WLCqYZPiouNigYEb58ZLK6ETuDuWyhklKmadiNouPiD576Nc7_WfKD6_Mfn14BhxxJ_X3XOuihAyJacU/s400/san-tastic.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Adding my CNAME and SANs</td></tr>
</tbody></table>Practical applications for doing this are for manually performed failover, or if you're really doing things right, you'll need this certificate (or a certificate like it) applied to every node in your NLB farm. Additionally, consider the use of <a href="http://msdn.microsoft.com/en-us/library/ms190445.aspx">aliases</a> for the convenience of client application <a href="http://sqlblog.com/blogs/roman_rehak/archive/2010/11/07/moving-sql-server-aliases-to-another-computer.aspx">deployments</a>.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-70264956543822479492011-12-04T23:01:00.000-08:002011-12-04T23:01:27.146-08:00Analyzing Vendor Recommendations<div class="MsoNormal"><span style="font-family: inherit;">Recently, I received some feedback from a vendor regarding changes I made to our customer's space-constrained application server, which hosts two user databases in a SQL Server 2005 instance. Let's look at some of these recommendations, shall we? These responses have more value for the vendor as learning points and thus weren't directly communicated with my customer. Rather the discussion with my customer revolves around application ownership and </span>recoverability<span style="font-family: inherit;">, and how those items align with their overall business needs.</span></div><div class="MsoNormal"><span style="font-family: inherit;"><br />
</span></div><div class="MsoNormal"><span style="font-family: inherit;">This is primarily in defense of my original actions, but brings up some important misconceptions around SQL Server, provides documentation for those myths, and discusses how to redress the issues so that the customer is served.</span></div><div class="MsoNormal"><span style="font-family: inherit;"><br />
</span></div><div class="MsoNormal"><span style="font-size: large;">Vendor Recommendations</span></div><blockquote class="tr_bq"><span style="font-family: inherit;">I realize it has been a while since I had setup my maintenance plan to backup the user databases and transaction logs, so I went in to see how they were doing. But I see they are not there anymore.</span></blockquote><div class="MsoNormal">Yes, I did change the existing maintenance plans. They didn't cover system databases, <a href="http://msdn.microsoft.com/en-us/library/dd207003.aspx">which are key for recoverability</a>. </div><blockquote class="tr_bq"><span style="font-family: inherit;">I also had a weekly maintenance plan to shrink the user databases.</span></blockquote><div class="MsoNormal">The application server is space constrained, so for performance's sake, the <a href="http://www.brentozar.com/archive/2009/08/stop-shrinking-your-database-files-seriously-now/">original Shrink Database item was removed</a> from the plan and replaced with T-SQL code for targeting log files only for <a href="http://support.microsoft.com/kb/907511">DBCC SHRINKFILE</a> commands. Joined with regular log backups, this would allow the OS to retain more free space for regular operation but still let us enjoy point-in-time recovery for user databases. For a long term solution, this system needs more storage provisioned, period.</div><blockquote class="tr_bq"><span style="font-family: inherit;">The alerts you have setup have thresholds too low. They don't take into account a database in "full" mode. </span></blockquote><div class="MsoNormal">The metrics gathered were from PerfMon stats, namely<a href="http://technet.microsoft.com/en-us/library/cc781394(WS.10).aspx"> \\SERVER\MSSQL$INSTNACE\Database\Percent Log Used</a> >= 90. This metric is valid for any recovery model and can be easily illustrated by the well known <a href="http://msdn.microsoft.com/en-us/library/ms189768.aspx">DBCC SQLPERF(LOGSPACE)</a> query, which will show us both the percentage used and the size of the log itself. This <a href="http://msdn.microsoft.com/en-us/library/ms175495.aspx">metric matters in any case</a>, and is logged to the Windows event log as an Error, not a Warning; its that important.</div><blockquote class="tr_bq"><span style="font-family: inherit;">And you should never get an alert on the tempdb system database. </span></blockquote><div class="MsoNormal">A full transaction log, regardless of which database it is for, will halt the writing of data. Things that might be missing from this systems configuration is a service account with the SE_MANAGE_VOLUME_NAME permission to allow for <a href="http://msdn.microsoft.com/en-us/library/ms175935.aspx">instant file initialization</a> when auto-growth kicks in frequently to address the utilization issue, further propagating the alerts.</div><blockquote class="tr_bq"><span style="font-family: inherit;">I went out and looked at the physical size of these databases and log sizes. They are very small compared to normal operation. The alert settings need to be changed.</span></blockquote><div class="MsoNormal">The database size isn't the issue in question (thought with Shrink Database commands, there will be fragmentation issues), but with a properly scheduled BACKUP LOG in conjuction with auto-growth enabled, a database log file will balance out with the volume of transactions hitting the database. Another item to consider is <a href="http://www.sqlskills.com/BLOGS/KIMBERLY/post/Transaction-Log-VLFs-too-many-or-too-few.aspx">the number of VLFs</a> since there's a history of growing and shrinking logs.</div><blockquote class="tr_bq"><span style="font-family: inherit;">I am changing the user databases to "simple" recovery model for now. Probably need to turn off the hourly transaction log backup for now. </span></blockquote><div class="MsoNormal"><span style="font-family: inherit;">Yes, if you're changing recovery models, you're going to cause those explicitly typed BACKUP LOG jobs to fail.</span></div><blockquote class="tr_bq"><span style="font-family: inherit;">I have run the shrink database on the user databases and on tempdb.</span></blockquote>I'm glad database size is a concern, but we should look at <a href="http://msdn.microsoft.com/en-us/library/ms188776.aspx">sp_spaceused</a> to see if we just plain need more space or if we're <a href="http://sqlserverperformance.wordpress.com/2011/02/04/five-dmv-queries-that-will-make-you-a-superhero-in-2011/">potentially over-indexed</a>. And <a href="http://sirsql.net/blog/2011/5/18/dont-shrink-tempdb.html">shrinking tempdb</a> is <a href="http://support.microsoft.com/kb/307487">documented to cause corruption</a>.<br />
<blockquote class="tr_bq"><span style="font-family: inherit;">I also see that the SQL backups are only for three days. Are these being swapped out so that there are actually more days being stored somewhere else (offsite maybe)?.</span></blockquote><div class="MsoNormal"><o:p><span style="font-family: inherit;">Looking at the larger picture, there is a VSS aware 3rd party backup system in place. SQL Server backups exist for the purpose of near-line recoverablity and point-in-time recoverability. Remember, we're space constrained, and you've just implimented a Shrink Database to address it, so we've only got so much space for backup retention. </span></o:p></div><blockquote class="tr_bq"><span style="font-family: inherit;">Please do not change any general or options properties on the user databases. I will maintain these. Just let me know if you need something changed as some items can have </span>repercussions<span style="font-family: inherit;"> on the functionallity of applications.</span></blockquote><div class="MsoNormal"><a href="http://www.brentozar.com/archive/2011/01/consulting-lines-sounds-like-youve-got-all-under-control/">It looks like you've got this under control</a>. The fact that <a href="http://msdn.microsoft.com/en-us/library/bb510680.aspx">compatibility_level is set to 80</a> and page_verify is set to <a href="http://www.littlekendra.com/2011/01/25/pageverify/">CHECKSUM</a> has me concerned. Which do we really need?</div><blockquote class="tr_bq"><span style="font-family: inherit;">The biggest point here is that user applications are two completely separate systems sharing the SQL server. They really need separate backup and maintenance plans as the data is used and maintained differently.</span></blockquote><div class="MsoNormal"><o:p><span style="font-family: inherit;">Taking a holistic view of the application and server together, these backup plans may <a href="http://sqlblog.com/blogs/merrill_aldrich/archive/2011/11/25/one-database-or-ten.aspx">need crash consistency between databases</a>. We've already shown that there are some unique issues with the compatilbity_level and "other general settings". </span></o:p></div><blockquote class="tr_bq"><span style="font-family: inherit; font-size: small;">The SQL server is two service packs behind. SQL Server 2005 should be on SP4. </span></blockquote>SQL Server 2005, even at Service Pack 4 with be <a href="http://support.microsoft.com/lifecycle/?p1=2855">out of maintenance from Microsoft</a> as of 12/2011. And this doesn't jive with the compatibility_level request from earlier. If I'm looking to future proof my application and move to SQL Server 2012, <a href="http://technet.microsoft.com/en-us/library/bb510680(SQL.110).aspx">I won't be able to attach my database</a>, let alone restore it.<br />
<br />
How can we be productive about these recommendations as consultant generalists and DBAs?<br />
<br />
<span style="font-size: large;">Communicate</span><br />
<br />
Get the stake holders into a stand-up meeting. Get the overall goals for the application written down. What's our time to recovery needs? What's our point in time recovery needs? Who's responsible for what part of a disaster recovery? How about performance? What's the life-cycle of this application?<br />
<div class="MsoNormal"><br />
</div><div class="MsoNormal"><span style="font-size: large;">Delegate</span></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Once the questions are answered, don't be afraid to let the 3rd party vendor handle the application the way your customer wants. They've elected to utilize this vendor. But be cautious, and take precautions. In this example, I'll have to let the customer know we'll still be getting alerts and inform them of the ramifications of ignoring or permanently suppressing those notifications.</div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><span style="font-size: large;">Act</span></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Put your plan into action. And, of course, backup, backup, backup. Then test, test, test! There's a ton of great information in the links above, so go do your homework so that you can act on knowledge, not assumptions.</div>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-21448174217926751822011-11-28T22:51:00.000-08:002011-11-28T22:51:09.018-08:00A New Challenger Has ArrivedHistorically, I've run this blog on hand coded HTML, <a href="http://www.wordpress.org/">Wordpress</a>, and <a href="http://www.textpattern.com/">Textpattern</a>. Those CMS platforms ran on Linux, Macs, and <a href="http://www.joyent.com/">Solaris</a> platforms. And now it's all Google.<br />
But what I really miss is my favorite CMS, Textpattern. So in the interest of restoring some of my historical posts (namely, my Japan trips) and to challenge myself to learn the .NET development stack and <a href="http://www.windowsazure.com/">Windows Azure</a> platform, I've begun the challenge to recode Textpattern. Okay, maybe not the whole thing, since Azure supports PHP, but at least get it into my RDBMS of choice, SQL Server. So, where to begin?<br />
<br />
<span style="font-size: large;">Development Platform</span><br />
<br />
To easy my way into the Windows development world, I'm going to cheat and start with <a href="http://www.microsoft.com/web/webmatrix/">WebMatrix</a>. It's fast, easy, free and has a <a href="http://www.microsoft.com/web/downloads/platform.aspx">one-click installer</a> for everything I need, named:<br />
<ul><li>WebMatrix IDE</li>
<li>MySQL 5</li>
<li>SQL Server Compac 4.0</li>
<li>IIS Express 7.5</li>
<li>PHP Extensions for PHP</li>
</ul>After I've installed the lot, it's a matter of getting the data replayed into a new database.<br />
<br />
<span style="font-size: large;">Getting Your Data Back</span><br />
<br />
Before restoring, I had to brush up on MySQL syntax, but quickly discovered what I needed. First open the MySQL prompt, connecting with the root password you set during the install. Then create a target database:<br />
<blockquote><span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">mysql> create database textpattern;</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">mysql> use textpattern;</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">mysql> source C:\path\to\mysql-dump.sql;</span><br />
<span style="font-family: "Courier New", Courier, monospace; font-size: x-small;">mysql> exit;</span></blockquote>That's all there is to it!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjygIwAPggunAK4tRmjjSzdavBNk1r2-ISWk5IFj9ZC4CUEMHJZ8I7N94ZatUiTVToLsgq8GleUmcic5UQGcct1Y97WhkgOLbsz5yPPslFV0XRl7Lx-dpUWg-UvhLlAwIZDq4NWeS3xtMI/s1600/replay-mysql-dump.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjygIwAPggunAK4tRmjjSzdavBNk1r2-ISWk5IFj9ZC4CUEMHJZ8I7N94ZatUiTVToLsgq8GleUmcic5UQGcct1Y97WhkgOLbsz5yPPslFV0XRl7Lx-dpUWg-UvhLlAwIZDq4NWeS3xtMI/s400/replay-mysql-dump.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">I can has data back!</td></tr>
</tbody></table><br />
<br />
<span style="font-size: large;">Connecting The Dots</span><br />
<br />
Next I created a new project in WebMatrix at the root folder of my extracted download of the latest version of Textpattern.<br />
<br />
<br />
<br />
If you'd like to take a look at your data from within WebMatrix, setup a database source connection to MySQL as in the screenshot below.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsKX0I7R4Ln1a1XygCmv2rU8VGqR9frXEUgj2lN-J3UzvIksZAmSwpAJCK9p1YsXEWg_zUCGQ39-H1vtB5nd8Q_7Av4QM2yjyO6x0kQjf5Ee3DLecgXU_YptDEHmNCNxadw9t0AM8Rh0s/s1600/connect-mysql.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsKX0I7R4Ln1a1XygCmv2rU8VGqR9frXEUgj2lN-J3UzvIksZAmSwpAJCK9p1YsXEWg_zUCGQ39-H1vtB5nd8Q_7Av4QM2yjyO6x0kQjf5Ee3DLecgXU_YptDEHmNCNxadw9t0AM8Rh0s/s320/connect-mysql.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Setup a MySQL Connection</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfHPAZGDtE9jcEhst0V6AdMYxbB2IqwVRzMSj7X16Xo2if9wkvJJRO6yT_dm6heyATQrqC9X9Tv_V0bw_ePEQFxnervjMxKQR27IlgYkK_gg9UJ4uEOshQW5JB9q-wF0DYw_dzkcVUIT0/s1600/my-txp-install.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfHPAZGDtE9jcEhst0V6AdMYxbB2IqwVRzMSj7X16Xo2if9wkvJJRO6yT_dm6heyATQrqC9X9Tv_V0bw_ePEQFxnervjMxKQR27IlgYkK_gg9UJ4uEOshQW5JB9q-wF0DYw_dzkcVUIT0/s320/my-txp-install.png" width="146" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Look at those pretty tables</td></tr>
</tbody></table><br />
Then, I renamed config-dist.php to match the MySQL settings I had configured, just as if I was deploying Textpattern for the first time.<br />
<br />
Launching the Textpattern admin interface for the first time forced a minor schema upgrade. Then switching to the Admin interface, I updated my website URL to match my development environment for relative URIs, and that was all I had to do!<br />
<br />
Take a quick look at my 404 page, which is clearly not Apache!<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr_9axBt610evJuYIJDRbk5-rr5TQWS8XK1JSan_3DjqsI0KCXXYS8d8D18MwBtIDP0ztbxyZFjCfdBEfy2rhOW-y9BWJkQw0_VXZlPVWFZeOdrINc0pz-evIwOAD9XTtOHkO1YnTe-DE/s1600/iis-express-404.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr_9axBt610evJuYIJDRbk5-rr5TQWS8XK1JSan_3DjqsI0KCXXYS8d8D18MwBtIDP0ztbxyZFjCfdBEfy2rhOW-y9BWJkQw0_VXZlPVWFZeOdrINc0pz-evIwOAD9XTtOHkO1YnTe-DE/s400/iis-express-404.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Definitely not Kansas</td></tr>
</tbody></table>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-55090031976143069912011-11-18T23:31:00.000-08:002011-11-18T23:31:42.792-08:00Why, SSRS, Why?<div class="separator" style="clear: both; text-align: left;">Once again, I've been digging into SSRS reporting. Today, I thought to myself, I should had a multi-valued parameter to this report for filtering my tablix aggregations. So, I created a data-set that was a self-join for gathering a list of Managers. Easy enough, that'll work great for a drop-down selection. But let's say a manager wants to only look at certain employees that they manage. A multi-valued parameter would be great for this! </div><div class="separator" style="clear: both; text-align: left;"><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhw9knSnut-LW_PInW3Ped4sh6RrSis-r8NbjqBuK2Ce2d4j7ACDjzgprzkZ2rh9uLF3MZExGEeh7u-C5JPtThCnPS5lBsjZLyf7NNegRrKF1uNGZB67J0G8Q54ifoIgh706FinNgLroV0/s1600/MVP.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhw9knSnut-LW_PInW3Ped4sh6RrSis-r8NbjqBuK2Ce2d4j7ACDjzgprzkZ2rh9uLF3MZExGEeh7u-C5JPtThCnPS5lBsjZLyf7NNegRrKF1uNGZB67J0G8Q54ifoIgh706FinNgLroV0/s400/MVP.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">I'd like a side of extra values in an array, please.</td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: left;">Add one data-set for that scenario, and re-order the parameters for proper cascading.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Then it's just a matter of adding my managed employees MVP to the tablix filter, right? Okay, here it is, I'll just double click it and get the right syntax.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSxmaWev8us93rhq9o2DB2EnOAZBU54XxC3NiEbrXSGjT-a1nGKZCuGTlYYLTYVJTBeNFaAVhpjYfLZzkvtJIgKKHlvQ9yTI7JmmVYFOOR-KOwSpBXuwMvrYPwKTrG61nqs47W3DTAoEs/s1600/Default.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="363" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSxmaWev8us93rhq9o2DB2EnOAZBU54XxC3NiEbrXSGjT-a1nGKZCuGTlYYLTYVJTBeNFaAVhpjYfLZzkvtJIgKKHlvQ9yTI7JmmVYFOOR-KOwSpBXuwMvrYPwKTrG61nqs47W3DTAoEs/s400/Default.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">What's wrong with this picture?</td></tr>
</tbody></table><br />
So, why am I only getting one member's aggregates in my tablix? This is some serious fail!<div><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwXC0TDo8tBP389Fi_YmYkRnh9ufFSCUKOSBivob4mRWEV56xELUHIk_eDhbwMcddN3LjY-cMS3tLr21R6YgzoDGtFIsK86gc2PpT5d1qnQnBcdREuC_tZ2KJFwSntld2IajK94ZfmglE/s1600/What-You-Need.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="363" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwXC0TDo8tBP389Fi_YmYkRnh9ufFSCUKOSBivob4mRWEV56xELUHIk_eDhbwMcddN3LjY-cMS3tLr21R6YgzoDGtFIsK86gc2PpT5d1qnQnBcdREuC_tZ2KJFwSntld2IajK94ZfmglE/s400/What-You-Need.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Oh, of course!</td></tr>
</tbody></table><div>A few searches through MSDN for syntax <a href="http://msdn.microsoft.com/en-us/library/aa337292(SQL.100).aspx">and we discover</a> that for multi-valued parameters, appending "(0)" in your expression causes SSRS to query only the first value in your array. I'm glad that got added by default when the parameter was an explicitly typed array. Not very conducive for learning syntax on the fly. But now we've got one (significantly more readable) report.</div>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-79335000577691717742011-10-25T09:34:00.000-07:002011-10-25T09:34:00.321-07:00More Schema FunSo let's say you don't have any sort of Exchange on premises for an Office 365 deployment. You have Active Directory on premises for authentication and some local storage for things like QuickBooks or large volumes of CAD drawings. Office 365 seems like a good fit for a small organization because you just don't need those extra servers and management overhead.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Wait, wait! Don't tell me!</span><br />
<br />
But once again, schema matters, because when you created a new user, even though you set their eUPN accordingly, they're getting email aliases with <a href="http://community.office365.com/en-us/f/148/t/310.aspx?PageIndex=2">that pesky <b><i>onmicrosoft.com</i></b> domain</a> as the primary alias. So you think, <i>It's just Exchange 2010, I'll use PowerShell remoting and do some wizardry behind the scenes.</i> Nope, fail. You can't. The primary SMTP alias comes from an Active Directory property that's automatically populated in domains with on premises Exchange when you create a user's mailbox.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Enter the ADSIEdit</span><br />
<br />
If you've been an Exchange administrator for a while, you've probably played with the proxyAddresses attribute before. I've mentioned it before when you're looking to add a secondary alias. But if you don't even have a primary alias, you'll be seeing this:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2PJoeIkBCTWittnZWbnR2yl0cs85P5a4MCP_Atvbiuj4REhFL4sqFE7nkqTzFq6dJV_Mwfy-Npm-_EmL-jnGeR9Ju9iVwgyxGOvHrdedHUPxvf96KW1eHh_h5gOOUNTdwNXpKD2b9Q2k/s1600/User-Properties.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2PJoeIkBCTWittnZWbnR2yl0cs85P5a4MCP_Atvbiuj4REhFL4sqFE7nkqTzFq6dJV_Mwfy-Npm-_EmL-jnGeR9Ju9iVwgyxGOvHrdedHUPxvf96KW1eHh_h5gOOUNTdwNXpKD2b9Q2k/s400/User-Properties.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">proxyAddresses is undefined</td></tr>
</tbody></table><br />
Launching <b><i>ADSIEdit</i> </b>from <i style="font-weight: bold;">Administrator Tools</i> on the <i style="font-weight: bold;">Start Menu</i> gets us going. Connect to your <i style="font-weight: bold;">Default Naming Context</i> and drill down to your user object. Right clicking the user allows you to select <i style="font-weight: bold;">Properties</i>. Double check that the <i style="font-weight: bold;">Show only attributes that have values</i> is unchecked.<div><br />
</div><div>Drilling down through our list you'll see that <i style="font-weight: bold;">proxyAddresses</i> is blank. Set it to <i style="font-weight: bold;">SMTP:youralias@vanitydomain.com</i>. Make sure that you have one and only one address with the <i style="font-weight: bold;">SMTP</i> capitalized. Hop over to your <i style="font-weight: bold;">Directory </i><b><i>Synchronization</i></b> host and re-run the <i><b>Directory Synchronization Configuration</b></i> wizard.</div><div><br />
</div><div><span class="Apple-style-span" style="font-size: large;">Other Cool Stuff</span></div><div><br />
</div><div>Let's say you want to see who you've missed this property on before. If you launch <i style="font-weight: bold;">ADUC</i>, you can create a custom query and configure an LDAP filter:</div><div><br />
</div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">(&(objectClass=User)(!proxyAddresses=*SMTP*))</span></div>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-11360530478092196512011-10-20T08:13:00.000-07:002011-10-20T08:13:47.176-07:00Office 365: Schema MattersWe just pushed an a la carte deployment of Microsoft Online services in order to eliminate the on-premises requirements for Lync. In the process, we discovered that our legacy OCS 2007 internal-only deployment caused some schema issues for us. We had politely decommissioned the OCS host by un-registering the various roles, uninstalling the application, then eventually disjoining it from the domain.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">The evils of directory synchronization</span><br />
<br />
But this environment is running ADFS2 and DirSync for a unified single sign-on experience. That means any AD schema extensions we have regarding Exchange or Lync/OCS are propagated to the cloud. The most critical property is msRTCSIP-UserEnabled. Anyone who logged into OCS in the legacy deployment has this attribute, and during the above decommissioning procedures, it is set to FALSE by the installers. Give it 3 hours, and now you have licensed users in Office 365, who have AD properties to the contrary. But you can't change it from the cloud, you have to change it in your AD and force a synchronization.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXrKJqk2mbVAasmuqyJntpQ1hwAbtwrW6y2g4aX71AyTvsKuNET990igpvXTe9J_rv1Pir8QErwOstsPBi7JJSOrQATGoEtccPxlQXfyV-x-FLkMmGn1x4uO7wCRcfDzqvggMa3dVzbiM/s1600/msRTCSIP-UserEnabled.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXrKJqk2mbVAasmuqyJntpQ1hwAbtwrW6y2g4aX71AyTvsKuNET990igpvXTe9J_rv1Pir8QErwOstsPBi7JJSOrQATGoEtccPxlQXfyV-x-FLkMmGn1x4uO7wCRcfDzqvggMa3dVzbiM/s1600/msRTCSIP-UserEnabled.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Don't let this happen to you.</td></tr>
</tbody></table><span class="Apple-style-span" style="font-size: large;">ADModify.net to the rescue</span><br />
<div><br />
</div><div>Enter my favorite ADDS tool (and soon to be yours), <a href="http://admodify.codeplex.com/">ADModify.net</a>. This tool uses LDAP calls to ADDS, scripting mass changes behind the scenes. This is useful not only for resolving this problem, but also for setting your <a href="http://blogs.dirteam.com/blogs/jorge/archive/2010/10/13/user-principal-names-in-ad-part-1.aspx">eUPN</a> to your vanity domain for all desired Office 365 users. It's also a portable app you can keep on a USB drive for quickly making changes at customer sites.</div><div><br />
</div><div>Before we solve our problem, don't forget to add <i style="font-weight: bold;">%sAMAccountName%</i> in the <i style="font-weight: bold;">Legacy Account</i> field of the <i style="font-weight: bold;">Account</i> tab, or you'll blank out everyone's UPNs! It's simple to resolve, but easy to miss.</div><div><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFcGbX7pdh3leVI1ELyVoKC2OvQ6khtdd2CoE_fZTf47RBw9O-rKlNpDq5l2UxGsArlIYO55lZ1TUG7cRTNI79HAF-3-J7XIZYxWAgOS9TTKjvvs_XUXgUba5Qx7tS6nK3QlcsA3BXIaQ/s1600/admod-upn.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFcGbX7pdh3leVI1ELyVoKC2OvQ6khtdd2CoE_fZTf47RBw9O-rKlNpDq5l2UxGsArlIYO55lZ1TUG7cRTNI79HAF-3-J7XIZYxWAgOS9TTKjvvs_XUXgUba5Qx7tS6nK3QlcsA3BXIaQ/s400/admod-upn.png" width="315" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Set that eUPN, but don't forget %sAMAccountName%</td></tr>
</tbody></table><br />
Moving on to the <i style="font-weight: bold;">Custom</i> tab, check the <i style="font-weight: bold;">Make a customized attribute modification</i> and specify our troublesome property, <i style="font-weight: bold;">msRTCSIP-UserEnabled</i>, and set it to <i style="font-weight: bold;">TRUE</i>. Note, this will add the property to any objects that currently do not have it, so select users judiciously.<br />
<div><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtiqaPNaYIf9t9MgnqmifE_7PWsje6rvnVjG0KycX8hlJw3MWeOOuBs7lYAuzUT-328L-7Z8iKekVI4p0Vl3IODzzvX1TzkVy7TZDbTLUVbE0BAWLFrdkO218ZNLQrTXolAEYllVxX8pg/s1600/admod-msRTCSIP-UserEnabled.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtiqaPNaYIf9t9MgnqmifE_7PWsje6rvnVjG0KycX8hlJw3MWeOOuBs7lYAuzUT-328L-7Z8iKekVI4p0Vl3IODzzvX1TzkVy7TZDbTLUVbE0BAWLFrdkO218ZNLQrTXolAEYllVxX8pg/s400/admod-msRTCSIP-UserEnabled.png" width="315" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Set a custom attribute, for everyone.</td></tr>
</tbody></table><div><br />
<div>Hit <i style="font-weight: bold;">Go!</i> then jump on your DirSync server and <a href="http://onlinehelp.microsoft.com/en-us/office365-enterprises/996fa36d-b4ea-441d-aacd-39a59a21b59f#BKMK_SynchronizeDirectories">force a synchronization</a> and it's off to the races for Lync.</div><div><br />
</div><div><span class="Apple-style-span" style="font-size: large;">Why do I care?</span></div><div><br />
</div><div>You probably asking why this even matters. Well, with DirSync, if you have a property Microsoft cares about (pretty much from any co-existence scenario), then Microsoft is going to take that objects property and put it in their AD. Say you're in an organization that never had on-premises Exchange and you move to Office 365. Well that means with SSO and DirSync, you won't be able to set the <a href="http://www.messageops.com/attributes-synchronized-by-microsoft-online-directory-synchronization">msExchangeHideFromAddressLists property</a>, because your schema doesn't have it. And you can't make that change via remote PowerShell or the Exchange Online console because Microsoft expects it to come from your on-premises AD.</div><div><br />
</div><div>So, know your limits. And also know your recent schema changes and how to look for differences between objects.</div></div>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-77426106132067763192011-08-26T12:26:00.000-07:002011-08-26T12:29:08.084-07:00Add a secondary alias to a federated Office 365 mailboxToday, Joe called and asked me why he couldn't get emails at <b><i>joesph@contoso.com</i></b>. Well, his account was setup for <b><i>joe@contoso.com</i></b> and that's also his UPN in Active Directory. His business cards have already been printed and he's been using his email to send, so we can't just re-create things.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Office 365, open the pod bay doors</span><br />
<br />
Now, you could just log into Office 365, click on <b><i>Manage</i> </b>under <i style="font-weight: bold;">Exchange Online</i>, find the user's mailbox and add the address under <i style="font-weight: bold;">E-mail Addresses</i>. But since your using SSO with Federation, you're getting this lovely message:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL1hRavsUuJS4wc_ngRdb4D841aVOdx4sZAgY9GjxUsYshKH-AKOfIjBYTG6My4qUPTMOGCeI75VyxRbJapjQU6RBRGvW2XSSXUjRJ150UpSMxRp19WQXfkME1d9RxL84CdL0EbqpCxbU/s1600/web-manage-fail.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL1hRavsUuJS4wc_ngRdb4D841aVOdx4sZAgY9GjxUsYshKH-AKOfIjBYTG6My4qUPTMOGCeI75VyxRbJapjQU6RBRGvW2XSSXUjRJ150UpSMxRp19WQXfkME1d9RxL84CdL0EbqpCxbU/s400/web-manage-fail.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">I'm sorry, Dave. I can't do that.</td></tr>
</tbody></table><span class="Apple-style-span" style="font-size: large;">Really, open the bay doors, please</span><br />
<div><br />
</div><div>Well, if you managed to get SSO and Federation configured, you're probably already familiar with the key to this process, ADSIEdit. Launch it and connect to the <i style="font-weight: bold;">Default naming context</i>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGQnO9a6UJp5xpJrJ263zJJh9Iwg_V_igA9kD_BwQvyACUaNE3MDbH9ig1lpz-Caf3hUEdiVI7BJQzA7v0dq0LrhG0_-R6rBcC8PCUtt9-88igIDVE-dtV5RjWQ6N38_ex3HoIc9sL2Xw/s1600/adsi-default-naming-context.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGQnO9a6UJp5xpJrJ263zJJh9Iwg_V_igA9kD_BwQvyACUaNE3MDbH9ig1lpz-Caf3hUEdiVI7BJQzA7v0dq0LrhG0_-R6rBcC8PCUtt9-88igIDVE-dtV5RjWQ6N38_ex3HoIc9sL2Xw/s400/adsi-default-naming-context.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Step 1: Get the Blue Key</td></tr>
</tbody></table>Drill down through the schema until you find your user object, right click it and select <i style="font-weight: bold;">Properties</i>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjqg3GzH71aM_u3cyAiwodjCfEUaIFokdLAl1Q2Ttxa5ZyZPZ-zhZMmRCXzNzu5MvbJuuucrEtFubw1b9Sl5gs8WiwDirNXz7M5mRNPwKpgF8ROZb5QpNPNE8-Hb6mecmbYxmVTYZILAE/s1600/proxyAddresses.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjqg3GzH71aM_u3cyAiwodjCfEUaIFokdLAl1Q2Ttxa5ZyZPZ-zhZMmRCXzNzu5MvbJuuucrEtFubw1b9Sl5gs8WiwDirNXz7M5mRNPwKpgF8ROZb5QpNPNE8-Hb6mecmbYxmVTYZILAE/s400/proxyAddresses.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Step 2: Get the Red key</td></tr>
</tbody></table> Locate the <i style="font-weight: bold;">proxyAddresses</i> property and edit it. Add your secondary alias using the following format (capitalization matters, significantly!):<br />
<br />
<div style="text-align: center;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">smtp:useralternate@contoso.com</span></div><br />
Note the existing alias with a capitalized <b><i>SMTP</i></b>. That means it's the primary, so we don't want to mess with it. Click <i style="font-weight: bold;">OK</i> all the way back out of ADSIEdit and head over to your DirectorySync server. Launch <b><i>%programfiles%\Microsoft Online Directory Sync\DirSyncConfigShell.ps1</i></b> and type:<br />
<br />
<div style="text-align: center;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Start-OnlineCoexistenceSync</span></div><br />
Later, log into the management console of Exchange Online and you should see the results you need:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNvYNsb0XOm_J_d4eUXZfQtFA6wwPT8lnA-3PNeqadipXUPH1zEalX3ldcTKSKTSIsZ1y7D7CTd90rv19wjEk99sSGDq1i8MHOkZeItyHsUzvpdOPxbH0kNYzXX16qeZy1wQHoAbmlNlo/s1600/the-pod-bay.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNvYNsb0XOm_J_d4eUXZfQtFA6wwPT8lnA-3PNeqadipXUPH1zEalX3ldcTKSKTSIsZ1y7D7CTd90rv19wjEk99sSGDq1i8MHOkZeItyHsUzvpdOPxbH0kNYzXX16qeZy1wQHoAbmlNlo/s400/the-pod-bay.jpg" width="346" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Look, it's the pod bay, finally!</td></tr>
</tbody></table><br />
And according to the references below, if we extend the Active Directory schema for Exchange 2010 SP1, we can leverage additional Active Directory properties that will replicate up to Office 365 and take effect. Or we could all learn <a href="http://www.mikepfeiffer.net/2010/11/office-365-connecting-to-exchange-online-with-remote-powershell/">PowerShell remoting</a>, which I've used a few times already for other items, like mass contact creation, but I'll leave that as an exercise for the reader.<br />
<br />
References:<br />
<br />
<ul><li><a href="http://community.office365.com/en-us/f/158/p/7857/32254.aspx#32254">http://community.office365.com/en-us/f/158/p/7857/32254.aspx#32254</a></li>
<li><a href="http://onlinehelp.microsoft.com/en-us/office365-enterprises/996fa36d-b4ea-441d-aacd-39a59a21b59f#BKMK_SynchronizeDirectories">http://onlinehelp.microsoft.com/en-us/office365-enterprises/996fa36d-b4ea-441d-aacd-39a59a21b59f#BKMK_SynchronizeDirectories</a></li>
</ul><br />
<br />
<br />
</div>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com1tag:blogger.com,1999:blog-4279057743765095593.post-34738888119873870362011-08-17T16:58:00.000-07:002013-06-01T13:28:33.100-07:00Refactoring sp_spaceusedA while back I refactored sp_spaceused into CTEs. One query would return the total for a database, the other would return totals for individual user objects within the current execution context. This only accounted for on-page data, which the original stored procedure does manage. I keep finding myself running the object level query to determine which tables are index heavy or are ready for historical archiving, both of which are especially handy when you're working with the storage limitation of Express Edition. (Sample <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1025914">use</a> <a href="http://kb.vmware.com/selfservice/microsites/search.do?cmd=displayKC&externalId=1007453">cases</a>)<br />
<br />
<i><u>Disclaimer: By following any of these activities you hold the author harmless of any effects, averse or otherwise. There's no fitness or guarantee for this information. </u></i><br />
<br />
<code style="font-size: 12px;"><span style="color: blue;">WITH </span><span style="color: black;">size_calculations </span><span style="color: grey;">(</span><span style="color: black;">objectid</span><span style="color: grey;">, </span><span style="color: black;">reserved_pages</span><span style="color: grey;">, </span><span style="color: black;">used_pages</span><span style="color: grey;">, </span><span style="color: black;">pages</span><span style="color: grey;">, </span><span style="color: black;">num_rows</span><span style="color: grey;">)</span><span style="color: blue;">AS </span><span style="color: grey;">(</span><span style="color: blue;">SELECT </span><span style="color: black;">[OBJECT_ID] </span><span style="color: blue;">AS </span><span style="color: black;">[objectid]<br />
</span><span style="color: grey;">, </span><span style="color: magenta;">SUM</span><span style="color: grey;">(</span><span style="color: black;">reserved_page_count</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[reserved_pages]<br />
</span><span style="color: grey;">, </span><span style="color: magenta;">SUM</span><span style="color: grey;">(</span><span style="color: black;">used_page_count</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[used_pages]<br />
</span><span style="color: grey;">, </span><span style="color: magenta;">SUM</span><span style="color: grey;">( </span><span style="color: magenta;">CASE<br />
</span><span style="color: blue;">WHEN </span><span style="color: grey;">(</span><span style="color: black;">index_id </span><span style="color: grey;">< </span><span style="color: black;">2</span><span style="color: grey;">) <br />
</span><span style="color: blue;">THEN </span><span style="color: grey;">(</span><span style="color: black;">in_row_data_page_count </span><span style="color: grey;">+ </span><span style="color: black;">lob_used_page_count </span><span style="color: grey;">+ </span><span style="color: black;">row_overflow_used_page_count</span><span style="color: grey;">)<br />
</span><span style="color: blue;">ELSE </span><span style="color: black;">lob_used_page_count </span><span style="color: grey;">+ </span><span style="color: black;">row_overflow_used_page_count<br />
</span><span style="color: blue;">END<br />
</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[pages]<br />
</span><span style="color: grey;">, </span><span style="color: magenta;">SUM</span><span style="color: grey;">( </span><span style="color: magenta;">CASE<br />
</span><span style="color: blue;">WHEN </span><span style="color: grey;">(</span><span style="color: black;">index_id </span><span style="color: grey;">< </span><span style="color: black;">2</span><span style="color: grey;">) </span><span style="color: blue;">THEN </span><span style="color: black;">row_count<br />
</span><span style="color: blue;">ELSE </span><span style="color: black;">0<br />
</span><span style="color: blue;">END<br />
</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[num_rows]</span><span style="color: blue;">FROM </span><span style="color: black;">sys.dm_db_partition_stats</span><span style="color: blue;"> GROUP BY </span><span style="color: black;">[object_id]</span><span style="color: grey;">)</span><span style="color: blue;">SELECT </span><span style="color: magenta;">OBJECT_NAME</span><span style="color: grey;">(</span><span style="color: black;">SC.objectid</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[name]<br />
</span><span style="color: grey;">, </span><span style="color: black;">SC.num_rows </span><span style="color: blue;">AS </span><span style="color: black;">[rows]<br />
</span><span style="color: grey;">, (</span><span style="color: black;">SC.reserved_pages </span><span style="color: grey;">* </span><span style="color: black;">8</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[reserved_kb]<br />
</span><span style="color: grey;">, (</span><span style="color: black;">SC.pages </span><span style="color: grey;">* </span><span style="color: black;">8</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[data_kb]<br />
</span><span style="color: grey;">, ((</span><span style="color: magenta;">CASE </span><span style="color: blue;">WHEN </span><span style="color: black;">SC.used_pages </span><span style="color: grey;">> </span><span style="color: black;">SC.pages </span><span style="color: blue;">THEN </span><span style="color: grey;">(</span><span style="color: black;">SC.used_pages </span><span style="color: grey;">- </span><span style="color: black;">SC.pages</span><span style="color: grey;">) </span><span style="color: blue;">ELSE </span><span style="color: black;">0 </span><span style="color: blue;">END</span><span style="color: grey;">) * </span><span style="color: black;">8</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[index_size_kb]<br />
</span><span style="color: grey;">, ((</span><span style="color: magenta;">CASE </span><span style="color: blue;">WHEN </span><span style="color: black;">SC.reserved_pages </span><span style="color: grey;">> </span><span style="color: black;">SC.used_pages </span><span style="color: blue;">THEN </span><span style="color: grey;">(</span><span style="color: black;">SC.reserved_pages </span><span style="color: grey;">-</span><span style="color: black;">SC.used_pages</span><span style="color: grey;">) </span><span style="color: blue;">ELSE </span><span style="color: black;">0 </span><span style="color: blue;">END</span><span style="color: grey;">) * </span><span style="color: black;">8</span><span style="color: grey;">) </span><span style="color: blue;">AS </span><span style="color: black;">[unused_kb]</span></code><br />
<code style="font-size: 12px;"><span style="color: blue;">FROM </span><span style="color: black;">size_calculations </span><span style="color: blue;">AS </span><span style="color: black;">SC</span></code><br />
<code style="font-size: 12px;"><span style="color: blue;">INNER JOIN </span><span style="color: black;">sys.objects </span><span style="color: blue;">AS </span><span style="color: black;">O</span></code><br />
<code style="font-size: 12px;"><span style="color: blue;">ON </span><span style="color: black;">SC.[objectid] </span><span style="color: blue;">= </span><span style="color: black;">O.[object_id]</span></code><br />
<code style="font-size: 12px;"><span style="color: blue;">WHERE </span><span style="color: black;">O.</span><span style="color: blue;">TYPE = </span><span style="color: red;">'U'</span></code><br />
<code style="font-size: 12px;"><span style="color: blue;">ORDER BY </span><span style="color: black;">SC.reserved_pages </span><span style="color: blue;">DESC</span><span style="color: grey;">;</span></code>Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-31009755617687239332011-08-08T16:31:00.000-07:002011-08-08T16:31:22.796-07:00Where are my SQL Servers?How can you discover where SQL Servers are in your enterprise environment?<br />
<br />
There's always the handy <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">sqlcmd -L</span>, but how can you know you've found everything?<br />
<br />
How about this for starters:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">csvde -f out.csv -r "(&(objectClass=Computer)(servicePrincipalName=*SQL*))" -l name,servicePrincipalName</span><br />
<br />
It's left as an exercise for the reader to find the intersection of the results of the above tools, along with validation.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-44443549080125630932011-08-01T08:00:00.000-07:002011-08-01T08:00:04.803-07:00Fixing Old LaptopsFor the last ten years, I've been the computer guy in the family. That means when I'm home or visiting friends, there's an awkward moment after "How have you been?" and before "So, my computer..."<br />
<br />
Last week, I went up to see my sister-in-law and her family, and her girls were complaining about their old "homework" laptop. It was essentially the same hardware as my ThinkPad x41t, which actually can manage to run Windows 7 Ultimate. That being said, with Windows XP on a Pentium M with a 4500RPM IDE drive, things just aren't going to be that fast. And there was malware involved. So where do we start?<br />
<i><br />
</i><br />
<i><u>Disclaimer: By following any of these activities you hold the author harmless of any effects, averse or otherwise. There's no fitness or guarantee for this information. </u></i><br />
<br />
<span class="Apple-style-span" style="font-size: large;">Safe Mode Cleaning</span><br />
<br />
First, boot the computer into Safe Mode with Networking. At this point, I like to cleanup as much temporary data as possible to reduce malware removal tool scan time. Tools like Piriform's <a href="http://www.piriform.com/ccleaner">CCleaner</a> work great to clean up the local profile. If you need to clean other user profiles, you're on your own or logging in and out several times to run the tool.<br />
<br />
Following up with a scan with tools like <a href="http://www.malwarebytes.org/products/malwarebytes_free">Malwarebytes</a> (a current favorite) and you've got a head start on the malware problem.<br />
<br />
Additionally, I typically like to check a few registry locations, however the majority of the startup items can be located by TrendMicro's <a href="http://free.antivirus.com/hijackthis/">Hijackthis</a> tool. Be cautious as many of the keys it enumerates are, in fact, supposed to exist.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Disk Problems</span><br />
<br />
In safe mode, you can also check the health of the logical disk using <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">chkdsk</span>. If I'm having a performance issue loading or opening programs, it's important to confirm that you're not getting disk read errors causing re-reads. Realistically, the speed at which disks operate today actually causes more read errors that you know, but there's automatic disk correction occurring under the hood. What I'm looking for is significant logical errors on the disk, which can also mean pending disk failure.<br />
<br />
If <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">chkdsk</span> reports more errors than a volume bitmap error, then I'll schedule a <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">chkdsk /f</span> on the next reboot to get those index errors repaired.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Useless Programs and Features</span><br />
<br />
Once back in Windows, I'll load up <b><i>Add and Remove Programs</i></b> and audit the installed applications. Frequently there's a plethora of toolbars, which can slow down browser performance. Occasionally, there's two versions of Java, which I recommend running only the latest, most up-to-date version, unless you have an application compatibility issue, such as using the web management software for Cisco PIX firewalls (Requires Java SE 1.4.14, I believe).<br />
<br />
The biggest culprit I see slowing down older hardware running Windows XP is the <a href="http://www.microsoft.com/windows/products/winfamily/desktopsearch/default.mspx">Windows Desktop Search 4.0</a> feature that's installed via Windows Update. It's a great tool, and I leverage it on my Windows 7 workstation, but that's newer hardware. It's the Microsoft equivalent to <a href="http://desktop.google.com/">Google Desktop</a>. If you don't need it, then you don't need it crawling across your slow disk, reading and indexing files in the background.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Defragmentation</span><br />
<br />
Speaking of disks, how about defragmenting? <a href="http://www.diskeeper.com/">Diskeeper</a> swears by it as a performance tool, however the measurable results can be negligible. Rather, if you have the option to re-install Windows from scratch and happen to have a Windows 7 install CD lying around, consider using it to pre-format your disks for your Windows XP install so that you can take advantage of <a href="http://blogs.msdn.com/b/jimmymay/archive/2009/05/08/disk-partition-alignment-sector-alignment-make-the-case-with-this-template.aspx">disk partition alignment</a>, which applies not only to servers, but to workstations.<br />
<br />
As for actually defragmenting, I prefer both Piriform's <a href="http://www.piriform.com/defraggler">Defraggler</a> and Sysinternal's <a href="http://technet.microsoft.com/en-us/sysinternals/bb897428">contig</a>. The former allows for a more efficient whole disk defragmentation including defragmenting free-space. Both utilities allow for single-file defragmentation.<br />
<br />
Additionally, some system files, namely the paging file and registry hives, cannot be defragmented in user-mode. Instead, you could defragment free space, set your paging file to zero, reboot, set your paging file back to a 1:1 ratio with you physical memory, and reboot again, hoping that the file will be created in contiguous free space. Or you could just use <a href="http://technet.microsoft.com/en-us/sysinternals/bb897426">PageDefrag</a>. The tool does a boot-time defrag of the paging file and registry hives, just like a <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">chkdsk /f</span>. I don't run this tool on a regular basis, but only when I'm being incredibly aggressive with my disk fragmentation.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">General System Optimizations</span><br />
<br />
Do you really need those fancy themes? Or Fast User Switching on a computer with a single account?<br />
<br />
Right clicking <i style="font-weight: bold;">My Computer</i> and selecting properties brings up all the tabs we need. Under the <i style="font-weight: bold;">Remote</i> tab, are you even using Remote Desktop or Remote Assistance? How about unchecking the option? How about System Restore? Checking the turn off box will also clear out the disk space it uses, where old malware files tend to hide.<br />
<br />
The <i style="font-weight: bold;">Advanced</i> tab is where the real magic happens. For Performance settings, set to <i style="font-weight: bold;">Adjust for best performance</i>. You'll lose that fancy blue color, but it's a few less bitmaps to load into memory. Switch over to the <i style="font-weight: bold;">Advanced</i> tab under <i style="font-weight: bold;">Peformance</i>, and click on <i style="font-weight: bold;">Change</i> to set your page file size. Regardless of the size you set (I prefer a 1:1 ratio to physical memory), you should set the <i style="font-weight: bold;">Custom Size</i> minimum and maximum to the same size. Why should Windows waste disk IO and CPU resources managing and resizing the paging file? Don't forget to click <i style="font-weight: bold;">Set</i> to actually apply the setting, and then later reboot. If you can put the paging file on a different volume that resides on a different physical disk, you can experience improved performance.<br />
<br />
Under the <b><i>Startup and Recovery</i> </b>section of the <i style="font-weight: bold;">Advanced</i> tab is also where you control the BSOD actions. If at all possible set it to not automatically reboot and to write a full memory dump. This allows you to use tools like Nirsoft's <a href="http://www.nirsoft.net/utils/blue_screen_view.html">BlueScreenView</a> to inspect the root cause of the crash. (It's left as an exercise to the reader to learn about <a href="http://www.dumpanalysis.org/blog/">Crash Dump Analysis</a>.)<br />
<br />
The next stop is <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">services.msc</span>. Now that we've got the windowing system down to the minimums, does the <b><i>Themes</i> </b>service need to be running? Nah, let's set it to <b><i>Stopped</i></b> and <b><i>Disabled</i></b>. And if we're using a single account on the system, stop and disable <i style="font-weight: bold;">Fast User Switching</i>. What about <i style="font-weight: bold;">Windows Wireless Zero Configuration</i> on a desktop system? Or <i style="font-weight: bold;">Print Spooler</i>? If you disabled <i style="font-weight: bold;">System Restore</i> earlier, you can also disable the service. <i style="font-weight: bold;">Windows Indexer</i>? <i style="font-weight: bold;">Windows Search</i>? (Which you hopefully uninstalled already.) Be very judicious about disabling services though, as some of the dependencies are not as obvious and your risk creating an unstable system.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">The End Result</span><br />
<br />
Once I went through all of these items, I was able to reduce CPU usage, stabilize a dying disk, and reduce memory utilization by a whopping 50%. The main problems I found were malware, logical disk corruption, and Windows Search causing high IO.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com1tag:blogger.com,1999:blog-4279057743765095593.post-4139326321865655222011-07-15T09:04:00.001-07:002011-07-15T09:04:28.129-07:00Mega-Patch TuesdayAt my local PASS chapter meeting last Wednesday, I discovered I was behind on the latest news. SQL Server 2008 R2 Service Pack 1 was released! Having just done a cluster deployment and three internal upgrades, I had to get a plan in order for deployment.<br />
<br />
Beforehand, I thankfully discovered <a href="http://blogs.msdn.com/b/sqlreleaseservices/archive/2011/06/21/cumulative-updates-included-in-sql-server-2008-r2-sp1.aspx">the latest</a> from Microsoft Release Services. Apparently the RTM of SP1 is essentially Cumulative Updates 1 through 6. Really? I'm ahead of the curve? In my zeal for fresh deployments (and for a customer's requirements), I had slipstreamed Cumulative Update 8 on all of my recent deployments. Those changsets don't get included until Service Pack 1 Cumulative Update 1. That certainly saves me some time!<br />
<br />
Now if I could only find time to finish deploying SSRS internally.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com0tag:blogger.com,1999:blog-4279057743765095593.post-78853572751190989022011-07-13T08:29:00.000-07:002011-07-13T08:31:38.899-07:00MPIO, iSCSI, and the ClusterI've been working away at a Windows Server 2008 R2 based cluster for the eventual deployment of two SQL Server 2008 R2 instances. I've dug, and I've dug, and I've dug, but I couldn't find a good order of configuration for getting the basics of the iSCSI SAN configured for multi-pathing, so here's what I've experienced.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Setup VLANs</span><br />
<br />
Unfortunately, we've only got one switch to work with, but at least it's gigabit and managed. I setup three VLANs, one to carry public network traffic, one for the first iSCSI subnet, and one for the second iSCSI subnet. Why two VLANs for iSCSI? I don't want to have the broadcast communication from one interfering with another, as there will be no default gateway on either subnet to assist with routing. It's left as an exercise for the reader to learn the VLAN configuration for your particular model switch. But if you've got an HP ProCurve, they do provide some <a href="http://www.hp.com/rnd/support/config_examples/2512_2524.htm">sample configurations</a>.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Configure SAN</span><br />
<br />
Thanks to Alan Hirt's (<a href="http://www.sqlha.com/blog/">blog</a> | <a href="http://twitter.com/#!/sqlha">twitter</a>) book, I was able to plan my LUNs, and even then as requirements changed I had to redo them several times. For my SAN, and <a href="http://h10010.www1.hp.com/wwpc/us/en/sm/WF06b/12169-304616-241493-241493-241493-4118559-5048949-5048950.html">HP P2000 G3 iSCSI bundle</a> with 12 2.5" SAS disks, HP uses the term "volume" to refer to LUNs. Don't confuse this with the term volume used to describe a filesystem container on a partition. All told, we needed eight LUNs for basic quorum, MSDTC, two data volumes, two log volumes, and two backup volumes. I avoided the use of mountpoints to keep the configuration easily readable. In the SMB market, mountpoints have been basically unheard of.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Configure IP addressing</span><br />
<br />
For Public, it's simple enough. For the Private (or heartbeat), we used a cross-over cable and 10.50.50.0/24. Then to differentiate our iSCSI controllers, we used 10.10.10.0/24 and 10.10.20.0/24 for Controller A and Controller B, respectively. Those subnets are over-zealous, but for the sake of support-ability, I chose a commonly known subnet mask.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Configuring iSCSI</span><br />
<br />
This is where things got heady and confusing. At this point there's about 10 different IPs in the mix, plus those VLANs, and a bunch of identically colored cables. When picking a target for discovery, go with the IP you know and love on Controller A. Remember to check <b style="font-style: italic;">Enable Multi-Path</b> when <a href="http://mikefrobbins.com/2010/08/26/multipath-io-installation-on-windows-2008-r2-server-core/">adding a Target</a>. It'll chose the default binding for the initiator (0.0.0.0), which might not be what we want, but it's a start. It's those sessions that really matter. Don't forget to switch to the <i style="font-weight: bold;">Volumes and Devices</i> tab and use <i style="font-weight: bold;">Auto Configure</i> to associate those LUNs.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiflo9qLVROVVKNMI-LHzxy-LgyzjljWDGc0WhtlWK9_0k8PH_wD0GGqMCJlA0S-viM0RQszR6xdN069paRKrvnDgkswucuKBzVZUJyL5_DSw4tU6fk_4sm3Wo0si-EVTHv8U9Hw7wQAg/s1600/iscsi-targets.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiflo9qLVROVVKNMI-LHzxy-LgyzjljWDGc0WhtlWK9_0k8PH_wD0GGqMCJlA0S-viM0RQszR6xdN069paRKrvnDgkswucuKBzVZUJyL5_DSw4tU6fk_4sm3Wo0si-EVTHv8U9Hw7wQAg/s320/iscsi-targets.jpg" width="228" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Connected to a Quick Connect Target</td></tr>
</tbody></table><br />
Go ahead and add a second target for Controller B on the <b><i>Discovery </i></b>tab. Then make sure that the MPIO feature is installed and run <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">mpclaim -n -i -a</span>, to grab all of the MPIO enabled drives. You'll likely have to reboot after this. Note that my HP P2000i G3 didn't have a vendor supplied DSM because it's so new, so the Microsoft DSM will work just fine. Repeat on your second host and reboot. Now in the MPIO control panel (Windows 2008 R2 only), you should see MSFT2005iSCSIBusType_0x9 as a claimed device. That's about it for your visits to the MPIO tool.<br />
<br />
Now let's confirm that we've got multiple paths or add them explicitly if you need particular source and target IPs. On the <i style="font-weight: bold;">Target</i> tab, click on <i style="font-weight: bold;">Properties</i>. Here you'll see sessions connected to your SAN. It's the multi-pathing of the sessions that keeps things running.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSHbL-HQF_CwQ5ekh_lUMerYDKNZo_cYZot1J2hvjA_GgrXccRHETKq3xD32YLjbiSNRA66YleSKZ1sQJ5f1cv-JOqePZOklCF21pqSRd8niAt_g6PPdjAhVnB_DBzuKVD_K5kc49uKfc/s1600/iscsi-properties.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSHbL-HQF_CwQ5ekh_lUMerYDKNZo_cYZot1J2hvjA_GgrXccRHETKq3xD32YLjbiSNRA66YleSKZ1sQJ5f1cv-JOqePZOklCF21pqSRd8niAt_g6PPdjAhVnB_DBzuKVD_K5kc49uKfc/s320/iscsi-properties.jpg" width="207" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The list of sessions in Target properties</td></tr>
</tbody></table><br />
Drill down further on a particular session by clicking on <i style="font-weight: bold;">Devices</i>. Here you'll see what LUNs are associated with that connection. If MPIO is correctly enabled, the <i style="font-weight: bold;">MPIO</i> button will be available.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAsHseh3lC26ELn86rHwaG1ZYgzap9piKqQF8CtZd-3r3daCEscjtyJ9Uq1vcloScxGU7kAgVwRKabRctZF0tKKLanjXa6j5yDen_dH2dDDVBSFosSevoxQrlxOuaqlnv8A4PtqWPEkQc/s1600/iscsi-devices.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAsHseh3lC26ELn86rHwaG1ZYgzap9piKqQF8CtZd-3r3daCEscjtyJ9Uq1vcloScxGU7kAgVwRKabRctZF0tKKLanjXa6j5yDen_dH2dDDVBSFosSevoxQrlxOuaqlnv8A4PtqWPEkQc/s320/iscsi-devices.jpg" width="260" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The list of disks associated with a session</td></tr>
</tbody></table><br />
<br />
Click on the <i style="font-weight: bold;">MPIO</i> button after highliting a LUN to look at it's paths a policies.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9nY7tyE5oj7ioNK5_l0_3_v4BbPky_S8t_f-4SP6HYjP8YzA5QActzo8x9D9kOIgl44j1vdBP-2N9VD0Wlq45nqnPRMPKMzZN1MANN0hv8zXyxxOwY-ieI2c1gM5-GeK_HUx3TQF_ThE/s1600/iscsi-device-details.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9nY7tyE5oj7ioNK5_l0_3_v4BbPky_S8t_f-4SP6HYjP8YzA5QActzo8x9D9kOIgl44j1vdBP-2N9VD0Wlq45nqnPRMPKMzZN1MANN0hv8zXyxxOwY-ieI2c1gM5-GeK_HUx3TQF_ThE/s320/iscsi-device-details.jpg" width="275" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">MPIO settings on a device</td></tr>
</tbody></table><br />
You can see that I've got mine already configured with 3 paths at this point. I've already set the policy to <i style="font-weight: bold;">Fail Over Only</i> and two of those paths have been set to <i style="font-weight: bold;">Standby</i>. To confirm each path's settings, highlight it and click on <i style="font-weight: bold;"> Details</i>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQeT6QCFXQh6HHIX1oIYaTBisl_EvPEb0pSEcgQII7sKg5y75boDM28riSntbZzyBLPO6Qoyq25lk7rXUp8LhgrPCE2Mmz5mgLurIL-MkmENYetdZw-mBaFqE6tXlSTwdSddKmmDO1ZcY/s1600/iscsi-mpio-path-details.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQeT6QCFXQh6HHIX1oIYaTBisl_EvPEb0pSEcgQII7sKg5y75boDM28riSntbZzyBLPO6Qoyq25lk7rXUp8LhgrPCE2Mmz5mgLurIL-MkmENYetdZw-mBaFqE6tXlSTwdSddKmmDO1ZcY/s320/iscsi-mpio-path-details.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Details of an MPIO path</td></tr>
</tbody></table><br />
Now you can see what each connection is using for source and target. You see from the example that its explicitly set to use the <i style="font-weight: bold;">Microsoft iSCSI Initiator</i> and it's source is explicitly set to the second iSCSI NIC's IP hitting the third port on Controller A.<br />
<br />
Now that seems like too much clicking, doesn't it? For my deployment, this was fast enough and it re-enforced the learning process visually. You can <a href="http://technet.microsoft.com/en-us/library/ee619743(WS.10).aspx">leverage</a> the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">mpclaim</span><span class="Apple-style-span" style="font-family: inherit;"> </span>command line tool to set these policies via scripts.<br />
<br />
Open <i style="font-weight: bold;">Disk Manager</i>, bring the disks<b style="font-style: italic;"> Online</b> then <i style="font-weight: bold;">Initialize</i> them. On the same node, you can format and assign drive letters. After this, the failover cluster installation will perform the magic to make them clustered resources.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Installing Failover Cluster Feature</span><br />
<br />
Now it's a matter of running some wizards. At this point, the configuration passed validation successfully. Everything is wizard driven, so I recommend Alan Hirt's book, <a href="http://www.amazon.com/Server-Failover-Clustering-Experts-Voice/dp/1430219661/ref=sr_1_1?ie=UTF8&qid=1310568153&sr=8-1">Pro SQL Server 2008 Failover Clustering</a> from Apress. Its what you need to understand the theory behind the process and points out several pitfalls during the architecture process, something I had to learn ad-hoc while running this last-minute project. And if you want to get perfect validation, you'll need to read Nic Cain's (<a href="http://sirsql.net/">blog</a> | <a href="http://twitter.com/#!/sirsql">twitter</a>) blog on the <a href="http://sirsql.net/blog/2011/5/12/sql-clusteringnetwork-binding-order-warnings.html">hidden cluster adapter</a>. If you're looking for more information, check out both Alan and Nic's blogs. Nic's running a series on <a href="http://sirsql.net/blog/tag/cluster">large cluster deployments</a> right now.Andrew Vogelhttp://www.blogger.com/profile/12040307522679113377noreply@blogger.com1