# SDPEnv.py
#------------------------------------------------------------------------------
# Copyright (c) Perforce Software, Inc., 2007-2014. All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1 Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE
# SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#------------------------------------------------------------------------------
# Utilities for creating or validating an environment based on a master configuration file
from __future__ import print_function
import os
import os.path
import sys
import subprocess
import socket
import shutil
import glob
import re
import textwrap
import logging
import argparse
from collections import OrderedDict
# Python 2.7/3.3 compatibility.
def python3():
return sys.version_info[0] >= 3
if python3():
from configparser import ConfigParser
from io import StringIO
else:
from ConfigParser import ConfigParser
from StringIO import StringIO
import P4
MODULE_NAME = 'SDPEnv'
DEFAULT_CFG_FILE = 'sdp_master_config.ini'
DEFAULT_LOG_FILE = '%s.log' % MODULE_NAME
DEFAULT_VERBOSITY = 'INFO'
LOGGER_NAME = '%s.py' % MODULE_NAME
DEFAULTS_SECTION = 'Defaults'
# Standard configure lines for an instance - these are arguments to
# p4 configure set <values below>
STANDARD_CONFIGURE_LINES = """db.peeking=2
dm.user.noautocreate=2
dm.user.resetpassword=1
filesys.P4ROOT.min=1G
filesys.depot.min=1G
filesys.P4JOURNAL.min=1G
spec.hashbuckets=99
monitor=1
server=3
net.tcpsize=128k
server.commandlimits=2""".split("\n")
class SDPException(Exception):
"Base exceptions"
pass
class SDPConfigException(SDPException):
"Exceptions in config"
pass
def joinpath(root, *path_elts):
"Deals with drive roots or a full path as the root"
if len(root) > 0 and root[-1] == ":":
return os.path.join(root, os.sep, *path_elts)
else:
return os.path.join(root, *path_elts)
def running_as_administrator():
"Makes sure current process has admin rights"
output = ""
try:
output = subprocess.check_output("net session", universal_newlines=True,
stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
output = e.output
return not re.search(r"Access is denied", output)
def find_record(rec_list, key_field, search_key):
"Returns dictionary found in list of them"
for rec in rec_list:
if rec[key_field].lower() == search_key.lower():
return rec
return None
class SDPInstance(object):
"A single instance"
def __init__(self, config, section):
"Expects a configparser"
self._attrs = {}
def_attrs = "p4name sdp_service_type sdp_hostname sdp_instance sdp_p4port_number sdp_os_username".split()
def_attrs.extend("metadata_root depotdata_root logdata_root".split())
for def_attr in def_attrs:
self._attrs[def_attr] = ""
for item in config.items(section):
self._attrs[item[0]] = item[1]
self._init_dirs()
def __iter__(self):
for attr in self._attrs.keys():
yield self._attrs[attr]
def _init_dirs(self):
"Initialises directory names for this instance"
curr_scriptdir = os.path.dirname(os.path.realpath(__file__))
self._attrs["sdp_common_bin_dir"] = os.path.abspath(os.path.join(curr_scriptdir, '..', 'p4', 'common', 'bin'))
self._attrs["depotdata_dir"] = joinpath(self.depotdata_root, 'p4', self.sdp_instance)
self._attrs["metadata_dir"] = joinpath(self.metadata_root, 'p4', self.sdp_instance)
self._attrs["logdata_dir"] = joinpath(self.logdata_root, 'p4', self.sdp_instance)
self._attrs["bin_dir"] = joinpath(self.depotdata_root, 'p4', self.sdp_instance, 'bin')
self._attrs["common_bin_dir"] = joinpath(self.depotdata_root, 'p4', 'common', 'bin')
self._attrs["root_dir"] = joinpath(self.metadata_root, 'p4', self.sdp_instance, 'root')
self._attrs["logs_dir"] = joinpath(self.logdata_root, 'p4', self.sdp_instance, 'logs')
self._attrs["sdp_config_dir"] = joinpath(self.depotdata_root, 'p4', 'config')
def __getitem__(self, name):
return object.__getattribute__(self, '_attrs').get(name)
def is_current_host(self):
"Checks against current hostname"
return socket.gethostname().lower() == self._attrs["sdp_hostname"].lower()
def __getattribute__(self, name):
"Only allow appropriate attributes"
if name in ["_attrs", "_init_dirs", "get", "is_current_host"]:
return object.__getattribute__(self, name)
else:
if not name in object.__getattribute__(self, '_attrs'):
raise AttributeError("Unknown attribute '%s'" % name)
return object.__getattribute__(self, '_attrs').get(name, "")
class SDPConfig(object):
"The main class to process SDP configurations"
def __init__(self, config_data=None):
self.config = None
self.instances = {}
self.commands = [] # List of command files to run - and their order
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent('''\
NAME
SDPEnv.py
VERSION
1.0.0
DESCRIPTION
Create the environment for an SDP (Server Deployment Package)
EXAMPLES
SDPEnv.py -h
EXIT CODES
Zero indicates normal completion. Non-zero indicates an error.
'''),
epilog="Copyright (c) 2008-2014 Perforce Software, Inc. "
"Provided for use as defined in the Perforce Consulting Services Agreement."
)
parser.add_argument('-y', '--yes', action='store_true',
help="Perform actual changes such as directory creation and file copying.")
parser.add_argument('-c', '--config_filename', default=DEFAULT_CFG_FILE,
help="Config file, relative or absolute path. Default: " + DEFAULT_CFG_FILE)
parser.add_argument('-r', '--report', action='store_true',
help="Report on current configuration")
parser.add_argument('-L', '--log', default=DEFAULT_LOG_FILE,
help="Default: " + DEFAULT_LOG_FILE)
parser.add_argument('-v', '--verbosity',
nargs='?',
const="INFO",
default=DEFAULT_VERBOSITY,
choices=('DEBUG', 'WARNING', 'INFO', 'ERROR', 'FATAL'),
help="Output verbosity level. Default is: " + DEFAULT_VERBOSITY)
self.options = parser.parse_args()
self.logger = logging.getLogger(LOGGER_NAME)
self.logger.setLevel(self.options.verbosity)
h = logging.StreamHandler()
# df = datestamp formatter; bf= basic formatter.
# df = logging.Formatter('%(asctime)s %(levelname)s: %(message)s', datefmt='%Y/%m/%d %H:%M:%S')
bf = logging.Formatter('%(levelname)s: %(message)s')
h.setFormatter(bf)
self.logger.addHandler(h)
self.logger.debug("Command Line Options: %s\n" % self.options)
if not self.options.yes:
self.logger.info("Running in reporting mode: use -y or --yes to perform actions.")
self._read_config(self.options.config_filename, config_data)
def _read_config(self, config_filename, config_data):
"Read the configuration file"
if config_data: # testing
config_file = StringIO(config_data)
else:
if not os.path.exists(config_filename):
raise SDPException("Master config file not found: '%s'" % config_filename)
config_file = open(config_filename)
self.config = ConfigParser()
self.config.readfp(config_file)
self.logger.info("Found the following sections: %s" % self.config.sections())
for section in self.config.sections():
self.instances[section] = SDPInstance(self.config, section)
def isvalid_config(self):
"Check configuration read is valid"
required_options = "p4name sdp_service_type sdp_hostname sdp_instance sdp_p4port_number sdp_os_username".split()
required_options.extend("metadata_root depotdata_root logdata_root".split())
errors = []
for instance_name in self.instances.keys():
missing = []
fields = {}
instance = self.instances[instance_name]
# Check for require fields
for opt in required_options:
if instance[opt] == "":
missing.append(opt)
else:
fields[opt] = instance[opt]
if missing:
errors.append("The following required options are missing '%s' in instance '%s'" % (
", ".join(missing), instance_name))
# Check for numeric fields
field_name = "sdp_p4port_number"
if field_name in fields:
if not instance[field_name].isdigit():
errors.append("%s must be numeric in instance '%s'" % (field_name.upper(), instance_name))
# Check for restricted values
field_name = "sdp_service_type"
if field_name in fields:
valid_service_types = "standard replica forwarding-replica build-server".split()
if not instance[field_name] in valid_service_types:
errors.append("%s must be one of '%s' in instance '%s'" % (field_name.upper(),
", ".join(valid_service_types), instance_name))
if errors:
raise SDPConfigException("\n".join(errors))
return True
def get_master_instance_name(self):
"Assumes valid config"
#TODO - this assumes only one standard section
for instance_name in self.instances:
if self.instances[instance_name]["sdp_service_type"] == "standard":
return instance_name
raise SDPConfigException("No master section found")
def write_master_config_ini(self):
"Write the appropriate configure values"
common_settings = """p4name sdp_os_username sdp_p4serviceuser
metadata_root depotdata_root logdata_root
sdp_p4superuser admin_pass_filename
mailfrom maillist mailhost
python
keepckps keeplogs limit_one_daily_checkpoint""".split()
instance_names = self.instances.keys()
lines = []
lines.append("# Global sdp_config.ini")
lines.append("")
for instance_name in instance_names:
instance = self.instances[instance_name]
lines.append("\n[%s:%s]" % (instance["sdp_instance"], instance["sdp_hostname"]))
lines.append("%s=%s:%s" % ("p4port", instance["sdp_hostname"], instance["sdp_p4port_number"]))
for setting in common_settings:
lines.append("%s=%s" % (setting, instance[setting]))
sdp_config_file = "sdp_config.ini"
self.commands.append(sdp_config_file)
self.logger.info("Config file written: %s" % sdp_config_file)
with open(sdp_config_file, "w") as fh:
for line in lines:
fh.write("%s\n" % line)
def get_configure_bat_contents(self):
"Return the information to be written into configure bat files per instance"
cmd_lines = {} # indexed by instance name
instance_names = self.instances.keys()
master_name = self.get_master_instance_name()
cmd_lines[master_name] = []
master_instance = self.instances[master_name]
p4cmd = "p4 -p %s:%s -u %s" % (master_instance["sdp_hostname"], master_instance["sdp_p4port_number"],
master_instance["sdp_p4superuser"])
p4configurecmd = "%s configure set" % (p4cmd)
path = joinpath(master_instance["depotdata_root"], "p4", master_instance["sdp_instance"],
"checkpoints", "p4_%s" % master_instance["sdp_instance"])
cmd_lines[master_name].append("%s %s#journalPrefix=%s" % (p4configurecmd, master_instance["p4name"], path))
cmd_lines[master_name].append("%s serverid %s" % (p4cmd, master_instance["p4name"]))
log_files = {3: 'errors.csv', 7: 'events.csv', 8: 'integrity.csv'}
for i in log_files.keys():
cmd_lines[master_name].append("%s %s#serverlog.file.%d=%s" % (p4configurecmd, master_instance["p4name"], i,
joinpath(master_instance["logs_dir"], log_files[i])))
cmd_lines[master_name].append("%s %s#serverlog.retain.%d=7" % (p4configurecmd, master_instance["p4name"], i))
for l in STANDARD_CONFIGURE_LINES:
if l.strip():
cmd_lines[master_name].append("%s %s" % (p4configurecmd, l.strip()))
# Now set up all the config variables for replication
for instance_name in [s for s in instance_names if s != master_name]:
instance = self.instances[instance_name]
if not instance["sdp_service_type"] in ["replica", "forwarding-replica", "build-server"]:
continue
path = joinpath(instance["depotdata_root"], "p4", instance["sdp_instance"], "checkpoints",
"p4_%s" % instance["sdp_instance"])
cmd_lines[master_name].append("%s %s#journalPrefix=%s" % (p4configurecmd, instance["p4name"], path))
path = joinpath(instance["depotdata_root"], "p4", instance["sdp_instance"], "p4tickets.txt")
cmd_lines[master_name].append('%s %s#P4PORT=%s' % (p4configurecmd, instance["p4name"], instance["sdp_p4port_number"]))
cmd_lines[master_name].append('%s %s#P4TARGET=%s:%s' % (p4configurecmd, instance["p4name"],
master_instance["sdp_hostname"],
master_instance["sdp_p4port_number"]))
tickets_path = joinpath(instance["depotdata_dir"], "p4tickets.txt")
cmd_lines[master_name].append('%s %s#P4TICKETS=%s' % (p4configurecmd, instance["p4name"], tickets_path))
log_path = joinpath(instance["logs_dir"], "%s.log" % instance["p4name"])
cmd_lines[master_name].append('%s %s#P4LOG=%s' % (p4configurecmd, instance["p4name"], log_path))
cmd_lines[master_name].append('%s %s#server=3' % (p4configurecmd, instance["p4name"]))
cmd_lines[master_name].append('%s "%s#startup.1=pull -i 1"' % (p4configurecmd, instance["p4name"]))
for i in range(2, 6):
cmd_lines[master_name].append('%s "%s#startup.%d=pull -u -i 1"' % (p4configurecmd, instance["p4name"], i))
cmd_lines[master_name].append('%s "%s#lbr.replication=readonly"' % (p4configurecmd, instance["p4name"]))
if instance["sdp_service_type"] in ["replica", "build-server", "forwarding-replica"]:
cmd_lines[master_name].append('%s "%s#db.replication=readonly"' % (p4configurecmd, instance["p4name"]))
if instance["sdp_service_type"] in ["forwarding-replica"]:
cmd_lines[master_name].append('%s "%s#rpl.forward.all=1"' % (p4configurecmd, instance["p4name"]))
cmd_lines[master_name].append('%s "%s#serviceUser=%s"' % (p4configurecmd, instance["p4name"], instance["p4name"]))
if not instance.p4name in cmd_lines:
cmd_lines[instance.p4name] = []
line = "p4 -p %s:%s -u %s serverid %s" % (instance["sdp_hostname"], instance["sdp_p4port_number"],
instance["sdp_p4superuser"], instance["p4name"])
cmd_lines[instance.p4name].append(line)
return cmd_lines
def write_configure_bat_contents(self, cmd_lines):
"Write the appropriate configure bat files for respective instances"
command_files = []
for instance_name in cmd_lines.keys():
command_file = "configure_%s.bat" % (instance_name)
command_files.append(command_file)
with open(command_file, "w") as fh:
for line in cmd_lines[instance_name]:
fh.write("%s\n" % line)
return command_files
def copy_ignore_errors(self, sourcefile, dest):
"Ignore errors when trying to copy file - target exists"
try:
shutil.copy(sourcefile, dest)
except Exception as e:
if not re.search("Permission denied:", str(e)):
self.logger.info("Error copying '%s': %s" % (sourcefile, e))
def get_instance_dirs(self):
"Get a list of instance dirs valid on the current machine"
dirlist = []
instance_names = sorted(self.instances.keys())
for instance_name in instance_names:
instance = self.instances[instance_name]
# Only create dirs when we are on the correct hostname
if not instance.is_current_host():
self.logger.info("Ignoring directories on '%s' for instance '%s'" % (instance["sdp_hostname"], instance["sdp_instance"]))
continue
dirlist.extend([
instance.root_dir,
instance.logdata_dir,
instance.bin_dir,
joinpath(instance.depotdata_dir, 'tmp'),
joinpath(instance.depotdata_dir, 'depots'),
joinpath(instance.depotdata_dir, 'checkpoints'),
joinpath(instance.depotdata_dir, 'ssl'),
instance.common_bin_dir,
joinpath(instance.common_bin_dir, 'triggers'),
joinpath(instance.metadata_dir, 'root', 'save'),
joinpath(instance.metadata_dir, 'offline_db'),
instance.logs_dir,
instance.sdp_config_dir
])
return dirlist
def checkdirs(self, dirlist):
"Check that the directories exist"
pass
def mkdirs(self, dirlist):
"Make all appropriate directories on this machine"
if not self.options.yes:
self.logger.info("The following directories would be created with the -y/--yes flag")
for mdir in dirlist:
self.logger.info(" %s" % mdir)
return
for dir in dirlist:
if not os.path.exists(dir):
self.logger.info("Creating dir '%s'" % dir)
os.makedirs(dir)
instance_names = self.instances.keys()
curr_scriptdir = os.path.dirname(os.path.realpath(__file__))
for instance_name in instance_names:
instance = self.instances[instance_name]
# Only create dirs when we are on the correct hostname
if not instance.is_current_host():
self.logger.info("Ignoring directories on '%s' for instance '%s'" % (instance["sdp_hostname"], instance["sdp_instance"]))
continue
self.logger.info("Copying files on '%s' for instance '%s'" % (instance["sdp_hostname"], instance["sdp_instance"]))
for filename in glob.glob(os.path.join(instance.sdp_common_bin_dir, '*.*')):
self.logger.info("Copying '%s' to '%s'" % (filename, instance.common_bin_dir))
self.copy_ignore_errors(filename, instance.common_bin_dir)
for filename in glob.glob(os.path.join(instance.sdp_common_bin_dir, 'triggers', '*.*')):
self.logger.info("Copying '%s' to '%s'" % (filename, os.path.join(instance.common_bin_dir, 'triggers')))
self.copy_ignore_errors(filename, os.path.join(instance.common_bin_dir, 'triggers'))
for filename in ['daily_backup.bat', 'p4verify.bat', 'replica_status.bat', 'sync_replica.bat',
'weekly_backup.bat', 'weekly_sync_replica.bat']:
self.logger.info("Creating instance bat file '%s'" % (os.path.join(instance.bin_dir, filename)))
self.create_instance_bat(instance.bin_dir, filename, instance['sdp_instance'], instance.common_bin_dir)
self.copy_ignore_errors(os.path.join(curr_scriptdir, 'p4.exe'), instance.bin_dir)
self.copy_ignore_errors(os.path.join(curr_scriptdir, 'p4d.exe'), instance.bin_dir)
self.copy_ignore_errors(os.path.join(curr_scriptdir, 'p4d.exe'), os.path.join(instance.bin_dir, 'p4s.exe'))
shutil.copy(os.path.join(curr_scriptdir, 'sdp_config.ini'), instance.sdp_config_dir)
def bat_file_hostname_guard_lines(self, hostname):
lines = ['@echo off',
'FOR /F "usebackq" %%i IN (`hostname`) DO SET HOSTNAME=%%i',
'if /i "%s" NEQ "%s" (' % ('%HOSTNAME%', hostname),
' echo ERROR: This command file should only be run on machine with hostname "%s"' % (hostname),
' exit /b 1',
')',
'@echo on']
return lines
def get_service_install_cmds(self):
"Configure any services on the current machine"
cmds = {}
instance_names = sorted(self.instances.keys())
for instance_name in instance_names:
instance = self.instances[instance_name]
hostname = instance['sdp_hostname'].lower()
self.logger.info("Creating service configure commands on '%s' for instance '%s' in install_services_%s.bat" % (
hostname, instance["sdp_instance"], hostname))
# Install services
if hostname not in cmds:
cmds[hostname] = []
instsrv = joinpath(instance['depotdata_root'], 'p4', 'common', 'bin', 'instsrv.exe')
cmd = '%s p4_%s "%s"' % (instsrv, instance['sdp_instance'],
os.path.join(instance.bin_dir, 'p4s.exe'))
cmds[hostname].append(cmd)
p4cmd = os.path.join(instance.bin_dir, 'p4.exe')
cmds[hostname].append('%s set -S p4_%s P4ROOT=%s' % (p4cmd, instance['sdp_instance'], instance.root_dir))
cmds[hostname].append('%s set -S p4_%s P4JOURNAL=%s' % (p4cmd, instance['sdp_instance'],
os.path.join(instance.logs_dir, 'journal')))
cmds[hostname].append('%s set -S p4_%s P4NAME=%s' % (p4cmd, instance['sdp_instance'],
instance['p4name']))
cmds[hostname].append('%s set -S p4_%s P4PORT=%s' % (p4cmd, instance['sdp_instance'],
instance['sdp_p4port_number']))
log_path = joinpath(instance["logs_dir"], "%s.log" % instance["p4name"])
cmds[hostname].append('%s set -S p4_%s P4LOG=%s' % (p4cmd, instance['sdp_instance'], log_path))
return cmds
def write_service_install_cmds(self, cmds):
"Configure any services on the various machines"
command_files = []
if not cmds:
return command_files
for instance_name in self.instances:
instance = self.instances[instance_name]
hostname = instance["sdp_hostname"].lower()
if hostname in cmds:
command_file = "install_services_%s.bat" % hostname
if not command_file in command_files:
command_files.append(command_file)
with open(command_file, "w") as fh:
# Write a safeguarding header for specific hostname
lines = self.bat_file_hostname_guard_lines(hostname)
lines.extend(cmds[hostname])
for line in lines:
fh.write("%s\n" % line)
return command_files
def create_instance_bat(self, destdir, fname, instance, common_bin_dir):
"Creates instance specific batch files which call common one"
hdrlines = """::-----------------------------------------------------------------------------
:: Copyright (c) 2012-2014 Perforce Software, Inc. Provided for use as defined in
:: the Perforce Consulting Services Agreement.
::-----------------------------------------------------------------------------
set ORIG_DIR=%CD%
""".split("\n")
with open(os.path.join(destdir, fname), "w") as fh:
for line in hdrlines:
fh.write("%s\n" % line.strip())
fh.write("\n")
fh.write('cd /d "%s"\n' % common_bin_dir)
fh.write('@call %s %s\n' % (fname, instance))
fh.write('cd /d %ORIG_DIR%\n')
# Validate:
# - master server on this host first - then any replica servers
# - server exists (so serverid)
# - server is of correct type
# - adminpass file exists
# - adminpass file is correct
# - any replica users exist as service users
# - replica users have long password timeout
# - configure variables are as expected (warn if different - not always an error)
# - if on replica then P4TICKETS variables
def report_config(self):
"Reports on whether the current configuration is valid - talks to master server"
if not self.options.report:
return
errors = []
info = []
p4 = P4.P4()
m_name = self.get_master_instance_name()
m_instance = self.instances[m_name]
if m_instance.is_current_host():
p4.port = m_instance.sdp_p4port_number
p4.user = m_instance.sdp_p4superuser
p4.connect()
server_defined = False
servers = p4.run_servers()
m_svr = find_record(servers, 'ServerID', m_name)
if not m_svr:
errors.append("Error: no 'server' record defined for instance '%s' - use 'p4 server' to define" %
m_name)
elif m_svr['Services'] != 'standard':
errors.append("Error: 'server' record for instance '%s' must have 'Services: standard'" % m_name)
info.append("Server record exists for master instance '%s'" % m_name)
users = p4.run_users("-a")
for i_name in [inst for inst in self.instances.keys() if inst != m_name]:
instance = self.instances[i_name]
svr = find_record(servers, 'ServerID', i_name)
if not svr:
errors.append("Error: no 'server' record defined for instance '%s' - use 'p4 server' to define" %
i_name)
else:
info.append("Server record exists for instance '%s'" % i_name)
if svr['Services'] != instance.sdp_service_type:
errors.append("Error: 'server' record for instance '%s' defines Services as '%s' - expected '%s'" %
(i_name, svr['Services'],instance.sdp_service_type))
user = find_record(users, 'User', instance.p4name)
if not user:
errors.append("Error: no 'user' record defined for instance '%s' - use 'p4 user' to define a service user" %
i_name)
else:
info.append("User record exists for instance '%s'" % i_name)
if user['Type'] != 'service':
errors.append("Error: 'user' record for instance '%s' defines Type as '%s' - expected '%s'" %
(i_name, user['Type'], 'service'))
p4.disconnect()
print("\nThe following environment values were checked:")
print("\n".join(info))
if errors:
print("\nThe following ERRORS/WARNINGS encountered:")
print("\n".join(errors))
else:
print("\nNo ERRORS/WARNINGS found.")
def process_config(self):
"Process and produce the various files"
self.isvalid_config()
if self.options.yes and not running_as_administrator():
raise SDPException("This action must be run with Administrator rights")
if self.options.report:
self.report_config()
return
self.write_master_config_ini()
dirs = self.get_instance_dirs()
if self.options.yes:
self.mkdirs(dirs)
else:
self.checkdirs(dirs)
cmds = self.get_service_install_cmds()
command_files = self.write_service_install_cmds(cmds)
cmd_lines = self.get_configure_bat_contents()
command_files.extend(self.write_configure_bat_contents(cmd_lines))
print("\n\n")
if self.options.yes:
print("Please run the following commands:")
else:
print("The following commands have been created - but you are in report mode so no directories have been created")
for cmd in command_files:
print(" %s" % cmd)
print("You will also need to seed the replicas from a checkpoint and run the appropriate commands on those machines")
def main():
"Initialization. Process command line argument and initialize logging."
sdpconfig = SDPConfig()
sdpconfig.process_config()
if __name__ == '__main__':
main()
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #2 | 15465 | alan_petersen | Merging using sdp_alan_petersen | ||
| #1 | 10151 | alan_petersen |
Populate //guest/alan_petersen/sdp/... from //guest/perforce_software/sdp/.... |
||
| //guest/perforce_software/sdp/main/Server/setup/SDPEnv.py | |||||
| #1 | 10148 | C. Thomas Tyler | Promoted the Perforce Server Deployment Package to The Workshop. | ||