def _validate_shared_net_resource(action, body=None):
    """Validate keys in outgoing shared network request"""
    if body:
        body_set = set(body.keys())
    else:
        return
    if 'vm-network' in action and 'port' not in action:
        vmnetwork_set = set(_resource_metadata['vmnetwork'])
        if body_set - vmnetwork_set:
            raise c_exc.VSMError(reason='Invalid Request')
    elif 'port' in action:
        port_set = set(_resource_metadata['port'])
        if body_set - port_set:
            raise c_exc.VSMError(reason='Invalid Request')
    elif 'subnet' in action:
        subnet_set = set(_resource_metadata['subnet'])
        if body_set - subnet_set:
            raise c_exc.VSMError(reason='Invalid Request')
    elif '/network-segment/' in action:
        network_set = set(_resource_metadata['network-segment'])
        if body_set - network_set:
            raise c_exc.VSMError(reason='Invalid Request')
        if body['tenantId'] != '0':
            raise c_exc.VSMError(reason='Invalid Shared Network Handling')
    else:
        return
 def _do_request(self,
                 method,
                 action,
                 body=None,
                 headers=None,
                 vsm_ip=None):
     """Handle outgoing requestes based on type"""
     if self.broken:
         raise c_exc.VSMError(reason='VSM:Internal Server Error')
     if self.inject_params and body:
         body['invalidKey'] = 'catchMeIfYouCan'
     if method == 'POST' and self.shared_net:
         return _validate_shared_net_resource(action, body)
     # For update to shared network cases, set to shared after net create
     elif (method == 'POST' and self.upd_shared_net
           and '/network-segment/' in action):
         ret = _validate_resource(action, body)
         self.shared_net = True
         return ret
     elif method == 'POST':
         return _validate_resource(action, body)
     elif method == 'GET':
         if 'virtual-port-profile' in action:
             return _policy_profile_generator(self._get_total_profiles())
         else:
             raise c_exc.VSMError(reason='VSM:Internal Server Error')
Example #3
0
    def _do_request(self,
                    method,
                    action,
                    body=None,
                    headers=None,
                    vsm_ip=None):
        """Perform the HTTP request.

        The response is in either JSON format or plain text. A GET method will
        invoke a JSON response while a PUT/POST/DELETE returns message from the
        VSM in plain text format.
        Exception is raised when VSM replies with an INTERNAL SERVER ERROR HTTP
        status code (500) i.e. an error has occurred on the VSM or SERVICE
        UNAVAILABLE (404) i.e. VSM is not reachable.

        :param method: type of the HTTP request. POST, GET, PUT or DELETE
        :param action: path to which the client makes request
        :param body: dict for arguments which are sent as part of the request
        :param headers: header for the HTTP request
        :param vsm_ip: vsm_ip for the HTTP request. If not provided then
                       request will be sent to all VSMs.
        :returns: JSON or plain text in HTTP response
        """

        action = self.action_prefix + action
        if body:
            body = jsonutils.dumps(body)
            LOG.debug("req: %s", body)
        hosts = []
        if vsm_ip:
            hosts.append(vsm_ip)
        else:
            hosts = self.get_vsm_hosts()
        if not headers:
            headers = self._get_auth_header()
            headers['Content-Type'] = headers['Accept'] = "application/json"
        for vsm_ip in hosts:
            vsm_action = action % vsm_ip
            try:
                resp = self.pool.spawn(requests.request,
                                       method,
                                       url=vsm_action,
                                       data=body,
                                       headers=headers,
                                       timeout=self.timeout).wait()
            except Exception as e:
                raise n1kv_exc.VSMConnectionFailed(reason=e)
            if resp.status_code != requests.codes.OK:
                raise n1kv_exc.VSMError(reason=resp.text)
        if 'application/json' in resp.headers['content-type']:
            try:
                return resp.json()
            except ValueError:
                return {}
        elif 'text/plain' in resp.headers['content-type']:
            LOG.info(_LI("VSM: %s"), resp.text)
def _validate_resource(action, body=None):
    """Validate expected keys are present in outgoing request"""
    if body:
        body_set = set(body.keys())
    else:
        return
    if 'vm-network' in action and 'port' not in action:
        vmnetwork_set = set(_resource_metadata['vmnetwork'])
        if body_set - vmnetwork_set:
            raise c_exc.VSMError(reason='Invalid Request')
    elif '/network-segment/' in action:
        network_set = set(_resource_metadata['network-segment'])
        if body_set - network_set:
            raise c_exc.VSMError(reason='Invalid Request')
    elif 'port' in action:
        port_set = set(_resource_metadata['port'])
        if body_set - port_set:
            raise c_exc.VSMError(reason='Invalid Request')
    elif 'subnet' in action:
        subnet_set = set(_resource_metadata['subnet'])
        if body_set - subnet_set:
            raise c_exc.VSMError(reason='Invalid Request')
    else:
        return
 def test_create_network_profile_on_vsm_error(self):
     """Test a network profile creation when the operation fails on VSM."""
     data = self.get_test_network_profile_dict(segment_type='vxlan',
                                               sub_type='enhanced')
     new_net_prof_name = data["network_profile"]["name"]
     mocked_ex = mock.MagicMock(side_effect=n1kv_exc.VSMError(
         reason='Internal VSM error'))
     with mock.patch(
             n1kv_client.__name__ + ".Client.create_network_segment_pool",
             mocked_ex):
         self.create_assert_network_profile_failure(
             data=data,
             expected_status=webob.exc.HTTPInternalServerError.code)
     # list all network profiles
     netprofs = self.list_resource(resource='network_profiles',
                                   tenant_id=self.admin_tenant)
     # assert that the network profile created is cleaned up on neutron
     # when creation on VSM fails
     self.assertNotIn(
         needle=new_net_prof_name,
         haystack=[d["name"] for d in netprofs["network_profiles"]])
Example #6
0
 def test_network_profile_create_on_vsm_error(self):
     """Test a network profile creation when the operation fails on VSM."""
     data = self.get_test_network_profile_dict(segment_type='vxlan',
                                               sub_type='enhanced')
     new_net_prof_name = data["network_profile"]["name"]
     mocked_ex = mock.MagicMock(side_effect=n1kv_exc.VSMError(
         reason='Internal VSM error'))
     with mock.patch(n1kv_client.__name__ +
                     ".Client.create_network_segment_pool", mocked_ex):
         network_req = self.new_create_request('network_profiles', data)
         res = network_req.get_response(self.ext_api)
         self.assertEqual(webob.exc.HTTPInternalServerError.code,
                          res.status_int)
     # list all network profiles
     list_req = self.new_list_request('network_profiles')
     list_res = list_req.get_response(self.ext_api)
     netprofs = self.deserialize(self.fmt, list_res)
     # assert that the network profile created is cleaned up on neutron
     # when creation on VSM fails
     self.assertNotIn(
         needle=new_net_prof_name,
         haystack=[d["name"] for d in netprofs["network_profiles"]])
Example #7
0
    def _do_request(self,
                    method,
                    action,
                    body=None,
                    headers=None,
                    vsm_ip=None):
        """Perform the HTTP request.

        The response is in either JSON format or plain text. A GET method will
        invoke a JSON response while a PUT/POST/DELETE returns message from the
        VSM in plain text format.
        Exception is raised when VSM replies with an INTERNAL SERVER ERROR HTTP
        status code (500) i.e. an error has occurred on the VSM or SERVICE
        UNAVAILABLE (404) i.e. VSM is not reachable.

        :param method: type of the HTTP request. POST, GET, PUT or DELETE
        :param action: path to which the client makes request
        :param body: dict for arguments which are sent as part of the request
        :param headers: header for the HTTP request
        :param vsm_ip: vsm_ip for the HTTP request. If not provided then
                       request will be sent to all VSMs.
        :returns: JSON or plain text in HTTP response
        """

        action = self.action_prefix + action
        if body:
            body = jsonutils.dumps(body)
            LOG.debug("req: %s", body)
        hosts = []
        if vsm_ip:
            hosts.append(vsm_ip)
        else:
            hosts = self.vsm_ips
        if not headers:
            headers = self._get_auth_header()
            headers['Content-Type'] = headers['Accept'] = "application/json"
        for vsm_ip in hosts:
            if netutils.is_valid_ipv6(vsm_ip):
                # Enclose IPv6 address in [] in the URL
                vsm_action = action % ("[%s]" % vsm_ip)
            else:
                # IPv4 address
                vsm_action = action % vsm_ip
            for attempt in range(self.max_vsm_retries + 1):
                try:
                    LOG.debug("[VSM %(vsm)s attempt %(id)s]: Connecting.." % {
                        "vsm": vsm_ip,
                        "id": attempt
                    })
                    resp = self.pool.spawn(requests.request,
                                           method,
                                           url=vsm_action,
                                           data=body,
                                           headers=headers,
                                           timeout=self.timeout).wait()
                    break
                except Exception as e:
                    LOG.debug("[VSM %(vsm)s attempt %(id)s]: Conn timeout." % {
                        "vsm": vsm_ip,
                        "id": attempt
                    })
                    if attempt == self.max_vsm_retries:
                        LOG.error(_LE("VSM %s, Conn failed."), vsm_ip)
                        raise n1kv_exc.VSMConnectionFailed(reason=e)
            if resp.status_code != requests.codes.OK:
                LOG.error(_LE("VSM %(vsm)s, Got error: %(err)s"), {
                    "vsm": vsm_ip,
                    "err": resp.text
                })
                raise n1kv_exc.VSMError(reason=resp.text)
        if 'application/json' in resp.headers['content-type']:
            try:
                return resp.json()
            except ValueError:
                return {}
        elif 'text/plain' in resp.headers['content-type']:
            LOG.info(_LI("VSM: %s"), resp.text)