1package Netdot::Model::VlanGroup; 2 3use base 'Netdot::Model'; 4use warnings; 5use strict; 6 7my $logger = Netdot->log->get_logger('Netdot::Model::Device'); 8 9=head1 NAME 10 11Netdot::Model::VlanGroup 12 13=head1 SYNOPSIS 14 15Netdot Vlan Group Class 16 17=head1 CLASS METHODS 18=cut 19 20#################################################################################### 21 22=head2 insert - Insert new VlanGroup 23 24 Override the base class to: 25 - Validate input 26 - Assign any existing vlans to the new group if applicable 27 28 Arguments: 29 Hash ref with field/value pairs 30 Returns: 31 New VlanGroup object 32 Examples: 33 my $newgroup = VlanGroup->insert({name=>$name, start_vid=>$start, end_vid=>$end}); 34 35=cut 36 37sub insert{ 38 my ($class, $argv) = @_; 39 $class->isa_class_method('insert'); 40 41 $class->throw_user('Vlan::insert: Argument variable must be hash reference') 42 unless ( ref($argv) eq 'HASH' ); 43 44 $class->throw_user("Missing one or more required arguments: name, start_vid, end_vid") 45 unless ( exists $argv->{name} && exists $argv->{start_vid} && exists $argv->{end_vid} ); 46 47 $class->_validate($argv); 48 49 my $newgroup = $class->SUPER::insert($argv); 50 51 $newgroup->assign_vlans; 52 53 return $newgroup; 54} 55 56#################################################################################### 57 58=head2 assign_all - Traverse the list of vlans and assign them to groups 59 60 Arguments: 61 None 62 Returns: 63 True if successful 64 Examples: 65 VlanGroup->assign_all(); 66 67=cut 68 69sub assign_all{ 70 my ($class) = @_; 71 $class->isa_class_method('assign_all'); 72 73 my @groups = VlanGroup->retrieve_all(); 74 unless ( @groups ){ 75 $logger->warn('VlanGroup::assign_all: No groups to assign vlans to'); 76 return; 77 } 78 79 foreach my $group ( @groups ){ 80 $group->assign_vlans; 81 } 82 83 return 1; 84} 85 86=head1 INSTANCE METHODS 87 88=cut 89#################################################################################### 90 91=head2 assign_vlans - Traverse the list of vlans and assign them to this group 92 93 Arguments: 94 None 95 Returns: 96 List of member Vlans 97 Examples: 98 $group->assign_vlans(); 99 100=cut 101 102sub assign_vlans{ 103 my $self = shift; 104 $self->isa_object_method('assign_vlans'); 105 106 # Get a list of my own vlans and index them by id 107 my %myvlans; 108 map { $myvlans{$_->id} = $_ } $self->vlans; 109 110 # Assing vlans to this new group 111 foreach my $vlan ( Vlan->retrieve_all ){ 112 if ( $vlan->vid >= $self->start_vid && $vlan->vid <= $self->end_vid ){ 113 if ( !defined $vlan->vlangroup || $vlan->vlangroup != $self->id ){ 114 $vlan->update({vlangroup=>$self->id}); 115 $logger->debug(sub{ sprintf("VlanGroup: %s: Vlan %s within my range. Updating.", 116 $self->name, $vlan->vid) }); 117 } 118 119 }else{ 120 # Remove from my members if necessary 121 if ( exists $myvlans{$vlan->id} ){ 122 $logger->debug(sprintf("VlanGroup %s: Vlan %s no longer within my range. Updating.", 123 $self->name, $vlan->vid)); 124 $vlan->update({vlangroup=>undef}); 125 } 126 } 127 } 128 return $self->vlans; 129} 130 131###################################################################################### 132 133=head2 update - update VlanGroup objects 134 135 We override the base method to: 136 - Validate input 137 - Automatically assign Vlans to this VLAN group if it applies 138 139 Arguments: 140 hash ref with field/value pairs 141 Returns: 142 Updated VlanGroup object 143 Examples: 144 145=cut 146 147sub update{ 148 my ($self, $argv) = @_; 149 $self->isa_object_method('update'); 150 my $class = ref($self); 151 $self->_validate($argv); 152 153 my $oldstart = $self->start_vid; 154 my $oldend = $self->end_vid; 155 my $id = $self->id; 156 157 my $res = $self->SUPER::update($argv); 158 $self = $class->retrieve($id); 159 160 # For some reason, we get an empty object after updating (weird) 161 # so we re-read the object from the DB to get the comparisons below to work 162 if ( $self->start_vid != $oldstart || $self->end_vid != $oldend ){ 163 my $name = $self->name; 164 $logger->info("VlanGroup $name: Range changed. Reassigning VLANs."); 165 $self->assign_vlans; 166 } 167 return $res; 168} 169#################################################################################### 170# 171# Private Methods 172# 173#################################################################################### 174 175 176#################################################################################### 177# _validate - Validate VlanGroup input before inserting or updating 178# 179# Check that group ranges are valid and do not overlap with existing ones. 180# Can be called as instance method or class method. 181# 182# Arguments: 183# Hash ref with field/value pairs 184# Returns: 185# True if successful 186# Examples: 187# VlanGroup->_validate($args); 188# 189 190sub _validate { 191 my ($proto, $argv) = @_; 192 my ($self, $class); 193 if ( $class = ref($proto) ){ 194 $self = $proto; 195 }else{ 196 $class = $proto; 197 } 198 199 # Get an iterator 200 my $groups = VlanGroup->retrieve_all(); 201 202 # Check range validity 203 if ( $argv->{start_vid} < 1 || $argv->{end_vid} > 4096 ){ 204 $class->throw_user("Invalid range: It must be within 1 and 4096"); 205 } 206 207 if ( exists $argv->{start_vid} && exists $argv->{end_vid} ){ 208 if ( $argv->{start_vid} > $argv->{end_vid} ){ 209 $class->throw_user("Invalid range: start must be lower or equal than end"); 210 } 211 while ( my $g = $groups->next ){ 212 # Do not compare to self 213 if ( $self && ($self->id == $g->id) ){ 214 next; 215 } 216 # Check that ranges do not overlap 217 unless ( ($argv->{start_vid} < $g->start_vid && $argv->{end_vid} < $g->start_vid) || 218 ($argv->{start_vid} > $g->end_vid && $argv->{end_vid} > $g->end_vid) ){ 219 220 $class->throw_user(sprintf("New range: %d-%d overlaps with Group: %s", 221 $argv->{start_vid}, $argv->{end_vid}, $g->name)); 222 } 223 } 224 } 225 return 1; 226} 227 228 229=head1 AUTHOR 230 231Carlos Vicente, C<< <cvicente at ns.uoregon.edu> >> 232 233=head1 COPYRIGHT & LICENSE 234 235Copyright 2012 University of Oregon, all rights reserved. 236 237This program is free software; you can redistribute it and/or modify 238it under the terms of the GNU General Public License as published by 239the Free Software Foundation; either version 2 of the License, or 240(at your option) any later version. 241 242This program is distributed in the hope that it will be useful, but 243WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 244or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 245License for more details. 246 247You should have received a copy of the GNU General Public License 248along with this program; if not, write to the Free Software Foundation, 249Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 250 251=cut 252 253# Make sure to return 1 2541; 255 256