Changeset 288
- Timestamp:
- 10/25/08 10:13:16 (2 months ago)
- Files:
-
- nethorus/app/controllers/device_admin_controller.rb (modified) (2 diffs)
- nethorus/app/controllers/search_controller.rb (modified) (1 diff)
- nethorus/app/helpers/bridges_helper.rb (modified) (2 diffs)
- nethorus/app/models/device.rb (modified) (1 diff)
- nethorus/app/models/ipv4_network.rb (modified) (1 diff)
- nethorus/app/views/common/_all_devices.html.erb (modified) (1 diff)
- nethorus/app/views/common/_all_interfaces.html.erb (modified) (2 diffs)
- nethorus/app/views/common/_device_hardware_inventory.html.erb (modified) (1 diff)
- nethorus/app/views/device_admin/edit.html.erb (modified) (2 diffs)
- nethorus/app/views/device_admin/index.html.erb (modified) (2 diffs)
- nethorus/app/views/ip_network_admin/edit.html.erb (modified) (1 diff)
- nethorus/app/views/ip_network_admin/index.html.erb (modified) (1 diff)
- nethorus/app/views/manage_bridge/show_bridge.html.erb (modified) (1 diff)
- nethorus/app/views/manage_device/device.html.erb (modified) (1 diff)
- nethorus/app/views/search/index.html.erb (modified) (7 diffs)
- nethorus/config/environment.rb (modified) (1 diff)
- nethorus/config/routes.rb (modified) (1 diff)
- nethorus/db/schema.rb (modified) (3 diffs)
- nethorus/public/stylesheets/stylesheet.css (modified) (1 diff)
- nethorus/spec/spec.opts (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
nethorus/app/controllers/device_admin_controller.rb
r287 r288 35 35 @subtitle = "Device Administration" 36 36 37 @all_devices = Device. paginate :page => params[:page]37 @all_devices = Device.all 38 38 39 39 end … … 101 101 if params[:device] 102 102 103 logger.debug "Form submitted, processing any changes" 103 104 # Compare the submitted data to the recorded data and log any changes 104 105 105 106 params[:device].each do |param| 106 107 107 # Only update the record if the attribute's value has actually108 # changed.109 110 108 if @device.send(param[0]) != param[1] 111 109 112 old_value = @device.send(param[0]) 113 114 @device.send("#{param[0]}=", param[1]) 115 110 @device.send("#{param[0]}=", "#{param[1]}") 111 logger.debug "Column #{param[0]} changed from value='#{@device.send(param[0])}' to value='#{param[1]}'" 112 113 else 114 115 logger.debug "Column #{param[0]} unchanged from value='#{@device.send(param[0])}'" 116 116 117 end 117 118 118 119 end 119 120 120 # Find out if anything has actually changed, and if so, report on it 121 122 if @device.changed? 123 124 @device.changes.keys.each do |change| 125 126 logger.debug "Column #{change} changed from #{@device.changes[change][0]} to #{@device.changes[change][1]}" 127 121 122 # Always check if the device is valid, in case we have a now-invalid 123 # record in the database. 124 125 if @device.valid? 126 127 if @device.changed? 128 129 # If the object has changed, save it and respond with a suitable flash message. 130 131 logger.debug "Device id=#{@device.id} changed - saving record" 132 @device.save 133 flash[:info] = "Updated <strong>#{@device.hostname}</strong>" 134 135 else 136 137 # If the object hasn't changed, log it for debugging purposes but 138 # don't show any feedback. 139 140 logger.debug "Device id=#{@device.id} not changed" 141 128 142 end 129 143 130 end 144 145 # Since the object is valid, we can return to the index. 146 147 redirect_to :action => 'index' 148 149 else 131 150 132 133 if @device.valid?134 135 # If the object is valid, save it and respond with a suitable flash message.136 137 logger.debug "Device id=#{@device.id} changed - saving record"138 @device.save139 flash[:info] = "Updated <strong>#{@device.hostname}</strong>"140 141 # Redirect to the index page since the device has been changed142 143 redirect_to :action => 'index'144 145 else146 147 151 # The object isn't valid - log it, and go back to the edit page 148 152 # which will then show the errors 149 153 150 154 logger.debug "Device id=#{@device.id} is invalid" 151 155 152 156 end 153 157 154 else 155 156 logger.debug "Form not submitted, continuing to load data" 157 158 end 159 158 end 159 160 160 end 161 161 nethorus/app/controllers/search_controller.rb
r287 r288 35 35 36 36 @devices = Device.find(:all, :conditions => [ "hostname LIKE :hostname", { :hostname => params[:for] } ]) 37 @l2_interfaces_short = L2Interface.find(:all, :conditions => [ "ifdescr_short LIKE :description", { :description => "%# {params[:for]}%" } ])37 @l2_interfaces_short = L2Interface.find(:all, :conditions => [ "ifdescr_short LIKE :description", { :description => "%#params[:for]}%" } ]) 38 38 @l2_interfaces_long = L2Interface.find(:all, :conditions => [ "ifdescr_long LIKE :description", { :description => "%#{params[:for]}%" } ]) 39 39 @l2_interfaces_address = L2Interface.find(:all, :conditions => [ "address LIKE :address", { :address => "%#{params[:for]}%" } ]) nethorus/app/helpers/bridges_helper.rb
r287 r288 37 37 return nil if bridge_id.blank? 38 38 39 bridge_ data = parse_bridge_id(bridge_id)39 bridge_info = bridge_id.match(/(.{4})(.+)/) 40 40 41 bridge = Bridge.find(:first, :conditions => { :dot1d_base_bridge_address => bridge_ data['mac_address']})41 bridge = Bridge.find(:first, :conditions => { :dot1d_base_bridge_address => bridge_info[2].upcase }) 42 42 43 43 if bridge.nil? … … 53 53 end 54 54 55 56 # Return the bridge priority and the bridge MAC address from a bridge ID.57 58 def parse_bridge_id(bridge_id)59 60 bridge_info = Hash.new61 62 bridge_elements = bridge_id.match(/(.{4})(.+)/)63 64 bridge_info['priority'] = bridge_elements[1].upcase65 bridge_info['mac_address'] = bridge_elements[2].upcase66 67 return bridge_info68 69 end70 71 55 end nethorus/app/models/device.rb
r287 r288 84 84 85 85 class Device < ActiveRecord::Base 86 87 cattr_reader :per_page88 @@per_page = 1589 86 90 87 has_many :l2_interfaces nethorus/app/models/ipv4_network.rb
r287 r288 58 58 59 59 belongs_to :site 60 belongs_to :ipvpn61 60 62 61 validates_presence_of :network_address, :network_mask nethorus/app/views/common/_all_devices.html.erb
r287 r288 1 <% if @devices.count > 0 %> 2 <table class="vert"> 3 <tr> 4 <th>Hostname</th> 5 <th>IP Address</th> 6 <th>Site</th> 7 <th>Description</th> 8 </tr> 9 <%- for device in @devices -%> 10 <tr class="<%= cycle('even_row', 'odd_row', :name => 'row_class') %>"> 11 <td> 12 <% if device.is_manageable? %> 13 <%= render :partial => 'common/device_information_box', :locals => { :device => device } %> 14 <% else %> 15 <%=h device.hostname %> 16 <% end %> 17 </td> 18 <td> 19 <%= device.ipv4_address %> 20 </td> 21 <td> 22 <%=h format_site(device.site) %> 23 </td> 24 <td> 25 <%=h device.description %> 26 </td> 27 </tr> 28 <%- end -%> 29 </table> 30 <% else %> 31 <p>No devices found.</p> 32 <% end %> 1 <table class="vert"> 2 <tr> 3 <th>Hostname</th> 4 <th>IP Address</th> 5 <th>Site</th> 6 <th>Description</th> 7 </tr> 8 <%- for device in @devices -%> 9 <tr class="<%= cycle('even_row', 'odd_row', :name => 'row_class') %>"> 10 <td> 11 <% if device.is_manageable? %> 12 <%= render :partial => 'common/device_information_box', :locals => { :device => device } %> 13 <% else %> 14 <%=h device.hostname %> 15 <% end %> 16 </td> 17 <td> 18 <%= device.ipv4_address %> 19 </td> 20 <td> 21 <%=h format_site(device.site) %> 22 </td> 23 <td> 24 <%=h device.description %> 25 </td> 26 </tr> 27 <%- end -%> 28 </table> nethorus/app/views/common/_all_interfaces.html.erb
r278 r288 1 <% if @device.has_inventory? %> 2 <p> 3 <%= link_to('Update interface inventory', { :controller => 'manage', :action => 'update_interfaces_and_return' }) %> | 4 <%= link_to('Delete interface inventory', { :controller => 'manage', :action => 'delete_interface_inventory_and_return' }) %> | 5 <%= link_to('Draw diagram', { :controller => 'diagram', :action => 'draw_ifstack' }) %> 6 </p> 1 <p> 2 <%= link_to('Update interface inventory', { :controller => 'manage', :action => 'update_interfaces_and_return' } ) %> | 3 <%= link_to_if(!@device.l2_interfaces.blank?, 'Delete interface inventory', { :controller => 'manage', :action => 'delete_interface_inventory_and_return' } ) %> | 4 <%= link_to_if(!@device.l2_interfaces.blank?, 'Draw diagram', { :controller => 'diagram', :action => 'draw_ifstack' } ) %> 5 </p> 7 6 7 <% unless @device.l2_interfaces.blank? %> 8 8 <table class="vert"> 9 9 <tr> … … 53 53 54 54 </table> 55 <% else %>56 <p>This device has no interface inventory recorded. Please <%= link_to('poll the device', { :controller => 'manage', :action => 'update_interfaces_and_return' }) %> to build up a list of interfaces.</p>57 55 <% end %> nethorus/app/views/common/_device_hardware_inventory.html.erb
r287 r288 1 <% if !@device.ent_physical_elements.empty? %>2 1 <p> 3 2 <%= link_to('Update hardware inventory', { :controller => 'manage', :action => 'update_physical_entity_table_and_return' } ) %> | 4 <%= link_to ('Draw diagram', { :controller => 'diagram', :action => 'draw_hardware' } ) %>3 <%= link_to_if(!@device.ent_physical_elements.empty?, 'Draw diagram', { :controller => 'diagram', :action => 'draw_hardware' } ) %> 5 4 </p> 6 5 7 <table class="vert"> 8 <tr> 9 <th>Description</th> 10 <th>Class</th> 11 <th>Revisions</th> 12 <th>Serial No.</th> 13 <th>Manufacturer</th> 14 <th>Model</th> 15 <th>FRU?</th> 16 </tr> 6 <% unless @device.ent_physical_elements.empty? %> 7 <table class="vert"> 8 <tr> 9 <th>Description</th> 10 <th>Class</th> 11 <th>Revisions</th> 12 <th>Serial No.</th> 13 <th>Manufacturer</th> 14 <th>Model</th> 15 <th>FRU?</th> 16 </tr> 17 17 <% @device.ent_physical_elements.each do |element| %> 18 <tr class="<%= cycle('even_row', 'odd_row', :name => 'row_class') %>"> 19 <td><%=h element.phys_description %></td> 20 <td><%=h element.phys_class %></td> 21 <td> 22 <% unless element.phys_hardware_rev.blank? %>H/W: <tt><%=h element.phys_hardware_rev %></tt><br /><% end %> 23 <% unless element.phys_firmware_rev.blank? %>F/W: <tt><%=h element.phys_firmware_rev %></tt><br /><% end %> 24 <% unless element.phys_software_rev.blank? %>S/W: <tt><%=h element.phys_software_rev %></tt><% end %> 25 </td> 26 <td><%=h element.phys_serial_number %></td> 27 <td><%=h element.phys_mfg_name %></td> 28 <td><%=h element.phys_model_name %></td> 29 <td><%=h display_yn(element.is_fru) %></td> 30 </tr> 31 </table> 18 <tr class="<%= cycle('even_row', 'odd_row', :name => 'row_class') %>"> 19 <td><%=h element.phys_description %></td> 20 <td><%=h element.phys_class %></td> 21 <td> 22 <% unless element.phys_hardware_rev.blank? %>H/W: <tt><%=h element.phys_hardware_rev %></tt><br /><% end %> 23 <% unless element.phys_firmware_rev.blank? %>F/W: <tt><%=h element.phys_firmware_rev %></tt><br /><% end %> 24 <% unless element.phys_software_rev.blank? %>S/W: <tt><%=h element.phys_software_rev %></tt><% end %> 25 </td> 26 <td><%=h element.phys_serial_number %></td> 27 <td><%=h element.phys_mfg_name %></td> 28 <td><%=h element.phys_model_name %></td> 29 <td><%=h display_yn(element.is_fru) %></td> 30 </tr> 32 31 <% end %> 33 <% else %> 34 <p>This device has no hardware inventory recorded. Please <%= link_to('poll the device', { :controller => 'manage', :action => 'update_physical_entity_table_and_return'} ) %> to build up a list of hardware components.</p> 32 </table> 35 33 <% end %> nethorus/app/views/device_admin/edit.html.erb
r287 r288 26 26 <legend>Management</legend> 27 27 <label for="ipv4_address" accesskey="a">IP Address</label><%= form.text_field :ipv4_address %><br /> 28 <%= form.radio_button("snmp_version", "1", { :onchange => "Element.show('snmpv1 v2_data'); Element.show('snmpv1_warning'); Element.hide('snmpv3_data');" } ) %>SNMPv1<br />29 <%= form.radio_button("snmp_version", "2", { :onchange => "Element. show('snmpv1v2_data'); Element.hide('snmpv1_warning'); Element.hide('snmpv3_data');" } ) %>SNMPv2<br />30 <%= form.radio_button("snmp_version", "3", { :onchange => "Element.hide('snmpv1 v2_data'); Element.hide('snmpv1_warning'); Element.show('snmpv3_data');" } ) %>SNMPv3<br />28 <%= form.radio_button("snmp_version", "1", { :onchange => "Element.show('snmpv1_data'); Element.hide('snmpv2_data'); Element.hide('snmpv3_data');" } ) %>SNMPv1<br /> 29 <%= form.radio_button("snmp_version", "2", { :onchange => "Element.hide('snmpv1_data'); Element.show('snmpv2_data'); Element.hide('snmpv3_data');" } ) %>SNMPv2<br /> 30 <%= form.radio_button("snmp_version", "3", { :onchange => "Element.hide('snmpv1_data'); Element.hide('snmpv2_data'); Element.show('snmpv3_data');" } ) %>SNMPv3<br /> 31 31 </fieldset> 32 32 33 <fieldset id="snmpv1v2_data"> 34 <legend>SNMPv1/v2 Settings</legend> 33 <fieldset id="snmpv1_data"> 34 <legend>SNMPv1 Settings</legend> 35 <p><strong>Select SNMPv1 only when you are certain this device does not support SNMPv2. Although SNMPv1 is backward compatible, it will not use GETBULK, which may delay gathering data.</strong></p> 35 36 <label for="snmp_community" accesskey="c">Community string</label><%= form.text_field :snmp_community %><br /> 36 <p id="snmpv1_warning"><strong>Select SNMPv1 only when you are certain this device does not support SNMPv2. Although SNMPv1 is backward compatible, it will not use GETBULK, which may delay gathering data.</strong></p> 37 </fieldset> 38 39 <fieldset id="snmpv2_data"> 40 <legend>SNMPv2 Settings</legend> 41 <label for="snmp_community" accesskey="c">Community string</label><%= form.text_field :snmp_community %><br /> 37 42 </fieldset> 38 43 … … 46 51 47 52 <% if @device.snmp_version == 1 %> 48 <%= javascript_tag "Element. show('snmpv1v2_data'); Element.show('snmpv1_warning'); Element.hide('snmpv3_data');" %>53 <%= javascript_tag "Element.hide('snmpv2_data'); Element.hide('snmpv3_data');" %> 49 54 <% elsif @device.snmp_version == 3 %> 50 <%= javascript_tag "Element.hide('snmpv1 v2_data'); Element.show('snmpv3_data');" %>55 <%= javascript_tag "Element.hide('snmpv1_data'); Element.hide('snmpv2_data');" %> 51 56 <% else %> 52 <%= javascript_tag "Element. show('snmpv1v2_data'); Element.hide('snmpv1_warning'); Element.hide('snmpv3_data');" %>57 <%= javascript_tag "Element.hide('snmpv1_data'); Element.hide('snmpv3_data');" %> 53 58 <% end %> 54 59 nethorus/app/views/device_admin/index.html.erb
r287 r288 2 2 3 3 <p><%= link_to "New device", { :controller => 'device_admin', :action => 'new' } %></p> 4 5 <div class="paginator"><%= will_paginate @all_devices %></div>6 4 7 5 <table class="vert"> … … 17 15 <% end %> 18 16 </table> 19 20 <div class="paginator"><%= will_paginate @all_devices %></div>nethorus/app/views/ip_network_admin/edit.html.erb
r287 r288 26 26 <fieldset> 27 27 <legend>Location</legend> 28 <label for="ipvpn_id" accesskey="v">IP VPN</label><%= collection_select(:ip_network, :ipvpn_id, Ipvpn.find(:all), :id, :ipvpn_name , { :prompt => :true }) %><br />28 <label for="ipvpn_id" accesskey="v">IP VPN</label><%= collection_select(:ip_network, :ipvpn_id, Ipvpn.find(:all), :id, :ipvpn_name) %><br /> 29 29 <label for="country" accesskey="c">Country</label><%= form.text_field :country, :size => 2 %> 30 30 </fieldset> nethorus/app/views/ip_network_admin/index.html.erb
r287 r288 17 17 <td><%= ip_network.network_description %></td> 18 18 <td><%= ip_network.country %></td> 19 <td><%= ip_network.ipvpn_id.nil? ? 'Global' : ipvpn_name_and_rd_or_nil(ip_network.ipvpn)%></td>19 <td><%= ip_network.ipvpn_id.nil? ? 'Global' : '#{ip_network.ipvpn_id.ipvpn_name} (#{ip_network.ipvpn_id.ipvpn_rd})' %></td> 20 20 </tr> 21 21 <% end %> nethorus/app/views/manage_bridge/show_bridge.html.erb
r287 r288 32 32 This is a root bridge and has no root port. 33 33 <% else %> 34 <%= link_to @bridge.stp_ports.find(:first, :conditions => { :dot1d_base_port => @bridge.dot1d_stp_root_port }).l2_interface.ifdescr_short, { :controller => 'manage _interface', :action => 'interface', :device_id => @bridge.device_id, :interface_id => @bridge.stp_ports.find(:first, :conditions => { :dot1d_base_port => @bridge.dot1d_stp_root_port }).l2_interface.id } %>34 <%= link_to @bridge.stp_ports.find(:first, :conditions => { :dot1d_base_port => @bridge.dot1d_stp_root_port }).l2_interface.ifdescr_short, { :controller => 'manage', :action => 'interface', :device_id => @bridge.device_id, :interface_id => @bridge.stp_ports.find(:first, :conditions => { :dot1d_base_port => @bridge.dot1d_stp_root_port }).l2_interface.id } %> 35 35 <% end %> 36 36 </td> nethorus/app/views/manage_device/device.html.erb
r278 r288 1 1 <h1>Device Management</h1> 2 2 3 <% tabs = [ [ 'Overview', 'manage_device', 'show_overview'], [ 'Interfaces', 'manage_ interface', 'index' ], [ 'Event Log', 'manage_device', 'show_event_log'], [ 'Hardware', 'manage_device', 'show_hardware' ], [ 'Features', 'manage_device', 'show_features' ], [ 'Functions', 'manage_device', 'show_functions' ] ] %>3 <% tabs = [ [ 'Overview', 'manage_device', 'show_overview'], [ 'Interfaces', 'manage_device', 'show_interfaces' ], [ 'Event Log', 'manage_device', 'show_event_log'], [ 'Hardware', 'manage_device', 'show_hardware' ], [ 'Features', 'manage_device', 'show_features' ], [ 'Functions', 'manage_device', 'show_functions' ] ] %> 4 4 5 5 <ul class="tabbed"> nethorus/app/views/search/index.html.erb
r287 r288 3 3 <p>You may search by hostname, interface name, interface description, Layer 2 or Layer 3 address.</p> 4 4 5 <form method=" post" action="">5 <form method="get"> 6 6 <input name="for" /> 7 7 <input type="submit" value="Search" /> … … 10 10 <% unless params[:for].nil? || @results.nil? %> 11 11 12 <p>You searched for <strong><%=h params[:for] %></strong>:</p> 13 <ul> 14 <li><%=h @devices.size %> matches on hostname</li> 15 <li><%=h @l2_interfaces_short.size + @l2_interfaces_long.size %> matches on interface name and description</li> 16 <li><%=h @l3_interfaces_exact.size %> matches on IPv4 address</li> 17 <li><%=h @l2_interfaces_address.size %> matches on Layer 2 address</li> 18 <li><%=h @element_serial.size %> matches on serial number</li> 19 </ul> 12 <p>You searched for <strong><%=h params[:for] %></strong>: 13 <ul> 14 <li><%=h @devices.size %> matches on hostname</li> 15 <li><%=h @l2_interfaces_short.size + @l2_interfaces_long.size %> matches on interface name and description</li> 16 <li><%=h @l3_interfaces_exact.size %> matches on IPv4 address</li> 17 <li><%=h @l2_interfaces_address.size %> matches on Layer 2 address</li> 18 <li><%=h @element_serial.size %> matches on serial number</li> 19 </ul> 20 </p> 20 21 21 22 <% unless @devices.nil? && @l2_interfaces.nil? && @l3_interfaces_exact.nil? %> … … 27 28 </tr> 28 29 30 29 31 <% for device in @devices %> 30 32 <tr class="<%= cycle('even_row', 'odd_row', :name => 'row_class') %>"> … … 34 36 </tr> 35 37 <% end %> 38 36 39 37 40 <% for l2_interface in @l2_interfaces_long %> … … 43 46 <% end %> 44 47 48 45 49 <% for l2_interface in @l2_interfaces_short %> 46 50 <tr class="<%= cycle('even_row', 'odd_row', :name => 'row_class') %>"> … … 50 54 </tr> 51 55 <% end %> 56 52 57 53 58 <% for l3_interface in @l3_interfaces_exact %> … … 75 80 <% end %> 76 81 82 83 77 84 </table> 78 85 <% end %> nethorus/config/environment.rb
r287 r288 90 90 require 'nethorus_functions' 91 91 92 config.gem "mislav-will_paginate", :version => '~> 2.3.4', :lib => 'will_paginate', :source => 'http://gems.github.com'93 94 92 end nethorus/config/routes.rb
r278 r288 30 30 map.connect 'manage/device/:device_id', :controller => 'manage_device', :action => 'device' 31 31 map.connect 'manage/device/:device_id/overview', :controller => 'manage_device', :action => 'show_overview' 32 map.connect 'manage/device/:device_id/interfaces', :controller => 'manage_ interface', :action => 'index'32 map.connect 'manage/device/:device_id/interfaces', :controller => 'manage_device', :action => 'show_interfaces' 33 33 map.connect 'manage/device/:device_id/interface/:interface_id', :controller => 'manage_interface', :action => 'interface' 34 34 map.connect 'manage/device/:device_id/event_log', :controller => 'manage_device', :action => 'show_event_log' nethorus/db/schema.rb
r287 r288 10 10 # It's strongly recommended to check this file into your version control system. 11 11 12 ActiveRecord::Schema.define(:version => 42) do 13 14 create_table "bridge_forwarding", :force => true do |t| 15 t.integer "vlan_id", :limit => 11 16 t.text "address" 17 t.integer "stp_port", :limit => 11 18 t.text "entry_status" 19 end 12 ActiveRecord::Schema.define(:version => 39) do 20 13 21 14 create_table "bridges", :force => true do |t| … … 131 124 132 125 create_table "ipvpns", :force => true do |t| 133 t. text "ipvpn_rd"126 t.integer "ipvpn_rd", :limit => 11 134 127 t.text "ipvpn_name" 135 128 t.datetime "created_at" 136 129 t.datetime "updated_at" 137 t.integer "ipvpn_rd_integer", :limit => 1 1130 t.integer "ipvpn_rd_integer", :limit => 16 138 131 end 139 132 … … 153 146 t.text "connector_present" 154 147 t.integer "parent_id", :limit => 11 155 end156 157 create_table "l2_vlans", :force => true do |t|158 t.integer "vlan_id", :limit => 11159 t.integer "device_id", :limit => 11160 t.text "vlan_state"161 t.text "vlan_name"162 t.integer "vlan_mtu", :limit => 11163 t.integer "vlan_ifindex", :limit => 11164 148 end 165 149 nethorus/public/stylesheets/stylesheet.css
r287 r288 354 354 margin: 5px 0 0 10px; 355 355 } 356 357 .paginator {358 padding: 0.5em 0em 0.5em 0em;359 text-align: center;360 font-weight: bold;361 }nethorus/spec/spec.opts
r287 r288 1 1 --colour 2 --format progress2 --format specdoc 3 3 --loadby mtime 4 4 --reverse
