Skip to content

Commit

Permalink
URL matching for control commands
Browse files Browse the repository at this point in the history
This patch allows all commands to accept not only an exact ID match but
also search patterns for matching URLs. This allows for a much easier
control of groups of servers instead of having to find out the servers
identifier every time and then handle each server indivifually.

For example, you can run the following command to enbale multiple
servers:

    ./bin/rake 'servers:enable[bbb0\[1-5\].lkiesow.io]'

You can still use exact identifier matches though and the identifiers
will always be checked before checking the URL. Hence, you still can use
a command like:

    ./bin/rake 'servers:disable[a18201ec-f090-4bff-aaac-d0f5ab003f42]'

This closes #205 which was trying to solve the same problem by using the
host manes as server identifier instead. That shouldn't be necessary any
longer when this patch is applied.
  • Loading branch information
lkiesow committed Mar 1, 2021
1 parent 8aecbee commit fc08449
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 44 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,12 @@ Scalelite comes with a set of commands to

Server management is provided using rake tasks which update server information in Redis.

In a Docker deployment, these should be run from in the Docker container. You can enter the Docker container using a command like `docker exec -it scalelite-api /bin/sh`
In a Docker deployment, these should be run from in the Docker container.
You can enter the container using a command like `docker exec -it scalelite-api /bin/sh`
or execute rake directly using `docker exec -it scalelite-api bin/rake …`.

All server commands can be used with either a specific server ID or a regular expressions matching the URL as argument.


### Show configured server details

Expand All @@ -206,6 +211,18 @@ id: 2d2d674a-c6bb-48f3-8ad4-68f33a80a5b7
online
```

as with all commands, you can search for specific servers using:

```sh
./bin/rake servers:[bbb.*\\.example\\.com]
```

or

```sh
./bin/rake servers:[bbb0\[1-5\].example.com]
```

Particular information to note:

* `id`: This is the ID value used when updating or removing the server
Expand Down
27 changes: 27 additions & 0 deletions app/models/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,33 @@ def self.find(id)
end
end

# Find a server by ID or URL
def self.find_all(search)
servers = []
with_connection do |redis|
ids = redis.smembers('servers')
raise RecordNotFound.new('No servers conficured', name, nil) if ids.blank?

search_regexp = Regexp.new(search)

ids.each do |id|
hash, enabled, load = redis.pipelined do
redis.hgetall(key(id))
redis.sismember('server_enabled', id)
redis.zscore('server_load', id)
end
next if hash.blank? || (search != id && !search_regexp.match?(hash['url']))

hash['id'] = id
hash['enabled'] = enabled
hash['load'] = load if enabled
hash['online'] = (hash['online'] == 'true')
servers << new.init_with_attributes(hash)
end
end
servers
end

# Find the server with the lowest load (for creating a new meeting)
def self.find_available
with_connection do |redis|
Expand Down
93 changes: 50 additions & 43 deletions lib/tasks/servers.rake
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# frozen_string_literal: true

desc('List configured BigBlueButton servers')
task servers: :environment do
servers = Server.all
puts('No servers are configured') if servers.empty?
task :servers, [:search] => :environment do |_t, args|
servers = args.search.nil? ? Server.all : Server.find_all(args.search)
puts('No servers found') if servers.empty?
servers.each do |server|
puts("id: #{server.id}")
puts("\turl: #{server.url}")
Expand Down Expand Up @@ -35,75 +35,82 @@ namespace :servers do
puts("id: #{server.id}")
end

desc 'Remove a BigBlueButton server'
task :remove, [:id] => :environment do |_t, args|
server = Server.find(args.id)
server.destroy!
desc 'Remove BigBlueButton servers'
task :remove, [:search] => :environment do |_t, args|
Server.find_all(args.search).each(&:destroy!)
puts('OK')
rescue ApplicationRedisRecord::RecordNotFound
puts("ERROR: No server found with id: #{args.id}")
puts("ERROR: No server found matching: #{args.id}")
end

desc 'Mark a BigBlueButton server as available for scheduling new meetings'
task :enable, [:id] => :environment do |_t, args|
server = Server.find(args.id)
server.enabled = true
server.save!
task :enable, [:search] => :environment do |_t, args|
servers = Server.find_all(args.search)
servers.each do |server|
server.enabled = true
server.save!
end
puts('OK')
rescue ApplicationRedisRecord::RecordNotFound
puts("ERROR: No server found with id: #{args.id}")
puts("ERROR: No server found matching: #{args.search}")
end

desc 'Mark a BigBlueButton server as unavailable to stop scheduling new meetings'
task :disable, [:id] => :environment do |_t, args|
server = Server.find(args.id)
server.enabled = false
server.save!
task :disable, [:search] => :environment do |_t, args|
servers = Server.find_all(args.search)
servers.each do |server|
server.enabled = false
server.save!
end
puts('OK')
rescue ApplicationRedisRecord::RecordNotFound
puts("ERROR: No server found with id: #{args.id}")
puts("ERROR: No server found matching: #{args.search}")
end

desc 'Mark a BigBlueButton server as unavailable, and clear all meetings from it'
task :panic, [:id, :keep_state] => :environment do |_t, args|
task :panic, [:search, :keep_state] => :environment do |_t, args|
args.with_defaults(keep_state: false)
include ApiHelper

server = Server.find(args.id)
server.enabled = false unless args.keep_state
server.save!
servers = Server.find_all(args.search)
servers.each do |server|
server.enabled = false unless args.keep_state
server.save!

meetings = Meeting.all.select { |m| m.server_id == server.id }
meetings.each do |meeting|
puts("Clearing Meeting id=#{meeting.id}")
meeting.destroy!
meetings = Meeting.all.select { |m| m.server_id == server.id }
meetings.each do |meeting|
puts("Clearing Meeting id=#{meeting.id}")
meeting.destroy!

get_post_req(encode_bbb_uri('end', server.url, server.secret, meetingID: meeting.id))
rescue ApplicationRedisRecord::RecordNotDestroyed => e
puts("WARNING: Could not destroy meeting id=#{meeting.id}: #{e}")
rescue StandardError => e
puts("WARNING: Could not end meeting id=#{meeting.id}: #{e}")
get_post_req(encode_bbb_uri('end', server.url, server.secret, meetingID: meeting.id))
rescue ApplicationRedisRecord::RecordNotDestroyed => e
puts("WARNING: Could not destroy meeting id=#{meeting.id}: #{e}")
rescue StandardError => e
puts("WARNING: Could not end meeting id=#{meeting.id}: #{e}")
end
end
puts('OK')
rescue ApplicationRedisRecord::RecordNotFound
puts("ERROR: No server found with id: #{args.id}")
puts("ERROR: No server found matching: #{args.search}")
end

desc 'Set the load-multiplier of a BigBlueButton server'
task :loadMultiplier, [:id, :load_multiplier] => :environment do |_t, args|
server = Server.find(args.id)
tmp_load_multiplier = 1.0
unless args.load_multiplier.nil?
tmp_load_multiplier = args.load_multiplier.to_d
if tmp_load_multiplier.zero?
puts('WARNING! Load-multiplier was not readable or 0, so it is now 1')
tmp_load_multiplier = 1.0
task :loadMultiplier, [:search, :load_multiplier] => :environment do |_t, args|
servers = Server.find_all(args.search)
servers.each do |server|
tmp_load_multiplier = 1.0
unless args.load_multiplier.nil?
tmp_load_multiplier = args.load_multiplier.to_d
if tmp_load_multiplier.zero?
puts('WARNING! Load-multiplier was not readable or 0, so it is now 1')
tmp_load_multiplier = 1.0
end
end
server.load_multiplier = tmp_load_multiplier
server.save!
end
server.load_multiplier = tmp_load_multiplier
server.save!
puts('OK')
rescue ApplicationRedisRecord::RecordNotFound
puts("ERROR: No server found with id: #{args.id}")
puts("ERROR: No server found matching: #{args.search}")
end
end

0 comments on commit fc08449

Please sign in to comment.