Posts
24
Comments
47
Trackbacks
0
Tuesday, May 12, 2009
Azure Local Storage Endpoints

I’m constantly having to search for the local development storage endpoint Uris when I create a new Azure storage project from scratch, not to mention the account name and shared key, so I’m posting them here for my own reference.  Hopefully others will also find it useful.

   1: <ConfigurationSettings>
   2:         <Setting name="AccountName" 
   3:             value="devstoreaccount1"/>
   4:         <Setting name="AccountSharedKey" 
   5:             value="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="/>
   6:         <Setting name="BlobStorageEndpoint" 
   7:             value="http://127.0.0.1:10000/"/>
   8:         <Setting name="QueueStorageEndpoint" 
   9:             value="http://127.0.0.1:100001/"/>
  10:         <Setting name="TableStorageEndpoint" 
  11:             value="http://127.0.0.1:10002/"/>
  12: </ConfigurationSettings>
posted @ Tuesday, May 12, 2009 9:40 AM | Feedback (0)
Tuesday, March 10, 2009
Team Build: Part 1

I’ve had the fortune of being involved in some pretty complex and elegant Team Build configurations.  I’ve started to blog about individual points several times, but ended up figuring that I should instead write a series of posts about common goals and general Team Build approaches.  I can’t take credit for all this content.  Some I’ve developed over time, some I’ve learned from others on the web, and yet other stuff I’ve learned from co-workers.  That said, here we go with Part 1.

General Approach

Every person has their personal preference, and this is typically taken to the nth degree with programmers.  What follows are my personal preferences.  Yours may vary.

First, I like to separate any custom team build stuff from the default TFSBuild.proj file.  I’ll update properties already existing in that file, or available via the Microsoft.TeamFoundation.Build.targets file, directly in TFSBuild.proj.  But all my custom stuff exists in a separate file, or files.  For example, I’ll aggregate all my custom tasks into a CustomTasks.targets file, and import that at the bottom of TFSBuild.proj:

   1: <ItemGroup>
   2:     <!--  ADDITIONAL REFERENCE PATH
   3:  The list of additional reference paths to use while resolving references. For example:
   4:  
   5:      <AdditionalReferencePath Include="C:\MyFolder\" />
   6:      <AdditionalReferencePath Include="C:\MyFolder2\" />
   7: -->
   8: </ItemGroup>
   9:  
  10: <!-- Add our custom target overrides -->
  11: <Import Project="Environment.proj"/>
  12: <Import Project="CustomTasks.targets" />
  13:  
  14: </Project>

Here, we’ve imported the CustomTasks.targets file that contains all of our customizations, and we’ve also imported an Environment.proj file that contains metadata about the environment to which we typically deploy this build configuration.  In this way, we can create additional build for additional environments, and only need to change the Environment.proj file.

Within the CustomTasks.targets file, I declare any custom MSBuild tasks I need, as well as define my overrides and custom targets.  (See http://msdn.microsoft.com/en-us/library/aa337604.aspx for a list of overridable team build targets).  An example skeleton is as follows:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
   3:  
   4: <UsingTask TaskName="XmlMassUpdate" AssemblyFile="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.dll" />
   5: <UsingTask TaskName="Attrib" AssemblyFile="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.dll" />
   6: <UsingTask TaskName="XmlFile.GetValue" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft.Sdc\Microsoft.Sdc.Tasks.dll" />
   7: <UsingTask TaskName="XmlFile.SetValue" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft.Sdc\Microsoft.Sdc.Tasks.dll" />
   8:  
   9: <Target Name="BuildNumberOverrideTarget">
  10:   <CallTarget Targets="CalculateCustomBuildNumber" />
  11: </Target>
  12:  
  13: <Target Name="GenerateDocumentation">
  14:   <CallTarget Targets="CreateCustomDocumentation" />
  15: </Target>
  16:  
  17: <!-- Custom targets removed for brevity. -->
  18:  
  19: </Project>

For custom build tasks, I typically rely heavily on the Sdc and MSBuild Community tasks (http://www.codeplex.com/sdctasks and http://msbuildtasks.tigris.org/).  There’s not alot they can’t do, but if you find something, you can always develop a custom task yourself.

Adjusting Application Settings During a Deploy

One of the custom tasks I rely *heavily* on is the XmlMassUpdate task.  There are many scenarios where you want to tweak configuration settings when you deploy to an environment, and this task is perfect for it.  In a nutshell, you provide a set of configuration data (in this case, Xml), and the task dynamically updates/removes/adds the config content to match your desired settings.  I typically embed the configuration directly in the custom build file, but you could also declares this externally.  MSBuild supports including “random” Xml in the build file via the <ProjectExtensions/> node (anything within this content is ignored by MSBuild).  So, using this and the XmlMassUpdate tasks, we can do the following (example only):

   1: <ProjectExtensions xmlns:xmu="urn:msbuildcommunitytasks-xmlmassupdate">
   2:   <MyAppConfig xmlns="">
   3:     <configuration>
   4:       <appSettings>
   5:         <add xmu:key="key" key="MyDeployedValue" value="One" />
   6:         <add xmu:key="key" key="MySecondDeployedValue" value="Two" />
   7:       </appSettings>
   8:     </configuration>
   9:   </MyAppConfig>
  10: </ProjectExtensions>
  11:  
  12:  
  13: <Target Name="ConfigOverride">
  14: <Attrib Files="$(SolutionRoot)\MyApp.config" ReadOnly="false" />
   1: <XmlMassUpdate ContentFile="$(SolutionRoot)\MyApp.config"
   2:                        ContentRoot="/configuration"
   3:                        SubstitutionsFile="$(BuildDirectory)\BuildType\CustomTasks.targets"
   4:                        SubstitutionsRoot="/msb:Project/msb:ProjectExtensions/MyAppConfig/configuration"
   5:                        NamespaceDefinitions="msb=http://schemas.microsoft.com/developer/msbuild/2003" />
  21: <Target>

The attrib task is there because, by default, files grabbed from source control to be used during a build are read-only.  You’ll want to check the docs on how to use XmlMassUpdate, but the short of this says (assume you call the ConfigOverride target somewhere else in your build process):

On the file MyApp.config in my solution path, replace/modify content starting at the /configuration node, using the content included in the CustomTasks.targets file (this same file) starting with the node located at Project/ProjectExtensions/MyAppConfig/configuration.  In this case, it will update the appSettings/add node with an “key” attribute of ‘MyDeployedValue’ to have a “value” attribute of ‘One’, and similarly for the second entry.

I use this for all manner of things, from updating configs, to updating project files (they’re just Xml after all), to updating Sandcastle help file docs, to adjusting ClickOnce settings on a deploy.  We’ll see more about these in the next several posts.

posted @ Tuesday, March 10, 2009 4:32 PM | Feedback (0)
Tuesday, February 10, 2009
I Can't Find the Live Framework SDK and Tools Download!

Applied for the Windows Azure Live services CTP and received your token, but can't find the download?  You're not alone.

Following the download links for me, even after I received and entered my token, took me in a circular loop.  That is, it took me into a loop until I actually started to create a Live-enabled cloud app.

Dariusz Parys blogs about this issue, and how to actually get the download links to work in this blog post.  Thanks, Dariusz!

posted @ Tuesday, February 10, 2009 9:24 AM | Feedback (0)
Thursday, January 15, 2009
Denver January 2009 Windows Azure User Group Meeting

The Denver January 2009 Windows Azure User Group Meeting was held on January 13th.  We discussed cloud storage in Windows Azure, including the blob, table, and queue tools.  Thanks for everyone who attended and for making the meeting a success!  For a recap of the presentation and demo material, go see the post at the official site:  www.azureusergroup.com.  While you're there, sign up to be informed of your next local user group meeting!

posted @ Thursday, January 15, 2009 3:07 AM | Feedback (0)
Friday, January 16, 2009
Windows Azure January 2009 CTP Released

For anyone who still hasn't seen the announcement, the January 2009 CTP for the Windows Azure tools were released.  See the official blog post here.  Go grab the latest bits and start leaning Azure today.

posted @ Friday, January 16, 2009 2:57 AM | Feedback (0)
Tuesday, January 27, 2009
VCBuild, BK1513, and Team Build

I ran across this issue while automating a particularly complex build.  It turns out the C++ project was being built twice during the automated build.  Ensuring the build only ran the C++ project once fixed up my problem.

Hope this helps anyone struggling with this combination of issues.

posted @ Tuesday, January 27, 2009 2:55 AM | Feedback (0)
Saturday, November 29, 2008
Network Media uPnP

I wrote last time about setting up my Linksys router with DD-WRT and sharing my media on the local network with a USB storage drive.  I had intended to also install a Universal Plug and Play (uPnP) media server on the router, but never could find a good media server that ran on embedded Linux.  I tried uShare, and it worked OK, but only with my pictures.  I also attempted to run TwonkyMedia, but never could get it installed on the router.  A friendly request in the Twonky Vision forums went unanswered, and others in the same forum lamented about the lack of support for a pay product.  Oh well.  I moved on.

So I turned to TVersity, a free uPNP media server for Windows.  The unfortunate side effect is that I'll have to leave my laptop running to serve up content, but hey, my opinion was that if it worked, it is a small price to pay.  I installed it, and it simply ... worked.  The management interface is clean and fairly easy to use.  While the initial media cataloging process took several hours (quite a bit longer than I had expected), once it was done, refreshes didn't take much time at all.  I'm now sharing local media, network media, and Internet media (podcasts, Flickr images, Internet video, etc.), all to any uPnP devices on my network (of which the Xbox 360 is the intended target).

I'm also waiting for MediaPortal version 2, which will include uPnP support in addition to the already-existing HTPC-type features, like tuner recording and program playback.  MediaPortal is also open source and written in .net, both features that I find extremely attractive.

posted @ Saturday, November 29, 2008 11:38 AM | Feedback (0)
Friday, November 21, 2008
Linksys WRT350N, DD-WRT, USB Storage, Samba, and uPNP

I'm writing this post for two reasons:  1) To preserve the details of the steps I took to get this all working, and also 2) To help others who might be looking to do the same thing.  While I'm not a complete Linux noob, some simple things still are not clear to me, and in other cases, there is conflicting information available on getting DD-WRT running with USB and Samba, so I'm clarifying here what worked for me.

Background

I've had a Windows server running over the years for various reasons.  As of late, it's just been a glorified file server.  With the proliferation of network storage devices, I figured I could do without running an entire machine all the time.  NAS devices are still fairly pricey, though, and I'm aware that some routers now have USB support for external drives.  I've been running DD-WRT on my Linksys router for several years now, and I had heard that was some basic support for USB devices in it, so I decided to give it a whirl.

After looking at a combination of factors, including price, USB support, and DD-WRT support, I settled on the Linksys WRT-350N.  My goals for this effort were to:

  • Run my router on DD-WRT
  • Attach a USB drive for storage
  • Use Samba to share the storage with other devices on the network
  • If possible, spin up a uPNP server for consuming media from an Xbox 360.

Process

Flash your router with DD-WRT

First of all, I installed DD-WRT on the Linksys 350N.  I won't go into specifics here, as this is well-documented on the DD-WRT website.  The only advice I can give is to always flash your router with the mini build and then upgrade to a standard or mega build.

Advice: The mega build will fit on the 350N, but I decided to go with the standard because of the memory footprint of the mega.  Having the standard build gives more room for JFFS, which is needed for the USB storage.  I didn't need OpenVPN or Milkfish, so standard worked fine for me.  You can see the feature differences here.

After flashing your router, you'll probably want to ensure telnet access is enabled.  To make editing files easier, I also enable SSH and use SCP to transfer/edit files on the router.

Configure DD-WRT for USB

For the most part, I followed the instructions from the website.  First off, you'll need to enable jffs (details in USB instructions).  Next, you want to update the ipkg that comes in DD-WRT so that you can grab some packages needed for USB support.  (Note: I needed the OHCI driver for my USB setup).

   1: ipkg update
   2:  
   3: ipkg -force-depends install kmod-usb-core kmod-usb2 kmod-usb-storage kmod-usb-ohci
   4:  

I used the ext3 filesystem on my attached storage, so I also needed ext3 support:

   1: ipkg install kmod-ext3

If you need xfs, ext2, or fat support, you'll need to install those modules as well.  See the USB install link above.  Package names are: kmod-vfat, kmod-ext2, and kmod-xfs.

Get USB drive ready

This might be a tad out of order, but you'll also need a USB drive to be used with the router.  I pulled one of the 60GB SATA drives out of my old server and am using a SATA to USB 2.0 drive enclosure.  Because I knew in advance I'd be using ext3 filesystem on the router, I went ahead and partitioned/formatted my drive using an Ubuntu LiveCD.  You can download just about any Linux distro -- I was familiar with Ubuntu and I knew the LiveCD comes with a partition editor, so I just used that.  Again, I won't go into using a partition editor within your Linux distribution, as that is documented well elsewhere.

What I will say is that it's useful to have three partitions on your drive:  1) Space for Optware packages (more on this later), 2) general "data" space (what I am using to share files over the network), and 3) some swap space (format as linux-swap).  I split them up as:  1) Optware (1GB), 2) Data (58GB), and 3) Swap (1GB).

I plugged in my USB drive to the router.  At this point, the router isn't running any drivers that recognize the drive.  We'll remedy that next.

Loading USB Drivers

Next, we need to load the drivers we just installed to be able to see the attached USB drive.  You can do this manually, but you'll want it to happen automatically when the router boots.  Keep in mind that the embedded Linux firmwares are largely read-only.  Enabling jffs allows to use a small portion of remaining free flash ROM as read/write area.

DD-WRT scans a few, well-known paths for startup scripts when it boots.  We'll use the one in /jffs/etc/config.  Create this folder is it doesn't already exist, either with a telnet connection or WinSCP.

My startup file is named init.startup and is shown as follows.  Note that the looping functionality is because, while testing, my USB drive wasn't always recognized immediately and appropriately, and so we loop to attempt to re-init the drivers.  Since I have disabled the EHCI driver (which is responsible for USB 2.0 compatibility, if I'm not mistaken), this is much more reliable.  More work on this driver is needed, I think.  USB 1.1 speeds are OK for my scenario.  Also note that apparently under certain circumstances, your startup script can be executed again, well after the router has booted.  So that we don't mess anything up then, we do an initial check to see if we're just booting, and only run then.  Note also that the entire script is wrapped in a pipe out to /tmp/init.log so we can see any errors upon startup.  /tmp is another read/write path within DD-WRT.

   1: #/bin/sh
   2: (
   3:  
   4: echo "Running init.startup."
   5:  
   6: # Only run once.  Check time and exit if running after startup.
   7: # Get uptime and round it to nearest integer
   8: uptime=`cat /proc/uptime | awk -F\. '{print $1}'`
   9:  
  10: if [ $uptime -gt 120 ]
  11: then
  12: echo "Did not run init.startup because uptime is $uptime."
  13: exit
  14: fi
  15:  
  16: # Init USB support and map drives
  17: # Loop until drive is detected
  18: while [ 1 -eq 1 ]
  19: do
  20: insmod /jffs/lib/modules/2.4.30/usbcore.o
  21: #insmod /jffs/lib/modules/2.4.30/ehci-hcd.o
  22: insmod /jffs/lib/modules/2.4.30/usb-ohci.o
  23: insmod /jffs/lib/modules/2.4.30/scsi_mod.o
  24: insmod /jffs/lib/modules/2.4.30/usb-storage.o
  25: insmod /jffs/lib/modules/2.4.30/sd_mod.o
  26:  
  27: sleep 5
  28:  
  29: if dmesg | tail -n10 | grep 'Attached scsi disk' 2>/dev/null 1>/dev/null
  30: then
  31:     break
  32: else
  33: rmmod sd_mod
  34: rmmod usb-storage
  35: rmmod scsi_mod
  36: rmmod usb-ohci
  37: #rmmod ehci-hcd
  38: rmmod usbcore
  39:  
  40: fi
  41: done
  42:  
  43: # Add other drivers needed for external drives
  44: insmod /jffs/lib/modules/2.4.30/jbd.o
  45: insmod /jffs/lib/modules/2.4.30/ext3.o
  46:  
  47: echo "DONE"
  48:  
  49: ) > /tmp/init.log 2>&1

You'll need this script to be executable by the system.  Make sure you 'chmod 700 init.startup' or use WinSCP to modify the execute bit on the file.  Otherwise, it won't run at startup.

Now it's the time to test out our drivers.  You can manually type in the insmod command to load the pertinent drivers, or you can reboot to test your script.  Either way, after you've got the drivers loaded, you'll want to see if Linux can 'see' your drive.  Issue a 'dmesg' command.  You should see that a SCSI device was detected, and that it was attached.

   1: hub.c: new USB device 00:02.0-1, assigned address 2
   2: scsi0 : SCSI emulation for USB Mass Storage devices
   3:   Vendor: Maxtor 6  Model: Y060M0            Rev:
   4:   Type:   Direct-Access                      ANSI SCSI revision: 02
   5: Attached scsi disk sda at scsi0, channel 0, id 0, lun 0
   6: SCSI device sda: 120103200 512-byte hdwr sectors (61493 MB)
   7: Partition check:
   8:  /dev/scsi/host0/bus0/target0/lun0: p1 p2 p3

You're good to go at this point if you see that.  With the EHCI driver, I often saw "USB device not accepting new address=x (error=-71)".  That's why the loop exists, and why it's no longer being loaded.

Now you can look at the disk and the partitions in a couple different ways:

   1: root@gateway:~# ls /dev/discs/disc0
   2: disc   part1  part2  part3
   3: root@gateway:~# ls -l /dev/discs/disc0
   4: lr-xr-xr-x    1 root     root           31 Jan  1  1970 /dev/discs/disc0 -> ../scsi/host0/bus0/target0/lun0

You can see that there are the three partitions, as well as the /dev/discs/disc0 being an alias for a longer name /dev/scsi/host0/bus0/target0/lun0.  Now that we know where the drive is, let's use it by mounting it locally.  We want to start with the /opt folder, as by using Optware packages, we can install packages to our heart's content on the first partition (assuming we have enough storage space and device memory to run them, of course).

   1: mount -t ext3 /dev/discs/disc0/part1 /opt
   2: mount --bind /opt /jffs/opt

This bit of magic mounts our first partition to /opt and rebinds /opt to /jffs/opt, effectively making it writable.  Let's mount the data portion to a suitable location.  It could be put in any writeable location.  I like the concept of putting it on /opt and using that as a mount point.

   1: mkdir /opt/nas
   2: mount -t ext3 /dev/discs/disc0/part2 /opt/nas

Note:  You only have to make the /opt/nas dir once, whereas we'll need to mount the disk every time.  That will be covered later when we extend our startup script.

To mount the swap partition, we'll need some more utilities, namely swapon.  I tried to use this from a package called swap-utils, but never could get it to work.  Instead, I just download busybox and use it from there. If anyone has any suggestions, leave me a comment. 

   1: ipkg install busybox
   2: /opt/bin/busybox/swapon /dev/discs/disc0/part3

Note: You'll only need to install the package once, of course.  The call to swapon should be on bootup.  We'll see that in the extended startup script later.

At this point, we should have three mounted drives.  Check them via the following two commands.  'mount' should show you the mount points, and free should show that there is available disk space.

   1: mount
   2: free

Installing Optware

Check the DD-WRT site for installing Optware.  The documentation there is good.  Some notes:  I used the 3iii.dk link.  Also make sure you 'chmod' the downloaded /tmp/optware-install.sh file.  Run the file and it should install the Optware installer.

Installing Samba

You'd think installing Samba would be fairly straightforward.  Well, technically, OK, it is.  Getting it to run as you expect is not.  Most of the documentation assumes you know things you may not, and there are a TON of options to set here.  Check the Optware page again for installing Samba.  The instructions there for installing are accurate.  However, to get things up and running, make sure you take note of the following:

Change the default xinetd allow ports in /opt/etc/xinet.conf.  This is usually CIDR format.  If you run a typical 192.168.1.1-255 subnet, you should probably set this to:

   1: defaults
   2: {
   3:         only_from      = 192.168.1.0/24
   4:         instances      = 60
   5:         log_type       = SYSLOG authpriv info
   6:         log_on_success = HOST PID
   7:         log_on_failure = HOST
   8:         cps            = 25 30
   9: }

For me, the Samba configuration I wanted was an anonymous share for music and pictures.  You can use the SWAT web configuration tool, but be careful.  You can quickly make a set of incompatible settings.  For me, I ended up with this:

   1: # Global parameters
   2: [global]
   3:     workgroup = STORAGE
   4:     netbios name = FILE01
   5:     server string = Samba File Storage
   6:     interfaces = 192.168.1.1
   7:     encrypt passwords = Yes
   8:     map to guest = Bad User
   9:     null passwords = Yes
  10:     lanman auth = No
  11:     log file = /opt/var/log/samba/log.%m
  12:     max log size = 25
  13:     name resolve order = wins hosts lmhosts bcast
  14:     socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
  15:     load printers = No
  16:     wins support = Yes
  17:     hosts allow = 192.168.1.0/255.255.255.0
  18:     status = No
  19:  
  20: [media]
  21:     comment = Media share
  22:     path = /opt/nas/Media
  23:     force user = root
  24:     read only = No
  25:     inherit permissions = Yes
  26:     inherit acls = Yes
  27:     guest only = Yes
  28:     guest ok = Yes
  29:     status = Yes

Key features to note are: I map bad user names to the guest user (by default, Windows machines attempt to pass over the current Windows user credentials).  For the media share, I set to guest only, guest access is ok, and I force the user (impersonation, basically) to root.  This is to create consistency on the owner of the files as they are modified, created, etc.  Please appreciate that this is basically giving 'superuser' access to all the files in this folder/subfolders, so make sure this is something you want to do if you copy my configuration.

The other key missing task from the instructions on the DD-WRT website is that, under the hood, the 'guest' user account is an account called 'nobody'.  You'll need to create the user account both in the Linux system (you'll have to do this on boot every time -- again in a script), but you also need to create the account for the Samba system.  Do this with the smbpasswd command:

   1: /opt/bin/smbpasswd -a nobody

I used a blank password when requested.

Start samba using the instructions at the DD-WRT site and you should be good to go.  If you map a drive from Windows, or use Start | Run, or use net use, and a user is requested, you should be able to put in anything, as this will be mapped to the guest account.

Sharing Media with uPNP

The ultimate for me is to be able to share my media with uPNP devices on the network (such as my Xbox).  I started with uShare, but this only worked with my pictures.  It didn't work with my music.  I guess it's a basic media server, and can't transform on the fly.  Apparently, the Xbox only supports some specific encoding formats, and uShare won't convert mine on the fly to something compatible.

I'm going to look at TwonkyMedia next, but it's a licensed (costs) product, and there is very little documentation on getting it working under DD-WRT.  If/when I do, I'll post back here.

Final Thoughts and Startup Scripts

There are some other aesthetic/functional elements to automating all of this at startup.  I didn't cover everything, but I will provide my startup scripts here for others.  Any questions, ask in the comments.

/jffs/etc/config/init.startup:

   1: #/bin/sh
   2: (
   3:  
   4: echo "Running init.startup."
   5:  
   6: # Only run once.  Check time and exit if running after startup.
   7: # Get uptime and round it to nearest integer
   8: uptime=`cat /proc/uptime | awk -F\. '{print $1}'`
   9:  
  10: if [ $uptime -gt 120 ]
  11: then
  12: echo "Did not run init.startup because uptime is $uptime."
  13: exit
  14: fi
  15:  
  16: # Init USB support and map drives
  17: # Loop until drive is detected
  18: while [ 1 -eq 1 ]
  19: do
  20: insmod /jffs/lib/modules/2.4.30/usbcore.o
  21: #insmod /jffs/lib/modules/2.4.30/ehci-hcd.o
  22: insmod /jffs/lib/modules/2.4.30/usb-ohci.o
  23: insmod /jffs/lib/modules/2.4.30/scsi_mod.o
  24: insmod /jffs/lib/modules/2.4.30/usb-storage.o
  25: insmod /jffs/lib/modules/2.4.30/sd_mod.o
  26:  
  27: sleep 5
  28:  
  29: if dmesg | tail -n10 | grep 'Attached scsi disk' 2>/dev/null 1>/dev/null
  30: then
  31:     break
  32: else
  33: rmmod sd_mod
  34: rmmod usb-storage
  35: rmmod scsi_mod
  36: rmmod usb-ohci
  37: #rmmod ehci-hcd
  38: rmmod usbcore
  39:  
  40: fi
  41: done
  42:  
  43: # Add other drivers needed for external drives
  44: insmod /jffs/lib/modules/2.4.30/jbd.o
  45: insmod /jffs/lib/modules/2.4.30/ext3.o
  46:  
  47: echo "Mounting drives and re-binding locations."
  48:  
  49: # Mount /opt
  50: mount -t ext3 /dev/discs/disc0/part1 /opt
  51: mount --bind /opt /jffs/opt 
  52:  
  53: # Mount swap
  54: /opt/bin/busybox swapon /dev/discs/disc0/part3
  55:  
  56: # Mount NAS
  57: mount -t ext3 /dev/discs/disc0/part2 /opt/nas
  58:  
  59: # Call Optware startup
  60: echo "Calling Optware script."
  61:  
  62: /jffs/etc/config/optware.start
  63:  
  64: echo "DONE"
  65:  
  66: ) > /tmp/init.log 2>&1

/jffs/etc/config/optware.start (I don't use the .startup extension because it would be run automatically by the OS, and I want to control when it's run):

   1: #/bin/sh
   2: (
   3:  
   4: # Optware tasks
   5: echo "Executing Optware tasks."
   6:  
   7: unset LD_LIBRARY_PATH
   8: unset LD_PRELOAD
   9:  
  10: if [ -e /opt/etc/profile ]; then
  11:        cp /opt/etc/profile /tmp               
  12:        mount -o bind /tmp/profile /etc/profile
  13: fi
  14:  
  15: if [ -d /opt/etc/init.d ]; then
  16:     for f in /opt/etc/init.d/S* ; do
  17:     [ -x $f ] && $f start
  18:     done
  19: fi 
  20:  
  21: ) > /tmp/optware.log 2>&1

/opt/etc/profile:

   1: export PATH=/opt/bin:/opt/sbin:/bin:/sbin:/usr/bin:/usr/sbin
   2: export PS1='\u@\h:\w\$ ' 
   3:  
   4: [ -x /opt/bin/less ] ||  alias less=more
   5: [ -x /otp/bin/vim ] ||  alias vim=vi
   6:  
   7: arp() { cat /proc/net/arp; }
   8: ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
   9:  
  10: reboot()
  11: {
  12: killall nmbd
  13: killall smbd
  14: sleep 1
  15: umount /opt
  16: /sbin/reboot 
  17: }

Acknowledgements

Most all of this knowledge was taken from others who already pioneered their way to getting this to work.  My scripts are compilations of scripts from others ... too many to list.  Lots of this information was in the DD-WRT forums or wiki site.  If your work is largely represented here without acknowledgement, and you would like some, let me know in the comments.  And my thanks & apologies in advance.  :)

posted @ Friday, November 21, 2008 8:32 AM | Feedback (14)
Friday, July 18, 2008
Excellent Article on WCF Channel Development and WCF Framework Extensibility

This is very old news, but it's worth repeating.

The highly respected WCF Sensei -- Nicholas Allen -- has an excellent article on the binding stack in WCF, how WCF is extensible, and specifically, where and how you can customize these points.  I've been looking for this kind of treatment of WCF customization for some time.  I really could have used it when I was struggling with building a custom interop solution for a client, but alas.  Regardless, I'm noting it here for posterity and for anyone else out there trying to grasp these concepts.

Anyway, the article starts out at http://blogs.msdn.com/drnick/archive/2007/02/19/channel-development-tour-part-1.aspx.  It is a lengthy series of bite-sized articles on various aspects of WCF.  Good stuff!  Thanks, Nicholas!

posted @ Friday, July 18, 2008 8:13 AM | Feedback (0)
Monday, June 30, 2008
Equivalent svcutil.exe command for VS2008 Add Service Reference

As a followup to my post about serialization funkiness between WCF and Peoplesoft, I wanted to post what svcutil.exe command I used to mimic the built-in behavior of the "Add Service Reference" behavior in Visual Studio 2008.

Contrary to Visual Studio 2005, the Add service reference command in Visual Studio 2008 does not use svcutil.exe, but rather it's own built-in functionality.

Using a comparison reference between the two and my own analysis of the results, I came up with the following command to mimic what the command does in VS 2008 (keep in mind a few of these options, such as the /ct and the /l switches, were specific to my situation):

svcutil *.wsdl *.xsd /l:C# /out:Reference.cs /noconfig /s /ct:System.Collections.Generic.List`1 /ser:Auto /tcv:Version30 /n:*,<NameOfYourNamespaceHere> /edb

I ran this in the folder where the schema files (WSDL, XSD) were located from a VS2008 command line.

If anyone figures out that this is missing any parameters, or any parameters are incorrect, I'd love to hear from you.

posted @ Monday, June 30, 2008 9:22 AM | Feedback (0)
News
Comment and opinions are my own and do not reflect on my company in any way.