Пример #1
1
    def set_cifs_homedirs(self, homedirs):
        """Set the list of CIFS home directory paths for the filer."""

        homedir_paths = NaElement('homedir-paths')

        for d in homedirs:
            homedir_paths.child_add(NaElement('homedir-path-info', d))

        chps = NaElement('cifs-homedir-paths-set')
        chps.child_add(homedir_paths)
        self.invoke_elem(chps)
def listSnapshots(volume):
    cmd = NaElement("snapshot-list-info")
    cmd.child_add_string("volume", volume)

    ret = executeCmd(cmd)

    return ret
def listSnapshots(volume):
    cmd = NaElement('snapshot-list-info')
    cmd.child_add_string('volume', volume)

    ret = executeCmd(cmd)

    return ret
def createClone(parentVolume, volume):
    cmd = NaElement("volume-clone-create")
    cmd.child_add_string("parent-volume", parentVolume)
    cmd.child_add_string("volume", volume)

    # Feature disabled for now
    debugret = NaElement("results")
    debugret.attr_set("status", "failed")
    debugret.attr_set("reason", "Creating clones not supported...yet!")
    return debugret
Пример #5
0
def get_volumes(conn):
    cmd = NaElement('volume-get-iter')
    cmd.child_add_string('max-records', 500)
    out = conn.invoke_elem(cmd)

    if(out.results_status() == 'failed'):
        print (out.results_reason() + '\n')
        sys.exit(2)

    attributes = out.child_get('attributes-list')

    return attributes.children_get()
def createSnapshot(volume, customname=None):
    if customname:
        snapshotName = customname
    else:
        #         Create snapshot format name
        snapshotName = "snap_" + volume + "_" + datetime.strftime(datetime.now(), "%Y%m%d%H%M%S")

    cmd = NaElement("snapshot-create")
    cmd.child_add_string("volume", volume)
    cmd.child_add_string("snapshot", snapshotName)

    return executeCmd(cmd)
def renameSnapshot(volume, snapshot, newName):
    cmd = NaElement("snapshot-rename")
    cmd.child_add_string("current-name", snapshot)
    cmd.child_add_string("volume", volume)
    cmd.child_add_string("new-name", newName)

    return executeCmd(cmd)
Пример #8
0
    def get_instance_list(self, perf_obj):
        '''
        Lists instances associated with the supplied performance object.
        Some objects actually have instances, like 'volume' and 'aggregate', while
        others only have themselves (so sad...) like 'system' or 'cifs'
        '''
        list_in = NaElement("perf-object-instance-list-info")
        list_in.child_add_string("objectname", perf_obj)

        out = self.invoke_elem(list_in)
        check_zapi_error(out)
        inst_info = out.child_get("instances")
        result = inst_info.children_get()

        instance_names = []
        for inst in result:
            inst_name = inst.child_get_string("name")
            instance_names.append(inst_name)
        return instance_names
Пример #9
0
    def set_snapshot_schedule(self, snap_sched):
        """@todo: Docstring for set_snapshot_schedule.

        :snap_sched: Dict that my contain one or more of the following keys:
            days,
            hours,
            minutes,
            weeks,
            which-hours,
            which-minutes
        :returns: @todo

        """
        list_in = NaElement('snapshot-set-schedule')
        list_in.child_add_string('volume', self.name)
        for snap_interval, snap_count in snap_sched.iteritems():
            list_in.child_add_string(snap_interval, snap_count)
        out = self.invoke_elem(list_in)
        check_zapi_error(out)
Пример #10
0
def invoke_cli(s, cli_args):
    """
    Call the unsupported/undocumented system-cli API.
    cli_args, a list of commands, would represent the command line
    if executing in the CLI.
    Return the NaElement result of executing the command.
    """
    args = NaElement('args')
    for arg in cli_args:
        args.child_add(NaElement('arg', arg))
    cli = NaElement('system-cli')
    cli.child_add(args)
    out = s.invoke_elem(cli)
    if out.results_status() != 'passed':
        raise Exception(out.results_reason())
    return out
Пример #11
0
    def invoke_cli(self, *cli_args):
        """
        Call the unsupported/undocumented system-cli API.

        args is a tuple of arguments that, joined with spaces, would represent
        the command line if executing in the CLI.
        """

        args = NaElement('args')
        for arg in cli_args:
            args.child_add(NaElement('arg', arg))

        cli = NaElement('system-cli')
        cli.child_add(args)
        out = self.api.invoke_elem(cli)
        if out.results_status() == 'failed':
            raise OntapApiException(out.results_errno(), out.results_reason())
        return out
Пример #12
0
def dict_to_naelement(naelem_dict, parent_naelem=None):
    """
    Generates an NaElement object from a dictionary, useful for
    API calls that require nested NaElement objects (like nfs exports)
    or for spoofing response objects.

    Note that the outermost dictionary can only contain one parent
    key and the optional attribute.
    """
    attrs = None
    #if not parent_naelem and len(naelem_dict) > 2 and 'attrs' not in naelem_dict:
    #    raise NetCrAPIOut('There can only be ONE (top level element)!')
    for k, v in naelem_dict.iteritems():
        if k == 'attrs':
            attrs = v
            #print "attrs: "
            #print v
            continue
        else:
            if isinstance(v, dict):
                new_naelem = NaElement(k)
                if parent_naelem:
                    parent_naelem.child_add(new_naelem)
                dict_to_naelement(v, new_naelem)
            elif isinstance(v, list):
                for item in v:
                    new_naelem = NaElement(k)
                    if parent_naelem:
                        parent_naelem.child_add(new_naelem)
                    dict_to_naelement(item, new_naelem)
            elif isinstance(v, str):
                if parent_naelem:
                    parent_naelem.child_add_string(k, v)
    if not parent_naelem:
        if attrs:
            for k, v  in attrs.iteritems():
                new_naelem.attr_set(k, v)
        return new_naelem
Пример #13
0
    def get_counter_list(self, perf_obj):
        '''
        Returns the counters associated with a performance object.
        This function also outputs the 'base counter', 'privilege level' and 
        'unit' of the counter.
        '''
        list_in = NaElement("perf-object-counter-list-info")
        list_in.child_add_string("objectname", perf_obj)
        out = self.invoke_elem(list_in)
        check_zapi_error(out)
        counter_info = out.child_get("counters")
        result = counter_info.children_get()
        counter_list = []
        for counter in result:
            counter_name = counter.child_get_string("name")
            if counter.child_get_string("base-counter"):
                base_counter = counter.child_get_string("base-counter")
            else:
                base_counter = "None"

            privilege_level = counter.child_get_string("privilege-level")

            if counter.child_get_string("unit"):
                unit = counter.child_get_string("unit")
            else:
                unit = "None"

            if counter.child_get_string("properties"):
                counter_type = counter.child_get_string("properties")
            else:
                counter_type = "None"
            counter_list.append([counter_name,
                                 base_counter,
                                 counter_type,
                                 privilege_level,
                                 unit])
        return counter_list
Пример #14
0
    def set_cifs_homedirs(self, homedirs):
        """Set the list of CIFS home directory paths for the filer."""

        homedir_paths = NaElement('homedir-paths')

        for d in homedirs:
            homedir_paths.child_add(NaElement('homedir-path-info', d))

        chps = NaElement('cifs-homedir-paths-set')
        chps.child_add(homedir_paths)
        self.invoke_elem(chps)
Пример #15
0
    def invoke_cli(self, *cli_args):
        """
        Call the unsupported/undocumented system-cli API.

        args is a tuple of arguments that, joined with spaces, would represent
        the command line if executing in the CLI.
        """

        args = NaElement('args')
        for arg in cli_args:
            args.child_add(NaElement('arg', arg))

        cli = NaElement('system-cli')
        cli.child_add(args)
        out = self.api.invoke_elem(cli)
        if out.results_status() == 'failed':
            raise OntapApiException(out.results_errno(), out.results_reason())
        return out
Пример #16
0
    def invoke_cli(self, command):
        """Undocumented API that runs supplied arguments as a command. API
        documentation and python code found here:
            https://communities.netapp.com/message/74370

        :command: @todo
        :returns: Object containing cli-output (string) and 
                  cli-result-value (integer)

        """
        args = NaElement('args')
        for arg in command.split():
            args.child_add(NaElement('arg', arg))
        cli = NaElement('system-cli')
        cli.child_add(args)
        out = self.invoke_elem(cli)
        check_zapi_error(out)
        return out
Пример #17
0
    perfGet = {
        # object names
        'system': {
            # instances
            'system':
            # counters
            [
                'serial_no', 'system_id', 'hostname', 'ontap_version',
                'system_model'
            ],
        },
    }

    server = ZenOntap('8.8.8.8', 'un', 'pw', 'HTTPS')

    request = NaElement('perf-object-get-instances')
    for perf, instances in perfGet.iteritems():
        request.child_add_string('objectname', perf)
        reqinst = NaElement('instances')
        for instance, counters in instances.iteritems():
            reqinst.child_add_string('instance', instance)
            reqcnts = NaElement('counters')
            for counter in counters:
                reqcnts.child_add_string('counter', counter)
            request.child_add(reqcnts)
        request.child_add(reqinst)

    response = server.invoke_elem_async(request)
    deferreds = [response]
    naElements = defer.DeferredList(deferreds,
                                    consumeErrors=True).addCallback(callback)
Пример #18
0
    def get_info(self):
        """@todo: Docstring for get_info.
        :returns: @todo

        """
        volume_info = {'volume-autosize-attributes': {
                           'maximum-size': 'integer',
                           'increment-size': 'integer',
                           'is-enabled': 'boolean'
                       },
                       'volume-id-attributes': {
                           'containing-aggregate-name': 'string',
                           'type': 'string',
                           'owning-vserver-name': 'string'
                       },
                       'volume-inode-attributes': {
                           'files-total': 'integer',
                           'files-used': 'integer',
                           'block-type': 'string'
                       },
                       'volume-state-attributes': {
                           'state': 'string'
                       },
                       'volume-space-attributes': {
                           'percentage-size-used': 'integer',
                           'size-total': 'integer',
                           'size-available': 'integer',
                           'size-used': 'integer',
                           'size-used-by-snapshots': 'integer',
                           'space-guarantee': 'string',
                           'size': 'integer',
                           'percentage-snapshot-reserve': 'integer',
                           'percentage-fractional-reserve': 'integer',
                       },
                       'volume-sis-attributes': {
                           'is-sis-volume': 'boolean',
                           'deduplication-space-saved': 'integer',
                           'compression-space-saved': 'integer',
                           'total-space-saved': 'integer'
                       }
                      }
        vol_get_iter = NaElement('volume-get-iter')
        query = NaElement('query')
        vol_query_attrs = NaElement('volume-attributes')
        vol_id_attrs = NaElement('volume-id-attributes')
        vol_get_iter.child_add(query)
        query.child_add(vol_query_attrs)
        vol_query_attrs.child_add(vol_id_attrs)
        vol_id_attrs.child_add_string('name', self.name)
        out = self.invoke_elem(vol_get_iter)
        attributes_list = out.child_get('attributes-list').children_get()[0]
        #print attributes_list.sprintf()
        vol_info_dict = {}
        for vol_attribute_type, attributes in volume_info.iteritems():
            attribute_group = attributes_list.child_get(vol_attribute_type)
            for attr_name, data_type in attributes.iteritems():
                #print vol_attribute_type
                #print attribute_group
                #print attr_name
                #print data_type
                if data_type == 'string':
                    data = attribute_group.child_get_string(attr_name)
                    vol_info_dict[attr_name] = data
                elif data_type == 'integer':
                    data = attribute_group.child_get_int(attr_name)
                    vol_info_dict[attr_name] = data
                elif data_type == 'boolean':
                    data = (attribute_group.child_get_string(attr_name) == 'true')
                    vol_info_dict[attr_name] = data
        return vol_info_dict
Пример #19
0
    def set_sv_sec_snap_sched(self, sched, auto_update, retention_ct,
                              dow = 'mon-sun',
                              hod = '0'):
        """
        Set the SnapVault snapshot schedule on a SnapVault secondary.

        sched - SnapVault schedule's name
        retention_ct - Number of snapshots to be retained
        dow - Days of week on which the schedule will run
        hod - Hours of day on whcih the schedule will run
        """

        nae = NaElement('snapvault-secondary-set-snapshot-schedule')

        snap_sched = NaElement('snapshot-schedule')

        ssssi = NaElement('snapvault-secondary-snapshot-schedule-info')

        if auto_update:
            ssssi.child_add(NaElement('is-auto-update', 'true'))
        else:
            ssssi.child_add(NaElement('is-auto-update', 'false'))

        ssssi.child_add(NaElement('retention-count', int(retention_ct)))
        ssssi.child_add(NaElement('schedule-name', sched))
        ssssi.child_add(NaElement('volume-name', self.name))
        
        sched_info = NaElement('snapvault-schedule-info')
        sched_info.child_add(NaElement('days-of-week', dow))
        sched_info.child_add(NaElement('hours-of_day', str(hod)))

        sched = NaElement('schedule')
        sched.child_add(sched_info)

        ssssi.child_add(sched)

        snap_sched.child_add(ssssi)
        nae.child_add(snap_sched)

        self.filer.invoke_elem(nae)
Пример #20
0
    def create(self, aggr, size):
        """@todo: Docstring for create.

        :aggr: @todo
        :size: @todo
        :returns: @todo

        """
        list_in = NaElement('volume-create')
        #name
        list_in.child_add_string("volume", self.name)
        #aggr
        list_in.child_add_string("containing-aggr-name", aggr)
        #size
        size_pattern = re.compile('^[1-9][0-9]*[kmgt]')
        if size_pattern.match(size):
            list_in.child_add_string("size", size)
        else:
            raise NetCrAPIOut("Size not valid. Please use <number>k|m|g|t.")
            pass
        #space reservation (none)
        list_in.child_add_string("space-reserve", "none")
        #language (en_US)
        list_in.child_add_string("language-code", "en_US")
        out = self.invoke_elem(list_in)
        check_zapi_error(out)
Пример #21
0
    def delete_rule(self):
        """Remove the exportfs rule for a share."""

        #
        # Construct NaElement tree:
        #

        pathname_info = NaElement('pathname-info')
        pathname_info.child_add(NaElement('name', self.path))

        pathnames = NaElement('pathnames')
        pathnames.child_add(pathname_info)

        elem = NaElement('nfs-exportfs-delete-rules')
        elem.child_add(NaElement('persistent', 'true'))
        elem.child_add(pathnames)

        # Execute it:
        self.filer.invoke_elem(elem)
Пример #22
0
    def modify_rule(self,
                    nosuid=True,
                    root_hosts=[],
                    ro_hosts=[],
                    rw_hosts=[],
                    sec_flavor='sys'):
        """
        Change the exportfs rule for an NFS share.

        This method follows the semantics of the NetApp API for
        default values, namely: 'By default, if no 'read-only' or
        'read-write' hosts are given, then 'read-write' [access is
        granted to all hosts].'

        The exportfs rule must already exist before calling this method, or
        an exception will be thrown.
        """

        # Parse arguments:
        if nosuid:
            nosuid_val = 'true'
        else:
            nosuid_val = 'false'

        #
        # Construct NaElement tree:
        #

        rule_info = NaElement('exports-rule-info')
        rule_info.child_add(NaElement('nosuid', nosuid_val))
        rule_info.child_add(NaElement('pathname', self.path))

        host_lists = {
            'root': root_hosts,
            'read-only': ro_hosts,
            'read-write': rw_hosts
        }

        for elem in host_lists:
            if len(host_lists[elem]) > 0:
                nae = NaElement(elem)
                for host in host_lists[elem]:
                    ehi = NaElement('exports-hostname-info')
                    ehi.child_add(NaElement('name', host))
                    nae.child_add(ehi)
                rule_info.child_add(nae)

        nfs_export = NaElement('nfs-exportfs-modify-rule')
        nfs_export.child_add(NaElement('persistent', 'true'))
        rule = NaElement('rule')
        rule.child_add(rule_info)
        nfs_export.child_add(rule)

        # Execute rule change:
        self.filer.invoke_elem(nfs_export)
Пример #23
0
    def get_perf_object(self, objectname, read=[], instances=[]):
        """
        Return objectname's performance data in a dict tree.

        read - optional array of counters whose values are to be read.
               If not set, all counters are reported.
        instances - optional array of instances whose values are to be read.
                    If not set, all instances are reported.
        """

        info = self.get_perf_object_info(objectname)

        get_perf_obj = NaElement('perf-object-get-instances-iter-start')
        get_perf_obj.child_add(NaElement('objectname', objectname))

        if read:
            read_counters = NaElement('counters')
            for c in read:
                read_counters.child_add(NaElement('counter', c))
            get_perf_obj.child_add(read_counters)

        if instances:
            insts = NaElement('instances')
            for inst in instances:
                insts.child_add(NaElement('instance', inst))
            get_perf_obj.child_add(insts)

        out = self.invoke_elem(get_perf_obj)

        iter_tag = out.child_get_int('tag')
        iter_recs = out.child_get_int('records')

        perf_insts = {}
        i = 0
        while i < iter_recs:
            out = self.invoke('perf-object-get-instances-iter-next',
                              'maximum', 1,
                              'tag', iter_tag)
            inst = out.child_get('instances').child_get('instance-data')
            inst_name = inst.child_get_string('name')
            perf_insts[inst_name] = {}
            counters = inst.child_get('counters').children_get()
            for c in counters:
                name = c.child_get_string('name')
                if info[name]['type'] == 'array':
                    vals = c.child_get_string('value').split(',')
                    data = {}
                    j = 0
                    while j < len(vals):
                        data[info[name]['labels'][j]] = int(vals[j])
                        j = j + 1
                    perf_insts[inst_name][name] = data
                else:
                    try:
                        perf_insts[inst_name][name] = c.child_get_int('value')
                    except ValueError:
                        # Must be a string...
                        perf_insts[inst_name][name] = c.child_get_string(
                            'value')
                
            i = i + 1

        self.invoke('perf-object-get-instances-iter-end', 'tag', iter_tag)
        return perf_insts
Пример #24
0
    def get_perf_object(self, objectname, read=[], instances=[]):
        """
        Return objectname's performance data in a dict tree.

        read - optional array of counters whose values are to be read.
               If not set, all counters are reported.
        instances - optional array of instances whose values are to be read.
                    If not set, all instances are reported.
        """

        info = self.get_perf_object_info(objectname)

        get_perf_obj = NaElement('perf-object-get-instances-iter-start')
        get_perf_obj.child_add(NaElement('objectname', objectname))

        if read:
            read_counters = NaElement('counters')
            for c in read:
                read_counters.child_add(NaElement('counter', c))
            get_perf_obj.child_add(read_counters)

        if instances:
            insts = NaElement('instances')
            for inst in instances:
                insts.child_add(NaElement('instance', inst))
            get_perf_obj.child_add(insts)

        out = self.invoke_elem(get_perf_obj)

        iter_tag = out.child_get_int('tag')
        iter_recs = out.child_get_int('records')

        perf_insts = {}
        i = 0
        while i < iter_recs:
            out = self.invoke('perf-object-get-instances-iter-next', 'maximum',
                              1, 'tag', iter_tag)
            inst = out.child_get('instances').child_get('instance-data')
            inst_name = inst.child_get_string('name')
            perf_insts[inst_name] = {}
            counters = inst.child_get('counters').children_get()
            for c in counters:
                name = c.child_get_string('name')
                if info[name]['type'] == 'array':
                    vals = c.child_get_string('value').split(',')
                    data = {}
                    j = 0
                    while j < len(vals):
                        data[info[name]['labels'][j]] = int(vals[j])
                        j = j + 1
                    perf_insts[inst_name][name] = data
                else:
                    try:
                        perf_insts[inst_name][name] = c.child_get_int('value')
                    except ValueError:
                        # Must be a string...
                        perf_insts[inst_name][name] = c.child_get_string(
                            'value')

            i = i + 1

        self.invoke('perf-object-get-instances-iter-end', 'tag', iter_tag)
        return perf_insts
Пример #25
0
def listVolumes():
    isDebug = getConfigOption("Debug")
    #     Build command to list volumes
    cmd = NaElement("volume-get-iter")
    xi = NaElement("desired-attributes")
    xi1 = NaElement("volume-attributes")

    xi1.child_add(NaElement("volume-id-attributes"))
    xi1.child_add(NaElement("volume-snapshot-attributes"))
    xi1.child_add(NaElement("volume-space-attributes"))

    xi2 = NaElement("volume-clone-attributes")
    xi2.child_add(NaElement("volume-clone-parent-attributes"))
    xi1.child_add(xi2)

    xi.child_add(xi1)

    cmd.child_add(xi)
    cmd.child_add_string("max-records", "500")

    ret = executeCmd(cmd)

    # Remove volumes from list that contain filterStrings
    filterString = getConfigOption("VolFilters")
    filterList = filterString.replace(" ", "").split(",")
    filteredVolumes = NaElement("attributes-list")

    for vol in ret.child_get("attributes-list").children_get():
        volattrs = vol.child_get("volume-id-attributes")

        if any(x in volattrs.child_get_string("name") for x in filterList):
            if isDebug == "True":
                print "Skipping filtered vol : %s" % volattrs.child_get_string("name")
            continue
        if isDebug == "True":
            print "Volume Name : %s" % volattrs.child_get_string("name")

        filteredVolumes.child_add(vol)

    filteredRet = NaElement("results")
    filteredRet.attr_set("status", "passed")
    filteredRet.child_add(filteredVolumes)

    if isDebug == "True":
        print "Number of volumes (after filtering): " + str(ret.child_get("attributes-list").children_get().__len__())
    return filteredRet
Пример #26
0
    def set_sv_sec_snap_sched(self,
                              sched,
                              auto_update,
                              retention_ct,
                              dow='mon-sun',
                              hod='0'):
        """
        Set the SnapVault snapshot schedule on a SnapVault secondary.

        sched - SnapVault schedule's name
        retention_ct - Number of snapshots to be retained
        dow - Days of week on which the schedule will run
        hod - Hours of day on whcih the schedule will run
        """

        nae = NaElement('snapvault-secondary-set-snapshot-schedule')

        snap_sched = NaElement('snapshot-schedule')

        ssssi = NaElement('snapvault-secondary-snapshot-schedule-info')

        if auto_update:
            ssssi.child_add(NaElement('is-auto-update', 'true'))
        else:
            ssssi.child_add(NaElement('is-auto-update', 'false'))

        ssssi.child_add(NaElement('retention-count', int(retention_ct)))
        ssssi.child_add(NaElement('schedule-name', sched))
        ssssi.child_add(NaElement('volume-name', self.name))

        sched_info = NaElement('snapvault-schedule-info')
        sched_info.child_add(NaElement('days-of-week', dow))
        sched_info.child_add(NaElement('hours-of_day', str(hod)))

        sched = NaElement('schedule')
        sched.child_add(sched_info)

        ssssi.child_add(sched)

        snap_sched.child_add(ssssi)
        nae.child_add(snap_sched)

        self.filer.invoke_elem(nae)
Пример #27
0
def restoreSnapshot(volume, snapshot):
    cmd = NaElement("snapshot-restore-volume")
    cmd.child_add_string("snapshot", snapshot)
    cmd.child_add_string("volume", volume)

    return executeCmd(cmd)
Пример #28
0
    def delete_rule(self):
        """Remove the exportfs rule for a share."""

        #
        # Construct NaElement tree:
        #
        
        pathname_info = NaElement('pathname-info')
        pathname_info.child_add(NaElement('name', self.path))

        pathnames = NaElement('pathnames')
        pathnames.child_add(pathname_info)

        elem = NaElement('nfs-exportfs-delete-rules')
        elem.child_add(NaElement('persistent', 'true'))
        elem.child_add(pathnames)

        # Execute it:
        self.filer.invoke_elem(elem)
Пример #29
0
    def modify_rule(self, nosuid=True, root_hosts = [], ro_hosts = [],
                    rw_hosts = [], sec_flavor = 'sys'):
        """
        Change the exportfs rule for an NFS share.

        This method follows the semantics of the NetApp API for
        default values, namely: 'By default, if no 'read-only' or
        'read-write' hosts are given, then 'read-write' [access is
        granted to all hosts].'

        The exportfs rule must already exist before calling this method, or
        an exception will be thrown.
        """

        # Parse arguments:
        if nosuid:
            nosuid_val = 'true'
        else:
            nosuid_val = 'false'

        #
        # Construct NaElement tree:
        #

        rule_info = NaElement('exports-rule-info')
        rule_info.child_add(NaElement('nosuid', nosuid_val))
        rule_info.child_add(NaElement('pathname', self.path))

        host_lists = { 'root': root_hosts,
                       'read-only': ro_hosts,
                       'read-write': rw_hosts }

        for elem in host_lists:
            if len(host_lists[elem]) > 0:
                nae = NaElement(elem)
                for host in host_lists[elem]:
                    ehi = NaElement('exports-hostname-info')
                    ehi.child_add(NaElement('name', host))
                    nae.child_add(ehi)
                rule_info.child_add(nae)

        nfs_export = NaElement('nfs-exportfs-modify-rule')
        nfs_export.child_add(NaElement('persistent', 'true'))
        rule = NaElement('rule')
        rule.child_add(rule_info)
        nfs_export.child_add(rule)

        # Execute rule change:
        self.filer.invoke_elem(nfs_export)
def deleteSnapshot(volume, snapshot):
    cmd = NaElement('snapshot-delete')
    cmd.child_add_string("snapshot", snapshot)
    cmd.child_add_string("volume", volume)

    return executeCmd(cmd)