From Fedora Project Wiki

< LVM‎ | liblvm

High Level API Proposal

/********************************* lvm handle ********************************/

/*
 * lvm_handle_t
 */
struct lib_context; /* internal context data */
typedef struct lib_context *lvm_handle_t;

/*
 * lvm_create
 *
 * Description: Create an LVM handle used in many other APIs.
 * Parameters:  system directory: path or NULL
 * Returns:     NULL: Fail - unable to initialise handle.
 *              non-NULL: Success - valid LVM handle returned
 */
lvm_handle_t lvm_create(const char *system_dir);

/*
 * lvm_destroy
 *
 * Description: Destroy an LVM handle allocated with lvm_create
 * Parameters:  libh (IN): handle obtained from lvm_create
 */
int lvm_destroy(lvm_handle_t libh);

/*
 * lvm_mknodes
 * 
 * Description: (Re)Create device nodes for volume path.
 *              The volume path can be a volume group, logical volume or NULL.
 *              If volume is NULL, then all devides will be (re)created.
 * Parameters:  libh (IN): handle obtained from lvm_create
 * Returns:     Status
 */
int lvm_mknodes(lvm_handle_t libh, const char *volume);

/****************************** physical volume ******************************/

/*
 * The lvm physical volume object.
 */
struct lvm_pv_obj;
typedef struct lvm_pv_obj *lvm_pv_obj_t; /* with mode inside (r/rw) */

/*
 * The lvm physical volume object list.
 */
typedef struct lvm_pv_list {
  dm_list list;
  lvm_pv_obj_t obj;
} *lvm_pv_list_t;

/*
 * lvm_pv_obj_get
 *
 * Description: Get object for a physical volume by volume path
 * Retuns:      lvm_pv_obj_t on success, otherwide NULL. errno is used to
 *              indicate the error.
 * Parameters:  phys_vol: device
 *              mode: "r" or "rw"
 */
lvm_pv_obj_t lvm_pv_obj_get(lvm_handle_t libh, const char *phys_vol,
                            const char *mode);

/*
 * Returns list of physical volumes.
 * Retuns lvm_pv_obj_list_t on success, otherwide NULL. errno is used to 
 * indicate the error. The objects are read only.
 */
lvm_pv_obj_list_t lvm_pv_obj_list(lvm_handle_t libh); /* rescan arg? */

/* lvm_pv_obj_list_t lvm_pv_obj_scan(lvm_handle_t libh); */

/*
 * Creates object for a physical volume path. "Object is readonly."?
 * Retuns lvm_pv_obj_t on success, otherwide NULL. errno is used to indicate 
 * the error.
 */
lvm_pv_obj_t lvm_pv_obj_create(lvm_handle_t libh, const char *phys_vol);

/*
 * Write physical volume obj to disk.
 * Returns error code (see errno).
 */
int lvm_pv_obj_write(lvm_pv_obj_t pv_obj);

/*
 * Closes and frees obj.
 */
int lvm_pv_obj_close(lvm_pv_obj_t pv_obj);

/*
 * Closes and frees obj list.
 */
int lvm_pv_obj_list_close(lvm_pv_obj_list_t pv_obj_list);

/*
 * Accessors and mutators for object attributes in memory.
 */
int lvm_pv_obj_set_attribute(lvm_pv_obj_t pv_obj, const char *attribute,
                             void *value);
void* lvm_pv_obj_get_attribute(lvm_pv_obj_t pv_obj, const char *attribute);

/*
 * Removes physical volume.
 */
int lvm_pv_obj_remove(lvm_pv_obj_t pv_obj);

#ifdef FUTURE_FEATURE
/*
 * Checks physical volume metadata for consistency.
 */
int lvm_pv_obj_check(lvm_pv_obj_t pv_obj);

/*
 * Loads physical volume attributes from a file using the UUID.
 * Use lvm_pv_obj_write afterwards.
 */
lvm_pv_obj_t lvm_pv_obj_load_from(const char *uuid,
                                  const char *restore_file);
#endif /* FUTURE_FEATURE */

/******************************* volume group ********************************/

/*
 * The lvm volume group object.
 */
struct lvm_vg_obj;
typedef struct lvm_vg_obj *lvm_vg_obj_t; /* with mode inside (r/rw) */

/*
 * The lvm volume group object list.
 */
typedef struct lvm_vg_list {
  dm_list list;
  lvm_vg_obj_t obj;
} *lvm_vg_list_t;

/*
 * Gets object for a volume group by volume group name
 * Retuns lvm_vg_obj_t on success, otherwide NULL. errno is used to indicate 
 * the error.
 * mode: "r" or "rw"
 */
lvm_vg_obj_t lvm_vg_obj_get(lvm_handle_t libh, const char *vol_group,
                            const char *mode);

/*
 * Returns list of volumes groups.
 * Retuns lvm_vg_obj_list_t on success, otherwide NULL. errno is used to 
 * indicate the error. The objects are read only.
 */
lvm_vg_obj_list_t lvm_vg_obj_list(lvm_handle_t libh); /* rescan arg? */

/* lvm_vg_obj_list_t lvm_vg_obj_scan(lvm_handle_t libh); */

/*
 * Creates object for a physical volume path. "Object is readonly."?
 * Retuns lvm_pv_obj_t on success, otherwide NULL. errno is used to indicate 
 * the error.
 */
lvm_vg_obj_t lvm_vg_obj_create(lvm_handle_t libh, const char *vol_group, 
                               lvm_pv_obj_t pv_obj);

/*
 * Write volume group obj to disk.
 * Returns error code (see errno).
 */
int lvm_vg_obj_write(lvm_vg_obj_t vg_obj);

/*
 * Closes and frees obj.
 */
int lvm_vg_obj_close(lvm_vg_obj_t vg_obj);

/*
 * Closes and frees obj list.
 */
int lvm_vg_obj_list_close(lvm_vg_obj_list_t vg_obj_list);

/*
 * Accessors and mutators for object attributes in memory.
 */
int lvm_vg_obj_set_attribute(lvm_vg_obj_t vg_obj, const char *attribute,
                             void *value);
void* lvm_vg_obj_get_attribute(lvm_vg_obj_t vg_obj, const char *attribute);

/*
 * Removes volume group.
 */
int lvm_vg_obj_remove(lvm_vg_obj_t vg_obj);

/*
 * List physical volumes in volume group.
 */
lvm_pv_obj_list_t lvm_vg_obj_list_pvs(lvm_vg_obj_t vg_obj);

/*
 * Extend volume group by physical volume.
 */
int lvm_vg_obj_add_pv(lvm_vg_obj_t vg_obj, lvm_pv_obj_t pv_obj);

/*
 * Remove physical volume from volume group.
 */
int lvm_vg_obj_remove_pv(lvm_vg_obj_t vg_obj, lvm_pv_obj_t pv_obj);

/*
 * Activate physical volume.
 */
int lvm_vg_obj_activate(lvm_vg_obj_t vg_obj);

/*
 * Deactivate physical volume.
 */
int lvm_vg_obj_deactivate(lvm_vg_obj_t vg_obj);

/*
 * Check if physical volume is active.
 */
int lvm_vg_obj_is_active(lvm_vg_obj_t vg_obj);

/****************************** logical volume *******************************/

struct lvm_lv_obj;
typedef struct lvm_lv_obj *lvm_lv_obj_t; /* with mode inside (r/rw) */

typedef struct lvm_lv_list {
  dm_list list;
  lvm_lv_obj_t obj;
} *lvm_lv_list_t;

lvm_lv_obj_t lvm_lv_obj_get(lvm_handle_t libh, const char *logical_vol,
                            const char *mode);
lvm_lv_obj_list_t lvm_lv_obj_list(lvm_handle_t libh); /* rescan arg? */
/* lvm_lv_obj_list_t lvm_lv_obj_scan(lvm_handle_t libh); */
lvm_lv_obj_t lvm_lv_obj_create(lvm_handle_t libh, const char *logical_vol,
                               lvm_vg_obj_t vg_obj);
int lvm_lv_obj_write(lvm_lv_obj_t lv_obj);
int lvm_lv_obj_close(lvm_lv_obj_t lv_obj);
int lvm_lv_obj_list_close(lvm_lv_obj_list_t lv_obj_list);
int lvm_lv_obj_set_attribute(lvm_lv_obj_t lv_obj, const char *attribute,
                             void *value);
void* lvm_lv_obj_get_attribute(lvm_lv_obj_t lv_obj, const char *attribute);
int lvm_lv_obj_remove(lvm_lv_obj_t lv_obj);

/********************************* examples **********************************

Example 1
---------

lvm_handle_t handle;
lvm_pv_obj_t pv_obj;

handle = lvm_create(NULL);

pv_obj = lvm_pv_obj_get(handle, "/dev/sda1", "r");
if (pv_obj == NULL) {
  fprintf(stderr, strerror(errno));
  lvm_destroy(handle);
  exit(-1);
}

printf("PV Name: '%s'\n", lvm_pv_obj_get_attribute(pv_obj, "pv_name"));
printf("VG Name: '%s'\n", lvm_pv_obj_get_attribute(pv_obj, "vg_name"));

lvm_pv_obj_close(pv_obj);
lvm_destroy(handle);


Example 2
---------
lvm_handle_t handle;
lvm_pv_obj_t pv_obj;

handle = lvm_create(NULL);

pv_obj = lvm_pv_obj_create(handle, "/dev/sda2");
if (pv_obj == NULL) {
  fprintf(stderr, strerror(errno));
  lvm_destroy(handle);
  exit(-1);
}

status = lvm_pv_obj_set_attribute(pv_obj, "uuid", "FOOBAR");
if (status == -1) {
  fprintf(stderr, "UUID is not valid.\n");
  lvm_pv_obj_close(pv_obj);
  lvm_destroy(handle);
  exit(-1);
}

status = lvm_pv_obj_write(pv_obj);
if (status == -1) {
  fprintf(stderr, "Creation of device failed.\n");
  lvm_pv_obj_close(pv_obj);
  lvm_destroy(handle);
  exit(-1);
}

lvm_pv_obj_close(pv_obj);
lvm_destroy(handle);


Example 3
---------

lvm_handle_t handle;
lvm_pv_obj_list_t pv_obj_list;
lvm_pv_obj_t pv_obj;

handle = lvm_create(NULL);

pv_obj_list = lvm_pv_obj_list(handle);
if (pv_obj_list == NULL) {
  fprintf(stderr, strerror(errno));
  lvm_destroy(handle);
  exit(-1);
}

/*TODO: dm_list_iterate_items ... */

lvm_pv_obj_close(pv_obj);
lvm_destroy(handle);

*******************************************************************************

ANACONDA:
---------

pvcreate:
  pvcreate -ff -y -v <node>

pvlist:
  pvdisplay -C --noheadings --units b --nosuffix --separator : \
    --options pv_name,vg_name,dev_size
  returns: [(dev, vg, size)]

vgactivate:
  vgchange -ay -v [<volgroup>]
  vgmknodes(volgroup)

vgcreate:
  vgcreate -v -An --physicalextentsize <PESize>k <vgname> <nodes>

vgcheckactive:
  lvs --noheadings --units b --nosuffix --separator : \
    --options vg_name,lv_name,attr
  returns: True if there is an active logical volume, else False

vgdeactivate:
  vgchange -an -v [<volgroup>]

vglist:
  vgdisplay -C --noheadings --units b --nosuffix --separator : \
    --options vg_name,vg_size,vg_extent_size
  returns: [(vg, size, pesize)]

vgmknodes:
  vgmknodes -v [<volgroup>]

vgremove:
  pvs = [ pv[0] for pv in pvlist() if pv[1] == vgname ]
  vgdeactivate(vgname)
  vgremove -v vgname
  for pvname in pvs:
    pvremove -ff -y -v pvname
    pvcreate -ff -y -v pvname
    wipeOtherMetadataFromPV(pvname)

vgscan:
  vgscan -v

lvcreate:
  vgscan()
  lvcreate -v -L <size>M -n <lvname> -An <vgname>

lvlist:
  lvdisplay -C --noheadings --units b --nosuffix --separator : \
    --options vg_name,lv_name,lv_size,origin
  returns: [(vg, lv, size, origin)]

lvremove:
  lvremove -f -v /dev/<vgname>/<lvname>

partialvgs:
  vgdisplay -C -P --noheadings --units b --nosuffix --separator :
  returns: [(vg)] if vgs are partial

******************************************************************************/