def check_router_similarity(source_client, src_router, destination_client,
                            dest_router):
    relevant_keys = {'admin_state_up', 'external_gateway_info',
                     'distributed', 'ha'}
    conflicting_keys = set()

    router_network_mapping = CONF.destination.external_network_name_map
    src_router = {k: v for k, v in src_router.items() if v is not None}
    dest_router = {k: v for k, v in dest_router.items() if v is not None}
    for k in src_router:
        if k in relevant_keys:
            if k == 'external_gateway_info':
                src_snat = src_router[k].get('enable_snat', False)
                dest_snat = dest_router.get(k, {}).get('enable_snat', False)
                src_network_id = src_router[k]['network_id']
                dest_network_id = dest_router.get(
                    k, {}).get('network_id', True)
                if src_snat == dest_snat:
                    src_net_name = networks.get_network(
                        source_client, src_network_id)['name']
                    dest_net_name = networks.get_network(
                        destination_client, dest_network_id)['name']
                    if (router_network_mapping.get(
                            src_net_name, src_net_name) == dest_net_name):
                        conflicting_keys.add(k)
            elif src_router[k] == dest_router.get(k):
                conflicting_keys.add(k)

    src_relevant_keys = set(src_router.keys()).intersection(relevant_keys)
    return conflicting_keys == src_relevant_keys
Example #2
0
    def take_action(self, args):
        # instantiate all clients:
        source_client = conf.get_source_openstack_client()
        destination_client = conf.get_destination_openstack_client()

        if args.src_network_name:
            src_network_id = networks.get_network(
                source_client, args.src_network_name)['id']
        else:
            src_network_id = args.src_network_id

        if args.dest_tenant_name:
            dest_tenant_id = destination_client.get_project_id(
                args.dest_tenant_name)
        else:
            dest_tenant_id = args.dest_tenant_id

        network_creation_payload = {
            "src_network_id": src_network_id,
            "dest_tenant_id": dest_tenant_id}

        network_creation_action = network_actions.NetworkCreationAction(
            network_creation_payload,
            source_openstack_client=source_client,
            destination_openstack_client=destination_client)

        done = network_creation_action.check_already_done()
        if done["done"]:
            LOG.info(
                "Network Migration seemingly done with Network Id '%s' ."
                % done['result'])
            dest_network = networks.get_network(
                destination_client, done['result'])
            network = {
                'destination_name': dest_network['name'],
                'destination_id': done['result'],
                'dest_tenant_name': destination_client.get_project_name(
                    dest_tenant_id),
                'dest_tenant_id': dest_tenant_id}

        else:
            if args.not_drill:
                try:
                    network = network_creation_action.execute_operations()
                except (Exception, KeyboardInterrupt):
                    LOG.warn("Error occured while recreating network with id "
                             "'%s'. Rolling back all changes.", src_network_id)
                    network_creation_action.cleanup()
                    raise
            else:
                network_creation_action.print_operations()
                network = {
                    'destination_name': 'NOT DONE',
                    'destination_id': 'NOT DONE',
                    'dest_tenant_name': destination_client.get_project_name(
                        dest_tenant_id),
                    'dest_tenant_id': dest_tenant_id}

        return NetworkMigrationFormatter().list_objects([network])
def create_router(destination_client, migr_info):
    body = migr_info['migration_body']
    src_router_name = migr_info['source_name']
    new_format = CONF.destination.new_router_name_format
    body['name'] = new_format % {
        "original": src_router_name}
    router_id = destination_client.neutron.create_router(
        {'router': body})['router']['id']

    src_ext_net_names = migr_info['src_ext_net_names']
    src_subnets = migr_info['src_subnets']

    external_network_map = CONF.destination.external_network_name_map
    if src_ext_net_names:
        dest_ext_net_names = [external_network_map.get(net_name, net_name)
                              for net_name in src_ext_net_names]

        dest_ext_net_ids = [networks.get_network(
            destination_client, net_name)['id'] for net_name in
            dest_ext_net_names]
        for net_id in dest_ext_net_ids:
            LOG.info(
                "Adding external network %s gateway to router %s"
                % (net_id, router_id))
            destination_client.neutron.add_gateway_router(
                router_id, {'network_id': net_id})

    new_net_name_format = CONF.destination.new_network_name_format
    new_subnet_name_format = CONF.destination.new_subnet_name_format

    # TODO more efficient way to determine destination subnets?
    for subnet in src_subnets:
        dest_net_name = new_net_name_format % {
            "original": subnet['network_name']}
        dest_net_id = networks.get_network(
            destination_client, dest_net_name)['id']

        dest_subnet_name = new_subnet_name_format % {
            "original": subnet['subnet_name']}

        dest_subnet_id = subnets.list_subnets(
            destination_client, filters={'network_id': dest_net_id,
                                         'name': dest_subnet_name})[0]['id']
        LOG.info("Adding interface for subnet '%s' to router '%s' "
                 % (dest_subnet_name, body['name']))
        destination_client.neutron.add_interface_router(
            router_id, body={'subnet_id': dest_subnet_id})

    return router_id
    def check_already_done(self):
        src_network = networks.get_network(
            self._source_openstack_client, self.payload['src_network_id'])

        dest_network_name = self.get_new_network_name()
        conflicting = networks.list_networks(
            self._destination_openstack_client, self.payload['dest_tenant_id'],
            filters={'name': dest_network_name})

        for dest_network in conflicting:
            if networks.check_network_similarity(
                    src_network, dest_network,
                    self._source_openstack_client,
                    self._destination_openstack_client):
                LOG.info("Found destination network '%s' with same "
                         "information and subnets as source network '%s'."
                         % (dest_network_name, src_network['name']))
                return {"done": True, "result": dest_network['id']}

        if len(conflicting) == 1:
            raise Exception("Found destination network with "
                            "with name '%s' but different attributes!"
                            % dest_network_name)
        elif conflicting:
            raise Exception("Found multiple destination networks with "
                            "with name '%s'! Aborting subnet "
                            "migration." % dest_network_name)

        return {"done": False, "result": None}
    def execute_operations(self):
        super(SubnetCreationAction, self).print_operations()
        dest_subnet_name = self.get_new_subnet_name()
        dest_network_id = self.payload['dest_network_id']
        done = self.check_already_done()
        if done["done"]:
            LOG.info(
                "Subnet named '%s' already exists.",
                dest_subnet_name)
            return done["result"]

        LOG.info("Creating destination Subnet with name '%s'" %
                 dest_subnet_name)
        description = (self.NEW_SUBNET_DESCRIPTION %
                       self.payload['source_name'])
        body = self.create_subnet_body(description)
        dest_subnet_id = subnets.create_subnet(
            self._destination_openstack_client, body)
        dest_network_name = networks.get_network(
            self._destination_openstack_client, dest_network_id)['name']
        dest_subnet = {
            'destination_name': dest_subnet_name,
            'destination_id': dest_subnet_id,
            'dest_network_id': dest_network_id,
            'dest_network_name': dest_network_name}

        return dest_subnet
    def get_destination_tenant_id(self):
        dest_network = networks.get_network(
            self._destination_openstack_client,
            self.payload['dest_network_id'])

        return (dest_network.get('tenant_id') or
                dest_network.get('project_id'))
def get_migration_info(source_client, name_or_id):
    router = get_router(source_client, name_or_id)
    relevant_keys = {'admin_state_up', 'distributed', 'ha',
                     'availability_zone_hints'}

    body = {k: v for k, v in router.items() if k in relevant_keys}
    body['availability_zone_hints'] += router['availability_zones']
    # eliminate any possible duplicates
    body['availability_zone_hints'] = list(
        set(body['availability_zone_hints']))
    ext_gateway_info = router['external_gateway_info']

    src_ext_subnet_ids = set()
    ext_network_names = []
    if ext_gateway_info:
        for fixed_ip in ext_gateway_info['external_fixed_ips']:
            src_ext_subnet_ids.add(fixed_ip['subnet_id'])
        ext_networks_ids = [subnets.get_subnet(source_client, subnet_id)[
            'network_id'] for subnet_id in src_ext_subnet_ids]
        ext_network_names = [networks.get_network(source_client, network_id)[
            'name'] for network_id in ext_networks_ids]

    # mapped with new_subnet_name_format and new_network_name_format
    src_subnet_ids = set()
    for port in source_client.neutron.list_ports(
            device_id=router['id'])['ports']:
        for fixed_ip in port['fixed_ips']:
            src_subnet_ids.add(fixed_ip['subnet_id'])

    src_subnet_ids = src_subnet_ids - src_ext_subnet_ids

    src_subnets = [subnets.get_subnet(source_client, subnet_id)
                   for subnet_id in src_subnet_ids]

    # adding both network name and subnet name the chance of a collision on
    # destination is greatly reduced
    src_subnets = [{'subnet_name': subnet['name'],
                    'network_name': networks.get_network(
                        source_client, subnet['network_id'])['name']}
                   for subnet in src_subnets]

    return {'source_name': router['name'],
            'migration_body': body,
            'src_ext_net_names': ext_network_names,
            'src_subnets': src_subnets}
    def execute_operations(self):
        super(NetworkCreationAction, self).print_operations()
        done = self.check_already_done()
        dest_network_name = self.get_new_network_name()
        if done["done"]:
            LOG.info(
                "Network named '%s' already exists.",
                dest_network_name)
            return done["result"]

        LOG.info("Creating destination Network with name '%s'" %
                 dest_network_name)

        description = (
            self.NEW_NETWORK_DESCRIPTION % self.get_source_network_name())

        body = networks.create_network_body(
            self._source_openstack_client, self.payload['src_network_id'],
            self.payload['dest_tenant_id'],
            self.get_new_network_name(), description)

        dest_network_id = networks.create_network(
            self._destination_openstack_client, body)

        src_subnet_ids = networks.get_network(
            self._source_openstack_client,
            self.payload['src_network_id'])['subnets']

        src_subnet_names = [
            subnets.get_subnet(
                self._source_openstack_client, subnet_id)['name']
            for subnet_id in src_subnet_ids]

        for name in src_subnet_names:
            subnet_migration_payload = {
                'source_name': name,
                'src_network_id': self.payload['src_network_id'],
                'dest_network_id': dest_network_id}
            subnet_migration_action = SubnetCreationAction(
                subnet_migration_payload,
                source_openstack_client=self._source_openstack_client,
                destination_openstack_client=(
                    self._destination_openstack_client))
            self.subactions.append(subnet_migration_action)
            subnet_migration_action.execute_operations()

        dest_network = {
            'destination_name': dest_network_name,
            'destination_id': dest_network_id,
            'dest_tenant_name':
                self._destination_openstack_client.connection_info[
                    'project_name'],
            'dest_tenant_id': self.payload['dest_tenant_id']}

        return dest_network
 def get_source_network_name(self):
     return networks.get_network(
         self._source_openstack_client,
         self.payload['src_network_id'])['name']
Example #10
0
    def take_action(self, args):
        # instantiate all clients:
        source_client = conf.get_source_openstack_client()
        destination_client = conf.get_destination_openstack_client()

        if args.src_network_id:
            src_network_id = args.src_network_id
            src_network_name = networks.get_network(
                source_client, args.src_network_id)['name']
        elif args.src_network_name:
            src_network_id = networks.get_network(source_client,
                                                  args.src_network_name)['id']
            src_network_name = args.src_network_name

        dest_network_name = CONF.destination.new_network_name_format % {
            "original": src_network_name
        }
        dest_network_id = networks.get_network(destination_client,
                                               dest_network_name)['id']

        subnet_creation_payload = {
            "source_name": args.subnet_name,
            "src_network_id": src_network_id,
            "dest_network_id": dest_network_id
        }

        subnet_creation_action = network_actions.SubnetCreationAction(
            subnet_creation_payload,
            source_openstack_client=source_client,
            destination_openstack_client=destination_client)

        done = subnet_creation_action.check_already_done()
        subnet = []
        if done["done"]:
            LOG.info("Subnet Migration seemingly done.")
            subnet = {
                'destination_name':
                (subnet_creation_action.get_new_subnet_name()),
                'destination_id': done['result'],
                'dest_network_id': dest_network_id,
                'dest_network_name': dest_network_name
            }

        else:
            if args.not_drill:
                try:
                    subnet = subnet_creation_action.execute_operations()
                except (Exception, KeyboardInterrupt):
                    LOG.warn(
                        "Error occured while recreating subnet '%s'."
                        "Rolling back all changes", args.subnet_name)
                    subnet_creation_action.cleanup()
                    raise
            else:
                subnet_creation_action.print_operations()
                subnet = {
                    'destination_name': 'NOT DONE',
                    'destination_id': 'NOT DONE',
                    'dest_network_id': dest_network_id,
                    'dest_network_name': dest_network_name
                }

        return SubnetMigrationFormatter().list_objects([subnet])