From Fedora Project Wiki

< LVM‎ | liblvm

The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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

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