예제 #1
0
class Netapp(SnapHandler):
    _exceptionbase = "netapp"
    _blocksize = 1024
    _filer = None
    _cacert = None

    def __init__(self, configname):
        zfscredfilename = os.path.join(scriptpath(), 'netappcredentials.cfg')
        if not os.path.isfile(zfscredfilename):
            raise Exception(
                self._exceptionbase,
                "Configuration file %s not found" % zfscredfilename)
        # Authentication information
        zfscredconfig = SafeConfigParser()
        zfscredconfig.read(zfscredfilename)
        zfsauth = (zfscredconfig.get('netappcredentials', 'user'),
                   zfscredconfig.get('netappcredentials', 'password'))
        #
        self._filer = Configuration.get('filer', 'netapp')
        self._srv = NaServer(self._filer, 1, 1)
        # Check if CA certificate validation is needed
        try:
            self._cacert = os.path.join(scriptpath(), 'certs',
                                        Configuration.get('cacert', 'netapp'))
        except NoOptionError:
            self._cacert = None
        if self._cacert:
            self._srv.set_ca_certs(self._cacert)
            self._srv.set_server_cert_verification(True)
            self._srv.set_hostname_verification(False)
        #
        self._srv.set_admin_user(
            zfscredconfig.get('netappcredentials', 'user'),
            zfscredconfig.get('netappcredentials', 'password'))
        self._volprefix = Configuration.get('volumeprefix', 'netapp')
        self._volname = "%s%s" % (self._volprefix, configname)
        super(Netapp, self).__init__(configname)

    def _check_netapp_error(self, output, errmsg):
        if output.results_errno() != 0:
            raise Exception(self._exceptionbase,
                            "%s. %s" % (errmsg, output.results_reason()))

    def _volsize_to_num(self, volsize):
        unit = volsize[-1].lower()
        factor = 1
        if unit == "m":
            factor = 20
        elif unit == "g":
            factor = 30
        elif unit == "t":
            factor = 40
        elif unit == "p":
            factor = 50
        return round(float(volsize[:-1]) * (2**factor))

    # Public interfaces
    def filesystem_info(self, filesystemname=None):
        info = {}
        output = self._srv.invoke("volume-clone-get", "volume", filesystemname)
        self._check_netapp_error(output, "Getting clone info failed")
        attrlist = output.child_get("attributes")
        if (attrlist is None or attrlist == ""):
            raise Exception(self._exceptionbase,
                            "No attributes found for clone.")
        for ss in attrlist.children_get():
            info['origin'] = ss.child_get_string('parent-volume')
            info['clonename'] = filesystemname
            info['mountpoint'] = ss.child_get_string('junction-path')
        return info

    def listclones(self):
        elem = NaElement("volume-clone-get-iter")
        elem.child_add_string("max-records", "50")
        query = NaElement("query")
        query.child_add_string("parent-volume", self._volname)
        elem.child_add(query)
        #
        output = self._srv.invoke_elem(elem)
        self._check_netapp_error(output, "List clones failed")
        attrlist = output.child_get("attributes-list")
        if (attrlist is not None and attrlist):
            for ss in attrlist.children_get():
                info = {}
                info['origin'] = ss.child_get_string('parent-volume')
                info['clonename'] = ss.child_get_string('volume')
                info['mountpoint'] = ss.child_get_string('junction-path')
                yield info

    def mountstring(self, filesystemname):
        info = self.filesystem_info(filesystemname)
        return "%s:%s" % (self._filer, info['mountpoint'])

    def snap(self):
        snapname = "%s_%s" % (self._volname,
                              datetime.now().strftime('%Y%m%dT%H%M%S'))
        output = self._srv.invoke("snapshot-create", "volume", self._volname,
                                  "snapshot", snapname)
        self._check_netapp_error(output, "Creating snapshot failed")
        return snapname

    def dropsnap(self, snapid):
        output = self._srv.invoke("snapshot-delete", "volume", self._volname,
                                  "snapshot", snapid)
        self._check_netapp_error(output, "Failed to drop snapshot %s" % snapid)

    def getsnapinfo(self, snapstruct):
        return snapstruct

    def listsnapshots(self, sortbycreation=False, sortreverse=False):
        output = self._srv.invoke("volume-size", "volume", self._volname)
        self._check_netapp_error(output,
                                 "Failed to get volume size information")
        volsize = self._volsize_to_num(output.child_get_string("volume-size"))
        pct_limit = round(2147483648 * 100 / (volsize / self._blocksize))
        output = self._srv.invoke("snapshot-list-info", "volume",
                                  self._volname)
        self._check_netapp_error(output, "Failed to list snapshots")
        snapshotlist = output.child_get("snapshots")
        snapshots = []
        if (snapshotlist is not None and snapshotlist):
            for ss in snapshotlist.children_get():
                snapshots.append({
                    'id':
                    ss.child_get_string("name"),
                    'creation':
                    datetime.utcfromtimestamp(
                        float(ss.child_get_int("access-time"))),
                    'numclones':
                    1 if ss.child_get_string("busy") == "true" else 0,
                    'space_total':
                    ss.child_get_int("cumulative-total") * self._blocksize if
                    ss.child_get_int("cumulative-percentage-of-total-blocks") <
                    pct_limit else round(volsize * ss.child_get_int(
                        "cumulative-percentage-of-total-blocks") / 100),
                    'space_unique':
                    ss.child_get_int("total") * self._blocksize if
                    ss.child_get_int("percentage-of-total-blocks") < pct_limit
                    else round(volsize *
                               ss.child_get_int("percentage-of-total-blocks") /
                               100)
                })
        if not sortbycreation:
            return snapshots
        else:
            return sorted(snapshots,
                          key=operator.itemgetter('creation'),
                          reverse=sortreverse)

    def clone(self, snapid, clonename):
        output = self._srv.invoke("volume-clone-create", "parent-volume",
                                  self._volname, "parent-snapshot", snapid,
                                  "volume", clonename)
        self._check_netapp_error(output, "Creating clone failed")
        output = self._srv.invoke("volume-mount", "junction-path",
                                  "/%s" % clonename, "volume-name", clonename)
        self._check_netapp_error(output, "Mounting clone failed")
        output = self._srv.invoke("volume-set-option", "option-name",
                                  "nosnapdir", "option-value", "on", "volume",
                                  clonename)
        self._check_netapp_error(output, "Setting attribute on clone failed")

    def dropclone(self, cloneid):
        info = self.filesystem_info(cloneid)
        if info['origin'] != self._volname:
            raise Exception(
                self._exceptionbase,
                "This clone does not belong to parent %s" % self._volname)
        output = self._srv.invoke("volume-unmount", "volume-name", cloneid)
        self._check_netapp_error(output,
                                 "Unmounting volume %s failed" % cloneid)
        output = self._srv.invoke("volume-offline", "name", cloneid)
        self._check_netapp_error(output,
                                 "Offlining volume %s failed" % cloneid)
        output = self._srv.invoke("volume-destroy", "name", cloneid)
        self._check_netapp_error(output, "Dropping volume %s failed" % cloneid)

    def createvolume(self):
        uid = os.getuid()
        gid = os.getgid()
        permissions = "0770"
        #
        ui = UIElement()
        aggregate = ui.ask_string("Aggregate name:", 50)
        volume_size = ui.ask_size("Volume size:")
        path = ui.ask_string("Parent namespace:", 50)
        export_policy = ui.ask_string("Export policy:", 50)
        #
        output = self._srv.invoke(
            "volume-create", "volume", self._volname, "containing-aggr-name",
            aggregate, "efficiency-policy", "default",
            "export-policy", export_policy, "group-id", gid, "user-id",
            os.getuid(), "unix-permissions", permissions, "junction-path",
            os.path.join(path, self.configname), "percentage-snapshot-reserve",
            0, "size", volume_size, "volume-state", "online")
        self._check_netapp_error(output, "Creating volume failed")
        #
        rootelem = NaElement("volume-modify-iter")
        attrelem1 = NaElement("attributes")
        attrelem = NaElement("volume-attributes")
        attrelem1.child_add(attrelem)
        queryelem1 = NaElement("query")
        queryelem = NaElement("volume-attributes")
        queryelem1.child_add(queryelem)
        volid = NaElement("volume-id-attributes")
        volid.child_add_string("name", self._volname)
        queryelem.child_add(volid)
        snapattr = NaElement("volume-snapshot-attributes")
        snapattr.child_add_string("auto-snapshots-enabled", "false")
        snapattr.child_add_string("snapdir-access-enabled", "false")
        autosizeattr = NaElement("volume-autosize-attributes")
        autosizeattr.child_add_string("mode", "grow")
        attrelem.child_add(snapattr)
        attrelem.child_add(autosizeattr)
        rootelem.child_add(attrelem1)
        rootelem.child_add(queryelem1)
        rootelem.child_add_string("max-records", "1")
        output = self._srv.invoke_elem(rootelem)
        self._check_netapp_error(output, "Setting volume options failed.")
        print "Volume created. Please disable automatic snapshot creation through GUI, for some reason it does not work through API."
예제 #2
0
파일: apitest.py 프로젝트: raykuan/docs
        print(response.results_reason() + "\n")
        sys.exit(2)

if (dossl or need_server_cert_verification):
    response = s.set_server_cert_verification(need_server_cert_verification)
    if (response):
        print(response.results_reason() + "\n")
        sys.exit(2)
    if (need_server_cert_verification):
        response = s.set_hostname_verification(need_hostname_verification)
        if (response):
            print(response.results_reason() + "\n")
            sys.exit(2)

if (ca_file):
    response = s.set_ca_certs(ca_file)
    if (response):
        print(response.results_reason() + "\n")
        sys.exit(2)

#
# Set the TCP port used for API invocations on the server.
#
if (use_port != -1) :
    s.set_port(use_port)

# This is needed for -X option.
if (showxml == 2) :
    s.set_debug_style("NA_PRINT_DONT_PARSE")

if (inputxml > 0) :
        print(response.results_reason() + "\n")
        sys.exit(2)

if (dossl or need_server_cert_verification):
    response = s.set_server_cert_verification(need_server_cert_verification)
    if (response):
        print(response.results_reason() + "\n")
        sys.exit(2)
    if (need_server_cert_verification):
        response = s.set_hostname_verification(need_hostname_verification)
        if (response):
            print(response.results_reason() + "\n")
            sys.exit(2)

if (ca_file):
    response = s.set_ca_certs(ca_file)
    if (response):
        print(response.results_reason() + "\n")
        sys.exit(2)

#
# Set the TCP port used for API invocations on the server.
#
if (use_port != -1):
    s.set_port(use_port)

# This is needed for -X option.
if (showxml == 2):
    s.set_debug_style("NA_PRINT_DONT_PARSE")

if (inputxml > 0):