This blog demonstrates an approach of collecting information about applications, service instances and other entities from SAP HANA Extended Application Services, Advanced Model (XSA) using XS Controller APIs.
TL;DR: The blog provided an overview of a command-line tool that utilizes XS Controller APIs to simplify some of maintenance operations. The tool is based on a reusable Python module that represents various entities of the XS Controller, such as applications, service instances and others, and methods to work with them. Besides the given examples, you can extend the functionality to cover your own use cases. The comprehensive documentation for this example is provided in the Git repository https://github.com/nklinked/otter.
The data samples provided in Example Use Cases are wide tables that might be quite complicated to read. Nevertheless, providing them here is a better approach than just describing their content without an example.
Introduction
-
Collect general statistics about applications and service instances deployed in all organizations and spaces. Preserving this information may be an important step when running an operation changing the global state of the system, e.g., while doing a system upgrade or a system copy
-
Collect the information about all User-Provided Services
-
Collect mappings between HANA service instances and their HDI container schemas. Not critically important but sometimes a nice feature, when you need to identify a respective service instance of the problematic HDI container
-
Identify orphaned applications and service instances created temporarily by SAP Web IDE for HANA to clean them up. Such objects are very intensively produced in an actively used development system
-
Identify STOPPED and CRASHED application instances to clean them up massively. Those instances are usually used for the post-mortem analysis, but deleting them for every single application can be a time-consuming task
-
Identify outdated service keys
-
Identify if count of the di-builder service bindings is coming closer to the threshold (should be <= 120)
-
Identify application API calls demonstrating decreased response time
-
Collect Organization and Space Roles and Role Collection assigned to users
-
Establish a foundation to collectively manage the respective entities
Motivation
Fulfilling the aforementioned tasks you may need to interactively run XS CLI commands and manually collect the required information, e.g., to collect information about MTA objects we need to iterate over all spaces and run:
- xs mtas to fetch all deployed MTA applications
- xs mta <mta_name> to fetch all applications and service instances belonging to the MTA project
- xs app <app_name> to fetch information about the specific application belonging to the MTA project
- xs service <service_instance_name> to fetch information about the specific service instance belonging to the MTA project
Automating such a scenario based on XS CLI, you may need to run the shell script performing all those steps iteratively. Even though this approach is feasible, it requires some further optimization.
Thanks to Thomas Jung and his great post about XS Controller interactions, implementation of those requirements received a solid foundation.
Addressing the basic requirements, following assumptions are taken:
- Python can be used to prototype and to implement the required functionality faster
- The user interface is not required, a command-line interface is absolutely sufficient
- All collected information can be stored in csv files for further analysis. Specific conclusions will be done based on those reports
- Operations changing state of the system should be marked as experimental and should be run with all required precautions
Brief Implementation Overview
The provided example is a Python-based application decoupling two layers:
- The reusable module representing the XS Controller entities, their metadata and applied methods. Files of the module are located in components/controller
- Specific functions consuming XS Controller APIs are located in components/tools. This folder contains tools implementing use cases provided above
Specific client configuration can be passed in the config.yaml, e.g., lists of objects that are prohibited for modifications.
otter
├── components
│ ├── controller
│ │ ├── application.py
│ │ ├── controller.py
│ │ ├── database.py
│ │ ├── organization.py
│ │ ├── service.py
│ │ ├── session.py
│ │ └── space.py
│ └── tools
│ ├── cleaner.py
│ ├── client.py
│ ├── collector.py
│ └── utils.py
├── config.yaml
├── otter.py
└── requirements.txt
The application follows the standard UAA authentication flow and requires the XS Advanced user with Role Collections XS_CONTROLLER_USER and XS_CONTROLLER_ADMIN assigned.
All commands run by the example application can be triggered by the respective command-line arguments, that follows the method similar to XS CLI. Every command requires the XS Controller API endpoint, user credentials and selective criteria to be provided.
Example Use Cases
Following examples demonstrate possible reports that can be generated from the system for further analysis.
Collecting information about mapped Tenant Databases
Using this command we can collect information about database tenants known by XS Advanced in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-databases
The operation is the system wide and ignores any selective argument. The resulting CSV file will be stored in <output_dir>/databases/databases.csv
The produced output will contain following fields:
GUID | Tenant | Encryption | HANA Broker User | HANA Broker Schema | Mapped Orgs / Spaces | DB Usergroups | JDBC Endpoint |
198dcc72-54b3-431f-b483-53c3da04a387 | SID | FALSE | SYS_XS_HANA_BROKER | _SYS_DI#SYS_XS_HANA_BROKER | [‘orgname/’, ‘orgname/SAP’] | [{‘plan’: ‘hana:hdi-shared’, ‘name’: ‘SYS_XS_UG_BROKER_HDI_SHARED#SYS_XS_HANA_BROKER’}, {‘plan’: ‘hana:sbss’, ‘name’: ‘SYS_XS_UG_BROKER_SBSS#SYS_XS_HANA_BROKER’}, {‘plan’: ‘hana:schema’, ‘name’: ‘SYS_XS_UG_BROKER_SCHEMA#SYS_XS_HANA_BROKER’}, {‘plan’: ‘hana:securestore’, ‘name’: ‘SYS_XS_UG_BROKER_SECSTORE#SYS_XS_HANA_BROKER’}] | jdbc:sap://some.hostname:30015/ |
Collecting information about Organization Roles assigned to users
Using this command we can collect information about Organization roles (OrgManager, OrgAuditor) assigned to users in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-org-roles-assignment
The operation is the system wide and ignores any selective argument. The resulting CSV file will be stored in <output_dir>/users/org_roles_assignment.csv
The produced output will contain following fields:
User GUID | User UAA GUID | User Name | Origin | Is Active | Is Orphaned | Organization GUID | Organization Name | Role |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | OrgManager | |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | OrgAuditor |
Collecting information about Space Roles assigned to users
Using this command we can collect information about Space roles (SpaceManager, SpaceAuditor, SpaceDeveloper) assigned to users in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-space-roles-assignment
The operation is the system wide and ignores any selective argument. The resulting CSV file will be stored in <output_dir>/users/space_roles_assignment.csv
The produced output will contain following fields:
User GUID | User UAA GUID | User Name | Origin | Is Active | Is Orphaned | Organization GUID | Organization Name | Space GUID | Space Name | Role |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | 224fea07-cd32-427f-98d1-68fe10cc5f7f | SAP | SpaceManager | |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | SpaceDeveloper |
Collecting information about Role Collections assigned to users
Using this command we can collect information about Role Collections assigned to users in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-space-roles-assignment
The operation is the system wide and ignores any selective argument. The resulting CSV file will be stored in <output_dir>/users/role_collections_assignment.csv
The produced output will contain following fields:
User GUID | User UAA GUID | User Name | Origin | Is Active | Is Orphaned | Role Collection Name |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | WEBIDE_ADMINISTRATOR | |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | WEBIDE_DEVELOPER | |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | XS_CONTROLLER_ADMIN | |
c637f44a-917f-4421-926d-f343d93ee556 | 169157 | MYUSER | TRUE | FALSE | XS_CONTROLLER_USER |
Collecting information about Applications
Using this command we can collect information about applications in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-application-instances
The operation can be limited to a single space by providing argument -s, –space <SPACE>. In case argument -s, –space <SPACE> is not given the command will be executed for all spaces within the given organization.
The resulting CSV file will be stored in <output_dir>/apps/<org>/<space>/apps.csv
The produced output will contain following fields:
Org GUID | Org Name | Space GUID | Space Name | App GUID | App Name | Target Runtime | Detected Buildpack | Created At | Updated At | State | Is Down | Uptime *100% | Memory | MTA Module Name | MTA ID | MTA Version | MTA Module Dependencies | MTA Services | Count of Bindings | Target Container (hdi-deploy) | Belongs to MTA | Has Deployment Tasks | Is HDI Deployer | Planned Instances Count | Running Instances Count | Crashed Instances Count | Short-Term Crashes Count | Mid-Term Crashes Count | Long-Term Crashes Count | Instance GUID | Instance Droplet GUID | Instance Started At | Instance Created At | Instance Updated At | Instance State | Instance Failure Reason | Instance PID | Instance OS User |
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | a4bcc2eb-9b20-4bef-846d-c0d41c39cf9f | di-builder | tomcat | 2022-01-13 23:11:11.999 | 2022-03-24 00:19:57.942 | STARTED | FALSE | 0.9999999999999998 | 1024 | di-builder | com.sap.devx.di.builder | 4.6.2 | [‘di-builder’] | [] | 5 | TRUE | FALSE | FALSE | 1 | 1 | 0 | 0 | 0 | 0 | 6e6e2b4a-28cc-4563-8744-364eb5943ff5 | c4d99f31-37ca-4ba8-9d04-219201cdb2a3 | 2022-03-27 15:26:19.849 | 2022-03-27 15:19:52.027 | 2022-03-27 15:26:19.849 | RUNNING | 12027.0 | sidxsa | |||
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | 414ac835-1f39-4415-916a-18f961d368a9 | my.app.db | sap_nodejs_buildpack 4.4.0 | 2022-05-26 10:19:30.543 | 2022-05-26 10:19:55.367 | STOPPED | 256 | my.app.db | MyApp | 0.0.3 | [] | [‘hdi_myapp.db’] | 1 | TRUE | TRUE | TRUE | 1 | 0 | 0 | 0 | 0 | 0 |
Collecting information about Service Instances
Using this command we can collect information about service instances in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-service-instances
The operation can be limited to a single space by providing argument -s, –space <SPACE>. In case argument -s, –space <SPACE> is not given the command will be executed for all spaces within the given organization.
The resulting CSV file will be stored in <output_dir>/services/<org>/<space>/service_instances.csv
The produced output will contain following fields:
Org GUID | Org Name | Space GUID | Space Name | Service Instance GUID | Service Instance Name | Created At | Updated At | Last Operation Type | Last Operation State | Last Operation Time | Service Label | Service Plan Name | Parameters | Belongs to HANA Broker | Tenant Name (for HANA) | Container Schema (for HANA) | Bindings Count | Bindings to Apps Count | Bindings to MTAs Count (except di-builder) | References to MTAs Count (except di-builder) | Bindings to di-builder Count | Bindings to Standalone Apps Count | Service Keys Count |
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | 0fdf631d-acf5-4ff4-a9a8-2e31652520b3 | myapp.db | 2022-05-26 10:19:14.762 | 2022-05-26 10:19:17.511 | create | succeeded | 2022-05-26 10:19:17.511 | hana | hdi-shared | TRUE | SID | 582D9196697D44938F607ACA4A701FDF | 2 | 2 | 1 | 1 | 1 | 0 | 1 | |
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | 044a9ee8-9fd5-44b0-a5e7-33fe6490d614 | MYUSER-s87m94bll56ylvik-grantor-procedure-example-hdi_consumer.db | 2022-05-26 12:38:36.620 | 2022-05-26 12:38:39.081 | create | succeeded | 2022-05-26 12:38:39.080 | hana | hdi-shared | {‘schema’: ‘GRANTOR_PROCEDURE_EXAMPLE_HDI_CONSUMER_DB’, ‘makeUniqueName’: True} | TRUE | SID | GRANTOR_PROCEDURE_EXAMPLE_HDI_CONSUMER_DB_1 | 1 | 1 | 0 | 0 | 1 | 0 | 2 |
Collecting information about User-Provided Service Instances
Using this command we can collect information about user-provided service instances in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-user-provided-service-instances
The operation can be limited to a single space by providing argument -s, –space <SPACE>. In case argument -s, –space <SPACE> is not given the command will be executed for all spaces within the given organization.
The resulting CSV file will be stored in <output_dir>/services/<org>/<space>/user_provided_service_instances.csv
The produced output will contain following fields:
Org GUID | Org Name | Space GUID | Space Name | UPS Instance GUID | UPS Instance Name | Created At | Updated At | Credentials (JSON) |
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | b54ba9ef-8662-4a06-b321-aab3fa503d72 | GRANTOR-USER-UPS | 2022-05-26 11:26:25.171 | 2022-05-26 11:26:25.171 | {‘password’: ‘MyPassword#1′, ‘driver’: ‘com.sap.db.jdbc.Driver’, ‘port’: ‘30015’, ‘host’: ‘some.hostname’, ‘user’: ‘GRANTOR_USER’, ‘tags’: [‘hana’]} |
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | d79d1b60-062e-46c6-a9c7-131bf62301c5 | GRANTOR-PROCEDURE-UPS | 2022-05-26 12:36:27.838 | 2022-05-26 12:36:27.838 | {‘schema’: ‘SYS’, ‘password’: ‘MyPassword#1’, ‘port’: ‘30015’, ‘procedure_schema’: ‘GRANTING_PROCEDURE_OWNER’, ‘host’: ‘some.hostname’, ‘procedure’: ‘PROCESS_HDBGRANTS’, ‘type’: ‘procedure’, ‘user’: ‘GRANTING_PROCEDURE_INVOKER’, ‘tags’: [‘hana’]} |
Collecting information about Service Keys
Using this command we can collect information about service instances and keys in the CSV file.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org --report-service-keys
The operation can be limited to a single space by providing argument -s, –space <SPACE>. In case argument -s, –space <SPACE> is not given the command will be executed for all spaces within the given organization.
The resulting CSV file will be stored in <output_dir>/services/<org>/<space>/service_instance_keys.csv
The produced output will contain following fields:
Org GUID | Org Name | Space GUID | Space Name | Service Instance GUID | Service Instance Name | Created At | Updated At | Last Operation Type | Last Operation State | Last Operation Time | Service Label | Service Plan Name | Parameters | Belongs to HANA Broker | Tenant Name (for HANA) | Container Schema (for HANA) | Service Key GUID | Service Key Name | Service Key Created At | Service Key Updated At |
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | 0fdf631d-acf5-4ff4-a9a8-2e31652520b3 | hdi_myapp.db | 2022-05-26 10:19:14.762 | 2022-05-26 10:19:17.511 | create | succeeded | 2022-05-26 10:19:17.511 | hana | hdi-shared | TRUE | SID | 582D9196697D44938F607ACA4A701FDF | 5ec8a4fc-29c4-4c00-84e2-d0a5dd97c50c | uaa#MYUSER:D10@0fdf631d-acf5-4ff4-a9a8-2e31652520b3 | 2022-05-26 10:25:20.372 | 2022-05-26 10:25:20.372 | |
a6b61d68-5cc9-4c0a-a659-eeabcd280997 | orgname | d18499ac-fc1c-433b-aa2f-44c26888ea5f | DEV_MYUSER | 044a9ee8-9fd5-44b0-a5e7-33fe6490d614 | MYUSER-s87m94bll56ylvik-grantor-procedure-example-hdi_consumer.db | 2022-05-26 12:38:36.620 | 2022-05-26 12:38:39.081 | create | succeeded | 2022-05-26 12:38:39.080 | hana | hdi-shared | {‘schema’: ‘GRANTOR_PROCEDURE_EXAMPLE_HDI_CONSUMER_DB’, ‘makeUniqueName’: True} | TRUE | SID | GRANTOR_PROCEDURE_EXAMPLE_HDI_CONSUMER_DB_1 | e94e303d-54ba-456a-8326-b9bd25acf730 | SharedDevKey | 2022-05-26 12:38:41.224 | 2022-05-26 12:38:41.224
|
Collecting information about Applications and Service Instances not belonging to any of the deployed MTA Projects
Using this command we can collect detailed information about applications and service instances, having no MTA information in the CSV file. Most frequently applications and service instances having no Multi-Target Application attribution are created by the SAP Web IDE and are not cleaned up properly after the development. Nevertheless, the exceptions are possible, e.g., the manually created service instances and applications pushed to XS Advanced.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org -s some_space --report-non-mta-objects
The produced outputs will contain the same fields as -rai (–report-application-instances) and -rsi (–report-service-instances).
The operation can be limited to a single space by providing argument -s, –space <SPACE>. In case argument -s, –space <SPACE> is not given the command will be executed for all spaces within the given organization.
The resulting CSV files will be stored in <output_dir>/apps/<org>/<space>/non_mta_apps.csv and in <output_dir>/services/<org>/<space>/non_mta_service_instances.csv
Collect parsed Router Logs of applications
Using this command we can collect the parsed application log, having only RTR entries, in the CSV file. Such an application log contains only the entries representing the API call routed to the application. The log is useful to identify the long running API calls within the monitored timeframe.
otter -a https://some.hostname:30033 -u some_user -p SomePassword12 -o some_org -s some_space -app some_app --report-parsed-app-log
The operation can be limited to a single app by providing argument -app, –application <APPLICATION> coupled with argument -s, –space <SPACE> .
The operation can be limited to a single space as well by providing argument -s, –space <SPACE> . In case argument -s, –space <SPACE> is not given the command will be executed for all spaces within the given organization.
The resulting CSV files will be stored in <output_dir>/apps/<org>/<space>/<app>/router_log.csv
The produced output will contain following fields:
Timestamp | Caller | Callee | Method | Request String | HTTP Status | Response Size, byte | Response Time, ms |
2022-04-11 11:11:23.596 | 10.128.104.199 | some.hostname:53075 | POST | /watt/index.html | 403 | 19 | 21485 |
2022-04-09 10:38:59.753 | 10.128.92.88 | some.hostname:53075 | POST | /che/mta/workspace7aepwsf0wyr43v6m/import/Project_Local | 202 | 123 | 21424 |
2022-05-11 17:30:23.423 | 10.98.243.225 | some.hostname:53075 | GET | /hrtt-service/sap/hana/cst/api/v2/objects(‘:’)/tree() | 200 | 1348 | 21398 |
Closing
The blog provided a brief overview of a Python-based module utilizing XS Controller APIs. Please refer to the complete example and more comprehensive documentation in the repository https://github.com/nklinked/otter.
Please note that running massive operations with the tool, e.g., deleting all STOPPED and CRASHED application instances, you need to specify the Exclusion List to avoid any influence on the critical applications. Current list of massive operations:
- Identify and stop continuously crashing applications still having a small portion of uptime
- Delete all STOPPED and CRASHED application instances
- Delete applications and service instances not belonging to MTA projects (highly experimental and requiring the Exclusion Lists to be properly set)
Reference
- Product Documentation: The XS Command-Line Interface Reference
- The example solution for Node.js: SAP HANA XSA Controller API Interaction
- The API documentation: Cloud Foundry /v2 APIs
- The example solution for Python: Otter