Esempio n. 1
0
 def get_cell_list(self, network_id):
     cell_list_url = '{}/{}'.format(self.config['cpsUrl'],
                                    self.config['cpsCellListUrl'])
     data = {'inputParameters': {'regionId': network_id}}
     response = self.rc.request(url=cell_list_url, data=json.dumps(data))
     debug_log.debug("cell list response {}".format(response))
     return sorted([x['idNRCellCU'] for x in response.get('NRCellCU')])
Esempio n. 2
0
def get_resource_count(query_template, inputs, osdf_config):
    query = Template(query_template).render(inputs)
    dsl_response = execute_dsl_query(query, "count", osdf_config)
    debug_log.debug("dsl_response {}".format(dsl_response))
    # the dsl query with format "count" includes the original service-instance, hence reducing one from the result
    count = dsl_response["results"][0]
    return count.get("service-instance", 0) - 1
Esempio n. 3
0
def initial_request_to_conductor(rc, conductor_url, conductor_req_json):
    """First steps in the request-redirect chain in making a call to Conductor

    :param rc: REST client object for calling conductor
    :param conductor_url: conductor's base URL to submit a placement request
    :param conductor_req_json: request json object to send to Conductor
    :return: URL to check for follow up (similar to redirects);
             we keep checking these till we get a result/error
    """
    debug_log.debug("Payload to Conductor: {}".format(json.dumps(conductor_req_json)))
    raw_resp = rc.request(url=conductor_url, raw_response=True, method="POST",
                          json=conductor_req_json)
    resp = raw_resp.json()
    if resp["status"] != "template":
        raise RequestException(response=raw_resp, request=raw_resp.request)
    time.sleep(10)  # 10 seconds wait time to avoid being too quick!
    plan_url = resp["links"][0][0]["href"]
    debug_log.debug("Attempting to read the plan from "
                    "the conductor provided url {}".format(plan_url))
    raw_resp = rc.request(raw_response=True,
                          url=plan_url)
    resp = raw_resp.json()

    if resp["plans"][0]["status"] in ["error"]:
        raise RequestException(response=raw_resp, request=raw_resp.request)
    return resp, raw_resp  # now the caller of this will handle further follow-ups
Esempio n. 4
0
def execute_dsl_query(query, format, osdf_config):
    """Get the response from AAI

           :param query: dsl query to be executed
           :param format format of the output
           :param osdf_config: configuration specific to OSDF app
           :return:response body from AAI
    """
    config = osdf_config.deployment
    dsl_url = config["aaiUrl"] + config["dslQueryPath"] + format

    data = json.dumps({'dsl': query})
    debug_log.debug("aai dsl request: {}".format(data))
    try:
        response = requests.put(dsl_url,
                                data=data,
                                headers=AAI_HEADERS,
                                auth=AUTH,
                                verify=False)
        debug_log.debug("aai dsl response: {}".format(response))
    except RequestException as ex:
        raise AAIException("Request exception was encountered {}".format(ex))

    if response.status_code == 200:
        return response.json()
    else:
        raise AAIException(
            "Response code other than 200 from AAI: {} {}".format(
                response.status_code, response.content))
Esempio n. 5
0
def get_model_data(model_id):
    with app.app_context():
        try:
            debug_log.debug(
                "getting model data given model_id = {}".format(model_id))
            d = dict()
            connection = get_db()
            cursor = connection.cursor(buffered=True)
            query = "SELECT model_id, model_content, description, " \
                    "solver_type  FROM optim_model_data WHERE model_id = %s"
            values = (model_id, )
            cursor.execute(query, values)
            if cursor is None:
                return 400, "FAILED"
            else:
                rows = cursor.fetchone()
                if rows is not None:
                    index = 0
                    for row in rows:
                        d[index] = row
                        index = index + 1
                    return 200, d
                else:
                    close_db()
                    return 500, "NOT_FOUND"
        except Exception:
            error_log.error("error for request_id: {} - {}".format(
                model_id, traceback.format_exc()))
            close_db()
            return 500, "FAILED"
Esempio n. 6
0
def get_local_policies(local_policy_folder,
                       local_policy_list,
                       policy_id_list=None):
    """
    Get policies from a local file system.
    Required for the following scenarios:
    (a) doing work-arounds (e.g. if we are asked to drop some policies for testing purposes)
    (b) work-arounds when policy platform is giving issues (e.g. if dev/IST policies are wiped out in an upgrade)
    :param local_policy_folder: where the policy files are present
    :param local_policy_list: list of local policies
    :param policy_id_list: list of policies to get (if unspecified or None, get all)
    :return: get policies
    """
    debug_log.debug(
        "Policy folder: {}, local_list {}, policy id list {}".format(
            local_policy_folder, local_policy_list, policy_id_list))
    policies = []
    if policy_id_list:
        for policy_id in policy_id_list:
            with open(os.path.join(local_policy_folder,
                                   policy_id + ".json")) as fid:
                policies.append(json.load(fid))
    else:
        for fname in local_policy_list:
            with open(os.path.join(local_policy_folder, fname)) as fid:
                policies.append(json.load(fid))
    return policies
Esempio n. 7
0
def get_aai_data(request_json, osdf_config):
    """Get the response from AAI

       :param request_json: requestjson
       :param osdf_config: configuration specific to OSDF app
       :return:response body from AAI
    """

    nxi_id = request_json["NxIId"]
    config = osdf_config.deployment
    aai_url = config["aaiUrl"]
    aai_req_url = aai_url + config[
        "aaiServiceInstanceUrl"] + nxi_id + "?depth=2"

    try:
        debug_log.debug("aai request: {}".format(aai_req_url))
        response = requests.get(aai_req_url,
                                headers=AAI_HEADERS,
                                auth=AUTH,
                                verify=False)
        debug_log.debug("aai response: {}".format(response.json()))
    except RequestException as e:
        raise AAIException("Request exception was encountered {}".format(e))

    if response.status_code == 200:
        return response.json()
    else:
        raise AAIException(
            "Error response recieved from AAI for the request {}".format(
                aai_req_url))
Esempio n. 8
0
 def get_app_policies(self, model_name, app_name):
     policy_request_json = self.request_json.copy()
     policy_request_json['serviceInfo'] = {'serviceName': model_name}
     debug_log.debug("policy_request_json {}".format(
         str(policy_request_json)))
     return get_policies(policy_request_json,
                         app_name)  # app_name: nst_selection
Esempio n. 9
0
def delete_file_folder(p):
    if not p:
        return
    debug_log.debug('Deleting folder/file {}'.format(p))
    if os.path.isfile(p):
        os.remove(p)
    else:
        rmtree(p, ignore_errors=True)
Esempio n. 10
0
 def update_config(self, data):
     new_config = json.loads(data['Value'].decode('utf-8'))
     osdf_deployment = new_config['osdf_config']
     osdf_core = new_config['common_config']
     self.config['osdf_config'].update(osdf_deployment)
     self.config['common_config'].update(osdf_core)
     debug_log.debug("updated config {}".format(new_config))
     debug_log.debug("value changed")
Esempio n. 11
0
    def request(self,
                url=None,
                method=None,
                asjson=True,
                ok_codes=(2, ),
                raw_response=False,
                noresponse=False,
                timeout=None,
                **kwargs):
        """Sends http request to the specified url

        :param url: REST end point to query
        :param method: GET or POST (default is None => self.method)
        :param asjson: whether the expected response is in json format
        :param ok_codes: expected codes (prefix matching -- e.g. can be (20, 21, 32) or (2, 3))
        :param noresponse: If no response is expected (as long as response codes are OK)
        :param raw_response: If we need just the raw response (e.g. conductor sends transaction IDs in headers)
        :param timeout: Connection and read timeouts
        :param kwargs: Other parameters
        :return:
        """
        if not self.req_id:
            debug_log.debug("Requesting URL: {}".format(url or self.url))
        else:
            debug_log.debug("Requesting URL: {} for request ID: {}".format(
                url or self.url, self.req_id))

        if not url:
            url = self.url
        if not self.verify and url.startswith("https"):
            verify = osdf_config.deployment["aaf_ca_certs"]
        else:
            verify = self.verify

        res = requests.request(url=url or self.url,
                               method=method or self.method,
                               auth=self.auth,
                               headers=self.headers,
                               timeout=timeout or self.timeout,
                               verify=verify,
                               **kwargs)

        if self.log_func:
            self.log_func(MH.received_http_response(res))

        res_code = str(res.status_code)
        if not any(res_code.startswith(x) for x in map(str, ok_codes)):
            raise BaseException(res.raise_for_status())

        if raw_response:
            return res
        elif noresponse:
            return None
        elif asjson:
            return res.json()
        else:
            return res.content
Esempio n. 12
0
 def get_app_policies(self, model_name, app_name):
     policy_request_json = self.request_json.copy()
     policy_request_json['serviceInfo'] = {'serviceName': model_name}
     if 'serviceProfile' in self.request_json:
         slice_scope = self.request_json['serviceProfile']['resourceSharingLevel']
         if 'preferReuse' in self.request_json and slice_scope == "shared":
             slice_scope = slice_scope + "," + ("reuse" if self.request_json['preferReuse'] else "create_new")
         policy_request_json['slice_scope'] = slice_scope
     debug_log.debug("policy_request_json {}".format(str(policy_request_json)))
     return get_policies(policy_request_json, app_name)
Esempio n. 13
0
    def get_nbr_list(self, network_id, cell_id):
        ts = dt.strftime(dt.now(), '%Y-%m-%d %H:%M:%S%z')
        nbr_list_url = '{}/{}/{}/{}'.format(
            self.config['configDbUrl'], self.config['configDbGetNbrListUrl'],
            cell_id, ts)
        response = self.rc.request(url=nbr_list_url, raw_response=True).json()

        debug_log.debug("cell_id {} nbr_list {}".format(
            cell_id, response.get('nbrList')))

        return response.get('nbrList', [])
Esempio n. 14
0
 def watch(self):
     index = None
     while True:
         try:
             index, data = yield self.consul.kv.get('osdfconfiguration',
                                                    index=index)
             if data is not None:
                 self.update_config(data)
         except Timeout:
             pass
         except Exception as e:
             debug_log.debug('Exception Encountered {}'.format(e))
Esempio n. 15
0
def osdf_response_for_request_accept(
        request_id="",
        transaction_id="",
        request_status="",
        status_message="",
        version_info={
            'placementVersioningEnabled': False,
            'placementMajorVersion': '1',
            'placementMinorVersion': '0',
            'placementPatchVersion': '0'
        },
        response_code=202,
        as_http=True):
    """Helper method to create a response object for request acceptance, so that the object can be sent to a client
    :param request_id: request ID provided by the caller
    :param transaction_id: transaction ID provided by the caller
    :param request_status: the status of a request
    :param status_message: details on the status of a request
    :param response_code: the HTTP status code to send -- default is 202 (accepted)
    :param as_http: whether to send response as HTTP response object or as a string
    :return: if as_http is True, return a HTTP Response object. Otherwise, return json-encoded-message
    """
    response_message = ACCEPTED_MESSAGE_TEMPLATE.render(
        request_id=request_id,
        transaction_id=transaction_id,
        request_status=request_status,
        status_message=status_message)
    if not as_http:
        return response_message

    response = Response(response_message,
                        content_type='application/json; charset=utf-8')
    response.headers.add('content-length', len(response_message))

    placement_ver_enabled = version_info['placementVersioningEnabled']

    if placement_ver_enabled:
        placement_minor_version = version_info['placementMinorVersion']
        placement_patch_version = version_info['placementPatchVersion']
        placement_major_version = version_info['placementMajorVersion']
        x_latest_version = placement_major_version + '.' + placement_minor_version + '.' + placement_patch_version
        response.headers.add('X-MinorVersion', placement_minor_version)
        response.headers.add('X-PatchVersion', placement_patch_version)
        response.headers.add('X-LatestVersion', x_latest_version)

        debug_log.debug(
            "Versions set in HTTP header for synchronous response: X-MinorVersion: {}  X-PatchVersion: {}  X-LatestVersion: {}"
            .format(placement_minor_version, placement_patch_version,
                    x_latest_version))

    response.status_code = response_code
    return response
Esempio n. 16
0
def get_aaf_permissions(uid, passwd):
    key = base64.b64encode(bytes("{}_{}".format(uid, passwd), "ascii"))
    time_delta = timedelta(
        minutes=deploy_config.get('aaf_cache_expiry_mins', 5))

    perms = perm_cache.get(key)

    if perms and datetime.now() < perms.get(EXPIRE_TIME):
        debug_log.debug("Returning cached value")
        return perms
    debug_log.debug("Invoking AAF authentication API")
    perms = {
        EXPIRE_TIME: datetime.now() + time_delta,
        'roles': remote_api(passwd, uid)
    }
    perm_cache[key] = perms
    return perms
Esempio n. 17
0
def get_options(argv):
    program_version_string = '%%prog %s' % "v1.0"
    program_longdesc = ""
    program_license = ""

    parser = OptionParser(version=program_version_string, epilog=program_longdesc, description=program_license)
    parser.add_option("-l", "--local", dest="local", help="run locally", action="store_true", default=False)
    parser.add_option("-t", "--devtest", dest="devtest", help="run in dev/test environment", action="store_true",
                      default=False)
    parser.add_option("-d", "--debughost", dest="debughost",
                      help="IP Address of host running debug server", default='')
    parser.add_option("-p", "--debugport", dest="debugport",
                      help="Port number of debug server", type=int, default=5678)
    opts, args = parser.parse_args(argv)

    if opts.debughost:
        debug_log.debug('pydevd.settrace({}, port={})'.format(opts.debughost, opts.debugport))
        # pydevd.settrace(opts.debughost, port=opts.debugport)
    return opts
Esempio n. 18
0
def py_solver(py_content, opt_info):
    py_file = '/tmp/custom_heuristics_{}.py'.format(
        datetime.timestamp(datetime.now()))
    with open(py_file, "wt") as f:
        f.write(py_content)
    if opt_info['optData'].get('json'):
        data_content = json.dumps(opt_info['optData']['json'])
        input_file = '/tmp/optim_engine_{}.json'.format(
            datetime.timestamp(datetime.now()))
    elif opt_info['optData'].get('text'):
        data_content = opt_info['optData']['text']
        input_file = '/tmp/optim_engine_{}.txt'.format(
            datetime.timestamp(datetime.now()))
    with open(input_file, "wt") as f:
        f.write(data_content)

    output_file = '/tmp/opteng_output_{}.json'.format(
        datetime.timestamp(datetime.now()))

    command = ['python', py_file, input_file, output_file]

    try:
        p = subprocess.run(command,
                           stderr=subprocess.STDOUT,
                           stdout=subprocess.PIPE)

        debug_log.debug('Process return code {}'.format(p.returncode))
        if p.returncode > 0:
            error_log.error('Process return code {} {}'.format(
                p.returncode, p.stdout))
            return 'error', {}
        with open(output_file) as file:
            data = file.read()
            return 'success', json.loads(data)

    except Exception as e:
        error_log.error("Error running optimizer {}".format(
            traceback.format_exc()))
        return 'error', {}
    finally:
        cleanup((input_file, output_file, py_file))
Esempio n. 19
0
def create_model_data(model_api):
    with app.app_context():
        try:
            model_info = model_api['modelInfo']
            model_id = model_info['modelId']
            debug_log.debug("persisting model_api {}".format(model_id))
            connection = get_db()
            cursor = connection.cursor(buffered=True)
            query = "SELECT model_id FROM optim_model_data WHERE model_id = %s"
            values = (model_id, )
            cursor.execute(query, values)
            if cursor.fetchone() is None:
                query = "INSERT INTO optim_model_data (model_id, model_content, description, solver_type) VALUES " \
                        "(%s, %s, %s, %s)"
                values = (model_id, model_info['modelContent'],
                          model_info.get('description'), model_info['solver'])
                cursor.execute(query, values)
                g.pg.commit()

                debug_log.debug(
                    "A record successfully inserted for request_id: {}".format(
                        model_id))
                return retrieve_model_data(model_id)
                close_db()
            else:
                query = "UPDATE optim_model_data SET model_content = %s, description = %s, solver_type = %s where " \
                        "model_id = %s "
                values = (model_info['modelContent'],
                          model_info.get('description'), model_info['solver'],
                          model_id)
                cursor.execute(query, values)
                g.pg.commit()

                return retrieve_model_data(model_id)
                close_db()
        except Exception as err:
            error_log.error("error for request_id: {} - {}".format(
                model_id, traceback.format_exc()))
            close_db()
            raise BusinessException(err)
Esempio n. 20
0
def delete_model_data(model_id):
    with app.app_context():
        try:
            debug_log.debug(
                "deleting model data given model_id = {}".format(model_id))
            connection = get_db()
            cursor = connection.cursor(buffered=True)
            query = "delete from optim_model_data WHERE model_id = %s"
            values = (model_id, )
            cursor.execute(query, values)
            g.pg.commit()
            close_db()
            resp = {
                "statusMessage":
                "model data for modelId {} deleted".format(model_id)
            }
            return build_response(json.dumps(resp), 200)
        except Exception as err:
            error_log.error("error deleting model_id: {} - {}".format(
                model_id, traceback.format_exc()))
            close_db()
            raise BusinessException(err)
Esempio n. 21
0
    def get_nbr_list(self, network_id, cell_id):
        nbr_list_url = '{}/{}'.format(self.config['cpsUrl'],
                                      self.config['cpsNbrListUrl'])
        data = {
            'inputParameters': {
                'regionId': network_id,
                'idNRCellCU': cell_id
            }
        }
        response = self.rc.request(url=nbr_list_url, data=json.dumps(data))
        debug_log.debug("nbr list response {}".format(response))
        nbr_list = []
        for cell_relation in response.get('NRCellRelation'):
            nbr = {
                'targetCellId': cell_relation['attributes']['nRTCI'],
                'pciValue': int(cell_relation['attributes']['nRPCI']),
                'ho': cell_relation['attributes']['isHOAllowed']
            }
            nbr_list.append(nbr)

        debug_log.debug("cell_id {} nbr_list {}".format(cell_id, nbr_list))

        return nbr_list
Esempio n. 22
0
def local_policies_location(req_json, osdf_config, service_type):
    """Get folder and list of policy_files if "local policies" option is enabled

    :param service_type: placement supported for now, but can be any other service
    :return: a tuple (folder, file_list) or None
    """
    lp = osdf_config.core.get('osdf_temp', {}).get('local_policies', {})
    if lp.get('global_disabled'):
        return None  # short-circuit to disable all local policies
    if lp.get('local_{}_policies_enabled'.format(service_type)):
        debug_log.debug(
            'Loading local policies for service type: {}'.format(service_type))
        if service_type == "scheduling":
            return lp.get('{}_policy_dir'.format(service_type)), lp.get(
                '{}_policy_files'.format(service_type))
        else:
            service_name = req_json['serviceInfo']['serviceName']
            debug_log.debug(
                'Loading local policies for service name: {}'.format(
                    service_name))
            return lp.get('{}_policy_dir_{}'.format(service_type, service_name.lower())), \
                lp.get('{}_policy_files_{}'.format(service_type, service_name.lower()))
    return None
Esempio n. 23
0
def get_all_models():
    with app.app_context():
        try:
            debug_log.debug("getting all model data".format())
            connection = get_db()
            cursor = connection.cursor(buffered=True)
            query = "SELECT model_id, model_content, description, solver_type  FROM optim_model_data"

            cursor.execute(query)
            if cursor is None:
                return 400, "FAILED"
            else:
                rows = cursor.fetchall()
                if rows is not None:
                    return 200, rows
                else:
                    close_db()
                    return 500, "NOT_FOUND"
        except Exception:
            error_log.error("error for request_id:  {}".format(
                traceback.format_exc()))
            close_db()
            return 500, "FAILED"
Esempio n. 24
0
    def do_slice_selection(self):
        req_info = self.request_json['requestInfo']
        app_info = self.slice_config['app_info'][self.model_type]
        mdc_from_json(self.request_json)
        requirements = self.request_json.get(app_info['requirements_field'], {})
        model_info = self.request_json.get(app_info['model_info'])
        model_name = model_info['name']
        policies = self.get_app_policies(model_name, app_info['app_name'])
        request_parameters = self.get_request_parameters(requirements, model_info)

        demands = [
            {
                "resourceModuleName": model_name,
                "resourceModelInfo": {}
            }
        ]

        try:
            template_fields = {
                'location_enabled': False,
                'version': '2020-08-13'
            }
            resp = conductor.request(req_info, demands, request_parameters, {}, template_fields,
                                     self.osdf_config, policies)
        except RequestException as e:
            resp = e.response.json()
            error = resp['plans'][0]['message']
            if isinstance(error, list) and "Unable to find any" in error[0]:
                return self.response_processor.get_slice_selection_response([])
            error_log.error('Error from conductor {}'.format(error))
            return self.response_processor.process_error_response(error)

        debug_log.debug("Response from conductor {}".format(str(resp)))
        recommendations = resp["plans"][0].get("recommendations")
        subnets = [subnet['domainType'] for subnet in self.request_json['subnetCapabilities']] \
            if self.request_json.get('subnetCapabilities') else []
        return self.response_processor.process_response(recommendations, model_info, subnets, self.model_type)
Esempio n. 25
0
    def get_conductor(self, req_info, request_parameters, policies,
                      model_name):
        demands = [{"resourceModuleName": model_name, "resourceModelInfo": {}}]

        try:
            template_fields = {
                'location_enabled': False,
                'version': '2020-08-13'
            }
            resp = conductor.request(req_info, demands, request_parameters, {},
                                     template_fields, self.osdf_config,
                                     policies)
        except RequestException as e:
            resp = e.response.json()
            error = resp['plans'][0]['message']
            if "Unable to find any" in error:
                return self.get_nst_selection_response([])
            error_log.error('Error from conductor {}'.format(error))
            return self.error_response(error)
        debug_log.debug(
            "Response from conductor in get_conductor method {}".format(
                str(resp)))
        recommendations = resp["plans"][0].get("recommendations")
        return self.process_response(recommendations, model_name)
Esempio n. 26
0
def retrieve_version_info(request, request_id):
    version_info_dict = defaultdict(dict)
    config = osdf_config.deployment 
    placement_ver_enabled = config.get('placementVersioningEnabled', False)

    if placement_ver_enabled: 
        placement_major_version = config.get('placementMajorVersion', None)
        placement_minor_version = config.get('placementMinorVersion', None)  
        placement_patch_version = config.get('placementPatchVersion', None)
        
        http_header = request.headers.environ
        http_x_minorversion = http_header.get("HTTP_X_MINORVERSION")
        http_x_patchversion = http_header.get("HTTP_X_PATCHVERSION")
        http_x_latestversion = http_header.get("HTTP_X_LATESTVERSION")
        
        debug_log.debug("Versions sent in HTTP header for request ID {} are: X-MinorVersion: {}  X-PatchVersion: {}  X-LatestVersion: {}"
                        .format(request_id, http_x_minorversion, http_x_patchversion, http_x_latestversion))
        debug_log.debug("latest versions specified in osdf config file are: placementMajorVersion: {}  placementMinorVersion: {}  placementPatchVersion: {}"
                        .format(placement_major_version, placement_minor_version, placement_patch_version))
    else:
        placement_major_version = config.get('placementDefaultMajorVersion', "1")
        placement_minor_version = config.get('placementDefaultMinorVersion', "0")
        placement_patch_version = config.get('placementDefaultPatchVersion', "0")
        
        debug_log.debug("Default versions specified in osdf config file are: placementDefaultMajorVersion: {}  placementDefaultMinorVersion: {}  placementDefaultPatchVersion: {}"
                        .format(placement_major_version, placement_minor_version, placement_patch_version))
        
    version_info_dict.update({
                               'placementVersioningEnabled': placement_ver_enabled,
                               'placementMajorVersion': str(placement_major_version),
                               'placementMinorVersion': str(placement_minor_version),
                               'placementPatchVersion': str( placement_patch_version)
                              })
    
    return version_info_dict  
    
Esempio n. 27
0
def conductor_response_processor(conductor_response, req_id, transaction_id):
    """Build a response object to be sent to client's callback URL from Conductor's response

    This includes Conductor's placement optimization response, and required ASDC license artifacts
    :param conductor_response: JSON response from Conductor
    :param raw_response: Raw HTTP response corresponding to above
    :param req_id: Id of a request
    :return: JSON object that can be sent to the client's callback URL
    """
    composite_solutions = []
    name_map = {
        "physical-location-id": "cloudClli",
        "host_id": "vnfHostName",
        "cloud_version": "cloudVersion",
        "cloud_owner": "cloudOwner",
        "cloud": "cloudRegionId",
        "service": "serviceInstanceId",
        "is_rehome": "isRehome",
        "location_id": "locationId",
        "location_type": "locationType",
        "directives": "oof_directives"
    }
    for reco in conductor_response['plans'][0]['recommendations']:
        for resource in reco.keys():
            c = reco[resource]['candidate']
            solution = {
                'resourceModuleName': resource,
                'serviceResourceId':
                reco[resource].get('service_resource_id', ""),
                'solution': {
                    "identifierType":
                    name_map.get(c['inventory_type'], c['inventory_type']),
                    'identifiers': [c['candidate_id']],
                    'cloudOwner':
                    c.get('cloud_owner', "")
                },
                'assignmentInfo': []
            }
            for key, value in c.items():
                if key in [
                        "location_id", "location_type", "is_rehome", "host_id"
                ]:
                    try:
                        solution['assignmentInfo'].append({
                            "key":
                            name_map.get(key, key),
                            "value":
                            value
                        })
                    except KeyError:
                        debug_log.debug(
                            "The key[{}] is not mapped and will not be returned in assignment info"
                            .format(key))

            for key, value in reco[resource]['attributes'].items():
                try:
                    solution['assignmentInfo'].append({
                        "key":
                        name_map.get(key, key),
                        "value":
                        value
                    })
                except KeyError:
                    debug_log.debug(
                        "The key[{}] is not mapped and will not be returned in assignment info"
                        .format(key))
            composite_solutions.append(solution)

    request_status = "completed" if conductor_response['plans'][0]['status'] == "done" \
        else conductor_response['plans'][0]['status']
    status_message = conductor_response.get('plans')[0].get('message', "")

    solution_info = {}
    if composite_solutions:
        solution_info.setdefault('placementSolutions', [])
        solution_info['placementSolutions'].append(composite_solutions)

    resp = {
        "transactionId": transaction_id,
        "requestId": req_id,
        "requestStatus": request_status,
        "statusMessage": status_message,
        "solutions": solution_info
    }
    return resp
Esempio n. 28
0
def request(req_info, demands, request_parameters, service_info, template_fields,
            osdf_config, flat_policies):
    config = osdf_config.deployment
    local_config = osdf_config.core
    uid, passwd = config['conductorUsername'], config['conductorPassword']
    conductor_url = config['conductorUrl']
    req_id = req_info["requestId"]
    transaction_id = req_info['transactionId']
    headers = dict(transaction_id=transaction_id)
    placement_ver_enabled = config.get('placementVersioningEnabled', False)

    if placement_ver_enabled:
        cond_minor_version = config.get('conductorMinorVersion', None)
        if cond_minor_version is not None:
            x_minor_version = str(cond_minor_version)
            headers.update({'X-MinorVersion': x_minor_version})
            debug_log.debug("Versions set in HTTP header to "
                            "conductor: X-MinorVersion: {} ".format(x_minor_version))

    max_retries = config.get('conductorMaxRetries', 30)
    ping_wait_time = config.get('conductorPingWaitTime', 60)

    rc = RestClient(userid=uid, passwd=passwd, method="GET", log_func=debug_log.debug,
                    headers=headers)
    conductor_req_json_str = conductor_api_builder(req_info, demands, request_parameters,
                                                   service_info, template_fields, flat_policies,
                                                   local_config)
    conductor_req_json = json.loads(conductor_req_json_str)

    debug_log.debug("Sending first Conductor request for request_id {}".format(req_id))

    resp, raw_resp = initial_request_to_conductor(rc, conductor_url, conductor_req_json)
    # Very crude way of keeping track of time.
    # We are not counting initial request time, first call back, or time for HTTP request
    total_time, ctr = 0, 2
    client_timeout = req_info['timeout']
    configured_timeout = max_retries * ping_wait_time
    max_timeout = min(client_timeout, configured_timeout)

    while True:  # keep requesting conductor till we get a result or we run out of time
        if resp is not None:
            if resp["plans"][0].get("status") in ["error"]:
                raise RequestException(response=raw_resp, request=raw_resp.request)

            if resp["plans"][0].get("status") in ["done", "not found", "solved"]:
                return resp
            new_url = resp['plans'][0]['links'][0][0]['href']  # TODO(krishna): check why a list of lists

        if total_time >= max_timeout:
            raise BusinessException("Conductor could not provide a solution within {} seconds,"
                                    "this transaction is timing out".format(max_timeout))
        time.sleep(ping_wait_time)
        ctr += 1
        debug_log.debug("Attempt number {} url {}; prior status={}"
                        .format(ctr, new_url, resp['plans'][0]['status']))
        total_time += ping_wait_time

        try:
            raw_resp = rc.request(new_url, raw_response=True)
            resp = raw_resp.json()
        except RequestException as e:
            debug_log.debug("Conductor attempt {} for request_id {} has failed because {}"
                            .format(ctr, req_id, str(e)))
Esempio n. 29
0
def process_nxi_termination_opt(request_json, osdf_config):
    """Process the nxi Termination request from API layer

           :param request_json: api request
           :param osdf_config: configuration specific to OSDF app
           :return: response as a success,failure
    """

    request_type = request_json["type"]
    request_info = request_json.get("requestInfo", {})
    addtnl_args = request_info.get("addtnlArgs", {})
    query_templates = osdf_config.core["nxi_termination"]["query_templates"]

    inputs = {"instance_id": request_json["NxIId"]}

    try:
        if request_type == "NSSI":
            templates = query_templates["nssi"]
            for template in templates:
                resource_count = get_resource_count(template, inputs,
                                                    osdf_config)
                if resource_count == -1:
                    continue
                elif resource_count > 1 or (
                        resource_count == 1
                        and not addtnl_args.get("serviceInstanceId")):
                    terminate_response = False
                elif resource_count == 0:
                    terminate_response = True
                elif resource_count == 1 and addtnl_args.get(
                        "serviceInstanceId"):
                    new_template = template + "('service-instance-id','{}')".format(
                        addtnl_args["serviceInstanceId"])
                    terminate_response = get_resource_count(
                        new_template, inputs, osdf_config) == 1
                return set_response("success", "", request_info,
                                    terminate_response)

        if request_type == "NSI":
            allotted_resources = get_allotted_resources(
                request_json, osdf_config)
            resource_count = len(allotted_resources)
            if resource_count == 1 and addtnl_args.get("serviceInstanceId"):
                debug_log.debug("resource count {}".format(resource_count))
                terminate_response = False
                properties = allotted_resources[0]["relationship-data"]
                for property in properties:
                    if property["relationship-key"] == "service-instance.service-instance-id" \
                            and property["relationship-value"] == addtnl_args.get("serviceInstanceId"):
                        terminate_response = True
            elif resource_count > 1 or (
                    resource_count == 1
                    and not addtnl_args.get("serviceInstanceId")):
                terminate_response = False
            elif resource_count == 0:
                terminate_response = True

        return set_response("success", "", request_info, terminate_response)
    except AAIException as e:
        reason = str(e)
        return set_response("failure", reason, request_info)

    except Exception as e:
        reason = "{} Exception Occurred while processing".format(str(e))
        return set_response("failure", reason, request_info)