Example #1
0
 def _execute(self, task):
     """Execute task."""
     msg = _("@@@ Start task %s") % str(task)
     LOG.debug(msg)
     try:
         task.wait()
     except Exception:
         msg = (_("Task %(task)s encountered exception"),
             {'task': str(task)})
         LOG.exception(msg)
         #status = constants.TaskStatus.ERROR
     LOG.debug("Task %(task)s return", {'task': str(task)})
 def _add_interface_by_subnet(self, context, router, subnet_id, owner):
     LOG.debug("_add_interface_by_subnet(): router=%(router)s, "
               "subnet_id=%(subnet_id)s, owner=%(owner)s",
               {'router': router, 'subnet_id': subnet_id, 'owner': owner})
     subnet = self._core_plugin._get_subnet(context, subnet_id)
     if not subnet['gateway_ip']:
         msg = _('Subnet for router interface must have a gateway IP')
         raise n_exc.BadRequest(resource='router', msg=msg)
     self._check_for_dup_router_subnets(context, router,
                                        subnet['network_id'],
                                        [subnet])
     fixed_ip = {'ip_address': subnet['gateway_ip'],
                 'subnet_id': subnet['id']}
     # TODO(jerryz): move this out of transaction.
     setattr(context, 'GUARD_TRANSACTION', False)
     return (self._core_plugin.create_port(context, {
         'port':
         {'tenant_id': subnet['tenant_id'],
          'network_id': subnet['network_id'],
          'fixed_ips': [fixed_ip],
          'mac_address': utils.get_mac(self, context),
          'admin_state_up': True,
          'device_id': router.id,
          'device_owner': owner,
          'name': ''}}), [subnet], True)
Example #3
0
    def wait_for_job(self, abort_on_error=False, wait_for_job_clean=False):
        """Wait for libvirt block job to complete.

        Libvirt may return either cur==end or an empty dict when
        the job is complete, depending on whether the job has been
        cleaned up by libvirt yet, or not.

        :param abort_on_error: Whether to stop process and raise NovaException
                               on error (default: False)
        :param wait_for_job_clean: Whether to force wait to ensure job is
                                   finished (see bug: LP#1119173)

        :returns: True if still in progress
                  False if completed
        """
        status = self.get_job_info()
        if not status and abort_on_error:
            msg = _('libvirt error while requesting blockjob info.')
            raise exceptions.FortinetException(msg)

        if wait_for_job_clean:
            job_ended = status.job == 0
        else:
            job_ended = status.cur == status.end

        return not job_ended
Example #4
0
    def get_info(self, host):
        """Retrieve information from libvirt for a specific instance name.

        If a libvirt error is encountered during lookup, we might raise a
        NotFound exception or Error exception depending on how severe the
        libvirt error is.

        :returns hardware.InstanceInfo:
        """
        try:
            dom_info = self._get_domain_info(host)
        except libvirt.libvirtError as ex:
            error_code = ex.get_error_code()
            if error_code == libvirt.VIR_ERR_NO_DOMAIN:
                raise exceptions.InstanceNotFound(instance_id=self.uuid)

            msg = (_('Error from libvirt while getting domain info for '
                     '%(instance_name)s: [Error Code %(error_code)s] %(ex)s') %
                   {'instance_name': self.name,
                    'error_code': error_code,
                    'ex': ex})
            raise exceptions.FortinetException(msg)

        return hardware.InstanceInfo(
            state=LIBVIRT_POWER_STATE[dom_info[0]],
            max_mem_kb=dom_info[1],
            mem_kb=dom_info[2],
            num_cpu=dom_info[3],
            cpu_time_ns=dom_info[4],
            id=self.id)
    def add_router_interface(self, context, router_id, interface_info):
        """creates vlnk on the fortinet device."""
        LOG.debug("FortinetL3ServicePlugin.add_router_interface: "
                  "router_id=%(router_id)s "
                  "interface_info=%(interface_info)r",
                  {'router_id': router_id, 'interface_info': interface_info})
        with context.session.begin(subtransactions=True):
            info = super(FortinetL3ServicePlugin, self).add_router_interface(
                context, router_id, interface_info)
            port = db.get_port(context, info['port_id'])
            port['admin_state_up'] = True
            port['port'] = port
            LOG.debug("FortinetL3ServicePlugin: "
                      "context=%(context)s"
                      "port=%(port)s "
                      "info=%(info)r",
                      {'context': context, 'port': port, 'info': info})
            interface_info = info
            subnet = self._core_plugin._get_subnet(context,
                                                   interface_info['subnet_id'])
            network_id = subnet['network_id']
            tenant_id = port['tenant_id']
            port_filters = {'network_id': [network_id],
                            'device_owner': [DEVICE_OWNER_ROUTER_INTF]}
            port_count = self._core_plugin.get_ports_count(context,
                                                           port_filters)
            # port count is checked against 2 since the current port is already
            # added to db
            if port_count == 2:
                # This subnet is already part of some router
                LOG.error(_LE("FortinetL3ServicePlugin: adding redundant "
                              "router interface is not supported"))
                raise Exception(_("FortinetL3ServicePlugin:adding redundant "
                                  "router interface is not supported"))
            try:
                db_namespace = fortinet_db.query_record(context,
                                        fortinet_db.Fortinet_ML2_Namespace,
                                        tenant_id=tenant_id)
                vlan_inf = utils.get_intf(context, network_id)
                int_intf, ext_intf = utils.get_vlink_intf(self, context,
                                               vdom=db_namespace.vdom)
                utils.add_fwpolicy(self, context,
                                   vdom=db_namespace.vdom,
                                   srcintf=vlan_inf,
                                   dstintf=int_intf,
                                   nat='enable')

            except Exception as e:
                LOG.error(_LE("Failed to create Fortinet resources to add "
                            "router interface. info=%(info)s, "
                            "router_id=%(router_id)s"),
                          {"info": info, "router_id": router_id})
                utils._rollback_on_err(self, context, e)
                with excutils.save_and_reraise_exception():
                    self.remove_router_interface(context, router_id,
                                                 interface_info)
        utils.update_status(self, context, t_consts.TaskStatus.COMPLETED)
        return info
Example #6
0
def ctrl_conn_to_str(conn):
    """Returns a string representing a connection URL to the controller."""
    if isinstance(conn, httplib.HTTPSConnection):
        proto = "https://"
    elif isinstance(conn, httplib.HTTPConnection):
        proto = "http://"
    else:
        raise TypeError(_('Invalid connection type: %s') % type(conn))
    return "%s%s:%s" % (proto, conn.host, conn.port)
Example #7
0
 def _do_wait_and_retry_detach():
     config = get_device_conf_func(device)
     if config is not None:
         # Device is already detached from persistent domain
         # and only transient domain needs update
         self.detach_device(config, persistent=False, live=live)
         # Raise error since the device still existed on the guest
         reason = _("Unable to detach from guest transient domain.")
         raise exceptions.DeviceDetachFailed(device=device,
                                            reason=reason)
Example #8
0
 def execute(self):
     if constants.TaskStatus.ROLLBACK != self.status:
         return
     while len(self._tasks):
         try:
             subtask = self._tasks.pop()
             subtask['func'](*subtask['params'])
         except Exception:
             msg = (_("Task %(task)s encountered exception in %(func)s "),
                    {'task': str(self), 'func': str(subtask['func'])})
             self.status = constants.TaskStatus.ERROR
             self._tasks = {}
             LOG.exception(msg)
     return self._update_status(constants.TaskStatus.COMPLETED)
Example #9
0
    def _result(self, task):
        """Notify task execution result."""
        try:
            return
        except Exception:
            msg = _("Task %(task)s encountered exception in %(cb)s") % {
                'task': str(task),
                'cb': str(task._result_callback)}
            LOG.exception(msg)

        LOG.debug("Task %(task)s return %(status)s",
                  {'task': str(task), 'status': task.status})

        task._finished()
Example #10
0
    def _get_domain_by_name(self, instance_name):
        """Retrieve libvirt domain object given an instance name.

        All libvirt error handling should be handled in this method and
        relevant nova exceptions should be raised in response.

        """
        try:
            conn = self.get_connection()
            return conn.lookupByName(instance_name)
        except libvirt.libvirtError as ex:
            error_code = ex.get_error_code()
            if error_code == libvirt.VIR_ERR_NO_DOMAIN:
                raise exceptions.InstanceNotFound(instance_id=instance_name)

            msg = (_('Error from libvirt while looking up %(instance_name)s: '
                     '[Error Code %(error_code)s] %(ex)s') %
                   {'instance_name': instance_name,
                    'error_code': error_code,
                    'ex': ex})
            raise exceptions.FortinetException(msg)
 def create_router(self, context, router):
     LOG.debug("create_router: router=%s", router)
     # Limit one router per tenant
     if not router.get('router', None):
         return
     tenant_id = router['router']['tenant_id']
     if fortinet_db.query_count(context, l3_db.Router,
                                tenant_id=tenant_id):
         raise Exception(_("FortinetL3ServicePlugin:create_router "
                           "Only support one router per tenant"))
     with context.session.begin(subtransactions=True):
         try:
             namespace = utils.add_vdom(self, context, tenant_id=tenant_id)
             utils.add_vlink(self, context, namespace.vdom)
         except Exception as e:
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE("Failed to create_router router=%(router)s"),
                           {"router": router})
                 utils._rollback_on_err(self, context, e)
     utils.update_status(self, context, t_consts.TaskStatus.COMPLETED)
     return super(FortinetL3ServicePlugin, self).\
         create_router(context, router)
    def create_network_postcommit(self, mech_context):
        """Create Network as a portprofile on the fortigate."""
        LOG.debug("create_network_postcommit: called")
        network = mech_context.current
        if network["router:external"]:
            # TODO(samsu)
            return
        # use network_id to get the network attributes
        # ONLY depend on our db for getting back network attributes
        # this is so we can replay postcommit from db
        network_name = network['name']
        tenant_id = network['tenant_id']
        segment = mech_context.network_segments[0]
        # currently supports only one segment per network
        if segment['network_type'] != 'vlan':
            raise Exception(_("Fortinet Mechanism: failed to create network,"
                              "only network type vlan is supported"))

        vlanid = segment['segmentation_id']
        context = mech_context._plugin_context
        try:
            namespace = utils.add_vdom(self, context, tenant_id=tenant_id)
            if not namespace:
                raise
            # TODO(samsu): type driver support vlan only,
            # need to check later
            inf_name = const.PREFIX['inf'] + str(vlanid)
            utils.add_vlanintf(self, context,
                               name=inf_name,
                               vdom=namespace.vdom,
                               vlanid=vlanid,
                               interface=self.fortigate.cfg['int_interface'],
                               alias=network_name)
        except Exception as e:
            utils.rollback_on_err(self, context, e)
            raise ml2_exc.MechanismDriverError(
                method=sys._getframe().f_code.co_name)
        utils.update_status(self, context, t_consts.TaskStatus.COMPLETED)
Example #13
0
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from oslo_config import cfg
from oslo_log import log as logging

from networking_fortinet._i18n import _
from networking_fortinet.common import constants as const


LOG = logging.getLogger(__name__)

ML2_FORTINET = [
    cfg.StrOpt('address', default='',
               help=_('The address of fortigates to connect to')),
    cfg.StrOpt('port', default='443',
               help=_('The FGT port to serve API requests')),
    cfg.StrOpt('protocol', default='https',
               help=_('The FGT uses which protocol: http or https')),
    cfg.StrOpt('username', default='admin',
               help=_('The username used to login')),
    cfg.StrOpt('password', default='password', secret=True,
               help=_('The password used to login')),
    cfg.StrOpt('int_interface', default='internal',
               help=_('The interface to serve tenant network')),
    cfg.StrOpt('ext_interface', default='',
               help=_('The interface to the external network')),
    cfg.StrOpt('tenant_network_type', default='vlan',
               help=_('tenant network type, default is vlan')),
    cfg.StrOpt('vlink_vlan_id_range', default='3500:4000',
Example #14
0
# Copyright (c) 2016 Fortinet Inc.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from oslo_config import cfg

from networking_fortinet._i18n import _

FORTIGATE = [
    cfg.BoolOpt('enable_default_fwrule', default=False,
                help=_('If True, fwaas will add a deny all rule automatically,'
                       ' otherwise users need to add it manaully.'))
]


def register_opts():
    cfg.CONF.register_opts(FORTIGATE, "fortigate")
Example #15
0
    def _issue_request(self):
        '''Issue a request to a provider.'''
        conn = self.get_conn()
        if conn is None:
            error = Exception(_("No API connections available"))
            self._request_error = error
            return error

        url = self._url
        LOG.debug("[%(rid)d] Issuing - request url: %(conn)s, body: %(body)s",
                  {'rid': self._rid(), 'conn': self._request_str(conn, url),
                   'body': self._body})
        issued_time = time.time()
        is_conn_error = False
        is_conn_service_unavail = False
        response = None
        try:
            redirects = 0
            while redirects <= self._redirects:
                # Update connection with user specified request timeout,
                # the connect timeout is usually smaller so we only set
                # the request timeout after a connection is established
                if conn.sock is None:
                    conn.connect()
                    conn.sock.settimeout(self._http_timeout)
                elif conn.sock.gettimeout() != self._http_timeout:
                    conn.sock.settimeout(self._http_timeout)

                headers = copy.copy(self._headers)
                if templates.RELOGIN in url:
                    url = jsonutils.loads(templates.LOGIN)['path']
                    conn.connect()
                    self._api_client._wait_for_login(conn, headers)
                    url = self._url

                cookie = self._api_client.auth_cookie(conn)

                if (self._url != jsonutils.loads(templates.LOGIN)['path'] and
                    cookie):
                    headers['Cookie'] = cookie['Cookie']
                    headers['X-CSRFTOKEN'] = cookie['X-CSRFTOKEN']

                try:
                    if self._body:
                        if (self._url ==
                                jsonutils.loads(templates.LOGIN)['path']):
                            body = urlparse.urlencode(self._body)
                        else:
                            body = jsonutils.dumps(self._body)
                    else:
                        body = None
                    LOG.debug("Issuing request: self._method = [%(method)s], "
                              "url= %(url)s, body=%(body)s, "
                              "headers=%(headers)s",
                              {'method': self._method, "url": url,
                               "body": body, "headers": headers})
                    conn.request(self._method, url, body, headers)
                except Exception as e:
                    with excutils.save_and_reraise_exception():
                        LOG.warning(
                            _LW("[%(rid)d] Exception issuing request: %(e)s"),
                            {'rid': self._rid(), 'e': e})

                response = conn.getresponse()
                response.body = response.read()
                response.headers = response.getheaders()
                elapsed_time = time.time() - issued_time
                LOG.debug("@@@@@@ [ _issue_request ] [%(rid)d] "
                          "Completed request '%(conn)s': "
                          "%(status)s (%(elapsed)s seconds), "
                          "response.headers %(response.headers)s, "
                          "response.body %(response.body)s",
                          {'rid': self._rid(),
                           'conn': self._request_str(conn, url),
                           'status': response.status,
                           'elapsed': elapsed_time,
                           'response.headers': response.headers,
                           'response.body': response.body})

                if response.status in (401, 302):
                    if (cookie is None and
                       self._url != jsonutils.loads(templates.LOGIN)['path']):
                        # The connection still has no valid cookie despite
                        # attempts to authenticate and the request has failed
                        # with unauthorized status code. If this isn't a
                        # a request to authenticate, we should abort the
                        # request since there is no point in retrying.
                        self._abort = True
                    # If request is unauthorized, clear the session cookie
                    # for the current provider so that subsequent requests
                    # to the same provider triggers re-authentication.
                    self._api_client.set_auth_cookie(conn, None)

                elif 503 == response.status:
                    is_conn_service_unavail = True

                if response.status not in [301, 307]:
                    break
                elif redirects >= self._redirects:
                    LOG.info(_LI("[%d] Maximum redirects exceeded, aborting "
                                 "request"), self._rid())
                    break
                redirects += 1
                conn, url = self._redirect_params(conn, response.headers,
                                                  self._client_conn is None)
                if url is None:
                    response.status = 500
                    break
                LOG.info(_LI("[%(rid)d] Redirecting request to: %(conn)s"),
                         {'rid': self._rid(),
                          'conn': self._request_str(conn, url)})
                # yield here, just in case we are not out of the loop yet
                eventlet.greenthread.sleep(0)
            # If we receive any of these responses, then
            # our server did not process our request and may be in an
            # errored state. Raise an exception, which will cause the
            # the conn to be released with is_conn_error == True
            # which puts the conn on the back of the client's priority
            # queue.
            if 500 == response.status or 501 < response.status:
                LOG.warning(_LW("[%(rid)d] Request '%(method)s %(url)s' "
                                "received: %(status)s"),
                            {'rid': self._rid(), 'method': self._method,
                             'url': self._url, 'status': response.status})
                raise Exception(_('Server error return: %s'), response.status)
            return response

        except Exception as e:
            if isinstance(e, httpclient.BadStatusLine):
                msg = ("Invalid server response")
            else:
                msg = str(e)
            if response is None:
                elapsed_time = time.time() - issued_time
            LOG.warning(_LW("[%(rid)d] Failed request '%(conn)s': '%(msg)s' "
                            "(%(elapsed)s seconds)"),
                        {'rid': self._rid(),
                         'conn': self._request_str(conn, url),
                         'msg': msg, 'elapsed': elapsed_time})
            self._request_error = e
            is_conn_error = True
            return e

        finally:
            # Make sure we release the original connection provided by the
            # acquire_connection() call above.
            if self._client_conn is None:
                self._api_client.release_connection(conn, is_conn_error,
                                                    is_conn_service_unavail,
                                                    rid=self._rid())