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 _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 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
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_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)
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)
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
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)
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)
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)
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()
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)
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()
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] LOG.debug( "network is created in tenant %(tenant_id)s," "segment id is %(segment)s", { "tenant_id": tenant_id, "segment": segment['segmentation_id'] }) # 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 inf_name = const.PREFIX['inf'] + str(vlanid) utils.add_vlanintf(self, context, name=inf_name, vdom=namespace.vdom, vlanid=vlanid, interface=self._fortigate['int_interface'], alias=network_name, network_id=network['id']) 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)
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_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)
# # 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 fortiosclient import client from oslo_config import cfg from networking_fortinet._i18n import _ 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',
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
class TaskStateSkipped(TaskException): message = _("State %(state)d skipped. Current state %(current)d")
class InvalidState(TaskException): message = _("Invalid state %(state)d")
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())
# 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',
# 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")
# Copyright (c) 2016 Tsinghuanet 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, "tsinghuanet")