$search
00001 #! /usr/bin/python 00002 # Software License Agreement (BSD License) 00003 # 00004 # Copyright (c) 2011, Willow Garage, Inc. 00005 # All rights reserved. 00006 # 00007 # Redistribution and use in source and binary forms, with or without 00008 # modification, are permitted provided that the following conditions 00009 # are met: 00010 # 00011 # * Redistributions of source code must retain the above copyright 00012 # notice, this list of conditions and the following disclaimer. 00013 # * Redistributions in binary form must reproduce the above 00014 # copyright notice, this list of conditions and the following 00015 # disclaimer in the documentation and/or other materials provided 00016 # with the distribution. 00017 # * Neither the name of Willow Garage, Inc. nor the names of its 00018 # contributors may be used to endorse or promote products derived 00019 # from this software without specific prior written permission. 00020 # 00021 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 # POSSIBILITY OF SUCH DAMAGE. 00033 # 00034 # Revision $Id: topics.py 11753 2010-10-25 06:23:19Z kwc $ 00035 00036 # author: pratkanis 00037 00038 """ 00039 Implements exchange part of app_manager, which handles listing of 00040 avialable and removable applications. 00041 """ 00042 00043 import subprocess 00044 import os 00045 import sys 00046 import yaml 00047 import rospy 00048 from std_msgs.msg import String 00049 from .msg import ExchangeApp, Icon 00050 00051 class Exchange(): 00052 def __init__(self, url, directory, on_error = lambda(x): None): 00053 self._url = url 00054 self._directory = directory 00055 self._on_error = on_error 00056 self._installed_apps = [] 00057 self._available_apps = [] 00058 self._debs = {} 00059 00060 self._exchange_local = os.path.join(self._directory, "exchange.yaml") 00061 d = os.path.join(self._directory, "installed") 00062 if (not os.path.exists(d)): 00063 os.mkdir(d) 00064 self._exchange_file = os.path.join(d, "app_exchange.installed") 00065 print "Directory:", self._directory 00066 print "Local path:", self._exchange_local 00067 print "Local file:", self._exchange_file 00068 print subprocess.Popen(["whoami"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 00069 00070 def get_installed_version(self, deb): 00071 data = subprocess.Popen(["dpkg", "-l", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 00072 val = (data[0] or '').strip() 00073 for i in val.split('\n'): 00074 if (i.find(deb) > 0 and i.find("ii") == 0): 00075 return [s for s in i.strip().split(" ") if s][2] 00076 self._on_error("Failed to get installed version: " + str(data)) 00077 return "FAILED" 00078 00079 def get_available_version(self, deb): 00080 data = subprocess.Popen(["apt-cache", "showpkg", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 00081 val = (data[0] or '').strip() 00082 nearing = False 00083 for i in val.split('\n'): 00084 if (nearing): 00085 return i.strip().split(" ")[0].strip() 00086 if (i.strip() == "Versions:"): 00087 nearing = True 00088 self._on_error("Failed to get available version: " + str(data)) 00089 return "FAILED" 00090 00091 def is_installed(self, deb): 00092 data = subprocess.Popen(["dpkg", "-l", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 00093 val = (data[0] or '').strip() 00094 for i in val.split("\n"): 00095 if (i.find(deb) > 0): 00096 return (i.find("ii") == 0) 00097 self._on_error("Error getting installed packages: " + str(data)) 00098 return False 00099 00100 def get_installed_apps(self): 00101 return self._installed_apps 00102 00103 def get_available_apps(self): 00104 return self._available_apps 00105 00106 def get_app_details(self, name): 00107 local_path = os.path.join(self._directory, name) 00108 if (not os.path.exists(local_path)): 00109 os.makedirs(local_path) 00110 data = subprocess.Popen(["wget", "-O", os.path.join(local_path, "app.yaml"), (self._url.strip('/') + "/" + name + ".yaml")], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 00111 val = (data[0] or '').strip() 00112 print val 00113 try: 00114 data = yaml.load(open(os.path.join(local_path, "app.yaml"))) 00115 icon_url = data["icon_url"] 00116 icon_format = data["icon_format"] 00117 val = (subprocess.Popen(["wget", "-O", os.path.join(local_path, "icon" + icon_format), icon_url], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] or '').strip() 00118 print val 00119 except: 00120 print "No icon" 00121 self.update_local() 00122 for i in self._available_apps: 00123 if (i.name == name): 00124 return i 00125 for i in self._installed_apps: 00126 if (i.name == name): 00127 return i 00128 self._on_error("Problem getting app details: " + str(data)) 00129 return None 00130 00131 def install_app(self, app): 00132 deb = False 00133 for i in self._available_apps: 00134 if (i.name == app): 00135 if (deb): 00136 return False #Somehow a dupe 00137 deb = self._debs[i.name] 00138 for i in self._installed_apps: 00139 if (i.name == app): 00140 if (deb): 00141 return False #Somehow a dupe 00142 deb = self._debs[i.name] 00143 if (deb == False): 00144 self._on_error("No debian found for install") 00145 return False 00146 print "install app" 00147 p = subprocess.Popen(["sudo", "rosget", "install", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 00148 #data = p.communicate() 00149 #data = "test string" 00150 pub = rospy.Publisher('install_status', String) 00151 l1 = [] 00152 for line in iter(p.stdout.readline, ''): 00153 if line.rstrip() != '': 00154 pub.publish(line.rstrip()) 00155 l1.append(line) 00156 else: 00157 break 00158 l2 = [] 00159 for line in iter(p.stderr.readline, ''): 00160 if line.rstrip() != '': 00161 pub.publish(line.rstrip()) 00162 l2.append(line) 00163 else: 00164 break 00165 00166 data = (''.join(l1), ''.join(l2)) 00167 val = (data[0] or '').strip() 00168 print val 00169 self.update_local() 00170 for i in self._installed_apps: 00171 if (i.name == app): 00172 return True 00173 self._on_error("Invalid return for install: " + str(data)) 00174 return False 00175 00176 def uninstall_app(self, app): 00177 deb = False 00178 for i in self._installed_apps: 00179 if (i.name == app): 00180 if (deb): 00181 return False #Somehow a dupe 00182 deb = self._debs[i.name] 00183 if (deb == False): 00184 self._on_error("No debian found for uninstall") 00185 return False 00186 print "uninstall app" 00187 data = subprocess.Popen(["sudo", "rosget", "remove", deb], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 00188 val = (data[0] or '').strip() 00189 self.update_local() 00190 for i in self._available_apps: 00191 if (i.name == app): 00192 return True 00193 self._on_error("Invalid return for uninstall: " + str(data)) 00194 return False 00195 00196 def update(self): 00197 #Call server 00198 val = (subprocess.Popen(["wget", "-O", self._exchange_local, self._url + "/applications.yaml"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] or '').strip() 00199 if (val != "" or not os.path.exists(self._exchange_local)): 00200 print sys.stderr >> val 00201 print sys.stderr >> "Wget failed" 00202 return False 00203 00204 p = subprocess.Popen(["sudo", "rosget", "update"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 00205 data = p.communicate() 00206 val = (data[0] or '').strip() 00207 if (p.returncode != 0): 00208 self._on_error("Invalid return of update: " + str(data)) 00209 self.update_local() 00210 if (p.returncode != 0): 00211 return False 00212 return True 00213 00214 def update_local(self): 00215 installed_apps = [] 00216 file_apps = [] 00217 available_apps = [] 00218 try: 00219 exchange_data = yaml.load(open(self._exchange_local)) 00220 except: 00221 return 00222 if (not exchange_data): 00223 return 00224 for app in exchange_data['apps']: 00225 appc = ExchangeApp() 00226 appc.name = app['app'] 00227 appc.display_name = app['display'] 00228 deb = app['debian'] 00229 self._debs[app['app']] = deb 00230 appc.latest_version = self.get_available_version(deb) 00231 appc.hidden = False 00232 try: 00233 if(app['hidden']): 00234 appc.hidden = True 00235 except: 00236 pass 00237 00238 local_path = os.path.join(self._directory, app['app']) 00239 if (os.path.exists(local_path)): 00240 format = "" 00241 if (os.path.exists(os.path.join(local_path, "app.yaml"))): 00242 print local_path 00243 data = yaml.load(open(os.path.join(local_path, "app.yaml"))) 00244 try: 00245 appc.description = data['description'] 00246 except: 00247 if (appc.hidden): 00248 appc.description = "Descriptionless hidden app" 00249 else: 00250 appc.description = "No description set, likely an error in the yaml file" 00251 try: 00252 format = data['icon_format'] 00253 except: 00254 pass 00255 if (os.path.exists(os.path.join(local_path, "icon" + format)) and format != ""): 00256 icon = Icon() 00257 icon.format = format.strip(".") 00258 if (icon.format == "jpg"): icon.format = "jpeg" 00259 icon.data = open(os.path.join(local_path, "icon" + format), "rb").read() 00260 appc.icon = icon 00261 if (self.is_installed(deb)): 00262 appc.version = self.get_installed_version(deb) 00263 installed_apps.append(appc) 00264 file_apps.append(app) #Should remove debian tag? 00265 else: 00266 available_apps.append(appc) 00267 00268 f = open(self._exchange_file, "w") 00269 yaml.dump({"apps": file_apps}, f) 00270 f.close() 00271 self._installed_apps = installed_apps 00272 self._available_apps = available_apps 00273 00274