Archive for December, 2010

I had set up one of our raids with a spare drive. A disk in this raid failed last night and the spare was used immediately. Unfortunately, I forgot that this raid had a spare, so I spent a bit of time trying to figure out why the new disk would not rebuild. But eventually, things worked again. Here’s my log:

[root@cps1 ~]# cd tw_cli
[root@cps1 tw_cli]# ./tw_cli 
//cps1> info c0

Unit  UnitType  Status         %RCmpl  %V/I/M  Stripe  Size(GB)  Cache  AVrfy
------------------------------------------------------------------------------
u0    RAID-5    OK             -       -       64K     1862.61   ON     OFF    

Port   Status           Unit   Size        Blocks        Serial
---------------------------------------------------------------
p0     OK               u0     465.76 GB   976773168     WD-WCANU2126397     
p1     OK               u0     465.76 GB   976773168     WD-WCANU2051520     
p2     OK               u0     465.76 GB   976773168     WD-WCANU2030999     
p3     DEVICE-ERROR     u?     465.76 GB   976773168     WD-WCANU2021246     
p4     OK               u0     465.76 GB   976773168     WD-WCANU2114264     
p5     OK               u0     465.76 GB   976773168     WD-WCANU2051215     
p6     NOT-PRESENT      -      -           -             -
p7     NOT-PRESENT      -      -           -             -

The first thing I should have noticed is that the raid was ok. Normally, if there’s a bad drive it shows up as degraded. But, I completely missed that fact and tried to rebuild it.

//cps1> maint remove c0 p3
Removing port /c0/p3 ... Done.


//cps1> info c0

Unit  UnitType  Status         %RCmpl  %V/I/M  Stripe  Size(GB)  Cache  AVrfy
------------------------------------------------------------------------------
u0    RAID-5    OK             -       -       64K     1862.61   ON     OFF    

Port   Status           Unit   Size        Blocks        Serial
---------------------------------------------------------------
p0     OK               u0     465.76 GB   976773168     WD-WCANU2126397     
p1     OK               u0     465.76 GB   976773168     WD-WCANU2051520     
p2     OK               u0     465.76 GB   976773168     WD-WCANU2030999     
p3     NOT-PRESENT      -      -           -             -
p4     OK               u0     465.76 GB   976773168     WD-WCANU2114264     
p5     OK               u0     465.76 GB   976773168     WD-WCANU2051215     
p6     NOT-PRESENT      -      -           -             -
p7     NOT-PRESENT      -      -           -             -

//cps1> rescan
Rescanning controller /c0 for units and drives ...Done.
Found the following unit(s): [/c0/u1].
Found the following drive(s): [none].

//cps1> info c0

Unit  UnitType  Status         %RCmpl  %V/I/M  Stripe  Size(GB)  Cache  AVrfy
------------------------------------------------------------------------------
u0    RAID-5    OK             -       -       64K     1862.61   ON     OFF    
u1    RAID-5    INOPERABLE     -       -       64K     1862.61   OFF    OFF    

Port   Status           Unit   Size        Blocks        Serial
---------------------------------------------------------------
p0     OK               u0     465.76 GB   976773168     WD-WCANU2126397     
p1     OK               u0     465.76 GB   976773168     WD-WCANU2051520     
p2     OK               u0     465.76 GB   976773168     WD-WCANU2030999     
p3     OK               u1     465.76 GB   976773168     WD-WCAS84739115     
p4     OK               u0     465.76 GB   976773168     WD-WCANU2114264     
p5     OK               u0     465.76 GB   976773168     WD-WCANU2051215     
p6     NOT-PRESENT      -      -           -             -
p7     NOT-PRESENT      -      -           -             -

//cps1> /c0/u0 start rebuild disk=3 ignoreecc
The following drive(s) cannot be used [3].
Error: (CLI:144) Invalid drive(s) specified.

I don’t need to list at all the other dumb commands I ran. All I needed to do was this.

//cps1> /c0/u1 del
Deleting /c0/u1 will cause the data on the unit to be permanently lost.
Do you want to continue ? Y|N [N]: Y
Deleting unit c0/u1 ...Done.

//cps1> info c0

Unit  UnitType  Status         %RCmpl  %V/I/M  Stripe  Size(GB)  Cache  AVrfy
------------------------------------------------------------------------------
u0    RAID-5    OK             -       -       64K     1862.61   ON     OFF    

Port   Status           Unit   Size        Blocks        Serial
---------------------------------------------------------------
p0     OK               u0     465.76 GB   976773168     WD-WCANU2126397     
p1     OK               u0     465.76 GB   976773168     WD-WCANU2051520     
p2     OK               u0     465.76 GB   976773168     WD-WCANU2030999     
p3     OK               -      465.76 GB   976773168     WD-WCAS84739115     
p4     OK               u0     465.76 GB   976773168     WD-WCANU2114264     
p5     OK               u0     465.76 GB   976773168     WD-WCANU2051215     
p6     NOT-PRESENT      -      -           -             -
p7     NOT-PRESENT      -      -           -             -

//cps1> /c0 add type=spare disk=3
Creating new unit on controller /c0 ... Done. The new unit is /c0/u1.
WARNING: This Spare unit may replace failed drive of same interface type only.

//cps1> info c0

Unit  UnitType  Status         %RCmpl  %V/I/M  Stripe  Size(GB)  Cache  AVrfy
------------------------------------------------------------------------------
u0    RAID-5    OK             -       -       64K     1862.61   ON     OFF    
u1    SPARE     OK             -       -       -       465.753   -      OFF    

Port   Status           Unit   Size        Blocks        Serial
---------------------------------------------------------------
p0     OK               u0     465.76 GB   976773168     WD-WCANU2126397     
p1     OK               u0     465.76 GB   976773168     WD-WCANU2051520     
p2     OK               u0     465.76 GB   976773168     WD-WCANU2030999     
p3     OK               u1     465.76 GB   976773168     WD-WCAS84739115     
p4     OK               u0     465.76 GB   976773168     WD-WCANU2114264     
p5     OK               u0     465.76 GB   976773168     WD-WCANU2051215     
p6     NOT-PRESENT      -      -           -             -
p7     NOT-PRESENT      -      -           -             -

That’s how it should look.

We have a rails application that allows users to sign up for an event. People not logged in are only allowed to see the names of people who have signed up to attend. People with logins are allowed to see all the contact info for the attendees. I decided it would also be nice to make a downloadable spreadsheet of this information for those people who will need to contact the attendees. Here is how I did it.

First, get the fasterCSV gem. Add this to the Gemfile:

gem 'fastercsv', :require => 'faster_csv'

Basically, all that will happen is that there will be a link on the attendees index page that only logged in users will see (and be allowed to access). This is done in two steps. First the csv file is generated and then it is downloaded.

So, where shall I put the file? Since my development and production workstations have different operating systems, I’m going to have different paths on both of them. I created an yaml file to hold this information.

config/download_csv.yml

development:
    csvfile: /Users/me/Desktop/output.csv
    
production:
    csvfile: /local/code/web/app/myapp/shared/system/output.csv

In my attendee model, I created a method to generate the csv file.

  def self.generate_csv
    csv_settings = YAML.load_file("#{Rails.root.to_s}/config/download_csv.yml")[Rails.env]
    csvfile = csv_settings['csvfile']
    @attendees = Attendee.order('lastname ASC')
    FasterCSV.open("#{csvfile}",'w') do |csv|
      csv << ['Firstname','Lastname','Institution','Address','Email','Number attending']
      @attendees.each do |attendee|
        csv << [attendee.firstname, attendee.lastname, attendee.institution, attendee.address, attendee.email, attendee.fest_count]
      end
    end
  end

In my attendee controller, I created a method called download_csv. In this method, I actually call the generate_csv method above. (Side note: I originally had it set up so that the generate_csv method was called with each new create method. But then decided that fewer people would be downloading the csv file than would be registering. And I changed things so that the csv is only generated when someone wants to download it.)

  def download_csv
    csv_settings = YAML.load_file("#{Rails.root.to_s}/config/download_csv.yml")[Rails.env]
    csvfile = csv_settings['csvfile']
    Attendee.generate_csv
    send_file "#{csvfile}", :type => 'text/csv'
  end

Since I'm using authlogic and declarative_authorization in this app, I also needed to edit my filter_resource_access line in the method to:

filter_resource_access :additional_collection => [[:download_csv, :edit], :edit]

(I.E. People who are allowed to edit attendees are also allowed to download the file.)

Lastly, on my view I have the link:

<% if current_user %>
	<%= link_to 'Download Spreadsheet of Attendees', :controller => :attendees, :action => :download_csv %>
<% end %>

This all worked perfectly on my laptop while I tested it. But when I uploaded it to the server, it kept giving me an empty file, even though the file on the server was not empty. Apparently, this is a common problem. All I needed to do was edit my environments/production.rb file to match this:

  # Specifies the header that your server uses for sending files
  #config.action_dispatch.x_sendfile_header = "X-Sendfile"

  # For nginx:
  config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'

/usr/sbin/cupsenable < printer >