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'])
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()
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)
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)
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)
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()