def bind_resources(offering, data, provider): # Check that the offering supports binding if offering.state != 'uploaded' and not (offering.open and offering.state == 'published'): raise PermissionDenied('This offering cannot be modified') added_resources = [] offering_resources = [] for of_res in offering.resources: offering_resources.append(of_res) for res in data: try: resource = Resource.objects.get(name=res['name'], version=res['version'], provider=provider.userprofile.current_organization) except: raise ValueError('Resource not found: ' + res['name'] + ' ' + res['version']) # Check resource state if resource.state == 'deleted': raise PermissionDenied('Invalid resource, the resource ' + res['name'] + ' ' + res['version'] + ' is deleted') # Check open if not resource.open and offering.open: raise PermissionDenied('It is not allowed to include not open resources in an open offering') if not ObjectId(resource.pk) in offering_resources: added_resources.append(resource.pk) else: offering_resources.remove(ObjectId(resource.pk)) # added_resources contains the resources to be added to the offering # and offering_resources the resources to be deleted from the offering for add_res in added_resources: resource = Resource.objects.get(pk=add_res) resource.offerings.append(offering.pk) resource.save() offering.resources.append(ObjectId(add_res)) for del_res in offering_resources: resource = Resource.objects.get(pk=del_res) resource.offerings.remove(offering.pk) resource.save() offering.resources.remove(del_res) offering.offering_description['modified'] = unicode(datetime.now()) offering.save() # Update USDL document if needed if offering.open and offering.state == 'published' and len(offering.description_url): usdl_generator = USDLGenerator() repository_adaptor = unreg_repository_adaptor_factory(offering.description_url) if settings.OILAUTH: repository_adaptor.set_credentials(provider.userprofile.access_token) repository_adaptor.upload( 'application/rdf+xml', usdl_generator.generate_offering_usdl(offering)[0] )
def _aggregate_text(self, offering): """ Create a single string for creating the index by extracting text fields from the USDL document of the offering """ graph = rdflib.ConjunctiveGraph() generator = USDLGenerator() graph.parse(data=generator.generate_offering_usdl(offering)[0], format='application/rdf+xml') text = offering.name for s, p, o in graph: if isinstance(o, rdflib.Literal): text += ' ' + unicode(o) return text
def _aggregate_text(self, offering): """ Create a single string for creating the index by extracting text fields from the USDL document of the offering """ graph = rdflib.ConjunctiveGraph() generator = USDLGenerator() graph.parse( data=generator.generate_offering_usdl(offering)[0], format='application/rdf+xml' ) text = offering.name for s, p, o in graph: if isinstance(o, rdflib.Literal): text += ' ' + unicode(o) return text
def publish_offering(user, offering, data): # Validate data if 'marketplaces' not in data: raise ValueError('Publication error: missing required field, marketplaces') # Validate the state of the offering if not offering.state == 'uploaded': raise PermissionDenied('Publication error: The offering ' + offering.name + ' ' + offering.version + ' cannot be published') # Validate the offering has enough content to be published # Open offerings cannot be published in they do not contain # digital assets (applications or resources) if offering.open and not len(offering.resources) and not len(offering.applications): raise PermissionDenied('Publication error: Open offerings cannot be published if they do not contain at least a digital asset (resource or application)') # Check if it possible to publish the offering in a Marketplace if not len(Repository.objects.all()) > 0 and len(data['marketplaces']) > 0: raise PermissionDenied('Publication error: It is not possible to publish an offering in a Markteplace if no Repositories has been registered') # Upload the USDL description of the offering to the repository if len(Repository.objects.all()) > 0: repository = Repository.objects.get(is_default=True) # Generate the USDL of the offering generator = USDLGenerator() usdl, offering_uri = generator.generate_offering_usdl(offering) repository_adaptor = repository_adaptor_factory(repository) offering_id = offering.owner_organization.name + '__' + offering.name + '__' + offering.version repository_adaptor.set_uri(offering_uri) if settings.OILAUTH: repository_adaptor.set_credentials(user.userprofile.access_token) offering.description_url = repository_adaptor.upload('application/rdf+xml', usdl, name=offering_id) # Publish the offering in the selected marketplaces for market in data['marketplaces']: try: m = Marketplace.objects.get(name=market) except: raise ValueError('Publication error: The marketplace ' + market + ' does not exist') market_adaptor = marketadaptor_factory(m, user) off_market_name = market_adaptor.add_service(offering) offering.marketplaces.append(MarketOffering( marketplace=m, offering_name=off_market_name )) # Create revenue sharing models if needed build_rs_model(offering) offering.state = 'published' offering.publication_date = datetime.now() 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 update_offering(user, 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 _save_encoded_image(path, data['image']['name'], data['image']['data']) 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']: _save_encoded_image(path, img['name'], img['data']) offering.related_images.append(settings.MEDIA_URL + dir_name + '/' + img['name']) if 'offering_description' in data: # Create offering USDL offering_info = deepcopy(data['offering_description']) offering_info['image_url'] = offering.image_url offering_info['name'] = offering.name offering_info['version'] = offering.version offering_info['organization'] = offering.owner_organization.name offering_info['base_id'] = offering.pk offering_info['created'] = unicode(offering.creation_date) mod = unicode(datetime.now()) offering_info['modified'] = mod usdl_generator = USDLGenerator() usdl_generator.validate_info(offering_info, offering.owner_organization, open_=offering.open) data['offering_description']['modified'] = mod offering.offering_description = data['offering_description'] if offering.open and offering.state == 'published' and len(offering.description_url): repository_adaptor = unreg_repository_adaptor_factory(offering.description_url) if settings.OILAUTH: repository_adaptor.set_credentials(user.userprofile.access_token) repository_adaptor.upload( 'application/rdf+xml', usdl_generator.generate_offering_usdl(offering)[0] ) 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, data): """ Creates a new offering including the media files and the repository uploads """ profile = provider.userprofile # Validate basic fields if 'name' not in data or 'version' not in data or 'offering_description' not in data \ or 'image' not in data: missing_fields = '' if 'name' not in data: missing_fields += ' name' if 'version' not in data: missing_fields += ' version' if 'offering_description' not in data: missing_fields += ' offering_description' if 'image' not in data: missing_fields += ' image' raise ValueError('Missing required fields:' + missing_fields) 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 if len(Offering.objects.filter(name=data['name'], owner_organization=organization, version=data['version'])) > 0: raise ConflictError('The offering ' + data['name'] + ' version ' + data['version'] + ' 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 = data.get('open', False) # If using the idm, get the applications from the request if settings.OILAUTH and 'applications' in data: # Validate application structure for app in data['applications']: if 'name' not in app or 'url' not in app or 'id' not in app or 'description' not in app: raise ValueError('Missing a required field in application definition') # Check the URL to notify the provider notification_url = '' if 'notification_url' in data: if 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(data['notification_url']): raise ValueError("Invalid notification URL format: It doesn't seem to be an URL") notification_url = 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) # Validate image format if not isinstance(data['image'], dict): raise TypeError('Invalid image type') data['image_url'] = _create_image(dir_name, path, data['image']) # Save screen shots screenshots = [] if 'related_images' in data: for image in data['related_images']: screenshots.append(_create_image(dir_name, path, image)) else: data['related_images'] = [] # Validate the USDL data['open'] = is_open data['organization'] = organization # Create offering USDL offering_info = deepcopy(data['offering_description']) offering_info['image_url'] = data['image_url'] offering_info['name'] = data['name'] offering_info['version'] = data['version'] offering_info['organization'] = organization.name offering_info['base_id'] = 'pk' created = datetime.now() offering_info['created'] = unicode(created) offering_info['modified'] = unicode(created) data['offering_description']['modified'] = unicode(created) usdl_generator = USDLGenerator() usdl_generator.validate_info(offering_info, organization, open_=is_open) # Create the offering offering = Offering( name=data['name'], owner_organization=organization, owner_admin_user=provider, version=data['version'], state='uploaded', resources=[], comments=[], tags=[], image_url=data['image_url'], related_images=screenshots, notification_url=notification_url, creation_date=created, open=is_open, offering_description=data['offering_description'] ) if settings.OILAUTH and 'applications' in data: offering.applications = data['applications'] offering.save() offering.offering_description['base_id'] = offering.pk offering.save() if 'resources' in data and len(data['resources']) > 0: bind_resources(offering, 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)