import os import pika from dotenv import load_dotenv from pyrabbit.api import Client load_dotenv(verbose=True) # Создание Vhost vh = os.getenv('RABBIT_VIRTUALHOST') user = os.getenv('RABBIT_USER') cl = Client(f"{os.getenv('RABBIT_HOST')}:{os.getenv('RABBIT_PORT_API')}", user, os.getenv('RABBIT_PASSWORD')) #'guest', 'guest' if vh not in cl.get_vhost_names(): cl.create_vhost(vh) cl.set_vhost_permissions(vh, user, '.*', '.*', '.*') # создаем новую очередь на vhost, которые указываем в parameters (в данном случае test) MQTT_credentials = pika.PlainCredentials(os.getenv('RABBIT_USER'), os.getenv('RABBIT_PASSWORD')) MQTT_params = pika.ConnectionParameters(os.environ.get("RABBIT_HOST"), os.environ.get('RABBIT_PORT'), os.environ.get('RABBIT_VIRTUALHOST', default='/'), credentials=MQTT_credentials) connection = pika.BlockingConnection(MQTT_params) channel = connection.channel() cnt = channel.queue_declare(queue=os.environ.get("RABBIT_QUEUE"), durable=True) # exclusive - то очередь будет разрешать подключаться только одному потребителю # x-max-priority — разрешает сортировку по приоритетам в очереди с максимальным значением приоритета 255 (RabbitMQ версий 3.5.0 и выше). Число указывает максимальный приоритет, который будет поддерживать очередь. Если аргумент не установлен, очередь не будет поддерживать приоритет сообщений
rabbitmq_url = args.rabbitmq_url rabbitmq_user = args.rabbitmq_username rabbitmq_password = args.rabbitmq_password user = args.username password = args.password vhost = args.vhostname cl = Client(rabbitmq_url, rabbitmq_user, rabbitmq_password) assert cl.is_alive() for queue in cl.get_queues(): if queue['vhost'] == vhost: cl.purge_queue(vhost, queue['name']) cl.delete_queue(vhost, queue['name']) for vhost_ in cl.get_all_vhosts(): if vhost_['name'] == vhost: while True: try: cl.delete_vhost(vhost_['name']) break except Exception: pass for user_ in cl.get_users(): if user_['name'] == user: cl.delete_user(user_['name']) cl.create_vhost(vhost) cl.create_user(user, password, tags='administrator') cl.set_vhost_permissions(vhost, user, '.*', '.*', '.*')
class AMQPManager(object): RABBITMQ_MANAGEMENT_PORT = 15672 VHOST_NAME_PATTERN = 'rabbitmq_vhost_{0}' USERNAME_PATTERN = 'rabbitmq_user_{0}' def __init__(self, host, username, password): host_str = '{0}:{1}'.format(host, self.RABBITMQ_MANAGEMENT_PORT) self._client = Client(host_str, username, password) self._storage_manager = get_storage_manager() def create_tenant_vhost_and_user(self, tenant): """ Create a new RabbitMQ vhost and user, and grant the user permissions on the vhost :param tenant: An SQLAlchemy Tenant object :return: The updated tenant object """ vhost = tenant.rabbitmq_vhost or \ self.VHOST_NAME_PATTERN.format(tenant.name) username = tenant.rabbitmq_username or \ self.USERNAME_PATTERN.format(tenant.name) password = (tenant.rabbitmq_password or AMQPManager._generate_user_password()) self._client.create_vhost(vhost) self._client.create_user(username, password) self._client.set_vhost_permissions(vhost, username, '.*', '.*', '.*') # TODO: Maybe won't be necessary in the future self._client.set_vhost_permissions('/', username, '.*', '.*', '.*') tenant.rabbitmq_vhost = vhost tenant.rabbitmq_username = username tenant.rabbitmq_password = password return tenant def sync_metadata(self): """Synchronize database tenants with rabbitmq metadata""" tenants = self._storage_manager.list(Tenant) self._clear_extra_vhosts(tenants) self._clear_extra_users(tenants) self._add_missing_vhosts_and_users(tenants) def _add_missing_vhosts_and_users(self, tenants): """Create vhosts and users present in the database""" for tenant in tenants: t = self.create_tenant_vhost_and_user(tenant) self._storage_manager.update(t) def _clear_extra_vhosts(self, tenants): """Remove vhosts in rabbitmq not present in the database""" expected_vhosts = set(tenant.rabbitmq_vhost for tenant in tenants if tenant.rabbitmq_vhost # Ignore None values ) current_vhosts = set(vhost for vhost in self._client.get_vhost_names() if vhost.startswith(self.VHOST_NAME_PATTERN[:-3])) extra_vhosts = current_vhosts - expected_vhosts for vhost in extra_vhosts: self._client.delete_vhost(vhost) def _clear_extra_users(self, tenants): """Remove users in rabbitmq not present in the database""" expected_usernames = set( tenant.rabbitmq_username for tenant in tenants if tenant.rabbitmq_username # Ignore None values ) current_usernames = set( user['name'] for user in self._client.get_users() if user['name'].startswith(self.USERNAME_PATTERN[:-3])) extra_usernames = current_usernames - expected_usernames for username in extra_usernames: self._client.delete_user(username) @staticmethod def _generate_user_password(password_length=32): """Generate random string to use as user password.""" system_random = random.SystemRandom() allowed_characters = (string.letters + string.digits + '-_') password = ''.join( system_random.choice(allowed_characters) for _ in xrange(password_length)) return password @ignore_not_found def _delete_vhost(self, vhost): self._client.delete_vhost(vhost) @ignore_not_found def _delete_user(self, username): self._client.delete_user(username) def remove_tenant_vhost_and_user(self, tenant_name): """ Delete the vhost and user associated with a tenant name """ vhost = self.VHOST_NAME_PATTERN.format(tenant_name) username = self.USERNAME_PATTERN.format(tenant_name) self._delete_vhost(vhost) self._delete_user(username)