LVM/liblvm/api

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);

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

/* * 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);
 * 1) 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

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

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

vgcreate: vgcreate -v -An --physicalextentsize k

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 [ ]

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

vgmknodes: vgmknodes -v [ ]

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 M -n -An

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/ /

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