def update_service(ws_id, project_id, service_id, service_data):
    """
    Update the service using the service data from the request

    :param ws_id:
    :param project_id:
    :param service_id:
    :param service_data:
    :return:
    """
    session = db_session()
    project = session.query(Project). \
        filter(Project.id == project_id).first()
    service = session.query(Service). \
        join(Project). \
        join(Workspace). \
        filter(Workspace.id == ws_id). \
        filter(Service.project == project). \
        filter(Service.id == service_id).first()
    if service:
        refs = get_references(service, session)
        old_file_name = get_file_path("nsd", service)
        old_uid = get_uid(service.vendor, service.name, service.version)
        # Parse parameters and update record
        if 'descriptor' in service_data:
            # validate service descriptor
            workspace = session.query(Workspace).filter(Workspace.id == ws_id).first()
            validate_service_descriptor(workspace.ns_schema_index, service_data["descriptor"])
            try:
                newName = shlex.quote(service_data["descriptor"]["name"])
                newVendor = shlex.quote(service_data["descriptor"]["vendor"])
                newVersion = shlex.quote(service_data["descriptor"]["version"])
            except KeyError as ke:
                raise InvalidArgument("Missing key {} in function data".format(str(ke)))
            new_uid = get_uid(newVendor, newName, newVersion)
            if old_uid != new_uid:
                if refs:
                    # keep old version and create new version in db
                    service = Service(newName, newVersion, newVendor, project=project)
                    session.add(service)
                else:
                    service.name = newName
                    service.vendor = newVendor
                    service.version = newVersion
            service.descriptor = json.dumps(service_data["descriptor"])

        if 'meta' in service_data:
            service.meta = json.dumps(service_data["meta"])

        if old_uid != new_uid:
            new_file_name = get_file_path("nsd", service)
            try:
                if not old_file_name == new_file_name:
                    if refs:
                        shutil.copy(old_file_name, new_file_name)
                    else:
                        shutil.move(old_file_name, new_file_name)
            except:
                logger.exception("Could not update descriptor file:")
                raise

        write_ns_vnf_to_disk("nsd", service)
        session.commit()
        return service.as_dict()
    else:
        raise NotFound("Could not update service '{}', because no record was found".format(service_id))
def update_service(ws_id, project_id, service_id, service_data):
    """
    Update the service using the service data from the request
    
    Will also check for references by other services and create a copy if so

    :param ws_id: The Workspace ID
    :param project_id: The project ID
    :param service_id: The service ID
    :param service_data: The service data containing the "descriptor" and optionally some "meta" data
    :return: The updated service data
    """
    session = db_session()
    project = session.query(Project). \
        filter(Project.id == project_id).first()
    service = session.query(Service). \
        join(Project). \
        join(Workspace). \
        filter(Workspace.id == ws_id). \
        filter(Service.project == project). \
        filter(Service.id == service_id).first()
    if service:
        refs = get_references(service, session)
        old_file_name = get_file_path("nsd", service)
        old_uid = get_uid(service.vendor, service.name, service.version)
        # Parse parameters and update record
        if 'descriptor' in service_data:
            # validate service descriptor
            workspace = session.query(Workspace).filter(Workspace.id == ws_id).first()
            validate_service_descriptor(workspace.schema_index, service_data["descriptor"])
            try:
                newName = shlex.quote(service_data["descriptor"]["name"])
                newVendor = shlex.quote(service_data["descriptor"]["vendor"])
                newVersion = shlex.quote(service_data["descriptor"]["version"])
            except KeyError as ke:
                raise InvalidArgument("Missing key {} in function data".format(str(ke)))
            new_uid = get_uid(newVendor, newName, newVersion)
            if old_uid != new_uid:
                if refs:
                    # keep old version and create new version in db
                    service = Service(newName, newVersion, newVendor, project=project)
                    session.add(service)
                else:
                    service.name = newName
                    service.vendor = newVendor
                    service.version = newVersion
            service.descriptor = json.dumps(service_data["descriptor"])

        if 'meta' in service_data:
            service.meta = json.dumps(service_data["meta"])

        if old_uid != new_uid:
            new_file_name = get_file_path("nsd", service)
            try:
                if not old_file_name == new_file_name:
                    if refs:
                        shutil.copy(old_file_name, new_file_name)
                    else:
                        shutil.move(old_file_name, new_file_name)
            except:
                logger.exception("Could not update descriptor file:")
                raise

        write_ns_vnf_to_disk("nsd", service)
        session.commit()
        return service.as_dict()
    else:
        raise NotFound("Could not update service '{}', because no record was found".format(service_id))