#!/usr/bin/python

import logging, optparse
import suds

#
# copy config params from 'nova.conf'
#
netapp_wsdl_url='http://127.0.0.1:8080/dfm.wsdl'
netapp_login='dfm'
netapp_password='dfm'
netapp_server_hostname='127.0.0.1'
netapp_server_port=8088
netapp_storage_service='openstack_service'

logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO,)
#logging.getLogger('suds.client').setLevel(logging.DEBUG)
#logging.getLogger('suds.transport').setLevel(logging.DEBUG)
#logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
#logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)

class ViewModifyMetadata(object):

    DATASET_METADATA_PROJECT_KEY = 'OpenStackProject'
    DATASET_METADATA_VOL_TYPE_KEY = 'OpenStackVolType'

    def __init__(self):
        logging.info('Initializing soap client ..')
        self.client = suds.client.Client(netapp_wsdl_url, username=netapp_login, password=netapp_password)
        soap_url = 'http://%s:%s/apis/soap/v1' % (netapp_server_hostname, netapp_server_port)
        self.client.set_options(location=soap_url)
        logging.info('Init done.')

    def _get_datasets(self):
        """Get the list of datasets from DFM."""
        server = self.client.service
        res = server.DatasetListInfoIterStart(IncludeMetadata=True)
        tag = res.Tag
        datasets = []
        try:
            while True:
                res = server.DatasetListInfoIterNext(Tag=tag, Maximum=100)
                if not res.Datasets:
                    break
                datasets.extend(res.Datasets.DatasetInfo)
        finally:
            server.DatasetListInfoIterEnd(Tag=tag)
        return datasets

    def command_view(self):
        for d in self._get_datasets():
            print d.DatasetName
            meta = str(d.DatasetMetadata)
            indented_meta = '\n'.join((4 * ' ') + i for i in meta.splitlines())
            print indented_meta

    def command_update(self, dataset, project, volume_type):
        factory = self.client.factory
        server = self.client.service

        metadata = factory.create('ArrayOfDfmMetadataField')

        field = factory.create('DfmMetadataField')
        field.FieldName = self.DATASET_METADATA_PROJECT_KEY
        field.FieldValue = project
        metadata.DfmMetadataField = [field]

        if volume_type:
            field = factory.create('DfmMetadataField')
            field.FieldName = self.DATASET_METADATA_VOL_TYPE_KEY
            field.FieldValue = volume_type
            metadata.DfmMetadataField.append(field)

        logging.info('Metadata to be set\n'+str(metadata))

        logging.info('Updating metadata for %s..' % dataset)
        lock_id = server.DatasetEditBegin(DatasetNameOrId=dataset)
        try:
            server.DatasetModify(EditLockId=lock_id,
                                       DatasetMetadata=metadata)
            res = server.DatasetEditCommit(EditLockId=lock_id,
                                           AssumeConfirmation=True)
            logging.info('Update done.')
        except (suds.WebFault, Exception):
            server.DatasetEditRollback(EditLockId=lock_id)
            logging.error('Update FAILED.')

parser = optparse.OptionParser(usage="""usage: %prog [options] [update <dataset-name>]

Simple tool to view (or update) DFM Openstack metadata about a dataset.
Without arguments, it will print all datasets with associated metadata.
With 'update' argument you can update metadata for one dataset identified by name.

Example:
%prog -p 01c14892d4a34765bdec8c576cf8b524 update Openstack_01c14892d4a34765bdec8c576cf8b524

..will set 'OpenStackProject' field to '01c14892d4a34765bdec8c576cf8b524'

With 'update', you must specify project (-p). Volume type (-t) is optional.""")
parser.add_option('-p', '', dest='project', default=None,
                  help='project ID to set in "OpenStackProject" field (eg. 01c14892d4a34765bdec8c576cf8b524)', metavar='ID')
parser.add_option('-t', '', dest='volume_type', default=None,
                  help='volume type to set in "OpenStackVolType" field')

(options, args) = parser.parse_args()

try:
    assert len(args) in (0, 2), 'Incorrect number of arguments (see -h for help)'

    if len(args) == 0:
        i = ViewModifyMetadata()
        i.command_view()
    else:
        assert args[0] == 'update', 'Unknown argument (see -h for help)'
        assert options.project is not None, 'Missing mandatory project id'
        i = ViewModifyMetadata()
        i.command_update(args[1], options.project, options.volume_type)

except AssertionError, e:
    print e

