Ejemplo n.º 1
0
 def GetLanguageCatalog(self, language):
     '''Returns a dictionary from 'MSG_...' to translated string'''
     enthome = E.getEnterpriseHome()
     languagelocal = language.replace('-', '_')
     languagefile = (
         '%s/local/google3/enterprise/i18n/FrontendMessages_%s.xlb' %
         (enthome, languagelocal))
     try:
         msgs = readxlb.Read(languagefile)
     except IOError:
         logging.error('Missing language file %s' % languagefile)
         if language != 'en':
             # Try en language so we can at least replace the tags.
             return self.GetLanguageCatalog('en')
         # Sorry, no language files
         msgs = {}
     # Handle right-to-left languages
     if language in ['ar', 'fa', 'iw', 'ku', 'sd', 'ur', 'yi']:
         msgs['DIR'] = 'rtl'
     else:
         msgs['DIR'] = 'ltr'
     # Encode Unicode messages in UTF-8.  (Adminrunner expects UTF-8 messages.)
     for key in msgs:
         msgs[key] = msgs[key].encode('utf-8')
     # Stick in the language list inside the advanced search page in
     # sorted order.
     msgs["INSERT_LANGUAGE_LIST_IN_ADV_SEARCH"] = self.GenerateLanguageList(
         msgs)
     return msgs
Ejemplo n.º 2
0
 def GetLanguageCatalog(self, language):
   '''Returns a dictionary from 'MSG_...' to translated string'''
   enthome = E.getEnterpriseHome()
   languagelocal = language.replace('-', '_')
   languagefile = ('%s/local/google3/enterprise/i18n/FrontendMessages_%s.xlb' %
                   (enthome, languagelocal))
   try:
     msgs = readxlb.Read(languagefile)
   except IOError:
     logging.error('Missing language file %s' % languagefile)
     if language != 'en':
       # Try en language so we can at least replace the tags.
       return self.GetLanguageCatalog('en')
     # Sorry, no language files
     msgs = {}
   # Handle right-to-left languages
   if language in ['ar', 'fa', 'iw', 'ku', 'sd', 'ur', 'yi']:
     msgs['DIR'] = 'rtl'
   else:
     msgs['DIR'] = 'ltr'
   # Encode Unicode messages in UTF-8.  (Adminrunner expects UTF-8 messages.)
   for key in msgs:
     msgs[key] = msgs[key].encode('utf-8')
   # Stick in the language list inside the advanced search page in
   # sorted order.
   msgs["INSERT_LANGUAGE_LIST_IN_ADV_SEARCH"] = self.GenerateLanguageList(msgs)
   return msgs
Ejemplo n.º 3
0
def GetARClientAndGlobalConfig(master_machine=None):
  if master_machine == None:
    machine_list = ReadSysconfigParam('MACHINES')
    if type(machine_list) == type(""):
      machine_list = map(string.strip, string.split(machine_list, ","))
    ver = install_utilities.extract_version_from_dir(E.getEnterpriseHome())
    master_machine = find_master.FindMasterUsingChubby(ver)
    if master_machine is None:
      raise "Could not find master."

  ar = adminrunner_client.AdminRunnerClient(master_machine, 2100)
  if not ar.IsAlive():
    raise "AdminRunner on machine %s:%d is not alive" % (master_machine, 2100)

  google_config = {}
  ok, response = ar.GetAllParamsIntoDict(google_config)
  if not ok:
    raise "Can not get all global params from %s:%d" % (master_machine, 2100)
  return (ar, google_config)
Ejemplo n.º 4
0
 def run(self):
     # Stop all services on all machines
     ret = None
     for service in self.services_to_stop_:
         logging.info("STATUS: STOP %s service %s on %s" %
                      (service, self.version_, self.machine_))
         func = lambda: self.stop_service(service)
         ret = try_repeatedly(func, success=0)
         if ret:
             self.msg_ = "Error stopping %s on %s." % (service,
                                                       self.machine_)
             logging.error("STATUS: %s" % self.msg_)
             self.err_ = ret
             return
         self.stopped_.extend([service])
     # Change the STATE file
     # TODO(zsyed): Move STATE file to chubby.
     logging.info("STATE: version %s on %s: %s" %
                  (self.version_, self.machine_, self.target_state_))
     if not install_utilities.set_install_state(
             self.machine_, E.getEnterpriseHome(), self.target_state_):
         # Well here is not clear that we want to exit half way ..
         logging.error("ERROR changing state on machine %s. " \
                       "Please rollback and try again" % self.machine_ )
         self.err_ = ret
         self.msg_ = "Cannot change STATE file."
         return
     # Start all services to be started
     for service in self.services_to_start_:
         logging.info("STATUS: START %s service %s on %s" %
                      (service, self.version_, self.machine_))
         func = lambda: self.start_service(service)
         ret = try_repeatedly(func, success=0)
         if ret:
             self.msg_ = "Error starting %s on %s" % (service,
                                                      self.machine_)
             logging.error("STATUS: %s" % self.msg_)
             self.err_ = ret
             return
         self.started_.extend([service])
Ejemplo n.º 5
0
 def run(self):
   # Stop all services on all machines
   ret = None
   for service in self.services_to_stop_:
     logging.info("STATUS: STOP %s service %s on %s" % (
       service, self.version_, self.machine_))
     func = lambda: self.stop_service(service)
     ret = try_repeatedly(func, success=0)
     if ret:
       self.msg_ = "Error stopping %s on %s." % (service, self.machine_)
       logging.error("STATUS: %s" % self.msg_)
       self.err_ = ret
       return
     self.stopped_.extend([service])
   # Change the STATE file
   # TODO(zsyed): Move STATE file to chubby.
   logging.info("STATE: version %s on %s: %s" % (
     self.version_, self.machine_, self.target_state_))
   if not install_utilities.set_install_state(
     self.machine_, E.getEnterpriseHome(), self.target_state_):
     # Well here is not clear that we want to exit half way ..
     logging.error("ERROR changing state on machine %s. " \
                   "Please rollback and try again" % self.machine_ )
     self.err_ = ret
     self.msg_ = "Cannot change STATE file."
     return
   # Start all services to be started
   for service in self.services_to_start_:
     logging.info("STATUS: START %s service %s on %s" % (
         service, self.version_, self.machine_))
     func = lambda: self.start_service(service)
     ret = try_repeatedly(func, success=0)
     if ret:
       self.msg_ = "Error starting %s on %s" % (service, self.machine_)
       logging.error("STATUS: %s" % self.msg_)
       self.err_ = ret
       return
     self.started_.extend([service])
Ejemplo n.º 6
0
from google3.enterprise.legacy.util import C
import threading
from google3.enterprise.core import core_utils
from google3.enterprise.legacy.install import install_utilities
from google3.enterprise.legacy.adminrunner import reset_index

###############################################################################
true  = 1
false = 0

##############################################################################
FLAGS = flags.FLAGS

flags.DEFINE_integer("port", 2100, "")
flags.DEFINE_integer("reset_status_cache_timeout", 60, "")
flags.DEFINE_string("enthome", E.getEnterpriseHome(), "")
flags.DEFINE_string("installstate", None, "")
flags.DEFINE_string("box_keys_dir", None, "")
flags.DEFINE_string("license_keys_dir", None, "")

##############################################################################
def StartupWork(cfg, state):

  try:
    #############################################################################
    # check memory-total
    logging.info("check memory-total")
    if not cfg.CheckMachineMemory():
      logging.fatal("failed to check memory-total")
      return
Ejemplo n.º 7
0
def send(cfg, to, problem, subject, msgText, logSubject):

  # No mails in install mode
  if cfg.getInstallState() == "INSTALL": return

  smtpHost   = cfg.getGlobalParam("SMTP_SERVER")
  fromEmail  = cfg.getGlobalParam("OUTGOING_EMAIL_SENDER")
  allSubject = None

  if not to:
    if problem:
      to = cfg.getGlobalParam("PROBLEM_EMAIL")
    else:
      to = cfg.getGlobalParam("NOTIFICATION_EMAIL")
  # if to is empty, we still go through the whole process, but bail out right
  # before actually sending the email.  we want all the side effects to still
  # happen (logging, testing hooks, etc..)

  # if "*EMAIL" is None, commands.mkarg() will throw a TypeError exception
  if not to:
    to = ""
  else:
    to = string.strip(to)

  if problem:
    allSubject = "%s: %s" % (
      cfg.getGlobalParam("ENT_LICENSE_INFORMATION").get("ENT_BOX_ID", ""),
      cfg.getGlobalParam("EMAIL_PROBLEM_PREFIX")
      )
  else:
    allSubject = "%s: %s" % (
      cfg.getGlobalParam("ENT_LICENSE_INFORMATION").get("ENT_BOX_ID", ""),
      cfg.getGlobalParam("EMAIL_NOTIFICATION_PREFIX")
      )

  allSubject = allSubject + subject

  # Log the subject
  if logSubject:
    logging.info('Sending mail: To: %s; Subject: %s' % (repr(to),
                                                        repr(subject)))
    cfg.writeAdminRunnerOpMsg(subject)

  dateString = time.strftime("%Y/%m/%d %H:%M:%S",
                             E.getLocaltime(time.time()))
  if msgText:
    msgText = msgText + "\n"
  else:
    msgText = ""


  ipAddr = cfg.getGlobalParam("EXTERNAL_WEB_IP")
  body = "%s [%s @%s from %s]" % (msgText, M.MSG_MAIL_AUTOGENERATED, dateString,
                                  ipAddr)

  # if we have a testing hook, call that
  if TEST_MAIL_HANDLER_HOOK != None:
    logging.info("calling TEST_MAIL_HANDLER_HOOK instead of mailnotify")
    to_list = filter(None, map(string.strip, string.split(to, ",")))
    TEST_MAIL_HANDLER_HOOK(smtpHost, to_list, fromEmail, allSubject, body)
    return

  # if to is empty, bail out
  if not (to and smtpHost): return

  # We execute this and not call the function directly because mailnotify
  # uses signal and we might call this from a secondary thread.
  E.execute([E.LOCALHOST],
            ". %s; cd %s/local/google3/enterprise/legacy/util; "\
            "./mailnotify.py %s %s %s %s %s" % (
    cfg.getGlobalParam('ENTERPRISE_BASHRC'),
    E.getEnterpriseHome(),
    commands.mkarg(smtpHost),
    commands.mkarg(allSubject),
    commands.mkarg(fromEmail),
    commands.mkarg(to),
    commands.mkarg(body)), None, 0)
Ejemplo n.º 8
0
def send(cfg, to, problem, subject, msgText, logSubject):

    # No mails in install mode
    if cfg.getInstallState() == "INSTALL": return

    smtpHost = cfg.getGlobalParam("SMTP_SERVER")
    fromEmail = cfg.getGlobalParam("OUTGOING_EMAIL_SENDER")
    allSubject = None

    if not to:
        if problem:
            to = cfg.getGlobalParam("PROBLEM_EMAIL")
        else:
            to = cfg.getGlobalParam("NOTIFICATION_EMAIL")
    # if to is empty, we still go through the whole process, but bail out right
    # before actually sending the email.  we want all the side effects to still
    # happen (logging, testing hooks, etc..)

    # if "*EMAIL" is None, commands.mkarg() will throw a TypeError exception
    if not to:
        to = ""
    else:
        to = string.strip(to)

    if problem:
        allSubject = "%s: %s" % (
            cfg.getGlobalParam("ENT_LICENSE_INFORMATION").get(
                "ENT_BOX_ID", ""), cfg.getGlobalParam("EMAIL_PROBLEM_PREFIX"))
    else:
        allSubject = "%s: %s" % (
            cfg.getGlobalParam("ENT_LICENSE_INFORMATION").get(
                "ENT_BOX_ID",
                ""), cfg.getGlobalParam("EMAIL_NOTIFICATION_PREFIX"))

    allSubject = allSubject + subject

    # Log the subject
    if logSubject:
        logging.info('Sending mail: To: %s; Subject: %s' %
                     (repr(to), repr(subject)))
        cfg.writeAdminRunnerOpMsg(subject)

    dateString = time.strftime("%Y/%m/%d %H:%M:%S",
                               E.getLocaltime(time.time()))
    if msgText:
        msgText = msgText + "\n"
    else:
        msgText = ""

    ipAddr = cfg.getGlobalParam("EXTERNAL_WEB_IP")
    body = "%s [%s @%s from %s]" % (msgText, M.MSG_MAIL_AUTOGENERATED,
                                    dateString, ipAddr)

    # if we have a testing hook, call that
    if TEST_MAIL_HANDLER_HOOK != None:
        logging.info("calling TEST_MAIL_HANDLER_HOOK instead of mailnotify")
        to_list = filter(None, map(string.strip, string.split(to, ",")))
        TEST_MAIL_HANDLER_HOOK(smtpHost, to_list, fromEmail, allSubject, body)
        return

    # if to is empty, bail out
    if not (to and smtpHost): return

    # We execute this and not call the function directly because mailnotify
    # uses signal and we might call this from a secondary thread.
    E.execute([E.LOCALHOST],
              ". %s; cd %s/local/google3/enterprise/legacy/util; "\
              "./mailnotify.py %s %s %s %s %s" % (
      cfg.getGlobalParam('ENTERPRISE_BASHRC'),
      E.getEnterpriseHome(),
      commands.mkarg(smtpHost),
      commands.mkarg(allSubject),
      commands.mkarg(fromEmail),
      commands.mkarg(to),
      commands.mkarg(body)), None, 0)
def doReconfigureNet(config, machines=None, i_am_master=1,
                     force_ntp_reconfig=0):
  """ reconfigure serveriron, DNS, NTPs, iptables, timezone as needed.
  Force NTP server reconfiguration if force_ntp_reconfig=1
  """

  # first we need to reconfigure our external IP address
  ret1 = ret2 = ret4 = ret5 = ret6 = ret8 = 0

  configType = config.var('ENT_CONFIG_TYPE')
  ent_home = E.getEnterpriseHome()
  if not machines:
    machines = config.var('MACHINES')

  # Sanity check
  if not config.var('EXTERNAL_WEB_IP'):
    logging.error('config file is missing EXTERNAL_WEB_IP, probably corrupt')
    raise Exception, 'config file is missing EXTERNAL_WEB_IP, probably corrupt'

  if config.var('USE_DHCP') is None:
    logging.error('config file is missing USE_DHCP, probably corrupt')
    raise Exception, 'config file is missing USE_DHCP, probably corrupt'

  if config.var('DNS_DHCP') is None:
    logging.error('config file is missing DNS_DHCP, probably corrupt')
    raise Exception, 'config file is missing DNS_DHCP, probably corrupt'

  tries = 3 # default for CLUSTER and PILE configuration
  if configType in ["SUPER", "ONEBOX", "MINI", "LITE", "FULL"]:
    tries = 1
    # reconfigure eth0 to dhcp mode
    if config.var('USE_DHCP') == 1:
      ret1 = ExecuteWrapper(
        machines,
        "%s LOCALNET DHCP %s" % (
        C.RECONFIGURE_COMMAND % ent_home,
        config.var('ONEBOX_NETCARD_SETTINGS'),
        ), None, 600, num_tries = tries)
      logging.info("reconfigure eth0 IP to dhcp mode: %s" % ret1)
    else:
      ret1 = ExecuteWrapper(
        machines,
        "%s LOCALNET %s %s %s %s" % (
        C.RECONFIGURE_COMMAND % ent_home,
        config.var('EXTERNAL_WEB_IP'),
        config.var('EXTERNAL_NETMASK'),
        config.var('EXTERNAL_DEFAULT_ROUTE'),
        config.var('ONEBOX_NETCARD_SETTINGS'),
        ), None, 600, num_tries = tries)
      logging.info("reconfigure eth0 IP address: %s" % ret1)
  elif "CLUSTER" == configType:
    # reconfigure serveriron IP address
    cmd = "(sleep 5; %s SERVERIRON %s %s %s %s %s %s %s %s %s >&/dev/null " \
          "</dev/null)" % (
      C.RECONFIGURE_COMMAND % ent_home,
      "%s/local/conf/defaults/" % ent_home,
      commands.mkarg(config.var("EXTERNAL_SWITCH_IP")),
      commands.mkarg(config.var("EXTERNAL_WEB_IP")),
      commands.mkarg(config.var("EXTERNAL_CRAWL_IP")),
      commands.mkarg(config.var("EXTERNAL_NETMASK")),
      commands.mkarg(config.var("EXTERNAL_DEFAULT_ROUTE")),
      commands.mkarg(str(config.var("EXTERNAL_WEB_PORT"))),
      commands.mkarg(str(config.var("SERVERIRON_AUTONEGOTIATION"))),
      commands.mkarg(str(config.var("ENT_ENABLE_EXTERNAL_SSH"))),
      )
    t = threading.Thread(target=E.execute,
                         args=([E.getCrtHostName()], cmd, None, 60))
    t.start()
    logging.info("serveriron IP address reconfigured")


  # we don't want to change ANYTHING on PILE clusters
  if "PILE" != configType:
    # DNS needs to be set everywhere
    dns_server = "\"\""
    dns_searchpath = "\"\""
    if config.var('BOT_DNS_SERVERS') != None:
      dns_server = config.var('BOT_DNS_SERVERS')
    if config.var('DNS_SEARCH_PATH') != None:
      dns_searchpath = config.var('DNS_SEARCH_PATH')
    if config.var('DNS_DHCP') != 1:
      ret8 = ExecuteWrapper(
          machines,
          "%s DNSMODE STATIC" % (
          C.RECONFIGURE_COMMAND % ent_home
          ),  None, 600, num_tries = tries)
      logging.info("setting DNS mode to STATIC: %s" % ret8)
      ret2 = ExecuteWrapper(
        machines,
        "%s DNS %s %s" % (
        C.RECONFIGURE_COMMAND % ent_home,
        commands.mkarg(dns_server),
        commands.mkarg(dns_searchpath),
        ), None, 600, num_tries = tries)
      logging.info("reconfigure DNS: %s" % ret2)
    else:
      ret8 = ExecuteWrapper(
          machines,
          "%s DNSMODE DHCP" % (
          C.RECONFIGURE_COMMAND % ent_home
          ),  None, 600, num_tries = tries)
      logging.info("setting DNS mode to DHCP: %s" % ret8)

    # NTP is special: all machines but the master must set their
    # NTP server to the master, the master to the external one.
    # However, It can take 3 minutes for the stratum level of the master
    # node to be set. Before that, non-master nodes using the master
    # node to do "ntpdate" may return "no server suitable for synchronization
    # found" error.
    # To fix the problem, we just use the external ntp servers for all nodes.
    # Later, periodic script will set the non-master nodes to use the master
    # node. (periodic script will only set it once as long as master does
    # not switch)
    ntpServers = "\"\""
    if config.var('NTP_SERVERS') != None:
      ntp_server_list = copy.copy(config.var('NTP_SERVERS'))
      AddDefaultNTPServer(ntp_server_list)
      ntpServers = string.join(ntp_server_list, ",")

    if i_am_master:
      ret4 = ExecuteWrapper(
        machines,
        "%s NTP %d %s" % (
        C.RECONFIGURE_COMMAND % ent_home,
        force_ntp_reconfig,
        commands.mkarg(ntpServers)),
        None, 600, num_tries = tries)
      logging.info("reconfigure NTP: %s" % ret4)

  # whenever we print dates, we want to include the timezone. Since
  # the timezone may change on the machine (through config interface),
  # and java VM does not pick this change up automatically,
  # we keep track of the timezone here
  ret5 = ExecuteWrapper(
    machines,
    "%s TIMEZONE %s" % (
    C.RECONFIGURE_COMMAND % ent_home,
    commands.mkarg(config.var('TIMEZONE'))),
    None, 600, num_tries = tries)
  logging.info("reconfigure TIMEZONE: %s" % ret5)

  # iptables
  if configType in ["SUPER", "ONEBOX", "LITE", "FULL"]:
    iptables_file = "%s/local/conf/defaults/iptables.onebox" % ent_home
  elif "MINI" == configType:
    iptables_file = "%s/local/conf/defaults/iptables.mini" % ent_home
  elif "CLUSTER" == configType:
    iptables_file = "%s/local/conf/defaults/iptables.cluster" % ent_home
  else:
    iptables_file = "%s/local/conf/defaults/iptables.open" % ent_home
  ret6 = ExecuteWrapper(
    machines,
    "%s IPTABLES %s %s %s" % (
    C.RECONFIGURE_COMMAND % ent_home,
    iptables_file,
    commands.mkarg(str(config.var("ENT_ENABLE_EXTERNAL_SSH"))),
    commands.mkarg(str(config.var("ENT_ENABLE_EXTERNAL_BORGMON"))),
    ), None, 600, num_tries = tries)
  logging.info("reconfigure IPTABLES: %s" % ret6)

  # return value from each reconfigurenet call is:
  # 0 : no change
  # 1 : changed
  # 2+: error (but we report no errors)

  # _our_ return value is if any of them failed
  ret = (ret1 <= 1 and ret2 <= 1 and ret4 <= 1 and
         ret5 <= 1 and ret6 <= 1 and ret8 <= 1)
  return ret
Ejemplo n.º 10
0
def main(argv):
  """ expects: argv[0] to be a machine name, argv[1] be a google_config file
  - copys google_config file from the machine specified into the local machine
    (by calling CopyFile() function)
  - calls ReplicateConfig() - which """
  if len(argv) < 2:
    sys.exit(__doc__)

  machine = argv[0]
  global_file = argv[1]
  global_dir = os.path.dirname(global_file)

  if E.getCrtHostName() == machine:
    logging.info("I do not try to replicate to myself")
    sys.exit(0)

  config = config_factory.ConfigFactory().CreateConfig(global_file)
  if not config.Load():
    sys.exit("ERROR: Cannot read file %s " % global_file)

  file_to_copy = [ C.ETC_SYSCONFIG,
                   global_file,
                   "%s/lic_counter" % global_dir,
                   "%s/lic_counter.bck" % global_dir,
                   "%s/passwd" % global_dir,
                   "/export/hda3/versionmanager/vmanager_passwd",
                   "%s/server.p12" % global_dir
                   ]
  # Sync all the files
  for f in file_to_copy:
    CopyFile(machine, f, production_tmp)

  # sync apache certificate
  CopyFileAsRoot(machine, (ssl_cert.CERT_FILENAME % config.var('ENTERPRISE_HOME')),
                 production_tmp, config)

  # sync private key
  CopyFileAsRoot(machine, (ssl_cert.KEY_FILENAME % config.var('ENTERPRISE_HOME')),
                 production_tmp, config)

  # sync the support request repository directory
  # GRR: ReplicateDirectory(machine, SUPPORTREQUEST_RECORDS_DIR)

  # replicate config including per collection/frontend stuff
  # some dirs in conf don't need to be rsync'ed
  if core_utils.CanRunGSAMaster(E.getCrtHostName()):
    exclude_patterns = ['cmr_working/failure/', 'cmr_working/success/',
                        'cmr_working/statusz/']
  else:
    exclude_patterns = ['cmr_working/', 'cmr/', 'fixer/', 'fixer_cmr/', 'gems']
  ReplicateDirectory(machine, "%s/local/conf/" % config.var('ENTERPRISE_HOME'),
                     exclude_patterns)

  # to replicate per frontend gws stuff (keymatches, gws bad urls)
  ReplicateDirectory(machine, "%s/gws/" % config.var('GOOGLEDATA'))

  # need to adjust NTP if master has changed
  # assumption : this machine is not the master
  if 'PILE' != config.var('ENT_CONFIG_TYPE'):
    ent_home = E.getEnterpriseHome()

    os.system("%s NTP %s" % (C.RECONFIGURE_COMMAND % ent_home, machine))

    # also make sure DNS is up to date
    os.system("%s DNS %s %s" % (
      C.RECONFIGURE_COMMAND % ent_home,
      config.var('BOT_DNS_SERVERS'),
      config.var('DNS_SEARCH_PATH')))
Ejemplo n.º 11
0
def main(argv):
    """ expects: argv[0] to be a machine name, argv[1] be a google_config file
  - copys google_config file from the machine specified into the local machine
    (by calling CopyFile() function)
  - calls ReplicateConfig() - which """
    if len(argv) < 2:
        sys.exit(__doc__)

    machine = argv[0]
    global_file = argv[1]
    global_dir = os.path.dirname(global_file)

    if E.getCrtHostName() == machine:
        logging.info("I do not try to replicate to myself")
        sys.exit(0)

    config = config_factory.ConfigFactory().CreateConfig(global_file)
    if not config.Load():
        sys.exit("ERROR: Cannot read file %s " % global_file)

    file_to_copy = [
        C.ETC_SYSCONFIG, global_file,
        "%s/lic_counter" % global_dir,
        "%s/lic_counter.bck" % global_dir,
        "%s/passwd" % global_dir,
        "/export/hda3/versionmanager/vmanager_passwd",
        "%s/server.p12" % global_dir
    ]
    # Sync all the files
    for f in file_to_copy:
        CopyFile(machine, f, production_tmp)

    # sync apache certificate
    CopyFileAsRoot(machine,
                   (ssl_cert.CERT_FILENAME % config.var('ENTERPRISE_HOME')),
                   production_tmp, config)

    # sync private key
    CopyFileAsRoot(machine,
                   (ssl_cert.KEY_FILENAME % config.var('ENTERPRISE_HOME')),
                   production_tmp, config)

    # sync the support request repository directory
    # GRR: ReplicateDirectory(machine, SUPPORTREQUEST_RECORDS_DIR)

    # replicate config including per collection/frontend stuff
    # some dirs in conf don't need to be rsync'ed
    if core_utils.CanRunGSAMaster(E.getCrtHostName()):
        exclude_patterns = [
            'cmr_working/failure/', 'cmr_working/success/',
            'cmr_working/statusz/'
        ]
    else:
        exclude_patterns = [
            'cmr_working/', 'cmr/', 'fixer/', 'fixer_cmr/', 'gems'
        ]
    ReplicateDirectory(machine,
                       "%s/local/conf/" % config.var('ENTERPRISE_HOME'),
                       exclude_patterns)

    # to replicate per frontend gws stuff (keymatches, gws bad urls)
    ReplicateDirectory(machine, "%s/gws/" % config.var('GOOGLEDATA'))

    # need to adjust NTP if master has changed
    # assumption : this machine is not the master
    if 'PILE' != config.var('ENT_CONFIG_TYPE'):
        ent_home = E.getEnterpriseHome()

        os.system("%s NTP %s" % (C.RECONFIGURE_COMMAND % ent_home, machine))

        # also make sure DNS is up to date
        os.system(
            "%s DNS %s %s" %
            (C.RECONFIGURE_COMMAND % ent_home, config.var('BOT_DNS_SERVERS'),
             config.var('DNS_SEARCH_PATH')))