Пример #1
0
    def read(self, request, organization, name, version):
        # Get offering
        try:
            org = Organization.objects.get(name=organization)
            offering = Offering.objects.get(owner_organization=org, name=name, version=version)
        except:
            return build_response(request, 404, 'Not found')

        # Get usdl from repository
        try:
            adaptor = RepositoryAdaptor(offering.description_url)
            result = adaptor.download()
        except:
            return build_response(request, 502, 'Bad Gateway')

        # Return the USDL with the origin format
        return HttpResponse(result['data'], status=200, mimetype=result['content_type'])
Пример #2
0
def rollback(provider, profile, json_data, msg):

    # Check the created exceptions in order to determine if is
    # necessary to remove something
    if msg == 'Missing required fields' or msg == 'Invalid version format' \
    or msg == 'The offering already exists':
        return

    # Check files
    dir_name = profile.current_organization.name + '__' + json_data['name'] + '__' + json_data['version']
    path = os.path.join(settings.MEDIA_ROOT, dir_name)

    if os.path.exists(path):
        # Remove all files and directory
        for file_ in os.listdir(path):
            file_path = os.path.join(path, file_)
            os.remove(file_path)

        os.rmdir(path)

    # Check if the offering has been created
    offering = Offering.objects.filter(owner_organization=profile.current_organization, name=json_data['name'], version=json_data['version'])

    remove = False
    if len(offering) > 0:
        offering = offering[0]

        # If the offerings has been created means that the USDL is
        # uploaded in the repository
        if 'offering_description' in json_data:
            remove = True
            url = offering.description_url

        offering.delete()
    else:
        # Check if the usdl was uploaded before the exception
        if 'offerings_description' in json_data:
            repository = Repository.objects.get(name=json_data['repository'])
            repository_adaptor = RepositoryAdaptor(repository.host, 'storeOfferingCollection')
            offering_id = profile.current_organization.name + '__' + json_data['name'] + '__' + json_data['version']

            uploaded = True
            try:
                repository_adaptor.download(name=offering_id, content_type=json_data['offering_description']['content_type'])
            except HTTPError:
                uploaded = False

            if uploaded:
                remove = True
                url = urljoin(repository.host, 'storeOfferingCollection')
                url = urljoin(url, offering_id)

    if remove:
        repository_adaptor = RepositoryAdaptor(url)
        repository_adaptor.delete()
Пример #3
0
def delete_offering(offering):
    # If the offering has been purchased it is not deleted
    # it is marked as deleted in order to allow customers that
    # have purchased the offering to install it if needed

    #delete the usdl description from the repository
    if offering.state == 'deleted':
        raise PermissionDenied('The offering is already deleted')

    parsed_url = urlparse(offering.description_url)
    path = parsed_url.path
    host = parsed_url.scheme + '://' + parsed_url.netloc
    path = path.split('/')
    host += '/' + path[1] + '/' + path[2]
    collection = path[3]

    repository_adaptor = RepositoryAdaptor(host, collection)
    repository_adaptor.delete(path[4])

    index_path = os.path.join(settings.BASEDIR, 'wstore')
    index_path = os.path.join(index_path, 'search')
    index_path = os.path.join(index_path, 'indexes')

    se = SearchEngine(index_path)

    if offering.state == 'uploaded':
        _remove_offering(offering, se)
    else:
        offering.state = 'deleted'
        offering.save()

        # Delete the offering from marketplaces
        for market in offering.marketplaces:
            m = Marketplace.objects.get(pk=market)
            market_adaptor = MarketAdaptor(m.host)
            market_adaptor.delete_service(settings.STORE_NAME, offering.name)

        # Update offering indexes
        if not offering.open:
            se.update_index(offering)

        context = Context.objects.all()[0]
        # Check if the offering is in the newest list
        if offering.pk in context.newest:
            # Remove the offering from the newest list
            newest = context.newest

            if len(newest) < 8:
                newest.remove(offering.pk)
            else:
                # Get the 8 newest offerings using the publication date for sorting
                connection = MongoClient()
                db = connection[settings.DATABASES['default']['NAME']]
                offerings = db.wstore_offering
                newest_off = offerings.find({'state': 'published'}).sort('publication_date', -1).limit(8)

                newest = []
                for n in newest_off:
                    newest.append(str(n['_id']))

            context.newest = newest
            context.save()

        # Check if the offering is in the top rated list
        if offering.pk in context.top_rated:
            # Remove the offering from the top rated list
            top_rated = context.top_rated
            if len(top_rated) < 8:
                top_rated.remove(offering.pk)
            else:
                # Get the 4 top rated offerings
                connection = MongoClient()
                db = connection[settings.DATABASES['default']['NAME']]
                offerings = db.wstore_offering
                top_off = offerings.find({'state': 'published', 'rating': {'$gt': 0}}).sort('rating', -1).limit(8)

                top_rated = []
                for t in top_off:
                    top_rated.append(str(t['_id']))

            context.top_rated = top_rated
            context.save()

        if offering.open:
            _remove_offering(offering, se)
Пример #4
0
def update_offering(offering, data):

    # Check if the offering has been published,
    # if published the offering cannot be updated
    if offering.state != 'uploaded' and not offering.open:
        raise PermissionDenied('The offering cannot be edited')

    dir_name = offering.owner_organization.name + '__' + offering.name + '__' + offering.version
    path = os.path.join(settings.MEDIA_ROOT, dir_name)

    # Update the logo
    if 'image' in data:
        logo_path = offering.image_url
        logo_path = os.path.join(settings.BASEDIR, logo_path[1:])

        # Remove the old logo
        os.remove(logo_path)

        # Save the new logo
        f = open(os.path.join(path, data['image']['name']), "wb")
        dec = base64.b64decode(data['image']['data'])
        f.write(dec)
        f.close()
        offering.image_url = settings.MEDIA_URL + dir_name + '/' + data['image']['name']

    # Update the related images
    if 'related_images' in data:

        # Delete old related images
        for img in offering.related_images:
            old_image = os.path.join(settings.BASEDIR, img[1:])
            os.remove(old_image)

        offering.related_images = []

        # Create new images
        for img in data['related_images']:
            f = open(os.path.join(path, img['name']), "wb")
            dec = base64.b64decode(img['data'])
            f.write(dec)
            f.close()
            offering.related_images.append(settings.MEDIA_URL + dir_name + '/' + img['name'])

    new_usdl = False
    # Update the USDL description
    if 'offering_description' in data:
        usdl_info = data['offering_description']

        repository_adaptor = RepositoryAdaptor(offering.description_url)

        usdl = usdl_info['data']
        repository_adaptor.upload(usdl_info['content_type'], usdl)
        new_usdl = True

    # The USDL document has changed in the repository
    elif 'description_url' in data:
        usdl_info = {}
        usdl_url = data['description_url']

        # Check the link
        if usdl_url != offering.description_url:
            raise ValueError('The provided USDL URL is not valid')

        # Download new content
        repository_adaptor = RepositoryAdaptor(usdl_url)
        accept = "text/plain; application/rdf+xml; text/turtle; text/n3"
        usdl = repository_adaptor.download(content_type=accept)

        usdl_info['content_type'] = usdl['content_type']
        usdl = usdl['data']

        new_usdl = True
    elif 'offering_info' in data:
        usdl_info = {
            'content_type': 'application/rdf+xml'
        }
        # Validate USDL info
        if not 'description' in data['offering_info'] or not 'pricing' in data['offering_info']:
            raise ValueError('Invalid USDL info')

        offering_info = data['offering_info']
        offering_info['image_url'] = offering.image_url

        offering_info['name'] = offering.name

        splited_desc_url = offering.description_url.split('/')

        base_uri = splited_desc_url[0] + '//'
        splited_desc_url.remove(splited_desc_url[0])
        splited_desc_url.remove(splited_desc_url[0])
        splited_desc_url.remove(splited_desc_url[-1])
        splited_desc_url.remove(splited_desc_url[-1])

        for p in splited_desc_url:
            base_uri += (p + '/')

        offering_info['base_uri'] = base_uri

        usdl = _create_basic_usdl(offering_info)
        usdl_info = {
            'content_type': 'application/rdf+xml'
        }

        repository_adaptor = RepositoryAdaptor(offering.description_url)
        repository_adaptor.upload(usdl_info['content_type'], usdl)
        new_usdl = True

    # If the USDL has changed store the new description
    # in the offering model
    if new_usdl:
        # Validate the USDL
        valid = validate_usdl(usdl, usdl_info['content_type'], {
            'name': offering.name,
            'organization': offering.owner_organization
        })

        if not valid[0]:
            raise ValueError(valid[1])

        # Serialize and store USDL info in json-ld format
        graph = rdflib.Graph()

        rdf_format = usdl_info['content_type']

        if usdl_info['content_type'] == 'text/turtle' or usdl_info['content_type'] == 'text/plain':
            rdf_format = 'n3'
        elif usdl_info['content_type'] == 'application/json':
            rdf_format = 'json-ld'

        off_description = usdl
        if rdf_format != 'json-ld':
            graph.parse(data=usdl, format=rdf_format)
            off_description = graph.serialize(format='json-ld', auto_compact=True)

        offering.offering_description = json.loads(off_description)

    offering.save()

    # Update offering indexes
    index_path = os.path.join(settings.BASEDIR, 'wstore')
    index_path = os.path.join(index_path, 'search')
    index_path = os.path.join(index_path, 'indexes')

    se = SearchEngine(index_path)
    se.update_index(offering)
Пример #5
0
def create_offering(provider, json_data):

    profile = provider.userprofile
    data = {}
    if not 'name' in json_data or not 'version' in json_data:
        raise ValueError('Missing required fields')

    data['name'] = json_data['name']
    data['version'] = json_data['version']

    if not re.match(re.compile(r'^(?:[1-9]\d*\.|0\.)*(?:[1-9]\d*|0)$'), data['version']):
        raise ValueError('Invalid version format')

    if not is_valid_id(data['name']):
        raise ValueError('Invalid name format')

    # Get organization
    organization = profile.current_organization

    # Check if the offering already exists
    existing = True

    try:
        Offering.objects.get(name=data['name'], owner_organization=organization, version=data['version'])
    except:
        existing = False

    if existing:
        raise Exception('The offering already exists')

    # Check if the version of the offering is lower than an existing one
    offerings = Offering.objects.filter(owner_organization=organization, name=data['name'])
    for off in offerings:
        if is_lower_version(data['version'], off.version):
            raise ValueError('A bigger version of the current offering exists')

    is_open = json_data.get('open', False)

    # If using the idm, get the applications from the request
    if settings.OILAUTH:

        # Validate application structure
        data['applications'] = []

        for app in json_data['applications']:
            data['applications'].append({
                'name': app['name'],
                'url': app['url'],
                'id': app['id'],
                'description': app['description']
            })

    data['related_images'] = []

    # Check the URL to notify the provider
    notification_url = ''

    if 'notification_url' in json_data:
        if json_data['notification_url'] == 'default':
            notification_url = organization.notification_url
            if not notification_url:
                raise ValueError('There is not a default notification URL defined for the organization ' + organization.name + '. To configure a default notification URL provide it in the settings menu')
        else:
            # Check the notification URL
            if not is_valid_url(json_data['notification_url']):
                raise ValueError("Invalid notification URL format: It doesn't seem to be an URL")

            notification_url = json_data['notification_url']

    # Create the directory for app media
    dir_name = organization.name + '__' + data['name'] + '__' + data['version']
    path = os.path.join(settings.MEDIA_ROOT, dir_name)
    os.makedirs(path)

    if not 'image' in json_data:
        raise ValueError('Missing required field: Logo')

    if not isinstance(json_data['image'], dict):
        raise TypeError('Invalid image type')

    image = json_data['image']

    if not 'name' in image or not 'data' in image:
        raise ValueError('Missing required field in image')

    # Save the application image or logo
    f = open(os.path.join(path, image['name']), "wb")
    dec = base64.b64decode(image['data'])
    f.write(dec)
    f.close()

    data['image_url'] = settings.MEDIA_URL + dir_name + '/' + image['name']
    # Save screen shots
    if 'related_images' in json_data:
        for image in json_data['related_images']:

            # images must be encoded in base64 format
            f = open(os.path.join(path, image['name']), "wb")
            dec = base64.b64decode(image['data'])
            f.write(dec)
            f.close()

            data['related_images'].append(settings.MEDIA_URL + dir_name + '/' + image['name'])

    # Save USDL document
    # If the USDL itself is provided

    if 'offering_description' in json_data:
        usdl_info = json_data['offering_description']

        repository = Repository.objects.get(name=json_data['repository'])
        repository_adaptor = RepositoryAdaptor(repository.host, 'storeOfferingCollection')
        offering_id = organization.name + '__' + data['name'] + '__' + data['version']

        usdl = usdl_info['data']
        data['description_url'] = repository_adaptor.upload(usdl_info['content_type'], usdl_info['data'], name=offering_id)

    # If the USDL is already uploaded in the repository
    elif 'description_url' in json_data:

        # Check that the link to USDL is unique since could be used to
        # purchase offerings from Marketplace
        usdl_info = {}
        usdl_url = json_data['description_url']
        off = Offering.objects.filter(description_url=usdl_url)

        if len(off) != 0:
            raise ValueError('The provided USDL description is already registered')

        # Download the USDL from the repository
        repository_adaptor = RepositoryAdaptor(usdl_url)
        accept = "text/plain; application/rdf+xml; text/turtle; text/n3"

        usdl = repository_adaptor.download(content_type=accept)
        usdl_info['content_type'] = usdl['content_type']

        usdl = usdl['data']
        data['description_url'] = usdl_url

    # If the USDL is going to be created
    elif 'offering_info' in json_data:

        _validate_offering_info(json_data['offering_info'])

        offering_info = json_data['offering_info']
        offering_info['image_url'] = data['image_url']
        offering_info['name'] = data['name']

        repository = Repository.objects.get(name=json_data['repository'])

        offering_info['base_uri'] = repository.host

        usdl = _create_basic_usdl(offering_info)
        usdl_info = {
            'content_type': 'application/rdf+xml'
        }

        repository_adaptor = RepositoryAdaptor(repository.host, 'storeOfferingCollection')
        offering_id = organization.name + '__' + data['name'] + '__' + data['version']
        data['description_url'] = repository_adaptor.upload(usdl_info['content_type'], usdl, name=offering_id)
    else:
        raise Exception('No USDL description provided')

    # Validate the USDL
    data['open'] = is_open
    data['organization'] = organization
    valid = validate_usdl(usdl, usdl_info['content_type'], data)

    if not valid[0]:
        raise Exception(valid[1])

    # Check new currencies used
    if len(valid) > 2:
        new_curr = valid[2]

        # Set the currency as used
        cont = Context.objects.all()[0]
        currency = None
        # Search the currency
        for c in cont.allowed_currencies['allowed']:
            if c['currency'].lower() == new_curr.lower():
                currency = c
                break

        cont.allowed_currencies['allowed'].remove(currency)
        currency['in_use'] = True
        cont.allowed_currencies['allowed'].append(currency)
        cont.save()

    # Serialize and store USDL info in json-ld format
    graph = rdflib.Graph()
    rdf_format = usdl_info['content_type']

    if rdf_format == 'text/turtle' or rdf_format == 'text/plain':
            rdf_format = 'n3'
    elif rdf_format == 'application/json':
            rdf_format = 'json-ld'

    graph.parse(data=usdl, format=rdf_format)
    data['offering_description'] = graph.serialize(format='json-ld', auto_compact=True)

    # Create the offering
    offering = Offering.objects.create(
        name=data['name'],
        owner_organization=organization,
        owner_admin_user=provider,
        version=data['version'],
        state='uploaded',
        description_url=data['description_url'],
        resources=[],
        comments=[],
        tags=[],
        image_url=data['image_url'],
        related_images=data['related_images'],
        offering_description=json.loads(data['offering_description']),
        notification_url=notification_url,
        creation_date=datetime.now(),
        open=is_open
    )

    if settings.OILAUTH:
        offering.applications = data['applications']
        offering.save()

    if 'resources' in json_data and len(json_data['resources']) > 0:
        bind_resources(offering, json_data['resources'], profile.user)

    # Load offering document to the search index
    index_path = os.path.join(settings.BASEDIR, 'wstore')
    index_path = os.path.join(index_path, 'search')
    index_path = os.path.join(index_path, 'indexes')

    search_engine = SearchEngine(index_path)
    search_engine.create_index(offering)
Пример #6
0
def rollback(provider, profile, json_data, msg):

    # Check the created exceptions in order to determine if is
    # necessary to remove something
    if msg == "Missing required fields" or msg == "Invalid version format" or msg == "The offering already exists":
        return

    # Check files
    dir_name = profile.current_organization.name + "__" + json_data["name"] + "__" + json_data["version"]
    path = os.path.join(settings.MEDIA_ROOT, dir_name)

    if os.path.exists(path):
        # Remove all files and directory
        for file_ in os.listdir(path):
            file_path = os.path.join(path, file_)
            os.remove(file_path)

        os.rmdir(path)

    # Check if the offering has been created
    offering = Offering.objects.filter(
        owner_organization=profile.current_organization, name=json_data["name"], version=json_data["version"]
    )

    remove = False
    if len(offering) > 0:
        offering = offering[0]

        # If the offerings has been created means that the USDL is
        # uploaded in the repository
        if "offering_description" in json_data:
            remove = True
            url = offering.description_url

        # Check if the offering has been bound
        if len(offering.resources):
            for res in offering.resources:
                re = Resource.objects.get(pk=unicode(res))
                re.offerings.remove(offering.pk)
                re.save()

        offering.delete()
    else:
        # Check if the usdl was uploaded before the exception
        if "offerings_description" in json_data:
            repository = Repository.objects.get(name=json_data["repository"])
            repository_adaptor = RepositoryAdaptor(repository.host, "storeOfferingCollection")
            offering_id = profile.current_organization.name + "__" + json_data["name"] + "__" + json_data["version"]

            uploaded = True
            try:
                repository_adaptor.download(
                    name=offering_id, content_type=json_data["offering_description"]["content_type"]
                )
            except HTTPError:
                uploaded = False

            if uploaded:
                remove = True
                url = urljoin(repository.host, "storeOfferingCollection")
                url = urljoin(url, offering_id)

    if remove:
        repository_adaptor = RepositoryAdaptor(url)
        repository_adaptor.delete()