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
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']
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])