예제 #1
0
    def test_task_manager_task_parallel_process(self):
        tasks = []

        def _exec(task):
            task.userdata['executed'] = True
            return ts_const.TaskStatus.PENDING

        def _status(task):
            for t in tasks:
                if not t.userdata.get('executed'):
                    t.userdata['resut'] = False
            return ts_const.TaskStatus.COMPLETED

        def _result(task):
            if (task.userdata.get('result') is None and
                task.status == ts_const.TaskStatus.COMPLETED):
                task.userdata['result'] = True
            else:
                task.userdata['result'] = False

        for i in range(5):
            name = "name-%d" % i
            res = 'resource-%d' % i
            task = ts.Task(name, res, _exec, _status, _result, {})
            tasks.append(task)
            self.manager.add(task)

        for task in tasks:
            task.wait(ts_const.TaskState.RESULT)
            self.assertTrue(task.userdata['result'])
 def delete_port_group(self, dvs_id, port_group_id):
     task_name = 'delete-port-group-%s-%s' % (port_group_id, dvs_id)
     userdata = {'retry_number': 1,
                 'retry_command': self.vcns.delete_port_group,
                 'args': [dvs_id, port_group_id]}
     task = tasks.Task(task_name, port_group_id,
                       self._retry_task,
                       status_callback=self._retry_task,
                       userdata=userdata)
     self.task_manager.add(task)
 def delete_virtual_wire(self, vw_id):
     task_name = 'delete-virtualwire-%s' % vw_id
     userdata = {'retry_number': 1,
                 'retry_command': self.vcns.delete_virtual_wire,
                 'args': [vw_id]}
     task = tasks.Task(task_name, vw_id,
                       self._retry_task,
                       status_callback=self._retry_task,
                       userdata=userdata)
     self.task_manager.add(task)
 def delete_portgroup(self, dvs_id, port_group_id, job_id):
     task_name = "delete-port-group-%s" % port_group_id
     userdata = {'dvs_id': dvs_id,
                 'port_group_id': port_group_id,
                 'job_id': job_id}
     task = tasks.Task(task_name, port_group_id,
                       self._delete_port_group,
                       status_callback=self._delete_port_group,
                       userdata=userdata)
     self.task_manager.add(task)
 def delete_edge(self, resource_id, edge_id, jobdata=None, dist=False):
     task_name = 'delete-%s' % edge_id
     userdata = {
         'router_id': resource_id,
         'dist': dist,
         'edge_id': edge_id,
         'jobdata': jobdata
     }
     task = tasks.Task(task_name, resource_id, self._delete_edge,
                       userdata=userdata)
     task.add_result_monitor(self.callbacks.edge_delete_result)
     self.task_manager.add(task)
     return task
 def delete_snat_rule(self, router_id, edge_id, src, jobdata=None):
     LOG.debug("VCNS: delete snat rule %s", src)
     userdata = {
         'edge_id': edge_id,
         'address': src,
         'addrtype': 'originalAddress',
         'jobdata': jobdata
     }
     task_name = "delete-snat-%s-%s" % (edge_id, src)
     task = tasks.Task(task_name, router_id, self._delete_nat_rule,
                       userdata=userdata)
     task.add_result_monitor(self.callbacks.snat_delete_result)
     self.task_manager.add(task)
     return task
    def rename_edge(self, router_id, edge_id, name):
        """rename edge."""
        task_name = 'rename-%s' % name

        userdata = {
            'edge_id': edge_id,
            'name': name
        }
        task = tasks.Task(task_name, router_id,
                          self._rename_edge,
                          userdata=userdata)
        task.add_result_monitor(self.callbacks.edge_rename_result)
        self.task_manager.add(task)
        return task
    def update_edge(self, router_id, edge_id, name, internal_network,
                    jobdata=None, dist=False, loadbalancer_enable=True,
                    appliance_size=nsxv_constants.LARGE,
                    set_errors=False):
        """Update edge name."""
        task_name = 'update-%s' % name
        edge_name = name
        edge = self._assemble_edge(
            edge_name, datacenter_moid=self.datacenter_moid,
            deployment_container_id=self.deployment_container_id,
            appliance_size=appliance_size, remote_access=False, dist=dist)
        edge['id'] = edge_id
        appliance = self._assemble_edge_appliance(self.resource_pool_id,
                                                  self.datastore_id)
        if appliance:
            edge['appliances']['appliances'] = [appliance]

        if not dist:
            vnic_external = self._assemble_edge_vnic(
                constants.EXTERNAL_VNIC_NAME, constants.EXTERNAL_VNIC_INDEX,
                self.external_network, type="uplink")
            edge['vnics']['vnics'].append(vnic_external)
        else:
            edge['mgmtInterface'] = {
                'connectedToId': self.external_network,
                'name': "mgmtInterface"}

        if internal_network:
            internal_vnic = self._assemble_edge_vnic(
                constants.INTERNAL_VNIC_NAME, constants.INTERNAL_VNIC_INDEX,
                internal_network,
                constants.INTEGRATION_EDGE_IPADDRESS,
                constants.INTEGRATION_SUBNET_NETMASK,
                type="internal")
            edge['vnics']['vnics'].append(internal_vnic)
        if not dist and loadbalancer_enable:
            self._enable_loadbalancer(edge)
        userdata = {
            'router_id': router_id,
            'edge_id': edge_id,
            'request': edge,
            'jobdata': jobdata,
            'set_errors': set_errors
        }
        task = tasks.Task(task_name, router_id,
                          self._update_edge,
                          userdata=userdata)
        task.add_result_monitor(self.callbacks.edge_update_result)
        self.task_manager.add(task)
        return task
 def delete_interface(self, router_id, edge_id, index, jobdata=None):
     task_name = "delete-interface-%s-%d" % (edge_id, index)
     userdata = {
         'router_id': router_id,
         'edge_id': edge_id,
         'vnic_index': index,
         'jobdata': jobdata
     }
     task = tasks.Task(task_name, router_id, self._delete_interface,
                       userdata=userdata)
     task.add_result_monitor(self.callbacks.interface_delete_result)
     self.task_manager.add(task)
     # avoid bug 1389358
     self.check_edge_jobs(edge_id)
     return task
 def delete_dnat_rule(self, router_id, edge_id, translated,
                      jobdata=None):
     # TODO(fank): pass in rule_id for optimization
     LOG.debug("VCNS: delete dnat rule %s", translated)
     userdata = {
         'edge_id': edge_id,
         'address': translated,
         'addrtype': 'translatedAddress',
         'jobdata': jobdata
     }
     task_name = "delete-dnat-%s-%s" % (edge_id, translated)
     task = tasks.Task(task_name, router_id, self._delete_nat_rule,
                       userdata=userdata)
     task.add_result_monitor(self.callbacks.dnat_delete_result)
     self.task_manager.add(task)
     return task
 def create_snat_rule(self, router_id, edge_id, src, translated,
                      jobdata=None, location=None):
     LOG.debug("VCNS: create snat rule %(src)s/%(translated)s", {
         'src': src, 'translated': translated})
     snat_rule = self._assemble_nat_rule("snat", src, translated)
     userdata = {
         'router_id': router_id,
         'edge_id': edge_id,
         'rule': snat_rule,
         'location': location,
         'jobdata': jobdata
     }
     task_name = "create-snat-%s-%s-%s" % (edge_id, src, translated)
     task = tasks.Task(task_name, router_id, self._create_nat_rule,
                       userdata=userdata)
     task.add_result_monitor(self.callbacks.snat_create_result)
     self.task_manager.add(task)
     return task
예제 #12
0
    def _test_task_manager_stop(self,
                                exec_wait=False,
                                result_wait=False,
                                stop_wait=0):
        def _exec(task):
            if exec_wait:
                greenthread.sleep(0.01)
            return ts_const.TaskStatus.PENDING

        def _status(task):
            greenthread.sleep(0.01)
            return ts_const.TaskStatus.PENDING

        def _result(task):
            if result_wait:
                greenthread.sleep(0)
            pass

        manager = ts.TaskManager().start(100)
        manager.stop()
        # Task manager should not leave running threads around
        # if _thread is None it means it was killed in stop()
        self.assertIsNone(manager._thread)
        manager.start(100)

        alltasks = {}
        for i in range(100):
            res = 'res-%d' % i
            tasks = []
            for i in range(100):
                task = ts.Task('name', res, _exec, _status, _result)
                manager.add(task)
                tasks.append(task)
            alltasks[res] = tasks

        greenthread.sleep(stop_wait)
        manager.stop()
        # Task manager should not leave running threads around
        # if _thread is None it means it was killed in stop()
        self.assertIsNone(manager._thread)

        for res, tasks in six.iteritems(alltasks):
            for task in tasks:
                self.assertEqual(ts_const.TaskStatus.ABORT, task.status)
    def update_routes(self, router_id, edge_id, gateway, routes,
                      skippable=True, jobdata=None,
                      gateway_vnic_index=constants.EXTERNAL_VNIC_INDEX):
        if gateway:
            gateway = gateway.split('/')[0]

        userdata = {
            'edge_id': edge_id,
            'gateway': gateway,
            'gateway_vnic_index': gateway_vnic_index,
            'routes': routes,
            'skippable': skippable,
            'jobdata': jobdata
        }
        task_name = "update-routes-%s" % (edge_id)
        task = tasks.Task(task_name, router_id, self._update_routes,
                          userdata=userdata)
        task.add_result_monitor(self.callbacks.routes_update_result)
        self.updated_task['route'][edge_id] = task
        self.task_manager.add(task)
        return task
 def create_dnat_rule(self, router_id, edge_id, dst, translated,
                      jobdata=None, location=None):
     # TODO(fank): use POST for optimization
     #             return rule_id for future reference
     LOG.debug("VCNS: create dnat rule %(dst)s/%(translated)s", {
         'dst': dst, 'translated': translated})
     dnat_rule = self._assemble_nat_rule(
         "dnat", dst, translated)
     userdata = {
         'router_id': router_id,
         'edge_id': edge_id,
         'rule': dnat_rule,
         'location': location,
         'jobdata': jobdata
     }
     task_name = "create-dnat-%s-%s-%s" % (edge_id, dst, translated)
     task = tasks.Task(task_name, router_id, self._create_nat_rule,
                       userdata=userdata)
     task.add_result_monitor(self.callbacks.dnat_create_result)
     self.task_manager.add(task)
     return task
예제 #15
0
    def test_task_pending_task(self):
        def _exec(task):
            task.userdata['executing'] = True
            while not task.userdata['tested']:
                greenthread.sleep(0)
            task.userdata['executing'] = False
            return ts_const.TaskStatus.COMPLETED

        userdata = {'executing': False, 'tested': False}
        manager = ts.TaskManager().start(100)
        task = ts.Task('name', 'res', _exec, userdata=userdata)
        manager.add(task)

        while not userdata['executing']:
            greenthread.sleep(0)
        self.assertTrue(manager.has_pending_task())

        userdata['tested'] = True
        while userdata['executing']:
            greenthread.sleep(0)
        self.assertFalse(manager.has_pending_task())
예제 #16
0
    def test_task_manager_task_ordered_process(self):
        def _task_failed(task, reason):
            task.userdata['result'] = False
            task.userdata['error'] = reason

        def _exec(task):
            task.userdata['executed'] = True
            return ts_const.TaskStatus.PENDING

        def _status(task):
            return ts_const.TaskStatus.COMPLETED

        def _result(task):
            next_task = task.userdata.get('next')
            if next_task:
                if next_task.userdata.get('executed'):
                    _task_failed(next_task, "executed premature")
            if task.userdata.get('result', True):
                task.userdata['result'] = True

        tasks = []
        prev = None
        last_task = None
        for i in range(5):
            name = "name-%d" % i
            task = ts.Task(name, 'res', _exec, _status, _result, {})
            tasks.append(task)
            if prev:
                prev.userdata['next'] = task
            prev = task
            last_task = task

        for task in tasks:
            self.manager.add(task)

        last_task.wait(ts_const.TaskState.RESULT)

        for task in tasks:
            self.assertTrue(task.userdata['result'])
    def update_nat_rules(self, router_id, edge_id, snats, dnats,
                         jobdata=None):
        LOG.debug("VCNS: update nat rule\n"
                  "SNAT:%(snat)s\n"
                  "DNAT:%(dnat)s\n", {
                        'snat': snats, 'dnat': dnats})
        nat_rules = []

        for dnat in dnats:
            vnic_index = constants.EXTERNAL_VNIC_INDEX
            if 'vnic_index' in dnat:
                vnic_index = dnat['vnic_index']
            nat_rules.append(self._assemble_nat_rule(
                'dnat', dnat['dst'], dnat['translated'], vnic_index=vnic_index
            ))
            nat_rules.append(self._assemble_nat_rule(
                'snat', dnat['translated'], dnat['dst'], vnic_index=vnic_index
            ))

        for snat in snats:
            vnic_index = constants.EXTERNAL_VNIC_INDEX
            if 'vnic_index' in snat:
                vnic_index = snat['vnic_index']
            nat_rules.append(self._assemble_nat_rule(
                'snat', snat['src'], snat['translated'], vnic_index=vnic_index
            ))

        userdata = {
            'edge_id': edge_id,
            'rules': nat_rules,
            'jobdata': jobdata,
        }
        task_name = "update-nat-%s" % edge_id
        task = tasks.Task(task_name, router_id, self._update_nat_rule,
                          userdata=userdata)
        task.add_result_monitor(self.callbacks.nat_update_result)
        self.updated_task['nat'][edge_id] = task
        self.task_manager.add(task)
        return task
 def asyn_update_firewall(self,
                          router_id,
                          edge_id,
                          firewall,
                          jobdata=None,
                          allow_external=True):
     # TODO(berlin): Remove uncessary context input parameter.
     config = self._convert_firewall(None,
                                     firewall,
                                     allow_external=allow_external)
     userdata = {
         'edge_id': edge_id,
         'config': config,
         'fw_config': firewall,
         'jobdata': jobdata
     }
     task_name = "update-firewall-%s" % edge_id
     task = tasks.Task(task_name,
                       router_id,
                       self._asyn_update_firewall,
                       userdata=userdata)
     task.add_result_monitor(self.callbacks.firewall_update_result)
     self.task_manager.add(task)
     return task
예제 #19
0
    def _test_task_manager_task_process_state(self, sync_exec=False):
        def _task_failed(task, reason):
            task.userdata['result'] = False
            task.userdata['error'] = reason

        def _check_state(task, exp_state):
            if not task.userdata.get('result', True):
                return False

            state = task.userdata['state']
            if state != exp_state:
                msg = "state %d expect %d" % (
                    state, exp_state)
                _task_failed(task, msg)
                return False

            task.userdata['state'] = state + 1
            return True

        def _exec(task):
            if not _check_state(task, 1):
                return ts_const.TaskStatus.ERROR

            if task.userdata['sync_exec']:
                return ts_const.TaskStatus.COMPLETED
            else:
                return ts_const.TaskStatus.PENDING

        def _status(task):
            if task.userdata['sync_exec']:
                _task_failed(task, "_status callback triggered")

            state = task.userdata['state']
            if state == 3:
                _check_state(task, 3)
                return ts_const.TaskStatus.PENDING
            else:
                _check_state(task, 4)
                return ts_const.TaskStatus.COMPLETED

        def _result(task):
            if task.userdata['sync_exec']:
                exp_state = 3
            else:
                exp_state = 5

            _check_state(task, exp_state)

        def _start_monitor(task):
            _check_state(task, 0)

        def _executed_monitor(task):
            _check_state(task, 2)

        def _result_monitor(task):
            if task.userdata['sync_exec']:
                exp_state = 4
            else:
                exp_state = 6

            if _check_state(task, exp_state):
                task.userdata['result'] = True
            else:
                task.userdata['result'] = False

        userdata = {
            'state': 0,
            'sync_exec': sync_exec
        }
        task = ts.Task('name', 'res', _exec, _status, _result, userdata)
        task.add_start_monitor(_start_monitor)
        task.add_executed_monitor(_executed_monitor)
        task.add_result_monitor(_result_monitor)

        self.manager.add(task)

        task.wait(ts_const.TaskState.RESULT)

        self.assertTrue(userdata['result'])
class EdgeApplianceDriver(object):
    def __init__(self):
        super(EdgeApplianceDriver, self).__init__()
        # store the last task per edge that has the latest config
        self.updated_task = {
            'nat': {},
            'route': {},
        }

    def _assemble_edge(self, name, appliance_size="compact",
                       deployment_container_id=None, datacenter_moid=None,
                       enable_aesni=True, dist=False,
                       enable_fips=False, remote_access=False):
        edge = {
            'name': name,
            'fqdn': None,
            'enableAesni': enable_aesni,
            'enableFips': enable_fips,
            'featureConfigs': {
                'features': [
                    {
                        'featureType': 'firewall_4.0',
                        'globalConfig': {
                            'tcpTimeoutEstablished': 7200
                        }
                    }
                ]
            },
            'cliSettings': {
                'remoteAccess': remote_access
            },
            'autoConfiguration': {
                'enabled': False,
                'rulePriority': 'high'
            },
            'appliances': {
                'applianceSize': appliance_size
            },
        }
        if not dist:
            edge['type'] = "gatewayServices"
            edge['vnics'] = {'vnics': []}
        else:
            edge['type'] = "distributedRouter"
            edge['interfaces'] = {'interfaces': []}

        if deployment_container_id:
            edge['appliances']['deploymentContainerId'] = (
                deployment_container_id)
        if datacenter_moid:
            edge['datacenterMoid'] = datacenter_moid

        if not dist and cfg.CONF.nsxv.edge_ha:
            self._enable_high_availability(edge)

        return edge

    def _assemble_edge_appliance(self, resource_pool_id, datastore_id):
        appliance = {}
        if resource_pool_id:
            appliance['resourcePoolId'] = resource_pool_id
        if datastore_id:
            appliance['datastoreId'] = datastore_id
        return appliance

    def _assemble_edge_vnic(self, name, index, portgroup_id, tunnel_index=-1,
                            primary_address=None, subnet_mask=None,
                            secondary=None,
                            type="internal",
                            enable_proxy_arp=False,
                            enable_send_redirects=True,
                            is_connected=True,
                            mtu=1500,
                            address_groups=None):
        vnic = {
            'index': index,
            'name': name,
            'type': type,
            'portgroupId': portgroup_id,
            'mtu': mtu,
            'enableProxyArp': enable_proxy_arp,
            'enableSendRedirects': enable_send_redirects,
            'isConnected': is_connected
        }
        if address_groups is None:
            address_groups = []
        if not address_groups:
            if primary_address and subnet_mask:
                address_group = {
                    'primaryAddress': primary_address,
                    'subnetMask': subnet_mask
                }
                if secondary:
                    address_group['secondaryAddresses'] = {
                        'ipAddress': secondary,
                        'type': 'secondary_addresses'
                    }

                vnic['addressGroups'] = {
                    'addressGroups': [address_group]
                }
            else:
                vnic['subInterfaces'] = {'subInterfaces': address_groups}
        else:
            if tunnel_index < 0:
                vnic['addressGroups'] = {'addressGroups': address_groups}
            else:
                vnic['subInterfaces'] = {'subInterfaces': address_groups}

        return vnic

    def _assemble_vdr_interface(self, portgroup_id,
                                primary_address=None, subnet_mask=None,
                                secondary=None,
                                type="internal",
                                is_connected=True,
                                mtu=1500,
                                address_groups=None):
        interface = {
            'type': type,
            'connectedToId': portgroup_id,
            'mtu': mtu,
            'isConnected': is_connected
        }
        if address_groups is None:
            address_groups = []
        if not address_groups:
            if primary_address and subnet_mask:
                address_group = {
                    'primaryAddress': primary_address,
                    'subnetMask': subnet_mask
                }
                if secondary:
                    address_group['secondaryAddresses'] = {
                        'ipAddress': secondary,
                        'type': 'secondary_addresses'
                    }

                interface['addressGroups'] = {
                    'addressGroups': [address_group]
                }
        else:
            interface['addressGroups'] = {'addressGroups': address_groups}
        interfaces = {'interfaces': [interface]}

        return interfaces

    def _edge_status_to_level(self, status):
        if status == 'GREEN':
            status_level = constants.RouterStatus.ROUTER_STATUS_ACTIVE
        elif status in ('GREY', 'YELLOW'):
            status_level = constants.RouterStatus.ROUTER_STATUS_DOWN
        else:
            status_level = constants.RouterStatus.ROUTER_STATUS_ERROR
        return status_level

    def _enable_loadbalancer(self, edge):
        if (not edge.get('featureConfigs') or
            not edge['featureConfigs'].get('features')):
            edge['featureConfigs'] = {'features': []}
        edge['featureConfigs']['features'].append(
            {'featureType': 'loadbalancer_4.0',
             'enabled': True})

    def _enable_high_availability(self, edge):
        if (not edge.get('featureConfigs') or
            not edge['featureConfigs'].get('features')):
            edge['featureConfigs'] = {'features': []}
        edge['featureConfigs']['features'].append(
            {'featureType': 'highavailability_4.0',
             'enabled': True})

    def get_edge_status(self, edge_id):
        try:
            response = self.vcns.get_edge_status(edge_id)[1]
            status_level = self._edge_status_to_level(
                response['edgeStatus'])
        except exceptions.VcnsApiException as e:
            LOG.exception(_LE("VCNS: Failed to get edge status:\n%s"),
                          e.response)
            status_level = constants.RouterStatus.ROUTER_STATUS_ERROR
            try:
                desc = jsonutils.loads(e.response)
                if desc.get('errorCode') == (
                    constants.VCNS_ERROR_CODE_EDGE_NOT_RUNNING):
                    status_level = constants.RouterStatus.ROUTER_STATUS_DOWN
            except ValueError:
                LOG.exception(e.response)

        return status_level

    def get_edges_statuses(self):
        edges_status_level = {}
        edges = self._get_edges()
        for edge in edges['edgePage'].get('data', []):
            edge_id = edge['id']
            status = edge['edgeStatus']
            edges_status_level[edge_id] = self._edge_status_to_level(status)

        return edges_status_level

    def get_interface(self, edge_id, vnic_index):
        self.check_edge_jobs(edge_id)
        # get vnic interface address groups
        try:
            return self.vcns.query_interface(edge_id, vnic_index)
        except exceptions.VcnsApiException:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("NSXv: Failed to query vnic %s"), vnic_index)

    def check_edge_jobs(self, edge_id):
        retries = max(cfg.CONF.nsxv.retries, 1)
        delay = 0.5
        for attempt in range(1, retries + 1):
            if attempt != 1:
                time.sleep(delay)
                delay = min(2 * delay, 60)
            h, jobs = self.vcns.get_edge_jobs(edge_id)
            if jobs['edgeJob'] == []:
                return
            job_number = len(jobs['edgeJob'])
            # Assume one job would wait time out after 20 minutes and one
            # job takes about 1 minute to be completed.
            if job_number < 20:
                LOG.warning(_LW("NSXv: %(num)s jobs still running on edge "
                                "%(edge_id)s."),
                            {'num': job_number,
                             'edge_id': edge_id})
            else:
                LOG.error(_LE("NSXv: %(num)s jobs still running on edge "
                              "%(edge_id)s. Too many jobs may lead to job "
                              "time out at the backend"),
                          {'num': job_number,
                           'edge_id': edge_id})
        LOG.error(_LE('NSXv: jobs are still runnings!'))

    def update_interface(self, router_id, edge_id, index, network,
                         tunnel_index=-1, address=None, netmask=None,
                         secondary=None, jobdata=None, is_connected=True,
                         address_groups=None):
        LOG.debug("VCNS: update vnic %(index)d: %(addr)s %(netmask)s", {
            'index': index, 'addr': address, 'netmask': netmask})
        if index == constants.EXTERNAL_VNIC_INDEX:
            name = constants.EXTERNAL_VNIC_NAME
            intf_type = 'uplink'
        else:
            name = constants.INTERNAL_VNIC_NAME + str(index)
            if tunnel_index < 0:
                intf_type = 'internal'
            else:
                intf_type = 'trunk'

        config = self._assemble_edge_vnic(
            name, index, network, tunnel_index,
            address, netmask, secondary, type=intf_type,
            address_groups=address_groups, is_connected=is_connected)

        self.vcns.update_interface(edge_id, config)

    def add_vdr_internal_interface(self, edge_id,
                                   network, address=None, netmask=None,
                                   secondary=None, address_groups=None,
                                   type="internal", is_connected=True):
        LOG.debug("Add VDR interface on edge: %s", edge_id)
        if address_groups is None:
            address_groups = []
        interface_req = (
            self._assemble_vdr_interface(network, address, netmask, secondary,
                                         address_groups=address_groups,
                                         is_connected=is_connected, type=type))
        self.vcns.add_vdr_internal_interface(edge_id, interface_req)
        header, response = self.vcns.get_edge_interfaces(edge_id)
        for interface in response['interfaces']:
            if interface['connectedToId'] == network:
                vnic_index = int(interface['index'])
                return vnic_index

    def update_vdr_internal_interface(self, edge_id, index, network,
                                      address_groups=None, is_connected=True):
        if not address_groups:
            address_groups = []
        interface = {
            'type': 'internal',
            'connectedToId': network,
            'mtu': 1500,
            'isConnected': is_connected,
            'addressGroups': {'addressGroup': address_groups}
        }
        interface_req = {'interface': interface}
        try:
            header, response = self.vcns.update_vdr_internal_interface(
                edge_id, index, interface_req)
        except exceptions.VcnsApiException:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Failed to update vdr interface on edge: "
                                  "%s"), edge_id)

    def delete_vdr_internal_interface(self, edge_id, interface_index):
        LOG.debug("Delete VDR interface on edge: %s", edge_id)
        try:
            header, response = self.vcns.delete_vdr_internal_interface(
                edge_id, interface_index)
        except exceptions.VcnsApiException:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Failed to delete vdr interface on edge: "
                                  "%s"),
                              edge_id)
        # avoid bug 1389358
        self.check_edge_jobs(edge_id)

    def _delete_interface(self, task):
        edge_id = task.userdata['edge_id']
        vnic_index = task.userdata['vnic_index']
        LOG.debug("start deleting vnic %s", vnic_index)
        try:
            self.vcns.delete_interface(edge_id, vnic_index)
        except exceptions.VcnsApiException:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Failed to delete vnic %(vnic_index)s: "
                                  "on edge %(edge_id)s"),
                              {'vnic_index': vnic_index,
                               'edge_id': edge_id})
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Failed to delete vnic %d"), vnic_index)

        return task_constants.TaskStatus.COMPLETED

    def delete_interface(self, router_id, edge_id, index, jobdata=None):
        task_name = "delete-interface-%s-%d" % (edge_id, index)
        userdata = {
            'router_id': router_id,
            'edge_id': edge_id,
            'vnic_index': index,
            'jobdata': jobdata
        }
        task = tasks.Task(task_name, router_id, self._delete_interface,
                          userdata=userdata)
        task.add_result_monitor(self.callbacks.interface_delete_result)
        self.task_manager.add(task)
        # avoid bug 1389358
        self.check_edge_jobs(edge_id)
        return task

    def _deploy_edge(self, task):
        userdata = task.userdata
        LOG.debug("NSXv: start deploying edge")
        request = userdata['request']
        try:
            header = self.vcns.deploy_edge(request)[0]
            objuri = header['location']
            job_id = objuri[objuri.rfind("/") + 1:]
            response = self.vcns.get_edge_id(job_id)[1]
            edge_id = response['edgeId']
            LOG.debug("VCNS: deploying edge %s", edge_id)
            userdata['edge_id'] = edge_id
            status = task_constants.TaskStatus.PENDING
        except exceptions.VcnsApiException:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("NSXv: deploy edge failed."))

        return status

    def _status_edge(self, task):
        edge_id = task.userdata['edge_id']
        try:
            response = self.vcns.get_edge_deploy_status(edge_id)[1]
            task.userdata['retries'] = 0
            system_status = response.get('systemStatus', None)
            if system_status is None:
                status = task_constants.TaskStatus.PENDING
            elif system_status == 'good':
                status = task_constants.TaskStatus.COMPLETED
            else:
                status = task_constants.TaskStatus.ERROR
        except exceptions.VcnsApiException as e:
            LOG.exception(_LE("VCNS: Edge %s status query failed."), edge_id)
            raise e
        except Exception as e:
            retries = task.userdata.get('retries', 0) + 1
            if retries < 3:
                task.userdata['retries'] = retries
                LOG.exception(_LE("VCNS: Unable to retrieve edge %(edge_id)s "
                                  "status. Retry %(retries)d."),
                              {'edge_id': edge_id,
                               'retries': retries})
                status = task_constants.TaskStatus.PENDING
            else:
                LOG.exception(_LE("VCNS: Unable to retrieve edge %s status. "
                                  "Abort."), edge_id)
                status = task_constants.TaskStatus.ERROR
        LOG.debug("VCNS: Edge %s status", edge_id)
        return status

    def _result_edge(self, task):
        edge_id = task.userdata.get('edge_id')
        if task.status != task_constants.TaskStatus.COMPLETED:
            LOG.error(_LE("NSXv: Failed to deploy edge %(edge_id)s "
                          "status %(status)d"),
                      {'edge_id': edge_id,
                       'status': task.status})
        else:
            LOG.debug("NSXv: Edge %s is deployed", edge_id)

    def _update_edge(self, task):
        edge_id = task.userdata['edge_id']
        LOG.debug("start update edge %s", edge_id)
        request = task.userdata['request']
        try:
            self.vcns.update_edge(edge_id, request)
            status = task_constants.TaskStatus.COMPLETED
        except exceptions.VcnsApiException as e:
            LOG.error(_LE("Failed to update edge: %s"),
                      e.response)
            status = task_constants.TaskStatus.ERROR

        return status

    def _rename_edge(self, task):
        edge_id = task.userdata['edge_id']
        LOG.debug("start rename edge %s", edge_id)
        try:
            # First get the current edge structure
            # [0] is the status, [1] is the body
            edge = self.vcns.get_edge(edge_id)[1]
            # remove some data that will make the update fail
            edge_utils.remove_irrelevant_keys_from_edge_request(edge)
            # set the new name in the request
            edge['name'] = task.userdata['name']
            # update the edge
            self.vcns.update_edge(edge_id, edge)
            status = task_constants.TaskStatus.COMPLETED
        except exceptions.VcnsApiException as e:
            LOG.error(_LE("Failed to rename edge: %s"),
                      e.response)
            status = task_constants.TaskStatus.ERROR

        return status

    def _delete_edge(self, task):
        edge_id = task.userdata['edge_id']
        LOG.debug("VCNS: start destroying edge %s", edge_id)
        status = task_constants.TaskStatus.COMPLETED
        if edge_id:
            try:
                self.vcns.delete_edge(edge_id)
            except exceptions.ResourceNotFound:
                pass
            except exceptions.VcnsApiException as e:
                LOG.exception(_LE("VCNS: Failed to delete %(edge_id)s:\n"
                                  "%(response)s"),
                              {'edge_id': edge_id, 'response': e.response})
                status = task_constants.TaskStatus.ERROR
            except Exception:
                LOG.exception(_LE("VCNS: Failed to delete %s"), edge_id)
                status = task_constants.TaskStatus.ERROR

        return status

    def _get_edges(self):
        try:
            return self.vcns.get_edges()[1]
        except exceptions.VcnsApiException as e:
            LOG.exception(_LE("VCNS: Failed to get edges:\n%s"), e.response)
            raise e

    def deploy_edge(self, resource_id, name, internal_network, jobdata=None,
                    dist=False, wait_for_exec=False, loadbalancer_enable=True,
                    appliance_size=nsxv_constants.LARGE, async=True):
        task_name = 'deploying-%s' % name
        edge_name = name
        edge = self._assemble_edge(
            edge_name, datacenter_moid=self.datacenter_moid,
            deployment_container_id=self.deployment_container_id,
            appliance_size=appliance_size, remote_access=False, dist=dist)
        appliance = self._assemble_edge_appliance(self.resource_pool_id,
                                                  self.datastore_id)
        if appliance:
            edge['appliances']['appliances'] = [appliance]

        if not dist:
            vnic_external = self._assemble_edge_vnic(
                constants.EXTERNAL_VNIC_NAME, constants.EXTERNAL_VNIC_INDEX,
                self.external_network, type="uplink")
            edge['vnics']['vnics'].append(vnic_external)
        else:
            edge['mgmtInterface'] = {
                'connectedToId': self.external_network,
                'name': "mgmtInterface"}
        if internal_network:
            vnic_inside = self._assemble_edge_vnic(
                constants.INTERNAL_VNIC_NAME, constants.INTERNAL_VNIC_INDEX,
                internal_network,
                constants.INTEGRATION_EDGE_IPADDRESS,
                constants.INTEGRATION_SUBNET_NETMASK,
                type="internal")
            edge['vnics']['vnics'].append(vnic_inside)

        # If default login credentials for Edge are set, configure accordingly
        if (cfg.CONF.nsxv.edge_appliance_user and
            cfg.CONF.nsxv.edge_appliance_password):
            edge['cliSettings'].update({
                'userName': cfg.CONF.nsxv.edge_appliance_user,
                'password': cfg.CONF.nsxv.edge_appliance_password})

        if not dist and loadbalancer_enable:
            self._enable_loadbalancer(edge)

        if async:
            userdata = {
                'dist': dist,
                'request': edge,
                'router_name': name,
                'jobdata': jobdata
            }
            task = tasks.Task(task_name, resource_id,
                              self._deploy_edge,
                              status_callback=self._status_edge,
                              result_callback=self._result_edge,
                              userdata=userdata)
            task.add_executed_monitor(self.callbacks.edge_deploy_started)
            task.add_result_monitor(self.callbacks.edge_deploy_result)
            self.task_manager.add(task)

            if wait_for_exec:
                # wait until the deploy task is executed so edge_id is
                # available
                task.wait(task_constants.TaskState.EXECUTED)

            return task
        else:
            edge_id = None
            try:
                header = self.vcns.deploy_edge(edge,
                                               async=False)[0]
                edge_id = header['location'].split('/')[-1]
                LOG.debug("VCNS: deploying edge %s", edge_id)

                self.callbacks.edge_deploy_started_sync(
                    jobdata['context'], edge_id, name,
                    jobdata['router_id'], dist)

                self.callbacks.edge_deploy_result_sync(
                    jobdata['context'], edge_id, name, jobdata['router_id'],
                    dist, True)

            except exceptions.VcnsApiException:
                self.callbacks.edge_deploy_result_sync(
                    jobdata['context'], edge_id, name, jobdata['router_id'],
                    dist, False)
                with excutils.save_and_reraise_exception():
                    LOG.exception(_LE("NSXv: deploy edge failed."))