Repository: F5Networks/f5-common-python

Issue:
Add license installation
Add license installation command similar to the revoking the license: 

Code snippet for the revoking the license:
```python
mgnt = ManagementRoot(bigip_mgnt, user, pass)
mgnt.tm.sys.license.exec_cmd('revoke')`
```
Code snippet for the license installation:
```python
mgnt = ManagementRoot(bigip_mgnt, user, pass)
mgnt.tm.sys.license.exec_cmd('install', registrationKey=regkey)
```

Discussion:
jasonrahm: @drenout can you change your two append lines to this line instead:

`self._meta_data['allowed_commands'].extend(['revoke', 'install'])`

Patch:
diff --git a/f5/bigip/tm/sys/license.py b/f5/bigip/tm/sys/license.py
index df150f9..c38d3d4 100644
--- a/f5/bigip/tm/sys/license.py
+++ b/f5/bigip/tm/sys/license.py
@@ -41,7 +41,7 @@ class License(UnnamedResource, CommandExecutionMixin):
         super(License, self).__init__(sys)
         self._meta_data['required_json_kind'] =\
             "tm:sys:license:licensestats"
-        self._meta_data['allowed_commands'].append('revoke')
+        self._meta_data['allowed_commands'].extend(['revoke', 'install'])
 
     def exec_cmd(self, command, **kwargs):
         self._is_allowed_command(command)


Test patch:
diff --git a/f5/bigip/tm/sys/test/unit/test_license.py b/f5/bigip/tm/sys/test/unit/test_license.py
index 617edf2..27222bc 100644
--- a/f5/bigip/tm/sys/test/unit/test_license.py
+++ b/f5/bigip/tm/sys/test/unit/test_license.py
@@ -37,3 +37,17 @@ def test_delete_raises(FakeLicense):
     with pytest.raises(UnsupportedMethod) as EIO:
         FakeLicense.delete()
     assert str(EIO.value) == "License does not support the delete method"
+
+
+def test_exec_install(FakeLicense):
+    assert "install" in FakeLicense._meta_data['allowed_commands']
+    FakeLicense._meta_data['bigip']._meta_data.__getitem__.return_value = "14.0.0"
+    FakeLicense._exec_cmd = mock.MagicMock()
+    version_dict = {"13.1.0": 13, "14.0.0": 14}
+
+    def get_version(version):
+        return version_dict[version]
+
+    License.LooseVersion = mock.MagicMock(side_effect=get_version)
+    FakeLicense.exec_cmd("install", registrationKey='1234-56789-0')
+    FakeLicense._exec_cmd.assert_called_with("install", registrationKey='1234-56789-0')