示例#1
0
static void
get_info_from_params(const struct dgcreate_params *params,
		     struct dgcreate_info *info,
		     cl_error_desc_t *err_desc)
{
    xmlDocPtr config;
    xmlNodePtr diskgroup_ptr;
    xmlAttrPtr attr;
    int i;

    EXA_ASSERT(params);
    EXA_ASSERT(info);
    EXA_ASSERT(err_desc);

    config = params->config;
    memset(info, 0, sizeof(*info));

    diskgroup_ptr = xml_conf_xpath_singleton(config, "/Exanodes/diskgroup");

    uuid_generate(&info->uuid);
    /* 0 means that the slot width will be automagically computed */
    info->slot_width = 0;
    info->chunk_size = adm_cluster_get_param_int("default_chunk_size");
    info->su_size = adm_cluster_get_param_int("default_su_size");
    info->dirty_zone_size = adm_cluster_get_param_int("default_dirty_zone_size");
    info->blended_stripes = false;
    info->nb_disks = 0;
    info->nb_spare = VRT_DEFAULT_NB_SPARES;
    info->layout[0] = '\0';

    for (attr = diskgroup_ptr->properties; attr != NULL; attr = attr->next)
    {
	if (xmlStrEqual(attr->name, BAD_CAST("name")))
	    strlcpy(info->name, xml_get_prop(diskgroup_ptr, "name"), EXA_MAXSIZE_GROUPNAME + 1);
	else if (xmlStrEqual(attr->name, BAD_CAST("layout")))
	    strlcpy(info->layout, xml_get_prop(diskgroup_ptr, "layout"), EXA_MAXSIZE_LAYOUTNAME + 1);
	else if (xmlStrEqual(attr->name, BAD_CAST("slot_width")))
	{
	    if (xml_get_uint_prop(diskgroup_ptr, "slot_width",
				  &info->slot_width, err_desc) != 0)
		return;
	    /* NOTE User can not give a zero value
	     * If slot_width is not provided, we pass zero
	     * to vrt so that it can calculate the proper slot_width
	     */
	    if (info->slot_width == 0)
	    {
		set_error(err_desc, -EXA_ERR_XML_GET,
			  "slot_width must be greater than zero");
		return;
	    }
	}
	else if (xmlStrEqual(attr->name, BAD_CAST("chunk_size")))
	{
	    if (xml_get_uint_prop(diskgroup_ptr, "chunk_size",
				  &info->chunk_size, err_desc) != 0)
		return;
	}
	else if (xmlStrEqual(attr->name, BAD_CAST("su_size")))
	{
	    if (xml_get_uint_prop(diskgroup_ptr, "su_size",
				  &info->su_size, err_desc) != 0)
		return;
	}
	else if (xmlStrEqual(attr->name, BAD_CAST("dirty_zone_size")))
	{
	    if (xml_get_uint_prop(diskgroup_ptr, "dirty_zone_size",
				  &info->dirty_zone_size, err_desc) != 0)
		return;
	}
	else if (xmlStrEqual(attr->name, BAD_CAST("blended_stripes")))
	{
	    if (xml_get_uint_prop(diskgroup_ptr, "blended_stripes",
				  &info->blended_stripes, err_desc) != 0)
		return;
	}
	else if (xmlStrEqual(attr->name, BAD_CAST("nb_spare")))
	{
	    if (xml_get_uint_prop(diskgroup_ptr, "nb_spare",
				  &info->nb_spare, err_desc) != 0)
		return;
	}
	else if (!xmlStrEqual(attr->name, BAD_CAST("cluster")))
	{
	    set_error(err_desc, -EXA_ERR_XML_GET,
		      "Unknown group property '%s'", (char *)attr->name);
	    return;
	}
    }

    /* Check the group name */
    if (info->name == NULL || info->name[0] == '\0')
    {
	set_error(err_desc, -EXA_ERR_INVALID_PARAM, NULL);
	return;
    }

    /* Check if a group with that name already exist */
    if (adm_group_get_group_by_name(info->name) != NULL)
    {
	set_error(err_desc, -VRT_ERR_GROUPNAME_USED, NULL);
	return;
    }

    if (info->layout[0] == '\0')
    {
	set_error(err_desc, -EXA_ERR_XML_GET, NULL);
	return;
    }

    if (params->alldisks)
    {
	struct adm_node *node;
	adm_cluster_for_each_node(node)
	{
	    struct adm_disk *disk;
	    adm_node_for_each_disk(node, disk)
	    {
		if (uuid_is_zero(&disk->group_uuid))
                {
                    if (disk->path[0] == '\0')
                    {
                        set_error(err_desc, -ADMIND_ERR_UNKNOWN_DISK,
                              "disk " UUID_FMT " is unknown", UUID_VAL(&disk->uuid));
                              return;
                    }

		    if (info->nb_disks >= NBMAX_DISKS_PER_GROUP)
		    {
			set_error(err_desc, -ADMIND_ERR_TOO_MANY_DISKS_IN_GROUP,
				  "too many disks in group (> %d)", NBMAX_DISKS_PER_GROUP);
			return;
		    }

		    uuid_copy(&info->disks[info->nb_disks], &disk->uuid);
		    info->nb_disks++;
		}
	    }
	}
    }
    else
    {
示例#2
0
/** \brief Implements the fscreate command
 *
 * - Set nodes started and stopped.
 * - Set nodes mounted and unmounted.
 * - Add it to the config tree with status NOK
 * - This command runs the FS-specific check and create command: creation
 *   of new volumes is done through specific FS function
 * - Update status to OK in the config file.
 */
static void cluster_fscreate(int thr_nb, void *data, cl_error_desc_t *err_desc)
{
  struct fscreate_params *fs_param = data;
  int error_val = EXA_SUCCESS, error_delete;
  struct adm_volume *volume;
  struct adm_group  *group;
  fs_data_t new_fs;
  const fs_definition_t *fs_definition;
  struct vrt_volume_info volume_info;

  exalog_info("received fscreate '%s:%s' "
              "--mountpoint='%s' --type='%s' --size=%" PRIu64
	      " --rg-size=%" PRIu64, fs_param->group_name, fs_param->volume_name,
	      fs_param->mountpoint, fs_param->type, fs_param->sizeKB,
	      fs_param->rg_sizeM);

  /* Check the license status to send warnings/errors */
  cmd_check_license_status();

  /* This is a workaround for bug #4600. */
  if (fs_param->sizeKB % 4 != 0)
  {
      set_error(err_desc, -EXA_ERR_INVALID_PARAM, "Size must be a multiple of 4KiB");
      return;
  }

  group = adm_group_get_group_by_name(fs_param->group_name);
  if (group == NULL)
    {
      set_error(err_desc, -ADMIND_ERR_UNKNOWN_GROUPNAME,
                NULL, fs_param->group_name);
      return;
    }

  /* The volume MUST NOT exist */
  if (adm_cluster_get_volume_by_name(group->name, fs_param->volume_name))
    {
      set_error(err_desc, -EXA_ERR_INVALID_PARAM,
	        "A file system or a volume with this name already exists");
      return;
    }

  fs_definition = fs_get_definition(fs_param->type);
  if (!fs_definition)
    {
      set_error(err_desc, -EXA_ERR_INVALID_PARAM, "Unknown file system type");
      return;
    }

  /* FIXME use cluster_vlcreate in place of vrt_master_volume_create */
  error_val = vrt_master_volume_create(thr_nb,
                                       group,
				       fs_param->volume_name,
                                       EXPORT_BDEV,
                                       fs_param->sizeKB,
                                       fs_definition->is_volume_private(),
				       adm_cluster_get_param_int("default_readahead"));

  if (error_val != EXA_SUCCESS)
      goto volume_delete;

  /* get the newly create volume */
  volume = adm_group_get_volume_by_name(group, fs_param->volume_name);

  /* Ask the vrt for the real size because "-s max" uses a size of "0" */
  if ((error_val = vrt_client_volume_info(adm_wt_get_localmb(),
                                          &group->uuid,
                                          &volume->uuid,
                                          &volume_info)) != EXA_SUCCESS)
    {
      goto volume_delete;
    }

  /* fill the structure with informations retrieved from the vrt */
  memset(&new_fs, 0, sizeof(new_fs));

  strlcpy(new_fs.fstype, fs_param->type, sizeof(new_fs.fstype));
  strlcpy(new_fs.mountpoint, fs_param->mountpoint, sizeof(new_fs.mountpoint));

  new_fs.sizeKB      = volume_info.size;
  new_fs.volume_uuid = volume->uuid;
  new_fs.transaction = 0;

  adm_volume_path(new_fs.devpath, sizeof(new_fs.devpath),
                  group->name, volume->name);

  /* Parse the filesystem-specific command parameters */
  if (fs_definition->parse_fscreate_parameters)
    {
      error_val = fs_definition->parse_fscreate_parameters(&new_fs,
							   fs_param->sfs_nb_logs,
							   fs_param->rg_sizeM);
      if (error_val != EXA_SUCCESS)
	goto volume_delete;
    }

  /* Write to tree, with INPROGRESS status */
  error_val = fs_update_tree(thr_nb, &new_fs);
  if (error_val != EXA_SUCCESS)
    goto volume_delete;

  exalog_debug("Set FS tree to NOK successfully");

    /* Perform clustered preparation specific to fs type */
    if (fs_definition->pre_create_fs)
    {
        error_val = fs_definition->pre_create_fs(thr_nb, &new_fs);
        if (error_val != EXA_SUCCESS)
            goto volume_delete;
    }

  /* Really create */
  error_val = pre_local_create_fs(thr_nb, &new_fs);

  if (error_val != EXA_SUCCESS)
    goto volume_delete;

  exalog_debug("Created FS successfully");

  /* Set transaction to COMMITTED */
  new_fs.transaction = 1;

  error_val = fs_update_tree(thr_nb, &new_fs);
  if (error_val != EXA_SUCCESS)
    goto volume_delete;

  exalog_debug("Set FS tree to COMMITTED successfully");

  set_success(err_desc);
  return;

volume_delete:
  /* retrieve the volume the was supposed to be created */
  volume = adm_group_get_volume_by_name(group, fs_param->volume_name);

  if (error_val == -ADMIND_ERR_NODE_DOWN ||
      error_val == -ADMIND_ERR_METADATA_CORRUPTION ||
      !volume)
    {
      set_error(err_desc, error_val, NULL);
      return;
    }
  /* Try to remove the volume in the config file.  If this fails
   * for any reason, silently ignore the error: the FS is rolled
   * back to an invalid status and cannot be started. The only way
   * out is to fsdelete it.
   */
  error_delete = vrt_master_volume_delete(thr_nb, volume, false);
  if (error_delete != EXA_SUCCESS)
    {
      exalog_error("Cannot delete file system: %s", exa_error_msg(error_delete));
    }

  set_error(err_desc, error_val, NULL);
  return;
}