SL-16124 First pass at a Python3 script to launch multiple non-interactive Viewers with differing command line options
parent
f3743b8e30
commit
b3382719ad
|
|
@ -0,0 +1,197 @@
|
|||
#!/usr/bin/env python3
|
||||
"""\
|
||||
@file perfbot_run.py
|
||||
@brief Run a number of non interactive Viewers (PerfBots) with
|
||||
a variety of options and settings. Pass --help for details.
|
||||
|
||||
$LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2021, 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$
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import os
|
||||
import math
|
||||
import time
|
||||
|
||||
# Required parameters that are always passed in
|
||||
# Specify noninteractive mode (SL-15999 for details)
|
||||
PARAM_NON_INTERACTIVE = "--noninteractive"
|
||||
# Run multiple Viewers at once
|
||||
PARAM_MULTI = "--multiple"
|
||||
# Specify username (first and last) and password
|
||||
PARAM_LOGIN = "--login"
|
||||
# SLURL to teleport to after login
|
||||
PARAM_SLURL = "--slurl"
|
||||
|
||||
|
||||
def gen_niv_script(args):
|
||||
print(f"Launching {(args.num)} instances of the Viewer")
|
||||
print(f"Reading creds from {(args.creds)} folder")
|
||||
print(f"Using the non interactive Viewer from {(args.viewer)}")
|
||||
print(f"Sleeping for {args.sleep}ms between Viewer launches")
|
||||
|
||||
# Read the lines from the creds file. Typically this will be
|
||||
# stored in the build-secrets-git private repository but you
|
||||
# can point to any location with the --creds parameter
|
||||
creds_lines = []
|
||||
with open(args.creds) as file:
|
||||
creds_lines = file.readlines()
|
||||
creds_lines = [line.rstrip() for line in creds_lines]
|
||||
creds_lines = [line for line in creds_lines if not line.startswith("#") and len(line)]
|
||||
# We cannot log in more users than we have credentials for
|
||||
if args.num > len(creds_lines):
|
||||
print(
|
||||
f"The number of agents specified ({(args.num)}) exceeds "
|
||||
f"the number of valid entries ({(len(creds_lines))}) in "
|
||||
f"the creds file "
|
||||
)
|
||||
return
|
||||
# The Viewer (in dev environments at least) needs a well specified
|
||||
# working directory to function properly. We try to guess what it
|
||||
# might be based on the full path to the Viewer executable but
|
||||
# you can also specify it explicitly with the --cwd parameter
|
||||
# (required for dev builds)
|
||||
working_dir = args.cwd
|
||||
if len(args.cwd) == 0:
|
||||
working_dir = os.path.dirname(os.path.abspath(args.viewer))
|
||||
print(f"Working directory is {working_dir}")
|
||||
os.chdir(working_dir)
|
||||
|
||||
if args.dryrun:
|
||||
print("Ruuning in dry-run mode - no Viewers will be started")
|
||||
print("")
|
||||
|
||||
for inst in range(args.num):
|
||||
|
||||
# Format of each cred line is username_first username_last password
|
||||
# A space is used to separate each and a # at the start of a line
|
||||
# removes it from the pool (useful if someone else is using a subset
|
||||
# of the available ones)
|
||||
creds = creds_lines[inst].split(" ")
|
||||
username_first = creds[0]
|
||||
username_last = creds[1]
|
||||
password = creds[2]
|
||||
|
||||
# The default layout is an evenly spaced circle in the
|
||||
# center of the region. We may extend this to allow other
|
||||
# patterns like a square/rectangle or a spiral. (Hint: it
|
||||
# likely won't be needed :))
|
||||
center_x = 128
|
||||
center_y = 128
|
||||
if args.layout == "circle":
|
||||
radius = 6
|
||||
angle = (2 * math.pi / args.num) * inst
|
||||
region_x = int(math.sin(angle) * radius + center_x)
|
||||
region_y = int(math.cos(angle) * radius + center_y)
|
||||
region_z = 0
|
||||
elif args.layout == "square":
|
||||
region_x = center_x
|
||||
region_y = center_y
|
||||
elif args.layout == "spiral":
|
||||
region_x = center_x
|
||||
region_y = center_y
|
||||
slurl = f"secondlife://{args.region}/{region_x}/{region_y}/{region_z}"
|
||||
|
||||
# Buold the script line
|
||||
script_cmd = [args.viewer]
|
||||
script_cmd.append(PARAM_NON_INTERACTIVE)
|
||||
script_cmd.append(PARAM_MULTI)
|
||||
script_cmd.append(PARAM_LOGIN)
|
||||
script_cmd.append(username_first)
|
||||
script_cmd.append(username_last)
|
||||
script_cmd.append(password)
|
||||
script_cmd.append(PARAM_SLURL)
|
||||
script_cmd.append(slurl)
|
||||
|
||||
# Display the script we will execute.
|
||||
cmd = ""
|
||||
for p in script_cmd:
|
||||
cmd = cmd + " " + p
|
||||
print(cmd)
|
||||
|
||||
# If --dry-run is specified, we do everything (including, most
|
||||
# usefully, display the script lines) but do not start the Viewer
|
||||
if args.dryrun == False:
|
||||
viewer_session = subprocess.Popen(script_cmd)
|
||||
|
||||
# Sleeping a bit between launches seems to help avoid a CPU
|
||||
# surge when N Viewers are started simulatanously. The default
|
||||
# value can be changed with the --sleep parameter
|
||||
time.sleep(args.sleep / 1000)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(allow_abbrev=False)
|
||||
parser.add_argument(
|
||||
"--num",
|
||||
type=int,
|
||||
required=True,
|
||||
dest="num",
|
||||
help="How many avatars to add to the script",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--creds",
|
||||
default="../../../build-secrets-git/perf/perfbot_creds.txt",
|
||||
dest="creds",
|
||||
help="Location of the text file containing user credentials",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--viewer",
|
||||
default="C:/Program Files/SecondLife/SecondLifeViewer.exe",
|
||||
dest="viewer",
|
||||
help="Location of the non interactive Viewer build",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cwd",
|
||||
default="",
|
||||
dest="cwd",
|
||||
help="Location of the current working directory to use",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--region",
|
||||
default="Sandbox Cordova",
|
||||
dest="region",
|
||||
help="The SLURL for the Second Life region to visit",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--layout",
|
||||
default="circle",
|
||||
dest="layout",
|
||||
choices={"circle", "square", "spiral"},
|
||||
help="The geometric layout of the avatar destination locations",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sleep",
|
||||
type=int,
|
||||
default=1000,
|
||||
dest="sleep",
|
||||
help="Time to sleep between launches in milliseconds",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
dest="dryrun",
|
||||
help="Dryrun mode - display parameters and script lines but do not start any Viewers",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
gen_niv_script(args)
|
||||
Loading…
Reference in New Issue