source: lmd/trunk/fuentes/lmd-server.install/usr/share/n4d/python-plugins/LmdServer.py @ 928

Last change on this file since 928 was 928, checked in by mabarracus, 5 years ago

wip

File size: 25.1 KB
Line 
1import socket
2import subprocess
3import sys
4
5import threading
6import time
7import datetime
8
9import json
10
11import os
12import signal
13
14import shutil
15import tempfile
16
17import tarfile
18import apt_pkg
19
20import lliurex.net
21
22class LmdServer:
23        def __init__(self):
24
25                self.last_job_id=0;
26                self.joblist=[]
27                self.global_listeners = {}
28                self.thread_jobs = {}
29                # Threading Multicast process to all listeners
30                self.multicast_thread = threading.Thread()
31                self.logfolder = '/run/lmdserver'
32                self.ltsp_path = '/opt/ltsp'
33                self.locks = {}
34                # Clean log folder and create
35                if (os.path.exists(self.logfolder)):
36                        shutil.rmtree(self.logfolder)
37                os.mkdir(self.logfolder)
38               
39                pass
40        #def __init__
41       
42        def set_default_boot(self,imgid):
43                dbm = objects['LmdBootManager'].getDefaultBootImage()
44                if dbm['default_boot'] == "":
45                        objects['LmdBootManager'].setDefaultBootImage(imgid)
46
47
48        def check_chroot_exists(self, name):
49                '''
50                Check if exists chroot /opt/ltsp/name and /opt/ltsp/images/name.img
51                DATE: 03/04/2014
52                '''
53                path=os.path.join("/opt/ltsp",name)
54                imagepath=os.path.join("/opt/ltsp/images",name+".img")
55               
56                #print "cheking "+name
57                if(os.path.isdir(path)):
58                        #print "111"
59                        return {"status": True, "error": 'chroot_exists'}
60               
61                if (os.path.isfile(imagepath)):
62                        #print "22222"
63                        return {"status": True, "error": 'image_exists'}
64                return {"status": False}
65               
66       
67        def create_image(self, ip, port, imgid, name, template, description='', bgimg='', srv_ip='127.0.0.1'):
68                try:
69                        # creates an image from an specified template
70               
71                        # Check if template exists
72                        path="/etc/ltsp/templates/"+template;
73                        if(os.path.isfile(path)):
74                                extraLliurexOpts="--accept-unsigned-packages --purge-chroot"
75                                # if template exists, create an image
76                                print "[LmdServer] Create_image from "+path
77                                command="ltsp-build-client --config "+path+" "+extraLliurexOpts+" --chroot "+imgid+"&& service nbd-server restart";
78                               
79                                metadata = {'id':imgid, 'name' : name,
80                                                        'desc' : description ,
81                                                        "template" : template,
82                                                        'img': bgimg,
83                                                        'ltsp_fatclient': 'undefined',
84                                                        'ldm_session': 'default',
85                                                        'fat_ram_threshold': 'default',
86                                                        'lmd_extra_params':'' }
87                               
88                                metadata_string = unicode(json.dumps(metadata,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
89                                objects['LmdImageManager'].setImage(imgid,metadata_string)
90                                self.set_default_boot(imgid)
91                                #command="cat "+path+"; sleep 15; cat "+path+"; echo 'command is: ltsp-build-client --config "+path+" "+extraLliurexOpts+" --chroot "+imgid+"'";
92                                #command="/tmp/miscript"
93                                #command="tree /"
94                                result=self.do_command(ip, port, command, srv_ip,target=imgid)
95                               
96                                # Registering imgid for boot PXE MEnu
97                                objects['LlxBootManager'].pushToBootList("ltsp_label"+str(imgid));
98                               
99                                return result
100
101                        else:
102                                return "{'status':'false', 'error':'template does not exists'}"
103                       
104                        pass
105                except Exception as e:
106                        print "Except: "+str(e)
107                        return e
108               
109       
110        def refresh_image(self, ip, username, password, port, imgid, srv_ip='127.0.0.1'):
111               
112                # Rebuild img file for imgid
113                import xmlrpclib
114
115                try:
116                        # umount anything
117                        path="/opt/ltsp/"+imgid
118                       
119                        server = xmlrpclib.ServerProxy("https://localhost:9779")
120                        server.umount_chroot((username,password),'LmdImageManager',path);
121                       
122                        # Let's rebuild image
123                        print "[LmdServer] Refreshing image for "+str(imgid)
124
125                        # Trying to solve the non-zenity problem
126                        #
127                        command="ltsp-chroot -p -m -a "+imgid+" dpkg-reconfigure libgl1-mesa-dri ;  "
128                       
129                       
130                        command=command + "ltsp-chroot -p -m -a "+imgid+" /usr/share/ltsp/update-kernels && "
131                        command=command + "ltsp-update-kernels "+imgid+" && ltsp-update-image "+imgid+"&& service nbd-server restart"; 
132                        result=self.do_command(ip, port, command, srv_ip,target=imgid)
133                        objects['LlxBootManager'].pushToBootList("ltsp_label"+str(imgid));
134                        return {"status": True, "msg": 'Image Updated'}
135
136                               
137                        pass
138                except Exception as e:
139                        print "Except: "+str(e)
140                        return {"False": True, "msg": str(e)}
141
142       
143               
144       
145       
146        def export_image(self, ip, port, imgid, srv_ip='127.0.0.1'):
147                try:
148                        # creates an image from an specified template
149               
150                        # Check if template exists
151                        print "[LmdServer] Export_image from "+imgid
152                       
153                        name_file = str(imgid) + "_" + time.strftime("%Hh%Mm%Ss_%d%m%Y") + '.tgz'
154
155                        command="ltsp-import-export export /tmp/"+ name_file +" "+str(imgid);
156
157                        result=self.do_command(ip, port, command, srv_ip,target=imgid)
158                        return {"status": True, "msg": str(result)}
159                        pass
160                except Exception as e:
161                        print "Except: "+str(e)
162                        return {"status": False, "msg": str(e)}
163
164        def import_image(self, ip, port, imgid, path, srv_ip='127.0.0.1'):
165                try:
166
167                        import xmlrpclib
168                        client=xmlrpclib.ServerProxy("https://127.0.0.1:9779")
169                        n4d_server_ip=client.get_variable("", "VariablesManager", "SRV_IP")
170
171                        '''print ("[************************ ip]"+ip);
172                        print ("[************************ srv_ip]"+srv_ip);
173                        print ("[************************ ip from host:]"+lliurex.net.get_ip_from_host(ip));
174                        print ("[************************ n4d ip server]"+n4d_server_ip);'''
175
176
177               
178                        #if(ip==srv_ip)
179                        print ("COMPARING: "+lliurex.net.get_ip_from_host(ip)+ "and "+ n4d_server_ip);
180                        if(lliurex.net.get_ip_from_host(ip)==n4d_server_ip or ip==srv_ip):
181                                print "[LmdServer] Import_image from ",path, " to ", imgid
182
183                                tar = tarfile.open(path)
184                                l = tar.getnames()
185                                folder = l[0]
186                                imgid = folder
187                                f = tar.extractfile(folder + '/' + folder + '.json')
188                                exec("json_content="+"".join(f.readlines()))
189                                try:
190                                        new_name = folder
191                                        count = 1
192                                        while os.path.exists(os.path.join(self.ltsp_path,new_name)):
193                                                        new_name = folder + "_" + str(count)
194                                                        count += 1
195
196                                        extra_opts = ""
197                                        if folder != new_name:
198                                                extra_opts = new_name
199                                except Exception as e:
200                                        extra_opts = ""
201                                command="ltsp-import-export import "+str(path)+" "+folder+" "+extra_opts+" && service nbd-server restart";
202                               
203                                if extra_opts != "":
204                                        imgid = extra_opts
205                                        json_content['id'] = imgid
206                                        json_content['name'] = imgid
207                                json_file = open('/etc/ltsp/images/' + imgid + '.json','w')
208                                data = unicode(json.dumps(json_content,indent=4,encoding='utf-8',ensure_ascii=False)).encode('utf-8')
209                                json_file.write(data)
210                                json_file.close()
211                                self.set_default_boot(imgid)
212                                result=self.do_command(ip, port, command, srv_ip,target=imgid)
213                                return {"status": True, "msg": str(result)}
214                                pass
215                        else:
216                                print "[LmdServer] ERROR. Trying to import image from out of server";
217                                return {"status": False, "msg": "Not in server"}
218                except Exception as e:
219                        print "Except: "+str(e)
220                        return {"status": False, "msg": str(e)}
221       
222        def deploy_minimal_client(self, ip, port, srv_ip='127.0.0.1'):
223                try:
224                        command="/usr/sbin/mini-light-client.py";
225                        imgid="mini-light-client"
226                       
227                        lng="es_ES.UTF-8"
228                        language="es_ES"
229       
230                        # After that, set image as available
231                        metadata = {'status':'enabled-non-editable',
232                                                'id':'mini-light-client',
233                                                'name':'Client Lleuger Minim',
234                                                'template':'Default by LMD',
235                                                'desc':'Minimal thin client -not fat- for Lliurex LTSP.',
236                                                'img':'llx-client13.png',
237                                                'ltsp_fatclient': 'false',
238                                                'ldm_session': 'gnome-fallback',
239                                                'fat_ram_threshold': 'default',
240                                                'lmd_extra_params':'XKBLAYOUT=es LDM_LANGUAGE="%s" LOCALE_DIR=%s'%(lng,language)}
241                        metadata_string = unicode(json.dumps(metadata,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
242                        objects['LmdImageManager'].setImage('mini-light-client',metadata_string)
243                        self.set_default_boot(imgid)
244                        result=self.do_command(ip, port, command, srv_ip,target=imgid)
245                       
246                        # Step 2. Writing lts.conf for mini-light-client
247                       
248                        print "[LMDServer] Writing lts.conf for mini-light-client"
249                        f=open('/var/lib/tftpboot/ltsp/mini-light-client/lts.conf', 'w')
250                        f.write('[Default]\n')
251                        f.write('LDM_LANGUAGE=es_ES.UTF-8\n')
252                        f.write('LTSP_FATCLIENT=false\n')
253                        f.close()
254                       
255                        # Step 3. Registering imgid for boot PXE menu
256                        objects['LlxBootManager'].pushToBootList("ltsp_label"+str(imgid));
257                       
258                        try:
259                                f=open("/etc/default/locale")
260                                lines=f.readlines()
261                                f.close()
262                                for line in lines:
263                                        if "LANG=" in line:
264                                                lng=line.strip().split("=")[1].strip("'").strip('"')
265                                                if "es_ES" in lng:
266                                                        language="es"
267                                                if "ca_ES" in lng:
268                                                        language="ca_ES@valencia"
269                                               
270                        except:
271                                pass
272
273                       
274                       
275               
276                       
277                       
278                        return {"status": True, "msg": str(result)}
279                        pass
280               
281                except Exception as e:
282                        print "Except: "+str(e)
283                        return {"status": False, "msg": str(e)}
284       
285
286        def do_command(self, ip, port, command, srv_ip='127.0.0.1',target=None):
287                try:
288                        # Add Job
289                        '''job={
290                                'job_id':str(self.last_job_id),
291                                'srv_ip': None,                                         #  Server (me) IP addr
292                                'process': None,
293                                'status':'started',
294                                'msg':'',                               # Error code
295                                'target':'None',
296                                'command':command,
297                                'started_by':None,
298                                'listeners': [{'ip':ip,
299                                                'port':port,
300                                                'socket':None}],
301                                'filepipe': ''
302                                }'''
303                        call_info = _n4d_get_user()
304                        job={
305                                'job_id':str(self.last_job_id),
306                                'srv_ip': srv_ip,
307                                'process': None,
308                                'status':'started',
309                                'msg':None,
310                                'target': target,
311                                'command':command,
312                                'started_by':str(ip),
313                                'listeners': [],
314                                'filepipe': '',
315                                'seek' : 0,
316                                'method':call_info['method'],
317                                'class': call_info['class']
318                               
319                        }
320                       
321                        lock = threading.Lock()
322                        self.locks[job['job_id']]={}
323                        self.locks[job['job_id']]['lock'] = lock
324                       
325                        self.locks[job['job_id']]['lock'].acquire()
326                        # Exec command
327                        # proc = subprocess.Popen([command],  shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, preexec_fn=os.setsid)
328                       
329                        # Prepare file pipe
330                        temp = tempfile.NamedTemporaryFile(prefix='pipe_', dir=self.logfolder, delete=False)
331                       
332                        # New exec command, ignoring stderr stdin for now
333                        proc = subprocess.Popen([command],  shell=True, stdout=temp, preexec_fn=os.setsid)
334                       
335                       
336                        # Add job to tasklist
337                        job['process']=proc                                     # Assotiate process to job
338                        job['status']="running"
339                        job['filepipe'] = temp.name
340
341                       
342                        self.joblist.append(job)                                #Adding job
343                        self.add_listener_to_job(ip, port, job) # Adding the client ip:port to listeners list
344                       
345                        ## PAUSA PARA PROVOCAR UNA CONDICION DE CARRERA
346                        ##
347                        ## time.sleep(2)
348                        ## FIN DE LA PAUSA
349                        ##
350                        #self.joblist.append(job)                               #Adding job  # Moved before add_listener_to_job
351               
352                        # Increase last_job_id
353                        self.last_job_id=self.last_job_id+1
354                        # Multicast process to all listeners
355                        print "[LmdServer] WAITING ...:"+str(datetime.datetime.now())
356                        ret=job['process'].poll()
357                       
358                        while ret is None:
359                                time.sleep(1)
360                                ret=job['process'].poll()
361                       
362                       
363                        #temp.close()
364                       
365                        job['status']="finished"
366                        job['msg']=str(ret)
367                        print "[LmdServer] END WAIT AT"+str(datetime.datetime.now())
368                        print "[LmdServer] FINISHING!!!, return code: "+str(ret)
369                               
370                        print "2"
371                        # Force umount (to avoid morrir destruction in mirrononnet)
372                        proc=subprocess.call(["/usr/share/lmd-scripts/umount-chroot.sh"])
373
374                        # Sending last line to log for all listeners
375                        line="<b>Finished with status:"+job['status']+" and Response: "+job['msg']+" </b>\n"
376                        aux = open(job['filepipe'],'a')
377                        aux.writelines(line)
378                        aux.close()
379
380                        # Append result of job and release mutex. Now all inform_me return finish
381                        self.locks[job['job_id']]['result'] = str(ret)
382                        self.locks[job['job_id']]['lock'].release()
383
384                        return str(ret)
385               
386                except Exception as e:
387                        job['status']="Error"
388                        print '[LmdServer]',e
389                        if (ret is None):
390                                job['msg']="Err code None (running)"
391                        elif (ret<0):
392                                job['msg']="Interrupted by signal: "+str(ret)
393                        else:
394                                job['msg']="Aparently all went well: "+str(ret)
395                       
396       
397                        # Append result of job and release mutex. Now all inform_me return finish
398                        self.locks[job['jobid']]['result'] = str(ret)
399                        self.locks[job['jobid']]['lock'].release()
400
401                        return str(e)
402               
403               
404        def inform_me(self,job_id):
405                '''
406                        Return result of job when finish
407                '''
408
409                self.locks[job_id]['lock'].acquire()
410                self.locks[job_id]['lock'].release()
411               
412                return {'status':True,'msg':self.locks[job_id]['result']}
413
414
415        def add_listener_to_job(self, ip, port, job):
416                '''
417                Description:
418                * Internal Function
419                * Adds a listener identified by an ip and a port to a job object
420               
421                How it Works:
422                * Creates a socket to send information to a listening socket in any client
423               
424                Last update:
425                    * 5/02/2014: Added Functionality
426                    * 2/04/2014: Add reference with job_id
427                '''
428               
429                try:
430                        # Create a socket for new listener
431                        srv=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
432                       
433                        # connection to socket to send log
434                        srv.connect((ip, int(port)))
435                       
436                        # Defines a new listener
437                        listener={'ip':ip,
438                                'port':port,
439                                'socket':srv}
440               
441                        # Add listener to job
442                        job['listeners'].append(listener)
443                        print "[LmdServer] add_listener_to_job: adding "+str(listener)+"to listeners for job "+str(job['job_id'])
444                       
445                        # Sending status of job
446                        listener['socket'].send("<b>Start listening on "+str(listener['port'])+"</b>")                 
447                        listener['socket'].send("<b> Task:"+str(job['command'])+"</b>")
448                        listener['socket'].send("<b> Started by: "+str(job['started_by'])+"</b>")
449                       
450                       
451                               
452                        # Add reference with job_id
453                        tuple_ip_port = (str(ip),str(port))
454                        self.global_listeners[tuple_ip_port] = job['job_id']
455                        #print "Len",len(self.global_listeners)
456                        #print "isAlive",self.multicast_thread.isAlive()
457                        if not self.multicast_thread.isAlive():
458                                #print "lanzando el thread"
459                                self.multicast_thread = threading.Thread(target=self.Multicast, args=())
460                                self.multicast_thread.daemon = True
461                                self.multicast_thread.start()
462                                pass
463                       
464                        return port
465                       
466                except Exception as e:
467                        print("[LmdServer] add_listener_to_job Exception: "+str(e))
468                        return -1
469               
470                pass
471               
472        def add_listener(self, ip, port, job_id):
473                '''
474                Description:
475                * n4d method
476                * Adds a listener identified by an ip and a port to a job object identified by its id
477               
478                How it Works:
479                * Search whic job has certain job_id and adds a listener to it
480               
481                Last update:
482                    * 5/02/2014: Added Functionality
483                '''
484                from operator import itemgetter
485               
486                #print ("[add_listener DEBUG] address: "+str(ip)+":"+str(port)+" job id: "+str(job_id))
487                try:
488                        # Get job identified by job_id
489                        current_job_index=map(itemgetter('job_id'), self.joblist).index(str(job_id))
490                        current_job=self.joblist[current_job_index]
491                        # Add listener to current_job
492                        self.add_listener_to_job(ip, port, current_job)
493                except Exception as e:
494                        print ("[LmdServer] add_listener Exception "+str(e))
495                pass
496
497
498        def send(self, ip, job_id, info):
499                '''
500                receives info to send to stdin
501                '''
502                from operator import itemgetter
503
504                try:
505                        current_job_index=map(itemgetter('job_id'), self.joblist).index(str(job_id))
506                        current_job=self.joblist[current_job_index]
507                        # Get listener identified by (ip:port)
508                       
509                        #current_job['process'].stdin.writelines(str(info))
510                        if(current_job['status']=='running'):
511                                current_job['process'].stdin.write(str(info)+"\n")
512                        #current_job['process'].write(info);
513                except Exception as e:
514                        print ("ERROR writing to process: "+str(e));
515               
516               
517
518        def remove_listener(self, ip, port, job_id):
519                '''
520                Description:
521                * n4d method
522                * Removes listener identified by an ip and a port to a job object identified by its id
523               
524                How it Works:
525                * Search whic job has certain job_id (if specified) and remove its
526                * If job_id is not specified, get it from ip:port
527               
528                Last update:
529                    * 6/02/2014: Added Functionality
530                    * 2/04/2014: Added checking for job_id and close socket
531                '''
532               
533                       
534                from operator import itemgetter
535                try:
536                        # If job_id is None, search job_ib by ip and port
537                        tuple_ip_port = (str(ip),str(port))
538                        if job_id == None:
539                                job_id = self.global_listeners[tuple_ip_port]
540                        # Get job identified by job_id
541                        current_job_index=map(itemgetter('job_id'), self.joblist).index(job_id)
542                        current_job=self.joblist[current_job_index]
543                        # Get listener identified by (ip:port)
544                        current_listener_index=map(itemgetter('ip','port'), current_job['listeners']).index((ip,int (port, base=10)))
545
546                        # Close port and remove listener to current_job
547                        current_job['listeners'][current_listener_index]['socket'].close()
548                        current_job['listeners'].remove(current_job['listeners'][current_listener_index])
549                        #remove listener reference
550                        self.global_listeners.pop(tuple_ip_port)
551                        return True
552                       
553                except Exception as e:
554                        print ("[LmdServer] remove_listener Exception "+str(e))
555                        return False
556                pass
557               
558       
559        def cancel_job(self, ip, port, job_id):
560                '''
561                Description:
562                * n4d method
563                *
564               
565                TO DO ...               
566                Same functionality that remove_listener and in addition, kills process identified by job
567               
568                '''
569               
570                # Remove listener
571               
572                from operator import itemgetter
573                try:
574                        # If job_id is None, search job_ib by ip and port
575                        tuple_ip_port = (str(ip),str(port))
576                        if job_id == None:
577                                job_id = self.global_listeners[tuple_ip_port]
578                        # Get job identified by job_id
579                        current_job_index=map(itemgetter('job_id'), self.joblist).index(job_id)
580                        current_job=self.joblist[current_job_index]
581                        # Get listener identified by (ip:port)
582                        current_listener_index=map(itemgetter('ip','port'), current_job['listeners']).index((ip,int (port, base=10)))
583                       
584                        # Kill process (only addition to remove_listener)
585                        os.killpg(current_job['process'].pid,signal.SIGKILL)
586                        current_job['status']='finished'
587                       
588
589                        # Close port and remove listener to current_job
590                        current_job['listeners'][current_listener_index]['socket'].close()
591                        current_job['listeners'].remove(current_job['listeners'][current_listener_index])
592                        #remove listener reference
593                        self.global_listeners.pop(tuple_ip_port)
594                       
595                       
596                        return True
597                       
598                except Exception as e:
599                        print ("[LmdServer] cancel_job Exception "+str(e))
600                        return False
601                pass
602
603               
604               
605               
606               
607       
608        def getJobList(self):
609                '''
610                Description:
611                * N4D Method
612                * Return JSON with the job list
613                '''
614                #import urllib
615               
616                #ret= urllib.quote(str(self.joblist)[1:-1])
617                #ret= (str(self.joblist)[1:-1]).replace("'", "\"");
618                #ret= (str(self.joblist)).replace("'", "\"");
619                '''ret=ret.replace("<", "\"");
620                ret=ret.replace(">", "\"");'''
621                ret='[';
622                count=0;
623                for job in self.joblist:
624                        if (count>0):
625                                ret=ret+','
626                        ret=ret+'{"job_id":"'+str(job['job_id'])+'"'
627                        ret=ret+', "srv_ip":"'+str(job['srv_ip'])+'"'                   
628                        ret=ret+', "status":"'+str(job['status'])+'"'
629                        ret=ret+', "msg":"'+str(job['msg'])+'"'
630                        ret=ret+', "target":"'+str(job['target'])+'"'
631                        ret=ret+', "command":"'+str(job['command'])+'"'
632                        ret=ret+', "started_by":"'+str(job['started_by'])+'"}'
633                        count=count+1
634                        #print "*********************"
635                        #print "Local listeners"
636                        #print job['listeners']
637                        #print "*********************"
638                       
639                       
640               
641                ret=ret+']'
642                #print (ret)
643                #print "*********************"
644                #print "globals listeners"
645                #print self.global_listeners
646                #print "*********************"
647                return str(ret)
648               
649        def Multicast(self):
650                '''
651                Description:
652                * Internam method
653                * Multicast the output of all processes to its listeners
654               
655                How it works:
656                * Traverses the list of jobs and write its output to all its listeners
657               
658                * Last Update: 13/02/2014
659                '''
660                try:
661                        while len(self.global_listeners) > 0 :
662                                counter = 0
663                                #print "joblist",self.joblist
664                                #print "global_listeners",self.global_listeners
665                                for job in self.joblist:
666                                        if True : #job['status'] != "finished":
667                                                counter += 1
668                                                try:
669                                                        if not self.thread_jobs.has_key(job['job_id']):
670                                                                self.thread_jobs[job['job_id']] = threading.Thread(target=self.send_info_by_socket, args=(job,))
671                                                                self.thread_jobs[job['job_id']].daemon = True
672                                                                self.thread_jobs[job['job_id']].start()
673                                                except Exception as e:
674                                                        print e
675                                if counter == 0:
676                                        break
677                                time.sleep(1)
678                except Exception as e:
679                        print "[LmdServer] EXCEPTION in Multicast: "+str(e)
680                       
681        def send_info_by_socket(self,job):
682                if not os.path.exists(job['filepipe']):
683                        return False
684                pipe = open(job['filepipe'],'r')
685                pipe.seek(job['seek'],0)
686                try:
687                        line = pipe.readline()
688                        while (line and len(self.global_listeners)>0):
689                                for listener in job['listeners']:
690                                        if(listener['socket']!=None):
691                                                try:
692                                                        listener['socket'].send(line)
693                                                except Exception as e:
694                                                        print "[LmdServer] EXCEPTION in Multicast internal loop: "+str(e)
695                                                continue
696                                line=pipe.readline()
697                                job['seek'] = pipe.tell()
698                except:
699                        pass
700               
701                if self.thread_jobs.has_key(job['job_id']):
702                        self.thread_jobs.pop(job['job_id'])
703                               
704        def getLastJobId(self):
705                return self.last_job_id
706
707       
708        def getJobStatus(self, jobid):
709                for i in self.joblist:
710                        if i['job_id']==jobid:
711                                return {"status": True, "msg": str(i['status'])}
712               
713                return {"status": False, "msg": 'bad luck, guy'}
714
715        def check_lmd_status(self):
716                '''
717                Description:
718                * N4D Method
719                * check status of lmd
720                '''
721                import os.path
722                if (os.path.isfile("/tmp/.lmd-editing-chroot")):
723                        return {"status": True, "lmd_status": 'lmd-editing-chroot'}
724                else:
725                        return {"status": True, "lmd_status": 'lmd-chroot-available'}
726               
727        def chek_minimal_client(self):
728                if (os.path.isfile("/etc/ltsp/images/mini-light-client.json") and os.path.isfile("/opt/ltsp/images/mini-light-client.img") ):
729                        return {"status": True}
730                else:
731                        return {"status": False}
732               
733
734        def get_versions_13(self):
735                '''
736                Checks if there is any old image un system (13.06)
737                '''
738               
739                ltsp_dir="/opt/ltsp/"
740                nbd_dir="/etc/nbd-server/conf.d/"
741               
742                ret_list=[];
743                for name in os.listdir(ltsp_dir):
744                        dir=ltsp_dir+name
745                       
746                        needs_update=False
747                        if (name!='images' and os.path.isdir(dir)):
748                                proc = subprocess.Popen(["chroot "+dir +" lliurex-version"], stdout=subprocess.PIPE, shell=True)
749                                (out, err) = proc.communicate()
750                               
751                                if ((not "16.05" in out) and out!="" ): 
752                                        # check nbd...
753                                        for nbd_descriptor in os.listdir(nbd_dir):
754                                                if (self.line_in_file("["+ltsp_dir+name+"]", nbd_dir+nbd_descriptor)):
755                                                        needs_update=True
756                        if (needs_update==True):
757                                ret_list.append(name)
758               
759                return ret_list
760
761        def line_in_file(self, line_to_find, filename):
762                '''
763                Aux function: ask for if certain line is contained in a file
764                '''
765                fd = open(filename, 'r')
766                lines = fd.readlines()
767                fd.close()
768                for line in lines:
769                        if str(line_to_find) in line:
770                                return True
771                               
772                return False
773       
774        def update_images(self, ip, port, imagelist, srv_ip):
775               
776                try:
777               
778                        imagelist_string = " ".join(imagelist)
779                        ##print imagelist," is ", type(imagelist)
780                        ### n4d-client -c LmdServer -m update_images -u joamuran -p lliurex -a  2 3 "['pajarito', 'perro']"
781                       
782                        # Prepare and launch command
783                        command="/usr/share/lmd-scripts/lmd-upgrade-images.sh "+imagelist_string;
784                        result=self.do_command(ip, port, command, srv_ip, None)
785                       
786                        # Add image description
787                        #imagelist=imagelist_string.replace("[","").replace("]","").replace(" ","").replace("'", "").replace(","," ");
788                        #print imagelist_string;
789                        print imagelist;
790                        #print imagelist.split(" ");
791                        for i in imagelist:
792                                metadata = {'id':i,
793                                        'name' : i,
794                                        'desc' : 'Upgraded from Lliurex 13.06',
795                                        'template' : 'none',
796                                        'ltsp_fatclient': 'undefined',
797                                        'ldm_session': 'default',
798                                        'fat_ram_threshold':'default',
799                                        'lmd_extra_params':''}
800                               
801                                metadata_string = unicode(json.dumps(metadata,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
802                               
803                                objects['LmdImageManager'].setImage(i,metadata_string)
804                                self.set_default_boot(imgid)
805                        return {"status": True}
806                except Exception as e:
807                        print "Exception", e
808                        return {"status": False, 'msg':str(e)}
809
810
811        def delete_images(self,imagelist):
812               
813                try:
814               
815                        for img in imagelist:
816                                print img
817                                path_chroot=os.path.join("/opt/ltsp/", img)
818                                path_tftpboot=os.path.join("/var/lib/tftpboot/ltsp/", img)
819                                path_img=os.path.join("/opt/ltsp/images/", img+".img")
820                                path_nbd=os.path.join("/etc/nbd-server/conf.d/", "ltsp_"+img+".conf")
821                                if (os.path.exists(path_chroot)):
822                                        shutil.rmtree(path_chroot)
823                                        #print "deleting: ",path_chroot
824                                if (os.path.exists(path_tftpboot)):
825                                        shutil.rmtree(path_tftpboot)
826                                if (os.path.exists(path_img)):
827                                        #print "deleting: ",path_img
828                                        shutil.rmtree(path_img);
829                                if (os.path.exists(path_nbd)):
830                                        #print "deleting: ",path_nbd
831                                        shutil.rmtree(path_nbd);
832                               
833                        return {"status": True, 'msg':'Finished'}
834
835                except Exception as e:
836                        print "Exception", e
837                        return {"status": False, 'msg':str(e)}
838
839        def LmdServerVersion(self):
840                info=subprocess.check_output(["apt-cache","policy","lmd-server"])
841                lines=str(info).split('\n')
842                version=lines[1][13:]
843                return (version)
844
845        def check_update_images(self):
846                list_dirs = [ os.path.join(self.ltsp_path,x) for x in os.listdir(self.ltsp_path) if os.path.isdir(os.path.join(self.ltsp_path,x)) ]
847                list_need_update = []
848                for chroot in list_dirs:
849                        available_file = os.path.join(chroot,'var','lib','dpkg','available')
850                        if os.path.exists(available_file):
851                                available_fd = open(available_file,'r')
852                                available_content = available_fd.readlines()
853                                try:
854                                        pos = available_content.index('Package: lmd-client\n')
855                                        version = None
856                                        for i in range(pos + 1 ,len(available_content)):
857                                                if available_content[i] == '\n':
858                                                        break
859                                                if available_content[i].startswith('Version'):
860                                                        version = available_content[i][8:].strip()
861                                        if version != None :
862                                                apt_pkg.init()
863                                                if apt_pkg.version_compare(version,'0.15') < 0 :
864                                                        list_need_update.append(os.path.basename(chroot))
865                                except Exception as e:
866                                        pass
867                if len(list_need_update) > 0:
868                        return [True,list_need_update]
869                else:
870                        return [False,[]]
Note: See TracBrowser for help on using the repository browser.