Example #1
0
def Main():
    """Main routine.

  """
    opts = ParseOptions()

    utils.SetupToolLogging(opts.debug, opts.verbose)

    try:
        getent = runtime.GetEnts()

        data = common.LoadData(sys.stdin.read(), SetupError)

        cluster_name = common.VerifyClusterName(data, SetupError,
                                                constants.NDS_CLUSTER_NAME)
        cert_pem = common.VerifyCertificateStrong(data, SetupError)
        ssdata = VerifySsconf(data, cluster_name)

        logging.info("Writing ssconf files ...")
        ssconf.WriteSsconfFiles(ssdata, dry_run=opts.dry_run)

        logging.info("Writing node daemon certificate ...")
        utils.WriteFile(pathutils.NODED_CERT_FILE,
                        data=cert_pem,
                        mode=pathutils.NODED_CERT_MODE,
                        uid=getent.masterd_uid,
                        gid=getent.masterd_gid,
                        dry_run=opts.dry_run)
        common.GenerateClientCertificate(data, SetupError)

        if (data.get(constants.NDS_START_NODE_DAEMON) and  # pylint: disable=E1103
                not opts.dry_run):
            logging.info("Restarting node daemon ...")

            stop_cmd = "%s stop-all" % pathutils.DAEMON_UTIL
            noded_cmd = "%s start %s" % (pathutils.DAEMON_UTIL,
                                         constants.NODED)
            mond_cmd = ""
            if constants.ENABLE_MOND:
                mond_cmd = "%s start %s" % (pathutils.DAEMON_UTIL,
                                            constants.MOND)

            cmd = "; ".join([stop_cmd, noded_cmd, mond_cmd])

            result = utils.RunCmd(cmd, interactive=True)
            if result.failed:
                raise SetupError(
                    "Could not start the node daemons, command '%s'"
                    " failed: %s" % (result.cmd, result.fail_reason))

        logging.info("Node daemon successfully configured")
    except Exception as err:  # pylint: disable=W0703
        logging.debug("Caught unhandled exception", exc_info=True)

        (retcode, message) = cli.FormatError(err)
        logging.error(message)

        return retcode
    else:
        return constants.EXIT_SUCCESS
Example #2
0
def Main():
    """Main routine.

  """
    (opts, args) = ParseOptions()

    utils.SetupToolLogging(opts.debug, opts.verbose)

    if args:
        logging.error("No arguments are expected")
        return constants.EXIT_FAILURE

    if opts.full_run:
        logging.info("Running in full mode")

    getent = runtime.GetEnts()

    try:
        for path in GetPaths():
            ProcessPath(path)

        if opts.full_run:
            RecursiveEnsure(pathutils.JOB_QUEUE_ARCHIVE_DIR,
                            getent.masterd_uid, getent.daemons_gid, 0750,
                            constants.JOB_QUEUE_FILES_PERMS)
    except errors.GenericError, err:
        logging.error("An error occurred while setting permissions: %s", err)
        return constants.EXIT_FAILURE
Example #3
0
    def __init__(self):
        """Constructs a new Mainloop instance.

    """
        self._signal_wait = []
        self.scheduler = AsyncoreScheduler(time.time)

        # Resolve uid/gids used
        runtime.GetEnts()
Example #4
0
def SetDrainFlag(drain_flag):
  """Sets the drain flag for the queue.

  @type drain_flag: boolean
  @param drain_flag: Whether to set or unset the drain flag
  @attention: This function should only called the current holder of the queue
    lock

  """
  getents = runtime.GetEnts()

  if drain_flag:
    utils.WriteFile(pathutils.JOB_QUEUE_DRAIN_FILE, data="",
                    uid=getents.masterd_uid, gid=getents.daemons_gid,
                    mode=constants.JOB_QUEUE_FILES_PERMS)
  else:
    utils.RemoveFile(pathutils.JOB_QUEUE_DRAIN_FILE)

  assert (not drain_flag) ^ CheckDrainFlag()
Example #5
0
def _VerifyDaemonUser(daemon_name):
    """Verifies the process uid matches the configured uid.

  This method verifies that a daemon is started as the user it is
  intended to be run

  @param daemon_name: The name of daemon to be started
  @return: A tuple with the first item indicating success or not,
           the second item current uid and third with expected uid

  """
    getents = runtime.GetEnts()
    running_uid = os.getuid()
    daemon_uids = {
        constants.MASTERD: getents.masterd_uid,
        constants.RAPI: getents.rapi_uid,
        constants.NODED: getents.noded_uid,
        constants.CONFD: getents.confd_uid,
    }
    assert daemon_name in daemon_uids, "Invalid daemon %s" % daemon_name

    return (daemon_uids[daemon_name] == running_uid, running_uid,
            daemon_uids[daemon_name])
Example #6
0
def InitAndVerifyQueue(must_lock):
    """Open and lock job queue.

  If necessary, the queue is automatically initialized.

  @type must_lock: bool
  @param must_lock: Whether an exclusive lock must be held.
  @rtype: utils.FileLock
  @return: Lock object for the queue. This can be used to change the
           locking mode.

  """
    getents = runtime.GetEnts()

    # Lock queue
    queue_lock = utils.FileLock.Open(pathutils.JOB_QUEUE_LOCK_FILE)
    try:
        # The queue needs to be locked in exclusive mode to write to the serial and
        # version files.
        if must_lock:
            queue_lock.Exclusive(blocking=True)
            holding_lock = True
        else:
            try:
                queue_lock.Exclusive(blocking=False)
                holding_lock = True
            except errors.LockError:
                # Ignore errors and assume the process keeping the lock checked
                # everything.
                holding_lock = False

        if holding_lock:
            # Verify version
            version = ReadVersion()
            if version is None:
                # Write new version file
                utils.WriteFile(pathutils.JOB_QUEUE_VERSION_FILE,
                                uid=getents.masterd_uid,
                                gid=getents.daemons_gid,
                                mode=constants.JOB_QUEUE_FILES_PERMS,
                                data="%s\n" % constants.JOB_QUEUE_VERSION)

                # Read again
                version = ReadVersion()

            if version != constants.JOB_QUEUE_VERSION:
                raise errors.JobQueueError(
                    "Found job queue version %s, expected %s", version,
                    constants.JOB_QUEUE_VERSION)

            serial = ReadSerial()
            if serial is None:
                # Write new serial file
                utils.WriteFile(pathutils.JOB_QUEUE_SERIAL_FILE,
                                uid=getents.masterd_uid,
                                gid=getents.daemons_gid,
                                mode=constants.JOB_QUEUE_FILES_PERMS,
                                data="%s\n" % 0)

                # Read again
                serial = ReadSerial()

            if serial is None:
                # There must be a serious problem
                raise errors.JobQueueError("Can't read/parse the job queue"
                                           " serial file")

            if not must_lock:
                # There's no need for more error handling. Closing the lock
                # file below in case of an error will unlock it anyway.
                queue_lock.Unlock()

    except:
        queue_lock.Close()
        raise

    return queue_lock
        alloc_script = utils.FindFile(default_iallocator,
                                      constants.IALLOCATOR_SEARCH_PATH,
                                      os.path.isfile)
        if alloc_script is None:
            raise errors.OpPrereqError(
                "Invalid default iallocator script '%s'"
                " specified" % default_iallocator, errors.ECODE_INVAL)
    else:
        # default to htools
        if utils.FindFile(constants.IALLOC_HAIL,
                          constants.IALLOCATOR_SEARCH_PATH, os.path.isfile):
            default_iallocator = constants.IALLOC_HAIL

    # check if we have all the users we need
    try:
        runtime.GetEnts()
    except errors.ConfigurationError, err:
        raise errors.OpPrereqError(
            "Required system user/group missing: %s" % err,
            errors.ECODE_ENVIRON)

    candidate_certs = {}

    now = time.time()

    if compression_tools is not None:
        cluster.CheckCompressionTools(compression_tools)

    initial_dc_config = dict(active=True,
                             interval=int(constants.MOND_TIME_INTERVAL * 1e6))
    data_collectors = dict((name, initial_dc_config.copy())
Example #8
0
def GetPaths():
    """Returns a tuple of path objects to process.

  """
    getent = runtime.GetEnts()
    masterd_log = constants.DAEMONS_LOGFILES[constants.MASTERD]
    noded_log = constants.DAEMONS_LOGFILES[constants.NODED]
    confd_log = constants.DAEMONS_LOGFILES[constants.CONFD]
    luxid_log = constants.DAEMONS_LOGFILES[constants.LUXID]
    rapi_log = constants.DAEMONS_LOGFILES[constants.RAPI]
    mond_log = constants.DAEMONS_LOGFILES[constants.MOND]

    rapi_dir = os.path.join(pathutils.DATA_DIR, "rapi")
    cleaner_log_dir = os.path.join(pathutils.LOG_DIR, "cleaner")
    master_cleaner_log_dir = os.path.join(pathutils.LOG_DIR, "master-cleaner")

    # A note on the ordering: The parent directory (type C{DIR}) must always be
    # listed before files (type C{FILE}) in that directory. Once the directory is
    # set, only files directly in that directory can be listed.
    paths = [
        (pathutils.DATA_DIR, DIR, 0755, getent.masterd_uid,
         getent.masterd_gid),
        (pathutils.CLUSTER_DOMAIN_SECRET_FILE, FILE, 0640, getent.masterd_uid,
         getent.masterd_gid, False),
        (pathutils.CLUSTER_CONF_FILE, FILE, 0640, getent.masterd_uid,
         getent.confd_gid, False),
        (pathutils.CONFD_HMAC_KEY, FILE, 0440, getent.confd_uid,
         getent.masterd_gid, False),
        (pathutils.SSH_KNOWN_HOSTS_FILE, FILE, 0644, getent.masterd_uid,
         getent.masterd_gid, False),
        (pathutils.RAPI_CERT_FILE, FILE, 0440, getent.rapi_uid,
         getent.masterd_gid, False),
        (pathutils.SPICE_CERT_FILE, FILE, 0440, getent.noded_uid,
         getent.masterd_gid, False),
        (pathutils.SPICE_CACERT_FILE, FILE, 0440, getent.noded_uid,
         getent.masterd_gid, False),
        (pathutils.NODED_CERT_FILE, FILE, pathutils.NODED_CERT_MODE,
         getent.masterd_uid, getent.masterd_gid, False),
        (pathutils.NODED_CLIENT_CERT_FILE, FILE, pathutils.NODED_CERT_MODE,
         getent.masterd_uid, getent.masterd_gid, False),
        (pathutils.WATCHER_PAUSEFILE, FILE, 0644, getent.masterd_uid,
         getent.masterd_gid, False),
    ]

    ss = ssconf.SimpleStore()
    for ss_path in ss.GetFileList():
        paths.append((ss_path, FILE, constants.SS_FILE_PERMS, getent.noded_uid,
                      getent.noded_gid, False))

    paths.extend([
        (pathutils.QUEUE_DIR, DIR, 0750, getent.masterd_uid,
         getent.daemons_gid),
        (pathutils.QUEUE_DIR, QUEUE_DIR, constants.JOB_QUEUE_FILES_PERMS,
         getent.masterd_uid, getent.daemons_gid),
        (pathutils.JOB_QUEUE_DRAIN_FILE, FILE, 0644, getent.masterd_uid,
         getent.daemons_gid, False),
        (pathutils.JOB_QUEUE_LOCK_FILE, FILE, constants.JOB_QUEUE_FILES_PERMS,
         getent.masterd_uid, getent.daemons_gid, False),
        (pathutils.JOB_QUEUE_SERIAL_FILE, FILE,
         constants.JOB_QUEUE_FILES_PERMS, getent.masterd_uid,
         getent.daemons_gid, False),
        (pathutils.JOB_QUEUE_VERSION_FILE, FILE,
         constants.JOB_QUEUE_FILES_PERMS, getent.masterd_uid,
         getent.daemons_gid, False),
        (pathutils.JOB_QUEUE_ARCHIVE_DIR, DIR, 0750, getent.masterd_uid,
         getent.daemons_gid),
        (rapi_dir, DIR, 0750, getent.rapi_uid, getent.masterd_gid),
        (pathutils.RAPI_USERS_FILE, FILE, 0640, getent.rapi_uid,
         getent.masterd_gid, False),
        (pathutils.RUN_DIR, DIR, 0775, getent.masterd_uid, getent.daemons_gid),
        (pathutils.SOCKET_DIR, DIR, 0770, getent.masterd_uid,
         getent.daemons_gid),
        (pathutils.MASTER_SOCKET, FILE, 0660, getent.masterd_uid,
         getent.daemons_gid, False),
        (pathutils.QUERY_SOCKET, FILE, 0660, getent.luxid_uid,
         getent.daemons_gid, False),
        (pathutils.BDEV_CACHE_DIR, DIR, 0755, getent.noded_uid,
         getent.masterd_gid),
        (pathutils.UIDPOOL_LOCKDIR, DIR, 0750, getent.noded_uid,
         getent.masterd_gid),
        (pathutils.DISK_LINKS_DIR, DIR, 0755, getent.noded_uid,
         getent.masterd_gid),
        (pathutils.CRYPTO_KEYS_DIR, DIR, 0700, getent.noded_uid,
         getent.masterd_gid),
        (pathutils.IMPORT_EXPORT_DIR, DIR, 0755, getent.noded_uid,
         getent.masterd_gid),
        (pathutils.LOG_DIR, DIR, 0770, getent.masterd_uid, getent.daemons_gid),
        (masterd_log, FILE, 0600, getent.masterd_uid, getent.masterd_gid,
         False),
        (confd_log, FILE, 0600, getent.confd_uid, getent.masterd_gid, False),
        (luxid_log, FILE, 0600, getent.luxid_uid, getent.masterd_gid, False),
        (noded_log, FILE, 0600, getent.noded_uid, getent.masterd_gid, False),
        (rapi_log, FILE, 0600, getent.rapi_uid, getent.masterd_gid, False),
        (mond_log, FILE, 0600, getent.mond_uid, getent.masterd_gid, False),
        (pathutils.LOG_OS_DIR, DIR, 0750, getent.noded_uid,
         getent.daemons_gid),
        (pathutils.LOG_XEN_DIR, DIR, 0750, getent.noded_uid,
         getent.daemons_gid),
        (cleaner_log_dir, DIR, 0750, getent.noded_uid, getent.noded_gid),
        (master_cleaner_log_dir, DIR, 0750, getent.masterd_uid,
         getent.masterd_gid),
        (pathutils.INSTANCE_REASON_DIR, DIR, 0755, getent.noded_uid,
         getent.noded_gid),
        (pathutils.LIVELOCK_DIR, DIR, 0750, getent.masterd_uid,
         getent.daemons_gid),
        (pathutils.LUXID_MESSAGE_DIR, DIR, 0750, getent.masterd_uid,
         getent.daemons_gid),
    ])

    return paths
Example #9
0
def InitCluster(
        cluster_name,
        mac_prefix,  # pylint: disable=R0913, R0914
        master_netmask,
        master_netdev,
        file_storage_dir,
        shared_file_storage_dir,
        gluster_storage_dir,
        candidate_pool_size,
        ssh_key_type,
        ssh_key_bits,
        secondary_ip=None,
        vg_name=None,
        beparams=None,
        nicparams=None,
        ndparams=None,
        hvparams=None,
        diskparams=None,
        enabled_hypervisors=None,
        modify_etc_hosts=True,
        modify_ssh_setup=True,
        maintain_node_health=False,
        drbd_helper=None,
        uid_pool=None,
        default_iallocator=None,
        default_iallocator_params=None,
        primary_ip_version=None,
        ipolicy=None,
        prealloc_wipe_disks=False,
        use_external_mip_script=False,
        hv_state=None,
        disk_state=None,
        enabled_disk_templates=None,
        install_image=None,
        zeroing_image=None,
        compression_tools=None,
        enabled_user_shutdown=False):
    """Initialise the cluster.

  @type candidate_pool_size: int
  @param candidate_pool_size: master candidate pool size

  @type enabled_disk_templates: list of string
  @param enabled_disk_templates: list of disk_templates to be used in this
    cluster

  @type enabled_user_shutdown: bool
  @param enabled_user_shutdown: whether user shutdown is enabled cluster
                                wide

  """
    # TODO: complete the docstring
    if config.ConfigWriter.IsCluster():
        raise errors.OpPrereqError("Cluster is already initialised",
                                   errors.ECODE_STATE)

    data_dir = vcluster.AddNodePrefix(pathutils.DATA_DIR)
    queue_dir = vcluster.AddNodePrefix(pathutils.QUEUE_DIR)
    archive_dir = vcluster.AddNodePrefix(pathutils.JOB_QUEUE_ARCHIVE_DIR)
    for ddir in [queue_dir, data_dir, archive_dir]:
        if os.path.isdir(ddir):
            for entry in os.listdir(ddir):
                if not os.path.isdir(os.path.join(ddir, entry)):
                    raise errors.OpPrereqError(
                        "%s contains non-directory entries like %s. Remove left-overs of an"
                        " old cluster before initialising a new one" %
                        (ddir, entry), errors.ECODE_STATE)

    if not enabled_hypervisors:
        raise errors.OpPrereqError(
            "Enabled hypervisors list must contain at"
            " least one member", errors.ECODE_INVAL)
    invalid_hvs = set(enabled_hypervisors) - constants.HYPER_TYPES
    if invalid_hvs:
        raise errors.OpPrereqError(
            "Enabled hypervisors contains invalid"
            " entries: %s" % invalid_hvs, errors.ECODE_INVAL)

    _InitCheckEnabledDiskTemplates(enabled_disk_templates)

    try:
        ipcls = netutils.IPAddress.GetClassFromIpVersion(primary_ip_version)
    except errors.ProgrammerError:
        raise errors.OpPrereqError(
            "Invalid primary ip version: %d." % primary_ip_version,
            errors.ECODE_INVAL)

    hostname = netutils.GetHostname(family=ipcls.family)
    if not ipcls.IsValid(hostname.ip):
        raise errors.OpPrereqError(
            "This host's IP (%s) is not a valid IPv%d"
            " address." % (hostname.ip, primary_ip_version),
            errors.ECODE_INVAL)

    if ipcls.IsLoopback(hostname.ip):
        raise errors.OpPrereqError(
            "This host's IP (%s) resolves to a loopback"
            " address. Please fix DNS or %s." %
            (hostname.ip, pathutils.ETC_HOSTS), errors.ECODE_ENVIRON)

    if not ipcls.Own(hostname.ip):
        raise errors.OpPrereqError(
            "Inconsistency: this host's name resolves"
            " to %s,\nbut this ip address does not"
            " belong to this host" % hostname.ip, errors.ECODE_ENVIRON)

    clustername = netutils.GetHostname(name=cluster_name, family=ipcls.family)

    if netutils.TcpPing(clustername.ip,
                        constants.DEFAULT_NODED_PORT,
                        timeout=5):
        raise errors.OpPrereqError("Cluster IP already active",
                                   errors.ECODE_NOTUNIQUE)

    if not secondary_ip:
        if primary_ip_version == constants.IP6_VERSION:
            raise errors.OpPrereqError(
                "When using a IPv6 primary address, a valid"
                " IPv4 address must be given as secondary", errors.ECODE_INVAL)
        secondary_ip = hostname.ip

    if not netutils.IP4Address.IsValid(secondary_ip):
        raise errors.OpPrereqError(
            "Secondary IP address (%s) has to be a valid"
            " IPv4 address." % secondary_ip, errors.ECODE_INVAL)

    if not netutils.IP4Address.Own(secondary_ip):
        raise errors.OpPrereqError(
            "You gave %s as secondary IP,"
            " but it does not belong to this host." % secondary_ip,
            errors.ECODE_ENVIRON)

    if master_netmask is not None:
        if not ipcls.ValidateNetmask(master_netmask):
            raise errors.OpPrereqError(
                "CIDR netmask (%s) not valid for IPv%s " %
                (master_netmask, primary_ip_version), errors.ECODE_INVAL)
    else:
        master_netmask = ipcls.iplen

    if vg_name:
        # Check if volume group is valid
        vgstatus = utils.CheckVolumeGroupSize(utils.ListVolumeGroups(),
                                              vg_name, constants.MIN_VG_SIZE)
        if vgstatus:
            raise errors.OpPrereqError("Error: %s" % vgstatus,
                                       errors.ECODE_INVAL)

    drbd_enabled = constants.DT_DRBD8 in enabled_disk_templates
    _InitCheckDrbdHelper(drbd_helper, drbd_enabled)

    logging.debug("Stopping daemons (if any are running)")
    result = utils.RunCmd([pathutils.DAEMON_UTIL, "stop-all"])
    if result.failed:
        raise errors.OpExecError("Could not stop daemons, command %s"
                                 " had exitcode %s and error '%s'" %
                                 (result.cmd, result.exit_code, result.output))

    file_storage_dir = _PrepareFileStorage(enabled_disk_templates,
                                           file_storage_dir)
    shared_file_storage_dir = _PrepareSharedFileStorage(
        enabled_disk_templates, shared_file_storage_dir)
    gluster_storage_dir = _PrepareGlusterStorage(enabled_disk_templates,
                                                 gluster_storage_dir)

    if not re.match("^[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}$", mac_prefix):
        raise errors.OpPrereqError(
            "Invalid mac prefix given '%s'" % mac_prefix, errors.ECODE_INVAL)

    if not nicparams.get('mode', None) == constants.NIC_MODE_OVS:
        # Do not do this check if mode=openvswitch, since the openvswitch is not
        # created yet
        result = utils.RunCmd(["ip", "link", "show", "dev", master_netdev])
        if result.failed:
            raise errors.OpPrereqError(
                "Invalid master netdev given (%s): '%s'" %
                (master_netdev, result.output.strip()), errors.ECODE_INVAL)

    dirs = [(pathutils.RUN_DIR, constants.RUN_DIRS_MODE)]
    utils.EnsureDirs(dirs)

    objects.UpgradeBeParams(beparams)
    utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
    utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)

    objects.NIC.CheckParameterSyntax(nicparams)

    full_ipolicy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, ipolicy)
    _RestrictIpolicyToEnabledDiskTemplates(full_ipolicy,
                                           enabled_disk_templates)

    if ndparams is not None:
        utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
    else:
        ndparams = dict(constants.NDC_DEFAULTS)

    # This is ugly, as we modify the dict itself
    # FIXME: Make utils.ForceDictType pure functional or write a wrapper
    # around it
    if hv_state:
        for hvname, hvs_data in hv_state.items():
            utils.ForceDictType(hvs_data, constants.HVSTS_PARAMETER_TYPES)
            hv_state[hvname] = objects.Cluster.SimpleFillHvState(hvs_data)
    else:
        hv_state = dict((hvname, constants.HVST_DEFAULTS)
                        for hvname in enabled_hypervisors)

    # FIXME: disk_state has no default values yet
    if disk_state:
        for storage, ds_data in disk_state.items():
            if storage not in constants.DS_VALID_TYPES:
                raise errors.OpPrereqError(
                    "Invalid storage type in disk state: %s" % storage,
                    errors.ECODE_INVAL)
            for ds_name, state in ds_data.items():
                utils.ForceDictType(state, constants.DSS_PARAMETER_TYPES)
                ds_data[ds_name] = objects.Cluster.SimpleFillDiskState(state)

    # hvparams is a mapping of hypervisor->hvparams dict
    for hv_name, hv_params in hvparams.items():
        utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
        hv_class = hypervisor.GetHypervisor(hv_name)
        hv_class.CheckParameterSyntax(hv_params)

    # diskparams is a mapping of disk-template->diskparams dict
    for template, dt_params in diskparams.items():
        param_keys = set(dt_params.keys())
        default_param_keys = set(constants.DISK_DT_DEFAULTS[template].keys())
        if param_keys > default_param_keys:
            unknown_params = param_keys - default_param_keys
            raise errors.OpPrereqError(
                "Invalid parameters for disk template %s:"
                " %s" % (template, utils.CommaJoin(unknown_params)),
                errors.ECODE_INVAL)
        utils.ForceDictType(dt_params, constants.DISK_DT_TYPES)
        if template == constants.DT_DRBD8 and vg_name is not None:
            # The default METAVG value is equal to the VG name set at init time,
            # if provided
            dt_params[constants.DRBD_DEFAULT_METAVG] = vg_name

    try:
        utils.VerifyDictOptions(diskparams, constants.DISK_DT_DEFAULTS)
    except errors.OpPrereqError as err:
        raise errors.OpPrereqError("While verify diskparam options: %s" % err,
                                   errors.ECODE_INVAL)

    # set up ssh config and /etc/hosts
    rsa_sshkey = ""
    dsa_sshkey = ""
    if os.path.isfile(pathutils.SSH_HOST_RSA_PUB):
        sshline = utils.ReadFile(pathutils.SSH_HOST_RSA_PUB)
        rsa_sshkey = sshline.split(" ")[1]
    if os.path.isfile(pathutils.SSH_HOST_DSA_PUB):
        sshline = utils.ReadFile(pathutils.SSH_HOST_DSA_PUB)
        dsa_sshkey = sshline.split(" ")[1]
    if not rsa_sshkey and not dsa_sshkey:
        raise errors.OpPrereqError("Failed to find SSH public keys",
                                   errors.ECODE_ENVIRON)

    if modify_etc_hosts:
        utils.AddHostToEtcHosts(hostname.name, hostname.ip)

    if modify_ssh_setup:
        ssh.InitSSHSetup(ssh_key_type, ssh_key_bits)

    if default_iallocator is not None:
        alloc_script = utils.FindFile(default_iallocator,
                                      constants.IALLOCATOR_SEARCH_PATH,
                                      os.path.isfile)
        if alloc_script is None:
            raise errors.OpPrereqError(
                "Invalid default iallocator script '%s'"
                " specified" % default_iallocator, errors.ECODE_INVAL)
    else:
        # default to htools
        if utils.FindFile(constants.IALLOC_HAIL,
                          constants.IALLOCATOR_SEARCH_PATH, os.path.isfile):
            default_iallocator = constants.IALLOC_HAIL

    # check if we have all the users we need
    try:
        runtime.GetEnts()
    except errors.ConfigurationError as err:
        raise errors.OpPrereqError(
            "Required system user/group missing: %s" % err,
            errors.ECODE_ENVIRON)

    candidate_certs = {}

    now = time.time()

    if compression_tools is not None:
        cluster.CheckCompressionTools(compression_tools)

    initial_dc_config = dict(active=True,
                             interval=int(constants.MOND_TIME_INTERVAL * 1e6))
    data_collectors = dict((name, initial_dc_config.copy())
                           for name in constants.DATA_COLLECTOR_NAMES)

    # init of cluster config file
    cluster_config = objects.Cluster(
        serial_no=1,
        rsahostkeypub=rsa_sshkey,
        dsahostkeypub=dsa_sshkey,
        highest_used_port=(constants.FIRST_DRBD_PORT - 1),
        mac_prefix=mac_prefix,
        volume_group_name=vg_name,
        tcpudp_port_pool=set(),
        master_ip=clustername.ip,
        master_netmask=master_netmask,
        master_netdev=master_netdev,
        cluster_name=clustername.name,
        file_storage_dir=file_storage_dir,
        shared_file_storage_dir=shared_file_storage_dir,
        gluster_storage_dir=gluster_storage_dir,
        enabled_hypervisors=enabled_hypervisors,
        beparams={constants.PP_DEFAULT: beparams},
        nicparams={constants.PP_DEFAULT: nicparams},
        ndparams=ndparams,
        hvparams=hvparams,
        diskparams=diskparams,
        candidate_pool_size=candidate_pool_size,
        modify_etc_hosts=modify_etc_hosts,
        modify_ssh_setup=modify_ssh_setup,
        uid_pool=uid_pool,
        ctime=now,
        mtime=now,
        maintain_node_health=maintain_node_health,
        data_collectors=data_collectors,
        drbd_usermode_helper=drbd_helper,
        default_iallocator=default_iallocator,
        default_iallocator_params=default_iallocator_params,
        primary_ip_family=ipcls.family,
        prealloc_wipe_disks=prealloc_wipe_disks,
        use_external_mip_script=use_external_mip_script,
        ipolicy=full_ipolicy,
        hv_state_static=hv_state,
        disk_state_static=disk_state,
        enabled_disk_templates=enabled_disk_templates,
        candidate_certs=candidate_certs,
        osparams={},
        osparams_private_cluster={},
        install_image=install_image,
        zeroing_image=zeroing_image,
        compression_tools=compression_tools,
        enabled_user_shutdown=enabled_user_shutdown,
        ssh_key_type=ssh_key_type,
        ssh_key_bits=ssh_key_bits,
    )
    master_node_config = objects.Node(
        name=hostname.name,
        primary_ip=hostname.ip,
        secondary_ip=secondary_ip,
        serial_no=1,
        master_candidate=True,
        offline=False,
        drained=False,
        ctime=now,
        mtime=now,
    )
    InitConfig(constants.CONFIG_VERSION, cluster_config, master_node_config)
    cfg = config.ConfigWriter(offline=True)
    ssh.WriteKnownHostsFile(cfg, pathutils.SSH_KNOWN_HOSTS_FILE)
    cfg.Update(cfg.GetClusterInfo(), logging.error)
    ssconf.WriteSsconfFiles(cfg.GetSsconfValues())

    master_uuid = cfg.GetMasterNode()
    if modify_ssh_setup:
        ssh.InitPubKeyFile(master_uuid, ssh_key_type)
    # set up the inter-node password and certificate
    _InitGanetiServerSetup(hostname.name, cfg)

    logging.debug("Starting daemons")
    result = utils.RunCmd([pathutils.DAEMON_UTIL, "start-all"])
    if result.failed:
        raise errors.OpExecError("Could not start daemons, command %s"
                                 " had exitcode %s and error %s" %
                                 (result.cmd, result.exit_code, result.output))

    _WaitForMasterDaemon()