| Filename | /appl/netdisco/netdisco_github_official/lib/App/Netdisco/DB/Result/Device.pm |
| Statements | Executed 774 statements in 1.87ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 774 | 10 | 3 | 1.78ms | 5.34ms | App::Netdisco::DB::Result::Device::__ANON__[:13] |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::BEGIN |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::first_seen_stamp |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::has_layer |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::is_pseudo |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::last_arpnip_stamp |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::last_discover_stamp |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::last_macsuck_stamp |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::oui |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::port_count |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::renumber |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::since_last_arpnip |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::since_last_discover |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::since_last_macsuck |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::uptime_age |
| 0 | 0 | 0 | 0s | 0s | App::Netdisco::DB::Result::Device::vlan |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | use utf8; | ||||
| 2 | package App::Netdisco::DB::Result::Device; | ||||
| 3 | |||||
| 4 | # Created by DBIx::Class::Schema::Loader | ||||
| 5 | # DO NOT MODIFY THE FIRST PART OF THIS FILE | ||||
| 6 | |||||
| 7 | use strict; | ||||
| 8 | use warnings; | ||||
| 9 | |||||
| 10 | use NetAddr::IP::Lite ':lower'; | ||||
| 11 | use App::Netdisco::Util::DNS 'hostname_from_ip'; | ||||
| 12 | |||||
| 13 | 774 | 1.87ms | 774 | 3.57ms | # spent 5.34ms (1.78+3.57) within App::Netdisco::DB::Result::Device::__ANON__[/appl/netdisco/netdisco_github_official/lib/App/Netdisco/DB/Result/Device.pm:13] which was called 774 times, avg 7µs/call:
# 171 times (466µs+1.06ms) by App::Netdisco::Util::Device::get_device at line 49 of App/Netdisco/Util/Device.pm, avg 9µs/call
# 171 times (377µs+689µs) by App::Netdisco::Util::Permission::check_acl_only at line 67 of App/Netdisco/Util/Permission.pm, avg 6µs/call
# 171 times (259µs+398µs) by App::Netdisco::Util::Permission::check_acl_no at line 45 of App/Netdisco/Util/Permission.pm, avg 4µs/call
# 57 times (189µs+474µs) by App::Netdisco::JobQueue::PostgreSQL::_get_denied_actions at line 35 of App/Netdisco/JobQueue/PostgreSQL.pm, avg 12µs/call
# 57 times (94µs+150µs) by App::Netdisco::Util::Device::is_macsuckable at line 280 of App/Netdisco/Util/Device.pm, avg 4µs/call
# 57 times (93µs+140µs) by App::Netdisco::Util::Device::is_arpnipable at line 231 of App/Netdisco/Util/Device.pm, avg 4µs/call
# 57 times (86µs+127µs) by App::Netdisco::Util::Device::is_discoverable at line 167 of App/Netdisco/Util/Device.pm, avg 4µs/call
# 11 times (72µs+179µs) by App::Netdisco::Util::Device::is_arpnipable at line 236 of App/Netdisco/Util/Device.pm, avg 23µs/call
# 11 times (71µs+175µs) by App::Netdisco::Util::Device::is_macsuckable at line 285 of App/Netdisco/Util/Device.pm, avg 22µs/call
# 11 times (70µs+174µs) by App::Netdisco::Util::Device::is_discoverable at line 187 of App/Netdisco/Util/Device.pm, avg 22µs/call # spent 3.57ms making 774 calls to App::Netdisco::DB::Result::Device::ip, avg 5µs/call |
| 14 | |||||
| 15 | use base 'DBIx::Class::Core'; | ||||
| 16 | __PACKAGE__->table("device"); | ||||
| 17 | __PACKAGE__->add_columns( | ||||
| 18 | "ip", | ||||
| 19 | { data_type => "inet", is_nullable => 0 }, | ||||
| 20 | "creation", | ||||
| 21 | { | ||||
| 22 | data_type => "timestamp", | ||||
| 23 | default_value => \"current_timestamp", | ||||
| 24 | is_nullable => 1, | ||||
| 25 | original => { default_value => \"now()" }, | ||||
| 26 | }, | ||||
| 27 | "dns", | ||||
| 28 | { data_type => "text", is_nullable => 1 }, | ||||
| 29 | "description", | ||||
| 30 | { data_type => "text", is_nullable => 1 }, | ||||
| 31 | "uptime", | ||||
| 32 | { data_type => "bigint", is_nullable => 1 }, | ||||
| 33 | "contact", | ||||
| 34 | { data_type => "text", is_nullable => 1 }, | ||||
| 35 | "name", | ||||
| 36 | { data_type => "text", is_nullable => 1 }, | ||||
| 37 | "location", | ||||
| 38 | { data_type => "text", is_nullable => 1 }, | ||||
| 39 | "layers", | ||||
| 40 | { data_type => "varchar", is_nullable => 1, size => 8 }, | ||||
| 41 | "ports", | ||||
| 42 | { data_type => "integer", is_nullable => 1 }, | ||||
| 43 | "mac", | ||||
| 44 | { data_type => "macaddr", is_nullable => 1 }, | ||||
| 45 | "serial", | ||||
| 46 | { data_type => "text", is_nullable => 1 }, | ||||
| 47 | "model", | ||||
| 48 | { data_type => "text", is_nullable => 1 }, | ||||
| 49 | "ps1_type", | ||||
| 50 | { data_type => "text", is_nullable => 1 }, | ||||
| 51 | "ps2_type", | ||||
| 52 | { data_type => "text", is_nullable => 1 }, | ||||
| 53 | "ps1_status", | ||||
| 54 | { data_type => "text", is_nullable => 1 }, | ||||
| 55 | "ps2_status", | ||||
| 56 | { data_type => "text", is_nullable => 1 }, | ||||
| 57 | "fan", | ||||
| 58 | { data_type => "text", is_nullable => 1 }, | ||||
| 59 | "slots", | ||||
| 60 | { data_type => "integer", is_nullable => 1 }, | ||||
| 61 | "vendor", | ||||
| 62 | { data_type => "text", is_nullable => 1 }, | ||||
| 63 | "os", | ||||
| 64 | { data_type => "text", is_nullable => 1 }, | ||||
| 65 | "os_ver", | ||||
| 66 | { data_type => "text", is_nullable => 1 }, | ||||
| 67 | "log", | ||||
| 68 | { data_type => "text", is_nullable => 1 }, | ||||
| 69 | "snmp_ver", | ||||
| 70 | { data_type => "integer", is_nullable => 1 }, | ||||
| 71 | "snmp_comm", | ||||
| 72 | { data_type => "text", is_nullable => 1 }, | ||||
| 73 | "snmp_class", | ||||
| 74 | { data_type => "text", is_nullable => 1 }, | ||||
| 75 | "vtp_domain", | ||||
| 76 | { data_type => "text", is_nullable => 1 }, | ||||
| 77 | "last_discover", | ||||
| 78 | { data_type => "timestamp", is_nullable => 1 }, | ||||
| 79 | "last_macsuck", | ||||
| 80 | { data_type => "timestamp", is_nullable => 1 }, | ||||
| 81 | "last_arpnip", | ||||
| 82 | { data_type => "timestamp", is_nullable => 1 }, | ||||
| 83 | ); | ||||
| 84 | __PACKAGE__->set_primary_key("ip"); | ||||
| 85 | |||||
| 86 | # Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-07 14:20:02 | ||||
| 87 | # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:671/XuuvsO2aMB1+IRWFjg | ||||
| 88 | |||||
| 89 | =head1 RELATIONSHIPS | ||||
| 90 | |||||
| 91 | =head2 device_ips | ||||
| 92 | |||||
| 93 | Returns rows from the C<device_ip> table which relate to this Device. That is, | ||||
| 94 | all the interface IP aliases configured on the Device. | ||||
| 95 | |||||
| 96 | =cut | ||||
| 97 | |||||
| 98 | __PACKAGE__->has_many( device_ips => 'App::Netdisco::DB::Result::DeviceIp', 'ip' ); | ||||
| 99 | |||||
| 100 | =head2 vlans | ||||
| 101 | |||||
| 102 | Returns the C<device_vlan> entries for this Device. That is, the list of VLANs | ||||
| 103 | configured on or known by this Device. | ||||
| 104 | |||||
| 105 | =cut | ||||
| 106 | |||||
| 107 | __PACKAGE__->has_many( vlans => 'App::Netdisco::DB::Result::DeviceVlan', 'ip' ); | ||||
| 108 | |||||
| 109 | =head2 ports | ||||
| 110 | |||||
| 111 | Returns the set of ports on this Device. | ||||
| 112 | |||||
| 113 | =cut | ||||
| 114 | |||||
| 115 | __PACKAGE__->has_many( ports => 'App::Netdisco::DB::Result::DevicePort', 'ip' ); | ||||
| 116 | |||||
| 117 | =head2 modules | ||||
| 118 | |||||
| 119 | Returns the set chassis modules on this Device. | ||||
| 120 | |||||
| 121 | =cut | ||||
| 122 | |||||
| 123 | __PACKAGE__->has_many( modules => 'App::Netdisco::DB::Result::DeviceModule', 'ip' ); | ||||
| 124 | |||||
| 125 | =head2 power_modules | ||||
| 126 | |||||
| 127 | Returns the set of power modules on this Device. | ||||
| 128 | |||||
| 129 | =cut | ||||
| 130 | |||||
| 131 | __PACKAGE__->has_many( power_modules => 'App::Netdisco::DB::Result::DevicePower', 'ip' ); | ||||
| 132 | |||||
| 133 | =head2 port_vlans | ||||
| 134 | |||||
| 135 | Returns the set of VLANs known to be configured on Ports on this Device, | ||||
| 136 | either tagged or untagged. | ||||
| 137 | |||||
| 138 | The JOIN is of type "RIGHT" meaning that the results are constrained to VLANs | ||||
| 139 | only on Ports on this Device. | ||||
| 140 | |||||
| 141 | =cut | ||||
| 142 | |||||
| 143 | __PACKAGE__->has_many( | ||||
| 144 | port_vlans => 'App::Netdisco::DB::Result::DevicePortVlan', | ||||
| 145 | 'ip', { join_type => 'RIGHT' } | ||||
| 146 | ); | ||||
| 147 | |||||
| 148 | # helper which assumes we've just RIGHT JOINed to Vlans table | ||||
| 149 | sub vlan { return (shift)->vlans->first } | ||||
| 150 | |||||
| 151 | =head2 wireless_ports | ||||
| 152 | |||||
| 153 | Returns the set of wireless IDs known to be configured on Ports on this | ||||
| 154 | Device. | ||||
| 155 | |||||
| 156 | =cut | ||||
| 157 | |||||
| 158 | __PACKAGE__->has_many( | ||||
| 159 | wireless_ports => 'App::Netdisco::DB::Result::DevicePortWireless', | ||||
| 160 | 'ip', { join_type => 'RIGHT' } | ||||
| 161 | ); | ||||
| 162 | |||||
| 163 | =head2 ssids | ||||
| 164 | |||||
| 165 | Returns the set of SSIDs known to be configured on Ports on this Device. | ||||
| 166 | |||||
| 167 | =cut | ||||
| 168 | |||||
| 169 | __PACKAGE__->has_many( | ||||
| 170 | ssids => 'App::Netdisco::DB::Result::DevicePortSsid', | ||||
| 171 | 'ip', { join_type => 'RIGHT' } | ||||
| 172 | ); | ||||
| 173 | |||||
| 174 | =head2 properties_ports | ||||
| 175 | |||||
| 176 | Returns the set of ports known to have recorded properties | ||||
| 177 | |||||
| 178 | =cut | ||||
| 179 | |||||
| 180 | __PACKAGE__->has_many( | ||||
| 181 | properties_ports => 'App::Netdisco::DB::Result::DevicePortProperties', | ||||
| 182 | 'ip', { join_type => 'RIGHT' } | ||||
| 183 | ); | ||||
| 184 | |||||
| 185 | =head2 powered_ports | ||||
| 186 | |||||
| 187 | Returns the set of ports known to have PoE capability | ||||
| 188 | |||||
| 189 | =cut | ||||
| 190 | |||||
| 191 | __PACKAGE__->has_many( | ||||
| 192 | powered_ports => 'App::Netdisco::DB::Result::DevicePortPower', | ||||
| 193 | 'ip', { join_type => 'RIGHT' } | ||||
| 194 | ); | ||||
| 195 | |||||
| 196 | =head2 community | ||||
| 197 | |||||
| 198 | Returns the row from the community string table, if one exists. | ||||
| 199 | |||||
| 200 | =cut | ||||
| 201 | |||||
| 202 | __PACKAGE__->might_have( | ||||
| 203 | community => 'App::Netdisco::DB::Result::Community', 'ip'); | ||||
| 204 | |||||
| 205 | =head2 throughput | ||||
| 206 | |||||
| 207 | Returns a sum of speeds on all ports on the device. | ||||
| 208 | |||||
| 209 | =cut | ||||
| 210 | |||||
| 211 | __PACKAGE__->has_one( | ||||
| 212 | throughput => 'App::Netdisco::DB::Result::Virtual::DevicePortSpeed', 'ip'); | ||||
| 213 | |||||
| 214 | =head1 ADDITIONAL METHODS | ||||
| 215 | |||||
| 216 | =head2 is_pseudo | ||||
| 217 | |||||
| 218 | Returns true if the vendor of the device is "netdisco". | ||||
| 219 | |||||
| 220 | =cut | ||||
| 221 | |||||
| 222 | sub is_pseudo { | ||||
| 223 | my $device = shift; | ||||
| 224 | return (defined $device->vendor and $device->vendor eq 'netdisco'); | ||||
| 225 | } | ||||
| 226 | |||||
| 227 | =head2 has_layer( $number ) | ||||
| 228 | |||||
| 229 | Returns true if the device provided sysServices and supports the given layer. | ||||
| 230 | |||||
| 231 | =cut | ||||
| 232 | |||||
| 233 | sub has_layer { | ||||
| 234 | my ($device, $layer) = @_; | ||||
| 235 | return unless $layer and $layer =~ m/^[1-7]$/; | ||||
| 236 | return ($device->layers and (substr($device->layers, (8-$layer), 1) == 1)); | ||||
| 237 | } | ||||
| 238 | |||||
| 239 | =head2 renumber( $new_ip ) | ||||
| 240 | |||||
| 241 | Will update this device and all related database records to use the new IP | ||||
| 242 | C<$new_ip>. Returns C<undef> if $new_ip seems invalid, otherwise returns the | ||||
| 243 | Device row object. | ||||
| 244 | |||||
| 245 | =cut | ||||
| 246 | |||||
| 247 | sub renumber { | ||||
| 248 | my ($device, $ip) = @_; | ||||
| 249 | my $schema = $device->result_source->schema; | ||||
| 250 | |||||
| 251 | my $new_addr = NetAddr::IP::Lite->new($ip) | ||||
| 252 | or return; | ||||
| 253 | |||||
| 254 | my $old_ip = $device->ip; | ||||
| 255 | my $new_ip = $new_addr->addr; | ||||
| 256 | |||||
| 257 | return | ||||
| 258 | if $new_ip eq '0.0.0.0' | ||||
| 259 | or $new_ip eq '127.0.0.1'; | ||||
| 260 | |||||
| 261 | # Community is not included as SNMP::test_connection will take care of it | ||||
| 262 | foreach my $set (qw/ | ||||
| 263 | DeviceIp | ||||
| 264 | DeviceModule | ||||
| 265 | DevicePort | ||||
| 266 | DevicePortLog | ||||
| 267 | DevicePortPower | ||||
| 268 | DevicePortProperties | ||||
| 269 | DevicePortSsid | ||||
| 270 | DevicePortVlan | ||||
| 271 | DevicePortWireless | ||||
| 272 | DevicePower | ||||
| 273 | DeviceVlan | ||||
| 274 | /) { | ||||
| 275 | $schema->resultset($set) | ||||
| 276 | ->search({ip => $old_ip}) | ||||
| 277 | ->update({ip => $new_ip}); | ||||
| 278 | } | ||||
| 279 | |||||
| 280 | $schema->resultset('DeviceSkip') | ||||
| 281 | ->search({device => $new_ip})->delete; | ||||
| 282 | $schema->resultset('DeviceSkip') | ||||
| 283 | ->search({device => $old_ip}) | ||||
| 284 | ->update({device => $new_ip}); | ||||
| 285 | |||||
| 286 | $schema->resultset('DevicePort') | ||||
| 287 | ->search({remote_ip => $old_ip}) | ||||
| 288 | ->update({remote_ip => $new_ip}); | ||||
| 289 | |||||
| 290 | $schema->resultset('Node') | ||||
| 291 | ->search({switch => $old_ip}) | ||||
| 292 | ->update({switch => $new_ip}); | ||||
| 293 | |||||
| 294 | $schema->resultset('Topology') | ||||
| 295 | ->search({dev1 => $old_ip}) | ||||
| 296 | ->update({dev1 => $new_ip}); | ||||
| 297 | |||||
| 298 | $schema->resultset('Topology') | ||||
| 299 | ->search({dev2 => $old_ip}) | ||||
| 300 | ->update({dev2 => $new_ip}); | ||||
| 301 | |||||
| 302 | $device->update({ | ||||
| 303 | ip => $new_ip, | ||||
| 304 | dns => hostname_from_ip($new_ip), | ||||
| 305 | }); | ||||
| 306 | |||||
| 307 | return $device; | ||||
| 308 | } | ||||
| 309 | |||||
| 310 | =head1 ADDITIONAL COLUMNS | ||||
| 311 | |||||
| 312 | =head2 oui | ||||
| 313 | |||||
| 314 | Returns the first half of the device MAC address. | ||||
| 315 | |||||
| 316 | =cut | ||||
| 317 | |||||
| 318 | sub oui { return substr( ((shift)->mac || ''), 0, 8 ) } | ||||
| 319 | |||||
| 320 | =head2 port_count | ||||
| 321 | |||||
| 322 | Returns the number of ports on this device. Enable this | ||||
| 323 | column by applying the C<with_port_count()> modifier to C<search()>. | ||||
| 324 | |||||
| 325 | =cut | ||||
| 326 | |||||
| 327 | sub port_count { return (shift)->get_column('port_count') } | ||||
| 328 | |||||
| 329 | |||||
| 330 | =head2 uptime_age | ||||
| 331 | |||||
| 332 | Formatted version of the C<uptime> field. | ||||
| 333 | |||||
| 334 | The format is in "X days/months/years" style, similar to: | ||||
| 335 | |||||
| 336 | 1 year 4 months 05:46:00 | ||||
| 337 | |||||
| 338 | =cut | ||||
| 339 | |||||
| 340 | sub uptime_age { return (shift)->get_column('uptime_age') } | ||||
| 341 | |||||
| 342 | =head2 first_seen_stamp | ||||
| 343 | |||||
| 344 | Formatted version of the C<creation> field, accurate to the minute. | ||||
| 345 | |||||
| 346 | The format is somewhat like ISO 8601 or RFC3339 but without the middle C<T> | ||||
| 347 | between the date stamp and time stamp. That is: | ||||
| 348 | |||||
| 349 | 2012-02-06 12:49 | ||||
| 350 | |||||
| 351 | =cut | ||||
| 352 | |||||
| 353 | sub first_seen_stamp { return (shift)->get_column('first_seen_stamp') } | ||||
| 354 | |||||
| 355 | =head2 last_discover_stamp | ||||
| 356 | |||||
| 357 | Formatted version of the C<last_discover> field, accurate to the minute. | ||||
| 358 | |||||
| 359 | The format is somewhat like ISO 8601 or RFC3339 but without the middle C<T> | ||||
| 360 | between the date stamp and time stamp. That is: | ||||
| 361 | |||||
| 362 | 2012-02-06 12:49 | ||||
| 363 | |||||
| 364 | =cut | ||||
| 365 | |||||
| 366 | sub last_discover_stamp { return (shift)->get_column('last_discover_stamp') } | ||||
| 367 | |||||
| 368 | =head2 last_macsuck_stamp | ||||
| 369 | |||||
| 370 | Formatted version of the C<last_macsuck> field, accurate to the minute. | ||||
| 371 | |||||
| 372 | The format is somewhat like ISO 8601 or RFC3339 but without the middle C<T> | ||||
| 373 | between the date stamp and time stamp. That is: | ||||
| 374 | |||||
| 375 | 2012-02-06 12:49 | ||||
| 376 | |||||
| 377 | =cut | ||||
| 378 | |||||
| 379 | sub last_macsuck_stamp { return (shift)->get_column('last_macsuck_stamp') } | ||||
| 380 | |||||
| 381 | =head2 last_arpnip_stamp | ||||
| 382 | |||||
| 383 | Formatted version of the C<last_arpnip> field, accurate to the minute. | ||||
| 384 | |||||
| 385 | The format is somewhat like ISO 8601 or RFC3339 but without the middle C<T> | ||||
| 386 | between the date stamp and time stamp. That is: | ||||
| 387 | |||||
| 388 | 2012-02-06 12:49 | ||||
| 389 | |||||
| 390 | =cut | ||||
| 391 | |||||
| 392 | sub last_arpnip_stamp { return (shift)->get_column('last_arpnip_stamp') } | ||||
| 393 | |||||
| 394 | =head2 since_last_discover | ||||
| 395 | |||||
| 396 | Number of seconds which have elapsed since the value of C<last_discover>. | ||||
| 397 | |||||
| 398 | =cut | ||||
| 399 | |||||
| 400 | sub since_last_discover { return (shift)->get_column('since_last_discover') } | ||||
| 401 | |||||
| 402 | =head2 since_last_macsuck | ||||
| 403 | |||||
| 404 | Number of seconds which have elapsed since the value of C<last_macsuck>. | ||||
| 405 | |||||
| 406 | =cut | ||||
| 407 | |||||
| 408 | sub since_last_macsuck { return (shift)->get_column('since_last_macsuck') } | ||||
| 409 | |||||
| 410 | =head2 since_last_arpnip | ||||
| 411 | |||||
| 412 | Number of seconds which have elapsed since the value of C<last_arpnip>. | ||||
| 413 | |||||
| 414 | =cut | ||||
| 415 | |||||
| 416 | sub since_last_arpnip { return (shift)->get_column('since_last_arpnip') } | ||||
| 417 | |||||
| 418 | 1; |