gs_phone 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.txt +4 -0
- data/CHANGES.txt +8 -0
- data/COPYING.txt +279 -0
- data/Manifest.txt +10 -0
- data/README.txt +26 -0
- data/Rakefile +67 -0
- data/TODO.txt +25 -0
- data/bin/gs_phone +12 -0
- data/lib/gs_phone/version.rb +9 -0
- data/lib/gs_phone.rb +274 -0
- data/setup.rb +1585 -0
- data/test/gs_phone_test.rb +11 -0
- data/test/test_helper.rb +2 -0
- metadata +61 -0
data/lib/gs_phone.rb
ADDED
@@ -0,0 +1,274 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# This is used to manage the Grandstream phones.
|
3
|
+
# It is a wrapper over Charles Howes (gsutil@ch.pkts.ca)'s gsutil
|
4
|
+
# utility (http://www.pkts.ca/gsutil.shtml)
|
5
|
+
#
|
6
|
+
# Copyright (C) 2007 Eric Davis <edavis10@gmail.com>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or
|
9
|
+
# modify it under the terms of the GNU General Public License
|
10
|
+
# as published by the Free Software Foundation; either version 2
|
11
|
+
# of the License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program; if not, write to the Free Software
|
20
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
21
|
+
|
22
|
+
|
23
|
+
require 'yaml'
|
24
|
+
require 'optparse'
|
25
|
+
|
26
|
+
class GrandStream
|
27
|
+
|
28
|
+
# Default configurations
|
29
|
+
@user_file = "users.yml"
|
30
|
+
@admin_password = "admin"
|
31
|
+
@gsutil = "gsutil"
|
32
|
+
@config_files = "config"
|
33
|
+
|
34
|
+
|
35
|
+
# Setup the help messages with the optparse library
|
36
|
+
def initialize(args)
|
37
|
+
read_configuration
|
38
|
+
@ip = args[1]
|
39
|
+
@current_ip = args[2]
|
40
|
+
@admin = args[3]
|
41
|
+
opts = OptionParser.new do |opts|
|
42
|
+
opts.banner = "Usage: #$0 COMMANDS [options]\n\n" +
|
43
|
+
" 'IP' is the ip address you want the phone to use\n" +
|
44
|
+
" 'crtIP' is the ip address the phone currently has\n" +
|
45
|
+
" 'pass' is the current phone password\n\n"
|
46
|
+
|
47
|
+
opts.on("--new 'IP' ['crtIP'|'pass']", "Add new user and setup their phone ") do
|
48
|
+
self.add_user(@ip)
|
49
|
+
self.make(@ip)
|
50
|
+
self.update_config(@ip, @current_ip, @admin)
|
51
|
+
self.reboot_phone(@current_ip)
|
52
|
+
end
|
53
|
+
opts.on('-A', "--add-user", 'Adds a user to the phone database') { self.add_user(@ip) }
|
54
|
+
opts.on('-M', "--make 'IP", 'Generates a config file from the template') { self.make(@ip) }
|
55
|
+
opts.on('--make-all', 'Reboots all phones') { self.make_all }
|
56
|
+
opts.on('-U', "--update 'IP' ['crtIP'|'pass']", "Update the configuration file to the phone") { self.update_config(@ip, @current_ip, @admin) }
|
57
|
+
opts.on('--update-all', 'Updates the configs on all phones') { self.update_all }
|
58
|
+
opts.on('-R', "--reboot 'IP'", 'Reboots a phone') { self.reboot_phone(@ip) }
|
59
|
+
opts.on('--reboot-all', 'Reboots all phones') { self.reboot_all_phones }
|
60
|
+
opts.on('-F', '--find-ip', "Find the ip address in the configuration file") { self.find_ip }
|
61
|
+
|
62
|
+
end
|
63
|
+
opts.parse!(args)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Read the gs_phone configuration file to get the settings
|
67
|
+
def read_configuration
|
68
|
+
|
69
|
+
if File.exists?("#{ENV["HOME"]}/.gs_phone")
|
70
|
+
settings = Hash.new
|
71
|
+
settings = YAML::load(File.open("#{ENV["HOME"]}/.gs_phone"))
|
72
|
+
|
73
|
+
@user_file = settings["user_file"] if settings.include?("user_file")
|
74
|
+
@admin_password = settings["admin_password"]
|
75
|
+
@gsutil = settings["gsutil"]
|
76
|
+
@config_files = settings["config_files"]
|
77
|
+
else
|
78
|
+
puts "You have no default configuration file. We will create one for you"
|
79
|
+
settings = {
|
80
|
+
"admin_password" => "admin",
|
81
|
+
"user_file" => "users.yml",
|
82
|
+
"gsutil" => "gsutil",
|
83
|
+
"config_files" => "config"
|
84
|
+
}
|
85
|
+
|
86
|
+
file = File.new("#{ENV["HOME"]}/.gs_phone","w")
|
87
|
+
file.puts settings.to_yaml
|
88
|
+
file.close
|
89
|
+
|
90
|
+
puts "File #{ENV["HOME"]}/.gs_phone has been created. Please make sure the"
|
91
|
+
puts " settings are correct."
|
92
|
+
exit
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Add a user to the configuration file
|
98
|
+
def add_user(ip_addr=nil)
|
99
|
+
# Lets get some details for the new user
|
100
|
+
puts "GS> Username?"
|
101
|
+
username = STDIN.gets.chomp
|
102
|
+
puts "GS> Extension Number?"
|
103
|
+
password = STDIN.gets.chomp
|
104
|
+
# Skip the ip address if they already passed it in.
|
105
|
+
if ip_addr.nil?
|
106
|
+
puts "GS> Phone IP Address (i.e. 192.168.1.1)"
|
107
|
+
ip_addr = STDIN.gets.chomp
|
108
|
+
end
|
109
|
+
puts "GS> MAC Address?"
|
110
|
+
mac_addy = STDIN.gets.chomp
|
111
|
+
|
112
|
+
# Open the user file and enter the data
|
113
|
+
users = File.open(@user_file, 'a')
|
114
|
+
users.puts "---"
|
115
|
+
users.puts "name: " + username
|
116
|
+
users.puts "ext: " + password
|
117
|
+
users.puts "ip: " + ip_addr
|
118
|
+
users.puts "mac: " + mac_addy
|
119
|
+
users.close
|
120
|
+
|
121
|
+
# Set this so we can use it in other parts of the script if "--new" was called
|
122
|
+
@ip = ip_addr
|
123
|
+
end
|
124
|
+
|
125
|
+
# Generate a config file from the template
|
126
|
+
def make(ip_address=@ip)
|
127
|
+
# Skip the ip address if they already passed it in.
|
128
|
+
if ip_address.nil?
|
129
|
+
puts "GS> What ip address? "
|
130
|
+
ip_address = STDIN.gets.chomp
|
131
|
+
end
|
132
|
+
|
133
|
+
@user_list = Hash.new
|
134
|
+
@phone = Array.new
|
135
|
+
|
136
|
+
# Open the user file and find the user who has the ip address that matches
|
137
|
+
# the one we are looking for
|
138
|
+
users = File.open(@user_file)
|
139
|
+
data = YAML::load_documents(users) do |element|
|
140
|
+
if element['ip'] == ip_address and not element['skip'] == 'y'
|
141
|
+
name = element['name']
|
142
|
+
password = element['ext'].to_s
|
143
|
+
exten = element['ext'].to_s
|
144
|
+
ip = element['ip']
|
145
|
+
|
146
|
+
# Split the ip address into each octal, the Grandstream config files
|
147
|
+
# needs it this way
|
148
|
+
ip1, ip2, ip3, ip4 = ip.split('.')
|
149
|
+
|
150
|
+
templated = IO.readlines(@config_files + "template.cfg")
|
151
|
+
phone_config = ""
|
152
|
+
|
153
|
+
# Substitue in the user fields into their config
|
154
|
+
# a.k.a. Magic REGEX section
|
155
|
+
templated.each do |line|
|
156
|
+
phone_config << line.gsub(/<<ext>>/, exten).gsub(/<<name>>/, name).gsub(/<<password>>/, password).gsub(/<<ip1>>/, ip1).gsub(/<<ip2>>/, ip2).gsub(/<<ip3>>/, ip3).gsub(/<<ip4>>/, ip4)
|
157
|
+
end
|
158
|
+
# Write out the string to a file now
|
159
|
+
File.open("#{@config_files}#{ip}.cfg", "w+") do |file|
|
160
|
+
file.puts phone_config
|
161
|
+
end
|
162
|
+
puts "GS< Made config for extension #{exten.to_s}"
|
163
|
+
end # IF
|
164
|
+
end # DO
|
165
|
+
end
|
166
|
+
|
167
|
+
def make_all
|
168
|
+
puts "GS< Making all configs"
|
169
|
+
@user_list = Hash.new
|
170
|
+
|
171
|
+
users = File.open(@user_file)
|
172
|
+
# Build a hash of the ext to ip
|
173
|
+
data = YAML::load_documents(users) do |element|
|
174
|
+
@user_list[element['ext']] = element['ip']
|
175
|
+
end
|
176
|
+
@user_list.each do |ext,ip|
|
177
|
+
puts "GS< Making config for #{ext} (#{ip})"
|
178
|
+
make(ip)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
# Make a config file and push it to phone via web scraping
|
184
|
+
def update_config(ip_address=@ip, current_ip=nil, admin=nil)
|
185
|
+
# Skip the ip address if they already passed it in.
|
186
|
+
if ip_address.nil?
|
187
|
+
puts "GS> What ip address? "
|
188
|
+
ip_address = STDIN.gets.chomp
|
189
|
+
end
|
190
|
+
if admin.nil?
|
191
|
+
admin = @admin_password
|
192
|
+
end
|
193
|
+
if current_ip.nil?
|
194
|
+
current_ip = ip_address
|
195
|
+
end
|
196
|
+
# Setup the string to shell out to the gsutil script to scrape the webforms
|
197
|
+
cmd = "#{@gsutil} -p '#{admin}' -r '#{current_ip}' < #{@config_files}#{ip_address}.cfg"
|
198
|
+
`#{cmd}`.to_s # Evil eval().
|
199
|
+
puts "GS< Config sent to phone"
|
200
|
+
end
|
201
|
+
|
202
|
+
# Make a config file for each phone and push it to the phone
|
203
|
+
def update_all
|
204
|
+
puts "GS< Updating all phones"
|
205
|
+
@user_list = Hash.new
|
206
|
+
|
207
|
+
users = File.open(@user_file)
|
208
|
+
# Build a hash of the ext to ip
|
209
|
+
data = YAML::load_documents(users) do |element|
|
210
|
+
if not element['skip'] == 'y'
|
211
|
+
@user_list[element['ext']] = element['ip']
|
212
|
+
end
|
213
|
+
end
|
214
|
+
@user_list.each do |ext,ip|
|
215
|
+
puts "GS< Making config for #{ext} (#{ip})"
|
216
|
+
update_config(ip)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
# Reboot a phone
|
222
|
+
def reboot_phone(ip_address=@ip)
|
223
|
+
# Skip the ip address if they already passed it in.
|
224
|
+
if ip_address.nil?
|
225
|
+
puts "GS> What ip address? "
|
226
|
+
ip_address = STDIN.gets.chomp
|
227
|
+
end
|
228
|
+
# Need a delay, if we just uploaded the new config then the phone will give a 500
|
229
|
+
# error if we try to reboot it too soon
|
230
|
+
sleep(3)
|
231
|
+
# Setup the string to shell out to the gsutil script to scrape the webforms
|
232
|
+
cmd = "#{@gsutil} -p '#{@admin_password}' -b '#{ip_address}'"
|
233
|
+
`#{cmd}` # Evil eval() two
|
234
|
+
puts "GS< Phone rebooted"
|
235
|
+
end
|
236
|
+
|
237
|
+
# Reboot all phones
|
238
|
+
def reboot_all_phones
|
239
|
+
puts "GS< Rebooting all phones"
|
240
|
+
@user_list = Hash.new
|
241
|
+
|
242
|
+
users = File.open(@user_file)
|
243
|
+
# Build a hash of the ext to ip
|
244
|
+
data = YAML::load_documents(users) do |element|
|
245
|
+
if not element['skip'] == 'y'
|
246
|
+
@user_list[element['ext']] = element['ip']
|
247
|
+
end
|
248
|
+
end
|
249
|
+
# Need a delay, if we just uploaded the new config then the phone will give a 500
|
250
|
+
# error if we try to reboot it too soon
|
251
|
+
sleep(3)
|
252
|
+
# Go-go BOFH method, this will reboot every phone in the user list.
|
253
|
+
@user_list.each do |ext,ip|
|
254
|
+
puts "GS< Rebooting phone #{ext} (#{ip})"
|
255
|
+
cmd = "#{@gsutil} -p '#{@admin_password}' -b '#{ip}'"
|
256
|
+
`#{cmd}`
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# Finds the ip address of the phone if you know the extension.
|
261
|
+
def find_ip
|
262
|
+
print "What extension? "
|
263
|
+
exten_in = STDIN.gets.chomp.to_i
|
264
|
+
|
265
|
+
# Go thorugh config file loking for the extension
|
266
|
+
data = YAML::load_documents(File.open(@user_file)) do |element|
|
267
|
+
if element['ext'] == exten_in
|
268
|
+
@ip = element['ip']
|
269
|
+
puts "GS< #{element['ip']}"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end # Class
|
274
|
+
|