Пример #1
0
 def test_fwg_port_list_for_tenant_no_ports(self):
     tenant_id = self.request.user.project_id
     neutronclient.list_ports(tenant_id=tenant_id).AndReturn({'ports': []})
     neutronclient.list_fwaas_firewall_groups(
         tenant_id=tenant_id).AndReturn({'firewall_groups': []})
     self.mox.ReplayAll()
     ports = api_fwaas_v2.fwg_port_list_for_tenant(self.request, tenant_id)
     self.assertEqual([], ports)
Пример #2
0
    def test_fwg_port_list_for_tenant(self):
        tenant_id = self.request.user.project_id
        router_port = {
            'id': 'id-1',
            'name': 'port-1',
            'device_owner': 'network:router_interface'
        }
        vm_port1 = {
            'id': 'id-vm_port-1',
            'name': 'port-2',
            'device_owner': 'compute:nova'
        }
        vm_port2 = {
            'id': 'id-vm_port-2',
            'name': 'port-2',
            'device_owner': 'compute:nova'
        }
        gateway_port = {
            'id': 'id-3',
            'name': 'port-3',
            'device_owner': 'network:router_gateway'
        }
        dhcp_port = {
            'id': 'id-4',
            'name': 'port-4',
            'device_owner': 'network:dhcp'
        }
        dummy_ports = {
            'ports': [
                router_port,
                vm_port1,
                vm_port2,
                gateway_port,
                dhcp_port,
            ]
        }

        neutronclient.list_ports(tenant_id=tenant_id).AndReturn(dummy_ports)
        neutronclient.list_fwaas_firewall_groups(
            tenant_id=tenant_id).AndReturn({'firewall_groups': []})
        self.mox.ReplayAll()
        ports = api_fwaas_v2.fwg_port_list_for_tenant(self.request, tenant_id)
        self.assertEqual(router_port['id'], ports[0]['id'])
        self.assertEqual(vm_port1['id'], ports[1]['id'])
        self.assertEqual(vm_port2['id'], ports[2]['id'])
Пример #3
0
 def test_fwg_port_list_for_tenant_no_match(self):
     tenant_id = self.request.user.project_id
     dummy_ports = {
         'ports': [
             {
                 'name': 'port-3',
                 'device_owner': 'network:router_gateway'
             },
             {
                 'name': 'port-4',
                 'device_owner': 'network:dhcp'
             },
         ]
     }
     neutronclient.list_ports(tenant_id=tenant_id).AndReturn(dummy_ports)
     neutronclient.list_fwaas_firewall_groups(
         tenant_id=tenant_id).AndReturn({'firewall_groups': []})
     self.mox.ReplayAll()
     ports = api_fwaas_v2.fwg_port_list_for_tenant(self.request, tenant_id)
     self.assertEqual([], ports)
class RouterPortCleanup():
    def __init__(self):
        kwargs = {}
        kwargs['username'] = os.environ.get('OS_USERNAME')
        kwargs['tenant_name'] = os.environ.get('OS_TENANT_NAME')
        kwargs['auth_url'] = os.environ.get('OS_AUTH_URL')
        #kwargs['endpoint_url'] = os.environ.get('OS_AUTH_URL')
        kwargs['auth_strategy'] = 'keystone'
        kwargs['password']= os.environ.get('OS_PASSWORD')
        self.client = NeutronClient(**kwargs)
        self.subnets = []
        self.ports = []
    
    def _check_and_delete(self, port):
        for subnet in self.subnets:
            if port['fixed_ips'][0]['subnet_id'] == subnet['id']:
                if port['fixed_ips'][0]['ip_address'] == subnet['gateway_ip']:
                    # delete this port
                    print "Found a stale port : "+ port['id']                    
                    self.client.delete_port(port['id'])
                    print "Deleted the port : " + port['id']
                    print "\n\n"
                    return

    def clean_up_ports(self):
        """ Delete the stale ports.
        These ports have
        1. Empty device_id
        2. Empty device_owner
        3. The IP address of the port will be the gateway ip of the subnet 
        """
        
        # get the subnets
        self.subnets = self.client.list_subnets()['subnets']
        print "subnets = \n"
        print self.subnets
        print "\n"
        
        self.ports = self.client.list_ports()['ports']
              
        for port in self.ports:
            print "\n**************************"
            print 'port =' + str(port)
            print "\n"
            if len(port['device_owner']) == 0 and len(port['device_id']) == 0:
                self._check_and_delete(port)
Пример #5
0
class OSClient(object):
    def __init__(self, testbed_name, testbed, tenant_name=None, project_id=None):
        self.testbed_name = testbed_name
        self.tenant_name = None
        self.project_id = None
        self.testbed = testbed
        self.project_domain_name = self.testbed.get('project_domain_name') or 'Default'
        self.user_domain_name = self.testbed.get('user_domain_name') or 'Default'
        self.api_version = self.testbed.get('api_version')
        self.username = self.testbed.get('username')
        self.password = self.testbed.get('password')
        self.auth_url = self.testbed.get("auth_url")
        if self.auth_url.endswith('/'):
            self.auth_url = self.auth_url[:-1]
        self.admin_tenant_name = self.testbed.get("admin_tenant_name")
        self.admin_project_id = self.testbed.get("admin_project_id")
        if not self.admin_tenant_name and not self.admin_project_id:
            raise OpenstackClientError("Missing both admin project id and admin tenant name")
        if self.api_version == 2 and not self.admin_tenant_name:
            raise OpenstackClientError("Missing tenant name required if using v2")
        if self.api_version == 3 and not self.admin_project_id:
            raise OpenstackClientError("Missing project id required if using v3")

        self.neutron = None
        self.nova = None
        self.glance = None
        self.keypair = None
        self.sec_group = None
        self.os_tenant_id = None

        # logger.debug("Log level is: %s and DEBUG is %s" % (logger.getEffectiveLevel(), logging.DEBUG))
        # if logger.getEffectiveLevel() == logging.DEBUG:
        #     logging.basicConfig(level=logging.DEBUG)

        if not tenant_name and not project_id:

            self.keystone = self._create_keystone_client()
            logger.debug("Created Keystone client %s" % self.keystone)
        else:
            self.tenant_name = tenant_name
            self.project_id = project_id

            if self.api_version == 2 and not self.tenant_name:
                raise OpenstackClientError("Missing tenant name required if using v2")
            if self.api_version == 3 and not self.project_id:
                raise OpenstackClientError("Missing project id required if using v3")

            logger.debug("Creating keystone client")
            if self.api_version == 3:
                self.keystone = self._create_keystone_client(project_id)
                self.os_tenant_id = project_id
            else:
                self.keystone = self._create_keystone_client(tenant_name)
                self.os_tenant_id = self.project_id = self._get_tenant_id_from_name(tenant_name)

            logger.debug("Created Keystone client %s" % self.keystone)
            self.set_nova(self.os_tenant_id)
            self.set_neutron(self.os_tenant_id)
            self.set_glance(self.os_tenant_id)

    def _create_keystone_client(self, project_id=None):
        if self.api_version == 3:
            return keystoneclient.v3.client.Client(session=self._get_session(project_id))
        elif self.api_version == 2:
            if not project_id:
                project_id = self.tenant_name or self.admin_tenant_name
            return keystoneclient.v2_0.client.Client(username=self.username,
                                                     password=self.password,
                                                     tenant_name=project_id,
                                                     auth_url=self.auth_url)

    def set_nova(self, os_tenant_id):
        self.nova = Nova('2.1', session=self._get_session(os_tenant_id))

    def _get_session(self, tenant_id=None):
        if self.api_version == 2:
            tenant_name = self.tenant_name or self.admin_tenant_name
            auth = v2.Password(auth_url=self.auth_url,
                               username=self.username,
                               password=self.password,
                               tenant_name=tenant_name)
        elif self.api_version == 3:
            p_id = tenant_id or self.project_id or self.admin_project_id
            auth = v3.Password(auth_url=self.auth_url,
                               username=self.username,
                               password=self.password,
                               project_id=p_id,
                               project_domain_name=self.project_domain_name,
                               user_domain_name=self.user_domain_name)
        else:
            msg = "Wrong api version: %s" % self.api_version
            logger.error(msg)
            raise OpenstackClientError(msg)
        return session.Session(auth=auth)

    def set_neutron(self, os_tenant_id):
        # self.os_tenant_id = os_tenant_id
        if not self.neutron:
            self.neutron = Neutron(session=self._get_session(os_tenant_id))

    def get_user(self, username=None):
        users = self.list_users()
        if username:
            un = username
        else:
            un = self.username
        for user in users:
            if user.name == un:
                return user

    def get_role(self, role_to_find):
        roles = self.list_roles()
        for role in roles:
            if role.name == role_to_find:
                return role

    def list_roles(self):
        return self.keystone.roles.list()

    def list_tenants(self):
        if self.api_version == 3:
            return self.keystone.projects.list()
        else:
            return self.keystone.tenants.list()

    def create_tenant(self, tenant_name, description):
        self.tenant_name = tenant_name
        if self.api_version == 2:
            return self.keystone.tenants.create(tenant_name=tenant_name, description=description)
        else:
            return self.keystone.projects.create(name=tenant_name, description=description,
                                                 domain=self.user_domain_name.lower())

    def add_user_role(self, user, role, tenant):
        if self.api_version == 2:
            try:
                return self.keystone.roles.add_user_role(user=user, role=role, tenant=tenant)
            except Conflict as c:
                if c.http_status == 409:  # role already assigned to user
                    return
                raise c
        else:
            return self.keystone.roles.grant(user=user, role=role, project=tenant)

    def import_keypair(self, key_file, os_tenant_id=None):
        if not self.nova and not os_tenant_id:
            raise OpenstackClientError("Both os_tenant_id and nova obj are None")
        if not self.nova:
            self.set_nova(os_tenant_id=os_tenant_id)
        keypair_name = "softfire-key"
        self.keypair = keypair_name
        for keypair in self.list_keypairs(os_tenant_id):
            if keypair.name == keypair_name:
                return keypair
        if os.path.isfile(key_file):
            with open(key_file, "r") as sosftfire_ssh_pub_key:
                kargs = {"name": keypair_name,
                         "public_key": sosftfire_ssh_pub_key.read()}
                return self.nova.keypairs.create(**kargs)
        else:
            kargs = {"name": keypair_name,
                     "public_key": key_file}
            return self.nova.keypairs.create(**kargs)

    def get_ext_net(self, ext_net_name='softfire-network'):
        return [ext_net for ext_net in self.neutron.list_networks()['networks'] if
                ext_net['router:external'] and ext_net['name'] == ext_net_name][0]

    def allocate_floating_ips(self, ext_net, fip_num=0):
        body = {
            "floatingip": {
                "floating_network_id": ext_net['id']
            }
        }
        for i in range(fip_num):
            try:
                self.neutron.create_floatingip(body=body)
            except IpAddressGenerationFailureClient as e:
                logger.error("Not able to allocate floatingips :(")
                raise OpenstackClientError("Not able to allocate floatingips :(")

    def create_networks_and_subnets(self, ext_net, router_name='ob_router'):
        networks = []
        subnets = []
        ports = []
        router_id = None
        exist_net = [network for network in self.neutron.list_networks()['networks']]
        exist_net_names = [network['name'] for network in exist_net]
        net_name_to_create = [net for net in NETWORKS if net not in exist_net_names]
        networks.extend(network for network in exist_net if network['name'] in NETWORKS)
        index = 1
        for net in net_name_to_create:
            kwargs = {'network': {
                'name': net,
                'shared': False,
                'admin_state_up': True
            }}
            logger.debug("Creating net %s" % net)
            network_ = self.neutron.create_network(body=kwargs)['network']
            networks.append(network_)
            kwargs = {
                'subnets': [
                    {
                        'name': "subnet_%s" % net,
                        'cidr': "192.%s.%s.0/24" % ((get_username_hash(self.username) % 254) + 1, index),
                        'gateway_ip': '192.%s.%s.1' % ((get_username_hash(self.username) % 254) + 1, index),
                        'ip_version': '4',
                        'enable_dhcp': True,
                        'dns_nameservers': ['8.8.8.8'],
                        'network_id': network_['id']
                    }
                ]
            }
            logger.debug("Creating subnet subnet_%s" % net)
            subnet = self.neutron.create_subnet(body=kwargs)
            subnets.append(subnet)

            router = self.get_router_from_name(router_name, ext_net)
            router_id = router['router']['id']

            body_value = {
                'subnet_id': subnet['subnets'][0]['id'],
            }
            try:
                ports.append(self.neutron.add_interface_router(router=router_id, body=body_value))
            except Exception as e:
                pass
            index += 1

        return networks, subnets, router_id

    def get_router_from_name(self, router_name, ext_net):
        for router in self.neutron.list_routers()['routers']:
            if router['name'] == router_name:
                return self.neutron.show_router(router['id'])
        request = {'router': {'name': router_name, 'admin_state_up': True}}
        router = self.neutron.create_router(request)
        body_value = {"network_id": ext_net['id']}
        self.neutron.add_gateway_router(router=router['router']['id'], body=body_value)
        return router

    def create_rule(self, sec_group, protocol):
        body = {"security_group_rule": {
            "direction": "ingress",
            "port_range_min": "1",
            "port_range_max": "65535",
            # "name": sec_group['security_group']['name'],
            "security_group_id": sec_group['security_group']['id'],
            "remote_ip_prefix": "0.0.0.0/0",
            "protocol": protocol,
        }}
        if protocol == 'icmp':
            body['security_group_rule'].pop('port_range_min', None)
            body['security_group_rule'].pop('port_range_max', None)
        try:
            self.neutron.create_security_group_rule(body=body)
        except neutronclient.common.exceptions.Conflict as e:
            logger.error("error while creating a rule: %s" % e.message)
            pass

    def create_security_group(self, project_id, sec_g_name=None):
        if not sec_g_name:
            sec_g_name = sec_group_name
        sec_group = {}
        for sg in self.list_sec_group(project_id):
            if sg['name'] == sec_g_name:
                sec_group['security_group'] = sg
                break
        if len(sec_group) == 0:
            body = dict(security_group=dict(name=sec_g_name, description="openbaton security group"),
                        project_id=project_id, tenant_id=project_id)
            sec_group = self.neutron.create_security_group(body=body)
            self.create_rule(sec_group, 'tcp')
            self.create_rule(sec_group, 'udp')
            self.create_rule(sec_group, 'icmp')
        self.sec_group = sec_group['security_group']
        return self.sec_group


    def list_sec_group(self, os_project_id):
        if not self.neutron:
            self.set_neutron(os_project_id)
        return [sec for sec in self.neutron.list_security_groups()['security_groups'] if
                (sec.get('tenant_id') is not None and sec.get('tenant_id') == os_project_id) or (
                        sec.get('project_id') is not None and sec.get('project_id') == os_project_id)]

    def get_vim_instance(self, tenant_name, username=None, password=None):
        if username:
            un = username
        else:
            un = self.username
        if password:
            pwd = password
        else:
            pwd = self.password

        logger.debug("Using tenant id: %s " % tenant_name)

        return {
            "name": "vim-instance-%s" % self.testbed_name,
            "authUrl": self.auth_url,
            "tenant": tenant_name,
            "username": un,
            "password": pwd,
            "securityGroups": [
                'default', sec_group_name
            ],
            "type": "openstack",
            "location": {
                "name": "Berlin",
                "latitude": "52.525876",
                "longitude": "13.314400"
            }
        }

    def upload_image(self, name, path, container_format="bare", disk_format="qcow2", visibility="public"):
        # image = self.glance.images.create(name=name)
        # self.glance.images.upload(image.id, open(path, 'rb'))

        with open(path, 'rb') as fimage:
            img = self.glance.images.create(name=name,
                                            # is_public="True",
                                            # public="True",
                                            visibility=visibility,
                                            disk_format=disk_format,
                                            container_format=container_format,
                                            data=path)
            # print(dir(self.glance.images))
            self.glance.images.upload(img.id, fimage)

    def list_images(self, tenant_id=None):
        if not self.nova:
            if not tenant_id:
                logger.error("Missing tenant_id!")
                raise OpenstackClientError('Missing tenant_id!')
            self.set_nova(tenant_id)
        try:
            imgs = self.nova.images.list()
            return imgs
        except:
            self.set_glance(tenant_id)
            return self.glance.images.list()

    def _get_tenant_id_from_name(self, tenant_name):
        if self.api_version == 2:
            tenants_list = self.keystone.tenants.list()
        else:
            tenants_list = self.keystone.projects.list()
        for tenant in tenants_list:
            if tenant.name == tenant_name:
                return tenant.id

    def set_glance(self, os_tenant_id):
        self.os_tenant_id = os_tenant_id
        self.glance = Glance('2', session=self._get_session(os_tenant_id))

    def _get_tenant_name_from_id(self, os_tenant_id):
        for t in self.list_tenants():
            if t.id == os_tenant_id:
                return t.name

    def create_user(self, username, password=None, tenant_id=None):
        for u in self.list_users():
            if hasattr(u, 'username'):
                u_username = u.username
            else:
                u_username = u.name
            if u_username == username:
                return u
        if not password:
            raise OpenstackClientError("Paswsord is needed to create user")
        if self.api_version == 2:
            return self.keystone.users.create(username, password, tenant_id=tenant_id)
        else:
            return self.keystone.users.create(name=username, password=password,
                                              project=self.get_project_from_id(tenant_id))

    def list_users(self):
        return self.keystone.users.list()

    def list_networks(self, project_id=None):
        if not self.neutron:
            if not project_id:
                raise OpenstackClientError("Missing project_id!")
            self.set_neutron(project_id)
        return self.neutron.list_networks(tenant_id=project_id)

    def list_subnets(self, project_id):
        if not self.neutron:
            if not project_id:
                raise OpenstackClientError("Missing project_id!")
            self.set_neutron(project_id)
        return self.neutron.list_subnets(tenant_id=project_id)

    def list_floatingips(self, project_id):
        if not self.neutron:
            if not project_id:
                raise OpenstackClientError("Missing project_id!")
            self.set_neutron(project_id)
        return self.neutron.list_floatingips(tenant_id=project_id)

    def list_routers(self, project_id):
        if not self.neutron:
            if not project_id:
                raise OpenstackClientError("Missing project_id!")
            self.set_neutron(project_id)
        return self.neutron.list_routers(tenant_id=project_id)

    def list_ports(self, project_id):
        if not self.neutron:
            if not project_id:
                raise OpenstackClientError("Missing project_id!")
            self.set_neutron(project_id)
        return self.neutron.list_ports(tenant_id=project_id)

    def list_keypairs(self, os_project_id=None):
        if not self.nova:
            if not os_project_id:
                raise OpenstackClientError("Missing project_id!")
            self.set_nova(os_project_id)
        return self.nova.keypairs.list()

    def list_domains(self):
        return self.keystone.domains.list()

    def get_project_from_id(self, tenant_id):
        for p in self.list_tenants():
            if p.id == tenant_id:
                return p
        raise OpenstackClientError("Project with id %s not found")

    def delete_user(self, username):
        try:
            self.keystone.users.delete(self.create_user(username=username))
        except:
            traceback.print_exc()
            logger.error("Not Able to delete user %s" % username)

    def delete_project(self, project_id):
        try:
            if self.api_version == 2:
                self.keystone.tenants.delete(project_id)
            else:
                self.keystone.projects.delete(project_id)
        except:
            traceback.print_exc()
            logger.error("Not Able to delete project %s" % project_id)

    def release_floating_ips(self, project_id, keep_fip_id_list=list()):
        fips = self.list_floatingips(project_id).get('floatingips')
        for fip in fips:
            if fip.get('id') in keep_fip_id_list:
                logger.debug("Not relasing floating ip: %s" % fip)
            else:
                self.neutron.delete_floatingip(fip.get('id'))

    def delete_ports(self, project_id):
        ports = self.list_ports(project_id).get('ports')
        for port in ports:
            try:
                self.neutron.delete_port(port.get('id'))
            except Exception as e:
                pass

    def remove_gateway_routers(self, project_id):
        routers = self.list_routers(project_id).get('routers')
        for router in routers:
            self.neutron.remove_gateway_router(router.get('id'))

    def remove_interface_routers(self, project_id):
        routers = self.list_routers(project_id).get('routers')
        subnets = self.list_subnets(project_id).get('subnets')
        for router in routers:
            for subnet in subnets:
                body_value = {
                    'subnet_id': subnet.get('id'),
                }
                try:
                    self.neutron.remove_interface_router(router.get('id'), body_value)
                    break
                except Exception as e:
                    pass
            else:
                logger.warning('No subnet found that is associated to router {}'.format(router.get('id')))

    def delete_routers(self, project_id):
        routers = self.list_routers(project_id).get('routers')
        for router in routers:
            self.neutron.delete_router(router.get('id'))

    def delete_networks(self, project_id):
        networks = self.list_networks(project_id).get('networks')
        for nw in networks:
            self.neutron.delete_network(nw.get('id'))

    def delete_security_groups(self, project_id):
        sec_groups = self.list_sec_group(project_id)
        for sec_group in sec_groups:
            self.neutron.delete_security_group(sec_group.get('id'))
Пример #6
0
class Server(object):
    """
    Launches an instance on a lease.
    """
    def __init__(self,
                 id=None,
                 lease=None,
                 key=None,
                 image=DEFAULT_IMAGE,
                 **kwargs):
        kwargs.setdefault("session", context.session())

        self.session = kwargs.pop("session")

        self.neutron = NeutronClient(session=self.session)
        self.nova = NovaClient("2", session=self.session)
        self.glance = GlanceClient("2", session=self.session)
        self.image = resolve_image_idname(self.glance, image)
        self.flavor = resolve_flavor(self.nova, "baremetal")

        self.ip = None
        self._fip = None
        self._fip_created = False
        self._preexisting = False

        kwargs.setdefault("_no_clean", False)
        self._noclean = kwargs.pop("_no_clean")

        net_ids = kwargs.pop("net_ids", None)
        net_name = kwargs.pop("net_name", "sharednet1")
        if net_ids is None and net_name is not None:
            net_ids = [get_networkid_byname(self.neutron, net_name)]

        if id is not None:
            self._preexisting = True
            self.server = self.nova.servers.get(id)
        elif lease is not None:
            if key is None:
                key = Keypair().key_name
            server_kwargs = instance_create_args(lease.node_reservation,
                                                 image=self.image,
                                                 flavor=self.flavor,
                                                 key=key,
                                                 net_ids=net_ids,
                                                 **kwargs)
            self.server = self.nova.servers.create(**server_kwargs)
        else:
            raise ValueError(
                "Missing required argument: 'id' or 'lease' required.")

        self.id = self.server.id
        self.name = self.server.name

    def __repr__(self):
        return "<{} '{}' ({})>".format(self.__class__.__name__, self.name,
                                       self.id)

    def __enter__(self):
        self.wait()
        return self

    def __exit__(self, exc_type, exc, exc_tb):
        if exc is not None and self._noclean:
            print("Instance existing uncleanly (noclean = True).")
            return

        self.disassociate_floating_ip()
        if not self._preexisting:
            self.delete()

    def refresh(self):
        now = datetime.now()
        try:
            lr = self._last_refresh
        except AttributeError:
            pass  # expected failure on first pass
        else:
            # limit refreshes to once/sec.
            if (now - lr).total_seconds() < 1:
                return

        self.server.get()
        self._last_refresh = now

    @property
    def status(self):
        self.refresh()
        return self.server.status

    @property
    def ready(self):
        return self.status == "ACTIVE"

    @property
    def error(self):
        return self.status == "ERROR"

    def wait(self):
        # check a couple for fast failures
        for _ in range(3):
            sleep(10)
            if self.ready:
                return
            if self.error:
                raise ServerError(self.server.fault, self.server)
        sleep(5 * 60)
        for _ in range(100):
            sleep(10)
            if self.ready:
                return
            if self.error:
                raise ServerError(self.server.fault, self.server)
        else:
            raise RuntimeError("timeout, server failed to start")
        # print('server active')

    def associate_floating_ip(self):
        if self.ip is not None:
            return self.ip

        created, self._fip = get_create_floatingip(self.neutron)
        self._fip_created = created
        self.ip = self._fip["floating_ip_address"]
        try:
            self.server.add_floating_ip(self.ip)
        except AttributeError:
            # using method from https://github.com/ChameleonCloud/horizon/blob/f5cf987633271518970b24de4439e8c1f343cad9/openstack_dashboard/api/neutron.py#L518
            ports = self.neutron.list_ports(**{
                "device_id": self.id
            }).get("ports")
            fip_target = {
                "port_id": ports[0]["id"],
                "ip_addr": ports[0]["fixed_ips"][0]["ip_address"],
            }
            # https://github.com/ChameleonCloud/horizon/blob/f5cf987633271518970b24de4439e8c1f343cad9/openstack_dashboard/dashboards/project/instances/tables.py#L671
            target_id = fip_target["port_id"]
            self.neutron.update_floatingip(
                self._fip["id"],
                body={
                    "floatingip": {
                        "port_id": target_id,
                        # 'fixed_ip_address': ip_address,
                    }
                },
            )
        return self.ip

    def disassociate_floating_ip(self):
        if self.ip is None:
            return

        self.server.remove_floating_ip(self.ip)
        if self._fip_created:
            self.neutron.delete_floatingip(self._fip["id"])

        self.ip = None
        self._fip = None
        self._fip_created = False

    def delete(self):
        self.server.delete()
        # wait for deletion complete
        for _ in range(30):
            sleep(60)
            try:
                self.server.get()
            except Exception as e:
                if "HTTP 404" in str(e):
                    return
        else:
            raise RuntimeError("timeout, server failed to terminate")

    def rebuild(self, idname):
        self.image = resolve_image_idname(self.glance, idname)
        self.server.rebuild(self.image)
Пример #7
0
class Server(object):
    """
    Launches an instance on a lease.
    """
    def __init__(self, lease, key='default', image=DEFAULT_IMAGE, **extra):
        self.lease = lease
        self.session = self.lease.session
        self.neutron = NeutronClient(
            session=self.session, region_name=os.environ.get('OS_REGION_NAME'))
        self.nova = NovaClient('2',
                               session=self.session,
                               region_name=os.environ.get('OS_REGION_NAME'))
        self.glance = GlanceClient(
            '2',
            session=self.session,
            region_name=os.environ.get('OS_REGION_NAME'))
        self.ip = None
        self._fip = None

        self.image = resolve_image_idname(self.glance, image)

        net_ids = extra.pop('net_ids', None)
        net_name = extra.pop('net_name', None)
        if net_ids is None and net_name is not None:
            net_ids = [get_networkid_byname(self.neutron, net_name)]

        self.server_kwargs = instance_create_args(self.lease.reservation,
                                                  key=key,
                                                  image=self.image,
                                                  net_ids=net_ids,
                                                  **extra)
        self.server = self.nova.servers.create(**self.server_kwargs)
        self.id = self.server.id
        self.name = self.server.name
        # print('created instance {}'.format(self.server.id))

    def __repr__(self):
        netloc = urllib.parse.urlsplit(self.session.auth.auth_url).netloc
        if netloc.endswith(':5000'):
            # drop if default port
            netloc = netloc[:-5]
        return '<{} \'{}\' on {} ({})>'.format(self.__class__.__name__,
                                               self.name, netloc, self.id)

    def refresh(self):
        now = time.monotonic()
        try:
            lr = self._last_refresh
        except AttributeError:
            pass  # expected failure on first pass
        else:
            # limit refreshes to once/sec.
            if now - lr < 1:
                return

        self.server.get()
        self._last_refresh = now

    @property
    def status(self):
        self.refresh()
        return self.server.status

    @property
    def ready(self):
        return self.status == 'ACTIVE'

    @property
    def error(self):
        return self.status == 'ERROR'

    def wait(self):
        # check a couple for fast failures
        for _ in range(3):
            time.sleep(10)
            if self.error:
                raise ServerError(self.server.fault, self.server)
        time.sleep(5 * 60)
        for _ in range(100):
            time.sleep(10)
            if self.ready:
                break
            if self.error:
                raise ServerError(self.server.fault, self.server)
        else:
            raise RuntimeError('timeout, server failed to start')
        # print('server active')

    def associate_floating_ip(self):
        created, self._fip = get_create_floatingip(self.neutron)
        self.ip = self._fip['floating_ip_address']
        try:
            self.server.add_floating_ip(self.ip)
        except AttributeError:
            # using method from https://github.com/ChameleonCloud/horizon/blob/f5cf987633271518970b24de4439e8c1f343cad9/openstack_dashboard/api/neutron.py#L518
            ports = self.neutron.list_ports(**{
                'device_id': self.id
            }).get('ports')
            fip_target = {
                'port_id': ports[0]['id'],
                'ip_addr': ports[0]['fixed_ips'][0]['ip_address']
            }
            # https://github.com/ChameleonCloud/horizon/blob/f5cf987633271518970b24de4439e8c1f343cad9/openstack_dashboard/dashboards/project/instances/tables.py#L671
            target_id = fip_target['port_id']
            self.neutron.update_floatingip(
                self._fip['id'],
                body={
                    'floatingip': {
                        'port_id': target_id,
                        # 'fixed_ip_address': ip_address,
                    }
                })
        return self.ip

    def delete(self):
        self.server.delete()
        # wait for deletion complete
        for _ in range(30):
            time.sleep(60)
            try:
                self.server.get()
            except Exception as e:
                if "HTTP 404" in str(e):
                    return
        else:
            raise RuntimeError('timeout, server failed to terminate')

    def rebuild(self, idname):
        self.image = resolve_image_idname(self.glance, idname)
        self.server.rebuild(self.image)
class StalePortCleanup():
    def __init__(self):
        kwargs = {}
        kwargs['username'] = os.environ.get('OS_USERNAME')
        kwargs['tenant_name'] = os.environ.get('OS_TENANT_NAME')
        kwargs['auth_url'] = os.environ.get('OS_AUTH_URL')
        # kwargs['endpoint_url'] = os.environ.get('OS_AUTH_URL')
        kwargs['auth_strategy'] = 'keystone'
        kwargs['password'] = os.environ.get('OS_PASSWORD')
        kwargs['endpoint_type'] = os.environ.get('OS_ENDPOINT_TYPE')
        self.client = NeutronClient(**kwargs)
        self.subnets = []
        self.stale_ports = []
        self.stale_networks = {}
        self.all_ports = []

    def get_stale_ports(self):
        self.all_ports = self.client.list_ports()['ports']
        for port in self.all_ports or []:
            try:
                if not port['fixed_ips'] or not port['fixed_ips'][0]['subnet_id']:
                    self.stale_ports.append(port)
                    if port['network_id'] not in self.stale_networks:
                        self.stale_networks[port['network_id']] = {
                            'network_id': port['network_id'],
                            'tenant_id': port['tenant_id']}
            except Exception as e:
                print("Exception occured for port : " + str(port['id']) + "\n")

    def _display_stale_port_info(self, port):
        print('Port Id = ' + str(port['id']) + '\n')
        print('This port belongs to tenant : ' + str(port['tenant_id']) + '\n')
        print('This port belongs to network : ' + str(port['network_id'] + '\n'))
        if port['fixed_ips']:
            print("This port has IP address : " + str(port['fixed_ips'][0]['ip_address']) + "\n")
        if port['device_id']:
            print("This port has device id set to : " + str(port['device_id']) + "\n")
        if port['device_owner']:
            print("This port has device owner set to : " + str(port['device_owner']) + "\n")

    def display_stale_resources(self):
        print('Total stale ports found : ' + str(len(self.stale_ports)))
        if len(self.stale_ports):
            print('Below are the stale ports which will be deleted : Please review')
            for port in self.stale_ports:
                print('**************\n')
                self._display_stale_port_info(port)
                print('**************\n\n')
        print('\n\n##################################\n\n')

        print('Total stale networks found : ' + str(len(self.stale_networks)))

        if len(self.stale_networks):
            print('Below are the stale networks')
            for net_info in self.stale_networks.itervalues():
                print('**************\n')
                print('Network Id : ' + net_info['network_id'] + '\n')
                print("This network belongs to tenant : " + net_info['tenant_id'] + "\n")
                print('**************\n')

    def delete_stale_resources(self):
        print("Deleting the stale resources")
        for port in self.stale_ports:
            print("Deleting port : " + str(port['id']) + "\n")
            try:
                self.client.delete_port(port['id'])
            except Exception as e:
                print("Exception occured in deleting port : " + str(port['id']) +"\n")
                print("Exception e = " + str(e) + "\n")

        if not self.stale_networks:
            return

        print("Deleting state networks now")
        for net_info in self.stale_networks.itervalues():
            print("Deleting Stale networks : " + net_info['network_id'] + "\n")
            try:
                self.client.delete_network(net_info['network_id'])
            except Exception as e:
                print("Exception occured in deleting network : " + str(net_info['network_id']) +"\n")
                print("Exception e = " + str(e) + "\n")