예제 #1
0
def add_resource(username,
                 id,
                 node_type,
                 cardinality,
                 description,
                 testbed,
                 file=None):
    """
    Creates a new ResourceMetadata object and stores it in the database.
    If the file parameter is not None, it is expected to be of type FileUpload from the bottle module or str.
    In the former case the file is stored where the available NSDs reside (/etc/softfire/experiment-nsd-csar).
    In the latter case the file parameter should contain the file name so it can be added to the ResourceMetadata.

    :param id:
    :param node_type:
    :param cardinality:
    :param description:
    :param testbed:
    :param file:
    :return: the ResourceMetadata ID
    """
    logger.debug('Add new resource')
    if username is None or username == '':
        raise Exception('Username must not be None or empty.')
    resource_metadata = ResourceMetadata()
    resource_metadata.user = username
    resource_metadata.id = id
    resource_metadata.description = description
    resource_metadata.cardinality = cardinality
    resource_metadata.node_type = node_type
    resource_metadata.testbed = testbed
    resource_metadata.properties = {}

    if file:
        if isinstance(file, FileUpload):  # method call comes directly from api
            logger.debug('File is provided')
            nsd_csar_location = get_config(
                'system', 'temp-csar-location',
                '/etc/softfire/experiment-nsd-csar').rstrip('/')
            nsd_csar_location = '{}/{}'.format(nsd_csar_location, username)
            if not os.path.exists(nsd_csar_location):
                os.makedirs(nsd_csar_location)
            logger.debug('Save file as {}/{}'.format(nsd_csar_location,
                                                     file.filename))
            file.save('{}/{}'.format(nsd_csar_location, file.filename),
                      overwrite=True)
            resource_metadata.properties['nsd_file_name'] = file.filename
        elif isinstance(file, str):  # only the file name is provided
            logger.debug('File name is provided')
            resource_metadata.properties['nsd_file_name'] = file

    save(resource_metadata, ResourceMetadata)
    logger.debug('Saved ResourceMetadata with ID: %s' % id)
    return resource_metadata.id
예제 #2
0
def refresh_resources(username, manager_name=None):
    managers = []
    if manager_name is None:
        for man in find(ManagerEndpoint):
            managers.append(man.name)
    else:
        managers.append(manager_name)

    user_info = get_user_info(username)
    result = []
    if user_info:
        for manager in managers:
            stub = get_stub_from_manager_name(manager)
            request_message = user_info
            try:
                response = stub.refresh_resources(request_message)
            except _Rendezvous:
                traceback.print_exc()
                logger.error(
                    "Exception while calling gRPC, maybe %s Manager is down?" %
                    manager)
                raise RpcFailedCall(
                    "Exception while calling gRPC, maybe %s Manager is down?" %
                    manager)
            if response.result != 0:
                logger.error("list resources returned %d: %s" %
                             (response.result, response.error_message))
                raise RpcFailedCall("list resources returned %d: %s" %
                                    (response.result, response.error_message))
            result.extend(response.list_resource.resources)

    logger.debug("Saving %d resources" % len(result))

    for rm in find(entities.ResourceMetadata):
        if rm.node_type in REFRESH_RES_NODE_TYPES:
            delete(rm)

    for rm in result:
        resource_metadata = ResourceMetadata()
        if rm.resource_id and (not hasattr(rm, 'user') or rm.user == username):
            resource_metadata.id = rm.resource_id
            resource_metadata.description = rm.description
            resource_metadata.cardinality = rm.cardinality
            resource_metadata.node_type = rm.node_type
            if hasattr(rm, 'user') and rm.user:
                resource_metadata.user = rm.user
            else:
                resource_metadata.user = ''
            resource_metadata.testbed = list(TESTBED_MAPPING.keys())[list(
                TESTBED_MAPPING.values()).index(rm.testbed)]
            save(resource_metadata, ResourceMetadata)

    return result
예제 #3
0
    def reserve(self):
        used_resources = []
        for node in self.topology_template.nodetemplates:
            used_resource = _get_used_resource_from_node(node, self.username)
            used_resources.append(used_resource)
            CalendarManager.check_availability_for_node(used_resource)
        try:
            CalendarManager.check_overlapping_resources(used_resources)
        except ExperimentValidationError as e:
            delete(self.experiment)
            raise e
        # all node have been granted

        for us in self.experiment.resources:
            us.status = ResourceStatus.RESERVED.value

        save(self.experiment)
 def register(self, request, context):
     logger.info("registering %s" % request.name)
     old_managers = find_by_element_value(ManagerEndpoint,
                                          ManagerEndpoint.name,
                                          request.name)
     for old_man in old_managers:
         delete(old_man)
         logger.debug("Removed old manager endpoint: %s:%s" %
                      (old_man.name, old_man.endpoint))
     manager_endpoint = ManagerEndpoint()
     manager_endpoint.name = request.name
     manager_endpoint.endpoint = request.endpoint
     save(manager_endpoint, ManagerEndpoint)
     list_resources()
     response_message = messages_pb2.ResponseMessage()
     response_message.result = 0
     return response_message
예제 #5
0
def _save_or_create_experimenter(user_info, role="experimenter"):
    old_experimenter = find_by_element_value(Experimenter,
                                             Experimenter.username,
                                             user_info.name)
    if not old_experimenter:
        experimenter = Experimenter()
    else:
        experimenter = old_experimenter[0]

    experimenter.username = user_info.name
    experimenter.password = user_info.password
    experimenter.role = role
    experimenter.testbed_tenants = {}
    experimenter.ob_project_id = user_info.ob_project_id
    for k, v in user_info.testbed_tenants.items():
        experimenter.testbed_tenants[k] = v
    save(experimenter)
    return experimenter
def check_endpoint():
    manager_unavailable_times = get_config('system', 'manager-unavailable',
                                           '5')
    while not stop.wait(int(get_config('system', 'manager-check-delay',
                                       '20'))):
        for endpoint in find(ManagerEndpoint):
            try:
                get_stub_from_manager_endpoint(endpoint).heartbeat(Empty())
            except:
                logger.error("Exception calling heartbeat for manager %s" %
                             endpoint.name)
                if logger.isEnabledFor(logging.DEBUG):
                    traceback.print_exc()
                if endpoint.unavailability >= int(manager_unavailable_times):
                    logger.error("Manager %s on endpoint %s is not running" %
                                 (endpoint.name, endpoint.endpoint))
                    MessagingAgent.unregister_endpoint(endpoint.name)
                else:
                    endpoint.unavailability += 1
                    save(endpoint)
예제 #7
0
def update_experiment(username, manager_name, resources):
    experiments = find_by_element_value(entities.Experiment,
                                        entities.Experiment.username, username)
    try:
        for new_res in resources:
            new_res_dict = json.loads(new_res.content)
            for experiment in experiments:
                for ur in experiment.resources:
                    if manager_name == 'nfv-manager' and ur.node_type == 'NfvResource':
                        try:
                            val_dict = json.loads(ur.value)
                        except Exception as e:
                            logger.warning(
                                "Failed parsing of experiment: name: %s, username: %s"
                                % (experiment.name, experiment.username))
                            raise e
                        if ur.node_type in get_mapping_managers().get(manager_name) \
                                and val_dict.get('id') == new_res_dict.get('id'):
                            ur.value = json.dumps(new_res_dict)
                    elif manager_name == 'security-manager' and ur.node_type == 'SecurityResource':
                        try:
                            val_dict = json.loads(ur.value)
                        except Exception as e:
                            logger.warning(
                                "Failed parsing of experiment: name: %s, username: %s"
                                % (experiment.name, experiment.username))
                            raise e
                        if val_dict.get('random_id') == new_res_dict.get(
                                'random_id'):
                            ur.value = json.dumps(new_res_dict)
                    else:
                        if ur.node_type in get_mapping_managers().get(
                                manager_name):
                            ur.value = json.dumps(new_res_dict)
                save(experiment)
    except:
        logger.warning(
            "error while updating resource of manager %s. Error is: %s " %
            (manager_name, traceback._cause_message))
예제 #8
0
def _provide_all_resources_for_manager(experiment_to_deploy,
                                       manager_name,
                                       user_info,
                                       value_to_pass=None):
    if value_to_pass is None:
        value_to_pass = {}
    stub = get_stub_from_manager_name(manager_name)
    ret = []
    for ur_to_deploy in experiment_to_deploy.resources:
        node_types = get_mapping_managers().get(manager_name)
        if ur_to_deploy.node_type in node_types:
            if value_to_pass:
                val = json.loads(ur_to_deploy.value)
                val.get('properties').update(value_to_pass)
                yaml_dump = json.dumps(val)
                ur_to_deploy.value = yaml_dump
            response = stub.execute(
                messages_pb2.RequestMessage(
                    method=messages_pb2.PROVIDE_RESOURCES,
                    payload=ur_to_deploy.value,
                    user_info=user_info))
            for ur in experiment_to_deploy.resources:
                if ur.id == ur_to_deploy.id:
                    if response.result == messages_pb2.ERROR:
                        logger.error("provide resources returned %d: %s" %
                                     (response.result, response.error_message))
                        ur.status = ResourceStatus.ERROR.value
                        ur.value = json.dumps(response.error_message)
                    else:
                        # TODO fix this in the api not here
                        for res in response.provide_resource.resources:
                            logger.debug("Received: %s" % str(res.content))
                            _res_dict = json.loads(res.content)
                            ur.value = json.dumps(_res_dict)
                            ret.append(_res_dict)
                            ur.status = ResourceStatus.DEPLOYED.value
                    save(ur)

    return ret
예제 #9
0
def list_resources(username='', manager_name=None):
    managers = []
    if manager_name is None:
        for man in find(ManagerEndpoint):
            managers.append(man.name)
    else:
        managers.append(manager_name)

    result = []
    # List resources can be done in parallel
    max_workers = len(managers)
    tpe = ThreadPoolExecutor(max_workers=max_workers)
    threads = []
    for manager in managers:
        threads.append(tpe.submit(_execute_rpc_list_res, manager))
    for t in threads:
        result.extend(t.result())

    logger.debug("Saving %d resources" % len(result))

    for rm in find(entities.ResourceMetadata):
        for rm_to_del in result:
            if rm.id == rm_to_del.resource_id:
                delete(rm)

    for rm in result:
        if username == '' or rm.user == username:
            resource_metadata = ResourceMetadata()
            if not username is None:
                resource_metadata.user = username
            resource_metadata.id = rm.resource_id
            resource_metadata.description = rm.description
            resource_metadata.cardinality = rm.cardinality
            resource_metadata.node_type = rm.node_type
            resource_metadata.testbed = _get_testbed_string(rm.testbed)
            save(resource_metadata, ResourceMetadata)

    return result
예제 #10
0
    def __init__(self, file_path, username):
        self.username = username
        self.file_path = file_path
        zf = zipfile.ZipFile(self.file_path)
        for info in zf.infolist():
            filename = info.filename
            logger.debug("Filename: %s" % filename)
            if filename.endswith(".yaml") and filename.startswith(
                    "Definitions/"):
                logger.debug("parsing %s..." % filename)
                try:
                    tpl = ToscaTemplate(
                        yaml_dict_tpl=yaml.load(zf.read(filename)))
                except Exception as e:
                    if hasattr(e, 'message'):
                        raise ExperimentValidationError(e.message)
                    elif isinstance(e.args, list):
                        raise ExperimentValidationError(e.args[0])
                    elif isinstance(e.args, str):
                        raise ExperimentValidationError(e.args)
                    else:
                        raise ExperimentValidationError(
                            "no message available", e)

                for node in tpl.nodetemplates:
                    logger.debug(
                        "Found node: %s of type %s with properties: %s" %
                        (node.name, node.type,
                         list(node.get_properties().keys())))
                self.topology_template = tpl
            if filename == 'TOSCA-Metadata/Metadata.yaml':
                metadata = yaml.load(zf.read(filename))
                self.name = metadata.get('name')
                if find(entities.Experiment,
                        '{}_{}'.format(self.username, self.name)) is not None:
                    raise ExperimentValidationError(
                        'There is already an experiment with this name, please choose a different one.'
                    )
                # 12/12/12 10:55
                self.start_date = self.get_start_date(metadata)
                # 12/12/12 11:55
                self.end_date = self.get_end_date(metadata)
                today = datetime.today().date()
                logger.info("End date: date: %s" % self.end_date.date())
                if self.end_date.date() < today:
                    logger.error(
                        'For the experiment {} the end date({}) is in the past.'
                        .format(self.name, self.end_date.date()))
                    raise ExperimentValidationError(
                        'For the experiment {} the end date({}) is in the past.'
                        .format(self.name, self.end_date.date()))
                self.duration = self.end_date - self.start_date
                logger.debug("Experiment duration %s" % self.duration)
            if filename.startswith("Files/") and filename.endswith('.csar'):

                experiment_nsd_csar_location = get_config(
                    'system', 'temp-csar-location',
                    '/etc/softfire/experiment-nsd-csar')

                experiment_nsd_csar_location = '{}/{}'.format(
                    experiment_nsd_csar_location.rstrip('/'), username)
                if not os.path.exists(experiment_nsd_csar_location):
                    os.makedirs(experiment_nsd_csar_location)
                data = zf.read(filename)

                nsd_file_location = "%s/%s" % (experiment_nsd_csar_location,
                                               filename.split('/')[-1])
                with open(nsd_file_location, 'wb+') as f:
                    f.write(data)
        temp_ids = []
        for node in self.topology_template.nodetemplates:
            if node.type == 'NfvResource':
                file_name = node.get_properties().get('file_name')
                if file_name:
                    file_name = file_name.value
                if file_name and file_name.startswith(
                        "Files/") and file_name.endswith(".csar"):
                    real_file_name = file_name[6:]
                    tmp_file_location = '{}/{}/{}'.format(
                        get_config(
                            'system', 'temp-csar-location',
                            '/etc/softfire/experiment-nsd-csar').rstrip('/'),
                        username, real_file_name)
                    # get the description
                    try:
                        zf = zipfile.ZipFile(tmp_file_location)
                    except FileNotFoundError:
                        logger.error(
                            "Please check that the file_name property is correctly set to the file name passed."
                        )
                        raise ExperimentValidationError(
                            "Please check that the file_name property is correctly set to the file name passed."
                        )
                    try:
                        filenames = [
                            zipinfo.filename for zipinfo in zf.filelist
                        ]
                        if 'TOSCA-Metadata/Metadata.yaml' in filenames:
                            logger.debug(
                                "Found 'TOSCA-Metadata/Metadata.yaml'")
                            yaml_file = zf.read('TOSCA-Metadata/Metadata.yaml')
                        elif 'tosca-metadata/Metadata.yaml' in filenames:
                            # just for legacy support
                            # the correct file name following the specification is 'TOSCA-Metadata'
                            # to support experiments that were created before this fix we still check for 'tosca-metadata' though
                            logger.warning(
                                "'TOSCA-Metadata/Metadata.yaml' not found. Will try 'tosca-metadata/Metadata.yaml' to support older experiments."
                            )
                            yaml_file = zf.read('tosca-metadata/Metadata.yaml')
                        else:
                            raise ExperimentValidationError(
                                'The TOSCA-Metadata/Metadata.yaml file is missing in {}.'
                                .format(file_name))
                    except KeyError as e:
                        traceback.print_exc()
                        if hasattr(e, 'message'):
                            raise ExperimentValidationError(e.message)
                        else:
                            raise ExperimentValidationError(e.args)
                    if yaml_file:
                        yaml_content = yaml.load(yaml_file)
                        description = yaml_content.get('description')
                    else:
                        description = 'No description available'
                    testbeds = node.get_properties().get('testbeds').value
                    temp_ids.append(
                        add_resource(
                            username,
                            node.get_properties().get('resource_id').value,
                            "NfvResource", -1, description,
                            list(testbeds.keys())[0], real_file_name))
        try:
            self._validate()
        except Exception as e:
            for id in temp_ids:
                delete(find(ResourceMetadata, _id=id))
            raise ExperimentValidationError(e.args)

        exp = entities.Experiment()
        exp.id = '{}_{}'.format(self.username, self.name)
        exp.username = self.username
        exp.name = self.name
        exp.start_date = self.start_date
        exp.end_date = self.end_date
        exp.resources = []

        for node in self.topology_template.nodetemplates:
            exp.resources.append(self._get_used_resource_by_node(node))

        element_value = find_by_element_value(entities.Experiment,
                                              entities.Experiment.username,
                                              self.username)
        max_no_experiment = get_config("System", "max-number-experiments", 3)
        if len(element_value) >= max_no_experiment:
            raise ExperimentValidationError(
                "You cannot have more than %s experiments at the same time!" %
                max_no_experiment)

        logger.info("Saving experiment %s" % exp.name)
        save(exp)
        self.experiment = exp
        for res in exp.resources:
            _start_termination_thread_for_res(res)