def _get_amqp_client(agent): delete_cert_path = False if agent.get('broker_config'): broker_config = agent['broker_config'] ssl_cert_path = _get_ssl_cert_path(broker_config) # Using a temp path, so we need to delete it delete_cert_path = True else: broker_config = _get_broker_config(agent) ssl_cert_path = get_local_rest_certificate() tenant = get_tenant() try: yield amqp_client.get_client( amqp_host=broker_config.get('broker_ip'), amqp_user=tenant.get('rabbitmq_username'), amqp_port=broker_config.get('broker_port'), amqp_pass=tenant.get('rabbitmq_password'), amqp_vhost=tenant.get('rabbitmq_vhost'), ssl_enabled=broker_config.get('broker_ssl_enabled'), ssl_cert_path=ssl_cert_path ) finally: if delete_cert_path and ssl_cert_path: os.remove(ssl_cert_path)
def start(cloudify_agent, **_): """ Only called in "init_script"/"plugin" mode, where the agent is started externally (e.g. userdata script), and all we have to do is wait for it """ update_agent_record(cloudify_agent, AgentState.STARTING) tenant = cloudify_utils.get_tenant() client = get_client( amqp_user=tenant['rabbitmq_username'], amqp_pass=tenant['rabbitmq_password'], amqp_vhost=tenant['rabbitmq_vhost'] ) agent_alive = utils.is_agent_alive(cloudify_agent['queue'], client) if not agent_alive: if ctx.operation.retry_number > 3: ctx.logger.warning('Waiting too long for Agent to start') update_agent_record(cloudify_agent, AgentState.NONRESPONSIVE) return ctx.operation.retry( message='Waiting for Agent to start...') ctx.logger.info('Agent has started') update_agent_record(cloudify_agent, AgentState.STARTED) if not cloudify_agent.is_provided: script.cleanup_scripts()
def restart(new_name=None, delay_period=5, **_): cloudify_agent = ctx.instance.runtime_properties['cloudify_agent'] if new_name is None: new_name = utils.internal.generate_new_agent_name( cloudify_agent.get('name', 'agent')) # update agent name in runtime properties so that the workflow will # what the name of the worker handling tasks to this instance. # the update cannot be done by setting a nested property directly # because they are not recognized as 'dirty' cloudify_agent['name'] = new_name update_agent_runtime_properties(cloudify_agent) daemon = _load_daemon(logger=ctx.logger) # make the current master stop listening to the current queue # to avoid a situation where we have two masters listening on the # same queue. rest_tenant = get_tenant() app = get_celery_app(tenant=rest_tenant) app.control.cancel_consumer( queue=daemon.queue, destination=['celery@{0}'.format(daemon.name)] ) # clone the current daemon to preserve all the attributes attributes = utils.internal.daemon_to_dict(daemon) # give the new daemon the new name attributes['name'] = new_name # remove the log file and pid file so that new ones will be created # for the new agent del attributes['log_file'] del attributes['pid_file'] # Get the broker credentials for the daemon attributes.update(ctx.bootstrap_context.broker_config()) new_daemon = DaemonFactory().new(logger=ctx.logger, **attributes) # create the new daemon new_daemon.create() _save_daemon(new_daemon) # configure the new daemon new_daemon.configure() new_daemon.start() # start a thread that will kill the current master. # this is done in a thread so that the current task will not result in # a failure thread = threading.Thread(target=shutdown_current_master, args=[delay_period, ctx.logger]) thread.daemon = True thread.start()
def tenant(self): """Full Cloudify tenant. This will go out to the REST API and fetch all the tenant details that the current user is allowed to obtain. """ if self._tenant is None: self._tenant = self._context.get('tenant', {}).copy() self._tenant.update(utils.get_tenant()) return self._tenant
def restart(new_name=None, delay_period=5, **_): cloudify_agent = ctx.instance.runtime_properties['cloudify_agent'] if new_name is None: new_name = utils.internal.generate_new_agent_name( cloudify_agent.get('name', 'agent')) # update agent name in runtime properties so that the workflow will # what the name of the worker handling tasks to this instance. # the update cannot be done by setting a nested property directly # because they are not recognized as 'dirty' cloudify_agent['name'] = new_name update_agent_runtime_properties(cloudify_agent) daemon = _load_daemon(logger=ctx.logger) # make the current master stop listening to the current queue # to avoid a situation where we have two masters listening on the # same queue. rest_tenant = get_tenant() app = get_celery_app(tenant=rest_tenant) app.control.cancel_consumer(queue=daemon.queue, destination=['celery@{0}'.format(daemon.name)]) # clone the current daemon to preserve all the attributes attributes = utils.internal.daemon_to_dict(daemon) # give the new daemon the new name attributes['name'] = new_name # remove the log file and pid file so that new ones will be created # for the new agent del attributes['log_file'] del attributes['pid_file'] # Get the broker credentials for the daemon attributes.update(ctx.bootstrap_context.broker_config()) new_daemon = DaemonFactory().new(logger=ctx.logger, **attributes) # create the new daemon new_daemon.create() _save_daemon(new_daemon) # configure the new daemon new_daemon.configure() new_daemon.start() # start a thread that will kill the current master. # this is done in a thread so that the current task will not result in # a failure thread = threading.Thread(target=shutdown_current_master, args=[delay_period, ctx.logger]) thread.daemon = True thread.start()
def set_default_values(self): self._set_process_management() self._set_name() self._set_network() self.setdefault('queue', self['name']) self.setdefault('rest_token', cloudify_utils.get_rest_token()) self.setdefault('rest_tenant', cloudify_utils.get_tenant()) self.setdefault('rest_port', cloudify_utils.get_manager_rest_service_port()) self.setdefault('bypass_maintenance', cloudify_utils.get_is_bypass_maintenance()) self.setdefault('min_workers', 0) self.setdefault('max_workers', 5) self.setdefault('disable_requiretty', True) self.setdefault('env', {}) self.setdefault('fabric_env', {}) self.setdefault('system_python', 'python')
def start(cloudify_agent, **_): """ Only called in "init_script"/"plugin" mode, where the agent is started externally (e.g. userdata script), and all we have to do is wait for it """ tenant = cloudify_utils.get_tenant() client = get_client( amqp_user=tenant['rabbitmq_username'], amqp_pass=tenant['rabbitmq_password'], amqp_vhost=tenant['rabbitmq_vhost'] ) agent_alive = utils.is_agent_alive(cloudify_agent['queue'], client) if not agent_alive: return ctx.operation.retry( message='Waiting for Agent to start...') ctx.logger.info('Agent has started') if not cloudify_agent.is_provided: script.cleanup_scripts()
def _send_cancel_task(self, target, execution_id): """Send a cancel-operation task to the agent given by `target`""" message = { 'service_task': { 'task_name': 'cancel-operation', 'kwargs': { 'execution_id': execution_id } } } if target == MGMTWORKER_QUEUE: client = get_client() else: tenant = get_tenant() client = get_client(amqp_user=tenant['rabbitmq_username'], amqp_pass=tenant['rabbitmq_password'], amqp_vhost=tenant['rabbitmq_vhost']) handler = SendHandler(exchange=target, routing_key='service') client.add_handler(handler) with client: handler.publish(message)
def start(cloudify_agent, **_): """ Only called in "init_script"/"plugin" mode, where the agent is started externally (e.g. userdata script), and all we have to do is wait for it """ update_agent_record(cloudify_agent, AgentState.STARTING) tenant = cloudify_utils.get_tenant() client = get_client(amqp_user=tenant['rabbitmq_username'], amqp_pass=tenant['rabbitmq_password'], amqp_vhost=tenant['rabbitmq_vhost']) agent_alive = utils.is_agent_alive(cloudify_agent['queue'], client) if not agent_alive: if ctx.operation.retry_number > 3: ctx.logger.warning('Waiting too long for Agent to start') update_agent_record(cloudify_agent, AgentState.NONRESPONSIVE) return ctx.operation.retry(message='Waiting for Agent to start...') ctx.logger.info('Agent has started') update_agent_record(cloudify_agent, AgentState.STARTED) if not cloudify_agent.is_provided: script.cleanup_scripts()
def _get_amqp_client(agent): delete_cert_path = False if agent.get('broker_config'): broker_config = agent['broker_config'] ssl_cert_path = _get_ssl_cert_path(broker_config) # Using a temp path, so we need to delete it delete_cert_path = True else: broker_config = _get_broker_config(agent) ssl_cert_path = get_local_rest_certificate() tenant = get_tenant() try: yield amqp_client.get_client( amqp_host=broker_config.get('broker_ip'), amqp_user=tenant.get('rabbitmq_username'), amqp_port=broker_config.get('broker_port'), amqp_pass=tenant.get('rabbitmq_password'), amqp_vhost=tenant.get('rabbitmq_vhost'), ssl_enabled=broker_config.get('broker_ssl_enabled'), ssl_cert_path=ssl_cert_path) finally: if delete_cert_path and ssl_cert_path: os.remove(ssl_cert_path)
def _create_agent_env(self): # Try to get broker credentials from the tenant. If they aren't set # get them from the broker_config module tenant = get_tenant() tenant_name = tenant.get('name', defaults.DEFAULT_TENANT_NAME) broker_user = tenant.get('rabbitmq_username', broker_config.broker_username) broker_pass = tenant.get('rabbitmq_password', broker_config.broker_password) broker_vhost = tenant.get('rabbitmq_vhost', broker_config.broker_vhost) execution_env = { # mandatory values calculated before the agent # is actually created env.CLOUDIFY_DAEMON_QUEUE: self.cloudify_agent['queue'], env.CLOUDIFY_DAEMON_NAME: self.cloudify_agent['name'], env.CLOUDIFY_REST_HOST: self.cloudify_agent['rest_host'], env.CLOUDIFY_BROKER_IP: self.cloudify_agent['broker_ip'], # Optional broker values env.CLOUDIFY_BROKER_USER: broker_user, env.CLOUDIFY_BROKER_PASS: broker_pass, env.CLOUDIFY_BROKER_VHOST: broker_vhost, env.CLOUDIFY_BROKER_SSL_ENABLED: broker_config.broker_ssl_enabled, env.CLOUDIFY_BROKER_SSL_CERT_PATH: self.cloudify_agent['broker_ssl_cert_path'], env.CLOUDIFY_HEARTBEAT: self.cloudify_agent.get('heartbeat'), # these are variables that have default values that will be set # by the agent on the remote host if not set here env.CLOUDIFY_DAEMON_USER: self.cloudify_agent.get('user'), env.CLOUDIFY_REST_PORT: self.cloudify_agent.get('rest_port'), env.CLOUDIFY_REST_TOKEN: get_rest_token(), env.CLOUDIFY_REST_TENANT: tenant_name, env.CLOUDIFY_DAEMON_MAX_WORKERS: self.cloudify_agent.get('max_workers'), env.CLOUDIFY_DAEMON_MIN_WORKERS: self.cloudify_agent.get('min_workers'), env.CLOUDIFY_DAEMON_PROCESS_MANAGEMENT: self.cloudify_agent['process_management']['name'], env.CLOUDIFY_DAEMON_WORKDIR: self.cloudify_agent['workdir'], env.CLOUDIFY_DAEMON_EXTRA_ENV: self.create_custom_env_file_on_target( self.cloudify_agent.get('env', {})), env.CLOUDIFY_BYPASS_MAINTENANCE_MODE: get_is_bypass_maintenance(), env.CLOUDIFY_LOCAL_REST_CERT_PATH: self.cloudify_agent['agent_rest_cert_path'], env.CLOUDIFY_CLUSTER_NODES: base64.b64encode(json.dumps(self.cloudify_agent.get('cluster', []))), env.CLOUDIFY_NETWORK_NAME: self.cloudify_agent.get('network') } execution_env = utils.purge_none_values(execution_env) execution_env = utils.stringify_values(execution_env) self.logger.debug('Cloudify Agent will be created using the following ' 'environment: {0}'.format(execution_env)) return execution_env
def _create_agent_env(self): tenant = get_tenant() tenant_name = tenant.get('name', defaults.DEFAULT_TENANT_NAME) tenant_user = tenant.get('rabbitmq_username', broker_config.broker_username) tenant_pass = tenant.get('rabbitmq_password', broker_config.broker_password) broker_vhost = tenant.get('rabbitmq_vhost', broker_config.broker_vhost) # Get the agent's broker credentials broker_user = self.cloudify_agent.get('broker_user', tenant_user) broker_pass = self.cloudify_agent.get('broker_pass', tenant_pass) manager_ip = self.cloudify_agent.get_manager_ip() network = self.cloudify_agent.get('network') execution_env = { # mandatory values calculated before the agent # is actually created env.CLOUDIFY_DAEMON_QUEUE: self.cloudify_agent['queue'], env.CLOUDIFY_DAEMON_NAME: self.cloudify_agent['name'], env.CLOUDIFY_REST_HOST: manager_ip, env.CLOUDIFY_BROKER_IP: ','.join( broker.networks[network] for broker in ctx.get_brokers(network=network) ), # Optional broker values env.CLOUDIFY_BROKER_USER: broker_user, env.CLOUDIFY_BROKER_PASS: broker_pass, env.CLOUDIFY_BROKER_VHOST: broker_vhost, env.CLOUDIFY_BROKER_SSL_ENABLED: broker_config.broker_ssl_enabled, env.CLOUDIFY_BROKER_SSL_CERT_PATH: ( self.cloudify_agent['broker_ssl_cert_path'] ), env.CLOUDIFY_HEARTBEAT: ( self.cloudify_agent.get('heartbeat') ), # these are variables that have default values that will be set # by the agent on the remote host if not set here env.CLOUDIFY_DAEMON_USER: self.cloudify_agent.get('user'), env.CLOUDIFY_REST_PORT: self.cloudify_agent.get('rest_port'), env.CLOUDIFY_REST_TOKEN: get_rest_token(), env.CLOUDIFY_REST_TENANT: tenant_name, env.CLOUDIFY_DAEMON_MAX_WORKERS: self.cloudify_agent.get( 'max_workers'), env.CLOUDIFY_DAEMON_MIN_WORKERS: self.cloudify_agent.get( 'min_workers'), env.CLOUDIFY_DAEMON_PROCESS_MANAGEMENT: self.cloudify_agent['process_management']['name'], env.CLOUDIFY_DAEMON_WORKDIR: self.cloudify_agent['workdir'], env.CLOUDIFY_DAEMON_EXTRA_ENV: self.create_custom_env_file_on_target( self.cloudify_agent.get('env', {})), env.CLOUDIFY_BYPASS_MAINTENANCE_MODE: get_is_bypass_maintenance(), env.CLOUDIFY_LOCAL_REST_CERT_PATH: ( self.cloudify_agent['agent_rest_cert_path'] ), env.CLOUDIFY_CLUSTER_NODES: base64.b64encode(json.dumps( self.cloudify_agent.get('cluster', []))), env.CLOUDIFY_NETWORK_NAME: network, ENV_CFY_EXEC_TEMPDIR: self.cloudify_agent.get( 'executable_temp_path'), ENV_AGENT_LOG_LEVEL: self.cloudify_agent.get('log_level'), ENV_AGENT_LOG_MAX_BYTES: self.cloudify_agent.get('log_max_bytes'), ENV_AGENT_LOG_MAX_HISTORY: self.cloudify_agent.get( 'log_max_history') } execution_env = utils.purge_none_values(execution_env) execution_env = utils.stringify_values(execution_env) self.logger.debug('Cloudify Agent will be created using the following ' 'environment: {0}'.format(execution_env)) return execution_env
def _create_agent_env(self): tenant = get_tenant() tenant_name = tenant.get('name', defaults.DEFAULT_TENANT_NAME) tenant_user = tenant.get('rabbitmq_username', broker_config.broker_username) tenant_pass = tenant.get('rabbitmq_password', broker_config.broker_password) broker_vhost = tenant.get('rabbitmq_vhost', broker_config.broker_vhost) # Get the agent's broker credentials broker_user = self.cloudify_agent.get('broker_user', tenant_user) broker_pass = self.cloudify_agent.get('broker_pass', tenant_pass) network = self.cloudify_agent.get('network') execution_env = { # mandatory values calculated before the agent # is actually created env.CLOUDIFY_DAEMON_QUEUE: self.cloudify_agent['queue'], env.CLOUDIFY_DAEMON_NAME: self.cloudify_agent['name'], env.CLOUDIFY_REST_HOST: ','.join(self.cloudify_agent['rest_host']), env.CLOUDIFY_BROKER_IP: ','.join(self.cloudify_agent['broker_ip']), # Optional broker values env.CLOUDIFY_BROKER_USER: broker_user, env.CLOUDIFY_BROKER_PASS: broker_pass, env.CLOUDIFY_BROKER_VHOST: broker_vhost, env.CLOUDIFY_BROKER_SSL_ENABLED: broker_config.broker_ssl_enabled, env.CLOUDIFY_BROKER_SSL_CERT_PATH: (self.cloudify_agent['broker_ssl_cert_path']), env.CLOUDIFY_HEARTBEAT: (self.cloudify_agent.get('heartbeat')), # these are variables that have default values that will be set # by the agent on the remote host if not set here env.CLOUDIFY_DAEMON_USER: self.cloudify_agent.get('user'), env.CLOUDIFY_REST_PORT: self.cloudify_agent.get('rest_port'), env.CLOUDIFY_REST_TOKEN: get_rest_token(), env.CLOUDIFY_REST_TENANT: tenant_name, env.CLOUDIFY_DAEMON_MAX_WORKERS: self.cloudify_agent.get('max_workers'), env.CLOUDIFY_DAEMON_MIN_WORKERS: self.cloudify_agent.get('min_workers'), env.CLOUDIFY_DAEMON_PROCESS_MANAGEMENT: self.cloudify_agent['process_management']['name'], env.CLOUDIFY_DAEMON_WORKDIR: self.cloudify_agent['workdir'], env.CLOUDIFY_DAEMON_EXTRA_ENV: self.create_custom_env_file_on_target( self.cloudify_agent.get('env', {})), env.CLOUDIFY_BYPASS_MAINTENANCE_MODE: get_is_bypass_maintenance(), env.CLOUDIFY_LOCAL_REST_CERT_PATH: (self.cloudify_agent['agent_rest_cert_path']), env.CLOUDIFY_NETWORK_NAME: network, ENV_CFY_EXEC_TEMPDIR: self.cloudify_agent.get('executable_temp_path'), ENV_AGENT_LOG_LEVEL: self.cloudify_agent.get('log_level'), ENV_AGENT_LOG_MAX_BYTES: self.cloudify_agent.get('log_max_bytes'), ENV_AGENT_LOG_MAX_HISTORY: self.cloudify_agent.get('log_max_history') } execution_env = utils.purge_none_values(execution_env) execution_env = utils.stringify_values(execution_env) self.logger.debug('Cloudify Agent will be created using the following ' 'environment: {0}'.format(execution_env)) return execution_env