2012-11-17 16:29:06 +01:00
# -*- coding: utf-8 -*-
2013-07-06 09:42:26 +02:00
""" License
Copyright ( C ) 2013 YunoHost
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program ; if not , see http : / / www . gnu . org / licenses
"""
""" yunohost_app.py
2013-07-06 10:17:16 +02:00
Manage apps
2013-07-06 09:42:26 +02:00
"""
2012-11-17 16:29:06 +01:00
import os
import sys
import json
2013-02-25 19:54:23 +01:00
import shutil
2013-02-26 14:52:13 +01:00
import stat
2013-02-26 20:36:37 +01:00
import yaml
2013-02-27 17:55:29 +01:00
import time
2013-10-25 12:26:03 +02:00
import re
2013-10-27 14:23:52 +01:00
import socket
2013-11-22 15:29:07 +01:00
import urlparse
2014-02-05 02:01:03 +01:00
2014-04-23 12:52:41 +02:00
from moulinette . helpers import win_msg , random_password , is_true , validate
from moulinette . core import MoulinetteError
2012-11-17 16:29:06 +01:00
2013-02-26 18:31:24 +01:00
repo_path = ' /var/cache/yunohost/repo '
apps_path = ' /usr/share/yunohost/apps '
2013-02-26 23:13:49 +01:00
apps_setting_path = ' /etc/yunohost/apps/ '
2013-11-22 18:00:20 +01:00
install_tmp = ' /var/cache/yunohost '
2013-02-26 18:31:24 +01:00
app_tmp_folder = install_tmp + ' /from_file '
def app_listlists ( ) :
"""
List fetched lists
"""
list_list = [ ]
try :
for filename in os . listdir ( repo_path ) :
if ' .json ' in filename :
list_list . append ( filename [ : len ( filename ) - 5 ] )
except OSError :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 1 , _ ( " No list found " ) )
2013-02-26 18:31:24 +01:00
return { ' Lists ' : list_list }
2013-02-25 22:23:32 +01:00
2013-02-24 17:36:58 +01:00
def app_fetchlist ( url = None , name = None ) :
2012-11-17 16:29:06 +01:00
"""
2013-07-06 10:17:16 +02:00
Fetch application list from app server
2012-11-17 16:29:06 +01:00
2013-07-06 10:17:16 +02:00
Keyword argument :
2014-03-20 00:13:31 +01:00
name - - Name of the list ( default yunohost )
url - - URL of remote JSON list ( default http : / / app . yunohost . org / list . json )
2012-11-17 16:29:06 +01:00
"""
# Create app path if not exists
2013-02-24 17:36:58 +01:00
try : os . listdir ( repo_path )
except OSError : os . makedirs ( repo_path )
2012-11-17 16:29:06 +01:00
2013-10-31 11:11:44 +01:00
if url is None :
2013-05-29 16:11:01 +02:00
url = ' http://app.yunohost.org/list.json '
name = ' yunohost '
2013-02-24 17:36:58 +01:00
else :
2014-04-23 12:52:41 +02:00
if name is None : raise MoulinetteError ( 22 , _ ( " You must indicate a name for your custom list " ) )
2012-11-17 16:29:06 +01:00
2014-04-23 12:52:41 +02:00
list_file = ' %s / %s .json ' % ( repo_path , name )
if os . system ( ' wget " %s " -O " %s .tmp " ' % ( url , list_file ) ) != 0 :
os . remove ( ' %s .tmp ' % list_file )
raise MoulinetteError ( 1 , _ ( " List server connection failed " ) )
2013-02-12 13:52:11 +01:00
2013-12-19 14:54:15 +01:00
# Rename fetched temp list
2014-04-23 12:52:41 +02:00
os . rename ( ' %s .tmp ' % list_file , list_file )
2013-12-19 14:54:15 +01:00
2014-04-23 12:52:41 +02:00
os . system ( " touch /etc/cron.d/yunohost-applist- %s " % name )
os . system ( " echo ' 00 00 * * * root yunohost app fetchlist -u %s -n %s --no-ldap > /dev/null 2>&1 ' >/etc/cron.d/yunohost-applist- %s " % ( url , name , name ) )
2013-10-31 11:11:44 +01:00
2014-04-23 12:52:41 +02:00
msignals . display ( _ ( " List successfully fetched " ) , ' success ' )
2012-11-17 16:29:06 +01:00
2013-02-25 22:54:28 +01:00
def app_removelist ( name ) :
"""
2013-07-06 10:17:16 +02:00
Remove list from the repositories
2013-02-25 22:54:28 +01:00
2013-07-06 10:17:16 +02:00
Keyword argument :
2013-02-25 22:54:28 +01:00
name - - Name of the list to remove
"""
try :
2014-04-23 12:52:41 +02:00
os . remove ( ' %s / %s .json ' % ( repo_path , name ) )
os . remove ( " /etc/cron.d/yunohost-applist- %s " % name )
2013-02-25 22:54:28 +01:00
except OSError :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " Unknown list " ) )
2013-02-25 22:54:28 +01:00
2014-04-23 12:52:41 +02:00
msignals . display ( _ ( " List successfully removed " ) , ' success ' )
2013-02-25 22:54:28 +01:00
2013-02-25 14:04:41 +01:00
def app_list ( offset = None , limit = None , filter = None , raw = False ) :
2013-02-10 22:34:14 +01:00
"""
2013-07-06 10:17:16 +02:00
List apps
2013-02-10 22:34:14 +01:00
2013-07-06 10:17:16 +02:00
Keyword argument :
filter - - Name filter of app_id or app_name
2013-10-31 11:21:59 +01:00
offset - - Starting number for app fetching
limit - - Maximum number of app fetched
2013-07-06 12:59:06 +02:00
raw - - Return the full app_dict
2013-02-10 22:34:14 +01:00
"""
if offset : offset = int ( offset )
else : offset = 0
if limit : limit = int ( limit )
else : limit = 1000
2013-02-10 21:04:15 +01:00
2013-02-24 17:36:58 +01:00
applists = os . listdir ( repo_path )
app_dict = { }
2013-09-24 22:04:13 +02:00
if raw :
list_dict = { }
else :
list_dict = [ ]
2013-02-10 21:04:15 +01:00
2013-10-27 19:37:19 +01:00
if not applists :
app_fetchlist ( )
applists = os . listdir ( repo_path )
2013-02-24 17:36:58 +01:00
for applist in applists :
if ' .json ' in applist :
2013-02-25 22:23:32 +01:00
with open ( repo_path + ' / ' + applist ) as json_list :
2013-02-24 17:36:58 +01:00
app_dict . update ( json . loads ( str ( json_list . read ( ) ) ) )
2013-10-27 19:37:19 +01:00
for app in os . listdir ( apps_setting_path ) :
if app not in app_dict :
# Look for forks
if ' __ ' in app :
original_app = app [ : app . index ( ' __ ' ) ]
if original_app in app_dict :
app_dict [ app ] = app_dict [ original_app ]
continue
2013-12-03 20:54:56 +01:00
with open ( apps_setting_path + app + ' /manifest.json ' ) as json_manifest :
app_dict [ app ] = { " manifest " : json . loads ( str ( json_manifest . read ( ) ) ) }
2013-12-03 21:02:34 +01:00
app_dict [ app ] [ ' manifest ' ] [ ' orphan ' ] = True
2013-10-27 19:37:19 +01:00
2013-02-10 22:34:14 +01:00
if len ( app_dict ) > ( 0 + offset ) and limit > 0 :
2013-02-24 17:36:58 +01:00
sorted_app_dict = { }
2013-09-08 14:48:07 +02:00
for sorted_keys in sorted ( app_dict . keys ( ) ) [ offset : ] :
2013-09-08 14:13:30 +02:00
sorted_app_dict [ sorted_keys ] = app_dict [ sorted_keys ]
i = 0
2013-02-10 22:34:14 +01:00
for app_id , app_info in sorted_app_dict . items ( ) :
2013-09-08 14:13:30 +02:00
if i < limit :
2013-09-08 14:48:07 +02:00
if ( filter and ( ( filter in app_id ) or ( filter in app_info [ ' manifest ' ] [ ' name ' ] ) ) ) or not filter :
2013-10-08 23:51:47 +02:00
installed = _is_installed ( app_id )
2013-02-27 19:20:45 +01:00
2013-09-08 14:48:07 +02:00
if raw :
2013-09-24 22:04:13 +02:00
app_info [ ' installed ' ] = installed
2013-09-08 14:48:07 +02:00
list_dict [ app_id ] = app_info
else :
2013-09-24 22:04:13 +02:00
list_dict . append ( {
' ID ' : app_id ,
' Name ' : app_info [ ' manifest ' ] [ ' name ' ] ,
' Description ' : app_info [ ' manifest ' ] [ ' description ' ] ,
2013-10-08 23:51:47 +02:00
' Installed ' : installed
2013-09-24 22:04:13 +02:00
} )
2013-09-08 14:48:07 +02:00
i + = 1
2013-09-08 14:13:30 +02:00
else :
2013-09-08 14:48:07 +02:00
break
2013-09-24 22:04:13 +02:00
if not raw :
list_dict = { ' Apps ' : list_dict }
2013-02-10 21:04:15 +01:00
return list_dict
2013-02-11 11:14:39 +01:00
2013-03-02 11:19:20 +01:00
2013-10-08 23:51:47 +02:00
def app_info ( app , raw = False ) :
2013-06-06 13:15:38 +02:00
"""
2013-10-31 11:21:59 +01:00
Get app info
2013-06-06 13:15:38 +02:00
2013-07-06 10:17:16 +02:00
Keyword argument :
2013-10-31 11:21:59 +01:00
app - - Specific app ID
2013-06-06 13:15:38 +02:00
raw - - Return the full app_dict
"""
try :
2013-10-27 19:37:19 +01:00
app_info = app_list ( filter = app , raw = True ) [ app ]
2013-10-28 11:51:44 +01:00
except :
2013-06-06 13:15:38 +02:00
app_info = { }
2013-10-28 11:51:44 +01:00
if _is_installed ( app ) :
with open ( apps_setting_path + app + ' /settings.yml ' ) as f :
app_info [ ' settings ' ] = yaml . load ( f )
2013-10-27 19:37:19 +01:00
2013-10-28 11:51:44 +01:00
if raw :
return app_info
else :
return {
' Name ' : app_info [ ' manifest ' ] [ ' name ' ] ,
' Description ' : app_info [ ' manifest ' ] [ ' description ' ] [ ' en ' ] ,
#TODO: Add more infos
}
2013-06-06 13:15:38 +02:00
2013-10-27 19:37:19 +01:00
def app_map ( app = None , raw = False , user = None ) :
2013-03-02 11:19:20 +01:00
"""
2013-07-06 10:17:16 +02:00
List apps by domain
2013-03-02 11:19:20 +01:00
2013-07-06 10:17:16 +02:00
Keyword argument :
2013-10-31 11:21:59 +01:00
user - - Allowed app map for a user
2013-06-07 13:44:23 +02:00
raw - - Return complete dict
2013-10-31 11:21:59 +01:00
app - - Specific app to map
2013-06-07 13:44:23 +02:00
2013-03-02 11:19:20 +01:00
"""
result = { }
2013-10-08 23:51:47 +02:00
for app_id in os . listdir ( apps_setting_path ) :
if app and ( app != app_id ) :
2013-06-07 13:44:23 +02:00
continue
2013-03-02 11:20:55 +01:00
2013-10-27 19:37:19 +01:00
if user is not None :
app_dict = app_info ( app = app_id , raw = True )
if ( ' mode ' not in app_dict [ ' settings ' ] ) or ( ' mode ' in app_dict [ ' settings ' ] and app_dict [ ' settings ' ] [ ' mode ' ] == ' private ' ) :
if ' allowed_users ' in app_dict [ ' settings ' ] and user not in app_dict [ ' settings ' ] [ ' allowed_users ' ] . split ( ' , ' ) :
continue
2013-10-08 23:51:47 +02:00
with open ( apps_setting_path + app_id + ' /settings.yml ' ) as f :
2013-06-07 13:44:23 +02:00
app_settings = yaml . load ( f )
2013-10-08 23:51:47 +02:00
if ' domain ' not in app_settings :
continue
2013-06-07 13:44:23 +02:00
if raw :
if app_settings [ ' domain ' ] not in result :
result [ app_settings [ ' domain ' ] ] = { }
result [ app_settings [ ' domain ' ] ] [ app_settings [ ' path ' ] ] = {
' label ' : app_settings [ ' label ' ] ,
2013-10-26 17:29:15 +02:00
' id ' : app_settings [ ' id ' ]
2013-06-07 13:44:23 +02:00
}
else :
2013-10-26 17:29:15 +02:00
result [ app_settings [ ' domain ' ] + app_settings [ ' path ' ] ] = app_settings [ ' label ' ]
2013-03-02 11:19:20 +01:00
return result
2013-06-07 13:44:23 +02:00
2013-10-08 23:51:47 +02:00
def app_upgrade ( app , url = None , file = None ) :
2013-06-06 13:15:38 +02:00
"""
2013-07-06 10:17:16 +02:00
Upgrade app
2013-06-06 13:15:38 +02:00
2013-07-06 10:17:16 +02:00
Keyword argument :
2013-06-06 13:15:38 +02:00
file - - Folder or tarball for upgrade
2013-10-31 11:21:59 +01:00
app - - App ( s ) to upgrade ( default all )
url - - Git url to fetch for upgrade
2013-06-06 13:15:38 +02:00
"""
2014-04-23 12:52:41 +02:00
from yunohost . hook import hook_add , hook_exec
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
try :
app_list ( )
except MoulinetteError :
raise MoulinetteError ( 1 , _ ( " No app to upgrade " ) )
2013-10-09 00:04:52 +02:00
2014-04-23 12:52:41 +02:00
upgraded_apps = [ ]
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
# If no app is specified, upgrade all apps
if not app :
app = os . listdir ( apps_setting_path )
elif not isinstance ( app , list ) :
app = [ app ]
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
for app_id in app :
installed = _is_installed ( app_id )
if not installed :
raise MoulinetteError ( 1 , _ ( " %s is not installed " ) % app_id )
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
if app_id in upgraded_apps :
continue
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
if ' __ ' in app_id :
original_app_id = app_id [ : app_id . index ( ' __ ' ) ]
else :
original_app_id = app_id
current_app_dict = app_info ( app_id , raw = True )
new_app_dict = app_info ( original_app_id , raw = True )
if file :
manifest = _extract_app_from_file ( file )
elif url :
manifest = _fetch_app_from_git ( url )
elif ' lastUpdate ' not in new_app_dict or ' git ' not in new_app_dict :
raise MoulinetteError ( 22 , _ ( " %s is a custom app, please provide an URL manually in order to upgrade it " ) % app_id )
elif ( new_app_dict [ ' lastUpdate ' ] > current_app_dict [ ' lastUpdate ' ] ) \
or ( ' update_time ' not in current_app_dict [ ' settings ' ] \
and ( new_app_dict [ ' lastUpdate ' ] > current_app_dict [ ' settings ' ] [ ' install_time ' ] ) ) \
or ( ' update_time ' in current_app_dict [ ' settings ' ] \
and ( new_app_dict [ ' lastUpdate ' ] > current_app_dict [ ' settings ' ] [ ' update_time ' ] ) ) :
manifest = _fetch_app_from_git ( app_id )
else :
continue
2013-12-19 15:43:21 +01:00
2014-04-23 12:52:41 +02:00
# Check min version
if ' min_version ' in manifest and __version__ < manifest [ ' min_version ' ] :
raise MoulinetteError ( 1 , _ ( " %s requires a more recent version of the moulinette " ) % app_id )
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
app_setting_path = apps_setting_path + ' / ' + app_id
if original_app_id != app_id :
# Replace original_app_id with the forked one in scripts
for file in os . listdir ( app_tmp_folder + ' /scripts ' ) :
#TODO: do it with sed ?
if file [ : 1 ] != ' . ' :
with open ( app_tmp_folder + ' /scripts/ ' + file , " r " ) as sources :
lines = sources . readlines ( )
with open ( app_tmp_folder + ' /scripts/ ' + file , " w " ) as sources :
for line in lines :
sources . write ( re . sub ( r ' ' + original_app_id + ' ' , app_id , line ) )
if ' hooks ' in os . listdir ( app_tmp_folder ) :
for file in os . listdir ( app_tmp_folder + ' /hooks ' ) :
2013-10-28 11:51:44 +01:00
#TODO: do it with sed ?
if file [ : 1 ] != ' . ' :
2014-04-23 12:52:41 +02:00
with open ( app_tmp_folder + ' /hooks/ ' + file , " r " ) as sources :
2013-10-28 11:51:44 +01:00
lines = sources . readlines ( )
2014-04-23 12:52:41 +02:00
with open ( app_tmp_folder + ' /hooks/ ' + file , " w " ) as sources :
2013-10-28 11:51:44 +01:00
for line in lines :
sources . write ( re . sub ( r ' ' + original_app_id + ' ' , app_id , line ) )
2014-04-23 12:52:41 +02:00
# Add hooks
if ' hooks ' in os . listdir ( app_tmp_folder ) :
for file in os . listdir ( app_tmp_folder + ' /hooks ' ) :
hook_add ( app_id , app_tmp_folder + ' /hooks/ ' + file )
2013-12-10 12:53:59 +01:00
2014-04-23 12:52:41 +02:00
# Execute App upgrade script
os . system ( ' chown -hR admin: %s ' % install_tmp )
if hook_exec ( app_tmp_folder + ' /scripts/upgrade ' ) != 0 :
#TODO: display fail messages from script
pass
else :
app_setting ( app_id , ' update_time ' , int ( time . time ( ) ) )
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
# Replace scripts and manifest
os . system ( ' rm -rf " %s /scripts " " %s /manifest.json " ' % ( app_setting_path , app_setting_path ) )
os . system ( ' mv " %s /manifest.json " " %s /scripts " %s ' % ( app_tmp_folder , app_tmp_folder , app_setting_path ) )
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
# So much win
upgraded_apps . append ( app_id )
msignals . display ( _ ( " %s upgraded successfully " ) % app_id , ' success ' )
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
if not upgraded_apps :
raise MoulinetteError ( 1 , _ ( " No app to upgrade " ) )
2013-06-06 13:15:38 +02:00
2014-04-23 12:52:41 +02:00
msignals . display ( _ ( " Upgrade complete " ) , ' success ' )
2013-06-06 13:15:38 +02:00
2013-03-02 11:19:20 +01:00
2014-04-23 12:52:41 +02:00
def app_install ( auth , app , label = None , args = None ) :
2013-02-11 11:14:39 +01:00
"""
2013-07-06 10:17:16 +02:00
Install apps
2013-02-11 11:14:39 +01:00
2013-07-06 10:17:16 +02:00
Keyword argument :
label
2013-10-31 11:21:59 +01:00
app - - App to install
2013-11-22 15:29:07 +01:00
args - - Serialize arguments of installation
2013-02-11 11:14:39 +01:00
"""
2014-04-23 12:52:41 +02:00
from yunohost . hook import hook_add , hook_remove , hook_exec
2013-02-11 11:14:39 +01:00
2014-04-23 12:52:41 +02:00
# Fetch or extract sources
try : os . listdir ( install_tmp )
except OSError : os . makedirs ( install_tmp )
2013-03-01 20:03:12 +01:00
2014-04-23 12:52:41 +02:00
if app in app_list ( raw = True ) or ( ' @ ' in app ) or ( ' http:// ' in app ) or ( ' https:// ' in app ) :
manifest = _fetch_app_from_git ( app )
else :
manifest = _extract_app_from_file ( app )
2013-02-11 13:45:58 +01:00
2014-04-23 12:52:41 +02:00
# Check ID
if ' id ' not in manifest or ' __ ' in manifest [ ' id ' ] :
raise MoulinetteError ( 22 , _ ( " App id is invalid " ) )
2013-02-11 13:45:58 +01:00
2014-04-23 12:52:41 +02:00
app_id = manifest [ ' id ' ]
2013-02-11 11:14:39 +01:00
2014-04-23 12:52:41 +02:00
# Check min version
if ' min_version ' in manifest and __version__ < manifest [ ' min_version ' ] :
raise MoulinetteError ( 1 , _ ( " %s requires a more recent version of the moulinette " ) % app_id )
2013-03-01 20:03:12 +01:00
2014-04-23 12:52:41 +02:00
# Check if app can be forked
instance_number = _installed_instance_number ( app_id , last = True ) + 1
if instance_number > 1 :
if ' multi_instance ' not in manifest or not is_true ( manifest [ ' multi_instance ' ] ) :
raise MoulinetteError ( 1 , _ ( " App is already installed " ) )
2013-12-19 17:31:29 +01:00
2014-04-23 12:52:41 +02:00
app_id_forked = app_id + ' __ ' + str ( instance_number )
2013-02-11 11:14:39 +01:00
2014-04-23 12:52:41 +02:00
# Replace app_id with the new one in scripts
for file in os . listdir ( app_tmp_folder + ' /scripts ' ) :
#TODO: do it with sed ?
if file [ : 1 ] != ' . ' :
with open ( app_tmp_folder + ' /scripts/ ' + file , " r " ) as sources :
lines = sources . readlines ( )
with open ( app_tmp_folder + ' /scripts/ ' + file , " w " ) as sources :
for line in lines :
sources . write ( re . sub ( r ' ' + app_id + ' ' , app_id_forked , line ) )
2013-02-11 11:14:39 +01:00
2014-04-23 12:52:41 +02:00
if ' hooks ' in os . listdir ( app_tmp_folder ) :
for file in os . listdir ( app_tmp_folder + ' /hooks ' ) :
2013-10-09 11:05:04 +02:00
#TODO: do it with sed ?
2013-10-25 12:26:03 +02:00
if file [ : 1 ] != ' . ' :
2014-04-23 12:52:41 +02:00
with open ( app_tmp_folder + ' /hooks/ ' + file , " r " ) as sources :
2013-10-25 12:26:03 +02:00
lines = sources . readlines ( )
2014-04-23 12:52:41 +02:00
with open ( app_tmp_folder + ' /hooks/ ' + file , " w " ) as sources :
2013-10-25 12:26:03 +02:00
for line in lines :
sources . write ( re . sub ( r ' ' + app_id + ' ' , app_id_forked , line ) )
2013-02-26 23:13:49 +01:00
2014-04-23 12:52:41 +02:00
# Change app_id for the rest of the process
app_id = app_id_forked
2013-12-10 00:47:30 +01:00
2014-04-23 12:52:41 +02:00
# Prepare App settings
app_setting_path = apps_setting_path + ' / ' + app_id
2013-03-01 20:03:12 +01:00
2014-04-23 12:52:41 +02:00
#TMP: Remove old settings
if os . path . exists ( app_setting_path ) : shutil . rmtree ( app_setting_path )
os . makedirs ( app_setting_path )
os . system ( ' touch %s /settings.yml ' % app_setting_path )
2013-03-01 20:03:12 +01:00
2014-04-23 12:52:41 +02:00
# Add hooks
if ' hooks ' in os . listdir ( app_tmp_folder ) :
for file in os . listdir ( app_tmp_folder + ' /hooks ' ) :
hook_add ( app_id , app_tmp_folder + ' /hooks/ ' + file )
2013-10-18 16:55:03 +02:00
2014-04-23 12:52:41 +02:00
app_setting ( app_id , ' id ' , app_id )
app_setting ( app_id , ' install_time ' , int ( time . time ( ) ) )
2013-12-10 00:47:30 +01:00
2014-04-23 12:52:41 +02:00
if label :
app_setting ( app_id , ' label ' , label )
else :
app_setting ( app_id , ' label ' , manifest [ ' name ' ] )
2013-02-11 11:14:39 +01:00
2014-04-23 12:52:41 +02:00
os . system ( ' chown -R admin: ' + app_tmp_folder )
2013-02-26 20:36:37 +01:00
2014-04-23 12:52:41 +02:00
try :
if args is None :
args = ' '
args_dict = dict ( urlparse . parse_qsl ( args ) )
except :
args_dict = { }
2013-11-22 15:29:07 +01:00
2014-04-23 12:52:41 +02:00
# Execute App install script
os . system ( ' chown -hR admin: %s ' % install_tmp )
# Move scripts and manifest to the right place
os . system ( ' cp %s /manifest.json %s ' % ( app_tmp_folder , app_setting_path ) )
os . system ( ' cp -R %s /scripts %s ' % ( app_tmp_folder , app_setting_path ) )
try :
if hook_exec ( app_tmp_folder + ' /scripts/install ' , args_dict ) == 0 :
shutil . rmtree ( app_tmp_folder )
os . system ( ' chmod -R 400 %s ' % app_setting_path )
os . system ( ' chown -R root: %s ' % app_setting_path )
os . system ( ' chown -R admin: %s /scripts ' % app_setting_path )
app_ssowatconf ( auth )
msignals . display ( _ ( " Installation complete " ) , ' success ' )
else :
#TODO: display script fail messages
2013-12-10 00:47:30 +01:00
hook_remove ( app_id )
2013-10-09 11:05:04 +02:00
shutil . rmtree ( app_setting_path )
2013-11-22 15:29:07 +01:00
shutil . rmtree ( app_tmp_folder )
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 1 , _ ( " Installation failed " ) )
except KeyboardInterrupt , EOFError :
hook_remove ( app_id )
shutil . rmtree ( app_setting_path )
shutil . rmtree ( app_tmp_folder )
raise MoulinetteError ( 125 , _ ( " Interrupted " ) )
2013-03-01 20:03:12 +01:00
2013-10-09 11:05:04 +02:00
def app_remove ( app ) :
2013-06-07 13:44:23 +02:00
"""
2013-07-06 10:17:16 +02:00
Remove app
2013-06-07 13:44:23 +02:00
2013-07-06 10:17:16 +02:00
Keyword argument :
app - - App ( s ) to delete
2013-06-07 13:44:23 +02:00
"""
2014-04-23 12:52:41 +02:00
from yunohost . hook import hook_exec , hook_remove
2013-06-07 13:44:23 +02:00
2013-10-09 11:05:04 +02:00
if not _is_installed ( app ) :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " App is not installed " ) )
2013-06-07 13:44:23 +02:00
2013-10-25 12:11:24 +02:00
app_setting_path = apps_setting_path + app
2013-10-09 11:05:04 +02:00
#TODO: display fail messages from script
2013-11-25 13:14:23 +01:00
try :
shutil . rmtree ( ' /tmp/yunohost_remove ' )
except : pass
2013-12-07 17:57:45 +01:00
2014-04-23 12:52:41 +02:00
os . system ( ' cp -a %s /tmp/yunohost_remove && chown -hR admin: /tmp/yunohost_remove ' % app_setting_path )
2013-11-25 13:14:23 +01:00
os . system ( ' chown -R admin: /tmp/yunohost_remove ' )
os . system ( ' chmod -R u+rX /tmp/yunohost_remove ' )
2013-12-07 17:57:45 +01:00
2013-11-25 13:14:23 +01:00
if hook_exec ( ' /tmp/yunohost_remove/scripts/remove ' ) != 0 :
pass
2013-06-07 13:44:23 +02:00
2013-10-18 16:55:03 +02:00
if os . path . exists ( app_setting_path ) : shutil . rmtree ( app_setting_path )
2013-11-25 19:06:06 +01:00
shutil . rmtree ( ' /tmp/yunohost_remove ' )
2013-12-10 00:47:30 +01:00
hook_remove ( app )
2013-11-25 18:23:53 +01:00
app_ssowatconf ( )
2014-04-23 12:52:41 +02:00
msignals . display ( _ ( " App removed: %s " ) % app , ' success ' )
2013-06-07 13:44:23 +02:00
2014-04-23 12:52:41 +02:00
def app_addaccess ( auth , apps , users ) :
2013-03-03 15:54:24 +01:00
"""
2013-07-06 10:17:16 +02:00
Grant access right to users ( everyone by default )
2013-03-03 15:54:24 +01:00
2013-07-06 10:17:16 +02:00
Keyword argument :
users
2013-07-06 12:59:06 +02:00
apps
2013-03-03 15:54:24 +01:00
"""
2014-04-23 12:52:41 +02:00
from yunohost . user import user_list , user_info
2014-03-03 13:49:18 +01:00
if not users :
users = [ ]
2014-04-23 12:52:41 +02:00
for user in user_list ( auth ) [ ' users ' ] :
2014-03-30 03:05:21 +02:00
users . append ( user [ ' username ' ] )
2014-03-03 13:49:18 +01:00
2013-03-03 15:54:24 +01:00
if not isinstance ( users , list ) : users = [ users ]
if not isinstance ( apps , list ) : apps = [ apps ]
2013-10-09 11:05:04 +02:00
for app in apps :
if not _is_installed ( app ) :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " App is not installed " ) )
2013-03-03 15:54:24 +01:00
2013-10-09 11:05:04 +02:00
with open ( apps_setting_path + app + ' /settings.yml ' ) as f :
app_settings = yaml . load ( f )
2013-03-03 16:07:07 +01:00
2013-10-27 15:48:10 +01:00
if ' mode ' not in app_settings :
app_setting ( app , ' mode ' , ' private ' )
app_settings [ ' mode ' ] = ' private '
if app_settings [ ' mode ' ] == ' private ' :
2013-10-09 11:05:04 +02:00
if ' allowed_users ' in app_settings :
new_users = app_settings [ ' allowed_users ' ]
else :
new_users = ' '
for allowed_user in users :
2013-10-17 11:38:55 +02:00
if allowed_user not in new_users . split ( ' , ' ) :
2013-10-09 11:05:04 +02:00
try :
2014-04-23 12:52:41 +02:00
user_info ( auth , allowed_user )
except MoulinetteError :
2013-10-09 11:05:04 +02:00
continue
2013-10-27 15:48:10 +01:00
if new_users == ' ' :
new_users = allowed_user
else :
new_users = new_users + ' , ' + allowed_user
2013-10-09 11:05:04 +02:00
2013-10-27 15:48:10 +01:00
app_setting ( app , ' allowed_users ' , new_users . strip ( ) )
2013-03-03 15:54:24 +01:00
2014-04-23 12:52:41 +02:00
app_ssowatconf ( auth )
2013-03-03 17:45:31 +01:00
2014-03-03 13:49:18 +01:00
return { ' allowed_users ' : new_users . split ( ' , ' ) }
2013-03-03 17:45:31 +01:00
2014-04-23 12:52:41 +02:00
def app_removeaccess ( auth , apps , users ) :
2013-03-03 17:45:31 +01:00
"""
2013-07-06 10:17:16 +02:00
Revoke access right to users ( everyone by default )
2013-03-03 17:45:31 +01:00
2013-07-06 10:17:16 +02:00
Keyword argument :
users
2013-07-06 12:59:06 +02:00
apps
2013-03-03 17:45:31 +01:00
"""
2014-04-23 12:52:41 +02:00
from yunohost . user import user_list
2014-03-03 13:49:18 +01:00
remove_all = False
if not users :
remove_all = True
2013-03-03 17:45:31 +01:00
if not isinstance ( users , list ) : users = [ users ]
if not isinstance ( apps , list ) : apps = [ apps ]
2013-10-09 11:05:04 +02:00
for app in apps :
new_users = ' '
2013-03-03 17:45:31 +01:00
2013-10-09 11:05:04 +02:00
if not _is_installed ( app ) :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " App is not installed " ) )
2013-03-03 17:45:31 +01:00
2013-10-09 11:05:04 +02:00
with open ( apps_setting_path + app + ' /settings.yml ' ) as f :
app_settings = yaml . load ( f )
2013-03-03 17:45:31 +01:00
2013-12-05 21:31:51 +01:00
if ' skipped_uris ' not in app_settings or app_settings [ ' skipped_uris ' ] != ' / ' :
2014-03-03 13:49:18 +01:00
if remove_all :
new_users = ' '
elif ' allowed_users ' in app_settings :
2013-10-17 11:38:55 +02:00
for allowed_user in app_settings [ ' allowed_users ' ] . split ( ' , ' ) :
2013-10-09 11:05:04 +02:00
if allowed_user not in users :
2013-10-27 15:48:10 +01:00
if new_users == ' ' :
new_users = allowed_user
else :
new_users = new_users + ' , ' + allowed_user
2013-12-05 21:31:51 +01:00
else :
new_users = ' '
2014-04-23 12:52:41 +02:00
for user in user_list ( auth ) [ ' users ' ] :
2014-03-30 03:05:21 +02:00
if user [ ' username ' ] not in users :
2013-12-05 21:31:51 +01:00
if new_users == ' ' :
2014-03-30 03:05:21 +02:00
new_users = user [ ' username ' ]
new_users = new_users + ' , ' + user [ ' username ' ]
2013-12-07 17:57:45 +01:00
2013-12-05 21:31:51 +01:00
app_setting ( app , ' allowed_users ' , new_users . strip ( ) )
2013-03-03 17:45:31 +01:00
2014-04-23 12:52:41 +02:00
app_ssowatconf ( auth )
2013-03-03 15:54:24 +01:00
2014-03-03 13:49:18 +01:00
return { ' allowed_users ' : new_users . split ( ' , ' ) }
2013-03-01 20:03:12 +01:00
2014-03-03 13:58:41 +01:00
2014-04-23 12:52:41 +02:00
def app_clearaccess ( auth , apps ) :
2014-03-03 13:58:41 +01:00
"""
Reset access rights for the app
Keyword argument :
apps
"""
if not isinstance ( apps , list ) : apps = [ apps ]
for app in apps :
if not _is_installed ( app ) :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " App is not installed " ) )
2014-03-03 13:58:41 +01:00
with open ( apps_setting_path + app + ' /settings.yml ' ) as f :
app_settings = yaml . load ( f )
if ' mode ' in app_settings :
app_setting ( app , ' mode ' , delete = True )
if ' allowed_users ' in app_settings :
app_setting ( app , ' allowed_users ' , delete = True )
2014-04-23 12:52:41 +02:00
app_ssowatconf ( auth )
2014-03-03 13:58:41 +01:00
2013-03-01 20:03:12 +01:00
2013-12-05 11:39:36 +01:00
def app_setting ( app , key , value = None , delete = False ) :
2013-10-18 15:48:01 +02:00
"""
2013-12-21 12:09:58 +01:00
Set or get an app setting value
2013-10-31 11:21:59 +01:00
Keyword argument :
value - - Value to set
app - - App ID
key - - Key to get / set
2013-12-05 11:39:36 +01:00
delete - - Delete the key
2013-10-18 15:48:01 +02:00
"""
settings_file = apps_setting_path + app + ' /settings.yml '
2013-10-26 17:29:15 +02:00
try :
with open ( settings_file ) as f :
app_settings = yaml . load ( f )
except IOError :
# Do not fail if setting file is not there
2013-10-29 14:40:44 +01:00
app_settings = { }
2013-10-18 15:48:01 +02:00
2013-12-05 11:45:23 +01:00
if value is None and not delete :
2013-10-26 17:29:15 +02:00
# Get the value
if app_settings is not None and key in app_settings :
print ( app_settings [ key ] )
else :
# Set the value
if app_settings is None :
app_settings = { }
2013-12-05 11:39:36 +01:00
if delete and key in app_settings :
2013-10-18 15:48:01 +02:00
del app_settings [ key ]
else :
app_settings [ key ] = value
2013-10-26 17:29:15 +02:00
with open ( settings_file , ' w ' ) as f :
yaml . safe_dump ( app_settings , f , default_flow_style = False )
2013-10-30 21:22:35 +01:00
2013-10-18 15:48:01 +02:00
2013-12-05 17:10:37 +01:00
def app_service ( service , status = None , log = None , runlevel = None , remove = False ) :
2013-12-05 16:51:07 +01:00
"""
Add or remove a YunoHost monitored service
Keyword argument :
service - - Service to add / remove
status - - Custom status command
2013-12-05 16:59:19 +01:00
log - - Absolute path to log file to display
2013-12-05 17:10:37 +01:00
runlevel - - Runlevel priority of the service
2013-12-05 16:51:07 +01:00
remove - - Remove service
"""
service_file = ' /etc/yunohost/services.yml '
try :
with open ( service_file ) as f :
services = yaml . load ( f )
except IOError :
# Do not fail if service file is not there
services = { }
if remove and service in services :
del services [ service ]
else :
if status is None :
services [ service ] = { ' status ' : ' service ' }
else :
services [ service ] = { ' status ' : status }
2013-12-07 17:57:45 +01:00
2013-12-05 16:59:19 +01:00
if log is not None :
services [ service ] [ ' log ' ] = log
2013-12-05 17:10:37 +01:00
if runlevel is not None :
services [ service ] [ ' runlevel ' ] = runlevel
2013-12-05 16:51:07 +01:00
with open ( service_file , ' w ' ) as f :
yaml . safe_dump ( services , f , default_flow_style = False )
2013-10-27 14:23:52 +01:00
def app_checkport ( port ) :
"""
2013-10-31 11:21:59 +01:00
Check availability of a local port
Keyword argument :
port - - Port to check
2013-10-27 14:23:52 +01:00
"""
try :
s = socket . socket ( socket . AF_INET , socket . SOCK_STREAM )
s . settimeout ( 1 )
s . connect ( ( " localhost " , int ( port ) ) )
s . close ( )
except socket . error :
2014-04-23 12:52:41 +02:00
msignals . display ( _ ( " Port available: %s " ) % str ( port ) , ' success ' )
2013-10-27 14:23:52 +01:00
else :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " Port not available: %s " ) % str ( port ) )
2013-10-27 14:23:52 +01:00
2014-04-23 12:52:41 +02:00
def app_checkurl ( auth , url , app = None ) :
2013-10-26 17:29:15 +02:00
"""
2013-10-31 11:21:59 +01:00
Check availability of a web path
Keyword argument :
url - - Url to check
app - - Write domain & path to app settings for further checks
2013-10-26 17:29:15 +02:00
"""
2014-04-23 12:52:41 +02:00
from yunohost . domain import domain_list
2013-10-26 17:29:15 +02:00
if " https:// " == url [ : 8 ] :
url = url [ 8 : ]
elif " http:// " == url [ : 7 ] :
url = url [ 7 : ]
2013-10-30 21:22:35 +01:00
2013-10-26 17:29:15 +02:00
if url [ - 1 : ] != ' / ' :
url = url + ' / '
domain = url [ : url . index ( ' / ' ) ]
path = url [ url . index ( ' / ' ) : ]
if path [ - 1 : ] != ' / ' :
path = path + ' / '
apps_map = app_map ( raw = True )
validate ( r ' ^([a-zA-Z0-9] {1} ([a-zA-Z0-9 \ -]*[a-zA-Z0-9])*)( \ .[a-zA-Z0-9] {1} ([a-zA-Z0-9 \ -]*[a-zA-Z0-9])*)*( \ .[a-zA-Z] {1} ([a-zA-Z0-9 \ -]*[a-zA-Z0-9])*)$ ' , domain )
2014-04-23 12:52:41 +02:00
if domain not in domain_list ( auth ) [ ' domains ' ] :
raise MoulinetteError ( 22 , _ ( " Domain doesn ' t exists " ) )
2013-10-26 17:29:15 +02:00
if domain in apps_map :
if path in apps_map [ domain ] :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 1 , _ ( " An app is already installed on this location " ) )
2013-10-26 17:29:15 +02:00
for app_path , v in apps_map [ domain ] . items ( ) :
if app_path in path and app_path . count ( ' / ' ) < path . count ( ' / ' ) :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 1 , _ ( " Unable to install app at this location " ) )
2013-10-26 17:29:15 +02:00
if app is not None :
app_setting ( app , ' domain ' , value = domain )
app_setting ( app , ' path ' , value = path )
def app_initdb ( user , password = None , db = None , sql = None ) :
"""
Create database and initialize it with optionnal attached script
2013-10-30 21:22:35 +01:00
2013-10-31 11:21:59 +01:00
Keyword argument :
db - - DB name ( user unless set )
user - - Name of the DB user
password - - Password of the DB ( generated unless set )
sql - - Initial SQL file
2013-10-30 21:22:35 +01:00
2013-10-26 17:29:15 +02:00
"""
if db is None :
db = user
return_pwd = False
if password is None :
password = random_password ( 12 )
return_pwd = True
print ( password )
mysql_root_pwd = open ( ' /etc/yunohost/mysql ' ) . read ( ) . rstrip ( )
2014-04-23 12:52:41 +02:00
mysql_command = ' mysql -u root -p %s -e " CREATE DATABASE %s ; GRANT ALL PRIVILEGES ON %s .* TO \' %s \' @localhost IDENTIFIED BY \' %s \' ; " ' % ( mysql_root_pwd , db , db , user , password )
2013-10-26 17:29:15 +02:00
if os . system ( mysql_command ) != 0 :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 1 , _ ( " MySQL DB creation failed " ) )
2013-10-26 17:29:15 +02:00
if sql is not None :
2014-04-23 12:52:41 +02:00
if os . system ( ' mysql -u %s -p %s %s < %s ' % ( user , password , db , sql ) ) != 0 :
raise MoulinetteError ( 1 , _ ( " MySQL DB init failed " ) )
2013-10-26 17:29:15 +02:00
if not return_pwd :
2014-04-23 12:52:41 +02:00
msignals . display ( _ ( " Database initiliazed " ) , ' success ' )
2013-10-26 17:29:15 +02:00
2013-10-25 12:11:24 +02:00
2014-04-23 12:52:41 +02:00
def app_ssowatconf ( auth ) :
2013-10-28 10:39:15 +01:00
"""
2013-10-31 11:21:59 +01:00
Regenerate SSOwat configuration file
2013-10-28 10:39:15 +01:00
"""
2014-04-23 12:52:41 +02:00
from yunohost . domain import domain_list
from yunohost . user import user_list
2013-10-28 10:39:15 +01:00
with open ( ' /etc/yunohost/current_host ' , ' r ' ) as f :
main_domain = f . readline ( ) . rstrip ( )
2014-04-23 12:52:41 +02:00
domains = domain_list ( auth ) [ ' domains ' ]
2013-10-28 10:39:15 +01:00
users = { }
2014-04-23 12:52:41 +02:00
for user in user_list ( auth ) [ ' users ' ] :
2014-03-30 03:05:21 +02:00
users [ user [ ' username ' ] ] = app_map ( user = user [ ' username ' ] )
2013-12-03 21:02:34 +01:00
2013-12-07 17:57:45 +01:00
skipped_urls = [ ]
2014-03-08 10:48:25 +01:00
skipped_regex = [ ]
2013-12-07 17:57:45 +01:00
unprotected_urls = [ ]
2014-03-08 10:48:25 +01:00
unprotected_regex = [ ]
protected_urls = [ ]
protected_regex = [ ]
2014-03-26 02:11:20 +01:00
2013-12-07 17:57:45 +01:00
apps = { }
2013-12-04 22:24:12 +01:00
for app in app_list ( ) [ ' Apps ' ] :
if _is_installed ( app [ ' ID ' ] ) :
2013-12-07 17:57:45 +01:00
with open ( apps_setting_path + app [ ' ID ' ] + ' /settings.yml ' ) as f :
app_settings = yaml . load ( f )
2013-12-06 20:40:49 +01:00
if ' skipped_uris ' in app_settings :
for item in app_settings [ ' skipped_uris ' ] . split ( ' , ' ) :
if item [ - 1 : ] == ' / ' :
item = item [ : - 1 ]
2013-12-07 17:57:45 +01:00
skipped_urls . append ( app_settings [ ' domain ' ] + app_settings [ ' path ' ] [ : - 1 ] + item )
2014-03-08 10:48:25 +01:00
if ' skipped_regex ' in app_settings :
for item in app_settings [ ' skipped_regex ' ] . split ( ' , ' ) :
skipped_regex . append ( item )
2013-12-07 17:57:45 +01:00
if ' unprotected_uris ' in app_settings :
for item in app_settings [ ' unprotected_uris ' ] . split ( ' , ' ) :
if item [ - 1 : ] == ' / ' :
item = item [ : - 1 ]
unprotected_urls . append ( app_settings [ ' domain ' ] + app_settings [ ' path ' ] [ : - 1 ] + item )
2014-03-08 10:48:25 +01:00
if ' unprotected_regex ' in app_settings :
for item in app_settings [ ' unprotected_regex ' ] . split ( ' , ' ) :
unprotected_regex . append ( item )
if ' protected_uris ' in app_settings :
for item in app_settings [ ' protected_uris ' ] . split ( ' , ' ) :
if item [ - 1 : ] == ' / ' :
item = item [ : - 1 ]
protected_urls . append ( app_settings [ ' domain ' ] + app_settings [ ' path ' ] [ : - 1 ] + item )
if ' protected_regex ' in app_settings :
for item in app_settings [ ' protected_regex ' ] . split ( ' , ' ) :
protected_regex . append ( item )
2013-12-07 17:57:45 +01:00
for domain in domains :
2013-12-07 18:03:53 +01:00
skipped_urls . extend ( [ domain + ' /ynhadmin ' , domain + ' /ynhapi ' ] )
2013-12-03 17:45:15 +01:00
2014-03-08 10:48:25 +01:00
with open ( ' /etc/ssowat/conf.json ' ) as f :
conf_dict = json . load ( f )
if not ' portal_domain ' in conf_dict :
conf_dict [ ' portal_domain ' ] = main_domain
if not ' portal_path ' in conf_dict :
conf_dict [ ' portal_path ' ] = ' /ynhsso/ '
if not ' portal_port ' in conf_dict :
conf_dict [ ' portal_port ' ] = ' 443 '
if not ' portal_scheme ' in conf_dict :
conf_dict [ ' portal_scheme ' ] = ' https '
if not ' additional_headers ' in conf_dict :
conf_dict [ ' additional_headers ' ] = {
2013-10-28 10:39:15 +01:00
' Auth-User ' : ' uid ' ,
' Remote-User ' : ' uid ' ,
' Name ' : ' cn ' ,
' Email ' : ' mail '
2014-03-08 10:48:25 +01:00
}
conf_dict [ ' domains ' ] = domains
conf_dict [ ' skipped_urls ' ] = skipped_urls
conf_dict [ ' unprotected_urls ' ] = unprotected_urls
conf_dict [ ' protected_urls ' ] = protected_urls
conf_dict [ ' skipped_regex ' ] = skipped_regex
conf_dict [ ' unprotected_regex ' ] = unprotected_regex
conf_dict [ ' protected_regex ' ] = protected_regex
conf_dict [ ' users ' ] = users
2013-10-28 10:39:15 +01:00
with open ( ' /etc/ssowat/conf.json ' , ' wb ' ) as f :
json . dump ( conf_dict , f )
2014-04-23 12:52:41 +02:00
msignals . display ( _ ( ' SSOwat configuration generated ' ) , ' success ' )
2013-10-28 10:39:15 +01:00
2013-10-25 10:28:50 +02:00
def _extract_app_from_file ( path , remove = False ) :
2013-02-25 22:23:32 +01:00
"""
2013-03-02 12:09:22 +01:00
Unzip or untar application tarball in app_tmp_folder , or copy it from a directory
2013-02-25 22:23:32 +01:00
Keyword arguments :
2013-03-02 12:09:22 +01:00
path - - Path of the tarball or directory
2013-10-25 10:28:50 +02:00
remove - - Remove the tarball after extraction
2013-02-25 22:23:32 +01:00
Returns :
Dict manifest
"""
2013-10-26 17:29:15 +02:00
global app_tmp_folder
2013-12-07 00:38:41 +01:00
print ( _ ( ' Extracting... ' ) )
2013-02-25 22:23:32 +01:00
if os . path . exists ( app_tmp_folder ) : shutil . rmtree ( app_tmp_folder )
os . makedirs ( app_tmp_folder )
2013-03-02 12:09:22 +01:00
2013-02-26 14:52:13 +01:00
if " .zip " in path :
2014-04-23 12:52:41 +02:00
extract_result = os . system ( ' cd %s && unzip %s -d %s > /dev/null 2>&1 ' % ( os . getcwd ( ) , path , app_tmp_folder ) )
2013-10-25 10:28:50 +02:00
if remove : os . remove ( path )
2013-02-26 14:52:13 +01:00
elif " .tar " in path :
2014-04-23 12:52:41 +02:00
extract_result = os . system ( ' cd %s && tar -xf %s -C %s > /dev/null 2>&1 ' % ( os . getcwd ( ) , path , app_tmp_folder ) )
2013-10-25 10:28:50 +02:00
if remove : os . remove ( path )
2014-04-23 12:52:41 +02:00
elif ( path [ : 1 ] == ' / ' and os . path . exists ( path ) ) or ( os . system ( ' cd %s / %s ' % ( os . getcwd ( ) , path ) ) == 0 ) :
2013-03-02 12:09:22 +01:00
shutil . rmtree ( app_tmp_folder )
if path [ len ( path ) - 1 : ] != ' / ' :
path = path + ' / '
2014-04-23 12:52:41 +02:00
extract_result = os . system ( ' cd %s && cp -a " %s " %s ' % ( os . getcwd ( ) , path , app_tmp_folder ) )
2013-02-25 22:23:32 +01:00
else :
extract_result = 1
if extract_result != 0 :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " Invalid install file " ) )
2013-02-25 22:23:32 +01:00
2013-03-02 12:09:22 +01:00
try :
2013-10-26 17:29:15 +02:00
if len ( os . listdir ( app_tmp_folder ) ) == 1 :
for folder in os . listdir ( app_tmp_folder ) :
app_tmp_folder = app_tmp_folder + ' / ' + folder
2013-10-07 22:49:58 +02:00
with open ( app_tmp_folder + ' /manifest.json ' ) as json_manifest :
2013-03-02 12:09:22 +01:00
manifest = json . loads ( str ( json_manifest . read ( ) ) )
manifest [ ' lastUpdate ' ] = int ( time . time ( ) )
except IOError :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 1 , _ ( " Invalid App file " ) )
2013-02-25 22:23:32 +01:00
2013-12-07 00:38:41 +01:00
print ( _ ( ' OK ' ) )
2013-02-26 14:52:13 +01:00
2013-02-25 22:23:32 +01:00
return manifest
2013-02-26 14:52:13 +01:00
def _fetch_app_from_git ( app ) :
2013-02-25 22:23:32 +01:00
"""
Unzip or untar application tarball in app_tmp_folder
2013-02-11 11:14:39 +01:00
2013-02-25 22:23:32 +01:00
Keyword arguments :
2013-06-06 13:15:38 +02:00
app - - App_id or git repo URL
2013-02-25 22:23:32 +01:00
Returns :
Dict manifest
"""
global app_tmp_folder
2013-12-07 00:38:41 +01:00
print ( _ ( ' Downloading... ' ) )
2013-06-06 13:15:38 +02:00
if ( ' @ ' in app ) or ( ' http:// ' in app ) or ( ' https:// ' in app ) :
2013-10-26 17:29:15 +02:00
if " github.com " in app :
url = app . replace ( " git@github.com: " , " https://github.com/ " )
if " .git " in url [ - 4 : ] : url = url [ : - 4 ]
if " / " in url [ - 1 : ] : url = url [ : - 1 ]
url = url + " /archive/master.zip "
2014-04-23 12:52:41 +02:00
if os . system ( ' wget " %s " -O " %s .zip " > /dev/null 2>&1 ' % ( url , app_tmp_folder ) ) == 0 :
2013-10-26 17:29:15 +02:00
return _extract_app_from_file ( app_tmp_folder + ' .zip ' , remove = True )
2014-04-23 12:52:41 +02:00
git_result = os . system ( ' git clone %s %s ' % ( app , app_tmp_folder ) )
2013-06-06 13:15:38 +02:00
git_result_2 = 0
try :
2013-10-07 22:49:58 +02:00
with open ( app_tmp_folder + ' /manifest.json ' ) as json_manifest :
2013-06-06 13:15:38 +02:00
manifest = json . loads ( str ( json_manifest . read ( ) ) )
manifest [ ' lastUpdate ' ] = int ( time . time ( ) )
except IOError :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 1 , _ ( " Invalid App manifest " ) )
2013-02-25 22:23:32 +01:00
else :
2013-06-06 13:15:38 +02:00
app_dict = app_list ( raw = True )
if app in app_dict :
app_info = app_dict [ app ]
app_info [ ' manifest ' ] [ ' lastUpdate ' ] = app_info [ ' lastUpdate ' ]
manifest = app_info [ ' manifest ' ]
else :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " App doesn ' t exists " ) )
2013-06-06 13:15:38 +02:00
2013-10-25 10:28:50 +02:00
if " github.com " in app_info [ ' git ' ] [ ' url ' ] :
url = app_info [ ' git ' ] [ ' url ' ] . replace ( " git@github.com: " , " https://github.com/ " )
if " .git " in url [ - 4 : ] : url = url [ : - 4 ]
if " / " in url [ - 1 : ] : url = url [ : - 1 ]
url = url + " /archive/ " + str ( app_info [ ' git ' ] [ ' revision ' ] ) + " .zip "
2014-04-23 12:52:41 +02:00
if os . system ( ' wget " %s " -O " %s .zip " > /dev/null 2>&1 ' % ( url , app_tmp_folder ) ) == 0 :
2013-10-25 10:28:50 +02:00
return _extract_app_from_file ( app_tmp_folder + ' .zip ' , remove = True )
2013-10-30 21:22:35 +01:00
2013-10-25 10:28:50 +02:00
app_tmp_folder = install_tmp + ' / ' + app
if os . path . exists ( app_tmp_folder ) : shutil . rmtree ( app_tmp_folder )
2013-10-30 21:22:35 +01:00
2014-04-23 12:52:41 +02:00
git_result = os . system ( ' git clone %s -b %s %s ' % ( app_info [ ' git ' ] [ ' url ' ] , app_info [ ' git ' ] [ ' branch ' ] , app_tmp_folder ) )
git_result_2 = os . system ( ' cd %s && git reset --hard %s ' % ( app_tmp_folder , str ( app_info [ ' git ' ] [ ' revision ' ] ) ) )
2013-02-25 22:23:32 +01:00
if not git_result == git_result_2 == 0 :
2014-04-23 12:52:41 +02:00
raise MoulinetteError ( 22 , _ ( " Sources fetching failed " ) )
2013-02-25 22:23:32 +01:00
2013-12-07 00:38:41 +01:00
print ( _ ( ' OK ' ) )
2013-02-26 14:52:13 +01:00
2013-06-06 13:15:38 +02:00
return manifest
2013-02-25 22:23:32 +01:00
2013-06-07 13:44:23 +02:00
def _installed_instance_number ( app , last = False ) :
2013-02-26 23:13:49 +01:00
"""
Check if application is installed and return instance number
Keyword arguments :
2013-10-08 23:51:47 +02:00
app - - id of App to check
2013-06-07 13:44:23 +02:00
last - - Return only last instance number
2013-02-26 23:13:49 +01:00
Returns :
2013-06-07 13:44:23 +02:00
Number of last installed instance | List or instances
2013-02-26 23:13:49 +01:00
"""
2013-06-07 13:44:23 +02:00
if last :
number = 0
try :
installed_apps = os . listdir ( apps_setting_path )
except OSError :
os . makedirs ( apps_setting_path )
return 0
2013-02-28 17:58:18 +01:00
2013-06-07 13:44:23 +02:00
for installed_app in installed_apps :
2013-10-25 12:35:23 +02:00
if number == 0 and app == installed_app :
number = 1
elif ' __ ' in installed_app :
2013-06-07 13:44:23 +02:00
if app == installed_app [ : installed_app . index ( ' __ ' ) ] :
if int ( installed_app [ installed_app . index ( ' __ ' ) + 2 : ] ) > number :
number = int ( installed_app [ installed_app . index ( ' __ ' ) + 2 : ] )
return number
else :
instance_number_list = [ ]
instances_dict = app_map ( app = app , raw = True )
for key , domain in instances_dict . items ( ) :
for key , path in domain . items ( ) :
instance_number_list . append ( path [ ' instance ' ] )
return sorted ( instance_number_list )
2013-02-26 23:13:49 +01:00
2013-10-09 11:05:04 +02:00
def _is_installed ( app ) :
"""
Check if application is installed
Keyword arguments :
app - - id of App to check
Returns :
Boolean
"""
try :
installed_apps = os . listdir ( apps_setting_path )
except OSError :
os . makedirs ( apps_setting_path )
return False
for installed_app in installed_apps :
if app == installed_app :
return True
else :
continue
return False