async def Remove_VIF(self, VIF_name): LOG.info("Removing a VIF from the board") try: LOG.info("Removing VIF") LOG.debug("Removing VIF :" + str(VIF_name)) LOG.info(VIF_name[8:]) p1 = subprocess.Popen("kill $(ps aux | grep -e '-r'" + VIF_name[8:] + " | awk '{print $2}')", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p1 = subprocess.Popen("kill $(ps aux | grep -e 'dhclient " + VIF_name + "' | awk '{print $2}')", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) message = 'VIF removed' w_msg = WM.WampSuccess(message) LOG.info("VIF removed") except Exception as e: LOG.error(str(e)) message = 'Error while removing the VIF' w_msg = WM.WampError(message) return w_msg.serialize()
async def Configure_VIF(self, port_mac, ip_add, cidr): LOG.info("Configuration of the VIF") try: LOG.debug("Configuration of the VIF " + interface) p3 = subprocess.Popen("ip link set dev " + interface + " address " + str(port_mac), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) time.sleep(1) p5 = subprocess.Popen("ip address add " + str(ip_add) + "/" + str(cidr) + " dev " + interface, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) #p5 = subprocess.Popen("ip link set " + interface + " up" , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) message = 'IP address assigned' w_msg = WM.WampSuccess(message) LOG.info("Configuration succeded") except Exception as e: LOG.error(str(e)) message = 'Error while the configuration' w_msg = WM.WampError(message) return w_msg.serialize()
async def Create_VIF(self, r_tcp_port): LOG.info("Creation of the VIF ") port_socat = random.randint(10000, 20000) i = 0 while i < len(Port): if Port[i] == port_socat: i = 0 port_socat = random.randint(10000, 20000) i += 1 Port.insert(0, port_socat) LOG.debug("Creation of the VIF iotronic" + str(r_tcp_port)) #LOG.debug('Creating virtual interface on the board') try: p2 = subprocess.Popen( 'socat -d -d TCP-L:' + str(port_socat) + ',bind=localhost,reuseaddr,forever,interval=10 TUN,tun-type=tap,tun-name=iotronic' + str(r_tcp_port) + ',up ', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) #ws://192.168.17.105:8080 p1 = subprocess.Popen('wstun -r' + str(r_tcp_port) + ':localhost:' + str(port_socat) + ' ' + str(self.wagent_url), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) LOG.debug('Creation of the VIF succeded: iotronic') global interface interface = 'iotronic' + str(r_tcp_port) message = 'creation de WS tun et SOCAT' w_msg = WM.WampSuccess(message) except: LOG.error('Error while creating the virtual interface') message = 'Error while the creation' w_msg = WM.WampError(message) return w_msg.serialize()
async def PluginStatus(self, plugin_uuid): """Check status thread plugin :param plugin_uuid: :return: """ rpc_name = utils.getFuncName() LOG.info("RPC " + rpc_name + " CALLED for '" + plugin_uuid + "' plugin:") try: if plugin_uuid in PLUGINS_THRS: worker = PLUGINS_THRS[plugin_uuid] if worker.isAlive(): result = "ALIVE" else: result = "DEAD" LOG.info(" - " + worker.complete(rpc_name, result)) w_msg = WM.WampSuccess(result) else: result = "DEAD" LOG.info(" - " + rpc_name + " result for " + plugin_uuid + ": " + result) w_msg = WM.WampSuccess(result) except Exception as err: message = \ rpc_name \ + " - ERROR - plugin (" + plugin_uuid + ") - " + str(err) LOG.error(" - " + message) w_msg = WM.WampError(str(err)) return w_msg.serialize() return w_msg.serialize()
def PluginReboot(self, plugin_uuid): """To reboot an asynchronous plugin (callable = false) into the board. :return: return a response to RPC request """ rpc_name = getFuncName() LOG.info("RPC " + rpc_name + " CALLED for '" + plugin_uuid + "' plugin:") try: plugin_home = iotronic_home + "/plugins/" + plugin_uuid plugin_filename = plugin_home + "/" + plugin_uuid + ".py" plugin_params_file = plugin_home + "/" + plugin_uuid + ".json" plugins_conf = loadPluginsConf() plugin_name = plugins_conf['plugins'][plugin_uuid]['name'] callable = plugins_conf['plugins'][plugin_uuid]['callable'] if callable is False: if plugin_uuid in PLUGINS_THRS: worker = PLUGINS_THRS[plugin_uuid] if worker.isAlive(): # STOP PLUGIN------------------------------------------ LOG.info(" - Thread " + plugin_uuid + " is running, stopping...") LOG.debug(" - Stopping plugin " + str(worker)) worker.stop() # Remove from plugin thread list del PLUGINS_THRS[plugin_uuid] # START PLUGIN------------------------------------------------- if os.path.exists(plugin_filename): # Import plugin python module task = imp.load_source("plugin", plugin_filename) if os.path.exists(plugin_params_file): with open(plugin_params_file) as conf: plugin_params = json.load(conf) else: plugin_params = None worker = task.Worker(plugin_uuid, plugin_name, params=plugin_params) PLUGINS_THRS[plugin_uuid] = worker LOG.info(" - Starting plugin " + str(worker)) worker.start() message = "REBOOTED" LOG.info(" - " + worker.complete(rpc_name, message)) w_msg = yield WM.WampSuccess(message) else: message = "ERROR '" + plugin_filename + "' does not exist!" LOG.error(" - " + message) w_msg = yield WM.WampError(message) except Exception as err: message = "Error rebooting plugin '" \ + plugin_uuid + "': " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) returnValue(w_msg.serialize())
def PluginRemove(self, plugin_uuid): """To remove a plugin from the board :param plugin_uuid: :return: return a response to RPC request """ rpc_name = getFuncName() LOG.info("RPC " + rpc_name + " for plugin " + plugin_uuid) plugin_path = iotronic_home + "/plugins/" + plugin_uuid + "/" if os.path.exists(plugin_path) is False \ or os.path.exists(PLUGINS_CONF_FILE) is False: message = "Plugin paths or files do not exist!" LOG.error(message) w_msg = yield WM.WampError(message) returnValue(w_msg.serialize()) else: LOG.info(" - Removing plugin...") try: try: shutil.rmtree(plugin_path, ignore_errors=False, onerror=None) except Exception as err: message = "Removing plugin's files error in " \ + plugin_path + ": " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) # Remove from plugins.json file its configuration try: plugins_conf = loadPluginsConf() if plugin_uuid in plugins_conf['plugins']: plugin_name = \ plugins_conf['plugins'][plugin_uuid]['name'] del plugins_conf['plugins'][plugin_uuid] with open(PLUGINS_CONF_FILE, 'w') as f: json.dump(plugins_conf, f, indent=4) if plugin_uuid in PLUGINS_THRS: worker = PLUGINS_THRS[plugin_uuid] if worker.isAlive(): LOG.info(" - Plugin " + plugin_name + " is running...") worker.stop() LOG.info(" ...stopped!") del PLUGINS_THRS[plugin_uuid] message = "PluginRemove result: " \ + plugin_uuid + " removed!" LOG.info(" - " + message) else: message = "PluginRemove result: " \ + plugin_uuid + " already removed!" LOG.warning(" - " + message) w_msg = yield WM.WampSuccess(message) returnValue(w_msg.serialize()) except Exception as err: message = "Updating plugins.json error: " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) except Exception as err: message = "Plugin removing error: {0}".format(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize())
def PluginCall(self, plugin_uuid, parameters=None): """To execute a synchronous plugin into the board :param plugin_uuid: :param parameters: :return: return a response to RPC request """ rpc_name = getFuncName() LOG.info("RPC " + rpc_name + " CALLED for " + plugin_uuid + " plugin:") try: if (plugin_uuid in PLUGINS_THRS) and (PLUGINS_THRS[plugin_uuid].isAlive()): message = "Plugin " + plugin_uuid + " already started!" LOG.warning(" - " + message) w_msg = yield WM.WampWarning(message) else: plugin_home = iotronic_home + "/plugins/" + plugin_uuid plugin_filename = plugin_home + "/" + plugin_uuid + ".py" plugin_params_file = plugin_home + "/" + plugin_uuid + ".json" plugins_conf = loadPluginsConf() plugin_name = plugins_conf['plugins'][plugin_uuid]['name'] # Import plugin (as python module) if os.path.exists(plugin_filename): try: task = imp.load_source("plugin", plugin_filename) LOG.info(" - Plugin " + plugin_uuid + " imported!") q_result = Queue() except Exception as err: message = "Error importing plugin " \ + plugin_filename + ": " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) try: # Store input parameters of the plugin if parameters is not None: with open(plugin_params_file, 'w') as f: json.dump(parameters, f, indent=4) with open(plugin_params_file) as conf: plugin_params = json.load(conf) LOG.info(" - Plugin configuration:\n" + str(plugin_params)) else: plugin_params = None worker = task.Worker(plugin_uuid, plugin_name, q_result=q_result, params=plugin_params) PLUGINS_THRS[plugin_uuid] = worker LOG.debug(" - Executing plugin " + str(worker)) worker.start() while q_result.empty(): pass response = q_result.get() LOG.info(" - " + worker.complete(rpc_name, response)) w_msg = yield WM.WampSuccess(response) except Exception as err: message = "Error spawning plugin " \ + plugin_filename + ": " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) else: message = \ rpc_name \ + " - ERROR " + plugin_filename + " does not exist!" LOG.error(" - " + message) w_msg = yield WM.WampError(message) except Exception as err: message = \ rpc_name \ + " - ERROR - plugin (" + plugin_uuid + ") - " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) returnValue(w_msg.serialize())
def PluginStop(self, plugin_uuid, parameters=None): """To stop an asynchronous plugin :param plugin_uuid: ID of plufin to stop :param parameters: JSON OPTIONAL stop parameters; 'delay' in seconds :return: return a response to RPC request """ rpc_name = getFuncName() LOG.info("RPC " + rpc_name + " CALLED for '" + plugin_uuid + "' plugin:") if parameters is not None: LOG.info(" - " + rpc_name + " parameters: " + str(parameters)) if 'delay' in parameters: delay = parameters['delay'] LOG.info(" --> stop delay: " + str(delay)) try: if plugin_uuid in PLUGINS_THRS: worker = PLUGINS_THRS[plugin_uuid] LOG.debug(" - Stopping plugin " + str(worker)) if worker.isAlive(): if 'delay' in parameters: time.sleep(delay) yield worker.stop() del PLUGINS_THRS[plugin_uuid] message = "STOPPED" LOG.info(" - " + worker.complete(rpc_name, message)) w_msg = yield WM.WampSuccess(message) else: message = \ rpc_name \ + " - ERROR - plugin (" + plugin_uuid \ + ") is instantiated but is not running anymore!" LOG.error(" - " + message) w_msg = yield WM.WampError(message) else: message = \ rpc_name + " - WARNING " \ + plugin_uuid + " is not running!" LOG.warning(" - " + message) w_msg = yield WM.WampWarning(message) except Exception as err: message = \ rpc_name \ + " - ERROR - plugin (" + plugin_uuid + ") - " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) returnValue(w_msg.serialize())
def PluginStart(self, plugin_uuid, parameters=None): """To start an asynchronous plugin; the plugin will run until the PluginStop is called. :param plugin_uuid: :param parameters: :return: return a response to RPC request """ try: rpc_name = getFuncName() LOG.info("RPC " + rpc_name + " called for '" + plugin_uuid + "' plugin:") plugins_conf = loadPluginsConf() if plugin_uuid in plugins_conf['plugins']: plugin_name = plugins_conf['plugins'][plugin_uuid]['name'] # Check if the plugin is already running if (plugin_uuid in PLUGINS_THRS) and ( PLUGINS_THRS[plugin_uuid].isAlive()): message = "ALREADY STARTED!" LOG.warning(" - Plugin " + plugin_uuid + " already started!") w_msg = yield WM.WampError(message) else: plugin_home = \ iotronic_home + "/plugins/" + plugin_uuid plugin_filename = \ plugin_home + "/" + plugin_uuid + ".py" plugin_params_file = \ plugin_home + "/" + plugin_uuid + ".json" # Import plugin (as python module) if os.path.exists(plugin_filename): task = imp.load_source("plugin", plugin_filename) LOG.info(" - Plugin '" + plugin_uuid + "' imported!") # Store input parameters of the plugin if parameters is not None: with open(plugin_params_file, 'w') as f: json.dump(parameters, f, indent=4) with open(plugin_params_file) as conf: plugin_params = json.load(conf) LOG.info(" - plugin with parameters:") LOG.info(" " + str(plugin_params)) else: plugin_params = None worker = task.Worker(plugin_uuid, plugin_name, params=plugin_params) PLUGINS_THRS[plugin_uuid] = worker LOG.debug(" - Starting plugin " + str(worker)) worker.start() # Apply the changes to plugins.json with open(PLUGINS_CONF_FILE, 'w') as f: plugins_conf['plugins'][plugin_uuid]['status'] = \ 'operative' json.dump(plugins_conf, f, indent=4) response = "STARTED" LOG.info(" - " + worker.complete(rpc_name, response)) w_msg = yield WM.WampSuccess(response) else: message = \ rpc_name + " - ERROR " \ + plugin_filename + " does not exist!" LOG.error(" - " + message) w_msg = yield WM.WampError(message) else: message = "Plugin " + plugin_uuid \ + " does not exist in this board!" LOG.warning(" - " + message) w_msg = yield WM.WampError(message) except Exception as err: message = \ rpc_name + " - ERROR - plugin (" + plugin_uuid + ") - " \ + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) returnValue(w_msg.serialize())
def PluginInject(self, plugin, onboot): """Plugin injection procedure into the board: 1. get Plugin files 2. deserialize files 3. store files :param plugin: :param onboot: :return: """ rpc_name = getFuncName() try: plugin_uuid = plugin['uuid'] plugin_name = plugin['name'] code = plugin['code'] callable = plugin['callable'] LOG.info("RPC " + rpc_name + " for plugin '" + plugin_name + "' (" + plugin_uuid + ")") # Deserialize the plugin code received ser = PluginSerializer.ObjectSerializer() loaded = ser.deserialize_entity(code) # LOG.debug("- plugin loaded code:\n" + loaded) plugin_path = iotronic_home + "/plugins/" + plugin_uuid + "/" plugin_filename = plugin_path + plugin_uuid + ".py" # Plugin folder creation if does not exist if not os.path.exists(plugin_path): os.makedirs(plugin_path) # Plugin code file creation with open(plugin_filename, "w") as pluginfile: pluginfile.write(loaded) # Load plugins.json configuration file plugins_conf = loadPluginsConf() # LOG.debug("Plugin setup:\n" # + json.dumps(plugin, indent=4, sort_keys=True)) # Save plugin settings in plugins.json if plugin_uuid not in plugins_conf['plugins']: # It is a new plugin plugins_conf['plugins'][plugin_uuid] = {} plugins_conf['plugins'][plugin_uuid]['name'] = plugin_name plugins_conf['plugins'][plugin_uuid]['onboot'] = onboot plugins_conf['plugins'][plugin_uuid]['callable'] = callable plugins_conf['plugins'][plugin_uuid]['injected_at'] = \ datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') plugins_conf['plugins'][plugin_uuid]['updated_at'] = "" plugins_conf['plugins'][plugin_uuid]['status'] = "injected" LOG.info("Plugin " + plugin_name + " created!") message = rpc_name + " result: INJECTED" else: # The plugin was already injected and we are updating it plugins_conf['plugins'][plugin_uuid]['name'] = plugin_name plugins_conf['plugins'][plugin_uuid]['onboot'] = onboot plugins_conf['plugins'][plugin_uuid]['callable'] = callable plugins_conf['plugins'][plugin_uuid]['updated_at'] = \ datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') plugins_conf['plugins'][plugin_uuid]['status'] = "updated" LOG.info("Plugin " + plugin_name + " (" + str(plugin_uuid) + ") updated!") message = rpc_name + " result: UPDATED" LOG.info("Plugin setup:\n" + json.dumps( plugins_conf['plugins'][plugin_uuid], indent=4, sort_keys=True) ) # Apply the changes to plugins.json with open(PLUGINS_CONF_FILE, 'w') as f: json.dump(plugins_conf, f, indent=4) LOG.info(" - " + message) w_msg = yield WM.WampSuccess(message) except Exception as err: message = "Plugin injection error: " + str(err) LOG.error(" - " + message) w_msg = yield WM.WampError(str(err)) returnValue(w_msg.serialize()) returnValue(w_msg.serialize())
async def ServiceRestore(self, service, public_port): rpc_name = utils.getFuncName() service_name = service['name'] service_uuid = service['uuid'] LOG.info("RPC " + rpc_name + " CALLED for '" + service_name + "' (" + service_uuid + ") service:") # Load services.json configuration file services_conf = self._loadServicesConf() if service_uuid in services_conf['services']: local_port = \ services_conf['services'][service_uuid]['local_port'] service_pid = \ services_conf['services'][service_uuid]['pid'] try: # 1. Kill wstun process (if exists) try: os.kill(service_pid, signal.SIGKILL) LOG.info(" - service '" + service_name + "' with PID " + str(service_pid) + " was killed.") except OSError: LOG.warning(" - WSTUN process already killed: " "creating new one...") # 2. Create the reverse tunnel wstun = self._startWstun(public_port, local_port) if wstun != None: service_pid = wstun.pid # UPDATE services.json file services_conf['services'][service_uuid]['pid'] = \ service_pid services_conf['services'][service_uuid]['updated_at'] = \ datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') self._updateServiceConf(services_conf, service_uuid, output=True) message = "service " + str(service_name) \ + " restored on port " \ + str(public_port) + " on " + self.url_ip LOG.info(" - " + message + " with PID " + str(service_pid)) w_msg = WM.WampSuccess(message) else: message = "Error spawning " + str(service_name) \ + " service tunnel!" LOG.error(" - " + message) w_msg = WM.WampError(message) except Exception as err: message = "Error restoring '" + str(service_name) \ + "' service tunnel: " + str(err) LOG.error(" - " + message) w_msg = WM.WampError(message) else: local_port = service['port'] wstun = self._startWstun(public_port, local_port) if wstun != None: service_pid = wstun.pid services_conf['services'][service_uuid] = {} services_conf['services'][service_uuid]['name'] = \ service_name services_conf['services'][service_uuid]['public_port'] = \ public_port services_conf['services'][service_uuid]['local_port'] = \ local_port services_conf['services'][service_uuid]['pid'] = \ service_pid services_conf['services'][service_uuid]['enabled_at'] = \ datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') services_conf['services'][service_uuid]['updated_at'] = "" self._updateServiceConf(services_conf, service_uuid, output=True) message = "service " + str(service_name) \ + " restored on port " \ + str(public_port) + " on " + self.url_ip LOG.info(" - " + message + " with PID " + str(service_pid)) w_msg = WM.WampSuccess(message) else: message = "Error spawning " + str(service_name) \ + " service tunnel!" LOG.error(" - " + message) w_msg = WM.WampError(message) return w_msg.serialize()
async def ServiceDisable(self, service): rpc_name = utils.getFuncName() service_name = service['name'] service_uuid = service['uuid'] LOG.info("RPC " + rpc_name + " CALLED for '" + service_name + "' (" + service_uuid + ") service:") # Remove from services.json file try: # Load services.json configuration file services_conf = self._loadServicesConf() if service_uuid in services_conf['services']: service_pid = services_conf['services'][service_uuid]['pid'] try: os.kill(service_pid, signal.SIGKILL) message = "Cloud service '" \ + str(service_name) + "' tunnel disabled." del services_conf['services'][service_uuid] self._updateServiceConf(services_conf, service_uuid, output=False) LOG.info(" - " + message) w_msg = WM.WampSuccess(message) except Exception as err: if err.errno == errno.ESRCH: # ESRCH == No such process message = "Service '" + str( service_name) + "' WSTUN process is not running!" LOG.warning(" - " + message) del services_conf['services'][service_uuid] self._updateServiceConf(services_conf, service_uuid, output=False) w_msg = WM.WampWarning(message) else: message = "Error disabling '" + str( service_name) + "' service tunnel: " + str(err) LOG.error(" - " + message) w_msg = WM.WampError(message) else: message = rpc_name + " result: " + service_uuid \ + " already removed!" LOG.error(" - " + message) w_msg = WM.WampError(message) except Exception as err: message = "Updating services.json error: " + str(err) LOG.error(" - " + message) w_msg = WM.WampError(message) return w_msg.serialize()
async def ServiceEnable(self, service, public_port): rpc_name = utils.getFuncName() service_name = service['name'] service_uuid = service['uuid'] local_port = service['port'] LOG.info("RPC " + rpc_name + " CALLED for '" + service_name + "' (" + service_uuid + ") service:") try: wstun = self._startWstun(public_port, local_port) if wstun != None: service_pid = wstun.pid LOG.debug(" - WSTUN stdout: " + str(wstun.stdout)) # Update services.json file # Load services.json configuration file services_conf = self._loadServicesConf() # Save plugin settings in services.json if service_uuid not in services_conf['services']: # It is a new plugin services_conf['services'][service_uuid] = {} services_conf['services'][service_uuid]['name'] = \ service_name services_conf['services'][service_uuid]['public_port'] = \ public_port services_conf['services'][service_uuid]['local_port'] = \ local_port services_conf['services'][service_uuid]['pid'] = \ service_pid services_conf['services'][service_uuid]['enabled_at'] = \ datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') services_conf['services'][service_uuid]['updated_at'] = "" else: # The service was already added and we are updating it services_conf['services'][service_uuid]['updated_at'] = \ datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') LOG.info(" - services.json file updated!") # Apply the changes to services.json self._updateServiceConf(services_conf, service_uuid, output=True) message = "Cloud service '" + str(service_name) \ + "' exposed on port " \ + str(public_port) + " on " + self.url_ip LOG.info(" - " + message + " with PID " + str(service_pid)) w_msg = WM.WampSuccess(message) else: message = "Error spawning " + str(service_name) \ + " service tunnel!" LOG.error(" - " + message) w_msg = WM.WampError(message) except Exception as err: message = "Error exposing " + str(service_name) \ + " service: " + str(err) LOG.error(" - " + message) w_msg = WM.WampError(message) return w_msg.serialize()