From 8ca3dbe70a71969bb8a68032f2e9a1dc62bab577 Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Tue, 3 Jun 2014 12:29:11 +0200 Subject: [PATCH] Adding VM support see #8183 need testing. --- plugin/bbb/config.php | 2 +- plugin/bbb/config.vm.dist.php | 35 ++++++ plugin/bbb/cron.php | 28 +++++ plugin/bbb/lib/VM.php | 109 ++++++++++++++++ plugin/bbb/lib/bbb_api.php | 2 +- plugin/bbb/lib/vm/AbstractVM.php | 49 ++++++++ plugin/bbb/lib/vm/AmazonVM.php | 43 +++++++ plugin/bbb/lib/vm/DigitalOceanVM.php | 179 +++++++++++++++++++++++++++ plugin/bbb/lib/vm/VMInterface.php | 28 +++++ plugin/bbb/listing.php | 23 +++- plugin/bbb/plugin.php | 3 +- plugin/bbb/start.php | 38 +++++- 12 files changed, 531 insertions(+), 8 deletions(-) create mode 100644 plugin/bbb/config.vm.dist.php create mode 100644 plugin/bbb/cron.php create mode 100644 plugin/bbb/lib/VM.php create mode 100644 plugin/bbb/lib/vm/AbstractVM.php create mode 100644 plugin/bbb/lib/vm/AmazonVM.php create mode 100644 plugin/bbb/lib/vm/DigitalOceanVM.php create mode 100644 plugin/bbb/lib/vm/VMInterface.php diff --git a/plugin/bbb/config.php b/plugin/bbb/config.php index 248e3d35d4..4f74dc1c5e 100755 --- a/plugin/bbb/config.php +++ b/plugin/bbb/config.php @@ -3,7 +3,7 @@ /* bbb parameters that will be registered in the course settings */ -require_once '../../main/inc/global.inc.php'; +require_once __DIR__ . '/../../main/inc/global.inc.php'; require_once api_get_path(LIBRARY_PATH).'plugin.class.php'; require_once 'lib/bbb.lib.php'; diff --git a/plugin/bbb/config.vm.dist.php b/plugin/bbb/config.vm.dist.php new file mode 100644 index 0000000000..9748a70026 --- /dev/null +++ b/plugin/bbb/config.vm.dist.php @@ -0,0 +1,35 @@ + true, + 'vms' => array( + array( + 'enabled' => true, + 'name' => 'DigitalOcean', + //'host' => 'server-address', + //'user'=> 'AjZjoXMEg0vm7P8QXEWOC', + 'vm_client_id' => 'client_id', + 'api_key' => '123456', + 'vm_id' => '123456', // The VM ID we want to access + 'vm_min_size_id' => '66', // VM size ID example for 512mb use 66 + 'vm_max_size_id' => '65' // For 1GB use 63 + ) + ) +); diff --git a/plugin/bbb/cron.php b/plugin/bbb/cron.php new file mode 100644 index 0000000000..639368e4ca --- /dev/null +++ b/plugin/bbb/cron.php @@ -0,0 +1,28 @@ +IsEnabled()) { + $bbb = new bbb(); + if ($bbb->plugin_enabled) { + $activeSessions = $bbb->getActiveSessionsCount(); + if (empty($activeSessions)) { + $vm->runCron(); + } else { + echo "Can't run cron active sessions found: " . $activeSessions; + } + } + } +} diff --git a/plugin/bbb/lib/VM.php b/plugin/bbb/lib/VM.php new file mode 100644 index 0000000000..2c17b1fce0 --- /dev/null +++ b/plugin/bbb/lib/VM.php @@ -0,0 +1,109 @@ +config = $config; + } + + /** + * @return array + */ + public function getConfig() + { + return $this->config; + } + + /** + * @return bool + */ + public function isEnabled() + { + $config = $this->getConfig(); + + if (!isset($config)) { + return false; + } + + if (!is_array($config)) { + return false; + } + + if (isset($config['enabled']) && $config['enabled']) { + + return true; + } + + return false; + } + + /** + * @return VirtualMachineInterface + */ + public function getVirtualMachine() + { + return $this->virtualMachine; + } + + /** + * @param VirtualMachineInterface $virtualMachine + */ + public function setVirtualMachine(VirtualMachineInterface $virtualMachine) + { + $this->virtualMachine = $virtualMachine; + } + + /** + * @return VirtualMachineInterface + */ + public function getVirtualMachineFromConfig() + { + $vmList = $this->config['vms']; + + foreach ($vmList as $vm) { + if (isset($vm['enabled']) && $vm['enabled'] == true) { + $className = $vm['name'] . 'VM'; + + return new $className($vm); + break; + } + } + + return false; + } + + /** + * Resize the VM to the max size + */ + public function resizeToMaxLimit() + { + $virtualMachine = $this->getVirtualMachineFromConfig(); + $this->setVirtualMachine($virtualMachine); + $virtualMachine->resizeToMaxLimit(); + } + + /** + * Resize the VM to the min size + */ + public function resizeToMinLimit() + { + $virtualMachine = $this->getVirtualMachineFromConfig(); + $this->setVirtualMachine($virtualMachine); + $virtualMachine->resizeToMinLimit(); + } + + public function runCron() + { + $virtualMachine = $this->getVirtualMachineFromConfig(); + $this->setVirtualMachine($virtualMachine); + + $virtualMachine->runCron(); + } +} diff --git a/plugin/bbb/lib/bbb_api.php b/plugin/bbb/lib/bbb_api.php index 630d52d3be..fca63e1921 100755 --- a/plugin/bbb/lib/bbb_api.php +++ b/plugin/bbb/lib/bbb_api.php @@ -164,7 +164,7 @@ class BigBlueButtonBN { */ $xml = $this->_processXmlResponse($this->getCreateMeetingURL($creationParams)); - if($xml) { + if ($xml) { if($xml->meetingID) return array( 'returncode' => $xml->returncode, diff --git a/plugin/bbb/lib/vm/AbstractVM.php b/plugin/bbb/lib/vm/AbstractVM.php new file mode 100644 index 0000000000..8c33e45e5c --- /dev/null +++ b/plugin/bbb/lib/vm/AbstractVM.php @@ -0,0 +1,49 @@ +name = $settings['name']; + $this->host = $settings['host']; + $this->user = $settings['user']; + $this->apiKey = $settings['api_key']; + $this->vmId = $settings['vm_id']; + $this->vmMinSize = $settings['vm_min_size_id']; + $this->vmMaxSize = $settings['vm_max_size_id']; + $this->vmClientId = $settings['vm_client_id']; + } + + /** + * @param string $message + */ + public function addMessage($message) + { + $this->messages[] = $message; + } + + /** + * @return string + */ + public function getMessageToString() + { + return implode(PHP_EOL, $this->messages); + } +} diff --git a/plugin/bbb/lib/vm/AmazonVM.php b/plugin/bbb/lib/vm/AmazonVM.php new file mode 100644 index 0000000000..4c9f712728 --- /dev/null +++ b/plugin/bbb/lib/vm/AmazonVM.php @@ -0,0 +1,43 @@ +connect(); + } + + /** + * @inheritdoc + */ + public function connect() + { + // Set up your credentials. + $credentials = new Credentials($this->vmClientId, $this->apiKey); + // Use the default adapter, CurlHttpAdapter. + $this->connector = new DigitalOcean($credentials); + + // Or use BuzzHttpAdapter. + //$this->connector = new DigitalOcean($credentials, new BuzzHttpAdapter()); + } + + /** + * @return DigitalOcean + */ + public function getConnector() + { + return $this->connector; + } + + /** + * @param string $type min or max + */ + public function resizeTo($type = 'min') + { + try { + $droplets = $this->getConnector()->droplets(); + $sizes = $this->getConnector()->sizes(); + $availableSizes = $sizes->getAll(); + + if (isset($availableSizes->status) && $availableSizes->status == 'OK') { + + $minSizeIdExists = false; + $maxSizeIdExists = false; + + foreach ($availableSizes->sizes as $size) { + if ($size->id == $this->vmMaxSize) { + $maxSizeIdExists = true; + } + if ($size->id == $this->vmMinSizeSize) { + $minSizeIdExists = true; + } + } + if ($maxSizeIdExists && $minSizeIdExists) { + throw new \Exception('Sizes are not well configured'); + } + } else { + throw new \Exception('Sizes not available'); + } + + // Returns all active droplets that are currently running in your account. + //$allActive = $droplets->showAllActive(); + + $dropletInfo = $droplets->show($this->vmId); + + if ($dropletInfo->status == 'OK') { + switch ($type) { + case 'min': + if ($dropletInfo->droplet->size_id == $this->vmMinSize) { + // No resize + $this->addMessage( + 'Nothing to execute. The size was already reduced.' + ); + } else { + $this->resize($this->vmMinSize); + } + + break; + case 'max': + if ($dropletInfo->droplet->size_id == $this->vmMaxSize) { + // No resize + $this->addMessage( + 'Nothing to execute. The size was already boost.' + ); + } else { + $this->resize($this->vmMaxSize); + } + break; + } + } else { + throw new \Exception(" Id " . $this->vmId . " doesn't exists."); + } + } catch (Exception $e) { + die($e->getMessage()); + } + } + + /** + * Turns off / resize / turns on + * @param int $sizeId + */ + public function resize($sizeId) + { + $droplets = $this->getConnector()->droplets(); + $dropletInfo = $droplets->show($this->vmId); + + $powerOff = $droplets->powerOff($this->vmId); + + $this->addMessage('Power off droplet #' . $this->vmId); + + $this->waitForEvent($powerOff->event_id); + + $this->addMessage('Current status: ' . $dropletInfo->droplet->status); + + $resizeDroplet = $droplets->resize( + $this->vmId, + array('size_id' => intval($sizeId)) + ); + $this->addMessage('Resize droplet to size id: ' . $sizeId); + $this->waitForEvent($resizeDroplet->event_id); + + $powerOn = $droplets->powerOn($this->vmId); + $this->waitForEvent($powerOn->event_id); + $this->addMessage('Power on droplet #' . $this->vmId); + + } + + /** + * Loops until an event answer 100 percentage + * @param int $eventId + */ + public function waitForEvent($eventId) + { + $events = $this->getConnector()->events(); + $status = false; + while ($status == false) { + $infoStatus = $events->show($eventId); + if ($infoStatus->status == 'OK' && $infoStatus->event->percentage == 100) { + $status = true; + } + } + } + + /** + * @inheritdoc + */ + public function runCron() + { + $this->resizeToMinLimit(); + echo $this->getMessageToString(); + } + + /** + * @inheritdoc + */ + public function resizeToMaxLimit() + { + $this->resizeTo('max'); + } + + /** + * @inheritdoc + */ + public function resizeToMinLimit() + { + $this->resizeTo('min'); + } +} diff --git a/plugin/bbb/lib/vm/VMInterface.php b/plugin/bbb/lib/vm/VMInterface.php new file mode 100644 index 0000000000..5c64bf3025 --- /dev/null +++ b/plugin/bbb/lib/vm/VMInterface.php @@ -0,0 +1,28 @@ +end_meeting($_GET['id']); - $message = Display::return_message(get_lang('MeetingClosed').'
'.get_lang('MeetingClosedComment'), 'success', false); + $message = Display::return_message( + get_lang('MeetingClosed') . '
' . get_lang( + 'MeetingClosedComment' + ), + 'success', + false + ); + + if (file_exists(__DIR__ . '/config.vm.php')) { + require __DIR__ . '/../../vendor/autoload.php'; + + require __DIR__ . '/lib/vm/AbstractVM.php'; + require __DIR__ . '/lib/vm/VMInterface.php'; + require __DIR__ . '/lib/vm/DigitalOceanVM.php'; + require __DIR__ . '/lib/VM.php'; + + $config = require __DIR__ . '/config.vm.php'; + + $vm = new VM($config); + $vm->resizeToMinLimit(); + } + break; case 'publish': //$result = $bbb->publish_meeting($_GET['id']); diff --git a/plugin/bbb/plugin.php b/plugin/bbb/plugin.php index 4c38a011e1..a9ad573475 100755 --- a/plugin/bbb/plugin.php +++ b/plugin/bbb/plugin.php @@ -1,4 +1,5 @@ get_info(); \ No newline at end of file + +$plugin_info = BBBPlugin::create()->get_info(); diff --git a/plugin/bbb/start.php b/plugin/bbb/start.php index f9c0ae8a7b..488fdec884 100755 --- a/plugin/bbb/start.php +++ b/plugin/bbb/start.php @@ -1,16 +1,23 @@ plugin_enabled) { @@ -18,6 +25,29 @@ if ($bbb->plugin_enabled) { if (isset($_GET['launch']) && $_GET['launch'] == 1) { + if (file_exists(__DIR__ . '/config.vm.php')) { + $config = require __DIR__ . '/config.vm.php'; + $vmIsEnabled = true; + $host = null; + $salt = null; + + require __DIR__ . '/lib/vm/AbstractVM.php'; + require __DIR__ . '/lib/vm/VMInterface.php'; + require __DIR__ . '/lib/vm/DigitalOceanVM.php'; + require __DIR__ . '/lib/VM.php'; + + $vm = new VM($config); + + if ($vm->IsEnabled()) { + try { + $vm->resizeToMaxLimit(); + } catch (\Exception $e) { + echo $e->getMessage(); + exit; + } + } + } + $meeting_params = array(); $meeting_params['meeting_name'] = api_get_course_id().'-'.api_get_session_id();