SL-321: basic launcher/updater integration test fixes

master
Glenn Glazer 2016-07-27 15:44:56 -07:00
parent 1224697a40
commit f44829f2ae
4 changed files with 119 additions and 75 deletions

View File

@ -1482,9 +1482,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>313f5c8edd328e05c59cbe980512f84c</string>
<string>13998879705aa1af36c6ea8f480901e3</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llbase/rev/317790/arch/Darwin/installer/llbase-0.8.6.317790-darwin-317790.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llbase/rev/318106/arch/Darwin/installer/llbase-0.8.6.318106-darwin-318106.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -1494,9 +1494,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>e85171c70b57dd086b956ba36e6f2306</string>
<string>80ef3f9f6bde28787b02837ace2ad84c</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llbase/rev/317790/arch/Linux/installer/llbase-0.8.6.317790-linux-317790.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llbase/rev/318106/arch/Linux/installer/llbase-0.8.6.318106-linux-318106.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1506,16 +1506,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>07b0d64d812cfaf3025b799cea5fe446</string>
<string>57837daafa60f98a4d9fa4dfe53d995e</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llbase/rev/317790/arch/CYGWIN/installer/llbase-0.8.6.0-windows-317790.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llbase/rev/318106/arch/CYGWIN/installer/llbase-0.8.6.0-windows-318106.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
<string>0.8.6.317790</string>
<string>0.8.6.318106</string>
</map>
<key>llceflib</key>
<map>

View File

@ -27,6 +27,7 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
$/LicenseInfo$
"""
import sys
import os
import os.path
import shutil
import errno
@ -702,6 +703,7 @@ class Darwin_i386_Manifest(ViewerManifest):
pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
relpkgdir = os.path.join(pkgdir, "lib", "release")
debpkgdir = os.path.join(pkgdir, "lib", "debug")
llbasedir = os.path.join(pkgdir, os.pardir)
if self.prefix(src="", dst="Contents"): # everything goes in Contents
self.path("Info.plist", dst="Info.plist")
@ -715,8 +717,14 @@ class Darwin_i386_Manifest(ViewerManifest):
#this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322 and SL-323
self.path2basename("../viewer_components/manager","SL_Launcher")
self.path2basename("../viewer_components/manager","*.py")
self.path2basename("../../../../../packages/llbase","*")
self.end_prefix()
llbase_path = os.path.join(self.get_dst_prefix(),'llbase')
if not os.path.exists(llbase_path):
os.makedirs(llbase_path)
if self.prefix(dst="llbase"):
self.path2basename("../packages/llbase","*.py")
self.path2basename("../packages/llbase","_cllsd.so")
self.end_prefix()
self.end_prefix()
# most everything goes in the Resources directory
if self.prefix(src="", dst="Resources"):
@ -1071,7 +1079,13 @@ class LinuxManifest(ViewerManifest):
#this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322 and SL-323
self.path2basename("../viewer_components/manager","SL_Launcher")
self.path2basename("../viewer_components/manager","*.py")
self.path2basename("../packages/llbase","*")
llbase_path = os.path.join(self.get_dst_prefix(),'llbase')
if not os.path.exists(llbase_path):
os.makedirs(llbase_path)
if self.prefix(dst="llbase"):
self.path2basename("../packages/llbase","*.py")
self.path2basename("../packages/llbase","_cllsd.so")
self.end_prefix()
self.end_prefix("bin")
if self.prefix("res-sdl"):

View File

@ -17,43 +17,51 @@
# $/LicenseInfo$
# Copyright (c) 2013, Linden Research, Inc.
import os
import sys
#module globals
log_file_handle = None
cwd = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, os.path.join(cwd, 'llbase'))
import argparse
import collections
import InstallerUserMessage
#NOTA BENE:
# For POSIX platforms, llsd.py will be imported from the same directory.
# For Windows, llsd.py will be compiled into the executable by pyinstaller
import llsd
import os
from llbase import llsd
import platform
import sys
import subprocess
import update_manager
def after_frame(my_message, timeout = 10000):
#pop up a InstallerUserMessage.basic_message that kills itself after timeout milliseconds
#note that this blocks the caller for the duration of timeout
frame = InstallerUserMessage(title = "Second Life Installer", icon_name="head-sl-logo.gif")
#this is done before basic_message so that we aren't blocked by mainloop()
frame.after(timout, lambda: frame._delete_window)
frame.basic_message(message = my_message)
def silent_write(log_file_handle, text):
#if we have a log file, write. If not, do nothing.
#this is so we don't have to keep trapping for an exception with a None handle
#oh and because it is best effort, it is also a holey_write ;)
if (log_file_handle):
#prepend text for easy grepping
log_file_handle.write("SL LAUNCHER: " + text + "\n")
def get_cmd_line():
platform_name = platform.system()
#find the parent of the logs and user_settings directories
if (platform_name == 'mac'):
if (platform_name == 'Darwin'):
settings_file = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'Resources/app_settings/cmd_line.xml')
elif (platform_name == 'lnx'):
elif (platform_name == 'Linux'):
settings_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'app_settings/cmd_line.xml')
#using list format of join is important here because the Windows pathsep in a string escapes the next char
elif (platform_name == 'win'):
elif (platform_name == 'Windows'):
settings_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'app_settings/cmd_line.xml')
else:
settings_dir = None
settings_file = None
try:
cmd_line = llsd.parse((open(settings_file)).read())
except:
silent_write(log_file_handle, "Could not parse settings file %s" % settings_file)
cmd_line = None
return cmd_line
@ -68,7 +76,6 @@ def get_settings():
return None
return settings
def capture_vmp_args(arg_list = None, cmd_line = None):
#expected input format: arg_list = ['--set', 'foo', 'bar', '-X', '-Y', 'qux']
#take a copy of the viewer parameters that are of interest to VMP.
@ -96,7 +103,8 @@ def capture_vmp_args(arg_list = None, cmd_line = None):
cli_overrides[vmp_params[param]] = (setting_name, setting_value)
else:
#find out how many args this parameter has
count = cmd_line[param]['count']
no_dashes = vmp_params[param]
count = cmd_line[no_dashes]['count']
param_args = []
if count:
for argh in range(1,count):
@ -112,6 +120,7 @@ def capture_vmp_args(arg_list = None, cmd_line = None):
except KeyError:
cli_overrides[key] = None
else:
cli_overrides["--set"] = {}
for arg in vmp_setters:
try:
cli_overrides[key][arg]
@ -119,7 +128,10 @@ def capture_vmp_args(arg_list = None, cmd_line = None):
cli_overrides[key][arg] = None
return cli_overrides
cwd = os.path.dirname(os.path.realpath(__file__))
#main entry point
#this and a few other update manager methods really should be refactored into a util lib
parent_dir = update_manager.get_parent_path(update_manager.get_platform_key())
log_file_handle = update_manager.get_log_file_handle(parent_dir)
executable_name = ""
if sys.platform.startswith('darwin'):
@ -137,23 +149,18 @@ else:
#SL doesn't run on VMS or punch cards
sys.exit("Unsupported platform")
#check for an update
#TODO
#find the viewer to be lauched
viewer_binary = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),executable_name)
parser = argparse.ArgumentParser()
args = parser.parse_known_args(sys.argv)
print args[1]
sys.exit()
#args[1] looks like ['./SL_Launcher', '--set', 'foo', 'bar', '-X', '-Y', 'qux'], dump the progname
args_list_to_pass = args[1][1:]
vmp_args = capture_vmp_args(args_list_to_pass)
#make a copy by value, not by reference
command = list(args_list_to_pass)
(success, state, condition) = update_manager.update_manager(cli_overrides)
(success, state, condition) = update_manager.update_manager(vmp_args)
# From update_manager:
# (False, 'setup', None): error occurred before we knew what the update was (e.g., in setup or parsing)
# (False, 'download', version): we failed to download the new version
@ -167,8 +174,8 @@ command = list(args_list_to_pass)
# No update, update succeeded in place in foreground, or background update started: silently launch the current viewer channel
# Updated succeed to a different channel, launch that viewer and exit
if not success:
msg = 'Update failed in the %s process. Please check logs. Viewer will launch starting momentarily.'
after_frame(msg)
msg = 'Update failed in the %s process. Please check logs. Viewer will launch starting momentarily.' % state
update_manager.after_frame(msg)
command.insert(0,viewer_binary)
viewer_process = subprocess.Popen(command)
#at the moment, we just exit here. Later, the crash monitor will be launched at this point

View File

@ -1,29 +1,35 @@
#!/usr/bin/env python
# $LicenseInfo:firstyear=2016&license=internal$
#
# Copyright (c) 2016, Linden Research, Inc.
#
# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
# this source code is governed by the Linden Lab Source Code Disclosure
# Agreement ("Agreement") previously entered between you and Linden
# Lab. By accessing, using, copying, modifying or distributing this
# software, you acknowledge that you have been informed of your
# obligations under the Agreement and agree to abide by those obligations.
#
# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
# COMPLETENESS OR PERFORMANCE.
# $/LicenseInfo$
# Copyright (c) 2013, Linden Research, Inc.
"""
@file update_manager.py
"""\
@file update_manager.py
@author coyot
@date 2016-05-16
@date 2016-05-16
@brief executes viewer update checking and manages downloading and applying of updates
$LicenseInfo:firstyear=2016&license=viewerlgpl$
Second Life Viewer Source Code
Copyright (C) 2016, Linden Research, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation;
version 2.1 of the License only.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
$/LicenseInfo$
"""
from llbase import llrest
from llbase.llrest import RESTError
from llbase import llsd
from urlparse import urljoin
@ -55,9 +61,9 @@ def silent_write(log_file_handle, text):
def after_frame(my_message, timeout = 10000):
#pop up a InstallerUserMessage.basic_message that kills itself after timeout milliseconds
#note that this blocks the caller for the duration of timeout
frame = InstallerUserMessage(title = "Second Life Installer", icon_name="head-sl-logo.gif")
frame = InstallerUserMessage.InstallerUserMessage(title = "Second Life Installer", icon_name="head-sl-logo.gif")
#this is done before basic_message so that we aren't blocked by mainloop()
frame.after(timout, lambda: frame._delete_window)
frame.after(timeout, lambda: frame._delete_window)
frame.basic_message(message = my_message)
def convert_version_file_style(version):
@ -146,8 +152,10 @@ def check_for_completed_download(download_dir):
def get_settings(log_file_handle, parent_dir):
#return the settings file parsed into a dict
print str(parent_dir)
try:
settings_file = os.path.abspath(os.path.join(parent_dir,'user_settings','settings.xml'))
print "Settings file: " + str(settings_file)
settings = llsd.parse((open(settings_file)).read())
except llsd.LLSDParseError as lpe:
silent_write(log_file_handle, "Could not parse settings file %s" % lpe)
@ -213,7 +221,7 @@ def query_vvm(log_file_handle = None, platform_key = None, settings = None, summ
else:
base_URI = 'https://update.secondlife.com/update/'
channelname = summary_dict['Channel']
#this is kind of a mess because the settings value a) in a map and b) is both the cohort and the version
#this is kind of a mess because the settings value is a) in a map and b) is both the cohort and the version
version = summary_dict['Version']
platform_version = platform.release()
#this will always return something usable, error handling in method
@ -250,7 +258,7 @@ def query_vvm(log_file_handle = None, platform_key = None, settings = None, summ
try:
result_data = VVMService.get(query_string)
except RESTError as re:
silent_write.write(log_file_handle, "Failed to query VVM using %s failed as %s" % (urljoin(base_URI,query_string, re)))
silent_write(log_file_handle, "Failed to query VVM using %s failed as %s" % (urljoin(base_URI,query_string), re))
return None
return result_data
@ -342,6 +350,8 @@ def update_manager(cli_overrides = None):
platform_key = get_platform_key()
parent_dir = get_parent_path(platform_key)
log_file_handle = get_log_file_handle(parent_dir)
settings = None
print "parent dir: " + str(parent_dir)
#check to see if user has install rights
#get the owner of the install and the current user
@ -367,10 +377,12 @@ def update_manager(cli_overrides = None):
print "Update manager exited with (%s, %s, %s)" % (False, 'setup', None)
return (False, 'setup', None)
if cli_overrides['settings'] is not None:
settings = get_settings(log_file_handle, cli_overrides['settings'])
else:
settings = get_settings(log_file_handle, parent_dir)
if cli_overrides is not None:
if '--settings' in cli_overrides.keys():
if cli_overrides['--settings'] is not None:
settings = get_settings(log_file_handle, cli_overrides['--settings'])
else:
settings = get_settings(log_file_handle, parent_dir)
if settings is None:
silent_write(log_file_handle, "Failed to load viewer settings")
@ -379,7 +391,7 @@ def update_manager(cli_overrides = None):
#323: If a complete download of that update is found, check the update preference:
#settings['UpdaterServiceSetting'] = 0 is manual install
"""
"""ssh://hg@bitbucket.org/lindenlab/viewer-release-maint-6585
<key>UpdaterServiceSetting</key>
<map>
<key>Comment</key>
@ -390,8 +402,10 @@ def update_manager(cli_overrides = None):
<string>0</string>
</map>
"""
if cli_overrides['set']['UpdaterServiceSetting'] is not None:
install_automatically = cli_overrides['set']['UpdaterServiceSetting']
if cli_overrides is not None:
if '--set' in cli_overrides.keys():
if 'UpdaterServiceSetting' in cli_overrides['--set'].keys():
install_automatically = cli_overrides['--set']['UpdaterServiceSetting']
else:
try:
install_automatically = settings['UpdaterServiceSetting']['Value']
@ -399,28 +413,37 @@ def update_manager(cli_overrides = None):
except KeyError:
install_automatically = 1
#use default chunk size if none is given
if cli_overrides['set']['UpdaterMaximumBandwidth ']:
chunk_size = cli_overrides['set']['UpdaterMaximumBandwidth ']
#use default chunk size if none is given
if cli_overrides is not None:
if '--set' in cli_overrides.keys():
if 'UpdaterMaximumBandwidth' in cli_overrides['--set'].keys():
chunk_size = cli_overrides['--set']['UpdaterMaximumBandwidth']
else:
chunk_size = 1024
#get channel and version
try:
summary_dict = get_summary(platform_key, os.path.abspath(os.path.realpath(__file__)))
if cli_overrides['channel']:
summary_dict['Channel'] = cli_overrides['channel']
except:
if cli_overrides is not None:
if 'channel' in cli_overrides.keys():
summary_dict['Channel'] = cli_overrides['channel']
except Exception, e:
silent_write(log_file_handle, "Could not obtain channel and version, exiting.")
silent_write(log_file_handle, e.message)
print "Update manager exited with (%s, %s, %s)" % (False, 'setup', None)
return (False, 'setup', None)
#323: On launch, the Viewer Manager should query the Viewer Version Manager update api.
UpdaterServiceURL = cli_overrides['update-service']
if cli_overrides is not None:
if '--update-service' in cli_overrides.keys():
UpdaterServiceURL = cli_overrides['--update-service']
else:
#tells query_vvm to use the default
UpdaterServiceURL = None
result_data = query_vvm(log_file_handle, platform_key, settings, summary_dict, UpdaterServiceURL)
#nothing to do or error
if not result_data:
silent_write.write(og_file_handle, "No update found.")
silent_write(log_file_handle, "No update found.")
print "Update manager exited with (%s, %s, %s)" % (True, None, None)
return (True, None, None)