├── .gitignore ├── CONTRIBUTORS ├── Makefile ├── README.md ├── bin ├── Makefile ├── build_topo_graph.pl ├── check_bgppeer.pl ├── check_ifstatus.pl ├── check_link_state.pl ├── device_checks.pl ├── dump-db.pl ├── ether_ip_port.pl ├── exporter.pl ├── find_address.pl ├── free_ip_space.pl ├── initdb ├── ipblock_checks.pl ├── oui.txt ├── perldeps.pl ├── prune_db.pl └── updatedevices.pl ├── doc ├── ChangeLog ├── Makefile ├── README ├── UPGRADE └── manual │ ├── Makefile │ ├── netdot-manual-es.html │ ├── netdot-manual-es.pdf │ ├── netdot-manual-es.txt │ ├── netdot-manual.html │ ├── netdot-manual.pdf │ └── netdot-manual.txt ├── etc ├── Default.conf ├── Makefile ├── default_data ├── netdot.meta ├── netdot_apache24_ldap.conf ├── netdot_apache24_local.conf ├── netdot_apache2_krb5.conf ├── netdot_apache2_ldap.conf ├── netdot_apache2_local.conf ├── netdot_apache2_radius.conf └── utility-Makefile ├── export ├── Makefile ├── cacti │ ├── netdot_to_cacti.php │ └── netdot_to_cacti_config.php ├── docs │ ├── circuits.pl │ ├── contacts.pl │ └── devices.pl └── nagios │ └── hosts.include ├── gpl.txt ├── htdocs ├── Makefile ├── autohandler ├── cable_plant │ ├── autohandler │ ├── backbone_graph.html │ ├── backbone_list_query.html │ ├── cable_backbone.html │ ├── cable_plant.html │ ├── cable_plant_backbone.mhtml │ ├── cable_plant_closet.mhtml │ ├── cable_plant_horizontal.mhtml │ ├── cable_plant_strand.mhtml │ ├── cable_strand.html │ ├── circuit.html │ ├── circuit_interfaces.mhtml │ ├── closet.html │ ├── dhandler │ ├── display_sequence.mhtml │ ├── get_strand_sequence_list.html │ ├── index.html │ ├── site_tasks.html │ ├── strand_backbone_list_query.html │ ├── suggest_backbonename.html │ └── suggest_jackid.html ├── contacts │ ├── autohandler │ ├── clists.html │ ├── dhandler │ ├── entities.html │ ├── index.html │ └── people.html ├── css │ ├── datechooser.css │ ├── new-style.css │ ├── style-blue.css │ ├── style-gray.css │ ├── style-uo.css │ └── style.css ├── dhandler ├── export │ ├── autohandler │ ├── config_tasks.html │ ├── dhandler │ └── index.html ├── footer.mhtml ├── generic │ ├── HERE.mhtml │ ├── access_right_form.html │ ├── attribute_table.mhtml │ ├── autohandler │ ├── browse.html │ ├── closet_floor_query.html │ ├── confirm.html │ ├── contactlist.html │ ├── contactlist.mhtml │ ├── data_table.mhtml │ ├── delete.html │ ├── descr.html │ ├── dhandler │ ├── display_bin.html │ ├── dynamic_list_query.html │ ├── edit-multiple.html │ ├── edit.html │ ├── error.mhtml │ ├── form.mhtml │ ├── hostlist.html │ ├── index.html │ ├── jsrs_netdot.html │ ├── jsrs_retrieve_all.html │ ├── list.html │ ├── no_search_criteria.html │ ├── no_search_results.html │ ├── raw_sql.html │ ├── search.html │ ├── search_obj.html │ ├── show_search_results.mhtml │ ├── sortresults.mhtml │ ├── subnet_zone_query.html │ ├── table.mhtml │ ├── user_pref.html │ ├── view.html │ ├── viewtext.html │ └── wrapping_table.mhtml ├── header.mhtml ├── help │ ├── autohandler │ ├── database-graph.html │ ├── database-rels.html │ ├── dhandler │ └── index.html ├── img │ ├── calendar.gif │ ├── favicon.ico │ └── title.png ├── index.html ├── java_script │ ├── datechooser.js │ ├── dynamic_list.js │ ├── jsrsClient.js │ ├── select.js │ └── toggle.js ├── login.html ├── logout.html ├── management │ ├── addneighbor.html │ ├── address_tasks.html │ ├── addservice.html │ ├── asset_tasks.html │ ├── autohandler │ ├── choose_ip.html │ ├── container.mhtml │ ├── device.html │ ├── device_tasks.html │ ├── dhandler │ ├── dhcp_tasks.html │ ├── host.html │ ├── host_tasks.html │ ├── hostlist.mhtml │ ├── i_arp.html │ ├── i_fdb.html │ ├── index.html │ ├── interface.html │ ├── interfaces.mhtml │ ├── ip-rec.html │ ├── ip.html │ ├── ipblock_list.mhtml │ ├── ipv6.html │ ├── list_rights.mhtml │ ├── live_results.mhtml │ ├── mac.html │ ├── scope.html │ ├── subnet.mhtml │ ├── template_edit.html │ ├── tree.mhtml │ ├── updatedevice.html │ ├── vlan.html │ ├── vlan_tasks.html │ ├── zone.html │ └── zone_tasks.html ├── menu_admin.mhtml ├── menu_user.mhtml ├── reports │ ├── addr_poll_stats.html │ ├── asset_inventory.html │ ├── autohandler │ ├── dev_poll_stats.html │ ├── device_inventory.html │ ├── dhandler │ ├── downtime.html │ ├── duplex.html │ ├── index.html │ ├── ip_reports.html │ ├── macs_by_vendor.html │ ├── maxed_subnets.html │ ├── mysql_stats.html │ ├── reports_custom.html │ ├── snmp_down.html │ ├── time_poll_stats.html │ ├── topology_graph.html │ ├── unused_statics.html │ ├── unused_subnets.html │ └── vlan_mismatches.html ├── rest │ ├── autohandler │ ├── devinfo │ ├── dhandler │ ├── host │ ├── host_contacts │ ├── index.html │ ├── ipattr │ └── updatedev ├── user_help │ ├── autohandler │ ├── dhandler │ ├── hosts.html │ └── index.html └── user_management │ ├── add_host.html │ ├── autohandler │ ├── contacts_tasks.html │ ├── device_tasks.html │ ├── dhandler │ ├── hostinfo_tasks.html │ ├── index.html │ ├── person.html │ └── user_device.html ├── import ├── Makefile ├── import_bind_zones.pl ├── import_closets.pl ├── import_hosts.pl ├── import_ip_bulk.pl ├── ip_list.txt ├── subnet_zone.pl ├── subnet_zone.txt └── update_dev_rest.pl ├── lib ├── DBUTIL.pm ├── Makefile ├── Netdot.pm ├── Netdot │ ├── AuthLocal.pm │ ├── Config.pm │ ├── Exporter.pm │ ├── Exporter │ │ ├── BIND.pm │ │ ├── DHCPD.pm │ │ ├── Nagios.pm │ │ ├── Rancid.pm │ │ ├── Smokeping.pm │ │ └── Sysmon.pm │ ├── FakeSNMPSession.pm │ ├── IPVisual.pm │ ├── Krb5.pm │ ├── LDAP.pm │ ├── Mason.pm │ ├── Meta.pm │ ├── Meta │ │ ├── SQLT.pm │ │ ├── Table.pm │ │ └── Table │ │ │ └── Column.pm │ ├── Model.pm │ ├── Model │ │ ├── ASN.pm │ │ ├── AccessRight.pm │ │ ├── ArpCacheEntry.pm │ │ ├── Asset.pm │ │ ├── BackboneCable.pm │ │ ├── CableStrand.pm │ │ ├── Circuit.pm │ │ ├── Closet.pm │ │ ├── ClosetPicture.pm │ │ ├── Contact.pm │ │ ├── DataCache.pm │ │ ├── Device.pm │ │ ├── Device │ │ │ ├── Airespace.pm │ │ │ ├── CLI.pm │ │ │ └── CLI │ │ │ │ ├── CiscoCat.pm │ │ │ │ ├── CiscoFW.pm │ │ │ │ ├── CiscoIOS.pm │ │ │ │ └── FoundryIW.pm │ │ ├── DeviceModule.pm │ │ ├── DhcpAttr.pm │ │ ├── DhcpScope.pm │ │ ├── FWTableEntry.pm │ │ ├── Floor.pm │ │ ├── FloorPicture.pm │ │ ├── GroupRight.pm │ │ ├── Interface.pm │ │ ├── Ipblock.pm │ │ ├── Nullify.pm │ │ ├── OUI.pm │ │ ├── Person.pm │ │ ├── PhysAddr.pm │ │ ├── Picture.pm │ │ ├── Plugins │ │ │ ├── DeviceIpNamesByInt.pm │ │ │ ├── DeviceIpNamesFixed.pm │ │ │ ├── DeviceIpNamesFromDNS.pm │ │ │ └── IPRangeDNS.pm │ │ ├── Product.pm │ │ ├── RR.pm │ │ ├── RRADDR.pm │ │ ├── RRCNAME.pm │ │ ├── RRDS.pm │ │ ├── RRHINFO.pm │ │ ├── RRLOC.pm │ │ ├── RRMX.pm │ │ ├── RRNAPTR.pm │ │ ├── RRNS.pm │ │ ├── RRPTR.pm │ │ ├── RRSRV.pm │ │ ├── RRTXT.pm │ │ ├── Room.pm │ │ ├── Site.pm │ │ ├── SitePicture.pm │ │ ├── Splice.pm │ │ ├── UserRight.pm │ │ ├── Vlan.pm │ │ ├── VlanGroup.pm │ │ └── Zone.pm │ ├── NetdotPermissionFactory.pm │ ├── ObjectAccessRule.pm │ ├── REST.pm │ ├── Radius.pm │ ├── SectionAccessRule.pm │ ├── SiteControlLoginWrapper.pm │ ├── Topology.pm │ ├── UI.pm │ ├── Util.pm │ └── Util │ │ ├── DNS.pm │ │ ├── Exception.pm │ │ ├── Log.pm │ │ └── Math.pm └── jsrsServer.pm ├── netdot.cron ├── patches └── ubuntu-1604 │ ├── DBI.pm.patch │ └── apache2-init.patch ├── t ├── ArpCacheEntry.t ├── Device.t ├── DhcpScope.t ├── Exporter.t ├── FWTableEntry.t ├── Interface.t ├── Ipblock-insert.t ├── Ipblock.t ├── Model.t ├── Nagios.t ├── Nullify.t ├── PhysAddr.t ├── Product.t ├── REST.t ├── RR.t ├── SitePicture.t ├── UI.t ├── Util.t ├── Vlan.t ├── VlanGroup.t ├── Zone.t ├── pod-coverage.t └── pod.t ├── upgrade ├── Makefile ├── updatedb └── upgrade-tasks └── var └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | 3 | # Most of these are produced by install 4 | # We don't want them in the repo 5 | .prefix 6 | bin/oui.txt 7 | etc/Site.conf* 8 | etc/schema* 9 | upgrade/error.log 10 | var/pollstats.rrd 11 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | A non-exhaustive list of contributors to Netdot: 2 | 3 | * Stephen Fromm 4 | * Kai Waldron 5 | * Nathan Collins 6 | * Aaron Parecki 7 | * Tony Kay 8 | * Peter Boothe 9 | * Dongting Yu 10 | * Tao Qin 11 | * Clayton (Parker) Coleman 12 | * Joe Pletcher 13 | * Brian Candler 14 | * Andy Linton 15 | * Anton Berezin 16 | * William Bulley 17 | * Wim Vandersmissen 18 | * Matt Zagrabelny 19 | * Vincent Magnin 20 | * Rolando Perez Martinez 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Network Documentation Tool 2 | 3 | Netdot is an open source tool designed to help network administrators collect, organize and maintain network documentation. 4 | 5 | Netdot was initially developed at the University of Oregon and continues to be maintained and expanded with support from volunteers. 6 | 7 | Features include: 8 | 9 | * Device discovery via SNMP 10 | * Layer2 topology discovery using: 11 | * CDP/LLDP 12 | * Spanning Tree Protocol 13 | * Switch forwarding tables 14 | * Router point-to-point subnets 15 | * IPv4 and IPv6 address space management (IPAM) 16 | * Address space visualization 17 | * DNS zone file generation (BIND) 18 | * ISC DHCPD config generation 19 | * IP and MAC address tracking 20 | * BGP peer and Autonomous Systems tracking 21 | * Cable plant (sites, fiber, copper, closets, circuits...) 22 | * Contacts (departments, providers, vendors, etc.) 23 | * Export scripts for various monitoring tools (Nagios, Sysmon, RANCID, Cacti, SmokePing) 24 | * Multi-level user access: Admin, Operator, User 25 | 26 | ## Documentation 27 | 28 | Read the Manual in [pdf](https://github.com/cvicente/Netdot/blob/master/doc/manual/netdot-manual.pdf) or [html](http://htmlpreview.github.io/?https://github.com/cvicente/Netdot/blob/master/doc/manual/netdot-manual.html) 29 | 30 | ## Contributing 31 | 32 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 33 | 34 | The most effective way to submit changes is to issue a Github pull request. 35 | 36 | ## Authors 37 | 38 | [Carlos Vicente](https://github.com/cvicente) 39 | 40 | Also see [Contributors](https://github.com/cvicente/Netdot/blob/master/CONTRIBUTORS) 41 | 42 | ## License 43 | 44 | This project is licensed under the [GPL](https://github.com/cvicente/Netdot/blob/master/gpl.txt) 45 | 46 | ## Acknowledgments 47 | 48 | * The University of Oregon and the Network Startup Resource Center (NSRC) 49 | * All the individuals who contributed patches, ideas, suggestions and feedback. 50 | 51 | Like us on [Facebook](http://www.facebook.com/NetdotTool) -------------------------------------------------------------------------------- /bin/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # NetDoT Makefile 5 | # 6 | 7 | PERL = /usr/bin/perl 8 | PREFIX = `cat ../.prefix` 9 | FMOD = 755 10 | OUI_URL = http://standards-oui.ieee.org/oui/oui.txt 11 | 12 | FILES := $(shell ls *.pl) 13 | 14 | ################################################################ 15 | # End of tweakable section 16 | ################################################################ 17 | install: 18 | $(substitute) 19 | 20 | installdb: _installdb install_oui 21 | 22 | _installdb: 23 | $(PERL) initdb initdb 24 | 25 | genschema: 26 | $(PERL) initdb generate 27 | 28 | dropdb: 29 | $(PERL) initdb dropdb 30 | 31 | defragdb: _defragdb 32 | 33 | _defragdb: 34 | $(PERL) defragdb 35 | 36 | oui: update_oui install_oui 37 | 38 | update_oui: 39 | rm -f oui.txt 40 | wget -t 1 -T 10 $(OUI_URL) 41 | 42 | install_oui: 43 | $(PERL) initdb oui 44 | -------------------------------------------------------------------------------- /bin/check_link_state.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | use SNMP::Info; 3 | use strict; 4 | use Data::Dumper; 5 | use lib "<>"; 6 | use Netdot::Model; 7 | # 8 | # 9 | # This simple utility collects interface status from devices matching a 10 | # given regular expression, and prints a report containing interfaces that 11 | # are operationally down and administratively up. It can be run periodically 12 | # as a CRON job. 13 | # 14 | my $DEBUG = 0; 15 | my %down_ports; 16 | my $name_regex = $ARGV[0] || 17 | die "Usage: $0 \n"; 18 | 19 | foreach my $d ( Device->retrieve_all() ){ 20 | if ( $d->get_label =~ /$name_regex/ ){ 21 | if ( $d->snmp_managed ){ 22 | &debug("Connecting to ".$d->get_label); 23 | my $info; 24 | eval { 25 | $info = $d->_get_snmp_session(); 26 | }; 27 | if ( my $e = $@ ){ 28 | warn "$e\n"; 29 | }else{ 30 | &check_ports($info, $d) if $info; 31 | } 32 | } 33 | } 34 | } 35 | 36 | &print_report() if %down_ports; 37 | 38 | 39 | ###################################################################################### 40 | # Subroutines 41 | ###################################################################################### 42 | 43 | 44 | ###################################################################################### 45 | sub print_report{ 46 | print "\n"; 47 | print "The Following ports are administratively up, but operationally down: \n\n"; 48 | foreach my $n ( sort keys %down_ports ){ 49 | print $n, "\n"; 50 | foreach my $p ( sort { $a <=> $b } keys %{$down_ports{$n}} ){ 51 | print " $p $down_ports{$n}{$p}{name}"; 52 | print " ($down_ports{$n}{$p}{description})" if $down_ports{$n}{$p}{description}; 53 | print "\n"; 54 | } 55 | print "\n"; 56 | } 57 | } 58 | 59 | ###################################################################################### 60 | sub check_ports { 61 | my ($info, $d) = @_; 62 | my $interfaces = $info->interfaces(); 63 | my $oper_status = $info->i_up(); 64 | my $admin_status = $info->i_up_admin(); 65 | my $names = $info->i_description(); 66 | my $descriptions = $info->i_alias(); 67 | 68 | foreach my $iid ( sort { $a <=> $b } keys %$interfaces ){ 69 | &debug($d->get_label . ": Checking interface: $iid"); 70 | if ( $d->monitored && 71 | defined $admin_status->{$iid} && 72 | defined $oper_status->{$iid} ){ 73 | 74 | if ( $admin_status->{$iid} eq 'up' && 75 | $oper_status->{$iid} eq 'down' ){ 76 | $down_ports{$d->fqdn}{$iid}{name} = $names->{$iid}; 77 | $down_ports{$d->fqdn}{$iid}{description} = $descriptions->{$iid}; 78 | } 79 | } 80 | } 81 | } 82 | 83 | sub debug{ 84 | print @_, "\n" if $DEBUG; 85 | } 86 | -------------------------------------------------------------------------------- /bin/free_ip_space.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use lib '/usr/local/netdot/lib'; 4 | use Netdot::Model; 5 | use strict; 6 | use Getopt::Long qw(:config no_ignore_case bundling); 7 | 8 | my $USAGE = < [-s ] 10 | -n, --network Network prefix 11 | -s, --size Maximum block size to partition space into 12 | -h, --help Print help (this message) 13 | 14 | EOF 15 | 16 | # handle cmdline args 17 | my %self; 18 | my $result = GetOptions( "n|network=s" => \$self{prefix}, 19 | "s|size=s" => \$self{size}, 20 | "h|help" => \$self{help}, 21 | ); 22 | 23 | if ( ! $result ) { 24 | print $USAGE; 25 | die "Error: Problem with cmdline args\n"; 26 | } 27 | if ( $self{help} ) { 28 | print $USAGE; 29 | exit; 30 | } 31 | die "You need to provide a network prefix\n" unless $self{prefix}; 32 | 33 | my $network = Ipblock->search(address=>$self{prefix})->first || 34 | die "Cannot find ".$self{prefix}." in the database\n"; 35 | 36 | foreach my $block ( sort $network->free_space($self{size}) ){ 37 | print $block, "\n"; 38 | } 39 | -------------------------------------------------------------------------------- /bin/initdb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # 4 | use strict; 5 | 6 | use lib "../lib"; 7 | use DBUTIL; 8 | 9 | 10 | my %CONFIG; 11 | $CONFIG{ACTION} = $ARGV[0] || ""; 12 | 13 | if ($CONFIG{ACTION} eq 'initdb' ) { 14 | &init_db(); 15 | }elsif ($CONFIG{ACTION} eq 'dropdb' ) { 16 | &drop_db(); 17 | }elsif ($CONFIG{ACTION} eq 'generate') { 18 | &generate_schema_file(); 19 | }elsif ($CONFIG{ACTION} eq 'oui') { 20 | &insert_oui(); 21 | }else { 22 | die '$CONFIG{ACTION} invalid: '.$CONFIG{ACTION} ; 23 | } 24 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # makefile for doc 5 | 6 | NDIR = manual 7 | 8 | FILES := `find . -type f |egrep -v '\.svn|Makefile' |sed -e 's/\.\///'` 9 | 10 | all: dir 11 | $(substitute) 12 | 13 | for dir in $(NDIR); do \ 14 | chown $(APACHEUSER):$(APACHEGROUP) $(STAGEDIR)/$(DIR)/$$dir; \ 15 | chmod 0755 $(STAGEDIR)/$(DIR)/$$dir; \ 16 | done 17 | 18 | # This section creates the doc/ subdirs 19 | dir: 20 | $(mkdirs) 21 | -------------------------------------------------------------------------------- /doc/README: -------------------------------------------------------------------------------- 1 | 2 | Please find the installation and operation manual under the manual/ directory. 3 | -------------------------------------------------------------------------------- /doc/UPGRADE: -------------------------------------------------------------------------------- 1 | 2 | == Instructions for Upgrading Netdot == 3 | 4 | 5 | NOTE: Starting with Netdot 1.0.1, the upgrade script is able to perform several 6 | version upgrades at once. 7 | 8 | 1. You may need to update the database schema in addition to the application. 9 | 10 | IMPORTANT: MAKE SURE YOU MAKE A BACKUP COPY OF YOUR DATABASE BEFORE UPGRADING 11 | 12 | After making a backup copy of your database, please execute the following command: 13 | 14 | # make upgrade 15 | 16 | This will call a script that updates your current database to the schema required 17 | by the version you are upgrading to. 18 | 19 | Any errors found while applying these schema changes will be written to a file 20 | called "error.log". You will need to inspect this file and make sure to correct 21 | any problems before continuing. You may have to restore your database from backup, 22 | fix any issues and start over. 23 | 24 | 2. Check for new required dependencies: 25 | 26 | # make testdeps 27 | 28 | 3. At this point you can do a 29 | 30 | # make install [PARAMETERS] 31 | 32 | 4. Restart Apache 33 | 34 | 35 | -------------------------------------------------------------------------------- /doc/manual/Makefile: -------------------------------------------------------------------------------- 1 | # The master form of the documentation is the .txt file, which is converted 2 | # to the other forms using pandoc 3 | # The input is in pandoc's extended form of 'markdown' 4 | # Requirements: 5 | # $ sudo apt-get install pandoc texlive-fonts-recommended texlive-latex-extra 6 | 7 | PANDOC_OPTIONS=--number-sections --toc 8 | PANDOC=/usr/bin/pandoc 9 | 10 | SOURCES=netdot-manual.txt netdot-manual-es.txt 11 | 12 | PDFS=$(SOURCES:.txt=.pdf) 13 | HTMLS=$(SOURCES:.txt=.html) 14 | 15 | all: $(PDFS) $(HTMLS) 16 | 17 | %.pdf: %.txt 18 | $(PANDOC) $(PANDOC_OPTIONS) $< -o $@ 19 | 20 | %.html: %.txt 21 | $(PANDOC) $(PANDOC_OPTIONS) $< -o $@ 22 | 23 | -------------------------------------------------------------------------------- /doc/manual/netdot-manual-es.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvicente/Netdot/d83466264096dbc9c9f7ca75f814a8484600cdba/doc/manual/netdot-manual-es.pdf -------------------------------------------------------------------------------- /doc/manual/netdot-manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvicente/Netdot/d83466264096dbc9c9f7ca75f814a8484600cdba/doc/manual/netdot-manual.pdf -------------------------------------------------------------------------------- /etc/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # makefile for etc/ 5 | 6 | 7 | FILES = Default.conf netdot_apache2_radius.conf netdot_apache2_ldap.conf netdot_apache2_local.conf netdot_apache24_local.conf netdot.meta 8 | 9 | all: 10 | $(substitute) 11 | if ! test -r $(PREFIX)/$(DIR)/Site.conf; then \ 12 | $(SED) -r $(REPLACEMENT_EXPRESSIONS) Site.conf \ 13 | > Site.conf.tmp;\ 14 | install -m $(FMOD) Site.conf.tmp $(PREFIX)/$(DIR)/Site.conf;\ 15 | rm -rf Site.conf.tmp;\ 16 | fi; 17 | -------------------------------------------------------------------------------- /etc/utility-Makefile: -------------------------------------------------------------------------------- 1 | # Include this make file in other make files. It includes common 2 | # functionality that is used in multiple netdot related make files. 3 | 4 | # We will include this as 5 | 6 | # include $(SRCROOT)/etc/utility-Makefile 7 | 8 | # where SRCROOT is defined as the cwd where the top level make file is 9 | # called. 10 | 11 | 12 | ###### SUBSTITUTIONS ###### 13 | 14 | # Specify the variables you would like replaced here. The definitions 15 | # can be specified in a make file or on the command line. 16 | REPLACEABLES := PREFIX LIB ETC PERL 17 | 18 | # Defaults 19 | REPLACE_PREFIX = $(PREFIX) 20 | REPLACE_LIB = $(REPLACE_PREFIX)/lib 21 | REPLACE_ETC = $(REPLACE_PREFIX)/etc 22 | REPLACE_PERL = $(PERL) 23 | 24 | # Build up a list of sed expressions for the replacements. Notice 25 | # that undefined replacements will get flagged when replaced. 26 | REPLACEMENT_EXPRESSIONS = $(foreach r, $(REPLACEABLES), \ 27 | -e "s|<>|$(if $(REPLACE_$(r)),$(REPLACE_$(r)),$(r)_WAS_NOT_DEFINED_DURING_MAKE)|g") 28 | 29 | # This macro does variable substitution using sed. It looks for 30 | # occurrences of ``<>'' and replaces them with $(NAME), 31 | # where NAME represents on the names specified above in REPLACEABLES. 32 | 33 | # It behaves just like the 6 old functions which occured in various 34 | # makefiles, that is, it installs all files in $(FILES) in 35 | # $(PREFIX)/$(DIR) using the permissions $(FMOD). 36 | 37 | # You call it just as you expand any other macro, i.e. $(substitute) 38 | define substitute 39 | @echo 40 | @echo "Preparing and installing $(DIR) files..." 41 | for file in $(FILES); do\ 42 | $(SED) -r $(REPLACEMENT_EXPRESSIONS) $$file\ 43 | > $$file.tmp;\ 44 | install -m $(FMOD) $$file.tmp $(STAGEDIR)/$(DIR)/$$file;\ 45 | rm -rf $$file.tmp;\ 46 | done 47 | @echo "Done." 48 | endef 49 | 50 | # Common routine for creating directories 51 | define mkdirs 52 | @echo "Creating necessary directories..." 53 | for dir in $(NDIR); do \ 54 | if test -d $(STAGEDIR)/$(DIR)/$$dir; then \ 55 | echo "Skipping dir $(STAGEDIR)/$(DIR)/$$dir; already exists"; \ 56 | else \ 57 | mkdir -m $(DMOD) -p $(STAGEDIR)/$(DIR)/$$dir ; \ 58 | fi ; \ 59 | done 60 | @echo "Done." 61 | endef 62 | 63 | # For some directories we want to make sure that old files are not 64 | # left hanging around 65 | define wipedir 66 | @echo "Wiping out directory before installing" 67 | rm -fr $(STAGEDIR)/$(DIR) 68 | @echo "done" 69 | endef 70 | -------------------------------------------------------------------------------- /export/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # makefile for export/ 5 | # 6 | NDIR = docs nagios sysmon rancid cacti ethers smokeping bind dhcpd 7 | 8 | FILES := `find . -type f |egrep -v '\.svn|Makefile' |sed -e 's/\.\///'` 9 | 10 | all: dir 11 | $(substitute) 12 | 13 | for dir in $(NDIR); do \ 14 | chown $(APACHEUSER):$(APACHEGROUP) $(STAGEDIR)/$(DIR)/$$dir; \ 15 | chmod 0755 $(STAGEDIR)/$(DIR)/$$dir; \ 16 | done 17 | 18 | # This section creates the export/ subdirs 19 | dir: 20 | $(mkdirs) 21 | -------------------------------------------------------------------------------- /htdocs/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # makefile for htdocs 5 | 6 | NDIR = cable_plant css generic help img img/graphs java_script management contacts operations reports export user_management user_help masondata/obj masondata/cache rest 7 | 8 | FILES := `find . -name "*" | egrep ".*(rest\/.*|handler|\.?html|\.css|\.png|\.gif|\.js|\.ico)$$" | sed -e 's/\.\///'` 9 | 10 | all: wipedir dir 11 | $(substitute) 12 | ln -s $(PREFIX)/doc/manual/netdot-manual.htm $(STAGEDIR)/$(DIR)/help/manual.html 13 | 14 | # Wipe out dir before installing 15 | wipedir: 16 | $(wipedir) 17 | 18 | # This section creates the htdocs/ subdirs 19 | dir: 20 | $(mkdirs) 21 | 22 | @echo "Hacking together mason permissions fix..." 23 | touch $(STAGEDIR)/$(DIR)/masondata/obj/.__obj_create_marker 24 | chown -R $(APACHEUSER):$(APACHEGROUP) $(STAGEDIR)/$(DIR)/masondata 25 | chmod 0755 $(STAGEDIR)/$(DIR)/masondata 26 | # Graphs can be updated dynamically so apache needs +w 27 | chown $(APACHEUSER):$(APACHEGROUP) $(STAGEDIR)/$(DIR)/img/graphs 28 | chmod 0750 $(STAGEDIR)/$(DIR)/img/graphs 29 | 30 | -------------------------------------------------------------------------------- /htdocs/cable_plant/backbone_graph.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show backbone cable graph 3 | 4 | 5 | <%args> 6 | 7 | 8 | <%init> 9 | my $DEBUG = 0; 10 | 11 | 12 |
13 |
14 | Backbone Cable Plant Graph 15 |
16 |
17 |   18 |
19 |
20 |
21 |
22 | Cable Legend: Cable Name (used/total strands) 23 |
24 | 25 |


26 | % print $ui->build_backbone_graph_html(web_path=>$r->dir_config('NetdotPath')); 27 |

28 |
29 | -------------------------------------------------------------------------------- /htdocs/cable_plant/backbone_list_query.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | ############################################################################### 3 | # A customized version of the generic dynamic_list_query.html 4 | ############################################################################### 5 | 6 | 7 | <%args> 8 | $val => $ARGS{crit}; 9 | $caller => $ARGS{self}; 10 | 11 | 12 | <%init> 13 | my $DEBUG = 0; 14 | print "
 ", Dumper(%ARGS), "

" if $DEBUG; 15 | 16 | 17 | <%perl> 18 | 19 | if ( $DEBUG ){ 20 | use Data::Dumper; 21 | print "
 ", Dumper(%ARGS), "

"; 22 | print &backbone_search("end_id", "1"); 23 | } else { 24 | do "jsrsServer.pm"; 25 | jsrsDispatch("backbone_search"); 26 | } 27 | 28 | 29 | 30 | <%shared> 31 | 32 | sub backbone_search { 33 | # Arguments: 34 | # - field: Form element to add the results into 35 | # - crit: Criteria. A string with one or more keywords to search 36 | 37 | my $field = shift; 38 | my $crit = shift; 39 | my $val = $crit; 40 | my @terms; 41 | 42 | if ( $val =~ /\w+/ ) { 43 | if ( $val =~ /\w+\s+\w+/ ){ 44 | # if there's more than one word 45 | @terms = split /\s+/, $val; 46 | }else{ 47 | $val =~ s/\s+//; 48 | push @terms, $val; 49 | } 50 | } 51 | 52 | my $site_id = $terms[0] if ( scalar(@terms) ); 53 | 54 | my $site_graph = BackboneCable->get_site_graph(); 55 | my @results = keys %{$site_graph->{$site_id}}; 56 | 57 | my $MAX_RESULTS = $ui->config->get('DEFAULT_SELECTMAX'); 58 | my $response = $field."&"; 59 | 60 | if ( scalar(@results ) < $MAX_RESULTS) { 61 | $response .= "0=".$ui->url_encode("No matches") unless (scalar(@results)); 62 | 63 | @results = sort { $a->name cmp $b->name } 64 | map { Site->retrieve($_) } @results; 65 | 66 | foreach my $site ( @results ){ 67 | $response .= $site->id."=".$ui->url_encode($site->name)."&"; 68 | } 69 | }else{ 70 | $response .= "0=".$ui->url_encode("More than ".$MAX_RESULTS." matches.")."&"; 71 | $response .= "0=".$ui->url_encode("Refine search.")."&"; 72 | } 73 | 74 | return $response; 75 | } 76 | 77 | 78 | -------------------------------------------------------------------------------- /htdocs/cable_plant/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | -------------------------------------------------------------------------------- /htdocs/cable_plant/get_strand_sequence_list.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Code to determine available "sequences" between a starting an ending 3 | site. A sequence is a set of CableStrands with splice relationships. 4 | 5 | Arguments; 6 | - start_id: id of starting Site. 7 | - end_id: id of ending Site. 8 | - form_name: name of html form. 9 | - field_name: name of widget to update. 9 | 10 | 11 | <%args> 12 | $bb_id 13 | $field_name 14 | $form_name 15 | 16 | 17 | <%init> 18 | my $DEBUG = 0; 19 | print "
 ", Dumper(%ARGS), "

" if $DEBUG; 20 | 21 | my $bb = BackboneCable->retrieve($bb_id) 22 | || $m->comp("../generic/error.mhtml", error =>"Cannot retrieve Backbone id $bb_id"); 23 | 24 | 25 | 26 | 27 | 28 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /htdocs/cable_plant/suggest_backbonename.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Attempts to guess an appropriate backbone name based on start and end closet. 3 | 4 | TODO: May need to be more intelligent about suggesting duplicates. 5 | 6 | 7 | <%args> 8 | $start 9 | $end 10 | $name 11 | 12 | 13 | 14 | 15 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /htdocs/cable_plant/suggest_jackid.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Generates a Jack ID based upon Building, Closet, and a user supplied jack number. 3 | 4 | The format for a Jack ID is: 5 | i.e. 017B026B 6 | 7 | 8 | 9 | <%args> 10 | $closetid 11 | $jackno 12 | $name 13 | 14 | 15 | 16 | 17 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /htdocs/contacts/autohandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Contacts Management 3 | 4 | 5 | <%args> 6 | $user => $ui->get_current_user($r); 7 | $showheader => 1 8 | 9 | 10 | <%attr> 11 | title => 'Contacts' 12 | # This is used by the toplevel autohandler to determine the section. 13 | # Since attributes aren't inherited (but shouldn't they be ...) we have 14 | # to also specify this in the dhandler 15 | section => "Contacts" # $SECTION 16 | 17 | 18 | <%shared> 19 | my $PAGE_ATTRIBUTE = "CONTACTS_PAGE"; 20 | my $SECTION = "Contacts"; 21 | 22 | 23 | <%init> 24 | my $DEBUG = 0; 25 | my $manager = $ui->get_permission_manager($r); 26 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 27 | print "Request component name: ", $m->request_comp->name if $DEBUG; 28 | 29 | my $page; 30 | 31 | if ( $manager && $manager->can($user, "access_section", 'contacts') ){ 32 | 33 | my $caller_args = $m->caller_args(-1); 34 | if (exists($caller_args->{page})){ 35 | $user->setAttribute($r, "$PAGE_ATTRIBUTE", $caller_args->{page}); 36 | } 37 | $page = $user->getAttribute("$PAGE_ATTRIBUTE"); 38 | 39 | if (exists($caller_args->{tasks})){ 40 | $user->setAttribute($r, "SHOW_TASKS", $caller_args->{tasks}); 41 | } 42 | my $show_tasks = $user->getAttribute("SHOW_TASKS"); 43 | if ($show_tasks eq "") { 44 | $user->setAttribute($r, "SHOW_TASKS", "show"); 45 | $show_tasks = "show"; 46 | } 47 | *print_showtaskslink = $m->comp('SELF:.sub_print_showtaskslink'); 48 | 49 | my $hideheader; 50 | if( !$showheader ) { 51 | $hideheader = 'style="display:none"'; 52 | } 53 | 54 | if ( $page eq "ENTITIES" && $m->request_comp->name ne "entities.html" ) { 55 | $m->comp('entities.html', %ARGS); 56 | }elsif ( ($page eq "PEOPLE" || $page eq "") && $m->request_comp->name ne "people.html" ) { 57 | $m->comp('people.html', %ARGS); 58 | }elsif ( ($page eq "CLISTS" || $page eq "") && $m->request_comp->name ne "clists.html" ) { 59 | my %args = (showheader=>$showheader); 60 | $args{view} = $ARGS{view} if defined $ARGS{view}; 61 | $m->comp('clists.html', %args); 62 | } 63 | } 64 | 65 | 66 | <%perl> 67 | if ( my $next = $m->fetch_next ){ 68 | if ( $page ){ 69 | $m->call_next(page => $page); 70 | }else{ 71 | $m->call_next(); 72 | } 73 | } 74 | 75 | 76 | 77 | %# Methods can be called externally. 78 | <%method .section_meta_data> 79 | <%doc> 80 | Returns the meta data used to generate this section\'s header in section1.mhtml 81 | 82 | <%init> 83 | return { 84 | section => $SECTION, 85 | page => 'contacts/', 86 | title => 'Contacts', 87 | attribute => $PAGE_ATTRIBUTE, 88 | sub_sections => [ 89 | { section => 'PEOPLE', title => 'People' }, 90 | { section => 'ENTITIES', title => 'Entities'}, 91 | { section => 'CLISTS', title => 'Contact Lists'}, 92 | ] 93 | }; 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /htdocs/contacts/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | 3 | -------------------------------------------------------------------------------- /htdocs/contacts/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Intentionally empty. Just triggers the autohandler. This file 3 | could be eliminated by setting up HTML::Mason to handle directory 4 | requests, I think. 5 | -------------------------------------------------------------------------------- /htdocs/css/datechooser.css: -------------------------------------------------------------------------------- 1 | .dateChooser td { 2 | cursor:default; 3 | text-align:center; 4 | } 5 | .dateChooser td.dateChooserActive:hover { 6 | color:white; 7 | background:#0A246A; 8 | } 9 | .dateChooser td.dateChooserActiveToday { 10 | border: 1px solid red; 11 | } 12 | .dateChooser th { 13 | background: #aaa; 14 | color: white; 15 | width: 18px; 16 | border: none; 17 | } 18 | .dateChooser option, .dateChooser select { 19 | font-size:10px; 20 | } 21 | .dateChooser { 22 | border: 2px outset #aaa; 23 | background: white; 24 | padding: 1px; 25 | } 26 | .dateChooser table { 27 | width:160px; 28 | } 29 | 30 | /* http://www.hedgerwow.com/360/bugs/css-select-free.html */ 31 | .select-free { 32 | position:absolute; 33 | z-index:10; 34 | cursor:pointer; 35 | overflow:hidden; 36 | width:33em; 37 | } 38 | .select-free iframe { 39 | display:none; 40 | display/**/:block; 41 | position:absolute; 42 | top:0; 43 | left:0; 44 | z-index:-1; 45 | /* filter:mask(); */ 46 | width:3000px; 47 | height:3000px 48 | } 49 | -------------------------------------------------------------------------------- /htdocs/css/new-style.css: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | body { 3 | margin-left: 10px; 4 | margin-right: 10px; 5 | padding: 0; 6 | background-color: #FFFFFF; 7 | color: #000000; 8 | } 9 | 10 | 11 | #header { 12 | height: 5em; 13 | } 14 | #header .headleft { 15 | float: left; 16 | } 17 | #header .headright { 18 | background-color: transparent; 19 | float: right; 20 | } 21 | #header hr { 22 | border: none; 23 | background-color: #c2bed8; /* for mozilla */ 24 | color: #c2bed8; /* for ie */ 25 | margin-top: 2em; 26 | clear: both; 27 | height: 3px; 28 | width: 100%; 29 | } 30 | #header form { 31 | display: inline; 32 | } 33 | #header a:link, #header a:visited { 34 | text-decoration: none; 35 | } 36 | #header a:active, #header a:hover { 37 | text-decoration: underline; 38 | } 39 | 40 | 41 | ul#navigation { 42 | list-style-type: none; 43 | margin: 0; 44 | padding-left: 20px; 45 | padding-bottom: 28px; 46 | border-bottom: 1px solid #000000; 47 | font-size: 1.1em; 48 | } 49 | ul#navigation li { 50 | float: left; 51 | height: 25px; 52 | display: inline; 53 | background-color: #c2bed8; 54 | color: #000000; 55 | margin: 2px 2px 0 2px; 56 | border: 1px solid #000000; 57 | } 58 | ul#navigation a:link, ul#navigation a:visited { 59 | display: block; 60 | color: #000000; 61 | background-color: transparent; 62 | text-decoration: none; 63 | padding: 4px; 64 | } 65 | ul#navigation a:hover { 66 | color: #000000; 67 | background-color: #e7e6f2; 68 | } 69 | 70 | 71 | body#Main li.main, 72 | body#Management li.management, 73 | body#Services li.services, 74 | body#Operations li.operations, 75 | body#Plant li.cableplant, 76 | body#Generic li.generic, 77 | body#Reports li.reports, 78 | body#Help li.help { 79 | border-bottom: 1px solid #000000; 80 | color: #000000; 81 | background-color: #e7e6f2; 82 | } 83 | 84 | 85 | 86 | body#Main li.main a:link, 87 | body#Main li.main a:visited, 88 | body#Management li.management a:link, 89 | body#Management li.management a:visited, 90 | body#Services li.services a:link, 91 | body#Services li.services a:visited, 92 | body#Operations li.operations a:link, 93 | body#Operations li.operations a:visited, 94 | body#Plant li.cableplant a:link, 95 | body#Plant li.cableplant a:visited, 96 | body#Generic li.generic a:link, 97 | body#Generic li.generic a:visited, 98 | body#Reports li.reports a:link, 99 | body#Reports li.reports a:visited, 100 | body#Help li.help a:link, 101 | body#Help li.help a:visited { 102 | color: #000000; 103 | background-color: #e7e6f2; 104 | } 105 | 106 | 107 | #content { 108 | border-left: 1px solid #000000; 109 | border-right: 1px solid #000000; 110 | border-bottom: 1px solid #000000; 111 | padding: 10px 5px 6px 5px; 112 | background-color: #e7e6f2; 113 | } 114 | 115 | #content h3 { 116 | font-size: 1.2em; 117 | background-color: transparent; 118 | } 119 | -------------------------------------------------------------------------------- /htdocs/dhandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Default Handler for nonexistent pages 3 | 4 | 5 | <%init> 6 | # Otherwise apache (by extension probably) determines the content type 7 | # which botches the error message if not html. 8 | $r->content_type(q{text/html; charset=utf-8}); 9 | my $arg = $m->dhandler_arg(); 10 | 11 | 12 | <%perl> 13 | 14 | $m->comp('/generic/error.mhtml', error => "The requested page: \"$arg\" does not exist"); 15 | 16 | 17 | -------------------------------------------------------------------------------- /htdocs/export/autohandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Export Section. 4 | 5 | 6 | % 7 | % 8 | <%args> 9 | $user => $ui->get_current_user($r); 10 | $showheader => 1 11 | 12 | % 13 | % 14 | <%attr> 15 | title => 'Export' 16 | section => 'Export' 17 | 18 | % 19 | % 20 | <%shared> 21 | my $PAGE_ATTRIBUTE = "EXPORT_PAGE"; 22 | my $SECTION = "Export"; 23 | 24 | % 25 | % 26 | <%init> 27 | 28 | my $manager = $ui->get_permission_manager($r); 29 | unless ( $manager && $manager->can($user, "access_section", 'export') ){ 30 | $m->comp('/generic/error.mhtml', error=>"You don't have permission to access this section"); 31 | } 32 | 33 | my %caller_args = $m->caller_args(-1); 34 | if (exists($caller_args{page})){ 35 | $user->setAttribute($r, "$PAGE_ATTRIBUTE", $caller_args{page}); 36 | } 37 | my $page = $user->getAttribute("$PAGE_ATTRIBUTE"); 38 | 39 | 40 | <%method .section_meta_data> 41 | <%doc> 42 | Returns the meta data used to generate this sections header in section1.mhtml 43 | 44 | <%init> 45 | return { 46 | section => $SECTION, 47 | page => 'export/', 48 | title => 'Export', 49 | attribute => $PAGE_ATTRIBUTE, 50 | sub_sections => [ 51 | { section => 'CONFIG', title => 'Configurations' }, 52 | ] 53 | }; 54 | 55 | 56 | 57 | <%perl> 58 | 59 | if ( ($page eq "CONFIG" || $page eq "") && $m->request_comp->name ne "config_tasks.html" ) { 60 | 61 | $m->comp('config_tasks.html', user=>$user, showheader=>$showheader); 62 | 63 | }if ( $m->fetch_next ){ 64 | $m->call_next; 65 | } 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /htdocs/export/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | -------------------------------------------------------------------------------- /htdocs/export/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Intentionally empty. Just triggers the autohandler. This file 3 | could be eliminated by setting up HTML::Mason to handle directory 4 | requests, I think. 5 | 6 | -------------------------------------------------------------------------------- /htdocs/footer.mhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /htdocs/generic/HERE.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | =head1 DESCRIPTION 4 | 5 | For capuring a chunk of mason *after* processing. Analogous to 6 | interpolating HERE documents in shell or perl. 7 | 8 | If you pass a scalar reference then the content will be put in there. 9 | Otherwise the default variable $_ is used. 10 | 11 | =head1 EXAMPLE 12 | 13 | If you pass in a scalar reference you can retrieve the wrapped 14 | contents *after* processing. 15 | 16 | % my $var; 17 | <&| "HERE.mhtml", var =>\$var &> 18 | % foreach ('a'..'z') { print "$_\n"; } 19 | Now I know my abcs 20 | 21 | 22 | So 23 | 24 | % some_perl_function($var); 25 | 26 | passes the string 27 | 28 | "a 29 | b 30 | c 31 | . 32 | . 33 | . 34 | x 35 | y 36 | z 37 | Now I know my abcs" 38 | 39 | to some perl function. 40 | 41 | You can also just insert it in some regular mason code: 42 | 43 |
<% $var %>
44 | 45 | =cut 46 | 47 | 48 | 49 | <%args> 50 | $var => \$_ # Reference to scalar to put content in. 51 | 52 | 53 | % $$var = $m->content(); 54 | 55 | -------------------------------------------------------------------------------- /htdocs/generic/attribute_table.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Displays a table for showing attribute/value pairs 4 | 5 | example output: 6 | 7 | headers data 8 | -------------------------------- 9 | | Address | 128.223.0.0 | 10 | | Status | Container | 11 | | Description | | 12 | | Parent Block| Root block | 13 | -------------------------------- 14 | 15 | Arguments: 16 | field_headers - array of captions to show in the left column 17 | data - array to show in the right column 18 | width - number of (HTML table) columns to display default is 1 19 | headercolwidth - cell width for the header columns 20 | datacolwidth - cell width for the data columns 21 | 22 | 23 | <%args> 24 | @field_headers => undef; 25 | @data => undef; 26 | $width => 1 27 | $headercolwidth => "30%"; 28 | $datacolwidth => ""; 29 | 30 | 31 | <%init> 32 | my $DEBUG = 0; 33 | my $headerwidthstr = "width=\"".$headercolwidth."\"" if ($headercolwidth ne "") ; 34 | my $datawidthstr = "width=\"".$datacolwidth."\"" if ($datacolwidth ne ""); 35 | my $nfields = scalar(@field_headers); 36 | my $nrows = ( $nfields % $width == 0 ) ? $nfields/$width : int($nfields/$width)+1; 37 | my $pos = 0; 38 | my $colwidth = int(100/$width); 39 | 40 | 41 | % my $jsstring = "jspopoutstring+=encodeURIComponent(\""; 42 | 43 | 44 | % for ( my($w)=1; $w <= $width; $w++ ){ 45 | 72 |
46 | 47 | % for ( my($r)=1; $r <= $nrows; $r++ ){ 48 | 49 | 50 | 51 | 52 | % #append to the plaintext version using javascript 53 | % my $jslabel = $field_headers[$pos]; 54 | % my $jsvalue = $data[$pos]; 55 | % $jslabel =~ s/<.*?>//g; 56 | % $jsvalue =~ s/<.*?>//g; 57 | % $jslabel =~ s/"/\\"/g; 58 | % $jsvalue =~ s/"/\\"/g; 59 | % $jslabel =~ s/[\r\n]//g; 60 | % $jsvalue =~ s/\r\n/
/g; 61 | % $jsvalue =~ s/\n/
/g; 62 | % $jsvalue =~ s/((
)*\s*
\s*)+$//; 63 | % $jsstring .= $jslabel." ".$jsvalue."
" if ($jslabel); 64 | 65 | 66 | % $pos++; 67 | % } 68 | 69 |
class="formtablec1"><% $field_headers[$pos] %> class="formtablec2"><% $data[$pos] %>
70 | % } 71 |
73 | 74 | % $jsstring .= "
\");"; 75 | 76 | 79 | -------------------------------------------------------------------------------- /htdocs/generic/browse.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Generic Browse function 3 | 4 | 5 | 6 | <%args> 7 | $table => undef 8 | 9 | 10 | <%attr> 11 | title => 'Browse' 12 | section => 'Generic' 13 | 14 | 15 | <%init> 16 | my $MAX = 20; 17 | my $WIDTH = 2; 18 | 19 | 20 | 21 |
22 | 23 | % if ( ! $table ) { 24 | % my( @t ); 25 | % @t = $ui->meta->get_tables(); 26 | <& table.mhtml, width => $WIDTH, link => "browse.html", title => "Please select a table to browse:" &> 27 | % } else { 28 | % my @r = $table->retrieve_all(); 29 | 30 |
31 |
<% $table %> ( <% scalar (@r) %> records)
32 |
33 | <& sortresults.mhtml, table => $table, object => \@r, view => "row", withedit=>1, return_args=>"?table=$table" &> 34 |
35 |
36 | % } 37 | 38 |
39 | -------------------------------------------------------------------------------- /htdocs/generic/closet_floor_query.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | ############################################################################### 3 | # A customized version of the generic dynamic_list_query.html 4 | ############################################################################### 5 | 6 | 7 | 8 | <%args> 9 | $field => $ARGS{field}; 10 | $val => $ARGS{val}; 11 | 12 | 13 | 14 | <%shared> 15 | my $DEBUG = 0; 16 | 17 | 18 | <%perl> 19 | 20 | 21 | if ( $DEBUG ){ 22 | use Data::Dumper; 23 | print "
 ", Dumper(%ARGS), "

"; 24 | print &closet_floor_search("end_id", "14"); 25 | } else { 26 | do "jsrsServer.pm"; 27 | jsrsDispatch("closet_floor_search"); 28 | } 29 | 30 | 31 | sub closet_floor_search { 32 | # Arguments: 33 | # - field: Form element to add the results into 34 | # - val: Criteria. The ID of the floor to query for closets 35 | 36 | my $field = shift; 37 | my $val = shift; 38 | 39 | my @terms; 40 | 41 | if ($val =~ /\w+/) { 42 | if ($val =~ /\w+\s+\w+/) { 43 | # if there's more than one word 44 | @terms = split /\s+/, $val; 45 | } else { 46 | $val =~ s/\s+//; 47 | push @terms, $val; 48 | } 49 | } 50 | 51 | 52 | my @results = (); 53 | my $floor_id = $terms[0]; 54 | my $floor; 55 | 56 | if ( $floor = Floor->retrieve($floor_id) ){ 57 | foreach my $room ($floor->rooms) { 58 | foreach my $closet ($room->closets) { 59 | push (@results, $closet); 60 | } 61 | } 62 | } 63 | 64 | my $response = $field."&"; 65 | 66 | @results = sort { $a->name cmp $b->name } @results; 67 | @results = sort { $a->room->name cmp $b->room->name } @results; 68 | 69 | $response .= "0=".$ui->url_encode("No matches") unless (scalar(@results)); 70 | 71 | if (scalar(@results)) { 72 | $response .= "0=-- Select --&"; 73 | foreach my $closet (@results) { 74 | $response .= $closet->id."=".$ui->url_encode($closet->name." (Room ".$closet->room->name.")")."&"; 75 | } 76 | } 77 | 78 | return $response; 79 | } 80 | 81 | 82 | -------------------------------------------------------------------------------- /htdocs/generic/confirm.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Generic confirmation dialog. Meant to be called from other components 4 | in order to ask for confirmation of a certain action. 5 | 6 | 7 | 8 | <%args> 9 | $target # This is the original component that needs input 10 | $message => undef # Message to be displayed for confirmation 11 | $sid => undef # Session ID 12 | $submit => undef # Controls execution flow 13 | 14 | 15 | <%init> 16 | my $DEBUG = 0; 17 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 18 | 19 | 20 | <%perl> 21 | if ( $submit && ($submit eq 'confirm') ){ 22 | $m->comp('/generic/error.mhtml', error=>"Missing required session id") 23 | unless ( $sid ); 24 | my $sess = $ui->get_session($sid); 25 | map { $ARGS{$_} = $sess->{$_} } keys %$sess; 26 | 27 | print '%ARGS after recovering session is
', Dumper(%ARGS), '

' if $DEBUG; 28 | 29 | # Now back to the calling component 30 | # Make sure to delete our own args 31 | foreach my $arg ( qw(message target sid) ){ 32 | delete $ARGS{$arg}; 33 | } 34 | $m->comp($target, %ARGS); 35 | }else{ 36 | $m->comp('/generic/error.mhtml', error=>"Missing required arguments: message, target") 37 | unless ( $message && $target ); 38 | 39 | # Create a session with current arguments 40 | my $sess = $ui->mk_session(); 41 | while ( my($k,$v) = each %ARGS ){ 42 | $sess->{$k} = $v; 43 | } 44 | my $sid = $sess->{_session_id}; 45 | 46 | 47 |
48 |
Confirm Action
49 |
50 |
51 |

<% $message %>

52 |

53 | 54 | 55 | 56 | 57 |

58 |
59 |
60 |
61 | 62 | <%perl> 63 | # We need to stop execution of the calling component 64 | $m->abort; 65 | 66 | 67 | %} 68 | -------------------------------------------------------------------------------- /htdocs/generic/data_table.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Displays a table for showing rows of data 4 | 5 | example data: 6 | -------------------------------------------------------- 7 | | Address | Status | Name | 8 | -------------------------------------------------------- 9 | | 192.168.56.5 | Static | vlan56-5.mydomain.com | 10 | | 192.168.56.5 | Static | vlan56-5.mydomain.com | 11 | | 192.168.56.5 | Static | vlan56-5.mydomain.com | 12 | | 192.168.56.5 | Static | vlan56-5.mydomain.com | 13 | -------------------------------------------------------- 14 | 15 | Arguments: 16 | field_headers - array of captions to show on the top row 17 | data - array of array references to show in the rows 18 | subclass - use class "datatabler1_subclass" in the stylesheet 19 | rowstyle - array of style parameters for all columns in a row (any css) 20 | style - array of style parameters for columns (any css). Overrides rowstyle. 21 | 22 | 23 | <%args> 24 | @field_headers => undef; 25 | @data => (); 26 | $subclass => ""; 27 | @style => (); 28 | @rowstyle => (); 29 | 30 | 31 | % if( $subclass ) { $subclass = '_'.$subclass; } 32 | 33 | 34 | 35 | 36 | % if ( @style ){ 37 | % for (my $i=0; $i < scalar @field_headers; $i++) { 38 | 39 | % } 40 | % }else{ 41 | % foreach (@field_headers) { 42 | 43 | % } 44 | % } 45 | 46 | 47 | % my $i = 0; 48 | % my $toggle = 1; 49 | % foreach my $row ( @data ) { 50 | % ($toggle %= 2) += 1; 51 | 52 | % if ( @style ){ 53 | % for (my $j=0; $j < scalar @$row; $j++) { 54 | 55 | % } 56 | % }elsif ( @rowstyle ){ 57 | % foreach (@$row) { 58 | 59 | % } 60 | % }else{ 61 | % foreach (@$row) { 62 | 63 | % } 64 | % } 65 | % $i++; 66 | 67 | % } 68 | 69 |
<% $field_headers[$i] %><% $_ %>
<% $row->[$j] %><% $_ %><% $_ %>
70 | -------------------------------------------------------------------------------- /htdocs/generic/descr.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Show Database Table or Column descriptions. This provides context help. 4 | 5 | 6 | % 7 | % 8 | % 9 | <%args> 10 | $table 11 | $col => undef; 12 | 13 | % 14 | <%attr> 15 | title => 'Help' 16 | 17 | % 18 | <%init> 19 | my $DEBUG = 0; 20 | my @field_headers; 21 | my @cell_data; 22 | my $table_help = $ui->table_descr_link($table, $table); 23 | if ( $col ){ 24 | my $mcol = $table->meta_data->get_column($col); 25 | my $descr = $mcol->descr(); 26 | my $tag = $mcol->tag(); 27 | my $type = $mcol->sql_type(); 28 | @field_headers = ( 'Table:', 'Column Name:', 'Column Label:', 'Column Type', 'Description:' ); 29 | @cell_data = ( $table_help, $col, $tag, $type, $descr ); 30 | if ( my $ftname = $mcol->links_to ){ 31 | push @field_headers, "References:"; 32 | push @cell_data, $ui->table_descr_link($ftname, $ftname); 33 | } 34 | }else{ 35 | my $mtable = $table->meta_data; 36 | my $descr = $mtable->descr(); 37 | my @cols = grep !/^id/, $mtable->get_column_names; 38 | my @clinks = map { $ui->col_descr_link($table, $_, $_) } @cols; 39 | my $clinks = join ', ', @clinks; 40 | @field_headers = ( 'Table:', 'Description:', 'Columns:' ); 41 | @cell_data = ( $table, $descr, $clinks ); 42 | } 43 | 44 | $m->clear_buffer; 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
55 |
Help
56 |
57 | 58 |

59 | 60 | <& /generic/attribute_table.mhtml, field_headers=>\@field_headers, data=>\@cell_data, 61 | width=>"1", headercolwidth=>"15%", datacolwidth=>"35%" &> 62 | 63 |

64 | [<<] 65 |  [close] 66 |
67 | 68 |
69 |
70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /htdocs/generic/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | -------------------------------------------------------------------------------- /htdocs/generic/display_bin.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Used for displaying binary content. For example, to display an image 3 | you can: 4 | 1) Invoke this page directly with an id to display, or; 5 | 2) Embed a reference to this page in another page, for example: 6 | 7 | 8 | This currently assumes "filetype" in the database represents the 9 | objects mime type. 10 | 11 | 12 | <%args> 13 | $table 14 | $id 15 | 16 | 17 | <%init> 18 | my $binfile = $table->retrieve($id); 19 | $m->comp("/generic/error.mhtml", error=>"$table id $id could not be retrieved") unless ( $binfile ); 20 | $m->comp("/generic/error.mhtml", error=>"$table id $id has no filetype") unless ( $binfile->filetype ); 21 | $m->comp("/generic/error.mhtml", error=>"$table id $id has no data") unless ( $binfile->bindata ); 22 | 23 | $m->clear_buffer; # Do not print headers 24 | $r->content_type($binfile->filetype); 25 | $m->print($binfile->bindata); 26 | $m->abort("OK"); # Do not print footers 27 | 28 | 29 | -------------------------------------------------------------------------------- /htdocs/generic/dynamic_list_query.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | ############################################################################### 3 | # backend code for most asynchronous javascript queries 4 | ############################################################################### 5 | 6 | 7 | <%args> 8 | $table => $ARGS{table}; 9 | $field => $ARGS{field}; 10 | $val => $ARGS{crit}; 11 | $search_field => $ARGS{search_field}; 12 | $caller => $ARGS{self}; 13 | 14 | 15 | <%init> 16 | my @terms; 17 | my $DEBUG = 0; 18 | my $MAX = $ui->config->get('DEFAULT_SELECTMAX'); 19 | 20 | 21 | 22 | <%perl> 23 | 24 | print "
 ", Dumper(%ARGS), "

" if $DEBUG; 25 | 26 | if ($val =~ /\w+/) { 27 | if ($val =~ /\w+\s+\w+/) { 28 | # if there's more than one word 29 | @terms = split /\s+/, $val; 30 | } else { 31 | $val =~ s/\s+//; 32 | push @terms, $val; 33 | } 34 | 35 | print "terms are: ", join ', ', @terms, "
" if $DEBUG; 36 | } 37 | 38 | 39 | 40 | 41 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /htdocs/generic/error.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | (Slightly more) user-friendly error messages 4 | 5 | 6 | 7 | 8 | <%args> 9 | $error 10 | $user => $ui->get_current_user($r) 11 | $showplainerror => 0 12 | 13 | 14 | <%init> 15 | my $caller = $m->caller->name; 16 | my $err_msg; 17 | my $trace; 18 | # 19 | # Try to customize the error message depending on the nature of the error. 20 | # 21 | # Fatal errors could be caused by bugs in the code, or by invalid user input 22 | # we want to hide the stack trace, but if the user believes it is a bug 23 | # we want the user to report it to their netdot administrator, who may submit a bug 24 | # report to us. This may be either a Netdot Fatal exception or a Mason Exception 25 | 26 | if ( ref($error) =~ /Netdot::Util::Exception/ ){ 27 | if ( $error->isa_netdot_exception('Fatal') ){ 28 | # Let's separate the error message from the stack trace 29 | $trace = $error->trace->as_string; 30 | } 31 | $err_msg = $error->error; 32 | }else{ 33 | $err_msg = $error; 34 | } 35 | 36 | 37 | 38 | % if ( !$showplainerror ) { 39 |
40 |
41 |
Error
42 |
43 | % } 44 | 45 |

46 | <% $caller %> produced the following error: 47 |

48 |

49 | 
50 | <% $err_msg %>
51 | 
52 | 
53 | 54 | % if ( $trace ){ 55 | 56 |

57 | This may be the result of invalid user input. However, if you believe this is a bug, please click here, then copy the full error message and send it to 58 | <% Netdot->config->get('ADMINEMAIL') %> 59 |

60 | 61 | 62 | 63 | % }else{ 64 |

65 | Please go back and try again. 66 |

67 | % } 68 | 69 | % if( !$showplainerror ) { 70 |
71 |
72 |
73 | % } 74 | 75 | <%perl> 76 | # Abort execution of the caller 77 | $m->abort; 78 | 79 | -------------------------------------------------------------------------------- /htdocs/generic/hostlist.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | A wrapper for hostlist.mhtml used when paging results. 3 | 4 | 5 | 6 | 7 |
8 |
9 | % $m->comp('/management/hostlist.mhtml', %ARGS ); 10 |
11 |
12 | -------------------------------------------------------------------------------- /htdocs/generic/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Intentionally empty. Just triggers the autohandler. This file 3 | could be eliminated by setting up HTML::Mason to handle directory 4 | requests, I think. 5 | -------------------------------------------------------------------------------- /htdocs/generic/jsrs_retrieve_all.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Performs retrieve_all queries whose return values are used to fill in objects in HTML pages 4 | via asynnchronous javascript calls. 5 | 6 | 7 | 8 | 9 | <%flags> 10 | inherit => undef 11 | 12 | 13 | <%shared> 14 | my $DEBUG = 0; 15 | 16 | 17 | <%args> 18 | $table => undef 19 | $form_field => 'form_field' 20 | 21 | 22 | <%perl> 23 | if ( $DEBUG ){ 24 | use Data::Dumper; 25 | print "
 ", Dumper(%ARGS), "

"; 26 | if ( $table ){ 27 | print &retrieve_all($table, $form_field); 28 | } 29 | }else{ 30 | # Do not use 'require' here. 31 | # We need to make sure the file is read *each time* 32 | do "jsrsServer.pm"; 33 | jsrsDispatch("retrieve_all"); 34 | } 35 | 36 | 37 | # Arguments: 38 | # - table: Table to search. 39 | # - form_field: Name of the form field to add the results into 40 | sub retrieve_all { 41 | my ( $table, $form_field ) = @_; 42 | my $response = $form_field."&"; 43 | my $MAX = $ui->config->get('DEFAULT_SELECTMAX'); 44 | $response .= "null=-- Select --&"; 45 | 46 | if ( $table eq 'Ipblock' ){ 47 | my $dbh = Netdot::Model->db_Main(); 48 | my $rows = $dbh->selectall_arrayref("SELECT id,version,address,prefix 49 | FROM ipblock 50 | WHERE (version=4 AND prefix!=32) 51 | OR (version=6 AND prefix!=128) 52 | ORDER BY address"); 53 | 54 | if ( my $n = scalar @$rows ){ 55 | if( $n <= $MAX ){ 56 | foreach my $row ( @$rows ){ 57 | my ($id, $version, $intaddr, $prefix) = @$row; 58 | my $address = Ipblock->int2ip($intaddr, $version); 59 | my $lbl = $address.'/'.$prefix; 60 | $response .= $id."=".$ui->url_encode($lbl)."&"; 61 | } 62 | }else{ 63 | $response .= "null=".$ui->url_encode("More than ".$MAX." matches.")."&"; 64 | $response .= "null=".$ui->url_encode("Refine search."); 65 | } 66 | }else{ 67 | $response .= "null=".$ui->url_encode("No matches"); 68 | } 69 | }else{ 70 | my @rows = $table->retrieve_all(); 71 | 72 | if ( my $n = scalar @rows ){ 73 | if( $n <= $MAX){ 74 | my $count = 0; 75 | my @objs = sort { $a->get_label cmp $b->get_label } @rows; 76 | foreach my $o ( @objs ){ 77 | my $lbl = $o->get_label(); 78 | $response .= $o->id."=".$ui->url_encode($lbl)."&"; 79 | } 80 | }else{ 81 | $response .= "null=".$ui->url_encode("More than ".$MAX." matches.")."&"; 82 | $response .= "null=".$ui->url_encode("Refine search."); 83 | } 84 | }else{ 85 | $response .= "null=".$ui->url_encode("No matches"); 86 | } 87 | } 88 | 89 | return $response; 90 | } 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /htdocs/generic/list.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | A wrapper for sortresults.html used when paging results. 3 | 4 | 5 | 6 | 7 |
8 |
9 | % $m->comp('sortresults.mhtml', %ARGS ); 10 |
11 |
12 | -------------------------------------------------------------------------------- /htdocs/generic/no_search_criteria.html: -------------------------------------------------------------------------------- 1 | %##########################################################################3 2 | %# 3 | %# No Search Criteria 4 | %# 5 | %##########################################################################3 6 | 7 |
8 |
9 | Error 10 |
11 |
12 |

No search criteria 13 |

14 |
15 | 16 | -------------------------------------------------------------------------------- /htdocs/generic/no_search_results.html: -------------------------------------------------------------------------------- 1 | %##########################################################################3 2 | %# 3 | %# No Results 4 | %# 5 | %##########################################################################3 6 | 7 | 8 | <%args> 9 | $search => undef 10 | 11 | 12 |
13 |
14 | No results 15 |
16 |
17 |

<% $search %> not found 18 |

19 |
20 | 21 | % $m->abort; 22 | 23 | 24 | -------------------------------------------------------------------------------- /htdocs/generic/search.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Performs a general search in the database, looking into every field of every table. 4 | 5 | 6 | 7 | 8 | <%args> 9 | $q => undef 10 | 11 | 12 | <%init> 13 | 14 | my %linksto; 15 | my $results; 16 | my $numtbls; 17 | my $DEBUG = 0; 18 | 19 | if ( defined $q ){ 20 | eval { 21 | $results = Netdot::Model->search_all_tables($q); 22 | }; 23 | if ( my $e = $@ ){ 24 | $m->comp("/generic/error.mhtml", error=>$e); 25 | } 26 | if ( $DEBUG ) { 27 | print "
", Dumper($results), "
"; 28 | $m->abort; 29 | } 30 | $numtbls = scalar keys %$results; 31 | } 32 | 33 | 34 | 35 |
36 | 37 |
38 | Netdot General Search 39 | % if ( $numtbls ){ 40 |
Found matches in <% $numtbls %> tables: 41 | % } 42 |
43 |
44 |
45 | 46 | 47 |
48 |
49 | 50 | % if( $numtbls < 1 || ! %$results ) { 51 |
52 | No matching records were found. 53 |
54 | % } else { 55 | % foreach my $tbl ( sort { $a cmp $b } keys %$results ) { 56 | % my @objs; 57 | % map { push @objs, $results->{$tbl}->{$_} } keys %{ $results->{$tbl} }; 58 |
59 |
<% $tbl %>
60 |
 
61 |
62 | <& sortresults.mhtml, table => $tbl, object => \@objs, view => "row", withedit => 1 &> 63 |
64 |
65 | 66 | % } # end foreach tbl 67 | % } # end else 68 | 69 |
70 | -------------------------------------------------------------------------------- /htdocs/generic/show_search_results.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Show search results. Used by several components. 4 | 5 | 6 | 7 | 8 | <%args> 9 | $list => undef 10 | $search => undef 11 | $dowindow => undef 12 | 13 | 14 |
15 |
16 | <% scalar(@$list) %> results for <% $search %> 17 |
 
18 |
19 | <& /generic/sortresults.mhtml, object=>$list, withedit=>1, dowindow=>$dowindow &> 20 |
21 |
22 | 23 | -------------------------------------------------------------------------------- /htdocs/generic/subnet_zone_query.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | ############################################################################### 3 | # A customized version of the generic dynamic_list_query.html 4 | ############################################################################### 5 | 6 | 7 | 8 | <%args> 9 | $field => $ARGS{field}; 10 | $val => $ARGS{val}; 11 | 12 | 13 | <%shared> 14 | my $DEBUG = 0; 15 | 16 | 17 | <%perl> 18 | 19 | if ( $DEBUG ){ 20 | use Data::Dumper; 21 | print "
 ", Dumper(%ARGS), "

"; 22 | } else { 23 | do "jsrsServer.pm"; 24 | jsrsDispatch("subnet_zone_search"); 25 | } 26 | 27 | sub subnet_zone_search { 28 | # Arguments: 29 | # - field: Form element to add the results into 30 | # - val: Criteria. The ID of the floor to query for closets 31 | 32 | my $field = shift; 33 | my $val = shift; 34 | my @results = (); 35 | 36 | if ( my $subnet = Ipblock->retrieve($val) ){ 37 | @results = $subnet->forward_zone(); 38 | } 39 | 40 | my $response = $field."&"; 41 | 42 | @results = sort { $a->name cmp $b->name } @results; 43 | 44 | $response .= "0=".$ui->url_encode("No matches") unless (scalar(@results)); 45 | 46 | if (scalar(@results)) { 47 | foreach my $zone (@results) { 48 | $response .= $zone->id."=".$ui->url_encode($zone->name)."&"; 49 | } 50 | } 51 | return $response; 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /htdocs/generic/table.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Simple component to display all tables in a pretty table. 4 | 5 | Arguments: 6 | 7 | width - width of the table (# of columns) (default = 2) 8 | link - page to go to for HREFs 9 | title - title of the table 10 | 11 | 12 | 13 | <%args> 14 | $width => 2 15 | $link => "browse.html" 16 | $title => undef 17 | 18 | 19 | <%init> 20 | my @tbls; 21 | my $max; 22 | my $j = 0; 23 | 24 | 25 | 26 | <%perl> 27 | map { push @tbls, $_ } sort { $a cmp $b } $ui->meta->get_table_names; 28 | $max = scalar( @tbls ); 29 | 30 | 31 |
32 |
<% $title %>
33 |
34 | 35 | 36 | % for (my($i)=0; $i < $max; $i++ ) { 37 | % if( $i % $width == 0 && $i != 0 ) { 38 | 39 | 40 | % } 41 | 42 | % if( ( ( $i ) % $width ) < ( $max % $width ) ) { 43 | % $j += int( $max / $width ) + 1; 44 | % } else { 45 | % $j += int( $max / $width ); 46 | % } 47 | % if( $j >= $max ) { 48 | % $j -= ( $max - 1 ); 49 | % } 50 | % } 51 | 52 |
<% $tbls[$j] %>
53 |
54 |
55 | -------------------------------------------------------------------------------- /htdocs/generic/user_pref.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | user_pref.html 3 | 4 | Saves the specified attribute in the user object. 5 | This is used by asynchronous javascript calls to set user attributes 6 | without reloading the page. 7 | 8 | 9 | 10 | <%flags> 11 | inherit => undef 12 | 13 | 14 | <%perl> 15 | 16 | do "jsrsServer.pm"; 17 | jsrsDispatch("set_value"); 18 | 19 | sub set_value { 20 | my $attr = shift; 21 | my $value = shift; 22 | my $user = $ui->get_current_user($r); 23 | 24 | $user->setAttribute($r, $attr, $value); 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /htdocs/generic/wrapping_table.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Prints out the contents of an array in a table with $cols columns. 3 | 4 | Arguments: 5 | data - array of arrays to show in the rows 6 | cols - number of columns 7 | 8 | 9 | 10 | <%args> 11 | @data => undef; 12 | $cols => 4; 13 | 14 | 15 | <%init> 16 | my $nfields = scalar (@data); 17 | my $nrows = ( $nfields % $cols == 0 ) ? $nfields/$cols : int($nfields/$cols)+1; 18 | my $pos = 0; 19 | my $colwidth = int(100/$cols); 20 | 21 | 22 | 23 | 24 | 25 | % for ( my($w)=1; $w <= $cols; $w++ ){ 26 | 38 |
27 | 28 | % for ( my($r)=1; $r <= $nrows; $r++ ){ 29 | 30 | 31 | 32 | % $pos++; 33 | % } 34 | 35 |
<% $data[$pos] %>
36 | % } 37 |
39 | -------------------------------------------------------------------------------- /htdocs/help/autohandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Help Section 4 | 5 | 6 | 7 | <%args> 8 | $user => $ui->get_current_user($r); 9 | 10 | 11 | <%attr> 12 | title => 'Netdot Help' 13 | section => 'Help' 14 | 15 | 16 | <%shared> 17 | my $PAGE_ATTRIBUTE = "HELP_PAGE"; 18 | my $SECTION = "Help"; 19 | 20 | 21 | <%init> 22 | my %caller_args = $m->caller_args(-1); 23 | 24 | if (exists($caller_args{page})){ 25 | $user->setAttribute($r, "$PAGE_ATTRIBUTE", $caller_args{page}); 26 | } 27 | 28 | my $page = $user->getAttribute("$PAGE_ATTRIBUTE"); 29 | 30 | 31 | <%method .section_meta_data> 32 | <%doc> 33 | Returns the meta data used to generate this sections header in section1.mhtml 34 | 35 | <%init> 36 | return { 37 | section => $SECTION, 38 | page => 'help/', 39 | title => 'Help', 40 | attribute => $PAGE_ATTRIBUTE, 41 | sub_sections => [ 42 | { section => 'MANUAL', title => 'User Manual' }, 43 | { section => 'DATABASE', title => 'Database Help' }, 44 | ], 45 | }; 46 | 47 | 48 | 49 | <%perl> 50 | 51 | if ($page eq "MANUAL") { 52 | $m->comp("manual.html"); 53 | 54 | }elsif ($page eq "DATABASE") { 55 | 56 |
57 |
Database Help
58 |
59 | 60 |
61 | Database Relationships (HTML)
62 | Displays a HTML table with the Netdot database schema.
63 | 64 |
65 | Database Relationships (GraphViz)
66 | Displays a GraphViz graph of the Netdot database schema.
67 | 68 |
69 |
70 | 71 |
72 |
73 | <%perl> 74 | } 75 | 76 | if ( $m->fetch_next ){ 77 | $m->call_next; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /htdocs/help/database-graph.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Graph the database using GraphViz 3 | 4 | 5 | <%args> 6 | 7 | 8 | <%init> 9 | use Netdot::Meta::SQLT; 10 | 11 | my $sqlt = Netdot::Meta::SQLT->new(); 12 | 13 | my $netdot_path = Netdot->config->get('NETDOT_PATH'); 14 | my $graph_path = "img/graphs/schema.png"; 15 | my $out_file = "$netdot_path/htdocs/" . $graph_path; 16 | 17 | $sqlt->graphviz_schema(out_file=>$out_file, output_type=>"png", width=>40, height=>30); 18 | 19 | my $web_path = $r->dir_config('NetdotPath'); 20 | my $img = $web_path . $graph_path; 21 | 22 | 23 | 24 |
25 |
Netdot Schema
26 |
27 |

Click on image to view full size

28 |

29 | Database Relationships 30 |

31 |
32 |
33 | -------------------------------------------------------------------------------- /htdocs/help/database-rels.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | 4 | <%args> 5 | 6 | 7 | <%init> 8 | use Netdot::Meta::SQLT; 9 | my $sqlt = Netdot::Meta::SQLT->new(); 10 | 11 | 12 | 13 |
14 |
Netdot Schema
15 |
16 | % print $sqlt->html_schema(); 17 |
18 |
19 | -------------------------------------------------------------------------------- /htdocs/help/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | -------------------------------------------------------------------------------- /htdocs/help/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Intentionally empty. Just triggers the autohandler. This file 3 | could be eliminated by setting up HTML::Mason to handle directory 4 | requests, I think. 5 | -------------------------------------------------------------------------------- /htdocs/img/calendar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvicente/Netdot/d83466264096dbc9c9f7ca75f814a8484600cdba/htdocs/img/calendar.gif -------------------------------------------------------------------------------- /htdocs/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvicente/Netdot/d83466264096dbc9c9f7ca75f814a8484600cdba/htdocs/img/favicon.ico -------------------------------------------------------------------------------- /htdocs/img/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvicente/Netdot/d83466264096dbc9c9f7ca75f814a8484600cdba/htdocs/img/title.png -------------------------------------------------------------------------------- /htdocs/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Netdot homepage 3 | 4 | 5 | <%args> 6 | 7 | $title => undef 8 | $user => $ui->get_current_user($r) 9 | 10 | <%init> 11 | my $default_page; 12 | 13 | if ( $user->getAttribute('USER_TYPE') eq 'Admin' || $user->getAttribute('USER_TYPE') eq 'Operator') { 14 | 15 | $default_page = $r->dir_config('NetdotPath') . "management/"; 16 | 17 | }elsif ( $user->getAttribute('USER_TYPE') eq 'User' ){ 18 | 19 | $default_page = $r->dir_config('NetdotPath') . "user_management/"; 20 | 21 | } 22 | 23 | 24 | % $m->redirect($default_page); 25 | 26 | -------------------------------------------------------------------------------- /htdocs/login.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Login Page 4 | 5 | 6 | 7 | <%attr> 8 | title => 'Netdot Login' 9 | 10 | 11 | <%init> 12 | my $message; 13 | my $netdot_path = $r->dir_config('NetdotPath'); 14 | my $main_page = $netdot_path . "index.html"; 15 | my $redirect_path = $main_page; 16 | my $submit_target = $netdot_path . "NetdotLogin"; 17 | 18 | # Unless they requested the login page directly while not logged in 19 | # (in which case prev isn't defined) they will have probably been 20 | # attempting to do something else. We try to let them continue doing it. 21 | if (defined $r->prev) { 22 | #$message = $r->prev->subprocess_env('AuthCookieReason') If they 23 | #really were just logging in they probably don't want to continue 24 | #to login ad nauseum. Also, logging in to logout page redirects to 25 | #index. 26 | unless ($r->prev->uri =~ m{/log(in|out).html} || $r->prev->uri =~ /NetdotLogin/ ) { 27 | $redirect_path = $r->prev->uri . ( $r->prev->args ? "?" . $r->prev->args : ""); 28 | } 29 | # We're assuming that NetdotPath contains a '/' at the end 30 | # but the URI in the query may or may not have it, so we try to catch that here 31 | my $path_wo_slash = $netdot_path; 32 | $path_wo_slash =~ s/\/$//; 33 | if ( $r->prev->uri eq $path_wo_slash ){ 34 | $redirect_path = $path_wo_slash . '/' . ( $r->prev->args ? "?" . $r->prev->args : ""); 35 | } 36 | } 37 | 38 | 39 | 40 | 41 |
42 | 43 | 51 | 52 |
53 | 54 |
55 |
56 | Please enter your login and password to authenticate. 57 |
58 |
59 |
60 |
61 | 62 |

63 | 64 | 65 |

66 |

67 | 68 | 69 |

70 |

71 | Remember me: 72 | 73 |

74 |

75 | 76 |

77 |
78 |
79 |
80 |
81 | 82 |
83 | 84 |
85 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /htdocs/logout.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Log out page 4 | 5 | 6 | 7 | <%attr> 8 | title => 'Netdot Logout' 9 | 10 | 11 | <%args> 12 | $user => $ui->get_current_user($r) 13 | 14 | 15 | <%init> 16 | if(defined($user) && $user->isa("Apache2::SiteControl::User")) { 17 | $user->logout($r); 18 | } 19 | 20 | $m->redirect("."); 21 | 22 | -------------------------------------------------------------------------------- /htdocs/management/choose_ip.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Present the user with a subnet block view to choose an IP address 3 | Inserts the option in the calling window select tag 4 | 5 | 6 | <%args> 7 | $subnet # Subnet ID 8 | $select_id # Caller select tag id 9 | 10 | 11 | <%init> 12 | $m->clear_buffer; 13 | my $o = Ipblock->retrieve($subnet); 14 | 15 | 16 | 17 | 18 | 19 | % my $js_prefix = $r->dir_config('NetdotPath') . "java_script"; 20 | % for my $script ( qw(dynamic_list select jsrsClient) ){ 21 | 22 | % } 23 | 24 | 33 | 34 | 35 | 36 | 37 |
38 |
Choose address in <% $o->get_label %>
39 |
40 | <& subnet.mhtml, network => $o &> 41 |
42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /htdocs/management/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | 3 | -------------------------------------------------------------------------------- /htdocs/management/i_arp.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Interface ARP entries for given timestamp 3 | 4 | % 5 | % 6 | <%attr> 7 | title => 'Interface' 8 | section => 'Management' 9 | 10 | % 11 | % 12 | <%args> 13 | $id 14 | $tstamp 15 | 16 | % 17 | % 18 | <%init> 19 | my $DEBUG = 0; 20 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 21 | my $obj = Interface->retrieve($id); 22 | my @arp = ArpCacheEntry->search_interface($id, $tstamp); 23 | 24 | 25 |
26 |
27 |
ARP entries in <% $obj->get_label %> at <% $tstamp %>
28 |
29 | <& /generic/sortresults.mhtml, object=>\@arp &> 30 |
31 |
32 |
33 | 34 | -------------------------------------------------------------------------------- /htdocs/management/i_fdb.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Interface FDB entries for given timestamp 3 | 4 | % 5 | % 6 | <%attr> 7 | title => 'Interface' 8 | section => 'Management' 9 | 10 | % 11 | % 12 | <%args> 13 | $id 14 | $tstamp 15 | 16 | % 17 | % 18 | <%init> 19 | my $DEBUG = 0; 20 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 21 | my $obj = Interface->retrieve($id); 22 | my @macs = PhysAddr->search_interface_macs($id,$tstamp); 23 | 24 | my (@headers, @rows); 25 | 26 | 27 |
28 |
29 |
MACs seen in <% $obj->get_label %> at <% $tstamp %>
30 |
31 | <& /generic/sortresults.mhtml, object=>\@macs &> 32 |
33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /htdocs/management/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Index page for the management subsection 3 | 4 | 5 | <%args> 6 | $page => undef 7 | 8 | 9 | <%perl> 10 | if ( $page eq "ADDRESS" ){ 11 | $m->comp('/management/ip.html', _action => "SHOW_ROOTS", rootversion => 'all'); 12 | } 13 | if ( $page eq "VLANS" ){ 14 | $m->comp('/management/vlan.html', _action => "SHOW_GROUPS"); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /htdocs/management/list_rights.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show a more concise list of access rights. 3 | It handles both UserRight and GroupRight objects 4 | 5 | 6 | <%args> 7 | $rights # Required. Array ref of UserRight and/or GroupRight objects 8 | $show_object => 1 # Optional. Determines if the object to which rights are assigned 9 | # should be shown in the list 10 | $add => undef # Show [add] button to add rights to each user or list. The value 11 | # is a URL containing caller arguments, in which the strings 12 | # SUBJECT and ID are replaced with person/contaclist id, which 13 | # are then good to pass to access_right_form.html 14 | 15 | 16 | 17 | <%init> 18 | my (@headers, @rows); 19 | push @headers, 'Type'; 20 | push @headers, 'Name'; 21 | push @headers, 'Object' if $show_object; 22 | push @headers, 'Rights'; 23 | push @headers, 'Actions' if $add; 24 | 25 | my %anames = $ui->get_access_names(); 26 | my $DEBUG = 0; 27 | 28 | use Data::Dumper; 29 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 30 | 31 | 32 | <%perl> 33 | my %r; 34 | foreach my $right ( @$rights ){ 35 | my $class = ref($right); 36 | my $type = ($class =~ /User/o)? 'User' : 'Group'; 37 | my $ar = $right->accessright; 38 | my $name; 39 | if ( $type eq 'User' ){ 40 | my $person = $right->person; 41 | $name = $person->get_label; 42 | $r{$name}{person} = $person; 43 | }else{ 44 | my $contactlist = $right->contactlist; 45 | $name = $contactlist->get_label; 46 | $r{$name}{contactlist} = $contactlist; 47 | } 48 | $r{$name}{type} = $type; 49 | $r{$name}{rights}{$ar->access} = $ar; 50 | if ( $show_object ){ 51 | my $oclass = $ar->object_class; 52 | my $oid = $ar->object_id; 53 | my $o = $oclass->retrieve($oid); 54 | $r{$name}{object} = $o; 55 | } 56 | } 57 | 58 | print '%r is
', Dumper(%r), '

' if $DEBUG; 59 | 60 | foreach my $name ( sort keys %r ){ 61 | my @row; 62 | push @row, $r{$name}{type}; 63 | my $subject = $r{$name}{person} || $r{$name}{contactlist}; 64 | push @row, sprintf('%s', 65 | $subject->short_class, $subject->id, $name); 66 | if ( $show_object ){ 67 | my $o = $r{$name}{object}; 68 | push @row, sprintf('%s', 69 | $o->short_class, $o->id, $o->get_label); 70 | } 71 | push @row, join(', ', map { $anames{$_} } sort keys %{$r{$name}{rights}}); 72 | if ( $add ){ 73 | my $add_txt = $add; 74 | my $subject = ($r{$name}{type} eq 'User')? 'person' : 'contactlist'; 75 | my $id = $r{$name}{$subject}->id; 76 | $add_txt =~ s/SUBJECT/$subject/; 77 | $add_txt =~ s/ID/$id/; 78 | my $t = sprintf('%s', $add_txt, '[add]'); 79 | push @row, $t ; 80 | } 81 | push @rows, \@row; 82 | } 83 | 84 | $m->comp('/generic/data_table.mhtml', field_headers=>\@headers, data=>\@rows); 85 | 86 | -------------------------------------------------------------------------------- /htdocs/management/live_results.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Show results from Live address search 4 | 5 | 6 | % 7 | % 8 | % 9 | <%args> 10 | $info 11 | 12 | % 13 | <%init> 14 | my $DEBUG = 0; 15 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 16 | 17 | 18 | <%perl> 19 | my (@headers, @data) = (); 20 | if ( $info->{mac} ){ 21 | push @headers, 'MAC Address'; 22 | push @data, $info->{mac}; 23 | 24 | if ( $info->{vendor} ){ 25 | push(@headers, 'Vendor'); 26 | push(@data, $info->{vendor}); 27 | } 28 | } 29 | if ( $info->{ip} ){ 30 | push @headers, 'IP Address'; 31 | push @data, $info->{ip}; 32 | if ( $info->{dns} ){ 33 | push(@headers, 'DNS'); 34 | push(@data, $info->{dns}); 35 | } 36 | } 37 | 38 | % if ( @headers && @data ){ 39 |
40 |
Live Search Results
41 |
42 | <& /generic/attribute_table.mhtml, field_headers=>\@headers, data=>\@data, 43 | width=>"1", headercolwidth=>"25%", datacolwidth=>"75%" &> 44 |
45 |
46 | % } 47 | 48 | % if ( $info->{edge} ){ 49 | % my $iface = Interface->retrieve($info->{edge}); 50 |
51 |
Edge Port
52 |
53 | <& /generic/sortresults.mhtml, object=>[$iface], view=>"row" &> 54 |
55 |
56 | % } 57 | 58 | <%perl> 59 | if ( $info->{routerports} ){ 60 | my @rows; 61 | foreach my $iid ( keys %{$info->{routerports}} ){ 62 | my $iface = Interface->retrieve($iid); 63 | my $lbl = $iface->get_label; 64 | my $ilnk = "$lbl"; 65 | my $ip = (keys %{$info->{routerports}{$iid}})[0]; 66 | my $mac = $info->{routerports}{$iid}{$ip}; 67 | push @rows, [$ip, $mac, $ilnk]; 68 | } 69 | 70 |
71 |
Router Ports
72 |
73 | <& /generic/data_table.mhtml, field_headers=>['IP', 'MAC', 'Interfaces'], data=>\@rows &> 74 |
75 |
76 | % } 77 | 78 | <%perl> 79 | if ( $info->{switchports} ){ 80 | my @rows; 81 | foreach my $i ( keys %{$info->{switchports}} ){ 82 | my $iface = Interface->retrieve($i); 83 | push @rows, $iface; 84 | } 85 | 86 |
87 |
Switch Ports
88 |
89 | <& /generic/sortresults.mhtml, object=>\@rows, view=>"row" &> 90 |
91 |
92 | % } 93 | -------------------------------------------------------------------------------- /htdocs/management/tree.mhtml: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show a tree representation of the address space of the given container or subnet. 3 | 4 | 5 | <%args> 6 | $network 7 | 8 | 9 | <%init> 10 | my $DEBUG = 0; 11 | my $list = $network->get_descendants(no_addresses=>1); 12 | if ( $DEBUG ){ 13 | print "
";
14 |     print Dumper($list);
15 |     print "
"; 16 | } 17 | 18 | print $ui->build_ip_tree_graph_html(id=>$network->id, list=>$list, web_path=>$r->dir_config('NetdotPath')); 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /htdocs/reports/addr_poll_stats.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Device Polling Statistics - Addresses 3 | 4 | 5 | <%attr> 6 | title => "Reports: Network Addresses" 7 | meta_refresh => 3600 8 | 9 | 10 | <%args> 11 | 12 | 13 | <%init> 14 | my $web_path = $r->dir_config('NetdotPath'); 15 | 16 | 17 |
18 |
Network Address Statistics
19 |
20 | 21 |

Number of end-node MAC and IP addresses seen when polling devices for ARP caches and forwarding tables: 22 | 23 |

24 |

25 | % print $ui->rrd_graph(type=>'addr', period=>'-1d', web_path=>$web_path, img=>"1d_addr_stats.png", title=>"Last day"); 26 |

27 | % print $ui->rrd_graph(type=>'addr', period=>'-1w', web_path=>$web_path, img=>"1w_addr_stats.png", title=>"Last Week"); 28 |

29 | % print $ui->rrd_graph(type=>'addr', period=>'-1m', web_path=>$web_path, img=>"1m_addr_stats.png", title=>"Last Month"); 30 |

31 | % print $ui->rrd_graph(type=>'addr', period=>'-1y', web_path=>$web_path, img=>"1y_addr_stats.png", title=>"Last Year"); 32 |

33 |
34 |
35 | -------------------------------------------------------------------------------- /htdocs/reports/dev_poll_stats.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Device Polling Statistics - Devices 3 | 4 | 5 | <%args> 6 | 7 | 8 | <%attr> 9 | title => "Reports: Devices Polled" 10 | meta_refresh => 3600 11 | 12 | 13 | <%init> 14 | my $web_path = $r->dir_config('NetdotPath'); 15 | 16 | 17 |
18 |
Polled Device Statistics
19 |
20 | 21 |

Number of devices polled for ARP caches and forwarding tables: 22 | 23 |

24 |

25 | % print $ui->rrd_graph(type=>'dev', period=>'-1d', web_path=>$web_path, img=>"1d_dev_stats.png", title=>"Last day"); 26 |

27 | % print $ui->rrd_graph(type=>'dev', period=>'-1w', web_path=>$web_path, img=>"1w_dev_stats.png", title=>"Last Week"); 28 |

29 | % print $ui->rrd_graph(type=>'dev', period=>'-1m', web_path=>$web_path, img=>"1m_dev_stats.png", title=>"Last Month"); 30 |

31 | % print $ui->rrd_graph(type=>'dev', period=>'-1y', web_path=>$web_path, img=>"1y_dev_stats.png", title=>"Last Year"); 32 |

33 |
34 |
35 | -------------------------------------------------------------------------------- /htdocs/reports/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | -------------------------------------------------------------------------------- /htdocs/reports/downtime.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Devices in downtime 3 | 4 | 5 | <%attr> 6 | title => 'Devices in Downtime' 7 | section => 'Reports' 8 | 9 | 10 | <%args> 11 | 12 | 13 | 14 | <%init> 15 | my $DEBUG = 0; 16 | if ( $DEBUG ){ 17 | print '%ARGS is
', Dumper(%ARGS), '

'; 18 | } 19 | my @devices = Device->get_within_downtime(); 20 | 21 | 22 | 23 |
24 |
Devices within downtime
25 |
26 | % if( @devices ){ 27 | <& ../generic/sortresults.mhtml, table => 'Device', object=>\@devices, view => "row", withdelete => 1, withedit => 1 &> 28 | % }else{ 29 | None 30 | % } 31 |
32 |
33 | 34 | -------------------------------------------------------------------------------- /htdocs/reports/duplex.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show duplex mismatches 3 | 4 | % 5 | % 6 | <%attr> 7 | title => 'Duplex Mismatches' 8 | section => 'Management' 9 | 10 | % 11 | % 12 | <%args> 13 | 14 | % 15 | % 16 | <%init> 17 | my $DEBUG = 0; 18 | print "
", Dumper(%ARGS), "

" if $DEBUG; 19 | 20 | my $list = Interface->find_duplex_mismatches(); 21 | my @cssitem = ("formtablec1", "formtablec2"); 22 | my $ci = 1; 23 | 24 | 25 | 26 |
27 |
Duplex/Speed Mismatches:
28 |
 
29 |
30 | % if ( !scalar(@$list) ){ 31 |

No mismatches found.

32 | % }else{ 33 | 34 | 35 | % foreach ('Interface', 'Admin Duplex', 'Oper Duplex', 'Speed'){ 36 | 37 | % } 38 | 39 | % foreach my $pair ( @$list ){ 40 | % $ci = ($ci + 1) % 2; 41 | % foreach my $id ( @$pair ){ 42 | % my $int = Interface->retrieve($id) || die "Can't retrieve Interaface id: $id"; 43 | 44 | 45 | 46 | 47 | 48 | 49 | % } 50 | 51 | % } 52 |
<% $_ %>
<% $int->get_label %><% $int->admin_duplex %><% $int->oper_duplex %><% $int->speed_pretty %>

53 | % } 54 |
55 |
56 | -------------------------------------------------------------------------------- /htdocs/reports/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Intentionally empty. Just triggers the autohandler. This file 3 | could be eliminated by setting up HTML::Mason to handle directory 4 | requests, I think. 5 | -------------------------------------------------------------------------------- /htdocs/reports/macs_by_vendor.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | MAC address Report 3 | 4 | arguments: 5 | topn - Show Top N vendors 6 | type - Count from one of 'all', 'node', 'infrastructure' MACs 7 | 8 | 9 | <%attr> 10 | title => 'MAC Address Report' 11 | section => 'Reports' 12 | 13 | 14 | <%args> 15 | $topn => 100; 16 | $type => 'node' 17 | $submit => undef 18 | 19 | 20 | <%init> 21 | my $DEBUG = 0; 22 | my ($stats, $total); 23 | my (@headers, @rows) = (); 24 | 25 | 26 | <%perl> 27 | if ( $submit ){ 28 | ($stats, $total) = PhysAddr->vendor_count($type); 29 | print "
", Dumper($stats), "
" if $DEBUG; 30 | 31 | @headers = ( 'OUI', 'Vendor', 'Count', '%', ); 32 | 33 | my @row = (); 34 | push( @row, "Total in Database" ); 35 | push( @row, "" ); 36 | push( @row, "$total" ); 37 | push( @row, " " ); 38 | push( @rows, \@row ); 39 | 40 | my $i; 41 | foreach my $oui ( sort { $stats->{$b}{total} <=> $stats->{$a}{total} } keys %$stats ){ 42 | $i++; 43 | my @row = (); 44 | my $vendor = $stats->{$oui}{vendor}; 45 | my $count = $stats->{$oui}{total}; 46 | my $srch = "$oui*"; 47 | my $slink = "$oui"; 48 | push( @row, $slink, $vendor, $count ); 49 | push( @row, sprintf("%02.2f",$count/$total * 100) ); 50 | push( @rows, \@row ); 51 | last if ( $i == $topn ); 52 | } 53 | } 54 | 55 | 56 |
57 |
MAC Addresses by Vendor (top <% $topn %>)
58 |
59 |

60 |

61 | Top Vendors of type: 62 | % my %checked = (node => "", infrastructure => "", all => ""); 63 | % $checked{$type} = "SELECTED"; 64 | % 65 | 70 | 71 |
72 | 73 | % if ( $submit ){ 74 | <& /generic/data_table.mhtml, field_headers=>\@headers, data=>\@rows, 75 | style=>['', '', 'text-align: right', 'text-align: right'] &> 76 | % } 77 |
78 |
79 | 80 | -------------------------------------------------------------------------------- /htdocs/reports/maxed_subnets.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show maxed out subnets 3 | 4 | % 5 | % 6 | <%attr> 7 | title => 'Maxed Out Subnets' 8 | section => 'Reports' 9 | 10 | % 11 | % 12 | <%args> 13 | $version => undef; 14 | 15 | % 16 | % 17 | <%init> 18 | my $DEBUG = 0; 19 | print "
", Dumper(%ARGS), "

" if $DEBUG; 20 | my $threshold = Netdot->config->get('SUBNET_USAGE_MINPERCENT'); 21 | my @pairs = Ipblock->get_maxed_out_subnets(version=>$version); 22 | 23 | my @subnets = map { $_->[0] } @pairs; 24 | 25 | 26 | 27 |
28 |
The following subnets are below <% $threshold %>% free:
29 |
 
30 |
31 | % if ( !scalar(@subnets) ){ 32 |

No maxed-out subnets found.

33 | % }else{ 34 | <& /generic/sortresults.mhtml, object=>\@subnets &> 35 | % } 36 |
37 |
38 | -------------------------------------------------------------------------------- /htdocs/reports/mysql_stats.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Table Information 3 | 4 | 5 | 6 | <%attr> 7 | title => 'Table Information' 8 | section => 'Reports' 9 | 10 | 11 | <%init> 12 | my $DEBUG = 0; 13 | my $netdot; 14 | 15 | 16 | <%perl> 17 | 18 | my (@headers, @rows) = (); 19 | @headers = ( 'Table', 'Rows', 'Data Length', 'Index Length', 'Max Data Length', 'Data Free', 'Create Time', 'Update Time', 'Comment' ); 20 | 21 | my $dbh = Netdot::Model->db_Main; 22 | my $q = $dbh->prepare("SHOW TABLE STATUS"); 23 | $q->execute(); 24 | 25 | my $data_sum; 26 | my $index_sum; 27 | my $free_sum; 28 | my $data_data_sum; 29 | my $data_index_sum; 30 | my $data_free_sum; 31 | 32 | while ( my ($name, $engine, $version, $row_format, $rows, $avg_row_len, $data_len, $max_data_len, 33 | $index_len, $data_free, $auto_increment, $create_time, $update_time, $check_time, $collation, 34 | $checksum, $create_options, $comment) = $q->fetchrow_array() ) { 35 | my @row = (); 36 | push( @row, $name ); 37 | push( @row, $rows ); 38 | push( @row, $ui->format_size($data_len) ); 39 | push( @row, $ui->format_size($index_len) ); 40 | push( @row, $ui->format_size($max_data_len) ); 41 | push( @row, $ui->format_size($data_free) ); 42 | push( @row, $create_time ); 43 | push( @row, $update_time ); 44 | push( @row, $comment ); 45 | push( @rows, \@row ); 46 | 47 | $data_sum += $data_len; 48 | $index_sum += $index_len; 49 | $free_sum += $data_free; 50 | 51 | $data_data_sum += $data_len; 52 | $data_index_sum += $index_len; 53 | $data_free_sum += $data_free; 54 | 55 | } 56 | 57 | { 58 | my @row = (); 59 | push( @row, "Total Size:" ); 60 | push( @row, " " ); 61 | push( @row, "".$ui->format_size($data_sum)."" ); 62 | push( @row, "".$ui->format_size($index_sum)."" ); 63 | push( @row, " " ); 64 | push( @row, "".$ui->format_size($free_sum)."" ); 65 | push( @row, " " ); 66 | push( @row, " " ); 67 | push( @row, " " ); 68 | push( @rows, \@row ); 69 | } 70 | 71 | { 72 | my @row = (); 73 | push( @row, "Size of Data:" ); 74 | push( @row, " " ); 75 | push( @row, $ui->format_size($data_data_sum) ); 76 | push( @row, $ui->format_size($data_index_sum) ); 77 | push( @row, " " ); 78 | push( @row, $ui->format_size($data_free_sum) ); 79 | push( @row, " " ); 80 | push( @row, " " ); 81 | push( @row, " " ); 82 | push( @rows, \@row ); 83 | } 84 | 85 | 86 | 87 | 88 |
89 |
90 | Table Information 91 |
92 |
93 | <& //generic/data_table.mhtml, field_headers=>\@headers, data=>\@rows &> 94 |
95 | -------------------------------------------------------------------------------- /htdocs/reports/reports_custom.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Custom Reports 3 | 4 | 5 | 6 | <%attr> 7 | title => 'Custom Reports' 8 | section => 'Reports' 9 | 10 | 11 | <%init> 12 | my $DEBUG = 0; 13 | 14 | 15 | -------------------------------------------------------------------------------- /htdocs/reports/snmp_down.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Devices in 'SNMP_Down' state 3 | 4 | 5 | <%attr> 6 | title => 'Devices in SNMP Down State' 7 | section => 'Reports' 8 | 9 | 10 | <%args> 11 | 12 | 13 | 14 | <%init> 15 | my $DEBUG = 0; 16 | if ( $DEBUG ){ 17 | print '%ARGS is
', Dumper(%ARGS), '

'; 18 | } 19 | my @devices = Device->search(snmp_down=>1); 20 | 21 | 22 | 23 |
24 |
Devices in 'SNMP Down' State
25 |
26 | % if( @devices ){ 27 | <& ../generic/sortresults.mhtml, table => 'Device', object=>\@devices, view => "row", withdelete => 1, withedit => 1 &> 28 | % }else{ 29 | None 30 | % } 31 |
32 |
33 | 34 | -------------------------------------------------------------------------------- /htdocs/reports/time_poll_stats.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Device Polling Statistics - Time 3 | 4 | 5 | <%args> 6 | 7 | 8 | <%attr> 9 | title => "Reports: Device Polling Time" 10 | meta_refresh => 3600 11 | 12 | 13 | <%init> 14 | my $web_path = $r->dir_config('NetdotPath'); 15 | 16 | 17 |
18 |
Device Polling Time
19 |
20 | 21 |

Device Polling time statistics: 22 | 23 |

24 |

25 | % print $ui->rrd_graph(type=>'time', period=>'-1d', web_path=>$web_path, img=>"1d_time_stats.png", title=>"Last day"); 26 |

27 | % print $ui->rrd_graph(type=>'time', period=>'-1w', web_path=>$web_path, img=>"1w_time_stats.png", title=>"Last Week"); 28 |

29 | % print $ui->rrd_graph(type=>'time', period=>'-1m', web_path=>$web_path, img=>"1m_time_stats.png", title=>"Last Month"); 30 |

31 | % print $ui->rrd_graph(type=>'time', period=>'-1y', web_path=>$web_path, img=>"1y_time_stats.png", title=>"Last Year"); 32 |

33 |
34 |
35 | -------------------------------------------------------------------------------- /htdocs/reports/unused_statics.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show Unused Statics 3 | 4 | % 5 | % 6 | <%attr> 7 | title => 'Unused Statics' 8 | section => 'Reports' 9 | 10 | % 11 | % 12 | <%args> 13 | $days 14 | $version => 4 15 | $edit => 0 16 | 17 | % 18 | % 19 | <%init> 20 | my $DEBUG = 0; 21 | print "
", Dumper(%ARGS), "

" if $DEBUG; 22 | my $sqldate = Netdot::Model->sqldate_days_ago($days); 23 | print "$days days ago was: $sqldate", "
" if $DEBUG; 24 | my $static = IpblockStatus->search(name=>'Static')->first; 25 | my @ips = Ipblock->search_where({status=>$static, 26 | version=>$version, 27 | last_seen=>{ '<', $sqldate }}, 28 | {order_by=>'address'}); 29 | 30 | # We're going to ignore device and multicast IPs 31 | my @unused; 32 | foreach my $ip ( @ips ){ 33 | next if ( int($ip->interface) != 0 ); 34 | next if ( $ip->snmp_devices ); 35 | next if ( $ip->is_multicast ); 36 | push @unused, $ip; 37 | } 38 | 39 | 40 | 41 | %if ( !scalar(@unused) ){ 42 |

No unused IPs found.

43 | %}else{ 44 | <& /generic/sortresults.mhtml, object=>\@unused, withedit=>$edit &> 45 | %} 46 | -------------------------------------------------------------------------------- /htdocs/reports/unused_subnets.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show unused subnets 3 | 4 | % 5 | % 6 | <%attr> 7 | title => 'Unused Subnets' 8 | section => 'Reports' 9 | 10 | % 11 | % 12 | <%args> 13 | $version => undef; 14 | 15 | % 16 | % 17 | <%init> 18 | my $DEBUG = 0; 19 | print "
", Dumper(%ARGS), "

" if $DEBUG; 20 | 21 | my @subnets = Ipblock->get_unused_subnets(version=>$version); 22 | 23 | 24 | 25 |
26 |
The following subnets appear to be unused:
27 |
 
28 |
29 | % if ( !scalar(@subnets) ){ 30 |

No unused subnets found.

31 | % }else{ 32 | <& /generic/sortresults.mhtml, object=>\@subnets, sort=>0 &> 33 | % } 34 |
35 |
36 | -------------------------------------------------------------------------------- /htdocs/reports/vlan_mismatches.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Show VLAN mismatches 3 | 4 | % 5 | % 6 | <%attr> 7 | title => 'VLAN Mismatches' 8 | 9 | % 10 | % 11 | <%args> 12 | 13 | % 14 | % 15 | <%init> 16 | my $DEBUG = 0; 17 | print "
", Dumper(%ARGS), "

" if $DEBUG; 18 | 19 | my $res = Interface->find_vlan_mismatches(); 20 | my $num; 21 | if ( defined $res && ref($res) eq 'HASH' ){ 22 | $num = scalar(keys %$res); 23 | }else{ 24 | $m->comp('/generic/error.mhtml', error=>"Invalid data"); 25 | } 26 | print Dumper($res) if $DEBUG; 27 | 28 | my @cssitem = ("formtablec1", "formtablec2"); 29 | my $ci = 1; 30 | 31 | 32 | 33 |
34 |
VLAN Mismatches <% ($num) %>:
35 |
 
36 |
37 | % if ( !$num ){ 38 |

No mismatches found.

39 | % }else{ 40 | 41 | 42 | % foreach ('Interface', 'VLANs', 'Interface', 'VLANs'){ 43 | 44 | % } 45 | 46 | % foreach my $iid ( sort { $res->{$a}{name} cmp $res->{$b}{name} } keys %$res ){ 47 | % my $name = $res->{$iid}{name}; 48 | % my $vlans = $res->{$iid}{vlans}; 49 | % my $n_id = $res->{$iid}{n_id}; 50 | % my $n_name = $res->{$iid}{n_name}; 51 | % my $n_vlans = $res->{$iid}{n_vlans}; 52 | % $ci = ($ci + 1) % 2; 53 | 54 | 55 | 56 | 57 | 58 | 59 | % } 60 |
<% $_ %>
<% $name %><% $vlans %><% $n_name %><% $n_vlans %>
61 | % } 62 |
63 |
64 | -------------------------------------------------------------------------------- /htdocs/rest/autohandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | /rest autohandler - Deals with the different nature of the REST interface 3 | 4 | <%args> 5 | $user => $ui->get_current_user($r); 6 | $manager => $ui->get_permission_manager($r); 7 | 8 | <%init> 9 | 10 | # Remove unnecessary headers 11 | $m->clear_buffer; 12 | 13 | my $DEBUG = 0; 14 | if ( $DEBUG ){ 15 | print '%ARGS is
', Dumper(%ARGS), '

'; 16 | print "req comp: ", $m->request_comp->name, "
"; 17 | print "URI: ", $r->uri, "
"; 18 | print "content_type : ", $r->content_type, "
"; 19 | print "user: ", $user, "
"; 20 | print "manager: ", $manager, "
"; 21 | } 22 | 23 | # Make sure we have this information for every user 24 | $ui->get_allowed_objects($r, $user) if $user; 25 | 26 | eval { 27 | $m->call_next(user=>$user, manager=>$manager); 28 | }; 29 | 30 | my $e; 31 | if ( $e = Netdot::Util::Exception->caught('Netdot::Util::Exception::REST') ){ 32 | $m->clear_and_abort($e->code); 33 | }elsif ( $e = $@ ){ 34 | die $e; 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /htdocs/rest/devinfo: -------------------------------------------------------------------------------- 1 | <%doc> 2 | REST resource to fetch device information 3 | 4 | <%args> 5 | $user # Should be assigned by autohandler 6 | $manager # Should be assigned by autohandler 7 | $site => undef # (optional) Filter results by site 8 | 9 | <%init> 10 | my $DEBUG = 0; 11 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 12 | 13 | use Apache2::Const -compile => qw(FORBIDDEN OK NOT_FOUND HTTP_BAD_REQUEST); 14 | use Data::Dumper; 15 | use Netdot::REST; 16 | use Netdot::Exporter; 17 | 18 | my $rest = Netdot::REST->new(user=>$user, manager=>$manager); 19 | $rest->request($r); 20 | 21 | # Get relevant HTTP headers from request object 22 | my $headers = $rest->{request}->headers_in; 23 | 24 | # Deal with Accept header 25 | $rest->check_accept_header($headers->{Accept}) if ( $headers->{Accept} ); 26 | 27 | my $method = $rest->{request}->method; 28 | my $req_args = $method eq 'POST' ? 29 | sprintf("%s", join(" ", Dumper(%ARGS))) : $rest->{request}->args; 30 | 31 | my $logger = Netdot->log->get_logger("Netdot::REST"); 32 | $logger->info(sprintf("/rest/devinfo: %s request with args: %s from %s (%s)", 33 | $method, 34 | $req_args, 35 | $rest->remote_ip, 36 | $headers->{'User-Agent'} 37 | )); 38 | 39 | 40 | <%perl> 41 | 42 | my %ret; 43 | if ( $method eq 'GET' ){ 44 | my %eargs; 45 | $eargs{site} = $site if defined $site; 46 | my $info = Netdot::Exporter->get_device_info(%eargs); 47 | $ret{device} = $info; 48 | $rest->print_serialized(\%ret); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /htdocs/rest/dhandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | This Mason default handler component handles requests for RESTful resources 3 | 4 | <%args> 5 | $user 6 | $manager 7 | 8 | <%init> 9 | 10 | delete $ARGS{user}; 11 | delete $ARGS{showheader}; 12 | 13 | my $resource = $m->dhandler_arg; 14 | 15 | my $DEBUG = 0; 16 | if ( $DEBUG ){ 17 | $r->content_type(q{text/html; charset=utf-8}); 18 | print '%ARGS is
', Dumper(%ARGS), '

'; 19 | print "req comp: ", $m->request_comp->name, "
"; 20 | print "URI: ", $r->uri, "
"; 21 | print "METHOD: ", $r->method, "
"; 22 | print "content_type : ", $r->content_type, "
"; 23 | print "resource: ", $resource, "
"; 24 | $m->abort; 25 | } 26 | 27 | # Handle generic requests 28 | # Remember that we'll only hit this code if there isn't a 29 | # specific component for the given request 30 | # 31 | use Netdot::REST; 32 | delete $ARGS{manager}; 33 | my $rest = Netdot::REST->new(user=>$user, manager=>$manager); 34 | eval { 35 | $rest->handle_resource(resource=>$resource, r=>$r, %ARGS); 36 | }; 37 | 38 | my $e; 39 | if ( $e = Netdot::Util::Exception->caught('Netdot::Util::Exception::REST') ){ 40 | $m->clear_and_abort($e->code); 41 | }elsif ( $e = $@ ){ 42 | die $e; 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /htdocs/rest/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Load the REST class to verify that it is operational 3 | 4 | <%args> 5 | $user 6 | $manager 7 | 8 | <%init> 9 | use Netdot::REST; 10 | my $rest = Netdot::REST->new(user=>$user, manager=>$manager); 11 | print "Netdot/$Netdot::VERSION REST OK. " if defined $rest; 12 | 13 | -------------------------------------------------------------------------------- /htdocs/rest/ipattr: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Retrieve list of inherited IP attributes for given IP 3 | 4 | <%args> 5 | $addr # IP block or address 6 | $user # Should be assigned by autohandler 7 | $manager # Should be assigned by autohandler 8 | 9 | <%init> 10 | my $DEBUG = 0; 11 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 12 | 13 | use Apache2::Const -compile => qw(FORBIDDEN OK NOT_FOUND HTTP_BAD_REQUEST); 14 | use Data::Dumper; 15 | use Netdot::REST; 16 | use Netdot::Exporter; 17 | 18 | my $rest = Netdot::REST->new(user=>$user, manager=>$manager); 19 | $rest->request($r); 20 | 21 | # Get relevant HTTP headers from request object 22 | my $headers = $rest->{request}->headers_in; 23 | 24 | # Deal with Accept header 25 | $rest->check_accept_header($headers->{Accept}) if ( $headers->{Accept} ); 26 | 27 | my $method = $rest->{request}->method; 28 | $rest->throw(code=>Apache2::Const::HTTP_BAD_REQUEST, 29 | msg=>'Bad request: invalid method') unless $method eq 'GET'; 30 | 31 | my $logger = Netdot->log->get_logger("Netdot::REST"); 32 | $logger->info(sprintf("/rest/ipattr: %s request with args: %s from %s (%s)", 33 | $method, 34 | $rest->{request}->args, 35 | $rest->remote_ip, 36 | $headers->{'User-Agent'} 37 | )); 38 | 39 | 40 | <%perl> 41 | my $ip = Ipblock->search(address=>$addr)->first; 42 | $rest->throw(code=>Apache2::Const::NOT_FOUND, msg=>"IP not found") 43 | unless $ip; 44 | my $attrs = $ip->get_inherited_attributes(); 45 | $rest->print_serialized($attrs); 46 | 47 | -------------------------------------------------------------------------------- /htdocs/rest/updatedev: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Discover devices via REST 3 | 4 | <%args> 5 | $user # Should be assigned by autohandler 6 | $manager # Should be assigned by autohandler 7 | $name # Device name 8 | $info # Device information (serialized) 9 | 10 | <%init> 11 | my $DEBUG = 0; 12 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 13 | 14 | use Apache2::Const -compile => qw(FORBIDDEN OK NOT_FOUND HTTP_BAD_REQUEST); 15 | 16 | use Data::Dumper; 17 | 18 | use Netdot::REST; 19 | my $rest = Netdot::REST->new(user=>$user, manager=>$manager); 20 | $rest->request($r); 21 | 22 | # Get relevant HTTP headers from request object 23 | my $headers = $rest->{request}->headers_in; 24 | 25 | # Deal with Accept header 26 | $rest->check_accept_header($headers->{Accept}) if ( $headers->{Accept} ); 27 | 28 | my $method = $rest->{request}->method; 29 | my $req_args = $method eq 'POST' ? 30 | sprintf("%s", join(" ", Dumper(%ARGS))) : $rest->{request}->args; 31 | 32 | my $logger = Netdot->log->get_logger("Netdot::REST"); 33 | $logger->info(sprintf("/rest/updatedev: %s request with args: %s from %s (%s)", 34 | $method, 35 | $req_args, 36 | $rest->remote_ip, 37 | $headers->{'User-Agent'} 38 | )); 39 | 40 | 41 | <%perl> 42 | 43 | my $dinfo; 44 | if ( $method eq 'POST' ){ 45 | $dinfo = $rest->read_serialized($info); 46 | 47 | my $obj; 48 | eval { 49 | Netdot::Model->do_transaction( sub{ 50 | $obj = Device->discover(name=>$name, info=>$dinfo); 51 | }); 52 | }; 53 | if ( my $e = $@ ){ 54 | $rest->throw(code=>Apache2::Const::HTTP_BAD_REQUEST, 55 | msg=>"Bad request: $e"); 56 | } 57 | 58 | 59 | my $o = $rest->get(obj=>$obj); 60 | $rest->print_serialized($o); 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /htdocs/user_help/autohandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Help section for unpriviledged users 4 | 5 | 6 | 7 | <%args> 8 | $user => $ui->get_current_user($r); 9 | 10 | 11 | <%attr> 12 | title => 'Netdot Help' 13 | section => 'Help' 14 | 15 | 16 | <%shared> 17 | my $PAGE_ATTRIBUTE = "HELP_PAGE"; 18 | my $SECTION = "Help"; 19 | 20 | 21 | <%init> 22 | my %caller_args = $m->caller_args(-1); 23 | 24 | if (exists($caller_args{page})){ 25 | $user->setAttribute($r, "$PAGE_ATTRIBUTE", $caller_args{page}); 26 | } 27 | 28 | my $page = $user->getAttribute("$PAGE_ATTRIBUTE"); 29 | 30 | 31 | <%method .section_meta_data> 32 | <%doc> 33 | Returns the meta data used to generate this sections header in section1.mhtml 34 | 35 | <%init> 36 | return { 37 | section => $SECTION, 38 | page => 'user_help/', 39 | title => 'Help', 40 | attribute => $PAGE_ATTRIBUTE, 41 | sub_sections => [ 42 | { section => 'HOSTS', title => 'Hosts' }, 43 | ], 44 | }; 45 | 46 | 47 | 48 | <%perl> 49 | if (($page eq "HOSTS") && $m->request_comp->name ne "hosts.html" ) { 50 | $m->comp('hosts.html', user=>$user, dowindow=>0); 51 | } 52 | 53 | if ( $m->fetch_next ){ 54 | $m->call_next; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /htdocs/user_help/dhandler: -------------------------------------------------------------------------------- 1 | <& "SELF:.section_dhandler", request => $m->dhandler_arg, %ARGS &> 2 | -------------------------------------------------------------------------------- /htdocs/user_help/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Intentionally empty. Just triggers the autohandler. This file 3 | could be eliminated by setting up HTML::Mason to handle directory 4 | requests, I think. 5 | -------------------------------------------------------------------------------- /htdocs/user_management/autohandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Management Functions for end users 4 | 5 | 6 | 7 | <%args> 8 | $user => $ui->get_current_user($r); 9 | $showheader => 1 10 | 11 | 12 | <%attr> 13 | title => 'Management' 14 | # This is used by the toplevel autohandler to determine the section. 15 | # Since attributes aren't inherited (but shouldn't they be ...) we have 16 | # to also specify this in the dhandler 17 | section => "Management" # $SECTION 18 | 19 | 20 | <%shared> 21 | my $PAGE_ATTRIBUTE = "USER_MANAGEMENT_PAGE"; 22 | my $SECTION = "Management"; 23 | 24 | 25 | <%init> 26 | 27 | my $DEBUG = 0; 28 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 29 | 30 | my $caller_args = $m->caller_args(-1); 31 | 32 | if (exists($caller_args->{page})){ 33 | $user->setAttribute($r, "$PAGE_ATTRIBUTE", $caller_args->{page}); 34 | } 35 | my $page = $user->getAttribute("$PAGE_ATTRIBUTE"); 36 | 37 | 38 | if (exists($caller_args->{tasks})){ 39 | $user->setAttribute($r, "SHOW_TASKS", $caller_args->{tasks}); 40 | } 41 | my $show_tasks = $user->getAttribute("SHOW_TASKS"); 42 | if ($show_tasks eq "") { 43 | $user->setAttribute($r, "SHOW_TASKS", "show"); 44 | $show_tasks = "show"; 45 | } 46 | *print_showtaskslink = $m->comp('SELF:.sub_print_showtaskslink'); 47 | 48 | my $hideheader; 49 | if( !$showheader ) { 50 | $hideheader = 'style="display:none"'; 51 | } 52 | 53 | % 54 | % 55 | %# Methods can be called externally. 56 | <%method .section_meta_data> 57 | <%doc> 58 | Returns the meta data used to generate this section\'s header in section1.mhtml 59 | 60 | <%init> 61 | return { 62 | section => $SECTION, 63 | page => 'user_management/', 64 | title => 'Management', 65 | attribute => $PAGE_ATTRIBUTE, 66 | sub_sections => [ 67 | { section => 'HOSTINFO', title => 'DNS/DHCP' }, 68 | { section => 'DEVICE', title => 'Devices' }, 69 | { section => 'CONTACTS', title => 'Contacts' }, 70 | ] 71 | }; 72 | 73 | 74 | 75 | <%perl> 76 | 77 | if (($page eq "HOSTINFO" || $page eq "") && $m->request_comp->name ne "hostinfo_tasks.html" ) { 78 | 79 | $m->comp('hostinfo_tasks.html', user=>$user, showheader=>$showheader); 80 | 81 | }elsif ( $page eq "DEVICE" && $m->request_comp->name ne "device_tasks.html" ) { 82 | 83 | $m->comp('device_tasks.html', user=>$user, showheader=>$showheader); 84 | 85 | } elsif ($page eq "CONTACTS" && $m->request_comp->name ne "contact_tasks.html" ) { 86 | 87 | $m->comp('contacts_tasks.html', user=>$user, showheader=>$showheader); 88 | 89 | } 90 | 91 | if ( my $next = $m->fetch_next ){ 92 | $m->call_next(page => $page); 93 | } 94 | 95 | 96 | -------------------------------------------------------------------------------- /htdocs/user_management/contacts_tasks.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | 3 | Manage Contact Lists (unprviledged users) 4 | 5 | 6 | 7 | 8 | %####################################################################### 9 | %# 10 | %# Args section 11 | %# 12 | %####################################################################### 13 | <%args> 14 | $user => $ui->get_current_user($r) 15 | $submit => undef 16 | $show_contactlist => undef 17 | $show_tasks => undef 18 | $showheader => 1 19 | 20 | % 21 | % 22 | % 23 | %####################################################################### 24 | %# 25 | %# INIT section 26 | %# 27 | %####################################################################### 28 | % 29 | <%init> 30 | my $DEBUG = 0; 31 | print '%ARGS is
', Dumper(%ARGS), '

' if $DEBUG; 32 | $show_tasks = $show_tasks || $user->getAttribute("SHOW_TASKS"); 33 | if ( $show_tasks eq "" ) { 34 | $user->setAttribute($r, "SHOW_TASKS", "show"); 35 | $show_tasks = "show"; 36 | } 37 | *print_showtaskslink = $m->comp('SELF:.sub_print_showtaskslink'); 38 | my $hideheader = 'style="display:none"' if ( !$showheader ); 39 | $ARGS{show_tasks} = $show_tasks; 40 | 41 | 42 | % if ( $show_contactlist ){ 43 | % $m->comp('../generic/contactlist.html', id=>$show_contactlist, user=>$user ); 44 | % }else{ 45 | 46 |
> 47 |
48 |
49 | My Contact Lists 50 |
51 |
52 | % print_showtaskslink($show_tasks); 53 |
54 |
"> 55 | 56 | <%perl> 57 | my @objs; 58 | my $objt = 'ContactList'; 59 | my $ao = $ui->get_allowed_objects($r, $user); 60 | if ( exists $ao->{$objt} ){ 61 | foreach my $id ( keys %{$ao->{$objt}} ){ 62 | if ( my $obj = ContactList->retrieve($id) ){ 63 | push @objs, $obj; 64 | }else{ 65 | delete $ao->{$objt}->{$id}; 66 | } 67 | } 68 | } 69 | 70 | 71 |

72 | 73 | % if ( @objs ){ 74 |

75 | 81 |
82 | % }else{ 83 | No Contact Lists available for this user. 84 | % } 85 | 86 |
87 |
88 |
89 | 90 | % } 91 | 92 | 93 | -------------------------------------------------------------------------------- /htdocs/user_management/dhandler: -------------------------------------------------------------------------------- 1 | <%doc> 2 | This default handler is particularly different because we want to provide 3 | more restricted access to components outside this directory 4 | 5 | 6 | <%perl> 7 | my $request = $m->dhandler_arg; 8 | my %comp_path_map = ( 9 | 'device.html' => '../management', 10 | 'host.html' => '../management', 11 | 'interface.html' => '../management', 12 | 'zone.html' => '../management', 13 | 'mac.html' => '../management', 14 | 'ip.html' => '../management', 15 | ); 16 | 17 | my $generic_pages_path = "../generic"; 18 | my $comp_path = (exists $comp_path_map{$request})? "$comp_path_map{$request}/$request" : "$generic_pages_path/$request"; 19 | 20 | if ( $m->comp_exists($comp_path) ){ 21 | # $m->dhandler_arg returns the path portion after "./", but not 22 | # the get/post args (e.g. ?foo=bar&baz=fraz). The args are passed 23 | # along in %ARGS. 24 | $m->comp( $comp_path, %ARGS ); 25 | }else{ 26 | $r->content_type(q{text/html; charset=utf-8}); 27 | $m->comp('/generic/error.mhtml', error => "The requested page: \"$request\" does not exist or you are not allowed to use it."); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /htdocs/user_management/index.html: -------------------------------------------------------------------------------- 1 | <%doc> 2 | Intentionally empty. Just triggers the autohandler. This file 3 | could be eliminated by setting up HTML::Mason to handle directory 4 | requests, I think. 5 | 6 | -------------------------------------------------------------------------------- /import/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # makefile for import/ 5 | # 6 | 7 | FILES := $(shell ls *.pl) 8 | 9 | install: 10 | $(substitute) 11 | 12 | -------------------------------------------------------------------------------- /import/import_hosts.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Import hosts from a CSV file 4 | # Each host is a 4-tuple: (name, zone, IP, MAC) 5 | # which will create DNS records and DHCP reservations in Netdot. 6 | # 7 | # Note: The subnet(s) to which the IPs belong must be DHCP enabled 8 | # 9 | use lib "/usr/local/netdot/lib"; 10 | use Netdot::Model; 11 | use strict; 12 | 13 | my $file = $ARGV[0] or die "Need input file\n"; 14 | open(FILE, $file) or die "Cannot open $file: $!\n"; 15 | 16 | while (){ 17 | next if /^#|^\s/; 18 | my($name, $zone, $ip, $mac) = split(',', $_); 19 | 20 | my $rr; 21 | eval { 22 | $rr = RR->add_host(name=>$name, zone=>$zone, 23 | address=>$ip, ethernet=>$mac); 24 | }; 25 | if (my $e = $@){ 26 | printf("Problem importing %s, %s, %s, %s: $e\n", 27 | $name, $zone, $ip, $mac); 28 | }else{ 29 | printf("Added %s with MAC %s\n", $rr->get_label, $mac); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /import/import_ip_bulk.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Import a list of IP blocks and addresses from a CSV file 4 | # (See sample input file ip_list.txt) 5 | # 6 | use lib "/usr/local/netdot/lib"; 7 | use Netdot::Model; 8 | use strict; 9 | 10 | my $file = $ARGV[0] or die "Need input file\n"; 11 | open(FILE, $file) or die "Cannot open $file: $!\n"; 12 | 13 | 14 | while (){ 15 | next if /^#|^\s/; 16 | my($block, $status, $owner, $used_by, $description) = split(',', $_); 17 | my($address, $prefix) = split(/\//, $block); 18 | die "Syntax error: Block must be in CIDR notation: $block\n" 19 | unless ($address && $prefix); 20 | die "Unrecognized status: $status\n" 21 | unless ( $status =~ /^Dynamic|Static|Container|Reserved|Subnet$/ ); 22 | 23 | my ($ent1, $ent2); 24 | if ($owner){ 25 | $ent1 = Entity->find_or_create({name=>$owner}); 26 | } 27 | if ($used_by){ 28 | $ent2 = Entity->find_or_create({name=>$used_by}); 29 | } 30 | if ( my $ip = Ipblock->search(address=>$address, prefix=>$prefix)->first ){ 31 | print "IP " . $ip->get_label . " exists. Updating.\n"; 32 | $ip->update({status => $status, 33 | owner => $ent1, 34 | used_by => $ent2, 35 | description => $description, 36 | }); 37 | }else{ 38 | my $newip; 39 | eval { 40 | $newip = Ipblock->insert({address => $address, 41 | prefix => $prefix, 42 | status => $status, 43 | owner => $ent1, 44 | used_by => $ent2, 45 | description => $description, 46 | no_update_tree => 1, 47 | }); 48 | }; 49 | if ( my $e = $@ ){ 50 | die "ERROR: $e\n"; 51 | }else{ 52 | print "Inserted " . $newip->get_label. "\n"; 53 | } 54 | } 55 | } 56 | 57 | Ipblock->build_tree(4); 58 | Ipblock->build_tree(6); 59 | -------------------------------------------------------------------------------- /import/ip_list.txt: -------------------------------------------------------------------------------- 1 | # IP list 2 | # Sytax: 3 | # ,,,, 4 | # 5 | # Example below: 6 | # 7 | 192.168.0.0/24,Container,Network Services,Group 1,blah 8 | 192.168.0.1/32,Static,Network Services,,user1 9 | 192.168.0.2/32,Static,Network Services,,user2 10 | 192.168.0.3/32,Static,Network Services,,user3 11 | 192.168.0.4/32,Static,Network Services,,blah 12 | 192.168.0.5/32,Static,Network Services,,blah 13 | 192.168.0.6/32,Static,Network Services,,blah 14 | 192.168.0.7/32,Static,Network Services,,blah 15 | 192.168.0.8/32,Static,Network Services,,blah 16 | 192.168.0.9/32,Static,Network Services,,blah 17 | 192.168.0.10/32,Static,Network Services,,blah 18 | # 19 | FEC0:468:D00::/40,Container,Network Services,Group 1,blah 20 | FEC0:468:D00::/48,Container,Network Services,Group 2,blah 21 | FEC0:468:D01::/48,Container,Network Services,Group 3,blah 22 | FEC0:468:D04::/48,Container,Network Services,Group 4,blah 23 | FEC0:468:D01:2::/64,Subnet,Network Services,Group 5,blah 24 | FEC0:468:D01:3::/64,Subnet,Network Services,Group 6,blah 25 | FEC0:468:D01:6::/64,Subnet,Network Services,Group 7,blah 26 | FEC0:468:D01:3C::/64,Subnet,Network Services,Group 8,blah 27 | FEC0:468:D01:3C::80DF:3C15/128,Static,Network Services,Group 9,server1 28 | FEC0:468:D01:3C::80DF:3C16/128,Static,Network Services,Group 10,server2 29 | 30 | -------------------------------------------------------------------------------- /import/subnet_zone.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Import subnet-to-zone assignments from text file 4 | # (See sample input file subnet_zone.txt) 5 | # 6 | use lib "<>"; 7 | use Netdot::Model; 8 | use strict; 9 | 10 | my $file = $ARGV[0] or die "Need input file\n"; 11 | open(FILE, $file) or die "Cannot open $file: $!\n"; 12 | 13 | while (){ 14 | next if /^#|^\s/; 15 | my($ipblock, $zone) = split(',', $_); 16 | $ipblock =~ s/\s+//g; 17 | $zone =~ s/\s+//g; 18 | my ($ipb, $z); 19 | if ( !($ipb = Ipblock->search(address=>$ipblock)->first) ){ 20 | die "Ipblock $ipblock not found"; 21 | } 22 | if ( !($z = (Zone->search(name=>$zone))[0]) ){ 23 | die "Zone $zone not found"; 24 | } 25 | my %args = (zone=>$z, subnet=>$ipb); 26 | if (! SubnetZone->search(%args) ){ 27 | print "Inserting SubnetZone for zone: $zone, ipblock: $ipblock\n"; 28 | SubnetZone->insert(\%args); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /import/subnet_zone.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Subnet to Zone relationship list 3 | # 4 | # Sytax: 5 | # , 6 | # 7 | # Example below: 8 | # 9 | 10.0.0.0/8,localdomain 10 | 172.16.0.0/12,localdomain 11 | 192.168.0.0/16,localdomain 12 | -------------------------------------------------------------------------------- /import/update_dev_rest.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # Sample code demonstrating the use 4 | # of the REST resource: /rest/updatedev 5 | # for importing device data in a single 6 | # operation. 7 | # 8 | 9 | 10 | use Netdot::Client::REST; 11 | use Data::Dumper; 12 | use XML::Simple; 13 | 14 | my $server = 'http://localhost/netdot'; 15 | my $username = 'admin'; 16 | my $passwd = 'admin'; 17 | 18 | my $netdot = Netdot::Client::REST->new(server=>$server, 19 | username=>$username, 20 | password=>$passwd); 21 | 22 | my $xs = XML::Simple->new( 23 | ForceArray => 1, 24 | XMLDecl => 1, 25 | KeyAttr => 'id', 26 | ); 27 | 28 | my $info = { 29 | 'sysname' => 'newdevice.localdomain', 30 | 'ipforwarding' => 0, 31 | 'layers' => '01000010', 32 | 'sysobjectid' => '', 33 | 'model' => 'Foo', 34 | 'os' => '1.2.3.4', 35 | 'manufacturer' => 'Bar', 36 | 'serial_number' => 'abcd1234', 37 | 38 | 'interface' => { 39 | '1' => { 40 | 'name' => 'lo0', 41 | 'number' => '1', 42 | 'type' => 'softwareLoopback', 43 | 'physaddr' => '', 44 | 'admin_status' => 'up', 45 | 'oper_status' => 'up', 46 | 'speed' => '10000000', 47 | 'ips' => { 48 | '192.168.10.20' => { 49 | 'address' => '192.168.10.20', 50 | 'version' => '4', 51 | 'subnet' => '192.168.10.20/32' 52 | }, 53 | }, 54 | }, 55 | '2' => { 56 | 'name' => 'eth0', 57 | 'number' => '2', 58 | 'type' => 'ethernet-csmacd', 59 | 'physaddr' => 'abcabcabcabc', 60 | 'admin_status' => 'up', 61 | 'oper_status' => 'up', 62 | 'speed' => '1000000000', 63 | 'ips' => { 64 | '192.168.100.200' => { 65 | 'address' => '192.168.100.200', 66 | 'version' => '4', 67 | 'subnet' => '192.168.100.0/24' 68 | }, 69 | }, 70 | }, 71 | }, 72 | }; 73 | 74 | my $xml = $xs->XMLout($info); 75 | 76 | my $r = $netdot->post('updatedev', { name => 'newdevice.localdomain', 77 | info => $xml }); 78 | print Dumper($r); 79 | 80 | =head1 AUTHOR 81 | 82 | Carlos Vicente, C<< >> 83 | 84 | =head1 COPYRIGHT & LICENSE 85 | 86 | Copyright 2014 Carlos Vicente 87 | 88 | This program is free software; you can redistribute it and/or modify 89 | it under the terms of the GNU General Public License as published by 90 | the Free Software Foundation; either version 2 of the License, or 91 | (at your option) any later version. 92 | 93 | This program is distributed in the hope that it will be useful, but 94 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 95 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 96 | License for more details. 97 | 98 | You should have received a copy of the GNU General Public License 99 | along with this program; if not, write to the Free Software Foundation, 100 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 101 | 102 | =cut 103 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # makefile for lib 5 | 6 | 7 | NDIR = Netdot Netdot/Manual Netdot/Meta Netdot/Meta/Table Netdot/Model Netdot/Model/Plugins Netdot/Model/Device Netdot/Model/Device/CLI Netdot/UI Netdot/Util Netdot/Exporter 8 | 9 | FILES := `find . -name "*.pm" | grep -v snmp-info | sed -e 's/\.\///'` 10 | 11 | all: wipedir dir 12 | $(substitute) 13 | 14 | # Wipe out dir before installing 15 | wipedir: 16 | $(wipedir) 17 | 18 | # This section creates the lib/Netdot subdirs 19 | dir: 20 | $(mkdirs) 21 | -------------------------------------------------------------------------------- /lib/Netdot/AuthLocal.pm: -------------------------------------------------------------------------------- 1 | package Netdot::AuthLocal; 2 | 3 | use strict; 4 | use warnings; 5 | use Netdot::Model; 6 | 7 | =head1 NAME 8 | 9 | Netdot::AuthLocal - Local authentication module for Netdot via Apache2::SiteControl 10 | 11 | =head1 SYNOPSIS 12 | 13 | In Apache configuration: 14 | 15 | =over 4 16 | 17 | PerlSetVar SiteControlMethod Netdot::AuthLocal 18 | 19 | =back 20 | 21 | =head1 SEE ALSO 22 | 23 | Apache2::SiteControl 24 | 25 | =cut 26 | 27 | =head2 check_credentials 28 | 29 | Arguments: 30 | Apache Request Object 31 | Username 32 | Password 33 | Returns: 34 | True or false 35 | Examples: 36 | if ( Netdot::Radius::check_credentials($r, $user, $pass) {...} 37 | 38 | =cut 39 | 40 | sub check_credentials { 41 | my ($r, $username, $password) = @_; 42 | 43 | unless ( $r && $username && $password ){ 44 | $r->log_error("Netdot::AuthLocal::check_credentials: Missing required arguments"); 45 | return 0; 46 | } 47 | 48 | my $user; 49 | unless ( $user = Person->search(username=>$username)->first ){ 50 | $r->log_error("Netdot::AuthLocal::check_credentials: $username not found in DB"); 51 | return 0; 52 | } 53 | 54 | unless ( $user->verify_passwd($password) ){ 55 | $r->log_error("Netdot::AuthLocal::check_credentials: $username: Bad password"); 56 | return 0; 57 | } 58 | 59 | return 1; 60 | } 61 | 62 | #Be sure to return 1 63 | 1; 64 | 65 | __END__ 66 | 67 | =head1 AUTHORS 68 | 69 | Carlos Vicente, C<< >> 70 | 71 | =head1 COPYRIGHT & LICENSE 72 | 73 | Copyright 2009 University of Oregon, all rights reserved. 74 | 75 | This program is free software; you can redistribute it and/or modify 76 | it under the terms of the GNU General Public License as published by 77 | the Free Software Foundation; either version 2 of the License, or 78 | (at your option) any later version. 79 | 80 | This program is distributed in the hope that it will be useful, but 81 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 82 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 83 | License for more details. 84 | 85 | You should have received a copy of the GNU General Public License 86 | along with this program; if not, write to the Free Software Foundation, 87 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 88 | 89 | =cut 90 | 91 | 92 | -------------------------------------------------------------------------------- /lib/Netdot/Mason.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Mason; 2 | use strict; 3 | use HTML::Mason::ApacheHandler; 4 | 5 | =head1 NAME 6 | 7 | Netdot::Mason 8 | 9 | =cut 10 | 11 | =head1 DESCRIPTION 12 | 13 | HTML::Mason setup for Netdot 14 | 15 | =cut 16 | 17 | { 18 | package HTML::Mason::Commands; 19 | use Data::Dumper; 20 | use lib "<>"; 21 | use Netdot::UI; 22 | use vars qw ( $ui $cable_manager ); 23 | $ui = Netdot::UI->new(); 24 | } 25 | 26 | # Create ApacheHandler object at startup. 27 | my $ah = 28 | HTML::Mason::ApacheHandler->new ( 29 | args_method => "mod_perl", 30 | comp_root => "<>/htdocs", 31 | data_dir => "<>/htdocs/masondata", 32 | error_mode => 'output', 33 | ); 34 | 35 | # Do not die for certain Perl warnings 36 | $ah->interp->ignore_warnings_expr("(?i-xsm:Subroutine .*redefined|as parentheses is deprecated)"); 37 | 38 | =head1 METHODS 39 | 40 | =head2 handler 41 | 42 | =cut 43 | 44 | sub handler 45 | { 46 | my ($r) = @_; 47 | 48 | # As instructed by Ima::DBI's documentation 49 | $r->push_handlers(PerlCleanupHandler => sub { 50 | if ( Netdot::Model->db_auto_commit == 0 ){ 51 | Netdot::Model->dbi_rollback(); 52 | Netdot::Model->db_auto_commit(1); 53 | } 54 | }); 55 | 56 | # We don't need to handle non-text items 57 | return -1 if $r->content_type && $r->content_type !~ m|^text/|i; 58 | 59 | return $ah->handle_request($r); 60 | 61 | } 62 | 63 | =head1 AUTHORS 64 | 65 | Carlos Vicente, Nathan Collins, Aaron Parecki, Peter Boothe. 66 | 67 | =head1 COPYRIGHT & LICENSE 68 | 69 | Copyright 2012 University of Oregon, all rights reserved. 70 | 71 | This program is free software; you can redistribute it and/or modify 72 | it under the terms of the GNU General Public License as published by 73 | the Free Software Foundation; either version 2 of the License, or 74 | (at your option) any later version. 75 | 76 | This program is distributed in the hope that it will be useful, but 77 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 78 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 79 | License for more details. 80 | 81 | You should have received a copy of the GNU General Public License 82 | along with this program; if not, write to the Free Software Foundation, 83 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 84 | 85 | =cut 86 | 87 | # Make sure to return 1 88 | 1; 89 | 90 | -------------------------------------------------------------------------------- /lib/Netdot/Model/AccessRight.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::AccessRight; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | my $logger = Netdot->log->get_logger('Netdot::Model'); 8 | 9 | # Classes used for access rights 10 | my %CLASSES = ( 11 | Device => 1, 12 | Ipblock => 1, 13 | ContactList => 1, 14 | Zone => 1, 15 | ); 16 | 17 | # Make sure to return 1 18 | 1; 19 | 20 | =head1 NAME 21 | 22 | Netdot::Model::AccessRight 23 | 24 | =head1 SYNOPSIS 25 | 26 | =head1 CLASS METHODS 27 | =cut 28 | 29 | ######################################################################## 30 | 31 | =head2 get_classes - Get a list of classes with access rights 32 | 33 | This is useful in places like Model::delete() where we can avoid 34 | searching for access rights if we know that the object being 35 | deleted does not deal with rights 36 | 37 | Arguments: 38 | None 39 | Returns: 40 | Hash with key = class name 41 | Examples: 42 | my %aclasses = AccessRight->get_classes(); 43 | 44 | =cut 45 | 46 | sub get_classes{ 47 | my ($self) = @_; 48 | return %CLASSES; 49 | } 50 | 51 | 52 | =head1 INSTANCE METHODS 53 | =cut 54 | 55 | ######################################################################## 56 | 57 | =head2 get_label - Get object label 58 | 59 | Arguments: 60 | None 61 | Returns: 62 | String 63 | Examples: 64 | print $accessright->get_label(); 65 | 66 | =cut 67 | 68 | sub get_label{ 69 | my ($self) = @_; 70 | $self->isa_object_method('get_label'); 71 | if ( $self->access ){ 72 | if ( $self->object_class && $self->object_id ){ 73 | my $oclass = $self->object_class; 74 | my $oid = $self->object_id; 75 | my $obj_lbl = $oclass->retrieve($oid)->get_label; 76 | return $self->object_class." ".$obj_lbl." - ".$self->access; 77 | }elsif ( $self->object_class ){ 78 | return $self->object_class." - ".$self->access; 79 | } 80 | }else{ 81 | return "?"; 82 | } 83 | } 84 | 85 | 86 | =head1 AUTHOR 87 | 88 | Carlos Vicente, C<< >> 89 | 90 | =head1 COPYRIGHT & LICENSE 91 | 92 | Copyright 2012 University of Oregon, all rights reserved. 93 | 94 | This program is free software; you can redistribute it and/or modify 95 | it under the terms of the GNU General Public License as published by 96 | the Free Software Foundation; either version 2 of the License, or 97 | (at your option) any later version. 98 | 99 | This program is distributed in the hope that it will be useful, but 100 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 101 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 102 | License for more details. 103 | 104 | You should have received a copy of the GNU General Public License 105 | along with this program; if not, write to the Free Software Foundation, 106 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 107 | 108 | =cut 109 | 110 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Circuit.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::Circuit; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | my $logger = Netdot->log->get_logger('Netdot::Model'); 8 | 9 | =head1 NAME 10 | 11 | Netdot::Model::Circuit 12 | 13 | =head1 INSTANCE METHODS 14 | =cut 15 | 16 | ################################################################################### 17 | 18 | =head2 search_by_keyword - Search Circuits by keywords 19 | 20 | Relevant fields include: CID, SiteLink name, Site names, SiteLink Entity 21 | 22 | Arguments: 23 | string or substring 24 | Returns: 25 | array of Circuit objects 26 | Examples: 27 | 28 | =cut 29 | 30 | sub search_by_keyword { 31 | my ($class, $string) = @_; 32 | my $crit = "%" . $string . "%"; 33 | my (@sites, @slinks, @ent); 34 | my %c; # Hash to prevent dups 35 | 36 | map { $c{$_} = $_ } Circuit->search_like(cid => $crit); 37 | @sites = Site->search_like(name => $crit); 38 | @slinks = SiteLink->search_like(name => $crit); 39 | @ent = Entity->search_like(name => $crit); 40 | 41 | map { push @slinks, $_->farlinks } @sites; 42 | map { push @slinks, $_->nearlinks } @sites; 43 | map { push @slinks, $_->links } @ent; 44 | map { $c{$_} = $_ } map { $_->circuits } @slinks; 45 | 46 | my @c = map { $c{$_} } keys %c; 47 | 48 | wantarray ? ( @c ) : $c[0]; 49 | 50 | } 51 | 52 | =head1 AUTHOR 53 | 54 | Carlos Vicente, C<< >> 55 | 56 | =head1 COPYRIGHT & LICENSE 57 | 58 | Copyright 2012 University of Oregon, all rights reserved. 59 | 60 | This program is free software; you can redistribute it and/or modify 61 | it under the terms of the GNU General Public License as published by 62 | the Free Software Foundation; either version 2 of the License, or 63 | (at your option) any later version. 64 | 65 | This program is distributed in the hope that it will be useful, but 66 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 67 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 68 | License for more details. 69 | 70 | You should have received a copy of the GNU General Public License 71 | along with this program; if not, write to the Free Software Foundation, 72 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 73 | 74 | =cut 75 | 76 | #Be sure to return 1 77 | 1; 78 | -------------------------------------------------------------------------------- /lib/Netdot/Model/ClosetPicture.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::ClosetPicture; 2 | 3 | use base 'Netdot::Model::Picture'; 4 | use warnings; 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::Module::ClosetPicture 10 | 11 | =head1 SYNOPSIS 12 | 13 | See Netdot::Model::Picture 14 | 15 | =head1 CLASS METHODS 16 | =cut 17 | 18 | =head2 insert 19 | 20 | Arguments: 21 | Hashref with key/value pairs 22 | Returns: 23 | New Picture object 24 | Examples: 25 | 26 | sub insert { 27 | my ($self, $argv) = @_; 28 | defined $argv->{closet} || 29 | $self->throw_fatal("Missing required arguments: closet"); 30 | 31 | return $self->SUPER::insert($argv); 32 | } 33 | 34 | =head1 AUTHOR 35 | 36 | Carlos Vicente, C<< >> 37 | 38 | =head1 COPYRIGHT & LICENSE 39 | 40 | Copyright 2012 University of Oregon, all rights reserved. 41 | 42 | This program is free software; you can redistribute it and/or modify 43 | it under the terms of the GNU General Public License as published by 44 | the Free Software Foundation; either version 2 of the License, or 45 | (at your option) any later version. 46 | 47 | This program is distributed in the hope that it will be useful, but 48 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 49 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 50 | License for more details. 51 | 52 | You should have received a copy of the GNU General Public License 53 | along with this program; if not, write to the Free Software Foundation, 54 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 55 | 56 | =cut 57 | 58 | 1; 59 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Contact.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::Contact; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::Model::Contact 10 | 11 | =head1 INSTANCE METHODS 12 | =cut 13 | 14 | ################################################################## 15 | 16 | =head2 get_label - Override get_label method 17 | 18 | Arguments: 19 | None 20 | Returns: 21 | string 22 | Examples: 23 | print $contact->get_label(); 24 | 25 | =cut 26 | 27 | sub get_label { 28 | my $self = shift; 29 | my $lbl = $self->person->get_label; 30 | $lbl .= ": ". $self->contacttype->name; 31 | return $lbl; 32 | } 33 | 34 | # Make sure to return 1 35 | 1; 36 | 37 | =head1 AUTHOR 38 | 39 | Carlos Vicente, C<< >> 40 | 41 | =head1 COPYRIGHT & LICENSE 42 | 43 | Copyright 2012 University of Oregon, all rights reserved. 44 | 45 | This program is free software; you can redistribute it and/or modify 46 | it under the terms of the GNU General Public License as published by 47 | the Free Software Foundation; either version 2 of the License, or 48 | (at your option) any later version. 49 | 50 | This program is distributed in the hope that it will be useful, but 51 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 52 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 53 | License for more details. 54 | 55 | You should have received a copy of the GNU General Public License 56 | along with this program; if not, write to the Free Software Foundation, 57 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 58 | 59 | =cut 60 | 61 | 1; 62 | -------------------------------------------------------------------------------- /lib/Netdot/Model/DataCache.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::DataCache; 2 | 3 | use base 'Netdot::Model'; 4 | use APR::Base64; 5 | use warnings; 6 | use strict; 7 | 8 | my $logger = Netdot->log->get_logger("Netdot::Model"); 9 | 10 | =head1 NAME 11 | 12 | Netdot::Model::DataCache 13 | 14 | =head1 SYNOPSIS 15 | 16 | The purpose of this class is only to add triggers for data manipulation, 17 | which are only needed when Postgres is used as the database. 18 | 19 | =cut 20 | 21 | ################################################# 22 | # Add some triggers 23 | # 24 | # Postgresql's fields of type 'bytea' must be encoded prior to storing 25 | # 26 | __PACKAGE__->add_trigger( deflate_for_create => \&_encode_bindata ); 27 | __PACKAGE__->add_trigger( deflate_for_update => \&_encode_bindata ); 28 | __PACKAGE__->add_trigger( select => \&_decode_bindata ); 29 | 30 | ################################################# 31 | # 32 | # Called before insert/update 33 | # 34 | sub _encode_bindata{ 35 | my $self = shift; 36 | return 1 unless ( $self->config->get('DB_TYPE') eq 'Pg' ); 37 | my $data = ($self->_attrs('data'))[0]; 38 | my $encoded = APR::Base64::encode($data); 39 | $self->_attribute_store( data => $encoded ); 40 | return 1; 41 | } 42 | 43 | ################################################# 44 | # 45 | # Called before select 46 | # 47 | sub _decode_bindata{ 48 | my $self = shift; 49 | return 1 unless ( $self->config->get('DB_TYPE') eq 'Pg' ); 50 | my $id = $self->id; 51 | my $dbh = $self->db_Main; 52 | my $encoded = ($dbh->selectrow_array("SELECT data FROM datacache WHERE id = $id"))[0]; 53 | unless ( $encoded ){ 54 | $logger->error("DataCache::_decode_bindata: No data available from DataCache id $id"); 55 | return 1; 56 | } 57 | my $decoded = APR::Base64::decode($encoded); 58 | unless ( $decoded ){ 59 | $logger->error("DataCache::_decode_bindata: Problem decoding bindata for DataCache id $id"); 60 | return 1; 61 | } 62 | $self->_attribute_store( data => $decoded ); 63 | return 1; 64 | } 65 | 66 | 67 | =head1 AUTHOR 68 | 69 | Carlos Vicente, C<< >> 70 | 71 | =head1 COPYRIGHT & LICENSE 72 | 73 | Copyright 2012 University of Oregon, all rights reserved. 74 | 75 | This program is free software; you can redistribute it and/or modify 76 | it under the terms of the GNU General Public License as published by 77 | the Free Software Foundation; either version 2 of the License, or 78 | (at your option) any later version. 79 | 80 | This program is distributed in the hope that it will be useful, but 81 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 82 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 83 | License for more details. 84 | 85 | You should have received a copy of the GNU General Public License 86 | along with this program; if not, write to the Free Software Foundation, 87 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 88 | 89 | =cut 90 | 91 | 1; 92 | -------------------------------------------------------------------------------- /lib/Netdot/Model/DeviceModule.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::DeviceModule; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | use Data::Dumper; 7 | 8 | my $logger = Netdot->log->get_logger('Netdot::Model::Device'); 9 | 10 | =head1 NAME 11 | 12 | Netdot::Model::DeviceModule - Device Module Class 13 | 14 | =head1 CLASS METHODS 15 | =cut 16 | 17 | ################################################################ 18 | 19 | =head2 insert - Insert DeviceModule object 20 | 21 | We override the insert method for extra functionality 22 | - Automatically assign timestamps 23 | 24 | Arguments: 25 | Hash ref with field/value pairs 26 | Returns: 27 | New DeviceModule object 28 | Examples: 29 | DeviceModule->insert({number=>1, name=>"blah"}); 30 | =cut 31 | 32 | sub insert { 33 | my ($class, $argv) = @_; 34 | $argv->{date_installed} = $class->timestamp(); 35 | $argv->{last_updated} = $class->timestamp(); 36 | return $class->SUPER::insert( $argv ); 37 | } 38 | 39 | =head1 OBJECT METHODS 40 | =cut 41 | 42 | ################################################################ 43 | 44 | =head2 update - Update DeviceModule object 45 | 46 | We override the update method for extra functionality 47 | - Automatically assign timestamps 48 | 49 | Arguments: 50 | Hash ref with field/value pairs 51 | Returns: 52 | See Class::DBI::update() 53 | Examples: 54 | $module->update({number=>1, name=>"blah"}); 55 | =cut 56 | 57 | sub update { 58 | my ($self, $argv) = @_; 59 | $argv->{last_updated} = $self->timestamp(); 60 | return $self->SUPER::update( $argv ); 61 | } 62 | 63 | =head1 AUTHOR 64 | 65 | Carlos Vicente, C<< >> 66 | 67 | =head1 COPYRIGHT & LICENSE 68 | 69 | Copyright 2012 University of Oregon, all rights reserved. 70 | 71 | This program is free software; you can redistribute it and/or modify 72 | it under the terms of the GNU General Public License as published by 73 | the Free Software Foundation; either version 2 of the License, or 74 | (at your option) any later version. 75 | 76 | This program is distributed in the hope that it will be useful, but 77 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 78 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 79 | License for more details. 80 | 81 | You should have received a copy of the GNU General Public License 82 | along with this program; if not, write to the Free Software Foundation, 83 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 84 | 85 | =cut 86 | 87 | #Be sure to return 1 88 | 1; 89 | 90 | -------------------------------------------------------------------------------- /lib/Netdot/Model/FWTableEntry.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::FWTableEntry; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | my $logger = Netdot->log->get_logger('Netdot::Model::Device'); 8 | 9 | # Make sure to return 1 10 | 1; 11 | 12 | =head1 NAME 13 | 14 | Netdot::Model::FWTableEntry 15 | 16 | =head1 SYNOPSIS 17 | 18 | Forwarding Table Entry class 19 | 20 | =head1 CLASS METHODS 21 | =cut 22 | 23 | ################################################################## 24 | 25 | =head2 fast_insert - Faster inserts for specific cases 26 | 27 | This method will traverse a list of hashes containing FWT 28 | info. Meant to be used by processes that insert/update large amounts of 29 | objects. We use direct SQL commands for improved speed. 30 | 31 | Notice that the PhysAddr (MAC) objects must exist prior to calling this. 32 | 33 | Arguments: 34 | Array ref containing hash refs with following keys: 35 | fwtable - id of ArpCache table record 36 | interface - id of Interface 37 | physaddr - string with mac address 38 | 39 | Returns: 40 | True if successul 41 | Examples: 42 | FWTableEntry->fast_insert(list=>\@list); 43 | 44 | =cut 45 | 46 | sub fast_insert{ 47 | my ($class, %argv) = @_; 48 | $class->isa_class_method('fast_insert'); 49 | 50 | my $list = $argv{list} || $class->throw_fatal('Missing list arg'); 51 | 52 | # Build SQL query 53 | my $dbh = $class->db_Main; 54 | my $sth= $dbh->prepare_cached("INSERT INTO fwtableentry 55 | (fwtable,interface,physaddr) 56 | VALUES (?, ?, (SELECT id FROM physaddr WHERE address=?))"); 57 | foreach my $r ( @$list ){ 58 | $sth->execute($r->{fwtable}, 59 | $r->{interface}, 60 | $r->{physaddr}); 61 | } 62 | return 1; 63 | } 64 | 65 | 66 | =head1 INSTANCE METHODS 67 | 68 | =cut 69 | 70 | =head1 AUTHOR 71 | 72 | Carlos Vicente, C<< >> 73 | 74 | =head1 COPYRIGHT & LICENSE 75 | 76 | Copyright 2012 University of Oregon, all rights reserved. 77 | 78 | This program is free software; you can redistribute it and/or modify 79 | it under the terms of the GNU General Public License as published by 80 | the Free Software Foundation; either version 2 of the License, or 81 | (at your option) any later version. 82 | 83 | This program is distributed in the hope that it will be useful, but 84 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 85 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 86 | License for more details. 87 | 88 | You should have received a copy of the GNU General Public License 89 | along with this program; if not, write to the Free Software Foundation, 90 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 91 | 92 | =cut 93 | 94 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Floor.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::Floor; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | my $logger = Netdot->log->get_logger('Netdot::Model'); 8 | 9 | =head1 NAME 10 | 11 | Netdot::Model::Floor 12 | 13 | =head1 CLASS METHODS 14 | =cut 15 | 16 | ################################################################## 17 | 18 | =head2 insert - Insert new object 19 | 20 | Arguments: 21 | Any of Floor's fields 22 | Returns: 23 | New Floor object 24 | Examples: 25 | my $floor = Floor->insert(\%args); 26 | 27 | =cut 28 | 29 | sub insert { 30 | my ($class, $argv) = @_; 31 | $class->_validate_args($argv); 32 | return $class->SUPER::insert($argv); 33 | } 34 | 35 | 36 | =head1 INSTANCE METHODS 37 | =cut 38 | 39 | ################################################################## 40 | 41 | =head2 update - Update object's values 42 | 43 | Arguments: 44 | Any of Floor's fields 45 | Returns: 46 | See Class::DBI's update method 47 | Examples: 48 | $floor->update(\%args); 49 | 50 | =cut 51 | 52 | sub update { 53 | my ($self, $argv) = @_; 54 | $self->isa_object_method('update'); 55 | $self->_validate_args($argv); 56 | return $self->SUPER::update($argv); 57 | } 58 | 59 | 60 | ################################################################## 61 | # Private methods 62 | ################################################################## 63 | 64 | # 65 | # Validate args passed to insert and update 66 | # 67 | sub _validate_args { 68 | my ($self, $argv) = @_; 69 | foreach my $field ( qw/level site/ ){ 70 | $self->throw_user("Missing required argument: $field") 71 | unless ( $argv->{$field} ); 72 | } 73 | 1; 74 | } 75 | 76 | =head1 AUTHOR 77 | 78 | Carlos Vicente, C<< >> 79 | 80 | =head1 COPYRIGHT & LICENSE 81 | 82 | Copyright 2012 University of Oregon, all rights reserved. 83 | 84 | This program is free software; you can redistribute it and/or modify 85 | it under the terms of the GNU General Public License as published by 86 | the Free Software Foundation; either version 2 of the License, or 87 | (at your option) any later version. 88 | 89 | This program is distributed in the hope that it will be useful, but 90 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 91 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 92 | License for more details. 93 | 94 | You should have received a copy of the GNU General Public License 95 | along with this program; if not, write to the Free Software Foundation, 96 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 97 | 98 | =cut 99 | 100 | 1; 101 | -------------------------------------------------------------------------------- /lib/Netdot/Model/FloorPicture.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::FloorPicture; 2 | 3 | use base 'Netdot::Model::Picture'; 4 | use warnings; 5 | use strict; 6 | 7 | # Make sure to return 1 8 | 1; 9 | 10 | =head1 NAME 11 | 12 | Netdot::Module::FloorPicture 13 | 14 | =head1 SYNOPSIS 15 | 16 | See Netdot::Model::Picture 17 | 18 | =head1 CLASS METHODS 19 | =cut 20 | 21 | ################################################################## 22 | 23 | =head2 insert - Insert new object 24 | 25 | Arguments: 26 | Any of FloorPicture's fields 27 | Returns: 28 | New FloorPicture object 29 | Examples: 30 | my $fp = FloorPicture->insert(\%args); 31 | 32 | =cut 33 | 34 | sub insert { 35 | my ($class, $argv) = @_; 36 | $argv->{floor} || 37 | $class->throw_user("Missing required arguments: floor"); 38 | return $class->SUPER::insert($argv); 39 | } 40 | 41 | =head1 INSTANCE METHODS 42 | =cut 43 | 44 | ################################################################## 45 | 46 | =head2 update - Update object's values 47 | 48 | Arguments: 49 | Any of FloorPicture's fields 50 | Returns: 51 | See Class::DBI's update method 52 | Examples: 53 | $fp->update(\%args); 54 | 55 | =cut 56 | 57 | sub update { 58 | my ($self, $argv) = @_; 59 | $self->isa_object_method('update'); 60 | if ( exists $argv->{floor} && $argv->{floor} == 0 ){ 61 | $self->throw_user("Missing required arguments: floor"); 62 | } 63 | return $self->SUPER::update($argv); 64 | } 65 | =head1 AUTHOR 66 | 67 | Carlos Vicente, C<< >> 68 | 69 | =head1 COPYRIGHT & LICENSE 70 | 71 | Copyright 2012 University of Oregon, all rights reserved. 72 | 73 | This program is free software; you can redistribute it and/or modify 74 | it under the terms of the GNU General Public License as published by 75 | the Free Software Foundation; either version 2 of the License, or 76 | (at your option) any later version. 77 | 78 | This program is distributed in the hope that it will be useful, but 79 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 80 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 81 | License for more details. 82 | 83 | You should have received a copy of the GNU General Public License 84 | along with this program; if not, write to the Free Software Foundation, 85 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 86 | 87 | =cut 88 | 89 | 1; 90 | -------------------------------------------------------------------------------- /lib/Netdot/Model/GroupRight.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::GroupRight; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::Model::GroupRight - Manipulate GroupRight objects 10 | 11 | =cut 12 | 13 | my $logger = Netdot->log->get_logger('Netdot::Model'); 14 | 15 | =head1 CLASS METHODS 16 | =cut 17 | 18 | ######################################################################### 19 | 20 | =head2 insert - Insert a new GroupRight object 21 | 22 | We override the insert method for extra functionality 23 | - Ignore duplicates 24 | - Check if 'none' exists for given object and complain. 25 | - If adding 'none' remove all other rights 26 | 27 | Args: 28 | userright table fields 29 | Returns: 30 | GroupRight object 31 | Examples: 32 | GroupRight->insert({contactlist=>$cl_id, accessright=>$ar_id }); 33 | 34 | =cut 35 | 36 | sub insert { 37 | my ($class, $argv) = @_; 38 | $class->throw_fatal("Model::GroupRight::insert: Missing required arguments") 39 | unless ( $argv->{contactlist} && $argv->{accessright} ); 40 | 41 | my $accessright = AccessRight->retrieve(int($argv->{accessright})); 42 | my $cl = ContactList->retrieve(int($argv->{contactlist})); 43 | 44 | foreach my $r ( $cl->access_rights ){ 45 | my $ar = $r->accessright; 46 | if ( $ar->object_class eq $accessright->object_class && 47 | $ar->object_id eq $accessright->object_id ){ 48 | # same object 49 | if ( $accessright->access eq $ar->access ){ 50 | # Do not try to insert rights if they exist 51 | return $r; 52 | } 53 | if ( $accessright->access ne 'none' && $ar->access eq 'none' ){ 54 | $class->throw_user("Cannot add other rights while 'none' right exists"); 55 | 56 | }elsif ( $accessright->access eq 'none' && $ar->access ne 'none' ){ 57 | $logger->debug("GroupRight::insert: Removing ".$ar->access." access on ". 58 | $ar->object_class." id ".$ar->object_id); 59 | $ar->delete(); 60 | } 61 | } 62 | } 63 | return $class->SUPER::insert($argv); 64 | } 65 | 66 | =head1 AUTHOR 67 | 68 | Carlos Vicente, C<< >> 69 | 70 | =head1 COPYRIGHT & LICENSE 71 | 72 | Copyright 2012 University of Oregon, all rights reserved. 73 | 74 | This program is free software; you can redistribute it and/or modify 75 | it under the terms of the GNU General Public License as published by 76 | the Free Software Foundation; either version 2 of the License, or 77 | (at your option) any later version. 78 | 79 | This program is distributed in the hope that it will be useful, but 80 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 81 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 82 | License for more details. 83 | 84 | You should have received a copy of the GNU General Public License 85 | along with this program; if not, write to the Free Software Foundation, 86 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 87 | 88 | =cut 89 | 90 | 1; 91 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Nullify.pm: -------------------------------------------------------------------------------- 1 | package Class::DBI::Cascade::Nullify; 2 | 3 | =head1 NAME 4 | 5 | Class::DBI::Cascade::Nullify - Set Foreign keys to null when deleting 6 | 7 | =head1 SYNOPSIS 8 | 9 | This is a Cascading Delete strategy that will nullify the foreign keys 10 | of relatd objects/ See Class::DBI for more information. 11 | 12 | =cut 13 | 14 | use strict; 15 | use warnings; 16 | 17 | use base 'Class::DBI::Cascade::None'; 18 | 19 | =head2 cascade 20 | 21 | =cut 22 | 23 | sub cascade { 24 | my ($self, $obj) = @_; 25 | map { $_->set($self->{_rel}->args->{foreign_key}, undef); 26 | $_->update; 27 | } $self->foreign_for($obj); 28 | } 29 | 30 | =head1 AUTHORS 31 | 32 | Carlos Vicente, C<< >> with contributions from Nathan Collins and Aaron Parecki. 33 | 34 | =head1 COPYRIGHT & LICENSE 35 | 36 | Copyright 2012 University of Oregon, all rights reserved. 37 | 38 | This program is free software; you can redistribute it and/or modify 39 | it under the terms of the GNU General Public License as published by 40 | the Free Software Foundation; either version 2 of the License, or 41 | (at your option) any later version. 42 | 43 | This program is distributed in the hope that it will be useful, but 44 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 45 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 46 | License for more details. 47 | 48 | You should have received a copy of the GNU General Public License 49 | along with this program; if not, write to the Free Software Foundation, 50 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 51 | 52 | =cut 53 | 54 | 1; 55 | -------------------------------------------------------------------------------- /lib/Netdot/Model/OUI.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::OUI; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | my $logger = Netdot->log->get_logger('Netdot::Model::Device'); 8 | 9 | =head1 NAME 10 | 11 | Netdot::Model::OUI - Organizational Unique Identifier (OUI) Class 12 | 13 | =head1 CLASS METHODS 14 | =cut 15 | 16 | ############################################################################ 17 | 18 | =head2 retrieve_all_hashref - Build a hash with key=OUI, value=vendor 19 | 20 | Arguments: 21 | None 22 | Returns: 23 | Hash reference 24 | Examples: 25 | my $uois = OUI->retrieve_all_hashref(); 26 | 27 | 28 | =cut 29 | 30 | sub retrieve_all_hashref { 31 | my ($class) = @_; 32 | $class->isa_class_method('retrieve_all_hashref'); 33 | 34 | # Build the search-all-macs SQL query 35 | my ($aref, %oui, $sth); 36 | 37 | my $dbh = $class->db_Main; 38 | eval { 39 | $sth = $dbh->prepare_cached("SELECT oui,vendor FROM oui"); 40 | $sth->execute(); 41 | $aref = $sth->fetchall_arrayref; 42 | }; 43 | if ( my $e = $@ ){ 44 | $class->throw_fatal($e); 45 | } 46 | # Build a hash 47 | foreach my $row ( @$aref ){ 48 | my ($oui, $vendor) = @$row; 49 | $oui{$oui} = $vendor; 50 | } 51 | return \%oui; 52 | } 53 | 54 | =head1 AUTHOR 55 | 56 | Carlos Vicente, C<< >> 57 | 58 | =head1 COPYRIGHT & LICENSE 59 | 60 | Copyright 2012 University of Oregon, all rights reserved. 61 | 62 | This program is free software; you can redistribute it and/or modify 63 | it under the terms of the GNU General Public License as published by 64 | the Free Software Foundation; either version 2 of the License, or 65 | (at your option) any later version. 66 | 67 | This program is distributed in the hope that it will be useful, but 68 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 69 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 70 | License for more details. 71 | 72 | You should have received a copy of the GNU General Public License 73 | along with this program; if not, write to the Free Software Foundation, 74 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 75 | 76 | =cut 77 | 78 | #Be sure to return 1 79 | 1; 80 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Picture.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::Picture; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | use APR::Base64; 7 | 8 | =head1 NAME 9 | 10 | Netdot::Module::Picture 11 | 12 | =cut 13 | 14 | my %MIMETYPES = ( 15 | "jpg" => "image/jpeg", "jpeg" => "image/jpeg", "gif" => "image/gif", 16 | "png" => "image/png", "bmp" => "image/bmp", "tiff" => "image/tiff", 17 | "tif" => "image/tiff", "pdf" => "application/pdf"); 18 | 19 | my $logger = Netdot->log->get_logger("Netdot::Model"); 20 | 21 | =head1 CLASS METHODS 22 | 23 | ############################################################################# 24 | 25 | =head2 insert - Inserts a picture into the DB. 26 | 27 | If filetype is not specified it will be (hopefully) determined automatically. 28 | 29 | Arguments: 30 | Key value pairs 31 | Returns: 32 | New Picture object 33 | Examples: 34 | $newobj = Picture->insert({filename=>'filename.ext'}); 35 | 36 | =cut 37 | 38 | sub insert { 39 | my ($self, $argv) = @_; 40 | ( defined $argv->{filename} && defined $argv->{bindata} ) || 41 | $self->throw_fatal("Missing required arguments: filename, bindata"); 42 | 43 | # Grab extension 44 | my $extension = $1 if ( $argv->{filename} =~ /\.(\w+)$/ ); 45 | 46 | # Determine filetype 47 | if ( !exists $argv->{filetype} && defined $extension ){ 48 | # Try to guess type from extension 49 | $extension = lc($extension); 50 | $argv->{filetype} = $MIMETYPES{$extension} || 51 | $self->throw_user("File type could not be determined: extension \".$extension\" is unknown."); 52 | }else{ 53 | $self->throw_user("File type could not be determined."); 54 | } 55 | $argv->{filesize} ||= length($argv->{bindata}); 56 | return $self->SUPER::insert($argv); 57 | } 58 | 59 | ################################################# 60 | # Handle PostgreSQL's bytea types correctly. 61 | # 62 | 63 | if (__PACKAGE__->config->get('DB_TYPE') eq 'Pg') { 64 | require DBD::Pg; 65 | __PACKAGE__->data_type(bindata => { pg_type => &DBD::Pg::PG_BYTEA }); 66 | } 67 | 68 | =head1 AUTHOR 69 | 70 | Carlos Vicente, C<< >> 71 | 72 | =head1 COPYRIGHT & LICENSE 73 | 74 | Copyright 2012 University of Oregon, all rights reserved. 75 | 76 | This program is free software; you can redistribute it and/or modify 77 | it under the terms of the GNU General Public License as published by 78 | the Free Software Foundation; either version 2 of the License, or 79 | (at your option) any later version. 80 | 81 | This program is distributed in the hope that it will be useful, but 82 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 83 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 84 | License for more details. 85 | 86 | You should have received a copy of the GNU General Public License 87 | along with this program; if not, write to the Free Software Foundation, 88 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 89 | 90 | =cut 91 | 92 | 1; 93 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Plugins/DeviceIpNamesFixed.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::Plugins::DeviceIpNamesFixed; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::Model::Plugins::DeviceIpNamesFixed 10 | 11 | =head1 DESCRIPTION 12 | 13 | This plugin is used at Device discovery time to automate the creation 14 | and maintenance of DNS records for IP addresses that belong to devices. 15 | 16 | This particular plugin only sets the record to the device name 17 | 18 | =head1 SYNOPSIS 19 | 20 | Netdot::Model::Plugins::DeviceIpNamesFromDNS->new(); 21 | my $name = Netdot::Model::Plugins::DeviceIpNamesFromDNS->get_name($ipblock); 22 | 23 | =cut 24 | 25 | ############################################################################ 26 | 27 | =head2 new - Class constructor 28 | 29 | Arguments: 30 | None 31 | Returns: 32 | Plugin object 33 | Examples: 34 | 35 | =cut 36 | 37 | sub new{ 38 | my ($proto, %argv) = @_; 39 | my $class = ref($proto) || $proto; 40 | my $self = {}; 41 | bless $self, $class; 42 | } 43 | 44 | ############################################################################ 45 | 46 | =head2 new - Class constructor 47 | 48 | Arguments: 49 | Ipblock object 50 | Returns: 51 | Name String 52 | Examples: 53 | $plugin->get_name($ip); 54 | 55 | =cut 56 | 57 | sub get_name { 58 | my ($self, $ip) = @_; 59 | 60 | return $ip->interface->device->short_name; 61 | } 62 | 63 | 1; 64 | 65 | =head1 AUTHORS 66 | 67 | Carlos Vicente, C<< >> 68 | 69 | =head1 COPYRIGHT & LICENSE 70 | 71 | Copyright 2012 University of Oregon, all rights reserved. 72 | 73 | This program is free software; you can redistribute it and/or modify 74 | it under the terms of the GNU General Public License as published by 75 | the Free Software Foundation; either version 2 of the License, or 76 | (at your option) any later version. 77 | 78 | This program is distributed in the hope that it will be useful, but 79 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 80 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 81 | License for more details. 82 | 83 | You should have received a copy of the GNU General Public License 84 | along with this program; if not, write to the Free Software Foundation, 85 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 86 | 87 | =cut 88 | 89 | 90 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Plugins/DeviceIpNamesFromDNS.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::Plugins::DeviceIpNamesFromDNS; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::Model::Plugins::DeviceIpNamesFromDNS 10 | 11 | =head1 DESCRIPTION 12 | 13 | This plugin is used at Device discovery time to automate the creation 14 | and maintenance of DNS records for IP addresses that belong to devices. 15 | 16 | This particular plugin uses DNS information to create the records 17 | in Netdot. 18 | 19 | =head1 SYNOPSIS 20 | 21 | Netdot::Model::Plugins::DeviceIpNamesFromDNS->new(); 22 | my $name = Netdot::Model::Plugins::DeviceIpNamesFromDNS->get_name($ipblock); 23 | 24 | =cut 25 | 26 | ############################################################################ 27 | 28 | =head2 new - Class constructor 29 | 30 | Arguments: 31 | None 32 | Returns: 33 | Plugin object 34 | Examples: 35 | 36 | =cut 37 | 38 | sub new{ 39 | my ($proto, %argv) = @_; 40 | my $class = ref($proto) || $proto; 41 | my $self = {}; 42 | bless $self, $class; 43 | } 44 | 45 | ############################################################################ 46 | 47 | =head2 get_name 48 | 49 | Return the current DNS name for this IP. 50 | If IP does not resolve, return IP address. 51 | 52 | =cut 53 | 54 | sub get_name { 55 | my ($self, $ip) = @_; 56 | 57 | my $name; 58 | unless ( $name = Netdot->dns->resolve_ip($ip->address) ){ 59 | $name = $ip->address; 60 | } 61 | return $name; 62 | } 63 | 64 | =head1 AUTHORS 65 | 66 | Carlos Vicente, C<< >> 67 | 68 | =head1 COPYRIGHT & LICENSE 69 | 70 | Copyright 2012 University of Oregon, all rights reserved. 71 | 72 | This program is free software; you can redistribute it and/or modify 73 | it under the terms of the GNU General Public License as published by 74 | the Free Software Foundation; either version 2 of the License, or 75 | (at your option) any later version. 76 | 77 | This program is distributed in the hope that it will be useful, but 78 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 79 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 80 | License for more details. 81 | 82 | You should have received a copy of the GNU General Public License 83 | along with this program; if not, write to the Free Software Foundation, 84 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 85 | 86 | =cut 87 | 88 | # Make sure to return 1 89 | 1; 90 | -------------------------------------------------------------------------------- /lib/Netdot/Model/SitePicture.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::SitePicture; 2 | 3 | use base 'Netdot::Model::Picture'; 4 | use warnings; 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::Model::Picture 10 | 11 | =head1 CLASS METHODS 12 | =cut 13 | 14 | =head2 insert 15 | 16 | =cut 17 | 18 | sub insert { 19 | my ($self, $argv) = @_; 20 | defined $argv->{site} || 21 | $self->throw_fatal("Missing required arguments: site"); 22 | 23 | return $self->SUPER::insert($argv); 24 | } 25 | 26 | =head1 AUTHOR 27 | 28 | Carlos Vicente, C<< >> 29 | 30 | =head1 COPYRIGHT & LICENSE 31 | 32 | Copyright 2012 University of Oregon, all rights reserved. 33 | 34 | This program is free software; you can redistribute it and/or modify 35 | it under the terms of the GNU General Public License as published by 36 | the Free Software Foundation; either version 2 of the License, or 37 | (at your option) any later version. 38 | 39 | This program is distributed in the hope that it will be useful, but 40 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 41 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 42 | License for more details. 43 | 44 | You should have received a copy of the GNU General Public License 45 | along with this program; if not, write to the Free Software Foundation, 46 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 47 | 48 | =cut 49 | 50 | 1; 51 | -------------------------------------------------------------------------------- /lib/Netdot/Model/Splice.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::Splice; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | my $logger = Netdot->log->get_logger('Netdot::Model'); 8 | 9 | =head1 NAME 10 | 11 | Netdot::Model::Splice 12 | 13 | =head1 CLASS METHODS 14 | =cut 15 | 16 | ################################################################## 17 | 18 | =head2 insert 19 | 20 | Splice together strand1 and strand2. 21 | Note: Two Splice objects are created (bi-directional) 22 | 23 | Arguments: 24 | - strand1, strand2: the CableStrand objects to create a splice for. 25 | Returns: 26 | New Splice object 27 | Examples: 28 | Splice->insert({strand1=>$strand1, strand2=>$strand2}) 29 | 30 | =cut 31 | 32 | sub insert { 33 | my ($class, $argv) = @_; 34 | $class->isa_class_method('insert'); 35 | 36 | $class->throw_fatal("Missing required arguments: strand1/strand2") 37 | unless ( exists $argv->{strand1} && exists $argv->{strand2} ); 38 | 39 | $class->throw_user("You cannot splice a strand with itself!") 40 | if ( $argv->{strand1} == $argv->{strand2} ); 41 | 42 | # Insert inverse first 43 | $class->SUPER::insert({strand1=>$argv->{strand2}, strand2=>$argv->{strand1}}); 44 | 45 | return $class->SUPER::insert($argv); 46 | } 47 | 48 | =head1 AUTHORS 49 | 50 | Kai Waldron & Carlos Vicente, C<< >> 51 | 52 | =head1 COPYRIGHT & LICENSE 53 | 54 | Copyright 2012 University of Oregon, all rights reserved. 55 | 56 | This program is free software; you can redistribute it and/or modify 57 | it under the terms of the GNU General Public License as published by 58 | the Free Software Foundation; either version 2 of the License, or 59 | (at your option) any later version. 60 | 61 | This program is distributed in the hope that it will be useful, but 62 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 63 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 64 | License for more details. 65 | 66 | You should have received a copy of the GNU General Public License 67 | along with this program; if not, write to the Free Software Foundation, 68 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 69 | 70 | =cut 71 | 72 | #Be sure to return 1 73 | 1; 74 | -------------------------------------------------------------------------------- /lib/Netdot/Model/UserRight.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Model::UserRight; 2 | 3 | use base 'Netdot::Model'; 4 | use warnings; 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::Model::UserRight - Manipulate UserRight objects 10 | 11 | =cut 12 | 13 | my $logger = Netdot->log->get_logger('Netdot::Model'); 14 | 15 | =head1 CLASS METHODS 16 | =cut 17 | 18 | ######################################################################### 19 | 20 | =head2 insert - Insert a new UserRight object 21 | 22 | We override the insert method for extra functionality 23 | - Ignore duplicates 24 | - Check if 'none' exists for given object and complain. 25 | - If adding 'none' remove all other rights 26 | 27 | 28 | Args: 29 | userright table fields 30 | Returns: 31 | UserRight object 32 | Examples: 33 | UserRight->insert({person=>$person_id, accessright=>$ar_id }); 34 | 35 | =cut 36 | 37 | sub insert { 38 | my ($class, $argv) = @_; 39 | $class->throw_fatal("Model::UserRight::insert: Missing required arguments") 40 | unless ( $argv->{person} && $argv->{accessright} ); 41 | 42 | my $accessright = AccessRight->retrieve(int($argv->{accessright})); 43 | my $person = Person->retrieve(int($argv->{person})); 44 | 45 | foreach my $r ( $person->access_rights ){ 46 | my $ar = $r->accessright; 47 | if ( $ar->object_class eq $accessright->object_class && 48 | $ar->object_id eq $accessright->object_id ){ 49 | # same object 50 | if ( $accessright->access eq $ar->access ){ 51 | # Do not try to insert rights if they exist 52 | return $r; 53 | } 54 | if ( $accessright->access ne 'none' && $ar->access eq 'none' ){ 55 | $class->throw_user("Cannot add other rights while 'none' right exists"); 56 | 57 | }elsif ( $accessright->access eq 'none' && $ar->access ne 'none' ){ 58 | $logger->debug("UserRight::insert: Removing ".$ar->access." access on ". 59 | $ar->object_class." id ".$ar->object_id); 60 | $ar->delete(); 61 | } 62 | } 63 | } 64 | return $class->SUPER::insert($argv); 65 | } 66 | 67 | =head1 AUTHOR 68 | 69 | Carlos Vicente, C<< >> 70 | 71 | =head1 COPYRIGHT & LICENSE 72 | 73 | Copyright 2012 University of Oregon, all rights reserved. 74 | 75 | This program is free software; you can redistribute it and/or modify 76 | it under the terms of the GNU General Public License as published by 77 | the Free Software Foundation; either version 2 of the License, or 78 | (at your option) any later version. 79 | 80 | This program is distributed in the hope that it will be useful, but 81 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 82 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 83 | License for more details. 84 | 85 | You should have received a copy of the GNU General Public License 86 | along with this program; if not, write to the Free Software Foundation, 87 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 88 | 89 | =cut 90 | 91 | #Be sure to return 1 92 | 1; 93 | -------------------------------------------------------------------------------- /lib/Netdot/NetdotPermissionFactory.pm: -------------------------------------------------------------------------------- 1 | package Netdot::NetdotPermissionFactory; 2 | 3 | use Apache2::SiteControl::PermissionManager; 4 | use Apache2::SiteControl::GrantAllRule; 5 | use Netdot::SectionAccessRule; 6 | use Netdot::ObjectAccessRule; 7 | 8 | =head2 NAME 9 | 10 | Netdot::NetdotPermissionFactory; 11 | 12 | =cut 13 | 14 | our $manager; 15 | 16 | =head1 METHODS 17 | 18 | =head2 getPermissionManager 19 | 20 | =cut 21 | 22 | sub getPermissionManager 23 | { 24 | return $manager if defined($manager); 25 | 26 | $manager = new Apache2::SiteControl::PermissionManager; 27 | $manager->addRule(new Apache2::SiteControl::GrantAllRule); 28 | $manager->addRule(new Netdot::SectionAccessRule); 29 | $manager->addRule(new Netdot::ObjectAccessRule); 30 | 31 | return $manager; 32 | } 33 | 34 | =head1 AUTHORS 35 | 36 | Carlos Vicente, Nathan Collins, Aaron Parecki, Peter Boothe. 37 | 38 | =head1 COPYRIGHT & LICENSE 39 | 40 | Copyright 2012 University of Oregon, all rights reserved. 41 | 42 | This program is free software; you can redistribute it and/or modify 43 | it under the terms of the GNU General Public License as published by 44 | the Free Software Foundation; either version 2 of the License, or 45 | (at your option) any later version. 46 | 47 | This program is distributed in the hope that it will be useful, but 48 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 49 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 50 | License for more details. 51 | 52 | You should have received a copy of the GNU General Public License 53 | along with this program; if not, write to the Free Software Foundation, 54 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 55 | 56 | =cut 57 | 58 | # Make sure to return 1 59 | 1; 60 | 61 | 62 | -------------------------------------------------------------------------------- /lib/Netdot/SectionAccessRule.pm: -------------------------------------------------------------------------------- 1 | package Netdot::SectionAccessRule; 2 | 3 | use Apache2::SiteControl::Rule; 4 | @ISA = qw(Apache2::SiteControl::Rule); 5 | use strict; 6 | use Netdot::Model; 7 | 8 | =head1 NAME 9 | 10 | Apache2::SiteControl::SectionAccessRule 11 | 12 | =cut 13 | 14 | =head2 DESCRIPTION 15 | 16 | This rule is going to be used in a system that automatically grants 17 | permission for everything (via the GrantAllRule). So this rule will 18 | only worry about what to deny, and the grants method can return whatever. 19 | 20 | =cut 21 | 22 | my $logger = Netdot->log->get_logger("Netdot::UI"); 23 | 24 | =head1 METHODS 25 | 26 | =head2 grants 27 | 28 | =cut 29 | 30 | sub grants() 31 | { 32 | return 0; 33 | } 34 | 35 | =head2 denies 36 | 37 | =cut 38 | 39 | sub denies(){ 40 | my ($this, $user, $action, $resource) = @_; 41 | 42 | my $user_type = $user->getAttribute('USER_TYPE'); 43 | my $username = $user->getUsername(); 44 | $resource ||= '(n/a)'; 45 | $logger->debug("Netdot::SectionAccessRule::denies: Requesting $action $resource ". 46 | "on behalf of $username ($user_type)"); 47 | 48 | # Deny access to UI sections only available to Admins and Operators 49 | if ( $action eq "access_section" && ($user_type ne "Admin" && $user_type ne "Operator") ){ 50 | $logger->debug("Netdot::SectionAccessRule::denies: Denying $action for $username ($user_type)"); 51 | return 1; 52 | } 53 | 54 | # Deny access to UI sections only available to Admins 55 | if ( $action eq "access_admin_section" && ($user_type ne "Admin") ){ 56 | $logger->debug("Netdot::SectionAccessRule::denies: Denying $action for $username ($user_type)"); 57 | return 1; 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | =head1 AUTHORS 64 | 65 | Carlos Vicente, Nathan Collins, Aaron Parecki, Peter Boothe. 66 | 67 | =head1 COPYRIGHT & LICENSE 68 | 69 | Copyright 2012 University of Oregon, all rights reserved. 70 | 71 | This program is free software; you can redistribute it and/or modify 72 | it under the terms of the GNU General Public License as published by 73 | the Free Software Foundation; either version 2 of the License, or 74 | (at your option) any later version. 75 | 76 | This program is distributed in the hope that it will be useful, but 77 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 78 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 79 | License for more details. 80 | 81 | You should have received a copy of the GNU General Public License 82 | along with this program; if not, write to the Free Software Foundation, 83 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 84 | 85 | =cut 86 | 87 | # Make sure to return 1 88 | 1; 89 | 90 | 91 | -------------------------------------------------------------------------------- /lib/Netdot/SiteControlLoginWrapper.pm: -------------------------------------------------------------------------------- 1 | package Netdot::SiteControlLoginWrapper; 2 | use base qw(Apache2::SiteControl); 3 | 4 | use Apache2::Request; # To get at POST args. 5 | use strict; 6 | 7 | =head1 NAME 8 | 9 | Netdot::SiteControlLoginWrapper 10 | 11 | =head1 SYNOPSIS 12 | 13 | In the apache configuration: 14 | 15 | NetdotTemporarySessionExpires +5m 16 | 17 | 18 | SetHandler perl-script 19 | PerlHandler Netdot::SiteControlLoginWrapper->login 20 | 21 | other-sitecontrol-or-apache-stuff 22 | 23 | 24 | =head1 METHODS 25 | 26 | =cut 27 | 28 | # Make sure to return true 29 | 1; 30 | 31 | =head2 login - Wraps Apache2::SiteControl::login 32 | 33 | Tweaks the environment to overcome deficiencies in the 34 | AuthCookie/SiteControl API. Specifically it sets the expire time on 35 | the session cookie at runtime. 36 | 37 | There are two kinds of cookies now. Permanent and tempory. The 38 | permanent ones last a *long* time. The temporary ones last the amount 39 | of time specified by the NetdotTemporarySessionExpires variable in the 40 | apache conf. The syntax for that variable is the same as that used by 41 | Apache2::AuthCookie. 42 | 43 | The temporary cookie is the default. The permanent cookie is used if 44 | there is an attribute called ``permanent_session'' in the post data 45 | submitted to the login-target. See login.html for an example. 46 | 47 | =cut 48 | 49 | sub login { 50 | my ($self, $r) = @_; 51 | 52 | my $req = Apache2::Request->new($r); 53 | 54 | # AuthCookie uses the value of NetdotExpires, as set in the apache 55 | # conf, to determine how long the session cookie should be valid. 56 | 57 | if ($req->param('permanent_session')) { 58 | $r->dir_config->set('NetdotExpires', '+10y'); # 10 years is pretty permanent for a cookie. 59 | } else { 60 | my $interval = $r->dir_config('NetdotTemporarySessionExpires'); 61 | 62 | my $debug = $r->dir_config("AuthCookieDebug") || 0; 63 | if ($debug) { 64 | $r->server->log_error("No value set for NetdotTemporarySessionExpires in apache conf" 65 | . " so AuthCookie's default will be used") 66 | unless $interval; 67 | } 68 | $r->dir_config->set('NetdotExpires', $interval); 69 | } 70 | 71 | # Let SiteControl do its thing. 72 | $self->SUPER::login($r); 73 | 74 | } 75 | -------------------------------------------------------------------------------- /lib/Netdot/Util.pm: -------------------------------------------------------------------------------- 1 | package Netdot::Util; 2 | 3 | use base 'Netdot'; 4 | 5 | 1; 6 | 7 | =head1 AUTHOR 8 | 9 | Carlos Vicente, C<< >> 10 | 11 | =head1 COPYRIGHT & LICENSE 12 | 13 | Copyright 2012 University of Oregon, all rights reserved. 14 | 15 | This program is free software; you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as published by 17 | the Free Software Foundation; either version 2 of the License, or 18 | (at your option) any later version. 19 | 20 | This program is distributed in the hope that it will be useful, but 21 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 22 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 23 | License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with this program; if not, write to the Free Software Foundation, 27 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 28 | 29 | =cut 30 | 31 | -------------------------------------------------------------------------------- /netdot.cron: -------------------------------------------------------------------------------- 1 | # 2 | # Recommended cron jobs for Netdot. Save as /etc/cron.d/netdot 3 | # 4 | # 5 | PREFIX=/usr/local/netdot 6 | 7 | # Every hour rediscover devices and topology 8 | 0 * * * * root $PREFIX/bin/updatedevices.pl -DIFAT 9 | 10 | # If you have a large number of devices and the above is too 11 | # aggressive, split the load using the following two jobs intead: 12 | 13 | # Retrieve forwarding tables and ARP caches 14 | #0 1-11,13-16,18-23 * * * root $PREFIX/bin/updatedevices.pl -DFA 15 | # Twice a day, rediscover devices and topology (in addition to above) 16 | #0 12,17 * * * root $PREFIX/bin/updatedevices.pl -DIFAT 17 | 18 | # Once a day, generate DNS records for interface IPs 19 | 30 7 * * * root $PREFIX/bin/updatedevices.pl -DN 20 | 21 | # Update whole-network topology graphs 22 | 45 0 * * * root $PREFIX/bin/build_topo_graph.pl -f $PREFIX/htdocs/img/graphs/whole_network_no_vlans.png 23 | 24 | 50 0 * * * root $PREFIX/bin/build_topo_graph.pl -v -f $PREFIX/htdocs/img/graphs/whole_network_with_vlans.png 25 | 26 | # Rotate forwarding tables and arp caches once a week. Keep 7 days of backups 27 | 45 3 * * 0 root $PREFIX/bin/prune_db.pl -F -A -d 7 -r 28 | 29 | # Once a week, remove MAC and IP addresses older than 3 months 30 | # NOTE: ONLY ENABLE THIS IF YOU ARE SURE OF WHAT IT DOES 31 | # 45 4 * * 0 root $PREFIX/bin/prune_db.pl -M -I -d 90 32 | 33 | # Remove audit records older than 3 months 34 | 40 4 * * 0 root $PREFIX/bin/prune_db.pl --audit --hostaudit -d 90 35 | 36 | -------------------------------------------------------------------------------- /patches/ubuntu-1604/DBI.pm.patch: -------------------------------------------------------------------------------- 1 | --- /usr/share/perl5/Class/DBI.pm 2007-10-04 21:27:07.000000000 +0000 2 | +++ /usr/share/perl5/Class/DBI.pm.orig 2018-11-06 21:08:32.364069274 +0000 3 | @@ -597,6 +597,7 @@ 4 | 5 | sub _auto_increment_value { 6 | my $self = shift; 7 | + my $sth = shift; 8 | my $dbh = $self->db_Main; 9 | 10 | # Try to do this in a standard method. Fall back to MySQL/SQLite 11 | @@ -607,6 +608,7 @@ 12 | my $id = $dbh->last_insert_id(undef, undef, $self->table, undef) # std 13 | || $dbh->{mysql_insertid} # mysql 14 | || eval { $dbh->func('last_insert_rowid') } 15 | + || $sth->{'mysql_insertid'} # Added for MySQL 5.7 16 | or $self->_croak("Can't get last insert id"); 17 | return $id; 18 | } 19 | @@ -623,7 +625,7 @@ 20 | $self->_bind_param($sth, \@columns); 21 | $sth->execute(values %$data); 22 | my @primary_columns = $self->primary_columns; 23 | - $data->{ $primary_columns[0] } = $self->_auto_increment_value 24 | + $data->{ $primary_columns[0] } = $self->_auto_increment_value($sth) 25 | if @primary_columns == 1 26 | && !defined $data->{ $primary_columns[0] }; 27 | }; 28 | -------------------------------------------------------------------------------- /patches/ubuntu-1604/apache2-init.patch: -------------------------------------------------------------------------------- 1 | --- /etc/init.d/apache2.orig 2018-11-06 20:30:52.478691277 +0000 2 | +++ /etc/init.d/apache2 2018-11-06 20:32:00.800835274 +0000 3 | @@ -159,8 +159,11 @@ 4 | fi 5 | 6 | if apache_conftest ; then 7 | + a2disconf netdot 8 | $APACHE2CTL start 9 | apache_wait_start $? 10 | + a2enconf netdot 11 | + $APACHE2CTL graceful 12 | return $? 13 | else 14 | APACHE2_INIT_MESSAGE="The apache2$DIR_SUFFIX configtest failed." 15 | -------------------------------------------------------------------------------- /t/ArpCacheEntry.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use Test::Exception; 4 | use lib "lib"; 5 | 6 | BEGIN { use_ok('Netdot::Model::ArpCacheEntry'); } 7 | 8 | my @macs = ('DEADDEADBEEF', 'BEEFDEADBEEF'); 9 | my @ips = ('10.0.0.10', '10.0.0.20'); 10 | my $testdev = 'testdev1'; 11 | 12 | sub cleanup { 13 | map { $_->delete } map { PhysAddr->search(address=>$_) } @macs; 14 | map { $_->delete } map { Ipblock->search(address=>$_) } @ips; 15 | map { $_->delete } Device->search(name=>$testdev); 16 | } 17 | 18 | &cleanup(); 19 | my $dev = Device->insert({name=>$testdev}); 20 | my $ints = $dev->add_interfaces(2); 21 | my $tstamp = Netdot::Model->timestamp(); 22 | my $arp_cache = ArpCache->insert({device=>$dev, tstamp=>$tstamp}); 23 | is($dev->arp_caches->first, $arp_cache->id, 'Device has ARP table'); 24 | my @ips_dec = map { Ipblock->insert({address=>$_})->address_numeric } @ips; 25 | my @arp_data; 26 | foreach my $i (0..1){ 27 | $arp_data[$i] = { 28 | arpcache => $arp_cache->id, 29 | interface => $ints->[$i]->id, 30 | physaddr => $macs[$i], 31 | ipaddr => $ips_dec[$i], 32 | version => 4 33 | }; 34 | } 35 | 36 | throws_ok { ArpCacheEntry->fast_insert(list=>\@arp_data) } qr/cannot be null/, 37 | 'fast_insert throws exception'; 38 | 39 | my @physaddrs = map { PhysAddr->insert({address=>$_}) } @macs; 40 | ArpCacheEntry->fast_insert(list=>\@arp_data); 41 | my @entries = $arp_cache->entries(); 42 | foreach my $i (0..1){ 43 | is($entries[$i]->interface, $ints->[$i], 'entry has interface'); 44 | is($entries[$i]->physaddr, $physaddrs[$i], 'entry has physaddr'); 45 | is($entries[$i]->ipaddr->address, $ips[$i], 'entry has ip'); 46 | } 47 | &cleanup(); 48 | -------------------------------------------------------------------------------- /t/DhcpScope.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More; 3 | use lib "lib"; 4 | 5 | BEGIN { 6 | use_ok('Netdot::Model::DhcpScope'); 7 | } 8 | 9 | my $ip = '192.168.0.10'; 10 | my $net = '192.168.0.0/24'; 11 | my $global_name = 'dhcp_global_test'; 12 | my $mac = 'deaddeadbeef'; 13 | 14 | sub cleanup{ 15 | foreach my $s ( ($ip, $net) ){ 16 | my $i = Ipblock->search(address=>$s)->first; 17 | $i->delete if $i; 18 | } 19 | map { $_->delete } DhcpScope->retrieve_all; 20 | } 21 | 22 | &cleanup(); 23 | 24 | my $global = DhcpScope->insert({name=>$global_name, type=>'global'}); 25 | isa_ok($global, 'Netdot::Model::DhcpScope', 'can insert a global scope'); 26 | 27 | my $subnet = Ipblock->insert({address=>$net, status=>'Subnet'}); 28 | $subnet->enable_dhcp(container=>$global); 29 | my $subnet_scope = $subnet->dhcp_scopes->first; 30 | 31 | is($subnet_scope->name, '192.168.0.0 netmask 255.255.255.0', 'Subnet scope created'); 32 | my %attr_names = map { $_->name->name => 1 } $subnet_scope->attributes; 33 | ok(exists $attr_names{'option broadcast-address'}, 'subnet gets broadcast'); 34 | ok(exists $attr_names{'option subnet-mask'}, 'subnet gets mask'); 35 | 36 | my $host_scope = DhcpScope->insert({ 37 | container=>$global, type=>'host', 38 | ipblock=>$ip, physaddr=>$mac}); 39 | 40 | isa_ok($host_scope, 'Netdot::Model::DhcpScope', 'can insert a host scope'); 41 | is($host_scope->name, $ip, 'host scope gets expected name'); 42 | is(DhcpScope->search(name=>$ip)->first, $host_scope, 'can search a scope by name' ); 43 | is(DhcpScope->search(type=>'host')->first, $host_scope, 'can search a scope by type' ); 44 | is($host_scope->container, $global, 'scope container matches global'); 45 | 46 | my $test_class_name = 'test_class_abc'; 47 | my $class_scope = DhcpScope->insert( 48 | { 49 | name => $test_class_name, 50 | type => 'class', 51 | container => $global, 52 | attributes => { 53 | 'next-server' => '192.0.2.1', 54 | 'filename' => '123abc' 55 | } 56 | } 57 | ); 58 | 59 | is($class_scope->name, $test_class_name, 'creates class with expected name'); 60 | 61 | my ($fh, $config); 62 | open($fh, '>', \$config); 63 | my $data = DhcpScope->_get_all_data(); 64 | DhcpScope->_print($fh, $global->id, $data); 65 | close($fh); 66 | 67 | my $dhcp_mac = PhysAddr->dhcpd_address($mac); 68 | like($config, qr/host $ip/, 'config contains host'); 69 | like($config, qr/fixed-address $ip;/, 'config contains fixed-address statement'); 70 | like($config, qr/hardware ethernet $dhcp_mac;/, 'config contains mac'); 71 | like($config, qr/class "test_class_abc"/, 'config contains class'); 72 | like($config, qr/next-server 192.0.2.1;/, 'config contains attribute'); 73 | like($config, qr/filename "123abc";/, 'filename attribute has double quotes'); 74 | 75 | &cleanup(); 76 | 77 | done_testing(); 78 | -------------------------------------------------------------------------------- /t/Exporter.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | 5 | BEGIN { 6 | use_ok('Netdot::Exporter'); 7 | } 8 | 9 | my @dev_names = ('test1', 'test2', 'test3', 'localhost'); 10 | my @sites = ('tsite1', 'tsite2', 'tsite3'); 11 | 12 | sub cleanup{ 13 | foreach my $name (@dev_names){ 14 | my $d = Device->search(name=>$name)->first; 15 | $d->delete if $d; 16 | } 17 | foreach my $name (@sites){ 18 | my $s = Site->search(name=>$name)->first; 19 | $s->delete if $s; 20 | } 21 | } 22 | 23 | &cleanup(); 24 | 25 | # Exporter 26 | my $exporter = Netdot::Exporter->new(); 27 | isa_ok($exporter, 'Netdot::Exporter', 'Constructor'); 28 | 29 | # Create some test info 30 | my @site_ids; 31 | for my $s (@sites){ 32 | push @site_ids, Site->insert({name=>$s}); 33 | } 34 | my $i = 0; 35 | for my $name (@dev_names){ 36 | my $dev = Device->manual_add(host=>$name); 37 | $dev->update({monitored=>1}); 38 | $dev->update({site=>$site_ids[$i]}); 39 | foreach my $int ($dev->interfaces){ 40 | $int->update({speed=>'100'}); 41 | } 42 | # Create a "removed" interface to test that we do not 43 | # get it in the exported data 44 | Interface->insert({ 45 | device=>$dev, 46 | name=>'dummy', 47 | number=>'999', 48 | doc_status=>'removed'}); 49 | $i++; 50 | } 51 | 52 | my $info = $exporter->get_device_info(); 53 | 54 | my @hdevs = map { $info->{$_} } sort keys %$info; 55 | is($hdevs[0]->{hostname}, "test1.defaultdomain"); 56 | is($hdevs[0]->{site_name}, "tsite1"); 57 | is($hdevs[1]->{hostname}, "test2.defaultdomain"); 58 | is($hdevs[1]->{site_name}, "tsite2"); 59 | is($hdevs[2]->{hostname}, "test3.defaultdomain"); 60 | is($hdevs[2]->{site_name}, "tsite3"); 61 | 62 | my @ints = keys %{$hdevs[0]->{interface}}; 63 | is(length(@ints), 1); 64 | my $f_int = $ints[0]; 65 | is($hdevs[0]->{interface}->{$f_int}->{speed}, 100); 66 | 67 | $info = $exporter->get_device_info(site=>'tsite1'); 68 | my @ids = (sort keys %$info); 69 | is(scalar(@ids), 1); 70 | is($info->{$ids[0]}->{hostname}, "test1.defaultdomain"); 71 | 72 | 73 | my $nagios = Netdot::Exporter->new(type=>'Nagios'); 74 | isa_ok($nagios, 'Netdot::Exporter::Nagios', 'Constructor'); 75 | #$nagios->generate_configs(); 76 | 77 | my $sysmon = Netdot::Exporter->new(type=>'Sysmon'); 78 | isa_ok($sysmon, 'Netdot::Exporter::Sysmon', 'Constructor'); 79 | #$sysmon->generate_configs(); 80 | 81 | my $rancid = Netdot::Exporter->new(type=>'Rancid'); 82 | isa_ok($rancid, 'Netdot::Exporter::Rancid', 'Constructor'); 83 | #$rancid->generate_configs(); 84 | 85 | &cleanup(); 86 | -------------------------------------------------------------------------------- /t/FWTableEntry.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use Test::Exception; 4 | use lib "lib"; 5 | 6 | BEGIN { use_ok('Netdot::Model::FWTableEntry'); } 7 | 8 | my @macs = ('DEADDEADBEEF', 'BEEFDEADBEEF'); 9 | my $testdev = 'testdev1'; 10 | 11 | sub cleanup { 12 | map { $_->delete } map { PhysAddr->search(address=>$_) } @macs; 13 | map { $_->delete } Device->search(name=>$testdev); 14 | } 15 | &cleanup(); 16 | my $dev = Device->insert({name=>$testdev}); 17 | my $ints = $dev->add_interfaces(2); 18 | my $tstamp = Netdot::Model->timestamp(); 19 | my $fwt = FWTable->insert({device=>$dev, tstamp=>$tstamp}); 20 | is($dev->forwarding_tables->first, $fwt->id, 'Device has fwtable'); 21 | my @fwt_data; 22 | foreach my $i (0..1){ 23 | $fwt_data[$i] = { 24 | fwtable => $fwt->id, 25 | interface => $ints->[$i]->id, 26 | physaddr => $macs[$i], 27 | }; 28 | } 29 | 30 | throws_ok { FWTableEntry->fast_insert(list=>\@fwt_data) } qr/cannot be null/, 31 | 'fast_insert throws exception'; 32 | 33 | my @physaddrs = map { PhysAddr->insert({address=>$_}) } @macs; 34 | FWTableEntry->fast_insert(list=>\@fwt_data); 35 | my @entries = $fwt->entries(); 36 | foreach my $i (0..1){ 37 | is($entries[$i]->interface, $ints->[$i], 'entry has interface'); 38 | is($entries[$i]->physaddr, $physaddrs[$i], 'entry has physaddr'); 39 | } 40 | &cleanup(); 41 | -------------------------------------------------------------------------------- /t/Interface.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | 5 | BEGIN { use_ok('Netdot::Model::Interface'); } 6 | 7 | my $test_dev = 'testdev1'; 8 | my @test_blocks = ('192.0.2.1', '192.0.2.0/26', '192.0.2.0/24'); 9 | 10 | sub cleanup{ 11 | foreach my $addr (@test_blocks){ 12 | $_->delete() for Ipblock->search(address=>$addr); 13 | } 14 | foreach my $dev (Device->search(name=>$test_dev)){ 15 | $dev->delete() if $dev; 16 | } 17 | } 18 | &cleanup(); 19 | 20 | my $ints = Device->insert({name=>$test_dev})->add_interfaces(1); 21 | my $iface = $ints->[0]; 22 | ok( $iface->isa('Netdot::Model::Interface') ); 23 | my %update_ip_args = ( 24 | address => $test_blocks[0], 25 | subnet => $test_blocks[1], 26 | version => '4', 27 | add_subnets => 1, 28 | ); 29 | my $ip = $iface->update_ip(%update_ip_args); 30 | ok( !defined Ipblock->search(address=>$test_blocks[1])->first, 31 | 'ignore_orphan_subnet' ); 32 | 33 | my $root = Ipblock->insert({address=>$test_blocks[2], 34 | status=>'Container'}); 35 | $ip = $iface->update_ip(%update_ip_args); 36 | ok( defined Ipblock->search(address=>$test_blocks[1])->first, 37 | 'add_non_orphan_subnet' ); 38 | 39 | # This avoids a common situation with Juniper routers 40 | # that have interfaces with IPs in 10/8 41 | $update_ip_args{subnet} = $test_blocks[2]; 42 | $iface->update_ip(%update_ip_args); 43 | is($root->status->name, 'Container', 44 | 'update_ip cannot turn container into subnet'); 45 | 46 | &cleanup(); 47 | -------------------------------------------------------------------------------- /t/Ipblock-insert.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | use Netdot::Model::Ipblock; 5 | 6 | my $sub1 = Ipblock->insert({ 7 | address => "12.0.0.0", 8 | prefix => '24', 9 | version => 4, 10 | status => 'Subnet', 11 | }); 12 | 13 | eval { 14 | Ipblock->insert({ 15 | address => "12.0.0.0", 16 | prefix => '25', 17 | version => 4, 18 | status => 'Subnet', 19 | }); 20 | }; 21 | ok($@); 22 | 23 | my $sub2 = Ipblock->search(address => '12.0.0.0/25')->first; 24 | is($sub2, undef); 25 | 26 | $sub1->delete; 27 | -------------------------------------------------------------------------------- /t/Model.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | 5 | BEGIN { use_ok('Netdot::Model'); } 6 | 7 | my $obj = Site->insert({name=>'test'}); 8 | is($obj->name, 'test', 'insert'); 9 | 10 | my @objs = Site->search_like(name=>'tes'); 11 | is($objs[0]->name, 'test', 'search_like'); 12 | 13 | my $ts = Netdot::Model->timestamp(); 14 | like($ts, qr/\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}/, 'timestamp'); 15 | 16 | my $date = Netdot::Model->date(); 17 | like($date, qr/\d{4}\/\d{2}\/\d{2}/, 'date'); 18 | 19 | my $meta = Site->meta_data(); 20 | isa_ok($meta, 'Netdot::Meta::Table', 'meta_data'); 21 | 22 | my $result = Netdot::Model->raw_sql("SELECT name FROM site WHERE name='test'"); 23 | my @headers = $result->{headers}; 24 | is($headers[0]->[0], 'name', 'raw_sql'); 25 | my $rows = $result->{rows}; 26 | is($rows->[0]->[0], 'test', 'raw_sql'); 27 | 28 | # Notice we pass an invalid field 'names' to cause the subroutine to fail 29 | # The result must be -1 (See Class::DBI's update method) 30 | my $r = Netdot::Model->do_transaction( sub{ return $obj->update(@_) }, names=>'test' ); 31 | is($r, -1, 'do_transaction'); 32 | 33 | my $ac = Netdot::Model->db_auto_commit(0); 34 | is($ac, '', 'db_auto_commit'); 35 | 36 | $ac = Netdot::Model->db_auto_commit(1); 37 | is($ac, 1, 'db_auto_commit'); 38 | 39 | $obj->update({name=>'test2'}); 40 | 41 | # This doesn't work for some stupid reason 42 | #my %state = $obj->get_state(); 43 | #is($state{name}, 'test2', 'get_state'); 44 | 45 | is($obj->get_label, 'test2', 'get_label'); 46 | 47 | my $res = Netdot::Model->search_all_tables('test2'); 48 | ok(exists $res->{'Site'}->{$obj->id}, 'search_all_tables'); 49 | 50 | my $bl = Ipblock->search(address=>'10.0.0.0')->first; 51 | $res = Netdot::Model->search_all_tables('10.0.0.0'); 52 | ok(exists $res->{'Ipblock'}->{$bl->id}, 'search_all_tables_2'); 53 | 54 | $obj->delete; 55 | isa_ok($obj, 'Class::DBI::Object::Has::Been::Deleted', 'delete'); 56 | 57 | is(Netdot::Model->sqldate2time('2011-09-13'), 1315872000, 'sqldate2time'); 58 | is(Netdot::Model->sqldate2time('2011-09-13 11:59:47'), 1315915187, 'sqldate2time'); 59 | -------------------------------------------------------------------------------- /t/Nagios.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use Test::File::Contents; 4 | use lib "lib"; 5 | 6 | my $TMP = '/tmp'; 7 | my $FILE = 'test_nagios.cfg'; 8 | 9 | my $dev = Device->manual_add('host'=>'localhost'); 10 | 11 | BEGIN { 12 | use_ok('Netdot::Exporter'); 13 | } 14 | 15 | my $obj = Netdot::Exporter->new( 16 | 'type'=>'Nagios', 17 | 'NAGIOS_DIR' => $TMP, 18 | 'NAGIOS_FILE' => $FILE, 19 | ); 20 | isa_ok($obj, 'Netdot::Exporter::Nagios', 'Constructor'); 21 | 22 | # Check generated file 23 | $obj->generate_configs(); 24 | my $fname = "$TMP/$FILE"; 25 | ok(-e $fname, "Test file created"); 26 | file_contents_like $fname, 'localhost', 'hostname'; 27 | file_contents_like $fname, 'define host', 'host definition'; 28 | file_contents_like $fname, 'define service', 'service definition'; 29 | 30 | unlink($fname); 31 | 32 | $dev->delete(); 33 | -------------------------------------------------------------------------------- /t/Nullify.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More qw(no_plan); 4 | use lib "lib"; 5 | use Data::Dumper; 6 | 7 | BEGIN { use_ok('Netdot::Model'); } 8 | 9 | my $s = Ipblock->search(address=>'1.1.1.0')->first; 10 | $s->delete if $s; 11 | 12 | my $subnet = Ipblock->insert({address => '1.1.1.0', 13 | prefix => 24, 14 | status => 'Subnet'}); 15 | my $s_id = $subnet->id; 16 | 17 | my $vlan = Vlan->insert({name => 'test vlan', 18 | vid => 1}); 19 | ok(defined $vlan, "vlan insert"); 20 | 21 | $subnet->update({vlan => $vlan}); 22 | is($subnet->vlan, $vlan, 'set vlan to subnet'); 23 | 24 | $vlan->delete; 25 | undef $subnet; 26 | $subnet = Ipblock->retrieve($s_id); 27 | is($subnet->vlan, undef, 'nullify'); 28 | $subnet->delete; 29 | -------------------------------------------------------------------------------- /t/Product.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | 5 | BEGIN { use_ok('Netdot::Model::Product'); } 6 | 7 | my $obj = Product->insert({name=>'test', 8 | sysobjectid=>'123', 9 | manufacturer=>1}); 10 | 11 | $obj->delete; 12 | isa_ok($obj, 'Class::DBI::Object::Has::Been::Deleted', 'delete'); 13 | 14 | -------------------------------------------------------------------------------- /t/REST.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use Test::Exception; 4 | 5 | use lib "lib"; 6 | 7 | 8 | BEGIN { use_ok('Netdot::REST'); } 9 | 10 | throws_ok { Netdot::REST->new() } qr/Missing required arg/, 11 | 'constructor throws missing args'; 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /t/SitePicture.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More; 4 | use lib "lib"; 5 | use Data::Dumper; 6 | use FindBin; 7 | 8 | BEGIN { use_ok('Netdot::Model::Site'); } 9 | BEGIN { use_ok('Netdot::Model::SitePicture'); } 10 | 11 | my $site = Site->insert({ name => "t/SitePicture.t" }); 12 | ok($site, "site insert"); 13 | 14 | my $picture_file = "$FindBin::Bin/../htdocs/img/title.png"; 15 | ok(-f($picture_file), "picture file exists"); 16 | 17 | my $picture_data; 18 | { 19 | local $/; 20 | if (open my $fh, "<", $picture_file) { 21 | $picture_data = <$fh>; 22 | } 23 | } 24 | is(length($picture_data), 8826, "the picture is right"); 25 | 26 | my $pic = SitePicture->insert({ 27 | site => $site->id, 28 | filename => $picture_file, 29 | bindata => $picture_data, 30 | }); 31 | ok($pic, "picture insert"); 32 | 33 | is($pic->bindata, $picture_data, "picture object holds correct data"); 34 | my $pic_id = $pic->id; 35 | undef $pic; 36 | $pic = SitePicture->retrieve($pic_id); 37 | ok($pic, "picture retrieve"); 38 | 39 | is($pic->bindata, $picture_data, "retrieved picture object holds correct data"); 40 | 41 | $site->delete; 42 | isa_ok($site, 'Class::DBI::Object::Has::Been::Deleted', 'cleanup ok'); 43 | 44 | done_testing; 45 | exit; 46 | 47 | # Ipblock 48 | my $subnet = Ipblock->insert({address => '1.1.1.0', 49 | prefix => 24, 50 | status => 'Subnet'}); 51 | my $subnet_id = $subnet->id; 52 | ok(defined $subnet, 'subnet insert'); 53 | 54 | $subnet->set('description', 'test1'); 55 | ok($subnet->update, "update without params returns success"); 56 | undef $subnet; 57 | $subnet = Ipblock->retrieve($subnet_id); 58 | is($subnet->description, 'test1', 'update without params'); 59 | 60 | ok($subnet->update({description => 'test2'}), "update with params returns success"); 61 | undef $subnet; 62 | $subnet = Ipblock->retrieve($subnet_id); 63 | is($subnet->description, 'test2', 'update with params'); 64 | 65 | eval { 66 | my $vlan = Vlan->insert({name => 'test vlan', 67 | vid => 1}); 68 | ok(defined $vlan, "vlan insert"); 69 | 70 | $subnet->update({vlan => $vlan}); 71 | is($subnet->vlan, $vlan, 'set vlan to subnet'); 72 | 73 | $vlan->delete; 74 | undef $subnet; 75 | $subnet = Ipblock->retrieve($subnet_id); 76 | ok(!$subnet->vlan, 'nullify'); 77 | }; 78 | fail($@) if $@; 79 | 80 | $subnet->delete; 81 | 82 | done_testing; -------------------------------------------------------------------------------- /t/UI.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | 5 | BEGIN { use_ok('Netdot::UI'); } 6 | 7 | my $ui = Netdot::UI->new(); 8 | my ($table, $col, $value) = ('Device', 'os', 'blah'); 9 | 10 | my %info = $ui->form_to_db($table . '__NEW1__name' => 'test'); 11 | isa_ok(\%info, 'HASH'); 12 | my $id = (keys %{$info{$table}{id}})[0]; 13 | my $o = $table->retrieve($id); 14 | isa_ok($o, 'Netdot::Model::Device'); 15 | 16 | $ui->form_to_db($table . '__' . $id . '__os' => $value); 17 | 18 | my %tmp = $ui->form_field(object=>$o, column=>$col, edit=>1 ); 19 | is($tmp{label}, "OS:", "form_field"); 20 | like($tmp{value}, "/input type=\"text\" name=\"Device__(\\d+)__os\" value=\"$value\"/", "form_field"); 21 | 22 | # TODO select_lookup 23 | # TODO select_multiple 24 | 25 | my $radio = $ui->radio_group_boolean(object=>$o, column=>"monitored", edit=>1, returnAsVar=>1); 26 | like($radio, '/Yes/', 'radio_group_boolean'); 27 | 28 | my $text = $ui->text_field(object=>$o, column=>"os", edit=>1, returnAsVar=>1); 29 | like($text, "//", 'text_field'); 30 | 31 | my $textarea = $ui->text_area(object=>$o, column=>"info", edit=>1, returnAsVar=>1); 32 | like($textarea, "//", 'text_area'); 33 | 34 | my $pb = $ui->percent_bar(percent=>'50'); 35 | is($pb, '
', 'percent_bar'); 36 | 37 | my $pb2 = $ui->percent_bar2(title1=>"Address Usage: ", title2=>"Subnet Usage: ", 38 | percent1=>'50', percent2=>'50'); 39 | is($pb2, '
', 'percent_bar2'); 40 | 41 | my $cm = $ui->color_mix(color1=>'ff00cc', color2=>'cc00ff', blend=>0.5); 42 | is($cm, 'e500e5', 'color_mix'); 43 | 44 | my $fp = $ui->friendly_percent(value=>'50',total=>'100'); 45 | is($fp, '50%', 'friendly_percent'); 46 | 47 | my $fs = $ui->format_size(1048576, 2); 48 | is($fs, '1 MB', 'format_size'); 49 | 50 | # TODO: add_to_fields 51 | 52 | my $r = $ui->select_query(table=>'EntityType', terms=>['Department']); 53 | is((values %$r)[0]->name, 'Department', 'select_query'); 54 | 55 | undef %info; 56 | %info = $ui->form_to_db($table . '__' . $id . '__DELETE' => 'null'); 57 | is($info{$table}{id}{$id}{action}, 'DELETED', 'form_to_db'); 58 | 59 | -------------------------------------------------------------------------------- /t/Util.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | use Netdot; 5 | 6 | BEGIN { use_ok('Netdot::Util::DNS'); } 7 | 8 | my $dns = Netdot::Util::DNS->new(); 9 | isa_ok($dns, 'Netdot::Util::DNS', 'constructor'); 10 | 11 | # Note, these are the addresses for the K root server. 12 | # No guarantee that they won't change 13 | my $ipv4 = '193.0.14.129'; 14 | my $ipv6 = '2001:7fd::1'; 15 | my $name = 'k.root-servers.net'; 16 | 17 | is($dns->resolve_ip($ipv4), $name, 'resolve_ip_v4'); 18 | is($dns->resolve_ip($ipv6), $name, 'resolve_ip_v6'); 19 | my @addresses = $dns->resolve_name($name); 20 | is($addresses[0], $ipv4, 'resolve_name_ipv4'); 21 | is($addresses[1], $ipv6, 'resolve_name_ipv6'); 22 | 23 | is(($dns->resolve_name($name, {v4_only=>1}))[0], $ipv4, 'resolve_name_ipv4_only'); 24 | is(($dns->resolve_name($name, {v6_only=>1}))[0], $ipv6, 'resolve_name_ipv6_only'); 25 | 26 | -------------------------------------------------------------------------------- /t/Vlan.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | 5 | BEGIN { use_ok('Netdot::Model::Vlan'); 6 | use_ok('Netdot::Model::VlanGroup'); 7 | } 8 | 9 | my $group = VlanGroup->insert({name =>'Data', 10 | description =>'Data Vlans', 11 | start_vid =>'100', 12 | end_vid =>'300', 13 | }); 14 | isa_ok($group, 'Netdot::Model::VlanGroup', 'insert'); 15 | is(VlanGroup->search(name=>'Data')->first, $group, 'search' ); 16 | 17 | 18 | my $vlan = Vlan->insert({vid=>'100', description=>'Vlan 100'}); 19 | isa_ok($vlan, 'Netdot::Model::Vlan', 'insert'); 20 | is(Vlan->search(vid=>'100')->first, $vlan, 'search' ); 21 | 22 | is($vlan->vlangroup, $group, 'auto group assignment'); 23 | 24 | $vlan->delete; 25 | isa_ok($vlan, 'Class::DBI::Object::Has::Been::Deleted', 'delete'); 26 | 27 | $group->delete; 28 | isa_ok($group, 'Class::DBI::Object::Has::Been::Deleted', 'delete'); 29 | 30 | my ($min, $max) = @{Netdot->config->get('VALID_VLAN_ID_RANGE')}; 31 | my $inv1 = $min - 1; 32 | eval { 33 | my $invalid = Vlan->insert({vid=>$inv1}); 34 | }; 35 | my $e = $@; 36 | ok($e->isa_netdot_exception, 'Invalid Vlan #1'); 37 | 38 | my $inv2 = $max + 1; 39 | eval { 40 | my $invalid = Vlan->insert({vid=>$inv2}); 41 | }; 42 | my $e = $@; 43 | ok($e->isa_netdot_exception, 'Invalid Vlan #2'); 44 | -------------------------------------------------------------------------------- /t/VlanGroup.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use lib "lib"; 4 | 5 | BEGIN { use_ok('Netdot::Model::Vlan'); 6 | use_ok('Netdot::Model::VlanGroup'); 7 | } 8 | 9 | my $group = VlanGroup->insert({name =>'Data', 10 | description =>'Data Vlans', 11 | start_vid =>'100', 12 | end_vid =>'300', 13 | }); 14 | isa_ok($group, 'Netdot::Model::VlanGroup', 'insert'); 15 | 16 | eval { 17 | VlanGroup->insert({name =>'Data2', 18 | description =>'Data Vlans', 19 | start_vid =>'300', 20 | end_vid =>'400', 21 | }); 22 | }; 23 | like($@, qr/overlaps/, 'overlapping insert'); 24 | 25 | $group->delete; 26 | isa_ok($group, 'Class::DBI::Object::Has::Been::Deleted', 'delete'); 27 | 28 | -------------------------------------------------------------------------------- /t/Zone.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More qw(no_plan); 3 | use Test::Exception; 4 | use lib "lib"; 5 | 6 | my $DOMAIN = 'test.tld'; 7 | my $SUB_DOMAIN = 'sub.'. $DOMAIN; 8 | 9 | BEGIN { use_ok('Netdot::Model::Zone'); } 10 | 11 | my $obj = Zone->insert({name=>$DOMAIN}); 12 | isa_ok($obj, 'Netdot::Model::Zone', 'insert'); 13 | 14 | lives_and { is(Zone->_dot_arpa_to_ip('1.in-addr.arpa'), '1.0.0.0/8', 'IPv4 /8 .arpa zone to address') }; 15 | lives_and { is(Zone->_dot_arpa_to_ip('2.1.in-addr.arpa'), '1.2.0.0/16', 'IPv4 /16 .arpa zone to address') }; 16 | lives_and { is(Zone->_dot_arpa_to_ip('3.2.1.in-addr.arpa'), '1.2.3.0/24', 'IPv4 /24 .arpa zone to address') }; 17 | lives_and { is(Zone->_dot_arpa_to_ip('4.3.2.1.in-addr.arpa'), '1.2.3.4/32', 'IPv4 /32 .arpa zone to address') }; 18 | 19 | lives_and { is(Zone->_dot_arpa_to_ip('1.ip6.arpa'), '1000::/4', 'IPv6 /4 .arpa zone to address') }; 20 | lives_and { is(Zone->_dot_arpa_to_ip('2.1.ip6.arpa'), '1200::/8', 'IPv6 /8 .arpa zone to address') }; 21 | lives_and { is(Zone->_dot_arpa_to_ip('3.2.1.ip6.arpa'), '1230::/12', 'IPv6 /12 .arpa zone to address') }; 22 | lives_and { is(Zone->_dot_arpa_to_ip('4.3.2.1.ip6.arpa'), '1234::/16', 'IPv6 /16 .arpa zone to address') }; 23 | lives_and { is(Zone->_dot_arpa_to_ip('5.4.3.2.1.ip6.arpa'), '1234:5000::/20', 'IPv6 /20 .arpa zone to address') }; 24 | lives_and { is(Zone->_dot_arpa_to_ip('6.5.4.3.2.1.ip6.arpa'), '1234:5600::/24', 'IPv6 /24 .arpa zone to address') }; 25 | lives_and { is(Zone->_dot_arpa_to_ip('7.6.5.4.3.2.1.ip6.arpa'), '1234:5670::/28', 'IPv6 /28 .arpa zone to address') }; 26 | lives_and { is(Zone->_dot_arpa_to_ip('8.7.6.5.4.3.2.1.ip6.arpa'), '1234:5678::/32', 'IPv6 /32 .arpa zone to address') }; 27 | lives_and { is(Zone->_dot_arpa_to_ip('9.8.7.6.5.4.3.2.1.ip6.arpa'), '1234:5678:9000::/36', 'IPv6 /36 .arpa zone to address') }; 28 | lives_and { is(Zone->_dot_arpa_to_ip('a.9.8.7.6.5.4.3.2.1.ip6.arpa'), '1234:5678:9a00::/40', 'IPv6 /40 .arpa zone to address') }; 29 | lives_and { is(Zone->_dot_arpa_to_ip('b.a.9.8.7.6.5.4.3.2.1.ip6.arpa'), '1234:5678:9ab0::/44', 'IPv6 /44 .arpa zone to address') }; 30 | lives_and { is(Zone->_dot_arpa_to_ip('c.b.a.9.8.7.6.5.4.3.2.1.ip6.arpa'), '1234:5678:9abc::/48', 'IPv6 /48 .arpa zone to address') }; 31 | 32 | is(Zone->search(name=>$SUB_DOMAIN)->first, $obj, 'search scalar'); 33 | is_deeply([Zone->search(name=>$SUB_DOMAIN)], [$obj], 'search array' ); 34 | 35 | is(Zone->search(name=>'fake')->first, undef, 'search empty scalar' ); 36 | is_deeply([Zone->search(name=>'fake')], [], 'search empty array' ); 37 | 38 | my $SUBSTR = substr($DOMAIN, 0, 3); 39 | is(Zone->search_like(name=>$SUBSTR)->first, $obj, 'search_like scalar'); 40 | is_deeply([Zone->search_like(name=>$SUBSTR)], [$obj], 'search_like array' ); 41 | is(Zone->search_like(name=>'fake')->first, undef, 'search_like empty scalar' ); 42 | is_deeply([Zone->search_like(name=>'fake')], [], 'search_like empty array' ); 43 | 44 | my $serial = $obj->serial; 45 | $obj->update_serial(); 46 | is($obj->serial, $serial+1, 'update_serial'); 47 | 48 | $obj->delete; 49 | isa_ok($obj, 'Class::DBI::Object::Has::Been::Deleted', 'delete'); 50 | -------------------------------------------------------------------------------- /t/pod-coverage.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # pod-coverage.t - Test to check POD coverage of Netdot classes 3 | 4 | use strict; 5 | use warnings; 6 | use Test::More qw(no_plan); 7 | #use Test::Pod::Coverage; 8 | #use Pod::Coverage; 9 | 10 | #all_pod_coverage_ok(); 11 | pass('temporarily disabled') 12 | -------------------------------------------------------------------------------- /t/pod.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # pod.t - Test to check for POD errors in Netdot 3 | 4 | use strict; 5 | use warnings; 6 | use Test::More; 7 | use Test::Pod; 8 | 9 | all_pod_files_ok(); 10 | -------------------------------------------------------------------------------- /upgrade/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # upgrade Makefile 3 | # 4 | 5 | PERL ?= /usr/bin/perl 6 | PREFIX ?= `cat ../.prefix` 7 | 8 | all: db tasks 9 | @echo 10 | @echo "Done applying changes. Now you should:" 11 | @echo 12 | @echo " * Check the file upgrade/error.log and correct any errors before continuing" 13 | @echo " * After making sure that errors have been corrected, you may:" 14 | @echo " 'make install'" 15 | @echo " * Stop and start Apache" 16 | @echo 17 | 18 | db: 19 | @echo 20 | @echo "Upgrading schema and data..." 21 | $(PERL) updatedb 2>error.log 22 | 23 | tasks: 24 | @echo 25 | @echo "Performing various upgrade tasks" 26 | $(PERL) upgrade-tasks $(PREFIX) 27 | -------------------------------------------------------------------------------- /upgrade/upgrade-tasks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | use strict; 3 | 4 | my $PREFIX = $ARGV[0] or die "Need install prefix\n"; 5 | 6 | # Miscellaneous upgrade-related tasks 7 | 8 | 9 | ########################################################### 10 | # Run system commands 11 | sub cmd { 12 | my $str = shift; 13 | if ( system($str) != 0 ){ 14 | die "There was a problem running $str\n"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /var/Makefile: -------------------------------------------------------------------------------- 1 | include $(SRCROOT)/etc/utility-Makefile 2 | 3 | # 4 | # makefile for var/ 5 | # 6 | # Note: The RRD definition below assumes a polling period of 1 hour 7 | # You will have to adjust it to reflect your desired polling interval 8 | # as defined in your cron jobs 9 | # 10 | # For reference see: 11 | # http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html 12 | # 13 | POLLSTATSRRD = pollstats.rrd 14 | 15 | all: 16 | if ! test -r $(STAGEDIR)/$(DIR)/$(POLLSTATSRRD); then \ 17 | rrdtool create $(POLLSTATSRRD) -s 3600 \ 18 | DS:ips:GAUGE:7200:0:4294967296 \ 19 | DS:macs:GAUGE:7200:0:4294967296 \ 20 | DS:arp_devs:GAUGE:7200:0:4294967296 \ 21 | DS:fwt_devs:GAUGE:7200:0:4294967296 \ 22 | DS:poll_time:GAUGE:7200:0:4294967296 \ 23 | RRA:AVERAGE:0.5:1:24 \ 24 | RRA:AVERAGE:0.5:24:365 \ 25 | RRA:MAX:0.5:24:30 \ 26 | RRA:MIN:0.5:24:30; \ 27 | install -m $(FMOD) $(POLLSTATSRRD) $(STAGEDIR)/$(DIR)/$(POLLSTATSRRD); \ 28 | fi; 29 | --------------------------------------------------------------------------------