def send(self, nodes_stats): deployment_id = helper.get_deployment_id() # If the deployment is not registered, skip. if not deployment_id: return # Send request to AppScale Portal. portal_path = self._portal_method.format(deployment_id=deployment_id) url = "{0}{1}".format(constants.PORTAL_URL, portal_path) data = { 'deployment_id': deployment_id, 'nodes_stats': json.dumps({ node_ip: [stats_to_dict(snapshot) for snapshot in snapshots] for node_ip, snapshots in nodes_stats.iteritems() }) } snapshots_num = sum( len(snapshots) for snapshots in nodes_stats.values()) logger.debug( "Sending {snapshots} node stats snapshots about {nodes} nodes to the " "AppScale Portal".format(snapshots=snapshots_num, nodes=len(nodes_stats))) request = helper.create_request(url=url, method='POST', body=urllib.urlencode(data)) response = helper.urlfetch(request) if not response[JSONTags.SUCCESS]: logger.error("Inaccessible resource: {}".format(url)) return
def poll(): """ Callback function that polls for new tasks based on a schedule. """ deployment_id = helper.get_deployment_id() # If the deployment is not registered, skip. if not deployment_id: return # If we can't reach the backup and recovery services, skip. nodes = helper.get_node_info() http_client = tornado.httpclient.HTTPClient() for node in nodes: br_host = node[helper.NodeInfoTags.HOST] request = tornado.httpclient.HTTPRequest(br_host) try: response = http_client.fetch(request) if json.loads(response.body)['status'] != 'up': logging.warn( 'Backup and Recovery service at {} is not up.'.format( br_host)) return except (socket.error, ValueError): logging.exception( 'Backup and Recovery service at {} is not up.'.format(br_host)) return logging.info("Polling for new task.") # Send request to AppScale Portal. url = "{0}{1}".format(constants.PORTAL_URL, constants.PORTAL_POLL_PATH) data = urllib.urlencode({JSONTags.DEPLOYMENT_ID: deployment_id}) request = helper.create_request(url=url, method='POST', body=data) response = helper.urlfetch(request) if not response[JSONTags.SUCCESS]: logging.error("Inaccessible resource: {}".format(url)) return try: data = json.loads(response[JSONTags.BODY]) except (TypeError, ValueError) as error: logging.error( "Cannot parse response from url '{0}'. Error: {1}".format( url, str(error))) return if data == {}: # If there's no task to perform. return # Verify all necessary fields are present in the request. if not set(data.keys()).issuperset(set(constants.REQUIRED_KEYS)): logging.error("Missing args in response: {0}".format(response)) return logging.debug("Task to run: {0}".format(data)) logging.info("Redirecting task request to TaskHandler.") url = "http://localhost:{}{}".format(constants.HERMES_PORT, '/do_task') request = helper.create_request(url, method='POST', body=json.dumps(data)) # The poller can move forward without waiting for a response here. helper.urlfetch_async(request)
def send(self, nodes_stats): deployment_id = helper.get_deployment_id() # If the deployment is not registered, skip. if not deployment_id: return # Send request to AppScale Portal. portal_path = self._portal_method.format(deployment_id=deployment_id) url = "{0}{1}".format(constants.PORTAL_URL, portal_path) data = { 'deployment_id': deployment_id, 'nodes_stats': json.dumps({ node_ip: [stats_to_dict(snapshot) for snapshot in snapshots] for node_ip, snapshots in nodes_stats.iteritems() }) } snapshots_num = sum(len(snapshots) for snapshots in nodes_stats.values()) logging.debug( "Sending {snapshots} node stats snapshots about {nodes} nodes to the " "AppScale Portal".format(snapshots=snapshots_num, nodes=len(nodes_stats)) ) request = helper.create_request(url=url, method='POST', body=urllib.urlencode(data)) response = helper.urlfetch(request) if not response[JSONTags.SUCCESS]: logging.error("Inaccessible resource: {}".format(url)) return
def poll(): """ Callback function that polls for new tasks based on a schedule. """ deployment_id = helper.get_deployment_id() # If the deployment is not registered, skip. if not deployment_id: return # If we can't reach the backup and recovery services, skip. nodes = helper.get_node_info() http_client = tornado.httpclient.HTTPClient() for node in nodes: br_host = node[helper.NodeInfoTags.HOST] request = tornado.httpclient.HTTPRequest(br_host) try: response = http_client.fetch(request) if json.loads(response.body)['status'] != 'up': logging.warn('Backup and Recovery service at {} is not up.' .format(br_host)) return except (socket.error, ValueError): logging.exception('Backup and Recovery service at {} is not up.' .format(br_host)) return logging.info("Polling for new task.") # Send request to AppScale Portal. url = "{0}{1}".format(constants.PORTAL_URL, constants.PORTAL_POLL_PATH) data = urllib.urlencode({JSONTags.DEPLOYMENT_ID: deployment_id}) request = helper.create_request(url=url, method='POST', body=data) response = helper.urlfetch(request) if not response[JSONTags.SUCCESS]: logging.error("Inaccessible resource: {}".format(url)) return try: data = json.loads(response[JSONTags.BODY]) except (TypeError, ValueError) as error: logging.error("Cannot parse response from url '{0}'. Error: {1}". format(url, str(error))) return if data == {}: # If there's no task to perform. return # Verify all necessary fields are present in the request. if not set(data.keys()).issuperset(set(constants.REQUIRED_KEYS)): logging.error("Missing args in response: {0}".format(response)) return logging.debug("Task to run: {0}".format(data)) logging.info("Redirecting task request to TaskHandler.") url = "http://localhost:{}{}".format(constants.HERMES_PORT, '/do_task') request = helper.create_request(url, method='POST', body=json.dumps(data)) # The poller can move forward without waiting for a response here. helper.urlfetch_async(request)
def test_get_deployment_id(self): # Test with a registered AppScale deployment. fake_acc = FakeAppControllerClient(True) flexmock(appscale_info).should_receive('get_appcontroller_client').\ and_return(fake_acc) flexmock(AppControllerClient).should_receive('deployment_id_exists').\ and_return(True) flexmock(AppControllerClient).should_receive('get_deployment_id').\ and_return('fake_id') self.assertEquals('fake_id', helper.get_deployment_id()) # Test with an AppScale deployment that's not registered. fake_acc = FakeAppControllerClient(False) flexmock(appscale_info).should_receive('get_appcontroller_client').\ and_return(fake_acc) flexmock(AppControllerClient).should_receive('deployment_id_exists').\ and_return(False) self.assertIsNone(helper.get_deployment_id())
def deploy(self): """ Uploads the sensor app for registered deployments. """ deployment_id = helper.get_deployment_id() # If deployment is not registered, then do nothing. if not deployment_id: return ua_client = UAClient(appscale_info.get_db_master_ip(), options.secret) # If the appscalesensor app is already running, then do nothing. version_node = '/appscale/projects/{}/services/{}/versions/{}'.format( constants.APPSCALE_SENSOR, DEFAULT_SERVICE, DEFAULT_VERSION) if self.zk_client.exists(version_node) is not None: return pwd = appscale_utils.encrypt_password( constants.USER_EMAIL, appscale_utils.random_password_generator()) if create_appscale_user(pwd, ua_client) and create_xmpp_user( pwd, ua_client): logging.debug( "Created new user and now tarring app to be deployed.") file_path = os.path.join(os.path.dirname(__file__), '../Apps/sensor') app_dir_location = os.path.join(constants.APP_DIR_LOCATION, constants.APPSCALE_SENSOR) archive = tarfile.open(app_dir_location, "w|gz") archive.add(file_path, arcname=constants.APPSCALE_SENSOR) archive.close() try: logging.info( "Deploying the sensor app for registered deployments.") acc = appscale_info.get_appcontroller_client() acc.upload_app(app_dir_location, constants.FILE_SUFFIX) except AppControllerException: logging.exception( "AppControllerException while trying to deploy " "appscalesensor app.") else: logging.error( "Error while creating or accessing the user to deploy " "appscalesensor app.")
def deploy(self): """ Uploads the sensor app for registered deployments. """ deployment_id = helper.get_deployment_id() # If deployment is not registered, then do nothing. if not deployment_id: return ua_client = UAClient(appscale_info.get_db_master_ip(), options.secret) # If the appscalesensor app is already running, then do nothing. version_node = '/appscale/projects/{}/services/{}/versions/{}'.format( constants.APPSCALE_SENSOR, DEFAULT_SERVICE, DEFAULT_VERSION) if self.zk_client.exists(version_node) is not None: return pwd = appscale_utils.encrypt_password(constants.USER_EMAIL, appscale_utils.random_password_generator()) if create_appscale_user(pwd, ua_client) and create_xmpp_user(pwd, ua_client): logging.debug("Created new user and now tarring app to be deployed.") file_path = os.path.join(os.path.dirname(__file__), '../Apps/sensor') app_dir_location = os.path.join(constants.APP_DIR_LOCATION, constants.APPSCALE_SENSOR) archive = tarfile.open(app_dir_location, "w|gz") archive.add(file_path, arcname=constants.APPSCALE_SENSOR) archive.close() try: logging.info("Deploying the sensor app for registered deployments.") acc = appscale_info.get_appcontroller_client() acc.upload_app(app_dir_location, constants.FILE_SUFFIX) except AppControllerException: logging.exception("AppControllerException while trying to deploy " "appscalesensor app.") else: logging.error("Error while creating or accessing the user to deploy " "appscalesensor app.")