Throughout today’s Cisco Spark launch, I couldn’t help but to think I was watching not a Cisco event, but an Apple one. Most of the event surrounded the new Spark Board, which itself sounded again like Apple when it was described as “Scandinavian minimalist design meets California approachability.”

The entire Mantra of the Spark Board was nothing new on the surface: zero cables, digital whiteboard, video conferencing unit; but taking an existing idea and executing it better than anyone else has worked before, for you guessed it: Apple.

My favorite takeaway from the launch event was just how relevant Jonathon Rosenberg spoke about the problem with today’s workflow. While I was watching the event in fact, I was in a scheduled WebEx meeting to talk about something that very well could have been handled “offline.” I’ve always been vocal on how frustrating it is asking someone to be 100% engaged when they don’t need to be, but had a hard time putting it into words. It’s neither efficient nor fair for the employee and certainly not for the customer!

We no longer work 8am to 5pm weekdays behind a desktop with 100% engagement. We work various times with varying levels of engagement. We can work in line at the grocery store from mobile devices now. Spark is OK with this.

Jonathon Rosenberg put the problem of meetings into time vs. engagement, and correlated these into the 4 categories below, which prior to Spark meant you had to use 4 different applications, each functional in some ways and lacking in others.

The first big industry disrupter to come along in this new market space was Slack, which had persistent chat, it was teams-based, and has a ton of APIs to integrate with other applications. Slack took the place of email in most cases and the need for a meeting for some others – however it was lacking the vision of an all-in-one application Rowan and team had for Spark. Not only does Spark aim to replace email, but its also a video phone, whiteboard, meeting space. It’s persistent and teams based with APIs but it also has the Spark cloud with an IVR builder. I can’t wait to see what comes next with their recent Worklife acquisition. Ahem: Cisco Spark Meeting Notes

Cisco Spark – https://www.ciscospark.com

Cisco Spark Board – https://www.ciscospark.com/products/spark-board.html

Another word I’ve heard buzzing around lately, microservices works to brings cloud and containers a step further and modularizes the application into smaller function-specific mini applications that work together through APIs. With this approach, the elasticity of the cloud is tuned to the needs of the subscribers, and the business only pays for the network and compute resources they need on a more granular level. The early adopters at this point are the usual suspects: Airbnb, Uber and Netflix.

“the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.”

Principals of Microservices (PPT)

Cisco’s APIC-EM, or Application Policy Infrastructure Controller Enterprise Module is an OpenDayLight based SDN (Software Defined Network) controller. You could also possibly call it Cisco’s attempt to Merakify the Enterprise. On the bright side, it’s a free virtual appliance and no license is required.

One of the biggest features of APIC-EM is called Network Plug and Play

At a high level, the Cisco switch or router talks to the APIC-EM to streamline workflows and automate deployments. Switches and routers, known as agents discover the controller using any of the following mechanisms in order:

dhcp option 43 or dns (below), usb key, cloud discovery (currently beta), or the smartphone app.

DHCP

option 43 ascii "5A1N;B2;K4;I172.19.45.222;J80"

The option 43 string has the following components, delimited by semicolons:

  • 5A1N;—Specifies the DHCP suboption for Plug and Play, active operation, version 1, no debug information. It is not necessary to change this part of the string.
  • B2;—IP address type:
    • B1 = hostname
    • B2 = IPv4 (default)
  • Ixxx.xxx.xxx.xxx ;—IP address or hostname of the APIC-EM controller (following a capital letter i). In this example, the IP address is 172.19.45.222.
  • Jxxxx —Port number to use to connect to the APIC-EM controller. In this example, the port number is 80. The default is port 80 for HTTP and port 443 for HTTPS.
  • K4;—Transport protocol to be used between the Cisco Plug and Play IOS Agent and the server:
    • K4 = HTTP (default)
    • K5 = HTTPS

DNS

APIC-EM: pnpserver.<customerdomain>.com
NTP Server: pnpntpserver.<customerdomain>.com

The DHCP pool will need to either be on vlan 1, or you’ll need to specify a staging vlan on the upstream switch:

pnp startup-vlan 55

That brings me to another caveat of of Plug and Play is that the firmware needs to be supported, and may not match the shipping version of the hardware!

Another feature of APIC-EM is called Easy QoS

I actually really like this use-case for network programmability. It’s important for the policies to match end-to-end in QoS, so being able to roll out policies and get insights into your policy-maps holistically is kind of a big deal.

APIC-EM documentation gives the concept of Northbound, which is the REST API you can use for custom applications, and Southbound in which APIC-EM talks to hardware using SNMP and CLI. Cisco states “future APIC-EM releases will leverage other southbound technology such as NetConf as they become available”.

I found some Postman collections from CiscoDevNet’s Github page here. Postman collections are a great way to learn by doing.

APIC-EM Firmware Compatibility

Official Getting Started Guide

When you change your dogs food, they get sick all over the place, they just can’t stomach change. As an IT professional, the dog food we know and love changes frequently.. The technology you spent all that time learning about last year is obsolete.

Don’t get mad, adapt! As a collaboration engineer, my title didn’t exist 20 years ago. During the TDM to VoIP migration, analog teleco guys were forced to adapt or find new work. When virtualization came on the map, the ability for one person to manage hundreds of servers meant that the early adopters got a new title and quite possibly a pay raise, while the ones late to the game found themselves no longer needed.

This blog is adapting, too. Let me throw out a few buzzwords: API, IoT, REST. Knowing what they mean and why they are important might save you from being the next casualty of change. It’s about asking more from technology. People don’t expect their GPS to just give them directions anymore. They want voice navigation with social networking that tells you where the cops are hiding, and they want it to predict when you’re leaving to go to work and tell you how to traffic is. From a development perspective, the GPS apps with the most APIs get the most love, and almost everything is OPEN, meaning you or I could “tap” into that technology, helping both parties.

I recently gave a presentation on coding along with the CTO of the company, Vinu Thomas. One of the points he made that really stuck was this: try to automate your own job. If you’re smart enough to do that, I promise you’ll be just fine.

I started asking during phone migrations: why do I have to tell the router what the new phone’s mac address is, if the switch already knows? Why can’t the switch and the router work this out between themselves ? Why do call center agents have to login to their phone every day if they also login to their computers ? I think we’re almost there, if not already. Both of these use cases: extension mobility and ios-xe have APIs. So do yourself a favor, hang in there, and learn Python.. or Ruby or my favorite: Node.js

#1 – request

Request is the easiest way to make REST calls. It runs server-side to hide your token and if you use Postman to test the HTTP request, it can even generate the code for you!
https://www.npmjs.com/package/request

Example Request Using Spark Messages API:

var request = require(‘request’);
var req = {
  auth: { bearer: ‘sparkTokenHere’ },
  url: ‘https://api.ciscospark.com/v1/messages’,
  json: true,
  body: {
    ‘roomId’: roomId,
    ‘text’: message
    }
};//end setup

request.post(req, function(err, res) {
if(err) {
console.log(err);
} else {
  }
});//end rest call


#2 – picker

Picker is a server side router for Meteor that works alongside middleware to easily provide an API or webhook into your application.
https://atmospherejs.com/meteorhacks/picker

Example Webhook with JSON parsing using body-parser:

Picker.middleware(bodyParser.json());
Picker.middleware(bodyParser.urlencoded({extended: false}));
Picker.route(‘/myWebhook’, function(params, request, response) {
  personEmail = (request.body.data.personEmail);
  msgid = (request.body.data.id);


#3 – Q

Before getting too far ahead with node.js, you’ll need to grasp the underlying language, javascript. Javascript is a synchronous language, meaning it runs functions all at the same time, which can make a mess of things if you don’t use callbacks properly. Q uses something called promises to run things asynchronously in the order you tell it. To learn more about callbacks and why this package is so necessary, check out callbackhell.com
http://documentup.com/kriskowal/q/

Example of promises with Q:

Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
})
.done();


#4 – bert

Bert makes notifications simple
https://github.com/themeteorchef/bert

Bert.alert({
  title: ‘Conference Now’,
  message: ‘Connecting to Tropo…’,
  type: ‘info’,
  style: ‘growl-bottom-right’,
  icon: ‘fa-phone’
});


#5 – fontawesome

fontawesome is a collection of 675 icons in unicode that can be embedded in your site with a single tag. Most people will use their built in CDN (content delivery network) to make deployment even easier.
http://fontawesome.io/icons/

<i class=fa fa-camera-retro”></i>


#6 – nodemailer

nodemailer is the best email package hands down. It supports an html body and allows you to specify options within the app.
https://www.npmjs.com/package/nodemailer

var nodemailer = require(‘nodemailer’);

// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport(‘smtps://user%40gmail.com:pass@smtp.gmail.com:587’);

// setup e-mail data with unicode symbols
var mailOptions = {
  from: ‘”Fred Foo 👥” <foo@blurdybloop.com>’, // sender address
  to: ‘bar@blurdybloop.com, baz@blurdybloop.com’, // list of receivers
  subject: ‘Hello ✔’, // Subject line
  text: ‘Hello world 🐴’, // plaintext body
  html: ‘Hello world 🐴‘ // html body
};

// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
  if(error){
  return console.log(error);
  }
console.log(‘Message sent: ‘ + info.response);
});


#7 – validator

Need to check if an email is actually an email? A dollar amount is actually a dollar amount? Validator has a ton of built-in methods to check for you.
https://www.npmjs.com/package/validator

var validator = require(‘validator’);
validator.isEmail(‘foo@bar.com’); //=> true


#8 – csv

While ECMA 5 has native XML and JSON support, a lot of Cisco applications still rely on CSV (comma seperated values). This package aims to bridge the gap.
https://www.npmjs.com/package/csv

var csv = require(‘csv’);
csv.parse(data, function(err, data){
  csv.stringify(data, function(err, data){
  process.stdout.write(data);
  });
});


#9 – bootstrap

Boostrap is so useful, I wish it was just included in HTML period. Any buttons, menus, fonts, tables, grids, layouts, etc. are super easy with Bootstrap.
https://www.npmjs.com/package/bootstrap

Just include the bootstrap code below to utilize their CDN:

<!– Latest compiled and minified CSS –>
<link rel=”stylesheet” href=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css” integrity=”sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u” crossorigin=”anonymous”>

<!– Latest compiled and minified JavaScript –>
<script src=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js” integrity=”sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa” crossorigin=”anonymous”></script>


#10 – jsPDF

PDFs are still the industry standard for “digital hard copies” of documents. jsPDF makes generating PDFs easy.
https://parall.ax/products/jspdf

<script src=”https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.debug.js”></script>
var pdf = new jsPDF();
pdf.text(30, 30, ‘Hello world!’);
pdf.save(‘hello_world.pdf’);

I did a post not too long ago on the vlookup function and how it can be used to extract data by matching on a row and returning data x number of columns away. The same exists using the hlookup command to match on a column and return data x number of rows away.

HLOOKUP(lookup_value, table_array, row_index_num, [range_lookup])

The use case for this is simple: you’re doing a parallel upgrade of Call Manager using the import/export method and you want to copy over all the tables that exist in the old database, but if they don’t exist, you still need the table headers. To do this you’ll need the old phone.csv and a blank export of the new phone.csv side by side.

You’ll paste this on the new phone.csv in A2 and drag to the right and down to populate the database.

=hlookup(a$1,(old-phone!$a$1:$dyt$5000),(row(a2)),false)

When you’re done you should copy all values to a new sheet to clean up any #N/A values it may create and thats your new phone.csv

A lot of apartment buildings have callboxes that will dial a tenant and allow the tenant to open the door by pressing a key sequence. I have had to use this to call myself before when I left my keys upstairs, or that time I lost my keys for a week (but thats another story). So what happens if you don’t have your phone or your keys? Or what about when you have guests that arrive early and you’re still in the shower, getting ready or can’t get to your phone in time?

In this example, the callbox dials Tropo instead of your phone, uses the built-in IVR to ask for a password. If the password is correct, it dials the dtmf digits to open the door and sends a text message to your phone alerting you of company.

var
result = ask(“The password is?”, {
choices: “sausages”
});
if(result.value == “sausages”){
say(“that is correct”);
say(“https://evolution.voxeo.com/library/audio/prompts/dtmf/Dtmf-9.wav”);
message(“A Guest has Arrived”, {
to:”+19192223323″,
network:”SMS”
});
}
else{
say(“there is a nice bench outside for you to sleep on”);
}

I recently posted about the Jabber Problem Report Tool and the csf-unified.log that turned out to be one of my most popular posts. I had some feedback asking for more info on specific troubleshooting after home cluster is found, so here it is.

Service Discovery Failure Codes (csf-unified.log)

IDNameUI MessageDescription
1001ServiceDiscoveryFailureFailed to discover network servicesUnknown discovery failure
1002ServiceDiscoveryAuthenticationFailureYour username or password is not correct.Failed to authenticate with CUCM (9.0+)
1003ServiceDiscoveryCannotConnectToCucmServerCannot communicate with the server. Cannot connect to CUCM (9.0+)
1004ServiceDiscoveryNoCucmConfigurationFailed to discover network services.CUCM server is misconfigured
1005ServiceDiscoveryNoSRVRecordsFoundFailed to discover network services.No SRV records are found
1006ServiceDiscoveryCannotConnectToEdgeCannot communicate with the serverCannot connect to EDGE server
1007ServiceDiscoveryNoNetworkConnectivityCannot communicate with the serverNo network connectivity

Service Discovery Cache File (service-location.xml)

Located in %appdata%\Cisco\Unified Communications\Jabber\CSF\Config

<?xml version=”1.0″?>
<UCServices>
<DomainName>pnslabs.com</DomainName>
<UCService>
<type>CUCM</type>
<connectionInformation>
<name>_cisco-uds</name>
<scope>UNKNOWN</scope>
<address>cucm.pnslabs.com</address>
<protocol>_tcp</protocol>
<port>8443</port>
</connectionInformation>
</UCService>
</UCServices>

IMS Result Codes

Client Profile Agent Logs pulled from IM&P Server EPASSoapXXXXX.log

IMS Result CodeDescription
0Success
1Wrong credentials
2Administratively Locked
3Hack Locked
7End User status inactive in LDAP

Anyone who has deployed Jabber knows of the cisco-uds SRV record that Jabber uses (or Expressway-C in the case of MRA) to discover it’s services. It’s also used for directory searches, and home cluster lookup with ILS.

UDS or User Data Services is a simple REST based API for CUCM. While the UDS API is not as extensive as what you can do with AXL through SOAP and WSDL, it makes a great use case for a front end to allow end users to manage their own devices: Change their single number reach destination, password, speed dials, and conference pins.

For security reasons, most browsers will block an XMLHttpRequest served on one page and originating on another (in the case of a front end making UDS calls to CUCM). To get around this, you would use CORS or Cross Origin Resource Sharing, defining the front end URL inside CUCM.

UDS supports REST queries POST/PUT/GET/DELETE in XML format. Some calls do not require authentication and some do. Ones that do will use Basic authentication built into the browser which encodes the username:password in Base64 format.

UDS resources that do not require authentication
clusterUser, installedLocales, models, options, phoneService(s), servers, timezones, users, version

GET https://{host}:8443/cucm-uds/users?last=Smit
GET https://{host}:8443/cucm-uds/clusterUser?username={userId}

UDS resources that require authentication
credentials, device(s), extension(s), remoteDestination(s), speedDial(s), subscribedService(s), user, userPolicy

POST https:­//{host}:8443/cucm-uds/user/{userId}/speedDials
<!–add speedDials example request body–>
<speedDials>
<speedDial>
<index>1</index>
<number>1234567890</number>
<label>Manager</label>
</speedDial>
<speedDial>
<index>2</index>
<number>1234567899</number>
<label>Assistant</label>
</speedDial>
</speedDials>

CUCM UDS API Reference
CUCM UDS Developer Guide
CUCM UDS Authentication Guide
Base64 Encoder/Decoder