Example #1
0
 def setUp(self):
     super().setUp()
     ScanMetadataParser.parse_metadata_file = MagicMock(
         return_value=METADATA)
     self.scanner = Scanner()
     self.scanner.set_env(self.env)
     MonitoringSetupManager.create_setup = MagicMock()
     self.scanner.inv.monitoring_setup_manager = \
         MonitoringSetupManager(self.env)
Example #2
0
    def handle(self, env, values):
        router = values['payload']['router']
        host_id = values["publisher_id"].replace("network.", "", 1)
        project_id = values['_context_project_id']
        router_id = encode_router_id(router['id'])
        host = self.inv.get_by_id(env, host_id)

        fetcher = CliFetchHostVservice()
        fetcher.setup(env=env, origin=self.origin)
        router_doc = fetcher.get_vservice(host_id, router_id)
        gateway_info = router['external_gateway_info']

        if gateway_info:
            network_id = gateway_info['network_id']
            self.add_router_document(env, network_id, router_doc, host)
            self.add_children_documents(env, project_id, network_id, host,
                                        router_doc)
        else:
            self.add_router_document(env, None, router_doc, host)

        # scan links and cliques
        FindLinksForVserviceVnics().add_links(search={"parent_id": router_id})
        scanner = Scanner()
        scanner.setup(env=env, origin=self.origin)
        scanner.scan_cliques()
        self.log.info("Finished router added.")

        return EventResult(result=True,
                           related_object=router_id,
                           display_context=router_id)
Example #3
0
    def handle(self, env, notification):
        # check for network document.
        subnet = notification['payload']['subnet']
        project_id = subnet['tenant_id']
        network_id = subnet['network_id']
        if 'id' not in subnet:
            self.log.info(
                'Subnet payload doesn\'t have id, aborting subnet add')
            return EventResult(result=False, retry=False)

        network_document = self.inv.get_by_id(env, network_id)
        if not network_document:
            self.log.info(
                'network document does not exist, aborting subnet add')
            return EventResult(result=False, retry=True)
        network_name = network_document['name']

        # build subnet document for adding network
        if subnet['cidr'] not in network_document['cidrs']:
            network_document['cidrs'].append(subnet['cidr'])
        if not network_document.get('subnets'):
            network_document['subnets'] = {}

        network_document['subnets'][subnet['name']] = subnet
        if subnet['id'] not in network_document['subnet_ids']:
            network_document['subnet_ids'].append(subnet['id'])
        self.inv.set(network_document)

        # Check DHCP enable, if true, scan network.
        if subnet['enable_dhcp'] is True:
            # update network
            if not ApiAccess.regions:
                fetcher = ApiFetchRegions()
                fetcher.set_env(env)
                fetcher.get(project_id)

            self.log.info("add new subnet.")
            host_id = notification["publisher_id"].replace("network.", "", 1)
            self.add_children_documents(env, project_id, network_id,
                                        network_name, host_id)

        # scan links and cliques
        self.log.info("scanning for links")
        FindLinksForPnics().add_links()
        FindLinksForVserviceVnics().add_links(
            search={"parent_id": "qdhcp-%s-vnics" % network_id})

        scanner = Scanner()
        scanner.set_env(env)
        scanner.scan_cliques()
        self.log.info("Finished subnet added.")
        return EventResult(result=True,
                           related_object=subnet['id'],
                           display_context=network_id)
Example #4
0
    def handle(self, env, notification):
        project = notification['_context_project_name']
        project_id = notification['_context_project_id']
        payload = notification['payload']
        port = payload['port']
        network_id = port['network_id']
        network_name = self.get_name_by_id(network_id)
        mac_address = port['mac_address']

        # check ports folder document.
        ports_folder = self.inv.get_by_id(env, network_id + '-ports')
        if not ports_folder:
            self.log.info("ports folder not found, add ports folder first.")
            self.add_ports_folder(env, project_id, network_id, network_name)
        self.add_port_document(env, project, project_id, network_name,
                               network_id, port)

        # update the port related documents.
        if 'compute' in port['device_owner']:
            # update the instance related document.
            host_id = port['binding:host_id']
            instance_id = port['device_id']
            old_instance_doc = self.inv.get_by_id(env, instance_id)
            instances_root_id = host_id + '-instances'
            instances_root = self.inv.get_by_id(env, instances_root_id)
            if not instances_root:
                self.log.info(
                    'instance document not found, aborting port adding')
                return EventResult(result=False, retry=True)

            # update instance
            instance_fetcher = ApiFetchHostInstances()
            instance_fetcher.setup(env=env, origin=self.origin)
            instance_docs = instance_fetcher.get(host_id + '-')
            instance = next(
                filter(lambda i: i['id'] == instance_id, instance_docs), None)

            if instance:
                old_instance_doc['network_info'] = instance['network_info']
                old_instance_doc['network'] = instance['network']
                if old_instance_doc.get('mac_address') is None:
                    old_instance_doc['mac_address'] = mac_address

                self.inv.set(old_instance_doc)
                self.log.info("update instance document")

            # add vnic document.
            if port['binding:vif_type'] == 'vpp':
                vnic_fetcher = CliFetchInstanceVnicsVpp()
            else:
                # set ovs as default type.
                vnic_fetcher = CliFetchInstanceVnics()

            vnic_fetcher.setup(env=env, origin=self.origin)
            vnic_docs = vnic_fetcher.get(instance_id + '-')
            vnic = next(
                filter(lambda vnic: vnic['mac_address'] == mac_address,
                       vnic_docs), None)

            if vnic:
                vnic['environment'] = env
                vnic['type'] = 'vnic'
                vnic['name_path'] = old_instance_doc[
                    'name_path'] + '/vNICs/' + vnic['name']
                vnic['id_path'] = '{}/{}/{}'.format(
                    old_instance_doc['id_path'], old_instance_doc['id'],
                    vnic['name'])
                self.inv.set(vnic)
                self.log.info(
                    "add instance-vnic document, mac_address: {}".format(
                        mac_address))

            self.log.info("scanning for links")
            fetchers_implementing_add_links = [
                FindLinksForInstanceVnics(),
                FindLinksForVedges()
            ]
            for fetcher in fetchers_implementing_add_links:
                fetcher.add_links()
            scanner = Scanner()
            scanner.setup(env=env, origin=self.origin)
            scanner.scan_cliques()

        port_document = self.inv.get_by_id(env, port['id'])
        if not port_document:
            self.log.error("Port {} failed to add".format(port['id']))
            return EventResult(result=False, retry=True)

        return EventResult(result=True,
                           related_object=port['id'],
                           display_context=network_id)
Example #5
0
    def run(self, args: dict = None):
        args = setup_args(args, self.DEFAULTS, self.get_args)
        # After this setup we assume args dictionary has all keys
        # defined in self.DEFAULTS
        self.log.set_loglevel(args['loglevel'])

        try:
            MongoAccess.set_config_file(args['mongo_config'])
            self.inv = InventoryMgr()
            self.inv.log.set_loglevel(args['loglevel'])
            self.inv.set_collections(args['inventory'])
            self.conf = Configuration()
        except FileNotFoundError as e:
            return False, 'Mongo configuration file not found: {}'\
                .format(str(e))

        scan_plan = self.get_scan_plan(args)
        if scan_plan.clear or scan_plan.clear_all:
            self.inv.clear(scan_plan)
        self.conf.log.set_loglevel(scan_plan.loglevel)

        env_name = scan_plan.env
        self.conf.use_env(env_name)

        # generate ScanObject Class and instance.
        scanner = Scanner()
        scanner.log.set_loglevel(args['loglevel'])
        scanner.set_env(env_name)
        scanner.found_errors[env_name] = False

        # decide what scanning operations to do
        inventory_only = scan_plan.inventory_only
        links_only = scan_plan.links_only
        cliques_only = scan_plan.cliques_only
        monitoring_setup_only = scan_plan.monitoring_setup_only
        run_all = False if inventory_only or links_only or cliques_only \
            or monitoring_setup_only else True

        # setup monitoring server
        monitoring = \
            self.inv.is_feature_supported(env_name,
                                          EnvironmentFeatures.MONITORING)
        if monitoring:
            self.inv.monitoring_setup_manager = \
                MonitoringSetupManager(env_name)
            self.inv.monitoring_setup_manager.server_setup()

        # do the actual scanning
        try:
            if inventory_only or run_all:
                scanner.run_scan(scan_plan.scanner_type, scan_plan.obj,
                                 scan_plan.id_field, scan_plan.child_id,
                                 scan_plan.child_type)
            if links_only or run_all:
                scanner.scan_links()
            if cliques_only or run_all:
                scanner.scan_cliques()
            if monitoring:
                if monitoring_setup_only:
                    self.inv.monitoring_setup_manager.simulate_track_changes()
                if not (inventory_only or links_only or cliques_only):
                    scanner.deploy_monitoring_setup()
        except ScanError as e:
            return False, "scan error: " + str(e)
        SshConnection.disconnect_all()
        status = 'ok' if not scanner.found_errors.get(env_name, False) \
            else 'errors detected'
        if status == 'ok' and scan_plan.object_type == "environment":
            self.mark_env_scanned(scan_plan.env)
        self.log.info('Scan completed, status: {}'.format(status))
        return True, status
Example #6
0
    def handle(self, env, values):
        # find the host, to serve as parent
        instance_id = values['payload']['instance_id']
        host_id = values['payload']['host']
        instances_root_id = host_id + '-instances'
        instances_root = self.inv.get_by_id(env, instances_root_id)
        if not instances_root:
            self.log.info('instances root not found, aborting instance add')
            return EventResult(result=False, retry=True)

        # scan instance
        scanner = Scanner()
        scanner.set_env(env)
        scanner.scan("ScanInstancesRoot",
                     instances_root,
                     limit_to_child_id=instance_id,
                     limit_to_child_type='instance')
        scanner.scan_from_queue()

        # scan host
        host = self.inv.get_by_id(env, host_id)
        scanner.scan(
            'ScanHost',
            host,
            limit_to_child_type=['vconnectors_folder', 'vedges_folder'])
        scanner.scan_from_queue()
        scanner.scan_links()
        scanner.scan_cliques()

        return EventResult(result=True,
                           related_object=instance_id,
                           display_context=instance_id)
Example #7
0
    def handle(self, env, values):
        interface = values['payload']['router_interface']
        project_id = values['_context_project_id']
        project = values['_context_project_name']
        host_id = values["publisher_id"].replace("network.", "", 1)
        port_id = interface['port_id']
        subnet_id = interface['subnet_id']
        router_id = encode_router_id(interface['id'])

        network_document = self.inv.get_by_field(env,
                                                 "network",
                                                 "subnet_ids",
                                                 subnet_id,
                                                 get_single=True)
        if not network_document:
            self.log.info(
                "network document not found, aborting interface adding")
            return EventResult(result=False, retry=True)
        network_name = network_document['name']
        network_id = network_document['id']

        # add router-interface port document.
        if not ApiAccess.regions:
            fetcher = ApiFetchRegions()
            fetcher.setup(env=env, origin=self.origin)
            fetcher.get(project_id)
        port_doc = EventSubnetAdd().add_port_document(
            env, port_id, network_name=network_name)

        mac_address = port_doc['mac_address'] if port_doc else None

        # add vnic document
        host = self.inv.get_by_id(env, host_id)
        router_doc = self.inv.get_by_id(env, router_id)

        add_vnic_document = partial(EventPortAdd().add_vnic_document,
                                    env=env,
                                    host=host,
                                    object_id=interface['id'],
                                    object_type='router',
                                    network_name=network_name,
                                    router_name=router_doc['name'],
                                    mac_address=mac_address)

        ret = add_vnic_document()
        if ret is False:
            # try it again to fetch vnic document, vnic will be created a little bit late before CLI fetch.
            time.sleep(self.delay)
            self.log.info(
                "Wait {} seconds, and then fetch vnic document again.".format(
                    self.delay))
            add_vnic_document()

        # update the router document: gw_port_id, network.
        self.update_router(env, project, network_id, network_name, router_doc,
                           host_id)

        # update vservice-vnic, vnic-network,
        FindLinksForVserviceVnics().add_links(search={"parent_id": router_id})
        scanner = Scanner()
        scanner.setup(env=env, origin=self.origin)

        scanner.scan_cliques()
        self.log.info("Finished router-interface added.")

        return EventResult(result=True,
                           related_object=interface['id'],
                           display_context=network_id)
Example #8
0
    def handle(self, env, notification):
        # check for network document.
        subnet = notification['payload']['subnet']
        project_id = notification['_context_project_id']
        project = notification['_context_project_name']
        host_id = notification['publisher_id'].replace('network.', '', 1)
        subnet_id = subnet['id']
        network_id = subnet['network_id']
        network_document = self.inv.get_by_id(env, network_id)
        if not network_document:
            self.log.info(
                'network document does not exist, aborting subnet update')
            return EventResult(result=False, retry=True)

        # update network document.
        subnets = network_document['subnets']
        key = next(filter(lambda k: subnets[k]['id'] == subnet_id, subnets),
                   None)

        if key:
            if subnet['enable_dhcp'] and subnets[key]['enable_dhcp'] is False:
                # scan DHCP namespace to add related document.
                # add dhcp vservice document.
                host = self.inv.get_by_id(env, host_id)
                port_handler = EventPortAdd()
                port_handler.add_dhcp_document(env, host, network_id,
                                               network_document['name'])

                # make sure that self.regions is not empty.
                if not ApiAccess.regions:
                    fetcher = ApiFetchRegions()
                    fetcher.setup(env=env, origin=self.origin)
                    fetcher.get(project_id)

                self.log.info("add port binding to DHCP server.")
                port_id = DbFetchPort(). \
                    get_id_by_field(network_id,
                                    """device_owner LIKE "%dhcp" """)
                port = EventSubnetAdd(). \
                    add_port_document(env, port_id,
                                      network_name=network_document['name'],
                                      project_name=project)
                if port:
                    port_handler. \
                        add_vnic_document(env, host, network_id,
                                          network_name=network_document['name'],
                                          mac_address=port['mac_address'])
                    # add link for vservice - vnic
                    FindLinksForVserviceVnics().add_links(
                        search={"id": "qdhcp-%s" % network_id})
                    scanner = Scanner()
                    scanner.setup(env=env, origin=self.origin)
                    scanner.scan_cliques()
                    FindLinksForVserviceVnics(). \
                        add_links(search={"id": "qdhcp-%s" % network_id})
                    scanner = Scanner()
                    scanner.setup(env=env, origin=self.origin)
                    scanner.scan_cliques()

            if subnet['enable_dhcp'] is False and subnets[key]['enable_dhcp']:
                # delete existed related DHCP documents.
                self.inv.delete("inventory",
                                {'id': "qdhcp-%s" % subnet['network_id']})
                self.log.info("delete DHCP document: qdhcp-%s" %
                              subnet['network_id'])

                port = self.inv.find_items(
                    {
                        'network_id': subnet['network_id'],
                        'device_owner': 'network:dhcp'
                    },
                    get_single=True)
                if 'id' in port:
                    EventPortDelete().delete_port(env, port['id'])
                    self.log.info("delete port binding to DHCP server.")

            if subnet['name'] == subnets[key]['name']:
                subnets[key] = subnet
            else:
                del subnets[key]
                subnets[subnet['name']] = subnet

            self.inv.set(network_document)
            return EventResult(result=True,
                               related_object=subnet['id'],
                               display_context=network_id)
        else:
            self.log.info('subnet not in network, aborting subnet update')
            return EventResult(result=False, retry=False)
Example #9
0
class TestScanner(TestScan):
    def setUp(self):
        super().setUp()
        ScanMetadataParser.parse_metadata_file = \
            MagicMock(return_value=METADATA)
        FindLinksMetadataParser.parse_metadata_file = \
            MagicMock(return_value=LINK_FINDERS_METADATA)
        self.scanner = Scanner()
        self.scanner.set_env(self.env)
        MonitoringSetupManager.create_setup = MagicMock()
        self.scanner.inv.monitoring_setup_manager = \
            MonitoringSetupManager(self.env)

    def test_check_type_env_without_environment_condition(self):
        result = self.scanner.check_type_env(TYPE_TO_FETCH_WITHOUT_ENV_CON)

        self.assertEqual(
            result, True, "Can't get true when the type_to_fetch " +
            "doesn't contain environment condition")

    def test_check_type_with_error_value(self):
        # store original method
        original_get_env_config = self.scanner.config.get_env_config

        # mock get_env_config method
        self.scanner.config.get_env_config =\
            MagicMock(return_value=CONFIGURATIONS)

        result = self.scanner.check_type_env(TYPE_TO_FETCH_WITH_ERROR_VALUE)

        # reset get_env_config method
        self.scanner.config.get_env_config = original_get_env_config

        self.assertEqual(
            result, False,
            "Can't get false when the type_to_fetch " + "contain error value")

    def test_check_type_env_without_mechanism_drivers_in_env_config(self):
        # store original method
        original_get_env_config = self.scanner.config.get_env_config

        # mock get_env_config_method
        self.scanner.config.get_env_config =\
            MagicMock(return_value=CONFIGURATIONS_WITHOUT_MECHANISM_DRIVERS)

        result = self.scanner.check_type_env(TYPE_TO_FETCH)
        # reset get_env_config method
        self.scanner.check_type_env = original_get_env_config

        self.assertEqual(
            result, False, "Can't get false when configuration " +
            "doesn't contain mechanism drivers")

    def test_check_type_env_with_wrong_mech_drivers_in_env_condition(self):
        # store original method
        original_get_env_config = self.scanner.config.get_env_config

        # mock get_env_config_method
        self.scanner.config.get_env_config =\
            MagicMock(return_value=CONFIGURATIONS)

        result = self.scanner.\
            check_type_env(TYPE_TO_FETCH_WITH_WRONG_ENVIRONMENT_CONDITION)
        # reset get_env_config method
        self.scanner.check_type_env = original_get_env_config

        self.assertEqual(
            result, False, "Can't get false when the mechanism " +
            "drivers in type_to_fetch " + "don't exist in configurations")

    def test_check_type_env(self):
        # store original method
        original_get_env_config = self.scanner.config.get_env_config

        # mock method
        self.scanner.config.get_env_config =\
            MagicMock(return_value=CONFIGURATIONS)

        result = self.scanner.check_type_env(TYPE_TO_FETCH)

        # reset method
        self.scanner.config.get_env_config = original_get_env_config

        self.assertEqual(result, True,
                         "Can't get True when the type_to_fetch is correct")

    def test_scan_error_type(self):
        # store original method
        original_check_type_env = self.scanner.check_type_env

        # mock method
        self.scanner.check_type_env = MagicMock(return_value=False)

        result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT,
                                        ID_FIELD)

        # reset method
        self.scanner.check_type_env = original_check_type_env

        self.assertEqual(result, [],
                         "Can't get [], when the type_to_fetch is wrong")

    def test_scan_type_without_parent_id(self):
        try:
            self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT,
                                   PARENT_WITHOUT_ID, ID_FIELD)
            self.fail("Can't get error when the parent " +
                      "doesn't contain id attribute")
        except:
            pass

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_with_get_exception(self, fetcher_get):
        fetcher_get.side_effect = Exception("get exception")

        try:
            self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT,
                                   ID_FIELD)
            self.fail(
                "Can't get exception when fetcher.get throws an exception")
        except:
            pass

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_without_master_parent(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITHOUT_MASTER_PARENT_IN_DB

        # store original get_by_id
        original_get_by_id = self.scanner.inv.get_by_id
        original_set = self.scanner.inv.set

        # mock methods
        self.scanner.inv.get_by_id = MagicMock(return_value=[])

        result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT,
                                        ID_FIELD)

        # reset methods
        self.scanner.inv.get_by_id = original_get_by_id
        self.scanner.inv.set = original_set
        self.assertEqual(
            result, [], "Can't get [], when the master parent " +
            "doesn't exist in database")

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_with_master_parent(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITH_MASTER_PARENT_IN_DB

        # store original methods
        original_get_by_id = self.scanner.inv.get_by_id
        original_set = self.scanner.inv.set

        # mock methods
        self.scanner.inv.get_by_id = MagicMock(return_value=MASTER_PARENT)
        self.scanner.inv.set = MagicMock()

        self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)
        self.assertEqual(self.scanner.inv.set.call_count, 2,
                         "Can't create additional folder")
        self.assertNotIn("master_parent_type",
                         DB_RESULTS_WITH_MASTER_PARENT_IN_DB,
                         "Can't delete the master_parent_type")
        self.assertNotIn("master_parent_id",
                         DB_RESULTS_WITH_MASTER_PARENT_IN_DB,
                         "Can't delete the master_parent_id")

        # reset methods
        self.scanner.inv.get_by_id = original_get_by_id
        self.scanner.inv.set = original_set

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_with_in_project(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITH_PROJECT

        # store original method
        original_set = self.scanner.inv.set
        original_get_by_id = self.scanner.inv.get_by_id

        # mock method
        self.scanner.inv.set = MagicMock()
        self.scanner.inv.get_by_id = MagicMock(return_value=PARENT)

        self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)
        self.assertIn("projects", DB_RESULTS_WITH_PROJECT[0],
                      "Can't get the projects from DB result")
        self.assertNotIn(PROJECT_KEY, DB_RESULTS_WITH_PROJECT[0],
                         "Can't delete the project key in the object")

        self.scanner.inv.set = original_set
        self.scanner.inv.get_by_id = original_get_by_id

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_without_create_object(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITHOUT_CREATE_OBJECT

        original_set = self.scanner.inv.set
        original_get_by_id = self.scanner.inv.get_by_id

        self.scanner.inv.set = MagicMock()
        self.scanner.inv.get_by_id = MagicMock(return_value=PARENT)
        self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)

        self.assertEqual(self.scanner.inv.set.call_count, 0,
                         "Set the object when the create object is false")

        self.scanner.inv.set = original_set
        self.scanner.inv.get_by_id = original_get_by_id

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_with_create_object(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT

        original_set = self.scanner.inv.set
        original_get_by_id = self.scanner.inv.get_by_id

        self.scanner.inv.set = MagicMock()
        self.scanner.inv.get_by_id = MagicMock(return_value=PARENT)

        self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)

        self.assertEqual(self.scanner.inv.set.call_count, 1,
                         "Set the object when the create object is false")

        self.scanner.inv.set = original_set
        self.scanner.inv.get_by_id = original_get_by_id

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_with_children_scanner(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT

        original_set = self.scanner.inv.set
        original_get_by_id = self.scanner.inv.get_by_id
        original_queue_for_scan = self.scanner.queue_for_scan

        self.scanner.inv.set = MagicMock()
        self.scanner.inv.get_by_id = MagicMock(return_value=PARENT)
        self.scanner.queue_for_scan = MagicMock()

        self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)

        self.assertEqual(self.scanner.queue_for_scan.call_count, 1,
                         "Can't put children scanner in the queue")

        self.scanner.inv.set = original_set
        self.scanner.inv.get_by_id = original_get_by_id
        self.scanner.queue_for_scan = original_queue_for_scan

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type_without_children_scanner(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT

        original_set = self.scanner.inv.set
        original_get_by_id = self.scanner.inv.get_by_id
        original_queue_for_scan = self.scanner.queue_for_scan

        self.scanner.inv.set = MagicMock()
        self.scanner.inv.get_by_id = MagicMock(return_value=PARENT)
        self.scanner.queue_for_scan = MagicMock()

        self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENV_WITHOUT_CHILDREN_FETCHER,
                               PARENT, ID_FIELD)

        self.assertEqual(self.scanner.queue_for_scan.call_count, 0,
                         "Can't put children scanner in the queue")

        self.scanner.inv.set = original_set
        self.scanner.inv.get_by_id = original_get_by_id
        self.scanner.queue_for_scan = original_queue_for_scan

    @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
    def test_scan_type(self, fetcher_get):
        fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT

        original_set = self.scanner.inv.set
        original_get_by_id = self.scanner.inv.get_by_id
        original_queue_for_scan = self.scanner.queue_for_scan

        self.scanner.inv.set = MagicMock()
        self.scanner.inv.get_by_id = MagicMock(return_value=PARENT)
        self.scanner.queue_for_scan = MagicMock()

        result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT,
                                        ID_FIELD)

        self.assertNotEqual(result, [], "Can't get children form scan_type")

        self.scanner.inv.set = original_set
        self.scanner.inv.get_by_id = original_get_by_id
        self.scanner.queue_for_scan = original_queue_for_scan

    def test_scan_with_limit_to_child_type(self):
        original_scan_type = self.scanner.scan_type
        original_get_scanner = self.scanner.get_scanner

        self.scanner.scan_type = MagicMock(return_value=[])
        self.scanner.get_scanner = MagicMock(return_value=TYPES_TO_FETCH)

        limit_to_child_type = TYPES_TO_FETCH[0]['type']

        self.scanner.scan(SCANNER_TYPE_FOR_ENV,
                          PARENT,
                          limit_to_child_type=limit_to_child_type)

        # only scan the limit child type
        self.scanner.scan_type.assert_called_with(TYPES_TO_FETCH[0], PARENT,
                                                  ID_FIELD)

        self.scanner.scan_type = original_scan_type
        self.scanner.get_scanner = original_get_scanner

    def test_scan_with_limit_to_child_id(self):
        original_scan_type = self.scanner.scan_type
        original_get_scanner = self.scanner.get_scanner

        self.scanner.get_scanner = MagicMock(return_value=TYPES_TO_FETCH)
        limit_to_child_id = SCAN_TYPE_RESULTS[0][ID_FIELD]

        self.scanner.scan_type = MagicMock(return_value=SCAN_TYPE_RESULTS)

        children = self.scanner.scan(SCANNER_TYPE_FOR_ENV,
                                     PARENT,
                                     id_field=ID_FIELD,
                                     limit_to_child_id=limit_to_child_id)

        # only get the limit child
        self.assertEqual(children, SCAN_TYPE_RESULTS[0])

        self.scanner.scan_type = original_scan_type
        self.scanner.get_scanner = original_get_scanner

    def test_scan(self):
        original_scan_type = self.scanner.scan_type
        original_get_scanner = self.scanner.get_scanner

        self.scanner.get_scanner = MagicMock(return_values=TYPES_TO_FETCH)
        result = self.scanner.scan(SCANNER_TYPE_FOR_ENV, PARENT)

        self.assertEqual(PARENT, result,
                         "Can't get the original parent after the scan")

        self.scanner.get_scanner = original_get_scanner
        self.scanner.scan_type = original_scan_type

    def test_run_scan(self):
        original_scan = self.scanner.scan
        original_scan_from_queue = self.scanner.scan_from_queue

        self.scanner.scan = MagicMock()
        self.scanner.scan_from_queue = MagicMock()

        self.scanner.run_scan(SCANNER_TYPE_FOR_ENV, PARENT, ID_FIELD,
                              LIMIT_TO_CHILD_ID, LIMIT_TO_CHILD_TYPE)

        self.scanner.scan.assert_called_with(SCANNER_TYPE_FOR_ENV, PARENT,
                                             ID_FIELD, LIMIT_TO_CHILD_ID,
                                             LIMIT_TO_CHILD_TYPE)
        self.scanner.scan_from_queue.assert_any_call()

        self.scanner.scan = original_scan
        self.scanner.scan_from_queue = original_scan_from_queue

    @patch("discover.scanner.Scanner.scan")
    def test_scan_from_queue(self, scan):
        scan.return_value = []
        Scanner.scan_queue = SCAN_QUEUE

        self.scanner.scan_from_queue()

        self.assertEqual(self.scanner.scan.call_count, QUEUE_SIZE,
                         "Can't scan all the objects in the queue")
Example #10
0
    def handle(self, env, values):
        payload = values['payload']
        router = payload['router']

        project_id = values['_context_project_id']
        host_id = values["publisher_id"].replace("network.", "", 1)
        router_id = payload['id'] if 'id' in payload else router['id']

        router_full_id = encode_router_id(router_id)
        router_doc = self.inv.get_by_id(env, router_full_id)
        if not router_doc:
            self.log.info(
                "Router document not found, aborting router updating")
            return EventResult(result=False, retry=True)

        router_doc['admin_state_up'] = router['admin_state_up']
        router_doc['name'] = router['name']
        gateway_info = router.get('external_gateway_info')
        if gateway_info is None:
            # when delete gateway, need to delete the port relate document.
            port_doc = {}
            if router_doc.get('gw_port_id'):
                port_doc = self.inv.get_by_id(env, router_doc['gw_port_id'])
                EventPortDelete().delete_port(env, router_doc['gw_port_id'])

            if router_doc.get('network'):
                if port_doc:
                    router_doc['network'].remove(port_doc['network_id'])
                router_doc['gw_port_id'] = None

                # remove related links
                self.inv.delete('links', {'source_id': router_full_id})
        else:
            if 'network' in router_doc:
                if gateway_info['network_id'] not in router_doc['network']:
                    router_doc['network'].append(gateway_info['network_id'])
            else:
                router_doc['network'] = [gateway_info['network_id']]
            # update static route
            router_doc['routes'] = router['routes']

            # add gw_port_id info and port document.
            fetcher = CliFetchHostVservice()
            fetcher.setup(env=env, origin=self.origin)
            router_vservice = fetcher.get_vservice(host_id, router_full_id)
            if router_vservice.get('gw_port_id'):
                router_doc['gw_port_id'] = router_vservice['gw_port_id']

            host = self.inv.get_by_id(env, host_id)
            EventRouterAdd().add_children_documents(env, project_id,
                                                    gateway_info['network_id'],
                                                    host, router_doc)

            # rescan the vnic links.
            FindLinksForVserviceVnics().add_links(
                search={'parent_id': router_full_id + '-vnics'})
        self.inv.set(router_doc)

        # update the cliques.
        scanner = Scanner()
        scanner.setup(env=env, origin=self.origin)
        scanner.scan_cliques()
        self.log.info("Finished router update.")
        return EventResult(result=True,
                           related_object=router_full_id,
                           display_context=router_full_id)