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

Last change on this file since 1490 was 1490, checked in by joamuran, 5 years ago

fixed LmdServer?.py

File size: 25.3 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-client16.png',
237                                                'ltsp_fatclient': 'false',
238                                                'ldm_session': 'startxfce4',
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                        if (str(ret)=='0'):
365                                job['status']="finished"
366                        else:
367                                job['status']="broken"
368                        job['msg']=str(ret)
369                        print "[LmdServer] END WAIT AT"+str(datetime.datetime.now())
370                        print "[LmdServer] FINISHING!!!, return code: "+str(ret)
371                               
372                        print "2"
373                        # Force umount (to avoid morrir destruction in mirrononnet)
374                        proc=subprocess.call(["/usr/share/lmd-scripts/umount-chroot.sh"])
375
376                        # Sending last line to log for all listeners
377                        line="<b>Finished with status:"+job['status']+" and Response: "+job['msg']+" </b>\n"
378                        aux = open(job['filepipe'],'a')
379                        aux.writelines(line)
380                        aux.close()
381
382                        # Append result of job and release mutex. Now all inform_me return finish
383                        self.locks[job['job_id']]['result'] = str(ret)
384                        self.locks[job['job_id']]['lock'].release()
385
386                        return str(ret)
387               
388                except Exception as e:
389                        job['status']="Error"
390                        print '[LmdServer]',e
391                        if (ret is None):
392                                job['msg']="Err code None (running)"
393                        elif (ret<0):
394                                job['msg']="Interrupted by signal: "+str(ret)
395                        else:
396                                job['msg']="Aparently all went well: "+str(ret)
397                       
398       
399                        # Append result of job and release mutex. Now all inform_me return finish
400                        self.locks[job['jobid']]['result'] = str(ret)
401                        self.locks[job['jobid']]['lock'].release()
402
403                        return str(e)
404               
405               
406        def inform_me(self,job_id):
407                '''
408                        Return result of job when finish
409                '''
410
411                self.locks[job_id]['lock'].acquire()
412                self.locks[job_id]['lock'].release()
413               
414                return {'status':True,'msg':self.locks[job_id]['result']}
415
416
417        def add_listener_to_job(self, ip, port, job):
418                '''
419                Description:
420                * Internal Function
421                * Adds a listener identified by an ip and a port to a job object
422               
423                How it Works:
424                * Creates a socket to send information to a listening socket in any client
425               
426                Last update:
427                    * 5/02/2014: Added Functionality
428                    * 2/04/2014: Add reference with job_id
429                '''
430               
431                try:
432                        # Create a socket for new listener
433                        srv=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
434                       
435                        # connection to socket to send log
436                        srv.connect((ip, int(port)))
437                       
438                        # Defines a new listener
439                        listener={'ip':ip,
440                                'port':port,
441                                'socket':srv}
442               
443                        # Add listener to job
444                        job['listeners'].append(listener)
445                        print "[LmdServer] add_listener_to_job: adding "+str(listener)+"to listeners for job "+str(job['job_id'])
446                       
447                        # Sending status of job
448                        listener['socket'].send("<b>Start listening on "+str(listener['port'])+"</b>")                 
449                        listener['socket'].send("<b> Task:"+str(job['command'])+"</b>")
450                        listener['socket'].send("<b> Started by: "+str(job['started_by'])+"</b>")
451                       
452                       
453                               
454                        # Add reference with job_id
455                        tuple_ip_port = (str(ip),str(port))
456                        self.global_listeners[tuple_ip_port] = job['job_id']
457                        #print "Len",len(self.global_listeners)
458                        #print "isAlive",self.multicast_thread.isAlive()
459                        if not self.multicast_thread.isAlive():
460                                #print "lanzando el thread"
461                                self.multicast_thread = threading.Thread(target=self.Multicast, args=())
462                                self.multicast_thread.daemon = True
463                                self.multicast_thread.start()
464                                pass
465                       
466                        return port
467                       
468                except Exception as e:
469                        print("[LmdServer] add_listener_to_job Exception: "+str(e))
470                        return -1
471               
472                pass
473               
474        def add_listener(self, ip, port, job_id):
475                '''
476                Description:
477                * n4d method
478                * Adds a listener identified by an ip and a port to a job object identified by its id
479               
480                How it Works:
481                * Search whic job has certain job_id and adds a listener to it
482               
483                Last update:
484                    * 5/02/2014: Added Functionality
485                '''
486                from operator import itemgetter
487               
488                #print ("[add_listener DEBUG] address: "+str(ip)+":"+str(port)+" job id: "+str(job_id))
489                try:
490                        # Get job identified by job_id
491                        current_job_index=map(itemgetter('job_id'), self.joblist).index(str(job_id))
492                        current_job=self.joblist[current_job_index]
493                        # Add listener to current_job
494                        self.add_listener_to_job(ip, port, current_job)
495                except Exception as e:
496                        print ("[LmdServer] add_listener Exception "+str(e))
497                pass
498
499
500        def send(self, ip, job_id, info):
501                '''
502                receives info to send to stdin
503                '''
504                from operator import itemgetter
505
506                try:
507                        current_job_index=map(itemgetter('job_id'), self.joblist).index(str(job_id))
508                        current_job=self.joblist[current_job_index]
509                        # Get listener identified by (ip:port)
510                       
511                        #current_job['process'].stdin.writelines(str(info))
512                        if(current_job['status']=='running'):
513                                current_job['process'].stdin.write(str(info)+"\n")
514                        #current_job['process'].write(info);
515                except Exception as e:
516                        print ("ERROR writing to process: "+str(e));
517               
518               
519
520        def remove_listener(self, ip, port, job_id):
521                '''
522                Description:
523                * n4d method
524                * Removes listener identified by an ip and a port to a job object identified by its id
525               
526                How it Works:
527                * Search whic job has certain job_id (if specified) and remove its
528                * If job_id is not specified, get it from ip:port
529               
530                Last update:
531                    * 6/02/2014: Added Functionality
532                    * 2/04/2014: Added checking for job_id and close socket
533                '''
534               
535                       
536                from operator import itemgetter
537                try:
538                        # If job_id is None, search job_ib by ip and port
539                        tuple_ip_port = (str(ip),str(port))
540                        if job_id == None:
541                                job_id = self.global_listeners[tuple_ip_port]
542                        # Get job identified by job_id
543                        current_job_index=map(itemgetter('job_id'), self.joblist).index(job_id)
544                        current_job=self.joblist[current_job_index]
545                        # Get listener identified by (ip:port)
546                        current_listener_index=map(itemgetter('ip','port'), current_job['listeners']).index((ip,int (port, base=10)))
547
548                        # Close port and remove listener to current_job
549                        current_job['listeners'][current_listener_index]['socket'].close()
550                        current_job['listeners'].remove(current_job['listeners'][current_listener_index])
551                        #remove listener reference
552                        self.global_listeners.pop(tuple_ip_port)
553                        return True
554                       
555                except Exception as e:
556                        print ("[LmdServer] remove_listener Exception "+str(e))
557                        return False
558                pass
559               
560       
561        def cancel_job(self, ip, port, job_id):
562                '''
563                Description:
564                * n4d method
565                *
566               
567                TO DO ...               
568                Same functionality that remove_listener and in addition, kills process identified by job
569               
570                '''
571               
572                # Remove listener
573                from operator import itemgetter
574                try:
575                        # If job_id is None, search job_ib by ip and port
576                        tuple_ip_port = (str(ip),str(port))
577                        print (tuple_ip_port)
578                        if job_id == None:
579                                print self.global_listeners
580                                job_id = self.global_listeners[tuple_ip_port]
581                        # Get job identified by job_id
582                        current_job_index=map(itemgetter('job_id'), self.joblist).index(job_id)
583                        current_job=self.joblist[current_job_index]
584                        # Get listener identified by (ip:port)
585                        current_listener_index=map(itemgetter('ip','port'), current_job['listeners']).index((ip,int (port, base=10)))
586                        # Kill process (only addition to remove_listener)
587                        os.killpg(current_job['process'].pid,signal.SIGKILL)
588                        current_job['status']='broken'
589
590                        # Close port and remove listener to current_job
591                        current_job['listeners'][current_listener_index]['socket'].close()
592                        current_job['listeners'].remove(current_job['listeners'][current_listener_index])
593                        #remove listener reference
594                        self.global_listeners.pop(tuple_ip_port)
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
744                #OBSOLETE REMOVED METHOD
745                #RETURN EMPTY LIST TO LMD-GUI TO AVOID LLIUREX 13 WARNING
746                #for name in os.listdir(ltsp_dir):
747                #       dir=ltsp_dir+name
748                #       
749                #       needs_update=False
750                #       if (name!='images' and os.path.isdir(dir)):
751                #               proc = subprocess.Popen(["chroot "+dir +" lliurex-version"], stdout=subprocess.PIPE, shell=True)
752                #               (out, err) = proc.communicate()
753                #               
754                #               if ((not "16.05" in out) and out!="" ):
755                #                       # check nbd...
756                #                       for nbd_descriptor in os.listdir(nbd_dir):
757                #                               if (self.line_in_file("["+ltsp_dir+name+"]", nbd_dir+nbd_descriptor)):
758                #                                       needs_update=True
759                #       if (needs_update==True):
760                #               ret_list.append(name)
761                #
762                return ret_list
763
764        def line_in_file(self, line_to_find, filename):
765                '''
766                Aux function: ask for if certain line is contained in a file
767                '''
768                fd = open(filename, 'r')
769                lines = fd.readlines()
770                fd.close()
771                for line in lines:
772                        if str(line_to_find) in line:
773                                return True
774                               
775                return False
776       
777        def update_images(self, ip, port, imagelist, srv_ip):
778               
779                try:
780               
781                        imagelist_string = " ".join(imagelist)
782                        ##print imagelist," is ", type(imagelist)
783                        ### n4d-client -c LmdServer -m update_images -u joamuran -p lliurex -a  2 3 "['pajarito', 'perro']"
784                       
785                        # Prepare and launch command
786                        command="/usr/share/lmd-scripts/lmd-upgrade-images.sh "+imagelist_string;
787                        result=self.do_command(ip, port, command, srv_ip, None)
788                       
789                        # Add image description
790                        #imagelist=imagelist_string.replace("[","").replace("]","").replace(" ","").replace("'", "").replace(","," ");
791                        #print imagelist_string;
792                        print imagelist;
793                        #print imagelist.split(" ");
794                        for i in imagelist:
795                                metadata = {'id':i,
796                                        'name' : i,
797                                        'desc' : 'Upgraded from Lliurex 13.06',
798                                        'template' : 'none',
799                                        'ltsp_fatclient': 'undefined',
800                                        'ldm_session': 'default',
801                                        'fat_ram_threshold':'default',
802                                        'lmd_extra_params':''}
803                               
804                                metadata_string = unicode(json.dumps(metadata,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
805                               
806                                objects['LmdImageManager'].setImage(i,metadata_string)
807                                self.set_default_boot(imgid)
808                        return {"status": True}
809                except Exception as e:
810                        print "Exception", e
811                        return {"status": False, 'msg':str(e)}
812
813
814        def delete_images(self,imagelist):
815               
816                try:
817               
818                        for img in imagelist:
819                                print img
820                                path_chroot=os.path.join("/opt/ltsp/", img)
821                                path_tftpboot=os.path.join("/var/lib/tftpboot/ltsp/", img)
822                                path_img=os.path.join("/opt/ltsp/images/", img+".img")
823                                path_nbd=os.path.join("/etc/nbd-server/conf.d/", "ltsp_"+img+".conf")
824                                if (os.path.exists(path_chroot)):
825                                        shutil.rmtree(path_chroot)
826                                        #print "deleting: ",path_chroot
827                                if (os.path.exists(path_tftpboot)):
828                                        shutil.rmtree(path_tftpboot)
829                                if (os.path.exists(path_img)):
830                                        #print "deleting: ",path_img
831                                        shutil.rmtree(path_img);
832                                if (os.path.exists(path_nbd)):
833                                        #print "deleting: ",path_nbd
834                                        shutil.rmtree(path_nbd);
835                               
836                        return {"status": True, 'msg':'Finished'}
837
838                except Exception as e:
839                        print "Exception", e
840                        return {"status": False, 'msg':str(e)}
841
842        def LmdServerVersion(self):
843                info=subprocess.check_output(["apt-cache","policy","lmd-server"])
844                lines=str(info).split('\n')
845                version=lines[1][13:]
846                return (version)
847
848        def check_update_images(self):
849                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)) ]
850                list_need_update = []
851                for chroot in list_dirs:
852                        available_file = os.path.join(chroot,'var','lib','dpkg','available')
853                        if os.path.exists(available_file):
854                                available_fd = open(available_file,'r')
855                                available_content = available_fd.readlines()
856                                try:
857                                        pos = available_content.index('Package: lmd-client\n')
858                                        version = None
859                                        for i in range(pos + 1 ,len(available_content)):
860                                                if available_content[i] == '\n':
861                                                        break
862                                                if available_content[i].startswith('Version'):
863                                                        version = available_content[i][8:].strip()
864                                        if version != None :
865                                                apt_pkg.init()
866                                                if apt_pkg.version_compare(version,'0.15') < 0 :
867                                                        list_need_update.append(os.path.basename(chroot))
868                                except Exception as e:
869                                        pass
870                if len(list_need_update) > 0:
871                        return [True,list_need_update]
872                else:
873                        return [False,[]]
Note: See TracBrowser for help on using the repository browser.