-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.json
1 lines (1 loc) · 41.4 KB
/
index.json
1
[{"content":"","date":"20 October 2023","permalink":"/tags/api/","section":"Tags","summary":"","title":"api"},{"content":"","date":"20 October 2023","permalink":"/","section":"Awetomate","summary":"","title":"Awetomate"},{"content":"","date":"20 October 2023","permalink":"/categories/","section":"Categories","summary":"","title":"Categories"},{"content":"","date":"20 October 2023","permalink":"/tags/itential/","section":"Tags","summary":"","title":"itential"},{"content":"The getAdaptersHealth API endpoint allows us to retrieve the data and operational status for all configured adapters on an IAP instance. I typically use this to e.g. determine the proper IAG adapter to onboard a device with or to determine if an adapter is healthy (Status:RUNNING, Connection:ONLINE) as part of my pre-change checks.\nThe generic restCall task # You can use the generic restCall task in IAP Automation Builder to send API calls to the local or a remote IAP server. This task enables you to send a query to the getAdaptersHealth API endpoint, which is part of the standard pronghorn-core group of API calls. There is currently no dedicated task available in Automation Builder to get all adapters and their operational status (IAP 2023.1). And the Itential IAP opensource adapter doesn\u0026rsquo;t contain this option either.\nExample # The following screenshot shows an example of how to use the restCall task to send an API call to the local IAP instance (127.0.0.1). uri https://127.0.0.1:3443/health/adapters verb GET user username password password headers leave blank body see queryOptions section below queryOptions # The queryOptions determine what and how much data is returned by the getAdaptersHealth API call.\nIn this example I want to retrieve all Cisco DNA Center adapter instances on my IAP. The field I want to filter by is package_id and package ID for the DNAC adapters is @itentialopensource/adapter-dna_center.\nThe package ID is usually the name of the adapter prebuilt as shown in the NPM or GitLab repositories. Alternatively, you can also get this value by going to Admin Essentials \u0026gt; Adapters \u0026gt; yourAdapter, toggle on the Advanced View, and copy the model value that starts with @itential/ or @itentialopensource/.\nHere is an example queryOptions template you can use to send as the body in the restCall task:\n{ \u0026#34;queryOptions\u0026#34;: { \u0026#34;equals\u0026#34;: \u0026#34;@itentialopensource/adapter-dna_center\u0026#34;, \u0026#34;equalsField\u0026#34;: \u0026#34;package_id\u0026#34;, \u0026#34;skip\u0026#34;: 0, \u0026#34;limit\u0026#34;: 10 } } equals Filter on a field. The value has to match exactly. equalsField The field to match against. skip Number of results to skip. Used for pagination. Default is 0. limit The number of results returned. sort Field to sort by. Default is name. order Sort direction. 1 for ascending and -1 for descending. Check out the schema definition for more options like contains or startsWith.\nUse filter options like equals/equalsField, contains/containsField, or startsWith/startsWithField to retrieve only the adapter data you are looking for.\nExample Workflow # Example Input/Output # Input\n{ \u0026#34;uri\u0026#34;: \u0026#34;https://127.0.0.1:3443/health/adapters\u0026#34;, \u0026#34;verb\u0026#34;: \u0026#34;GET\u0026#34;, \u0026#34;user\u0026#34;: \u0026#34;* * * * *\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;* * * * *\u0026#34;, \u0026#34;headers\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;body\u0026#34;: { \u0026#34;queryOptions\u0026#34;: { \u0026#34;equals\u0026#34;: \u0026#34;@itentialopensource/adapter-dna_center\u0026#34;, \u0026#34;equalsField\u0026#34;: \u0026#34;package_id\u0026#34;, \u0026#34;skip\u0026#34;: 0, \u0026#34;limit\u0026#34;: 10 } }, \u0026#34;responseHeaders\u0026#34;: false } Output (truncated)\n{ \u0026#34;response\u0026#34;: { \u0026#34;body\u0026#34;: { \u0026#34;results\u0026#34;: [ { \u0026#34;id\u0026#34;: \u0026#34;dnac-lab.domain.com\u0026#34;, \u0026#34;package_id\u0026#34;: \u0026#34;@itentialopensource/adapter-dna_center\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;0.6.2\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;Adapter\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;This adapter integrates with system Dna_center\u0026#34;, \u0026#34;state\u0026#34;: \u0026#34;RUNNING\u0026#34;, \u0026#34;connection\u0026#34;: { \u0026#34;state\u0026#34;: \u0026#34;ONLINE\u0026#34; }, \u0026#34;uptime\u0026#34;: 491162.191712545, \u0026#34;memoryUsage\u0026#34;: { \u0026#34;rss\u0026#34;: 256696320, \u0026#34;heapTotal\u0026#34;: 109891584, \u0026#34;heapUsed\u0026#34;: 103882776, \u0026#34;external\u0026#34;: 38782589, \u0026#34;arrayBuffers\u0026#34;: 37866102 }, \u0026#34;cpuUsage\u0026#34;: { \u0026#34;user\u0026#34;: 352368455, \u0026#34;system\u0026#34;: 67758551 }, \u0026#34;pid\u0026#34;: 2323470, \u0026#34;logger\u0026#34;: { \u0026#34;console\u0026#34;: \u0026#34;debug\u0026#34;, \u0026#34;file\u0026#34;: \u0026#34;debug\u0026#34;, \u0026#34;syslog\u0026#34;: {} }, \u0026#34;routePrefix\u0026#34;: \u0026#34;Dna_center\u0026#34;, \u0026#34;prevUptime\u0026#34;: 491134.916105273 } ], \u0026#34;total\u0026#34;: 4 } } ","date":"20 October 2023","permalink":"/2023/10/itential-getadaptershealth-api-call/","section":"Posts","summary":"The getAdaptersHealth API endpoint allows us to retrieve the data and operational status for all configured adapters on an IAP instance. I typically use this to e.g. determine the proper IAG adapter to onboard a device with or to determine if an adapter is healthy (Status:RUNNING, Connection:ONLINE) as part of my pre-change checks.","title":"Itential getAdaptersHealth API Call"},{"content":"The getDevicesFiltered task allows us to retrieve the inventory data for one or more configured devices in Configuration Manager. I typically use this to e.g. retrieve a list of devices of a certain OS type.\nThe official API documentation for this endpoint was not really clear to me and it took some testing and playing with different query parameters to figure out how to properly use this task.\nThe getDevicesFiltered task # You can use the getDevicesFiltered task, which is part of the ConfigurationManager tasks group in IAP Automation Builder, to retrieve data for one or multiple devices. The critical piece is to set the proper query parameters using the options object to filter and limit the results. This is especially important for large environments with thousands of devices.\nExample # The following screenshot shows an example of how to use the getDevicesFiltered task. options Object with filters and query params. options # The options object determines what and how much data is returned by the getDevicesFiltered API call.\nIn this example I want to retrieve the first ten devices from Configuration Manager that have an OS Type value of cisco-asa.\nHere is an example template you can use to send as the options object in the getDevicesFiltered task:\n{ \u0026#34;limit\u0026#34;: 10, \u0026#34;start\u0026#34;: 0, \u0026#34;filter\u0026#34;: { \u0026#34;ostype\u0026#34;: \u0026#34;cisco-asa\u0026#34; }, \u0026#34;exactMatch\u0026#34;: true } limit The number of results returned. required start Number of results to skip. Used for pagination. optional filter Filter on a field. The object can take multiple keys. optional sort Field(s) to sort by. optional order Sort direction; ascending or descending. optional exactMatch Boolean that indicates if an exact result will be returned or not. seems to be required despite the documentation not listing it as such Check out the schema definition for more filter and query options.\nexactMatch seems to be a required parameter in IAP 2023.1 and earlier. Add this parameter to your options object if you receive server 500 errors when executing the getDevicesFiltered task. Example Input/Output # Input\n{ \u0026#34;options\u0026#34;: { \u0026#34;limit\u0026#34;: 10, \u0026#34;start\u0026#34;: 0, \u0026#34;filter\u0026#34;: { \u0026#34;ostype\u0026#34;: \u0026#34;cisco-asa\u0026#34; }, \u0026#34;exactMatch\u0026#34;: true } } Output (truncated)\n{ \u0026#34;devices\u0026#34;: { \u0026#34;entity\u0026#34;: \u0026#34;device\u0026#34;, \u0026#34;total\u0026#34;: 30, \u0026#34;totalByAdapter\u0026#34;: { \u0026#34;itential-iag1-dev.domain.com\u0026#34;: 10, \u0026#34;itential-iag2-dev.domain.com\u0026#34;: 10, \u0026#34;itential-iag3-dev.domain.com\u0026#34;: 10 }, \u0026#34;unique_device_count\u0026#34;: 23, \u0026#34;return_count\u0026#34;: 10, \u0026#34;start_index\u0026#34;: 0, \u0026#34;list\u0026#34;: [ { \u0026#34;user\u0026#34;: \u0026#34;username\u0026#34;, \u0026#34;port\u0026#34;: \u0026#34;22\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;************\u0026#34;, \u0026#34;ostype\u0026#34;: \u0026#34;cisco-asa\u0026#34;, \u0026#34;ipaddress\u0026#34;: \u0026#34;10.11.12.13\u0026#34;, \u0026#34;device-type\u0026#34;: \u0026#34;network_cli\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;testdevice1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;itential-iag1-dev.domain.com\u0026#34;, \u0026#34;actions\u0026#34;: [ \u0026#34;deleteDevice\u0026#34;, \u0026#34;getConfig\u0026#34;, \u0026#34;getDevice\u0026#34;, \u0026#34;getDevicesFiltered\u0026#34;, \u0026#34;getOperationalData\u0026#34;, \u0026#34;isAlive\u0026#34;, \u0026#34;loadConfig\u0026#34;, \u0026#34;restoreConfig\u0026#34;, \u0026#34;runCommand\u0026#34;, \u0026#34;setConfig\u0026#34; ], \u0026#34;origins\u0026#34;: [ \u0026#34;itential-iag1-dev.domain.com\u0026#34;, \u0026#34;itential-iag2-dev.domain.com\u0026#34; ] } ] } } ","date":"20 October 2023","permalink":"/2023/10/itential-getdevicesfiltered-api-call/","section":"Posts","summary":"The getDevicesFiltered task allows us to retrieve the inventory data for one or more configured devices in Configuration Manager. I typically use this to e.g. retrieve a list of devices of a certain OS type.","title":"Itential getDevicesFiltered API Call"},{"content":"The getJobs API endpoint/canvas task allows us to retrieve detailed job data for one or multiple jobs. It returns a staggering amount of data, and I strongly advise to use the filter options to limit both the number of results and the returned fields. Consider also using pagination (limit and skip options) when retrieving many jobs.\nThe official API documentation for this endpoint was not really clear to me and I couldn\u0026rsquo;t figure out how to set the queryParameters to get this API call to work. Luckily, the Itential Service Desk was able to get me on the right track. And I am sharing my lessons learned here.\nThe getJobs task # You can use the getJobs task, which is part of the OperationsManager tasks group in IAP Automation Builder, to retrieve data for one or multiple jobs.\nExample # The following screenshot shows an example of how to use the getJobs task. queryParameters The query parameters available for this method. queryParameters # The queryParameters determine what and how much data is returned by the getJobs API call.\nIn this example I want to retrieve ten jobs that are either in a running or paused state. I also only want four data points returned: name, last_updated, status, and created_by.\nHere is an example template you can use to send as the queryParameters object in the getJobs task:\n{ \u0026#34;limit\u0026#34;: 10, \u0026#34;order\u0026#34;: 1, \u0026#34;sort\u0026#34;: \u0026#34;last_updated\u0026#34;, \u0026#34;include\u0026#34;: \u0026#34;name,last_updated,status,created_by\u0026#34;, \u0026#34;in\u0026#34;: { \u0026#34;status\u0026#34;: \u0026#34;running,paused\u0026#34; } } limit The number of results returned. skip Number of results to skip. Used for pagination. order Sort direction, 1 for ascending and -1 for descending. sort The field to sort by. include The fields to include in the result. Comma-separated string. in Filter on one or more fields. The Object can take multiple keys. Multiple values can be joined in a comma-separated string. not-in Filter on one or more fields. Same as \u0026ldquo;in\u0026rdquo; but negated. equals Filter on one or more fields. The Object can take multiple keys. The value has to match exactly. dereference Designates foreign key fields to dereference in the API output. Check out the schema definition for more options.\nAs mentioned at the beginning, you will want to limit the amount of data returned by this API call. Make good use of the in, not-in, and equals filters and limit the returned fields using the include parameter.\nValues in the sort option must also be present in the include option. Otherwise, IAP will throw an error. Example Input/Output # Input\n{ \u0026#34;limit\u0026#34;: 10, \u0026#34;order\u0026#34;: 1, \u0026#34;sort\u0026#34;: \u0026#34;last_updated\u0026#34;, \u0026#34;include\u0026#34;: \u0026#34;name,last_updated,status,created_by\u0026#34;, \u0026#34;in\u0026#34;: { \u0026#34;status\u0026#34;: \u0026#34;error\u0026#34; } } Output (truncated)\n{ \u0026#34;result\u0026#34;: { \u0026#34;message\u0026#34;: \u0026#34;Successfully retrieved items\u0026#34;, \u0026#34;data\u0026#34;: [ { \u0026#34;_id\u0026#34;: \u0026#34;218ca51de2ee46db804708fa\u0026#34;, \u0026#34;created_by\u0026#34;: \u0026#34;616736faae58e11d5875293e\u0026#34;, \u0026#34;last_updated\u0026#34;: \u0026#34;2023-07-10T13:35:30.069Z\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;child-updateUserDatetimeTimeZone\u0026#34;, \u0026#34;encodingVersion\u0026#34;: 1, \u0026#34;status\u0026#34;: \u0026#34;error\u0026#34; } ] } Parent vs. Child Jobs # Some job entries in the API output will have a property called parent, while others don\u0026rsquo;t. This allows us to easily distinguish child jobs from parent jobs.\nIf the job has a parent property, it\u0026rsquo;s a child job. Otherwise, it\u0026rsquo;s either a parent job or simply one with no child jobs.\nLookup data using the Dereference option # The dereference option allows us to join data from another Mongo document using foreign keys.\nIn the previous example we could see that the created_by value returned by the getJobs API is just a foreign key value by default.\n\u0026ldquo;created_by\u0026rdquo;: \u0026ldquo;616736faae58e11d5875293e\u0026rdquo;\nLet\u0026rsquo;s get some user data using this foreign key. You will need to know in which Mongo collection the data behind the foreign key lives in. The created_by value corresponds to the id in accounts.\nPrefix the foreign key value with the proper collection name and add it as a string to the dereference option.\nIn our example we are joining the accounts data using the created_by key like this:\n\u0026ldquo;dereference\u0026rdquo;: \u0026ldquo;accounts.created_by\u0026rdquo;\nYou can look up multiple values by chaining them as a comma-separated string.\nBy default, this will return the all the user\u0026rsquo;s information. To limit the amount of data we join, we can specify which field(s) we want to be returned by using the include option.\nLet\u0026rsquo;s assume we only want the get the firstname value for our user from the accounts collection. So, we update our include filter as follows:\n\u0026ldquo;include\u0026rdquo;: \u0026ldquo;name,last_updated,status,created_by.firstname\u0026rdquo;\nInput\n{ \u0026#34;limit\u0026#34;: 10, \u0026#34;order\u0026#34;: 1, \u0026#34;sort\u0026#34;: \u0026#34;last_updated\u0026#34;, \u0026#34;include\u0026#34;: \u0026#34;name,last_updated,status,created_by.firstname\u0026#34;, \u0026#34;in\u0026#34;: { \u0026#34;status\u0026#34;: \u0026#34;error\u0026#34; }, \u0026#34;dereference\u0026#34;: \u0026#34;accounts.created_by\u0026#34; } Output\n{ \u0026#34;result\u0026#34;: { \u0026#34;message\u0026#34;: \u0026#34;Successfully retrieved items\u0026#34;, \u0026#34;data\u0026#34;: [ { \u0026#34;_id\u0026#34;: \u0026#34;218ca51de2ee46db804708fa\u0026#34;, \u0026#34;created_by\u0026#34;: { \u0026#34;firstname\u0026#34;: \u0026#34;Spongebob\u0026#34; }, \u0026#34;last_updated\u0026#34;: \u0026#34;2023-07-10T13:35:30.069Z\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;child-updateUserDatetimeTimeZone\u0026#34;, \u0026#34;encodingVersion\u0026#34;: 1, \u0026#34;status\u0026#34;: \u0026#34;error\u0026#34; } ] } The created_by field in the API response now shows a user object containing the first name of the user instead of a foreign key value.\n","date":"20 October 2023","permalink":"/2023/10/itential-getjobs-api-call/","section":"Posts","summary":"The getJobs API endpoint/canvas task allows us to retrieve detailed job data for one or multiple jobs. It returns a staggering amount of data, and I strongly advise to use the filter options to limit both the number of results and the returned fields.","title":"Itential getJobs API Call"},{"content":"","date":"20 October 2023","permalink":"/tags/low-code/","section":"Tags","summary":"","title":"low-code"},{"content":"","date":"20 October 2023","permalink":"/categories/network-automation/","section":"Categories","summary":"","title":"Network Automation"},{"content":"","date":"20 October 2023","permalink":"/posts/","section":"Posts","summary":"","title":"Posts"},{"content":"","date":"20 October 2023","permalink":"/tags/","section":"Tags","summary":"","title":"Tags"},{"content":"","date":"16 October 2022","permalink":"/tags/cucm/","section":"Tags","summary":"","title":"cucm"},{"content":"There may be many reasons why you would need to check which users have the home cluster enabled on a given CUCM cluster. In my personal experience, the most common reason is to troubleshoot an issue with people being unable to log into Cisco Jabber due to a “Unable to Communicate with Server” error message. Now, many things could cause issues with Jabber\u0026rsquo;s service discovery and authentication process (e.g. issues with DNS, missing discovery host records, firewalls blocking traffic, issues with the LDAP authorization, etc.). However, in my personal experience, it usually tends to be an issue with the home cluster being enabled on multiple clusters at once or the home cluster not being enabled on the target cluster.\nLuckily, it\u0026rsquo;s very straightforward to get the status of the home cluster setting (islocaluser) from the enduser table. In this example, we will also include the service profile\u0026rsquo;s name in the result. To make sure we can uniquely identify a user, we will include the username, first name, and last name, too.\nHome cluster for all users # Relevant data, attributes, tables # Tables # enduser AS eu contains information about end users ucserviceprofile AS ucp translates the ucserviceprofile integers (enums) to the human-readable service profile names Attributes # eu.userid AS id eu.firstname AS first_name eu.lastname AS last_name eu.islocaluser AS homecluster ucp.name AS serviceprofile Conditions # eu.islocaluser = 't' only include users whose Home Cluster setting (islocaluser) is enabled or true (t) Query # Use the following query to get a report of all users who have the home cluster setting enabled.\nSELECT eu.userid AS id, eu.firstname AS first_name, eu.lastname AS last_name, eu.islocaluser AS homecluster, ucp.name AS serviceprofile FROM enduser AS eu LEFT JOIN ucserviceprofile AS ucp ON ucp.pkid = eu.fkucserviceprofile WHERE eu.islocaluser = \u0026#39;t\u0026#39; ORDER BY eu.userid Return # id first_name last_name homecluster serviceprofile ========= ========== ========= =========== ============== jdoe1 Jane Doe t UCSP_STANDARD jdoe2 John Doe t UCSP_STANDARD HBarbossa Hector Barbossa t UCSP_SPECIAL ... Home cluster for a specific user # I modified the first query by adding the and eu.userid=’user1′ condition to limit our output to just the one user we want. We don’t want to pull a full report for all users; we just want a quick and easy way to verify the setting against a single problematic user.\nImportant! SQL userid search is case-sensitive by default! Relevant data, attributes, tables # Tables # enduser AS eu contains information about end users ucserviceprofile AS ucp translates the ucserviceprofile integers (enums) to the human-readable service profile names Attributes # eu.userid AS id eu.firstname AS first_name eu.lastname AS last_name eu.islocaluser AS homecluster ucp.name AS serviceprofile Conditions # eu.islocaluser = 't' only include users whose Home Cluster setting (islocaluser) is enabled or true (t) eu.userid = 'jdoe1' filter on one specific user id Query # Use the following query to get a report of all users who have the home cluster setting enabled.\nSELECT eu.userid AS id, eu.firstname AS first_name, eu.lastname AS last_name, eu.islocaluser AS homecluster, ucp.name AS serviceprofile FROM enduser AS eu LEFT JOIN ucserviceprofile AS ucp ON ucp.pkid = eu.fkucserviceprofile WHERE eu.islocaluser = \u0026#39;t\u0026#39; AND eu.userid = \u0026#39;jdoe1\u0026#39; ORDER BY eu.userid Return # id first_name last_name homecluster serviceprofile ======= ========== ========= =========== ============== jdoe1 Jane Doe t UCSP_STANDARD ... Case-insensitive query # An easy way to avoid the case sensitivity issue is to turn the userid and the search string into uppercase or lowercase before comparing them.\nSELECT eu.userid AS id, eu.firstname AS first_name, eu.lastname AS last_name, eu.islocaluser AS homecluster, ucp.name AS serviceprofile FROM enduser AS eu LEFT JOIN ucserviceprofile AS ucp ON ucp.pkid = eu.fkucserviceprofile WHERE eu.islocaluser = \u0026#39;t\u0026#39; AND UPPER(eu.userid) = UPPER(\u0026#39;hbarbossa\u0026#39;) ORDER BY eu.userid Return # id first_name last_name homecluster serviceprofile ========= ========== ========= =========== ============== HBarbossa Hector Barbossa t UCSP_SPECIAL ... ","date":"16 October 2022","permalink":"/2022/10/home-cluster-check-via-sql/","section":"Posts","summary":"There may be many reasons why you would need to check which users have the home cluster enabled on a given CUCM cluster. In my personal experience, the most common reason is to troubleshoot an issue with people being unable to log into Cisco Jabber due to a “Unable to Communicate with Server” error message.","title":"Home Cluster Check via Sql"},{"content":"","date":"16 October 2022","permalink":"/tags/sql/","section":"Tags","summary":"","title":"sql"},{"content":"","date":"16 October 2022","permalink":"/categories/unified-communications/","section":"Categories","summary":"","title":"Unified Communications"},{"content":"As with every CUCM release, some phones will not be supported anymore. For this example, let us look at how to find a list of phones on CUCM 11.X that are deprecated in release 12.X and newer.\nThe deprecated and supported phone lists are included in the 12.5 compatibility matrix. The following two queries help extract the necessary data for deprecated and unsupported device models and phone counts.\nDeprecated Phone Models # The following table lists all the phone models that are deprecated for this release of Unified Communications Manager, along with the Unified CM release where the phone model first became deprecated.\nDeprecated Phone Models for this Release First Deprecated as of Unified CM Cisco Unified Wireless IP Phone 7921\nCisco Unified IP Phone 7970\nCisco Unified IP Phone 7971 12.0(1) and later releases Cisco IP Phone 12 S\nCisco IP Phone 12 SP\nCisco IP Phone 12 SP+\nCisco IP Phone 30 SP+\nCisco IP Phone 30 VIP\nCisco Unified IP Phone 7902G\nCisco Unified IP Phone 7905G\nCisco Unified IP Phone 7910\nCisco Unified IP Phone 7910G\nCisco Unified IP Phone 7910+SW\nCisco Unified IP Phone 7910G+SW\nCisco Unified IP Phone 7912G\nCisco Unified Wireless IP Phone 7920\nCisco Unified IP Conference Station 7935 11.5(1) and later releases Relevant data, attributes, tables # Tables # device contains information about the phones typemodel translates the typemodel integers (enums) to the human-readable phone model names Attributes # typemode.name Conditions # typemodel.name in ( list of deprecated phones) Query # Use the following query to get the count for each deprecated phone model.\nSELECT COUNT(*), typemodel.name AS phonemodel FROM device INNER JOIN typemodel ON typemodel.enum = device.tkmodel WHERE typemodel.name IN ( \u0026#39;Cisco 7970\u0026#39;, \u0026#39;Cisco 7971\u0026#39;, \u0026#39;Cisco 7921\u0026#39;, \u0026#39;Cisco 12 SP+\u0026#39;, \u0026#39;Cisco 12 SP\u0026#39;, \u0026#39;Cisco 12 S\u0026#39;, \u0026#39;Cisco 30 VIP\u0026#39;, \u0026#39;Cisco 30 SP+\u0026#39;, \u0026#39;Cisco 7902\u0026#39;, \u0026#39;Cisco 7905\u0026#39;, \u0026#39;Cisco 7910\u0026#39;, \u0026#39;Cisco 7912\u0026#39;, \u0026#39;Cisco 7920\u0026#39; ) GROUP BY typemodel.name ORDER BY typemodel.name Return # The query will return a table with two columns, one containing the deprecated phone model and the other the count of how many there are in the environment.\nrun sql SELECT COUNT(*), typemodel.name as phonemodel FROM device INNER JOIN typemodel ON typemodel.enum=device.tkmodel WHERE typemodel.name in ( \u0026#39;Cisco 7970\u0026#39;, \u0026#39;Cisco 7971\u0026#39;, \u0026#39;Cisco 7921\u0026#39;, \u0026#39;Cisco 12 SP+\u0026#39;, \u0026#39;Cisco 12 SP\u0026#39;, \u0026#39;Cisco 12 S\u0026#39;, \u0026#39;Cisco 30 VIP\u0026#39;, \u0026#39;Cisco 30 SP+\u0026#39;, \u0026#39;Cisco 7902\u0026#39;, \u0026#39;Cisco 7905\u0026#39;, \u0026#39;Cisco 7910\u0026#39;, \u0026#39;Cisco 7912\u0026#39;, \u0026#39;Cisco 7920\u0026#39; ) GROUP BY typemodel.name ORDER BY typemodel.name (count(*)) phonemodel ========== ========== 7 Cisco 7921 1 Cisco 7970 ... Unsupported Phone Models # This query is much longer and lists all phone models/counts by excluding system devices, all supported models and deprecated models.\nCisco Endpoints at End of Support Cisco Unified SIP Phone 3911, 3951 Cisco Unified IP Phone 6911, 6921, 6941, 6945, 6961, 7906G, 7911G, 7931G, 7940G, 7941G, 7960G, 7961G, 8941 Cisco Unified IP Phone Expansion Module 7925G, 7925G-EX, 7926G Cisco Unified IP Conference Station 7935, 7936, 7937G Cisco TelePresence EX60 Cisco TelePresence MX200-G1, MX200-G2, MX300-G1, MX300-G2 Cisco TelePresence 500-32, 500-37, 1000 MXP, 1100, 1300-65, 1300-47, 3000 Series Relevant data, attributes, tables # Tables # device contains information about the phones typemodel translates the typemodel integers (enums) to the human-readable phone model names Attributes # typemode.name Conditions # typemodel.name NOT IN ( list of supported or deprecated phones) Query # Use the following query to get the count for each unsupported phone model.\nSELECT COUNT(*), typemodel.name AS phonemodel FROM device INNER JOIN typemodel ON typemodel.enum = device.tkmodel WHERE typemodel.name NOT IN ( \u0026#39;Cisco 3905\u0026#39;, \u0026#39;Cisco 6901\u0026#39;, \u0026#39;Cisco 7841\u0026#39;, \u0026#39;Cisco 7811\u0026#39;, \u0026#39;Cisco 7821\u0026#39;, \u0026#39;Cisco 7841\u0026#39;, \u0026#39;Cisco 7861\u0026#39;, \u0026#39;Cisco 7832\u0026#39;, \u0026#39;7915 12-Button Line Expansion Module\u0026#39;, \u0026#39;7915 24-Button Line Expansion Module\u0026#39;, \u0026#39;7916 12-Button Line Expansion Module\u0026#39;, \u0026#39;7916 24-Button Line Expansion Module\u0026#39;, \u0026#39;Cisco 7942\u0026#39;, \u0026#39;Cisco 7962\u0026#39;, \u0026#39;Cisco 7945\u0026#39;, \u0026#39;Cisco 7965\u0026#39;, \u0026#39;Cisco 8811\u0026#39;, \u0026#39;Cisco 8821\u0026#39;, \u0026#39;Cisco 8841\u0026#39;, \u0026#39;Cisco 8851\u0026#39;, \u0026#39;Cisco 8851NR\u0026#39;, \u0026#39;Cisco 8861\u0026#39;, \u0026#39;Cisco 8831\u0026#39;, \u0026#39;Cisco 8845\u0026#39;, \u0026#39;Cisco 8865\u0026#39;, \u0026#39;Cisco 8865NR\u0026#39;, \u0026#39;Cisco 8832\u0026#39;, \u0026#39;Cisco 8945\u0026#39;, \u0026#39;Cisco 8961\u0026#39;, \u0026#39;Cisco 9951\u0026#39;, \u0026#39;Cisco 9971\u0026#39;, \u0026#39;Cisco Dual Mode for Android\u0026#39;, \u0026#39;Cisco Dual Mode for iPhone\u0026#39;, \u0026#39;Cisco Jabber for Tablet\u0026#39;, \u0026#39;Cisco Jabber for Mac\u0026#39;, \u0026#39;Cisco Unified Client Services Framework\u0026#39;, \u0026#39;Cisco IP Communicator\u0026#39;, \u0026#39;Cisco ATA 190\u0026#39;, \u0026#39;Cisco ATA 191\u0026#39;, \u0026#39;Cisco DX650\u0026#39;, \u0026#39;Cisco DX70\u0026#39;, \u0026#39;Cisco DX80\u0026#39;, \u0026#39;Cisco TelePresence IX5000\u0026#39;, \u0026#39;Cisco TelePresence EX60\u0026#39;, \u0026#39;Cisco TelePresence EX90\u0026#39;, \u0026#39;Cisco TelePresence MX200 G2\u0026#39;, \u0026#39;Cisco TelePresence MX300 G2\u0026#39;, \u0026#39;Cisco TelePresence MX700\u0026#39;, \u0026#39;Cisco TelePresence MX800\u0026#39;, \u0026#39;Cisco TelePresence MX800 Dual\u0026#39;, \u0026#39;Cisco TelePresence SX10\u0026#39;, \u0026#39;Cisco TelePresence SX20\u0026#39;, \u0026#39;Cisco TelePresence SX80\u0026#39;, \u0026#39;Cisco Webex DX80\u0026#39; ) AND typemodel.name NOT IN ( \u0026#39;Analog Phone\u0026#39;, \u0026#39;Cisco VGC Phone\u0026#39;, \u0026#39;Cisco IOS Conference Bridge (HDV2)\u0026#39;, \u0026#39;MGCP Trunk\u0026#39;, \u0026#39;CTI Port\u0026#39;, \u0026#39;Conference Bridge\u0026#39;, \u0026#39;Media Termination Point\u0026#39;, \u0026#39;Interactive Voice Response\u0026#39;, \u0026#39;Cisco IOS Media Termination Point (HDV2)\u0026#39;, \u0026#39;Third-party SIP Device (Advanced)\u0026#39;, \u0026#39;Third-party SIP Device (Basic)\u0026#39;, \u0026#39;Tone Announcement Player\u0026#39;, \u0026#39;SIP Trunk\u0026#39;, \u0026#39;Universal Device Template\u0026#39;, \u0026#39;Voice Mail Port\u0026#39;, \u0026#39;MGCP Station\u0026#39;, \u0026#39;Music On Hold\u0026#39;, \u0026#39;CTI Route Point\u0026#39;, \u0026#39;Remote Destination Profile\u0026#39;, \u0026#39;Cisco IOS Software Media Termination Point (HDV2)\u0026#39;, \u0026#39;SCCP gateway virtual phone\u0026#39;, \u0026#39;Route List\u0026#39;, \u0026#39;Cisco TelePresence Conductor\u0026#39;, \u0026#39;Gatekeeper\u0026#39; ) AND typemodel.name NOT IN ( \u0026#39;Cisco 7970\u0026#39;, \u0026#39;Cisco 7971\u0026#39;, \u0026#39;Cisco 7921\u0026#39;, \u0026#39;Cisco 12 SP+\u0026#39;, \u0026#39;Cisco 12 SP\u0026#39;, \u0026#39;Cisco 12 S\u0026#39;, \u0026#39;Cisco 30 VIP\u0026#39;, \u0026#39;Cisco 30 SP+\u0026#39;, \u0026#39;Cisco 7902\u0026#39;, \u0026#39;Cisco 7905\u0026#39;, \u0026#39;Cisco 7910\u0026#39;, \u0026#39;Cisco 7912\u0026#39;, \u0026#39;Cisco 7920\u0026#39; ) GROUP BY typemodel.name ORDER BY typemodel.name Return # The query will return a table with two columns, one containing the unsupported phone model and the other the count of how many there are in the environment.\nrun sql SELECT COUNT(*), typemodel.name AS phonemodel FROM device INNER JOIN typemodel ON typemodel.enum = device.tkmodel WHERE typemodel.name NOT IN (\u0026#39;Cisco 3905\u0026#39;, \u0026#39;Cisco 6901\u0026#39;, \u0026#39;Cisco 7841\u0026#39;, \u0026#39;Cisco 7811\u0026#39;, \u0026#39;Cisco 7821\u0026#39;, \u0026#39;Cisco 7841\u0026#39;, \u0026#39;Cisco 7861\u0026#39;, \u0026#39;Cisco 7832\u0026#39;, \u0026#39;7915 12-Button Line Expansion Module\u0026#39;, \u0026#39;7915 24-Button Line Expansion Module\u0026#39;, \u0026#39;7916 12-Button Line Expansion Module\u0026#39;, \u0026#39;7916 24-Button Line Expansion Module\u0026#39;, \u0026#39;Cisco 7942\u0026#39;, \u0026#39;Cisco 7962\u0026#39;, \u0026#39;Cisco 7945\u0026#39;, \u0026#39;Cisco 7965\u0026#39;, \u0026#39;Cisco 8811\u0026#39;, \u0026#39;Cisco 8821\u0026#39;, \u0026#39;Cisco 8841\u0026#39;, \u0026#39;Cisco 8851\u0026#39;, \u0026#39;Cisco 8851NR\u0026#39;, \u0026#39;Cisco 8861\u0026#39;, \u0026#39;Cisco 8831\u0026#39;, \u0026#39;Cisco 8845\u0026#39;, \u0026#39;Cisco 8865\u0026#39;, \u0026#39;Cisco 8865NR\u0026#39;, \u0026#39;Cisco 8832\u0026#39;, \u0026#39;Cisco 8945\u0026#39;, \u0026#39;Cisco 8961\u0026#39;, \u0026#39;Cisco 9951\u0026#39;, \u0026#39;Cisco 9971\u0026#39;, \u0026#39;Cisco Dual Mode for Android\u0026#39;, \u0026#39;Cisco Dual Mode for iPhone\u0026#39;, \u0026#39;Cisco Jabber for Tablet\u0026#39;, \u0026#39;Cisco Jabber for Mac\u0026#39;, \u0026#39;Cisco Unified Client Services Framework\u0026#39;, \u0026#39;Cisco IP Communicator\u0026#39;, \u0026#39;Cisco ATA 190\u0026#39;, \u0026#39;Cisco ATA 191\u0026#39;, \u0026#39;Cisco DX650\u0026#39;, \u0026#39;Cisco DX70\u0026#39;, \u0026#39;Cisco DX80\u0026#39;, \u0026#39;Cisco TelePresence IX5000\u0026#39;, \u0026#39;Cisco TelePresence EX60\u0026#39;, \u0026#39;Cisco TelePresence EX90\u0026#39;, \u0026#39;Cisco TelePresence MX200 G2\u0026#39;, \u0026#39;Cisco TelePresence MX300 G2\u0026#39;, \u0026#39;Cisco TelePresence MX700\u0026#39;, \u0026#39;Cisco TelePresence MX800\u0026#39;, \u0026#39;Cisco TelePresence MX800 Dual\u0026#39;, \u0026#39;Cisco TelePresence SX10\u0026#39;, \u0026#39;Cisco TelePresence SX20\u0026#39;, \u0026#39;Cisco TelePresence SX80\u0026#39;, \u0026#39;Cisco Webex DX80\u0026#39;) AND typemodel.name NOT IN (\u0026#39;Analog Phone\u0026#39;, \u0026#39;Cisco VGC Phone\u0026#39;, \u0026#39;Cisco IOS Conference Bridge (HDV2)\u0026#39;, \u0026#39;MGCP Trunk\u0026#39;, \u0026#39;CTI Port\u0026#39;, \u0026#39;Conference Bridge\u0026#39;, \u0026#39;Media Termination Point\u0026#39;, \u0026#39;Interactive Voice Response\u0026#39;, \u0026#39;Cisco IOS Media Termination Point (HDV2)\u0026#39;, \u0026#39;Third-party SIP Device (Advanced)\u0026#39;, \u0026#39;Third-party SIP Device (Basic)\u0026#39;, \u0026#39;Tone Announcement Player\u0026#39;, \u0026#39;SIP Trunk\u0026#39;, \u0026#39;Universal Device Template\u0026#39;, \u0026#39;Voice Mail Port\u0026#39;, \u0026#39;MGCP Station\u0026#39;, \u0026#39;Music On Hold\u0026#39;, \u0026#39;CTI Route Point\u0026#39;, \u0026#39;Remote Destination Profile\u0026#39;, \u0026#39;Cisco IOS Software Media Termination Point (HDV2)\u0026#39;, \u0026#39;SCCP gateway virtual phone\u0026#39;, \u0026#39;Route List\u0026#39;, \u0026#39;Cisco TelePresence Conductor\u0026#39;, \u0026#39;Gatekeeper\u0026#39;) AND typemodel.name NOT IN (\u0026#39;Cisco 7970\u0026#39;, \u0026#39;Cisco 7971\u0026#39;, \u0026#39;Cisco 7921\u0026#39;, \u0026#39;Cisco 12 SP+\u0026#39;, \u0026#39;Cisco 12 SP\u0026#39;, \u0026#39;Cisco 12 S\u0026#39;, \u0026#39;Cisco 30 VIP\u0026#39;, \u0026#39;Cisco 30 SP+\u0026#39;, \u0026#39;Cisco 7902\u0026#39;, \u0026#39;Cisco 7905\u0026#39;, \u0026#39;Cisco 7910\u0026#39;, \u0026#39;Cisco 7912\u0026#39;, \u0026#39;Cisco 7920\u0026#39;) GROUP BY typemodel.name ORDER BY typemodel.name (count(*)) phonemodel ========== ==================== 16 Cisco 6921 1 Cisco 6941 1 Cisco 7936 54 Cisco 7937 1 Cisco 7941 1 Cisco 7960 735 Cisco 8941 1 Cisco ATA 186 3 Cisco ATA 187 ... ","date":"15 October 2022","permalink":"/2022/10/find-deprecated-phones-via-sql/","section":"Posts","summary":"As with every CUCM release, some phones will not be supported anymore. For this example, let us look at how to find a list of phones on CUCM 11.X that are deprecated in release 12.","title":"Find Deprecated Phones via SQL"},{"content":"Cisco Unified Communications Manager uses an Informix database for data storage. Accessing this data directly using SQL queries to create custom reports or gather data for analysis has often come in handy. These days I work primarily with the SOAP API, and depending on the information I\u0026rsquo;m looking for, sending SQL queries via Thin AXL is sometimes more efficient.\nThis article aims to give you a quick introduction to the CUCM database. You don\u0026rsquo;t need to know anything about Informix. Still, a basic understanding of relational databases, some basic SQL and an offline copy of Cisco\u0026rsquo;s Data Dictionary will help you with creating any kinds of queries you might need.\nIntro # There are three main categories of tables in the CUCM Informix database - \u0026lsquo;main\u0026rsquo; as in most-used; system tables, mapping tables, and enumeration tables. Then there are dynamic tables and configuration tables.\nSystem tables Regular tables containing data for a particular CUCM configuration object like devices, devicepools, end users, partitions, etc. Mapping tables Mapping primary keys/unique identifiers of one table to those of another. E.g. the DeviceNumPlanMap maps phones (device table) to directory numbers (numplan table). Type tables Used by other tables to resolve enumerator IDs to some name or moniker. E.g. contains the human-readable phone model name to the numeric tkmodel value of a phone in the device table. This table is static and cannot be altered. Both standard tables and mapping tables use primary keys called pkid, whereas type tables use primary keys called enum.\nThe foreign keys used to link fields in one table with another table or another record within the same table follow a specific naming convention:\npkid this is the primary key ID. fk(x) This is a foreign key (unique value) in another table. That table will be named (x), and the foreign key field will always be pkid. fk(x)_(y) This is a foreign key (unique value) in another table. The table will be named (x), and the \u0026ldquo;_(y)\u0026rdquo; is a descriptor which usually indicates that in a given record, there is more than one field pointing to the same foreign table. tk(x) This is a type key (enumerator) in another table. The table will be named type(x), and the foreign key will always be an enum. ik(x) Fields that begin with the letters \u0026ldquo;ik\u0026rdquo; represent internal keys in the same table. The table will be named (x). Show all tables in the database # To navigate the database and understand what tables and data are available to us, we need to identify the tables by name and id. The table IDs between 1 and 100 are used for system information. Table IDs over 1000 are where CUCM stores CDR information.\nSELECT tabname, tabid FROM systables or\nSELECT tabname, tabid FROM systables WHERE tabid \u0026gt; 100 AND tabid \u0026lt; 1000 Output:\nrun sql SELECT tabname,tabid FROM systables WHERE tabid \u0026gt; 100 AND tabid \u0026lt; 1000 tabname tabid ================================ ===== dblschemaorder 101 aarneighborhood 102 aardialprefixmatrix 103 alarmusertext 104 availdialplan 105 axlchangenotifyclient 106 carrierselectprofile 107 ccaprofile 108 ccdhosteddngroup 109 ccdhosteddn 110 cdrmconfig 111 cmcinfo 112 codeclist 113 confidentialaccesslevel 114 ... Show all columns of a specific table # The first step is to identify the tabid of, e.g. the device table. We know from the previous example that we can get the tabid from systables.\nSELECT tabname, tabid FROM systables WHERE tabname = \u0026#34;device\u0026#34; Output:\nrun sql SELECT tabname,tabid FROM systables WHERE tabname=\u0026#34;device\u0026#34; tabname tabid ======= ===== device 753 Using the tabid, we can now get the colname and colno values from syscolumns.\nSELECT colname, colno FROM syscolumns WHERE tabid = \u0026#34;753\u0026#34; Output:\nrun sql SELECT colname, colno FROM syscolumns WHERE tabid=\u0026#34;753\u0026#34; colname tabid colno ===================================== ===== ===== pkid 753 1 name 753 2 description 753 3 tkmodel 753 4 tkdeviceprotocol 753 5 tkprotocolside 753 6 specialloadinformation 753 7 fkdevicepool 753 8 fkphonetemplate 753 9 fkcallingsearchspace 753 10 ctiid 753 11 tkclass 753 12 fkprocessnode 753 13 defaultdtmfcapability 753 14 fklocation 753 15 ... Or combine the two queries into one.\nSELECT c.colname, t.tabid, c.colno FROM systables AS t, syscolumns AS c WHERE t.tabname = \u0026#34;device\u0026#34; AND t.tabid = c.tabid Cisco Resources # Cisco created Data Dictionaries for all CUCM releases. The Data Dictionary describes the data stored in the database in meticulous detail; every table, field, element, data type, and relationship.\nThe Cisco AXL documentation archive https://developer.cisco.com/docs/axl/#!archived-references contains CUCM Data Dictionaries for all releases since 7.1(3).\n","date":"7 October 2022","permalink":"/2022/10/working-with-the-cucm-database/","section":"Posts","summary":"Cisco Unified Communications Manager uses an Informix database for data storage. Accessing this data directly using SQL queries to create custom reports or gather data for analysis has often come in handy.","title":"Working With The CUCM Database"},{"content":"Well, thanks for the interest, truly, but if you are here, we are much alike or have similar interests. So, no big surprises here.\nI’m John, and I’ve worked as both a network and voice (UC) engineer my entire career and always for large(r) multinational enterprises. I decided to move into the network automation space a few years ago. So, I started by learning some Python and scripting some of my daily tasks, mainly using Paramiko and Netmiko, instead of doing them manually. I also got the Cisco DevNet Associate cert and am working now on the DevNet Professional cert - because it’s always good to have some certs. There is a lot to learn still.\nSo, why this blog, then? Fair question. I guess I just want to share. Many times in my career, I was stuck with a problem, hitting a wall, and then stumbled upon a blog entry of a fellow engineer facing the same challenge and decided to share the solution, saving me from many headaches. I hope the information I share on this website will be helpful to someone else out there on the interwebs and protect them from unnecessary headaches, too.\n","date":"3 October 2022","permalink":"/about/","section":"Awetomate","summary":"Well, thanks for the interest, truly, but if you are here, we are much alike or have similar interests. So, no big surprises here.\nI’m John, and I’ve worked as both a network and voice (UC) engineer my entire career and always for large(r) multinational enterprises.","title":"About"},{"content":"You can change archives page details above.\nKeep this file saft to ensure Hugo generate the archives page.\n","date":"1 January 0001","permalink":"/archives/","section":"Archives","summary":"You can change archives page details above.\nKeep this file saft to ensure Hugo generate the archives page.","title":"Archives"},{"content":"","date":"1 January 0001","permalink":"/authors/","section":"Authors","summary":"","title":"Authors"},{"content":"You can change search page details above.\nKeep this file saft to ensure Hugo generate the search page.\n","date":"1 January 0001","permalink":"/search/","section":"Search","summary":"You can change search page details above.\nKeep this file saft to ensure Hugo generate the search page.","title":"Search"},{"content":"","date":"1 January 0001","permalink":"/series/","section":"Series","summary":"","title":"Series"}]