From Fedora Project Wiki

< LVM‎ | liblvm

 
(3 intermediate revisions by one other user not shown)
Line 1: Line 1:
== High Level API Proposal ==
== High Level API Proposal ==
<pre>
/********************************* lvm handle ********************************/
/*
* lvm_handle_t
*/
struct lib_context; /* internal context data */
typedef struct lib_context *lvm_handle_t;


liblvm/liblvm.h
/*
<pre>
* lvm_create
#include "error.h"
*
#include "handle.h"
* Description: Create an LVM handle used in many other APIs.
#include "units.h"
* Parameters:  system directory: path or NULL
#include "physical_volume.h"
* Returns:    NULL: Fail - unable to initialise handle.
*              non-NULL: Success - valid LVM handle returned
*/
lvm_handle_t lvm_create(const char *system_dir);


/*
/*
  * lvm_init
  * lvm_destroy
  *   Initialize LVM
  *
* Description: Destroy an LVM handle allocated with lvm_create
* Parameters:  libh (IN): handle obtained from lvm_create
  */
  */
lvm_handle lvm_init(const char *config_dir=NULL);
int lvm_destroy(lvm_handle_t libh);


/*
/*
  * lvm_release
  * lvm_mknodes
  *   Release LVM
  *  
* 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
  */
  */
lvm_error_status lvm_release(lvm_handle handle);
int lvm_mknodes(lvm_handle_t libh, const char *volume);
 
/****************************** physical volume ******************************/


/*
/*
  * lvm_reload_config
  * The lvm physical volume object.
* Reload configuration files
  */
  */
lvm_error_status lvm_reload_config(lvm_handle handle);
struct lvm_pv_obj;
typedef struct lvm_pv_obj *lvm_pv_obj_t; /* with mode inside (r/rw) */


/*
/*
  * lvm_load_config_file
  * The lvm physical volume object list.
*  Load a lvm configuration file
  */
  */
lvm_error_status lvm_load_config_file(lvm_handle h, const char *filename);
typedef struct lvm_pv_list {
  dm_list list;
  lvm_pv_obj_t obj;
} *lvm_pv_list_t;


/*
/*
  * lvm_set_config_option
  * lvm_pv_obj_get
*  Load an lvm config option into the existing configuration.
  *
  *
  *   The formation of the option parameter is similar to the names
  * Description: Get object for a physical volume by volume path
  *   in /etc/lvm/lvm.conf.
* Retuns:      lvm_pv_obj_t on success, otherwide NULL. errno is used to
*   An option within a section is specified with a '/' between
*              indicate the error.
  *   the section name and optionFor example, the 'filter' option
* Parameters:  phys_vol: device
  *   in the devices section is specified by 'devices/filter'
*              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_error_status lvm_set_config_option(lvm_handle h, const char *option,
lvm_pv_obj_list_t lvm_pv_obj_list(lvm_handle_t libh); /* rescan arg? */
                                      const char *value);
 
/* lvm_pv_obj_list_t lvm_pv_obj_scan(lvm_handle_t libh); */
 
/*
/*
  * lvm_remove_config_option
  * 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_error_status lvm_remove_config_option(lvm_handle h, const char *option);
lvm_pv_obj_t lvm_pv_obj_create(lvm_handle_t libh, const char *phys_vol);
</pre>


liblvm/handle.h
/*
<pre>
* Write physical volume obj to disk.
struct _lvm_handle {
* Returns error code (see errno).
  char* config_file; /* default: NULL */
*/
  char** config_options; /* default: NULL */
int lvm_pv_obj_write(lvm_pv_obj_t pv_obj);
  char** config_values; /* default: NULL */
 
/*
* 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);


  char* last_error_message; /* default: NULL */
/*
};
* 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);


typedef struct _lvm_handle lvm_handle;
/*
</pre>
* Removes physical volume.
*/
int lvm_pv_obj_remove(lvm_pv_obj_t pv_obj);


liblvm/error.h
#ifdef FUTURE_FEATURE
<pre>
/*
#include "handle.h"
* Checks physical volume metadata for consistency.
*/
int lvm_pv_obj_check(lvm_pv_obj_t pv_obj);


enum _lvm_error_status {
/*
        NO_ERROR = 0,
* Loads physical volume attributes from a file using the UUID.
        INVALID_PV_NAME,
* Use lvm_pv_obj_write afterwards.
        INVALID_PV_SIZE,
*/
        INVALID_DEV_SIZE,
lvm_pv_obj_t lvm_pv_obj_load_from(const char *uuid,
        INVALID_PE_SIZE,
                                  const char *restore_file);
        INVALID_UUID,
#endif /* FUTURE_FEATURE */
        INVALID_LABEL_SECTOR,
        INVALID_METADATA_COPIES,
        INVALID_METADATA_SIZE,
        INVALID_PE_START,
        INVALID_EXTENT_COUNT,
        INVALID_EXTENT_SIZE,
       
        /* more to come */
};


typedef enum _lvm_error_status lvm_error_status;
/******************************* volume group ********************************/


/*
/*
  * lvm_strerror
  * The lvm volume group object.
*  Returns error string stored in the handle
  */
  */
const char* lvm_strerror(lvm_handle h);
struct lvm_vg_obj;
</pre>
typedef struct lvm_vg_obj *lvm_vg_obj_t; /* with mode inside (r/rw) */


liblvm/physical_volume.h
/*
<pre>
* The lvm volume group object list.
#incldue "error.h"
*/
#include "handle.h"
typedef struct lvm_vg_list {
  dm_list list;
  lvm_vg_obj_t obj;
} *lvm_vg_list_t;


/*
/*
  * lvm physical volume information
  * 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"
  */
  */
struct lvm_physical_volume {
lvm_vg_obj_t lvm_vg_obj_get(lvm_handle_t libh, const char *vol_group,
  char* pv_name;
                            const char *mode);
  char* vg_name;
  uint64_t pv_size; /* bytes */
  uint64_t dev_size; /* bytes */
  uint64_t pe_size; /* bytes */
  uint64_t total_pe;
  uint64_t free_pe;
  char* uuid;
};


/*
/*
  * private lvm pv object for physical volume creation and modification
  * 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.
  */
  */
typedef struct lvm_pv_obj {
lvm_vg_obj_list_t lvm_vg_obj_list(lvm_handle_t libh); /* rescan arg? */
  char* phys_vol;
 
  uint64_t size;
/* lvm_vg_obj_list_t lvm_vg_obj_scan(lvm_handle_t libh); */
  int64_t labelsector;
  int metadata_copies;
  uint64_t metadata_size;
  uint64_t pe_start;
  uint32_t extent_count;
  uint32_t extent_size;
  const char* uuid; 
} lvm_pv_obj_t;


/*
/*
  * lvm_pv_scan
  * Creates object for a physical volume path. "Object is readonly."?
*  scans all supported LVM block devices in the system for physical volumes
  * Retuns lvm_pv_obj_t on success, otherwide NULL. errno is used to indicate
  *   and gets attibutes of all physicalvolume
  * the error.
  *   returns: status
  */
  */
lvm_error_status lvm_pv_scan(lvm_handle h,
lvm_vg_obj_t lvm_vg_obj_create(lvm_handle_t libh, const char *vol_group,  
                            struct LVM_PYSICAL_VOLUME** pv_return,
                              lvm_pv_obj_t pv_obj);
                            uint32_t* pv_count);


/*
/*
  * lvm_pv_get
  * Write volume group obj to disk.
*  gets attibutes of one physicalvolume by volume path
  * Returns error code (see errno).
  *   returns: status
  */
  */
lvm_error_status lvm_pv_get(lvm_handle h,
int lvm_vg_obj_write(lvm_vg_obj_t vg_obj);
                            struct lvm_physical_volume* pv_return,
                            const char* phys_vol_path);


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


/*
/*
  * lvm_pv_list
  * Closes and frees obj list.
*  gets attibutes of all physicalvolume by volume paths
*  returns: status
  */
  */
lvm_error_status lvm_pv_list(lvm_handle h,
int lvm_vg_obj_list_close(lvm_vg_obj_list_t vg_obj_list);
                            struct lvm_physical_volume** pv_return,
                            const char** phys_vol_paths, uint32_t* pv_count);


/*
/*
  * lvm_pv_remove
  * Accessors and mutators for object attributes in memory.
*  removes a physicalvolume by volume path
*  returns: status
  */
  */
lvm_error_status lvm_pv_remove(lvm_handle h, const char* phys_vol_path);
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);


/*
/*
  * lvm_pv_create
  * Removes volume group.
*  creates a physicalvolume object model with accessors and mutators
  */
  */
int lvm_vg_obj_remove(lvm_vg_obj_t vg_obj);


/*
/*
  * usage example:
  * List physical volumes in volume group.
* lvm_pv_obj_t *pv = lvm_pv_obj_create("/dev/sda1");
* lvm_pv_obj_set_uuid(pv "WDhaBn-bSGn-EW98-DkI7-M8zB-R4S9-BPkFqS");
* status = lvm_pv_create(handle, pv, 1);
  */
  */
lvm_pv_obj_list_t lvm_vg_obj_list_pvs(lvm_vg_obj_t vg_obj);


lvm_pv_obj_t* lvm_pv_obj_create(const char* phys_vol);
/*
/* accessors */
* Extend volume group by physical volume.
lvm_error_status lvm_pv_obj_set_volume(lvm_pv_obj_t* pv_obj,
*/
                                      const char* phys_vol);
int lvm_vg_obj_add_pv(lvm_vg_obj_t vg_obj, lvm_pv_obj_t pv_obj);
lvm_error_status lvm_pv_obj_set_size(lvm_pv_obj_t* pv_obj, uint64t size);
lvm_error_status lvm_pv_obj_set_labelsector(lvm_pv_obj_t* pv_obj,
                                            int64_t labelsector);
lvm_error_status lvm_pv_obj_set_metadata_copies(lvm_pv_obj_t* pv_obj,
                                                int metadata_copies);
lvm_error_status lvm_pv_obj_set_metadata_size(lvm_pv_obj_t* pv_obj,
                                              uint64_t metadata_size);
lvm_error_status lvm_pv_obj_set_pe_start(lvm_pv_obj_t* pv_obj,
                                        uint64_t pe_start);
lvm_error_status lvm_pv_obj_set_extent_count(lvm_pv_obj_t* pv_obj,
                                            uint32_t extent_count);
lvm_error_status lvm_pv_obj_set_extent_size(lvm_pv_obj_t* pv_obj,
                                            uint32_t extent_size);
lvm_error_status lvm_pv_obj_set_uuid(lvm_pv_obj_t* pv_obj, const char* uuid);
lvm_error_status lvm_pv_obj_set_volume(lvm_pv_obj_t* pv_obj,
                                      const char* phys_vol);
/* mutators */
uint64_t lvm_pv_obj_get_size(lvm_pv_obj_t* pv_obj);
int64_t lvm_pv_obj_get_labelsector(lvm_pv_obj_t* pv_obj);
int lvm_pv_obj_get_metadata_copies(lvm_pv_obj_t* pv_obj);
uint64_t lvm_pv_obj_get_metadata_size(lvm_pv_obj_t* pv_obj);
uint64_t lvm_pv_obj_get_pe_start(lvm_pv_obj_t* pv_obj);
uint32_t lvm_pv_obj_get_extent_count(lvm_pv_obj_t* pv_obj);
uint32_t lvm_pv_obj_get_extent_size(lvm_pv_obj_t* pv_obj);
const char* lvm_pv_obj_get_uuid(lvm_pv_obj_t* pv_obj);
const char* lvm_error_status lvm_pv_obj_get_volume(lvm_pv_obj_t* pv_obj);


lvm_error_status lvm_pv_create(lvm_handle h, lvm_pv_obj_t* pv_obj, int zero);
/*
* Remove physical volume from volume group.
*/
int lvm_vg_obj_remove_pv(lvm_vg_obj_t vg_obj, lvm_pv_obj_t pv_obj);


/*
/*
  * lvm_pv_change
  * Activate physical volume.
*  changes physicalvolume parameters
  */
  */
lvm_error_status lvm_pv_obj_get(const char* phys_vol,
int lvm_vg_obj_activate(lvm_vg_obj_t vg_obj);
                                lvm_pv_obj_t* pv_obj_return);
lvm_error_status lvm_pv_change(lvm_handle h, lvm_pv_obj_t* pv_obj);


/*
/*
  * lvm_pv_restore_from
  * Deactivate physical volume.
*  restore physicalvolume parameters, use lvm_pv_change afterwards
  */
  */
lvm_error_status lvm_pv_obj_restore_from(const char* uuid,
int lvm_vg_obj_deactivate(lvm_vg_obj_t vg_obj);
                                        lvm_pv_obj_t* pv_obj_return,
 
                                        const char* restore_file);
/*
/*
  * lvm_pv_fsck
  * Check if physical volume is active.
  */
  */
lvm_error_status lvm_pv_fsck(const char* phys_vol, int64_t labelsector);
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
 
******************************************************************************/
 
</pre>
</pre>

Latest revision as of 15:24, 11 February 2009

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

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