initial commit

This commit is contained in:
John Bowdre 2021-01-11 17:14:27 -06:00
commit 7b8065c9de
1781 changed files with 274682 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"python.pythonPath": "venv_tango/bin/python"
}

23
Dockerfile Normal file
View File

@ -0,0 +1,23 @@
FROM photon:3.0-20200609
ADD target/python /ipam/python
RUN tdnf install -y python3-pip.noarch python3-devel gcc glibc-devel binutils linux-api-headers shadow && \
pip3 install --upgrade pip setuptools && \
pip3 install certifi && \
tdnf clean all && \
rm -fr /var/cache/tdnf/*
RUN pip3 install -r /ipam/python/allocate_ip/requirements.txt --target=/ipam/python/allocate_ip
RUN pip3 install -r /ipam/python/deallocate_ip/requirements.txt --target=/ipam/python/deallocate_ip
RUN pip3 install -r /ipam/python/get_ip_ranges/requirements.txt --target=/ipam/python/get_ip_ranges
RUN pip3 install -r /ipam/python/validate_endpoint/requirements.txt --target=/ipam/python/validate_endpoint
RUN if [ "@provider.supportsUpdateRecord@" = "true" ] ; then pip3 install -r /ipam/python/update_record/requirements.txt --target=/ipam/python/update_record ; fi
RUN if [ "@provider.supportsOnDemandNetworks@" = "true" ] ; then pip3 install -r /ipam/python/get_ip_blocks/requirements.txt --target=/ipam/python/get_ip_blocks ; fi
RUN if [ "@provider.supportsOnDemandNetworks@" = "true" ] ; then pip3 install -r /ipam/python/allocate_ip_range/requirements.txt --target=/ipam/python/allocate_ip_range ; fi
RUN if [ "@provider.supportsOnDemandNetworks@" = "true" ] ; then pip3 install -r /ipam/python/deallocate_ip_range/requirements.txt --target=/ipam/python/deallocate_ip_range ; fi
RUN useradd -ms /bin/bash -u @user.id@ -U @user.name@
CMD yes | cp -rf -R /ipam/python /ipam/result && \
echo Collecting-dependencies-complete

263
README.md Normal file
View File

@ -0,0 +1,263 @@
Sample IPAM Integration
============
A reference implementation of an IPAM integration plugin for vRA(C) 8.x
Use this documentation as a step by step guide for creating your own IPAM plugin.
For more information about the IPAM integration see: [vRA IPAM plugin reference documentation]
[vRA IPAM plugin reference documentation]: https://docs.vmware.com/en/VMware-Cloud-services/1.0/ipam_integration_contract_reqs.pdf
Prerequisites
===============
The following software should be installed and configured in order to use this plugin:
1. **Java 8**
2. **Maven 3** (Used for packaging the IPAM zip)
3. **Python 3** (The IPAM plugin is based on Python)
4. **Docker** (Docker is used to collect Python dependency libs that are needed by the IPAM plugin)
5. **Internet access** (The IPAM SDK relies on Maven Central, Docker HUB & PIP during packaging time. **Internet access is not required during runtime.** More details below)
Note: You can use a higher version of the above software as long as it is backward compatible.
Guide for creating the IPAM package
===============
Step 1: Package the scripts
----------------
Maven & Docker are used during build time to package the Python scripts into IPAM.zip distribution.
Maven enables the building of the IPAM package to be platform independent. This allows integrators to develop their IPAM integration solution under any Java-enabled OS - Windows, Unix, Mac, etc...
Docker is used during build time to start up a Photon OS container. All 3rd party libraries that the IPAM plugin depends on are downloaded during build time, using PIP, from within the Photon OS docker container. This guarantees that all Python lib binaries will be compiled exactly for Photon OS which is the OS of the Running Environment that is going to be executing the IPAM Python actions.
The first thing you can do is build the package by following the instructions below:
1. Open the `pom.xml` and modify the following properties:
`<provider.name>SampleIPAM</provider.name>`
`<provider.description>Sample IPAM integration for vRA</provider.description>`
`<provider.version>0.1</provider.version>`
Replace these property values with the name, description & version of your choice.
The provider.name will be used as a display name in vRA(C) when you deploy the plugin zip, along with the description & version.
Note:
Use the src/main/resources/CHANGELOG.md file to document any bug fixes, features and additions to the plugin over the course of time when a new plugin version is released. The file is included in the final plugin zip distribution so that vRA end-customers would know what is new in the plugin.
2. Update the logo.png file with the logo icon of your company (advisable)
The vRA(C) UI uses the logo.png file located in ./src/main/resources when displaying the IPAM endpoints you create using this package.
3. (Optional) Change the IPAM Integration endpoint custom form.
This is done by modifying the endpoint-schema.json file located in ./src/main/resources. It contains the custom form definition that renders the IPAM provider's specific fields
during IPAM endpoint registration. You can change it however you like except that **it is required that this file contains entries for privateKey and privateKeyId fields.**
Note: In ./src/main/resources you can also see the registration.yaml file. It contains meta information about the contents of the package.
**Don't change anything in this file.**
4. Run `mvn package -PcollectDependencies`
**This produces a SampleIPAM.zip file under ./target.**
**The zip should be ready for deployment into vRA(C).**
Notice that the first time you run this command, it could take up to several minutes to complete packaging the IPAM zip.
The reason for that is because the first time the script runs it attempts to collect any 3rd party Python libs that
the plugin depends on - such as **requests**, **pyopenssh** & others.
Next consecutive runs of `mvn package` **will not** trigger another collection of 3rd party libs because this is time consuming and most often unnecessary.
In order to re-trigger collection of dependencies (could be needed in case you introduced a new 3rd party Python lib) you must provide the `-PcollectDependencies` option again.
Note:
If you are building the package on Linux you must add one additional parameter to the build: `-Duser.id=${UID}`
(`mvn package -PcollectDependencies -Duser.id=${UID}`)
Now the IPAM package is ready to use.
We advise you to test whether it works by uploading it in vRA(C) and then checking that the actions are triggered when they should be and executed successfully.
For example, create a new IPAM endpoint and choose the package you uploaded in the **Provider** dropdown, enter an arbitrary username and password, enter **httpbin.org** as a **Hostname** and click on `Validate`.
You should see the **Validate Endpoint** action is triggered in the **Extensibility** tab. It should complete successfully.
Step 2: Get familiar with the IPAM operations and their skeleton implementations
----------------
After checking that the packaging of the sample IPAM scripts works, you can start exploring the code.
Under ./src/main/python you'd find separate directory for each IPAM specific operation that the plugin supports.
| Operation name | Description | Script | Required |
| ----------------------------|:------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------|:---------|
| Allocate IP | Allocates the next available IP for a VM | ./src/main/python/allocate_ip/source.py | Yes |
| Deallocate IP | Deallocates an already allocated IP | ./src/main/python/deallocate_ip/source.py | Yes |
| Get IP Ranges | Data collects IP ranges & networks from the IPAM provider | ./src/main/python/get_ip_ranges/source.py | Yes |
| Update Record | Updates the created host record. Could be used to update MAC address of VM after it has been provisioned | ./src/main/python/update_record/source.py | No |
| Validate Endpoint | Validates that the IPAM endpoint credentials are valid and that a connection to the external IPAM system can be established successfully | ./src/main/python/validate_endpoint/source.py | Yes |
| Allocate IP Range | Creates network inside some of the specified IP blocks | ./src/main/python/allocate_ip_range/source.py | No |
| Deallocate IP Range | Deletes an already allocated network | ./src/main/python/deallocate_ip_range/source.py | No |
| Get IP Blocks | Data collects IP blocks | ./src/main/python/get_ip_blocks/source.py | No |
The ./src/main/python/\*\*/source.py scripts contain the Python source code that would be used by vRA(C) to perform the respective IPAM operation.
Each script defines a `def handler(context, inputs):` function that is the entry point into the IPAM operation. vRA(C)'s IPAM framework calls the respective operation's `handler` function, passing request specific inputs in the form of Python dictionary along with the context object that can be used to securely connect to vRA(C) and call its services.
Step 3: Implement the IPAM operations
----------------
Integrators can choose to implement the `def handler(context, inputs):` function of each IPAM operation's source.py script from scratch, as long as they conform to the contract defined in the [vRA IPAM plugin reference documentation]
---
**We advise against implementing the operations from scratch.**
Instead, integrators can utilize the `vra_ipam_utils` library located in ./src/main/python/commons/vra_ipam_utils which contains utility functions and classes that will help with the `def handler(context, inputs):` implementation.
The source.py code already makes use of the `vra_ipam_utils` lib so you can look at it as reference:
```python
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_validate_endpoint = do_validate_endpoint
return ipam.validate_endpoint()
def do_validate_endpoint(self, auth_credentials, cert):
# Your implemention goes here
...
```
All you need to do in order to implement an operation is add your specific logic in the places indicated by the comments in the corresponding source.py file.
**Tip: It is a good idea to build the package, upload it in vRA(C) and test it after implementing each operation.**
We advise integrators to implement the IPAM operations one by one in the following order:
1. Validate Endpoint
2. Get IP Ranges
3. Get IP Blocks (Optionally)
4. Allocate IP
5. Allocate IP Range (Optionally)
6. Deallocate IP
7. Deallocate IP Range (Optionally)
8. Update Record (Optionally)
----
**Tip: How to call vRA(C) REST endpoints from within the IPAM operation**\
You can execute REST calls against vRA from within the Python scripts.
This is done by using the ```context``` object in your ```handler```
```python
context.request(link='/iaas/api/machines', operation='GET', body='')
```
The ```context``` is configured to handle authentication, authorization and proxying of your requests.
Step 4: Define 3rd party libraries (in case you use some)
----------------
In order to use 3rd party Python libs in the source.py scripts, you need to define them in the `requirements.txt` file that is located next to each IPAM operation's source.py.
The plugin build script takes care of downloading the dependency libs defined in `requirements.txt` and package them in the correct format within the IPAM zip.
The only important thing to remember here is to always re-run `mvn package -PcollectDependencies` every time you add or remove new dependency from the `requirements.txt`
The `requirements.txt` format is defined [here](https://pip.readthedocs.io/en/1.1/requirements.html)
Step 5: Change specific properties in the `pom.xml` (if needed)
----------------
**Implementing the optional Update Record operation**\
Integrators can choose to optionally implement the Update Record operation.
This operation is used by the vRA(C) IPAM service to notify the external IPAM system that a VM has been successfully provisioned and to propagate the VM's MAC address to the IPAM system.
Support of this optional operation is controlled by the following property in the `pom.xml`:
`<provider.supportsUpdateRecord>true</provider.supportsUpdateRecord>`
Changing this to `false` will force the build to exclude the Update Operation from the IPAM.zip package.
**Note**: If you ever change the property value from `false` to `true`, you'd have to re-run the build with `mvn package -PcollectDependencies` since the dependencies for the Update Operation would need to be re-collected.
----
**Implementing the optional 'Get IP Blocks', 'Allocate IP Range' and 'Deallocate IP Range' operations**\
The three operations are part of the extended IPAM plugin specification for vRA 8.X. They enable the plugin to support provisioning of on-demand networks from vRA.
Every time a vRA user requests to provision an on-demand network on i.e. NSX-T, a CIDR for that network will be allocated from the plugin along with other network settings such as default gateway.
The support for this operations is controlled by the following property in the `pom.xml`:
`<provider.supportsOnDemandNetworks>false</provider.supportsOnDemandNetworks>`
Changing this to `true` will force the build to include the `get_ip_blocks`, `allocate_ip_range` and `deallocate_ip_range` operations inside the IPAM.zip package.
**Note**: The same as with the Update operation, changing the `provider.supportsOnDemandNetworks` property from `false` to `true` must be followed by re-run of the `mvn package -PcollectDependencies` command in order to collect the required dependencies.
----
**Supporting address spaces**\
External IPAM networks & ranges can be organized into logical groups with overlapping address spaces, serving a single routing domain.
By default, the **SampleIPAM.zip** that this SDK produces is configured to not support address spaces. If your IPAM system does have the notion of an address space, you can choose to enable support for address spaces. This is done by changing the following property in the `pom.xml`:
`<provider.supportsAddressSpaces>true</provider.supportsAddressSpaces>`
Step 6: Build the package with the implemented IPAM operations (actually, it is advisable to do so after implementing each operation)
----------------
It is a good idea to deploy the package to vRA(C) and test the operations after implementing each IPAM operation.
When you're ready with your implementation, you can build the package by running `mvn package` (or `mvn package -PcollectDependencies` if needed) again.
After you implement all of the required operations (and some optional ones, if you choose to do so), the IPAM package is ready to be distributed and used.
Troubleshooting
===============
The following list contains the most common errors that might occur during build time:
1. `mvn package` build fails with:
> [ERROR] Plugin org.apache.maven.plugins:maven-resources-plugin:3.1.0 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-resources-plugin:jar:3.1.0: Could not transfer artifact org.apache.maven.plugins:maven-resources-plugin:pom:3.1.0 from/to central (https://repo.maven.apache.org/maven2): repo.maven.apache.org: Unknown host repo.maven.apache.org -> [Help 1]
**Resolution**:
Sometimes establishing connections to Maven Central fails. Retry again after couple of minutes. If the issue persists - check your internet connection.
2. `mvn package -PcollectDependencies` build fail with:
>[ERROR] DOCKER> Unable to pull 'vmware/photon2:20180424' : error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/12/1204ad97f071063bea855f351348e15e9cc03610cbfc8df46ab96b42d7cafa9f/data?verify=1578042999-Nu9yKJgKQcuFU0Y9hAQe%2BKEOKGo%3D: dial tcp: lookup production.cloudflare.docker.com on XXX:53: read udp XXX:57798->XXX:53: i/o timeout
**Resolution**:
Sometimes establishing connections to the Docker Registry times out. Retry again after couple of minutes. If the issue persists - check your internet connection
3. `mvn package -PcollectDependencies` build on `Windows` fails with:
> [ERROR] Failed to execute goal io.fabric8:docker-maven-plugin:0.31.0:start (start-container) on project sample-ipam: I/O Error: Unable to create container for [ipam-dependency-collector:latest] : Drive has not been shared (Internal Server Error: 500)
**Resolution**:
The build script uses Docker to collect the Python dependencies that are needed by the plugin. In order for Docker to operate correctly, it needs to have access to the Windows Drive that the build script resides in.
You need to allow Docker access to the respective drive: [Configure shared volume on Docker for Windows](https://blogs.msdn.microsoft.com/stevelasker/2016/06/14/configuring-docker-for-windows-volumes/)
4. `mvn package -PcollectDependencies` build fails with:
> [INFO] --- docker-maven-plugin:0.31.0:start (start-container) @ sample-ipam ---
[ERROR] DOCKER> Error occurred during container startup, shutting down...
[ERROR] DOCKER> I/O Error [Unable to create container for [ipam-dependency-collector:latest] : {"message":"Conflict. The container name \"/ipam-dependency-collector-1\" is already in use by container \"2bfb215381514cd6496ecd5d0103da0a4d94034c5691b25bdf27b16bd2236022\". You have to remove (or rename) that container to be able to reuse that name."} (Conflict: 409)]
**Resolution**:
Run `docker ps -a `
The output should look similar to this:
| CONTAINER ID | IMAGE | COMMAND | CREATED | STATUS | PORTS | NAMES
| ------------ | ----- | ------- | ------- | ------ | ----- | ---- |
| 2bfb21538151 | d886e9bba96e | "/bin/sh -c 'yes \| c…" | 3 minutes ago | Exited (0) 3 minutes ago | | ipam-dependency-collector-1
Locate the container with name `ipam-dependency-collector-*` and purge it:
Run `docker rm -f 2bfb21538151`
5. `mvn package -PcollectDependencies` build fails with:
> [INFO] --- docker-maven-plugin:0.31.0:build (build-image) @ sample-ipam ---
> [INFO] Building tar: ...\sample-abx-integration\target\docker\ipam-dependency-collector\latest\tmp\docker-build.tar
> [INFO] DOCKER> [ipam-dependency-collector:latest]: Created docker-build.tar in 214 milliseconds
> [ERROR] DOCKER> Unable to build image [ipam-dependency-collector:latest] : "The command '/bin/sh -c tdnf install -y python3-3.6.5-1.ph2 python3-pip-3.6.5-1.ph2 shadow && pip3 install --upgrade pip setuptools && pip3 install certifi' returned a non-zero code: 127" ["The command '/bin/sh -c tdnf install -y python3-3.6.5-1.ph2 python3-pip-3.6.5-1.ph2 shadow && pip3 install --upgrade pip setuptools && pip3 install certifi' returned a non-zero code: 127" ]
**Resolution**:
Sometimes the **tdnf** Photon OS package manager fails to install Python3 due to connectivity errors.
In case this happens, please wait for 1 min and retrigger the build.
If the issue persists, check your internet connectivity.
Changelog
============
## IPAM SDK 1.1.0:
**Features:**
- IPAM actions are now packaged for Python 3.7.5 runtime. User's 3rd party libraries that contain binaries (defined in requirements.txt and gathered during build time when -PcollectDependencies is supplied) are now compiled against Python 3.7.5 runtime (as opposed to Python 3.6).
If you upgrade from SDK 1.0.0, you'd have to recompile with -PcollectDependencies so that new libs for Python 3.7.5 are gathered.
- This version adds a new CHANGELOG.md file in src/main/resources to allow IPAM SDK users to keep track of bug fixes, features and additions to the plugin over the course of time when a new plugin version is released.
**Bug fixes:**
- As part of this release, a known permission issue for Linux users is fixed by adding the `-Duser.id` parameter.

259
open_source_licenses.txt Normal file
View File

@ -0,0 +1,259 @@
open_source_license.txt
VMware vRealize® Automation Third-Party IP Address Management™ SDK 1.0.0 GA
======================================================================
The following copyright statements and licenses apply to various open
source software packages (or portions thereof) that are distributed with
this VMware Product.
The VMware Product may also include other VMware components, which may
contain additional open source software packages. One or more such
open_source_licenses.txt files may therefore accompany this VMware
Product.
The VMware Product that includes this file does not necessarily use all
the open source software packages referred to below and may also only
use portions of a given package.
=============== TABLE OF CONTENTS =============================
The following is a listing of the open source components detailed in
this document. This list is provided for your convenience; please read
further if you wish to review the copyright notice(s) and the full text
of the license associated with each component.
SECTION 1: Apache License, V2.0
>>> python-requests-2.21.0
APPENDIX. Standard License Files
>>> Apache License, V2.0
--------------- SECTION 1: Apache License, V2.0 ----------
Apache License, V2.0 is applicable to the following component(s).
>>> python-requests-2.21.0
Copyright 2018 Kenneth Reitz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=============== APPENDIX. Standard License Files ==============
--------------- SECTION 1: Apache License, V2.0 -----------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the
copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other
entities that control, are controlled by, or are under common control
with that entity. For the purposes of this definition, "control" means
(i) the power, direct or indirect, to cause the direction or management
of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii)
beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source,
and configuration files.
"Object" form shall mean any form resulting from mechanical transformation
or translation of a Source form, including but not limited to compiled
object code, generated documentation, and conversions to other media
types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a copyright
notice that is included in or attached to the work (an example is provided
in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form,
that is based on (or derived from) the Work and for which the editorial
revisions, annotations, elaborations, or other modifications represent,
as a whole, an original work of authorship. For the purposes of this
License, Derivative Works shall not include works that remain separable
from, or merely link (or bind by name) to the interfaces of, the Work
and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the
original version of the Work and any modifications or additions to
that Work or Derivative Works thereof, that is intentionally submitted
to Licensor for inclusion in the Work by the copyright owner or by an
individual or Legal Entity authorized to submit on behalf of the copyright
owner. For the purposes of this definition, "submitted" means any form of
electronic, verbal, or written communication sent to the Licensor or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems
that are managed by, or on behalf of, the Licensor for the purpose of
discussing and improving the Work, but excluding communication that is
conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, sublicense, and
distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty- free, irrevocable (except as stated in this section) patent
license to make, have made, use, offer to sell, sell, import, and
otherwise transfer the Work, where such license applies only to those
patent claims licensable by such Contributor that are necessarily
infringed by their Contribution(s) alone or by combination of
their Contribution(s) with the Work to which such Contribution(s)
was submitted. If You institute patent litigation against any entity
(including a cross-claim or counterclaim in a lawsuit) alleging that the
Work or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses granted
to You under this License for that Work shall terminate as of the date
such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works
thereof in any medium, with or without modifications, and in Source or
Object form, provided that You meet the following conditions:
a. You must give any other recipients of the Work or Derivative Works
a copy of this License; and
b. You must cause any modified files to carry prominent notices stating
that You changed the files; and
c. You must retain, in the Source form of any Derivative Works that
You distribute, all copyright, patent, trademark, and attribution
notices from the Source form of the Work, excluding those notices
that do not pertain to any part of the Derivative Works; and
d. If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one of
the following places: within a NOTICE text file distributed as part
of the Derivative Works; within the Source form or documentation,
if provided along with the Derivative Works; or, within a display
generated by the Derivative Works, if and wherever such third-party
notices normally appear. The contents of the NOTICE file are for
informational purposes only and do not modify the License. You
may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text
from the Work, provided that such additional attribution notices
cannot be construed as modifying the License. You may add Your own
copyright statement to Your modifications and may provide additional
or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works
as a whole, provided Your use, reproduction, and distribution of the
Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally
submitted for inclusion in the Work by You to the Licensor shall be
under the terms and conditions of this License, without any additional
terms or conditions. Notwithstanding the above, nothing herein shall
supersede or modify the terms of any separate license agreement you may
have executed with Licensor regarding such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor
provides the Work (and each Contributor provides its Contributions) on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied, including, without limitation, any warranties or
conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
A PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any risks
associated with Your exercise of permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including
negligence), contract, or otherwise, unless required by applicable law
(such as deliberate and grossly negligent acts) or agreed to in writing,
shall any Contributor be liable to You for damages, including any direct,
indirect, special, incidental, or consequential damages of any character
arising as a result of this License or out of the use or inability to
use the Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all other
commercial damages or losses), even if such Contributor has been advised
of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may
choose to offer, and charge a fee for, acceptance of support, warranty,
indemnity, or other liability obligations and/or rights consistent with
this License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf of
any other Contributor, and only if You agree to indemnify, defend, and
hold each Contributor harmless for any liability incurred by, or claims
asserted against, such Contributor by reason of your accepting any such
warranty or additional liability.
END OF TERMS AND CONDITIONS
======================================================================
To the extent any open source components are licensed under the GPL
and/or LGPL, or other similar licenses that require the source code
and/or modifications to source code to be made available (as would be
noted above), you may obtain a copy of the source code corresponding to
the binaries for such open source components and modifications thereto,
if any, (the "Source Files"), by downloading the Source Files from
VMware's website at http://www.vmware.com/download/open_source.html, or
by sending a request, with your name and address to: VMware, Inc., 3401
Hillview Avenue, Palo Alto, CA 94304, United States of America. All such
requests should clearly specify: OPEN SOURCE FILES REQUEST, Attention
General Counsel. VMware shall mail a copy of the Source Files to you on
a CD or equivalent physical medium. This offer to obtain a copy of the
Source Files is valid for three years from the date you acquired this
Software product. Alternatively, the Source Files may accompany the
VMware product.
[vraipamsdk100GARZ022520]

372
pom.xml Normal file
View File

@ -0,0 +1,372 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2020 VMware, Inc. All Rights Reserved.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vmware.cas.ipam.adapter</groupId>
<artifactId>sample-ipam</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<provider.name>phpIPAM</provider.name>
<provider.description>phpIPAM integration for vRA</provider.description>
<provider.version>0.1</provider.version>
<provider.supportsAddressSpaces>false</provider.supportsAddressSpaces>
<provider.supportsUpdateRecord>true</provider.supportsUpdateRecord>
<provider.supportsOnDemandNetworks>false</provider.supportsOnDemandNetworks>
<user.id>1000</user.id>
</properties>
<profiles>
<profile>
<id>collectDependencies</id>
<activation>
<file>
<missing>${basedir}/target/dependencies.collected.flag</missing>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.31.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>prepare-package</phase>
<goals>
<goal>build</goal>
</goals>
<configuration>
<name>ipam-dependency-collector:latest</name>
<images>
<image>
<name>ipam-dependency-collector:latest</name>
<build>
<dockerFile>${project.basedir}/Dockerfile</dockerFile>
<filter>@</filter>
</build>
</image>
</images>
</configuration>
</execution>
<execution>
<id>start-container</id>
<phase>prepare-package</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<images>
<image>
<name>ipam-dependency-collector:latest</name>
<run>
<volumes>
<bind>${basedir}/target:/ipam/result</bind>
</volumes>
<wait>
<log>Collecting-dependencies-complete</log>
<time>600000</time> <!-- Wait for 10 minutes to copy the dependencies into the mounted dir -->
</wait>
<user>${user.name}</user>
</run>
</image>
</images>
</configuration>
</execution>
<execution>
<id>stop-container</id>
<phase>prepare-package</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<id>copy-dependencies-collected-flag</id>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>dependencies.collected.flag</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.12</version>
<executions>
<execution>
<id>dynamic-set-props</id>
<phase>initialize</phase>
<goals>
<goal>bsh-property</goal>
</goals>
<configuration>
<source>skipUpdateRecord =
!${provider.supportsUpdateRecord};
excludeUpdateRecordFromAssemblyFilePattern
= skipUpdateRecord ? "update_record.abx"
: "dont-exclude"; skipOnDemandNetworks =
!${provider.supportsOnDemandNetworks};
excludeGetIpBlocksFromAssemblyFilePattern
= skipOnDemandNetworks ?
"get_ip_blocks.abx" : "dont-exclude";
excludeAllocateIpRangeFromAssemblyFilePattern
= skipOnDemandNetworks ?
"allocate_ip_range.abx" : "dont-exclude";
excludeDeallocateIpRangeFromAssemblyFilePattern
= skipOnDemandNetworks ?
"deallocate_ip_range.abx" : "dont-exclude";
supportsAddressSpaces
= ${provider.supportsAddressSpaces} ?
"supportsAddressSpaces: true" : "";
</source>
<properties>
<property>skipUpdateRecord</property>
<property>excludeUpdateRecordFromAssemblyFilePattern</property>
<property>skipOnDemandNetworks</property>
<property>excludeGetIpBlocksFromAssemblyFilePattern</property>
<property>excludeAllocateIpRangeFromAssemblyFilePattern</property>
<property>excludeDeallocateIpRangeFromAssemblyFilePattern</property>
<property>supportsAddressSpaces</property>
</properties>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-scripts</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/python</outputDirectory>
<resources>
<resource>
<directory>src/main/python</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<goals>
<goal>resources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<executions>
<execution>
<id>allocate_ip</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/allocate_ip.xml</descriptor>
<finalName>allocate_ip</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
</configuration>
</execution>
<execution>
<id>deallocate_ip</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/deallocate_ip.xml</descriptor>
<finalName>deallocate_ip</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
</configuration>
</execution>
<execution>
<id>get_ip_ranges</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/get_ip_ranges.xml</descriptor>
<finalName>get_ip_ranges</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
</configuration>
</execution>
<execution>
<id>update_record</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/update_record.xml</descriptor>
<finalName>update_record</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
<skipAssembly>${skipUpdateRecord}</skipAssembly>
</configuration>
</execution>
<execution>
<id>validate_endpoint</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/validate_endpoint.xml</descriptor>
<finalName>validate_endpoint</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
</configuration>
</execution>
<execution>
<id>get_ip_blocks</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/get_ip_blocks.xml</descriptor>
<finalName>get_ip_blocks</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
<skipAssembly>${skipOnDemandNetworks}</skipAssembly>
</configuration>
</execution>
<execution>
<id>allocate_ip_range</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/allocate_ip_range.xml</descriptor>
<finalName>allocate_ip_range</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
<skipAssembly>${skipOnDemandNetworks}</skipAssembly>
</configuration>
</execution>
<execution>
<id>deallocate_ip_range</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/python/deallocate_ip_range.xml</descriptor>
<finalName>deallocate_ip_range</finalName>
<outputDirectory>${project.build.directory}/actions</outputDirectory>
<skipAssembly>${skipOnDemandNetworks}</skipAssembly>
</configuration>
</execution>
<execution>
<id>zip-actions</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/zip-actions.xml</descriptor>
<finalName>bundle</finalName>
</configuration>
</execution>
<execution>
<id>zip-provider</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/assembly/zip-provider.xml</descriptor>
<finalName>${provider.name}</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.nicoulaj.maven.plugins</groupId>
<artifactId>checksum-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>build-ipam-package-signature</id>
<phase>prepare-package</phase>
<goals>
<goal>files</goal>
</goals>
</execution>
</executions>
<configuration>
<fileSets>
<fileSet>
<directory>${basedir}/target/</directory>
<includes>
<include>bundle.zip</include>
</includes>
</fileSet>
</fileSets>
<algorithms>
<algorithm>SHA-256</algorithm>
</algorithms>
<csvSummary>false</csvSummary>
<shasumSummary>true</shasumSummary>
<shasumSummaryFile>signature</shasumSummaryFile>
<individualFiles>false</individualFiles>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/allocate_ip</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/allocate_ip_range</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/deallocate_ip</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/deallocate_ip_range</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/get_ip_blocks</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/get_ip_ranges</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/update_record</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,25 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/python/validate_endpoint</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>target/python/commons</directory>
<includes>
<include>**</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,28 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/classes/bundle</directory>
<outputDirectory></outputDirectory>
<excludes>
<exclude>${excludeUpdateRecordFromAssemblyFilePattern}</exclude>
<exclude>${excludeGetIpBlocksFromAssemblyFilePattern}</exclude>
<exclude>${excludeAllocateIpRangeFromAssemblyFilePattern}</exclude>
<exclude>${excludeDeallocateIpRangeFromAssemblyFilePattern}</exclude>
</excludes>
</fileSet>
<fileSet>
<directory>target/actions</directory>
<includes>
<include>*.zip</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View File

@ -0,0 +1,29 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/classes</directory>
<outputDirectory></outputDirectory>
<includes>
<include>registration.yaml</include>
<include>endpoint-schema.json</include>
<include>logo.png</include>
<include>CHANGELOG.md</include>
</includes>
</fileSet>
<fileSet>
<directory>target</directory>
<outputDirectory></outputDirectory>
<includes>
<include>bundle.zip</include>
<include>signature</include>
</includes>
</fileSet>
</fileSets>
</assembly>

BIN
src/main/python/.DS_Store vendored Normal file

Binary file not shown.

View File

View File

@ -0,0 +1 @@
requests==2.21.0

View File

@ -0,0 +1,143 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
import logging
"""
Example payload
"inputs": {
"resourceInfo": {
"id": "11f912e71454a075574a728848458",
"name": "external-ipam-it-mcm-323412",
"description": "test",
"type": "VM",
"owner": "mdzhigarov@vmware.com",
"orgId": "ce811934-ea1a-4f53-b6ec-465e6ca7d126",
"properties": {
"osType": "WINDOWS",
"vcUuid": "ff257ed9-070b-45eb-b2e7-d63926d5bdd7",
"__moref": "VirtualMachine:vm-288560",
"memoryGB": "4",
"datacenter": "Datacenter:datacenter-2",
"provisionGB": "1",
"__dcSelfLink": "/resources/groups/b28c7b8de065f07558b1612fce028",
"softwareName": "Microsoft Windows XP Professional (32-bit)",
"__computeType": "VirtualMachine",
"__hasSnapshot": "false",
"__placementLink": "/resources/compute/9bdc98681fb8b27557252188607b8",
"__computeHostLink": "/resources/compute/9bdc98681fb8b27557252188607b8"
}
},
"ipAllocations": [
{
"id": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"ipRangeIds": [
"network/ZG5zLm5ldHdvcmskMTAuMjMuMTE3LjAvMjQvMA:10.23.117.0/24/default"
],
"nicIndex": "0",
"isPrimary": "true",
"size": "1",
"properties": {
"__moref": "DistributedVirtualPortgroup:dvportgroup-307087",
"__dvsUuid": "0c 8c 0b 50 46 b6 1c f2-e8 63 f4 24 24 d7 24 6c",
"__dcSelfLink": "/resources/groups/abe46b8cfa663a7558b28a6ffe088",
"__computeType": "DistributedVirtualPortgroup",
"__portgroupKey": "dvportgroup-307087"
}
}
],
"endpoint": {
"id": "f097759d8736675585c4c5d272cd",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"certificate": "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
"""
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_allocate_ip = do_allocate_ip
return ipam.allocate_ip()
def do_allocate_ip(self, auth_credentials, cert):
# Your implemention goes here
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
allocation_result = []
try:
resource = self.inputs["resourceInfo"]
for allocation in self.inputs["ipAllocations"]:
allocation_result.append(allocate(resource, allocation, self.context, self.inputs["endpoint"]))
except Exception as e:
try:
rollback(allocation_result)
except Exception as rollback_e:
logging.error(f"Error during rollback of allocation result {str(allocation_result)}")
logging.error(rollback_e)
raise e
assert len(allocation_result) > 0
return {
"ipAllocations": allocation_result
}
def allocate(resource, allocation, context, endpoint):
last_error = None
for range_id in allocation["ipRangeIds"]:
logging.info(f"Allocating from range {range_id}")
try:
return allocate_in_range(range_id, resource, allocation, context, endpoint)
except Exception as e:
last_error = e
logging.error(f"Failed to allocate from range {range_id}: {str(e)}")
logging.error("No more ranges. Raising last error")
raise last_error
def allocate_in_range(range_id, resource, allocation, context, endpoint):
## Plug your implementation here to allocate an ip address
## ...
## Allocation successful
result = {
"ipAllocationId": allocation["id"],
"ipRangeId": range_id,
"ipVersion": "IPv4"
}
result["ipAddresses"] = ["10.23.117.5"]
result["properties"] = {"customPropertyKey1": "customPropertyValue1"}
return result
## Rollback any previously allocated addresses in case this allocation request contains multiple ones and failed in the middle
def rollback(allocation_result):
for allocation in reversed(allocation_result):
logging.info(f"Rolling back allocation {str(allocation)}")
ipAddresses = allocation.get("ipAddresses", None)
## release the address
return

View File

@ -0,0 +1 @@
requests==2.21.0

View File

@ -0,0 +1,139 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
import logging
"""
Example payload
"inputs": {
"resourceInfo": {
"id": "/resources/sub-networks/255ac10c-0198-4a92-9414-b8e0c23c0204",
"name": "net1-mcm223-126361015194",
"type": "SUBNET",
"orgId": "e0d6ea3a-519a-4308-afba-c973a8903250",
"owner": "jason@csp.local",
"properties": {
"networkType": "PRIVATE",
"datacenterId": "Datacenter:datacenter-21",
"__networkCidr": "192.168.197.0/28",
"__deploymentLink": "/resources/deployments/f77fbe4d-9e78-4b1b-93b0-024d342d0872",
"__infrastructureUse": "true",
"__composition_context_id": "f77fbe4d-9e78-4b1b-93b0-024d342d0872",
"__isInfrastructureShareable": "true"
}
},
"ipRangeAllocation": {
"name": "net1-mcm223-126361015194",
"ipBlockIds": [
"block1",
"block2"
],
"properties": {
"networkType": "PRIVATE",
"datacenterId": "Datacenter:datacenter-21",
"__networkCidr": "192.168.197.0/28",
"__deploymentLink": "/resources/deployments/f77fbe4d-9e78-4b1b-93b0-024d342d0872",
"__infrastructureUse": "true",
"__composition_context_id": "f77fbe4d-9e78-4b1b-93b0-024d342d0872",
"__isInfrastructureShareable": "true"
},
"subnetCidr": "192.168.197.0/28",
"addressSpaceId": "default"
},
"endpoint": {
"id": "f097759d8736675585c4c5d272cd",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"certificate": "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
"""
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_allocate_ip_range = do_allocate_ip_range
return ipam.allocate_ip_range()
def do_allocate_ip_range(self, auth_credentials, cert):
# Your implemention goes here
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
resource = self.inputs["resourceInfo"]
allocation = self.inputs["ipRangeAllocation"]
ipRange = allocate(resource, allocation, self.context, self.inputs["endpoint"])
return {
"ipRange": ipRange
}
def allocate(resource, allocation, context, endpoint):
last_error = None
for ip_block_id in allocation["ipBlockIds"]:
logging.info(f"Allocating from ip block {ip_block_id}")
try:
return allocate_in_ip_block(ip_block_id, resource, allocation, context, endpoint)
except Exception as e:
last_error = e
logging.error(f"Failed to allocate from ip block {ip_block_id}: {str(e)}")
logging.error("No more ip blocks. Raising last error")
raise last_error
def allocate_in_ip_block(ip_block_id, resource, allocation, context, endpoint):
## Plug your implementation here to allocate an ip range
## ...
## Allocation successful
result = {
"id": "range-new",
"name": "sample range new",
"startIPAddress": "10.10.40.1",
"endIPAddress": "10.10.40.10",
"description": "sampleDescription",
"ipVersion": "IPv4",
"addressSpaceId": "default",
"subnetPrefixLength": "24",
"gatewayAddress": "10.10.13.1",
"domain": "test.local",
"tags": [{
"key": "Building",
"value": "VMware main facility"
}],
"properties": {
}
}
return result

View File

@ -0,0 +1,7 @@
class InvalidCertificateException(Exception):
def __init__(self, message, host, port):
# Call the base class constructor with the parameters it needs
super().__init__(message)
self.host = host
self.port = port

View File

@ -0,0 +1,344 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import json
import tempfile
import os
import logging
from vra_ipam_utils.exceptions import InvalidCertificateException
class IPAM(object):
""" IPAM holds util methods for interacting with vRA's IPAM service.
Defines methods for the following ipam operations:
1] Validate endpoint
2] Get IP Ranges
3] Allocate IP
4] Deallocate IP
5] Update record
"""
def __init__(self, context, inputs):
self.context = context
self.inputs = inputs
# Setup the logging globally
self._setup_logger()
def validate_endpoint(self):
cert = None
try:
auth_credentials = self._get_auth_credentials()
cert = self._get_cert()
return self.do_validate_endpoint(auth_credentials, cert)
except InvalidCertificateException as e:
return {
"certificateInfo": {
"certificate": self._fetch_server_certificate(e.host, e.port)
},
"error": self._build_error_response("3002", str(e))["error"] ## Return special status code "3002" on invalid certificate
}
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def get_ip_ranges(self):
cert = None
try:
auth_credentials = self._get_auth_credentials()
cert = self._get_cert()
result = self.do_get_ip_ranges(auth_credentials, cert)
# Validation of returned result
err_msg = "{} is mandatory part of the response schema and must be present in the response"
assert result.get("ipRanges") is not None, err_msg.format("ipRanges")
assert isinstance(result["ipRanges"], list), "ipRanges must be a list type"
for i in range(len(result["ipRanges"])):
assert result["ipRanges"][i].get("id") is not None, err_msg.format(f"ipRanges[{i}]['id']")
assert result["ipRanges"][i].get("name") is not None, err_msg.format(f"ipRanges[{i}]['name']")
assert result["ipRanges"][i].get("startIPAddress") is not None, err_msg.format(f"ipRanges[{i}]['startIPAddress']")
assert result["ipRanges"][i].get("endIPAddress") is not None, err_msg.format(f"ipRanges[{i}]['endIPAddress']")
assert result["ipRanges"][i].get("ipVersion") is not None, err_msg.format(f"ipRanges[{i}]['ipVersion']")
assert result["ipRanges"][i].get("subnetPrefixLength") is not None, err_msg.format(f"ipRanges[{i}]['subnetPrefixLength']")
return result
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def allocate_ip(self):
cert = None
try:
auth_credentials = self._get_auth_credentials()
cert = self._get_cert()
result = self.do_allocate_ip(auth_credentials, cert)
# Validation of returned result
err_msg = "{} is mandatory part of the response schema and must be present in the response"
assert result.get("ipAllocations") is not None, err_msg.format("ipAllocations")
assert isinstance(result["ipAllocations"], list), "ipAllocations must be a list type"
assert len(result["ipAllocations"]) == len(self.inputs["ipAllocations"]), "Size of ipAllocations in the inputs is different than the one in the outputs"
for i in range(len(result["ipAllocations"])):
assert result["ipAllocations"][i].get("ipAllocationId") is not None, err_msg.format(f"ipAllocations[{i}]['ipAllocationId']")
assert result["ipAllocations"][i].get("ipRangeId") is not None, err_msg.format(f"ipAllocations[{i}]['ipRangeId']")
assert result["ipAllocations"][i].get("ipVersion") is not None, err_msg.format(f"ipAllocations[{i}]['ipVersion']")
assert result["ipAllocations"][i].get("ipAddresses") is not None, err_msg.format(f"ipAllocations[{i}]['ipAddresses']")
assert isinstance(result["ipAllocations"][i]["ipAddresses"], list), f"ipAllocations[{i}]['ipAddresses'] must be a list type"
assert len(result["ipAllocations"][i]["ipAddresses"]) > 0, f"ipAllocations[{i}]['ipAddresses'] must not be empty"
for allocation in self.inputs["ipAllocations"]:
found = False
if allocation["id"] == result["ipAllocations"][i]["ipAllocationId"]:
found = True
break
assert found, f"Allocation result with id {result['ipAllocations'][i]['ipAllocationId']} not found"
return result
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def deallocate_ip(self):
cert = None
try:
auth_credentials = self._get_auth_credentials()
cert = self._get_cert()
result = self.do_deallocate_ip(auth_credentials, cert)
# Validation of returned result
err_msg = "{} is mandatory part of the response schema and must be present in the response"
assert result.get("ipDeallocations") is not None, err_msg.format("ipDeallocations")
assert isinstance(result["ipDeallocations"], list), "ipDeallocations must be a list type"
assert len(result["ipDeallocations"]) == len(self.inputs["ipDeallocations"]), "Size of ipDeallocations in the inputs is different than the one in the outputs"
for i in range(len(result["ipDeallocations"])):
assert result["ipDeallocations"][i].get("ipDeallocationId") is not None, err_msg.format(f"ipDeallocations[{i}]['ipDeallocationId']")
for deallocation in self.inputs["ipDeallocations"]:
found = False
if deallocation["id"] == result["ipDeallocations"][i]["ipDeallocationId"]:
found = True
break
assert found, f"Deallocation result with id {result['ipDeallocations'][i]['ipDeallocationId']} not found"
return result
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def update_record(self):
cert = None
try:
auth_credentials = self._get_auth_credentials();
cert = self._get_cert()
return self.do_update_record(auth_credentials, cert)
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def get_ip_blocks(self):
cert = None
try:
auth_credentials = self._get_auth_credentials()
cert = self._get_cert()
result = self.do_get_ip_blocks(auth_credentials, cert)
# Validation of returned result
err_msg = "{} is mandatory part of the response schema and must be present in the response"
assert result.get("ipBlocks") is not None, err_msg.format("ipBlocks")
assert isinstance(result["ipBlocks"], list), "ipRanges must be a list type"
for i in range(len(result["ipBlocks"])):
assert result["ipBlocks"][i].get("id") is not None, err_msg.format(f"ipBlocks[{i}]['id']")
assert result["ipBlocks"][i].get("name") is not None, err_msg.format(f"ipBlocks[{i}]['name']")
assert result["ipBlocks"][i].get("ipBlockCIDR") is not None, err_msg.format(f"ipBlocks[{i}]['ipBlockCIDR']")
assert result["ipBlocks"][i].get("ipVersion") is not None, err_msg.format(f"ipBlocks[{i}]['ipVersion']")
return result
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def allocate_ip_range(self):
cert = None
try:
auth_credentials = self._get_auth_credentials()
cert = self._get_cert()
result = self.do_allocate_ip_range(auth_credentials, cert)
# Validation of returned result
err_msg = "{} is mandatory part of the response schema and must be present in the response"
assert result.get("ipRange") is not None, err_msg.format("ipRange")
assert result["ipRange"].get("id") is not None, err_msg.format(f"ipRange['id']")
assert result["ipRange"].get("name") is not None, err_msg.format(f"ipRange['name']")
assert result["ipRange"].get("startIPAddress") is not None, err_msg.format(f"ipRange['startIPAddress']")
assert result["ipRange"].get("endIPAddress") is not None, err_msg.format(f"ipRange['endIPAddress']")
assert result["ipRange"].get("ipVersion") is not None, err_msg.format(f"ipRange['ipVersion']")
assert result["ipRange"].get("subnetPrefixLength") is not None, err_msg.format(f"ipRange['subnetPrefixLength']")
return result
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def deallocate_ip_range(self):
cert = None
try:
auth_credentials = self._get_auth_credentials()
cert = self._get_cert()
return self.do_deallocate_ip_range(auth_credentials, cert)
finally:
if cert is not None and type(cert) is str:
os.unlink(cert)
def do_validate_endpoint(self, auth_credentials, cert):
raise Exception("Method do_validate_endpoint(self, auth_credentials, cert) not implemented")
def do_get_ip_ranges(self, auth_credentials, cert):
raise Exception("Method do_get_ip_ranges(self, auth_credentials, cert) not implemented")
def do_allocate_ip(self, auth_credentials, cert):
raise Exception("Method do_allocate_ip(self, auth_credentials, cert) not implemented")
def do_deallocate_ip(self, auth_credentials, cert):
raise Exception("Method do_deallocate_ip(self, auth_credentials, cert) not implemented")
def do_update_record(self, auth_credentials, cert):
raise Exception("Method do_update_record(self, auth_credentials, cert) not implemented")
def do_get_ip_blocks(self, auth_credentials, cert):
raise Exception("Method do_get_ip_blocks(self, auth_credentials, cert) not implemented")
def do_allocate_ip_range(self, auth_credentials, cert):
raise Exception("Method do_allocate_ip_range(self, auth_credentials, cert) not implemented")
def do_deallocate_ip_range(self, auth_credentials, cert):
raise Exception("Method do_deallocate_ip_range(self, auth_credentials, cert) not implemented")
def _get_cert(self):
inputs = self.inputs.get("endpoint", self.inputs)
certificate = inputs["endpointProperties"].get("certificate", None)
if certificate is not None:
cert = tempfile.NamedTemporaryFile(mode='w', delete=False)
cert.write(certificate)
cert.close()
return cert.name
else:
return True
""" Fetches the server certificate of the host.
Used in case the certificate is not automatically trusted
"""
def _fetch_server_certificate(self, hostname, port):
logging.info(f"Fetching certificate of {hostname}")
import ssl
import socket
from OpenSSL import SSL
from OpenSSL import crypto
import os
import idna
hostname_idna = idna.encode(hostname)
proxy = os.environ.get("http_proxy", None)
if proxy is not None:
from urllib.parse import urlparse
o = urlparse(proxy)
PROXY_ADDR = (o.hostname, o.port)
CONNECT = "CONNECT %s:%s HTTP/1.0\r\nConnection: close\r\n\r\n" % (hostname, port)
logging.info(f"HTTP Proxy is configured. Sending CONNECT command to {proxy}: {CONNECT}")
CONNECT = bytes(CONNECT, "utf-8")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(PROXY_ADDR)
sock.send(CONNECT)
logging.info(sock.recv(4096))
else:
sock = socket.socket()
sock.connect((hostname, port))
ctx = SSL.Context(SSL.SSLv23_METHOD) # most compatible
ctx.check_hostname = False
ctx.verify_mode = SSL.VERIFY_NONE
sock_ssl = SSL.Connection(ctx, sock)
sock_ssl.set_connect_state()
sock_ssl.set_tlsext_host_name(hostname_idna)
sock_ssl.do_handshake()
certs = sock_ssl.get_peer_cert_chain()
sb = ""
for cert in certs:
cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
cert = cert.decode()
sb += cert
sock_ssl.shutdown()
sock_ssl.close()
sock.close()
return sb
def _build_error_response(self, error_code, error_message):
return {
"error": {
"errorCode": error_code,
"errorMessage": error_message
}
}
""" Fetches the auth credentials from vRA """
def _get_auth_credentials(self):
if self._is_mock_request(): # Used for testing purposes within VMware
return {"privateKeyId": "admin", "privateKey":"VMware"}
logging.info("Querying for auth credentials")
inputs = self.inputs.get("endpoint", self.inputs)
auth_credentials_link = inputs["authCredentialsLink"]
auth_credentials_response = self.context.request(auth_credentials_link, 'GET', '') ## Integrators can use context.request() to call CAS/Prelude REST endpoints
if auth_credentials_response["status"] == 200:
logging.info("Credentials obtained successfully!")
return json.loads(auth_credentials_response["content"])
raise Exception('Failed to obtain auth credentials from {}: {}'.format(auth_credentials_link, str(auth_credentials_response)))
def _setup_logger(self):
logger = logging.getLogger()
if logger.handlers:
for handler in logger.handlers:
logger.removeHandler(handler)
logging.basicConfig(format="[%(asctime)s] [%(levelname)s] - %(message)s", level=logging.INFO)
logging.StreamHandler.emit = lambda self, record: print(logging.StreamHandler.format(self, record))
def _is_mock_request(self):
endpoint = self.inputs.get("endpoint", self.inputs)
return endpoint["endpointProperties"].get("isMockRequest", False)

View File

@ -0,0 +1 @@
requests==2.21.0

View File

@ -0,0 +1,96 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
import logging
"""
Example payload:
"inputs": {
"resourceInfo": {
"id": "11f912e71454a075574a728848458",
"name": "external-ipam-it-mcm-323412",
"description": "test",
"type": "VM",
"owner": "mdzhigarov@vmware.com",
"orgId": "ce811934-ea1a-4f53-b6ec-465e6ca7d126",
"properties": {
"osType": "WINDOWS",
"vcUuid": "ff257ed9-070b-45eb-b2e7-d63926d5bdd7",
"__moref": "VirtualMachine:vm-288560",
"memoryGB": "4",
"datacenter": "Datacenter:datacenter-2",
"provisionGB": "1",
"__dcSelfLink": "/resources/groups/b28c7b8de065f07558b1612fce028",
"softwareName": "Microsoft Windows XP Professional (32-bit)",
"__computeType": "VirtualMachine",
"__hasSnapshot": "false",
"__placementLink": "/resources/compute/9bdc98681fb8b27557252188607b8",
"__computeHostLink": "/resources/compute/9bdc98681fb8b27557252188607b8"
}
},
"ipDeallocations": [
{
"id": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"ipRangeId": "network/ZG5zLm5ldHdvcmskMTAuMjMuMTE3LjAvMjQvMA:10.23.117.0/24/default",
"ipAddress": "10.23.117.5"
}
],
"endpoint": {
"id": "f097759d8736675585c4c5d272cd",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"certificate": "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
"""
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_deallocate_ip = do_deallocate_ip
return ipam.deallocate_ip()
def do_deallocate_ip(self, auth_credentials, cert):
# Your implemention goes here
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
deallocation_result = []
for deallocation in self.inputs["ipDeallocations"]:
deallocation_result.append(deallocate(self.inputs["resourceInfo"], deallocation))
assert len(deallocation_result) > 0
return {
"ipDeallocations": deallocation_result
}
def deallocate(resource, deallocation):
ip_range_id = deallocation["ipRangeId"]
ip = deallocation["ipAddress"]
resource_id = resource["id"]
logging.info(f"Deallocating ip {ip} from range {ip_range_id}")
## Plug your implementation here to deallocate an already allocated ip address
## ...
## Deallocation successful
return {
"ipDeallocationId": deallocation["id"],
"message": "Success"
}

View File

@ -0,0 +1 @@
requests==2.21.0

View File

@ -0,0 +1,74 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
import logging
"""
Example payload:
"inputs": {
"resourceInfo": {
"id": "/resources/sub-networks/255ac10c-0198-4a92-9414-b8e0c23c0204",
"name": "net1-mcm223-126361015194",
"type": "SUBNET",
"owner": "mdzhigarov@vmware.com",
"orgId": "ce811934-ea1a-4f53-b6ec-465e6ca7d126",
},
"ipDeallocations": [
{
"id": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"ipRangeId": "network/ZG5zLm5ldHdvcmskMTAuMjMuMTE3LjAvMjQvMA:10.23.117.0/24/default",
"ipAddress": "10.23.117.5"
}
],
"endpoint": {
"id": "f097759d8736675585c4c5d272cd",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"certificate": "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
"""
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_deallocate_ip_range = do_deallocate_ip_range
return ipam.deallocate_ip_range()
def do_deallocate_ip_range(self, auth_credentials, cert):
# Your implemention goes here
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
deallocation_result = deallocate(self.inputs["resourceInfo"], self.inputs["ipRangeDeallocation"])
return {
"message": f"Successfully deallocated {str(deallocation_result)}"
}
def deallocate(resource, deallocation):
ip_range_id = deallocation["ipRangeId"]
resource_id = resource["id"]
logging.info(f"Deallocating ip range {ip_range_id}")
## Plug your implementation here to deallocate an already allocated ip address
## ...
## Deallocation successful
return "Deallocated!"

View File

@ -0,0 +1 @@
requests==2.21.0

View File

@ -0,0 +1,130 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
import logging
'''
Example payload:
"inputs": {
"endpoint": {
"id": "f097759d8736675585c4c5d272cd",
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com",
"certificate": "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
}
},
"pagingAndSorting": {
"maxResults": 1000,
"pageToken": "87811419dec2112cda2aa29685685d650ac1f61f"
}
}
'''
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_get_ip_blocks = do_get_ip_blocks
return ipam.get_ip_blocks()
def do_get_ip_blocks(self, auth_credentials, cert):
# Your implemention goes here
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
## If many IP blocks are expected on the IPAM server, it is considered a best practice
## to return them page by page instead of all at once.
## The vRA IPAM Service will propagate a pageToken string with each consecutive request
## until all pages are exhausted
pageToken = self.inputs['pagingAndSorting'].get('pageToken', None) ## The first request that vRA sends is with 'None' pageToken
## Plug your implementation here to collect all the ip blocks from the external IPAM system
result_ip_blocks, next_page_token = collect_ip_blocks(pageToken)
result = {
"ipBlocks": result_ip_blocks
}
## Return the next page token so that vRA can process the first page and then fetch the second page or ip blocks with the next request
if next_page_token is not None:
result["nextPageToken"] = next_page_token
return result
def collect_ip_blocks(pageToken):
logging.info("Collecting ip blocks")
ip_block1 = {
"id": "block1",
"name": "sample name 1",
"ipBlockCIDR": "10.10.0.0/16",
"description": "sampleDescription",
"ipVersion": "IPv4",
"addressSpaceId": "default",
"gatewayAddress": "10.10.13.1",
"domain": "test.local",
"tags": [{
"key": "Building",
"value": "VMware main facility"
}],
"properties": {
}
}
ip_block2 = {
"id": "block2",
"name": "sample name 2",
"ipBlockCIDR": "10.10.40.0/24",
"description": "sampleDescription",
"ipVersion": "IPv4",
"addressSpaceId": "default",
"dnsServerAddresses": ["10.10.17.3", "10.10.22.1"],
"dnsSearchDomains": ["com", "net", "test.local"],
"domain": "test.local",
"tags": [{
"key": "Building",
"value": "VMware main facility"
}],
"properties": {
}
}
result = []
next_page_token = None
if pageToken is None:
result = [ip_block1]
next_page_token = "87811419dec2112cda2aa29685685d650ac1f61f"
else:
result = [ip_block2]
return result, next_page_token

View File

@ -0,0 +1,2 @@
requests==2.21.0
ipaddress

View File

@ -0,0 +1,87 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
import logging
import ipaddress
'''
Example payload:
"inputs": {
"endpoint": {
"id": "f097759d8736675585c4c5d272cd",
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com",
"certificate": "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
}
},
"pagingAndSorting": {
"maxResults": 1000,
"pageToken": "789c55905d6e02310c84df7d91452a456481168ec04b55950344f9db55dadd384abc056e5f3b42adfa12299f279ec9ac7c5670e9b0045a4ad2430c93af7a465f3bc83d4f9e3aa8976e6681ce660c827770de2aa1a68c72dfc3cae74393999b2e4df302e72691373aa60199bd827398efac18810f87a952591c61817c849513999df0b6c11436d6d400effcfacc14f2099cd6768913c5a435a0fd0c8e20ab2dbcd147564a2228c93b60b99ae2d94efde6ac640a09d9331130c539367078c41c915067ac9122268dc350439bf3379e9bc01b32025e9bd111aa65c829e89e83f0135ba740572c5f525c73f95faa608e39e55e62c6fcbd37de9775b891212a758d59bceb7a0eb30d7c7f6cd35c1399984291053b30f29fc5feed6cedf7adfe21962ab17b8ebde5089b1fec0d97d7-e5c4e5a1d726f600c22ebfd9f186148a1449755fd79a69ceabfe2aa"
}
}
'''
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_get_ip_ranges = do_get_ip_ranges
return ipam.get_ip_ranges()
def auth_session(uri, auth, cert):
auth_uri = f'{uri}/user/'
req = requests.post(auth_uri, auth=auth, verify=cert)
if req.status_code != 200:
raise requests.exceptions.RequestException('Authentication Failure!')
print('Auth success.')
token = {"token": req.json()['data']['token']}
return token
def do_get_ip_ranges(self, auth_credentials, cert):
# Build variables
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
hostname = self.inputs["endpoint"]["endpointProperties"]["hostName"]
apiAppId = self.inputs["endpoint"]["endpointProperties"]["apiAppId"]
uri = f'https://{hostname}/api/{apiAppId}/'
auth = (username, password)
# Auth to API
token = auth_session(uri, auth, cert)
# Request list of subnets
subnet_uri = f'{uri}/subnets/'
ipRanges = []
req = requests.get(subnet_uri, headers=token, verify=cert)
subnets = req.json()['data']
for subnet in subnets:
ipRange = {}
ipRange['id'] = str(subnet['id'])
ipRange['name'] = f"{str(subnet['subnet'])}/{str(subnet['mask'])}"
ipRange['description'] = str(subnet['description'])
logging.info(f"Found subnet: {ipRange['name']} - {ipRange['description']}.")
network = ipaddress.ip_network(str(subnet['subnet']) + '/' + str(subnet['mask']))
ipRange['ipVersion'] = 'IPv' + str(network.version)
ipRange['startIpAddress'] = str(network[10])
ipRange['endIpAddress'] = str(network[-6])
ipRange['subnetPrefixLength'] = str(subnet['mask'])
logging.debug(ipRange)
ipRanges.append(ipRange)
# Return results to vRA
result = {
"ipRanges" : ipRanges
}
return result

View File

@ -0,0 +1 @@
requests==2.21.0

View File

@ -0,0 +1,92 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
import logging
"""
Example payload:
"inputs": {
"resourceInfo": {
"id": "11f912e71454a075574a728848458",
"name": "external-ipam-it-mcm-323412",
"description": "test",
"type": "VM",
"owner": "mdzhigarov@vmware.com",
"orgId": "ce811934-ea1a-4f53-b6ec-465e6ca7d126",
"properties": {
"osType": "WINDOWS",
"vcUuid": "ff257ed9-070b-45eb-b2e7-d63926d5bdd7",
"__moref": "VirtualMachine:vm-288560",
"memoryGB": "4",
"datacenter": "Datacenter:datacenter-2",
"provisionGB": "1",
"__dcSelfLink": "/resources/groups/b28c7b8de065f07558b1612fce028",
"softwareName": "Microsoft Windows XP Professional (32-bit)",
"__computeType": "VirtualMachine",
"__hasSnapshot": "false",
"__placementLink": "/resources/compute/9bdc98681fb8b27557252188607b8",
"__computeHostLink": "/resources/compute/9bdc98681fb8b27557252188607b8"
}
},
"addressInfos": [
{
"nicIndex": 0,
"address": "10.23.117.5",
"macAddress": "00:30:26:a7:23:26"
}
],
"endpoint": {
"id": "f097759d8736675585c4c5d272cd",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"certificate": "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
"""
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_update_record = do_update_record
return ipam.update_record()
def do_update_record(self, auth_credentials, cert):
# Your implemention goes here
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
update_result = []
resource = self.inputs["resourceInfo"]
for update_record in self.inputs["addressInfos"]:
update_result.append(update(resource, self.inputs, update_record))
assert len(update_result) > 0
return {
"updateResults": update_result
}
def update(resource, inputs, update_record):
try:
## Plug your implementation here to update the MAC address of an already allocate ip record
## Search the record and update its MAC
mac = update_record["macAddress"]
return "Success"
except Exception as e:
logging.error(f"Failed to update record {update_record}: {e}")
raise e

View File

@ -0,0 +1,11 @@
# User libs go here
#
requests==2.21.0
#
# ----------------- #
#
# The following libs are needed by vra_ipam_utils to fetch the server certificate and return it to vRA in case it is self signed or not automatically trusted
ndg-httpsclient
pyopenssl
pyasn1
idna

View File

@ -0,0 +1,77 @@
"""
Copyright (c) 2020 VMware, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
This product may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
"""
import requests
from vra_ipam_utils.ipam import IPAM
from vra_ipam_utils.exceptions import InvalidCertificateException
import logging
'''
Example payload:
"inputs": {
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0",
"endpointProperties": {
"hostName": "sampleipam.sof-mbu.eng.vmware.com"
}
}
'''
def handler(context, inputs):
ipam = IPAM(context, inputs)
IPAM.do_validate_endpoint = do_validate_endpoint
return ipam.validate_endpoint()
def auth_session(uri, auth, cert):
auth_uri = f'{uri}/user/'
req = requests.post(auth_uri, auth=auth, verify=cert)
## We don't need to handle errors or save the token here since we're just validating the endpoint
# if req.status_code != 200:
# raise requests.exceptions.RequestException('Authentication Failed!')
# logging.info('Authentication successful.')
# token = {"token": req.json()['data']['token']}
# return token
return req
def do_validate_endpoint(self, auth_credentials, cert):
# Build variables
username = auth_credentials["privateKeyId"]
password = auth_credentials["privateKey"]
hostname = self.inputs["endpointProperties"]["hostName"]
apiAppId = self.inputs["endpointProperties"]["apiAppId"]
uri = f'https://{hostname}/api/{apiAppId}/'
auth = (username, password)
# Test auth connection
try:
response = auth_session(uri, auth, cert)
if response.status_code == 200:
return {
"message": "Validated successfully",
"statusCode": "200"
}
elif response.status_code == 500 and response.json()['message'] == 'Invalid username or password':
logging.error(f"Invalid credentials error: {str(response.content)}")
raise Exception(f"Invalid credentials error: {str(response.content)}")
else:
raise Exception(f"Failed to connect: {str(response.content)}")
except Exception as e:
""" In case of SSL validation error, a InvalidCertificateException is raised.
So that the IPAM SDK can go ahead and fetch the server certificate
and display it to the user for manual acceptance.
"""
if "SSLCertVerificationError" in str(e) or "CERTIFICATE_VERIFY_FAILED" in str(e) or 'certificate verify failed' in str(e):
raise InvalidCertificateException("certificate verify failed", self.inputs["endpointProperties"]["hostName"], 443) from e
raise e

View File

View File

@ -0,0 +1,58 @@
---
exportVersion: "1"
exportId: "@provider.name@_AllocateIP"
name: "@provider.name@_AllocateIP"
runtime: "python"
entrypoint: "source.handler"
inputs:
resourceInfo:
id: "11f912e71454a075574a728848458"
name: "external-ipam-it-mcm-323412"
description: "test"
type: "VM"
owner: "mdzhigarov@vmware.com"
orgId: "ce811934-ea1a-4f53-b6ec-465e6ca7d126"
properties:
osType: "WINDOWS"
vcUuid: "ff257ed9-070b-45eb-b2e7-d63926d5bdd7"
__moref: "VirtualMachine:vm-288560"
memoryGB: "4"
datacenter: "Datacenter:datacenter-2"
provisionGB: "1"
__dcSelfLink: "/resources/groups/b28c7b8de065f07558b1612fce028"
softwareName: "Microsoft Windows XP Professional (32-bit)"
__computeType: "VirtualMachine"
__hasSnapshot: "false"
__placementLink: "/resources/compute/9bdc98681fb8b27557252188607b8"
__computeHostLink: "/resources/compute/9bdc98681fb8b27557252188607b8"
ipAllocations:
- id: "111bb2f0-02fd-4983-94d2-8ac11768150f"
ipRangeIds: ["network/ZG5zLm5ldHdvcmskMTAuMjMuMTE3LjAvMjQvMA:10.23.117.0/24/default"]
nicIndex: "0"
isPrimary: "true"
size: "1"
properties:
__moref: "DistributedVirtualPortgroup:dvportgroup-307087"
__dvsUuid: "0c 8c 0b 50 46 b6 1c f2-e8 63 f4 24 24 d7 24 6c"
__dcSelfLink: "/resources/groups/abe46b8cfa663a7558b28a6ffe088"
__computeType: "DistributedVirtualPortgroup"
__portgroupKey: "dvportgroup-307087"
endpoint:
id: "f097759d8736675585c4c5d272cd"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
projectId: "111bb2f0-02fd-4983-94d2-8ac11768150f"
providerId: "d8a5e3f2-d839-4365-af5b-f48de588fdc1"
certificate: "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 3000

View File

@ -0,0 +1,53 @@
---
exportVersion: "1"
exportId: "@provider.name@_AllocateIPRange"
name: "@provider.name@_AllocateIPRange"
runtime: "python"
entrypoint: "source.handler"
inputs:
resourceInfo:
id: "/resources/sub-networks/255ac10c-0198-4a92-9414-b8e0c23c0204"
name: net1-mcm223-126361015194
type: SUBNET
owner: "mdzhigarov@vmware.com"
orgId: "ce811934-ea1a-4f53-b6ec-465e6ca7d126"
properties:
networkType: PRIVATE
datacenterId: Datacenter:datacenter-21
__networkCidr: 192.168.197.0/28
__deploymentLink: "/resources/deployments/f77fbe4d-9e78-4b1b-93b0-024d342d0872"
__infrastructureUse: 'true'
__composition_context_id: f77fbe4d-9e78-4b1b-93b0-024d342d0872
__isInfrastructureShareable: 'true'
ipRangeAllocation:
name: net1-mcm223-126361015194
ipBlockIds: ["block1", "block2"]
properties:
networkType: PRIVATE
datacenterId: Datacenter:datacenter-21
__networkCidr: 192.168.197.0/28
__deploymentLink: "/resources/deployments/f77fbe4d-9e78-4b1b-93b0-024d342d0872"
__infrastructureUse: 'true'
__composition_context_id: f77fbe4d-9e78-4b1b-93b0-024d342d0872
__isInfrastructureShareable: 'true'
subnetCidr: 192.168.197.0/28
addressSpaceId: default
endpoint:
id: "f097759d8736675585c4c5d272cd"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
projectId: "111bb2f0-02fd-4983-94d2-8ac11768150f"
providerId: "d8a5e3f2-d839-4365-af5b-f48de588fdc1"
certificate: "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 3000

View File

@ -0,0 +1,50 @@
---
exportVersion: "1"
exportId: "@provider.name@_DeallocateIP"
name: "@provider.name@_DeallocateIP"
runtime: "python"
entrypoint: "source.handler"
inputs:
resourceInfo:
id: "11f912e71454a075574a728848458"
name: "external-ipam-it-mcm-323412"
description: "test"
type: "VM"
owner: "mdzhigarov@vmware.com"
orgId: "ce811934-ea1a-4f53-b6ec-465e6ca7d126"
properties:
osType: "WINDOWS"
vcUuid: "ff257ed9-070b-45eb-b2e7-d63926d5bdd7"
__moref: "VirtualMachine:vm-288560"
memoryGB: "4"
datacenter: "Datacenter:datacenter-2"
provisionGB: "1"
__dcSelfLink: "/resources/groups/b28c7b8de065f07558b1612fce028"
softwareName: "Microsoft Windows XP Professional (32-bit)"
__computeType: "VirtualMachine"
__hasSnapshot: "false"
__placementLink: "/resources/compute/9bdc98681fb8b27557252188607b8"
__computeHostLink: "/resources/compute/9bdc98681fb8b27557252188607b8"
ipDeallocations:
- id: "111bb2f0-02fd-4983-94d2-8ac11768150f"
ipRangeId: "network/ZG5zLm5ldHdvcmskMTAuMjMuMTE3LjAvMjQvMA:10.23.117.0/24/default"
ipAddress: "10.23.117.5"
endpoint:
id: "f097759d8736675585c4c5d272cd"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
projectId: "111bb2f0-02fd-4983-94d2-8ac11768150f"
providerId: "d8a5e3f2-d839-4365-af5b-f48de588fdc1"
certificate: "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 3000

View File

@ -0,0 +1,38 @@
---
exportVersion: "1"
exportId: "@provider.name@_DeallocateIPRange"
name: "@provider.name@_DeallocateIPRange"
runtime: "python"
entrypoint: "source.handler"
inputs:
resourceInfo:
id: "/resources/sub-networks/255ac10c-0198-4a92-9414-b8e0c23c0204"
name: "net1-mcm223-126361015194"
type: "SUBNET"
owner: "mdzhigarov@vmware.com"
orgId: "ce811934-ea1a-4f53-b6ec-465e6ca7d126"
ipRangeDeallocation:
ipRangeId: "network/ZG5zLm5ldHdvcmskMTAuMjMuMTE3LjAvMjQvMA:10.23.117.0/24/default"
addressSpaceIs: "default"
properties:
__subnetName: "net1-mcm223-126361015194"
__subnetRangeCidr: "10.23.117.0/24"
endpoint:
id: "f097759d8736675585c4c5d272cd"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
projectId: "111bb2f0-02fd-4983-94d2-8ac11768150f"
providerId: "d8a5e3f2-d839-4365-af5b-f48de588fdc1"
certificate: "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 3000

View File

@ -0,0 +1,25 @@
---
exportVersion: "1"
exportId: "@provider.name@_GetIPBlocks"
name: "@provider.name@_GetIPBlocks"
runtime: "python"
entrypoint: "source.handler"
inputs:
endpoint:
id: "f097759d8736675585c4c5d272cd"
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
pagingAndSorting:
maxResults: 1000
pageToken: "789c55905d6e02310c84df7d91452a456481168ec04b55950344f9db55dadd384abc056e5f3b42adfa12299f279ec9ac7c5670e9b0045a4ad2430c93af7a465f3bc83d4f9e3aa8976e6681ce660c827770de2aa1a68c72dfc3cae74393999b2e4df302e72691373aa60199bd827398efac18810f87a952591c61817c849513999df0b6c11436d6d400effcfacc14f2099cd6768913c5a435a0fd0c8e20ab2dbcd147564a2228c93b60b99ae2d94efde6ac640a09d9331130c539367078c41c915067ac9122268dc350439bf3379e9bc01b32025e9bd111aa65c829e89e83f0135ba740572c5f525c73f95faa608e39e55e62c6fcbd37de9775b891212a758d59bceb7a0eb30d7c7f6cd35c1399984291053b30f29fc5feed6cedf7adfe21962ab17b8ebde5089b1fec0d97d7-e5c4e5a1d726f600c22ebfd9f186148a1449755fd79a69ceabfe2aa"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 3000

View File

@ -0,0 +1,25 @@
---
exportVersion: "1"
exportId: "@provider.name@_GetIPRanges"
name: "@provider.name@_GetIPRanges"
runtime: "python"
entrypoint: "source.handler"
inputs:
endpoint:
id: "f097759d8736675585c4c5d272cd"
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
pagingAndSorting:
maxResults: 1000
pageToken: "789c55905d6e02310c84df7d91452a456481168ec04b55950344f9db55dadd384abc056e5f3b42adfa12299f279ec9ac7c5670e9b0045a4ad2430c93af7a465f3bc83d4f9e3aa8976e6681ce660c827770de2aa1a68c72dfc3cae74393999b2e4df302e72691373aa60199bd827398efac18810f87a952591c61817c849513999df0b6c11436d6d400effcfacc14f2099cd6768913c5a435a0fd0c8e20ab2dbcd147564a2228c93b60b99ae2d94efde6ac640a09d9331130c539367078c41c915067ac9122268dc350439bf3379e9bc01b32025e9bd111aa65c829e89e83f0135ba740572c5f525c73f95faa608e39e55e62c6fcbd37de9775b891212a758d59bceb7a0eb30d7c7f6cd35c1399984291053b30f29fc5feed6cedf7adfe21962ab17b8ebde5089b1fec0d97d7-e5c4e5a1d726f600c22ebfd9f186148a1449755fd79a69ceabfe2aa"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 3000

View File

@ -0,0 +1,50 @@
---
exportVersion: "1"
exportId: "@provider.name@_Update"
name: "@provider.name@_Update"
runtime: "python"
entrypoint: "source.handler"
inputs:
resourceInfo:
id: "11f912e71454a075574a728848458"
name: "external-ipam-it-mcm-323412"
description: "test"
type: "VM"
owner: "mdzhigarov@vmware.com"
orgId: "ce811934-ea1a-4f53-b6ec-465e6ca7d126"
properties:
osType: "WINDOWS"
vcUuid: "ff257ed9-070b-45eb-b2e7-d63926d5bdd7"
__moref: "VirtualMachine:vm-288560"
memoryGB: "4"
datacenter: "Datacenter:datacenter-2"
provisionGB: "1"
__dcSelfLink: "/resources/groups/b28c7b8de065f07558b1612fce028"
softwareName: "Microsoft Windows XP Professional (32-bit)"
__computeType: "VirtualMachine"
__hasSnapshot: "false"
__placementLink: "/resources/compute/9bdc98681fb8b27557252188607b8"
__computeHostLink: "/resources/compute/9bdc98681fb8b27557252188607b8"
addressInfos:
- nicIndex: 0
address: "10.23.117.1"
macAddress: "00:30:26:a7:23:26"
endpoint:
id: "f097759d8736675585c4c5d272cd"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
projectId: "111bb2f0-02fd-4983-94d2-8ac11768150f"
providerId: "d8a5e3f2-d839-4365-af5b-f48de588fdc1"
certificate: "-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 3000

View File

@ -0,0 +1,20 @@
---
exportVersion: "1"
exportId: "@provider.name@_ValidateEndpoint"
name: "@provider.name@_ValidateEndpoint"
runtime: "python"
entrypoint: "source.handler"
inputs:
authCredentialsLink: "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
endpointProperties:
hostName: "sampleipam.sof-mbu.eng.vmware.com"
timeoutSeconds: 600
deploymentTimeoutSeconds: 600
actionType: "SCRIPT"
configuration:
const-providers:
- ""
const_azure-system_managed_identity: false
actionTemplateName: "Custom script"
actionTemplateNamespace: "com.vmware.automation.abx"
memoryInMB: 600

View File

@ -0,0 +1,74 @@
{
"layout":{
"pages":[
{
"id":"Sample IPAM",
"title":"Sample IPAM endpoint",
"sections":[
{
"id":"section_1",
"fields":[
{
"id":"apiAppId",
"display":"textField"
},
{
"id":"privateKeyId",
"display":"textField"
},
{
"id":"privateKey",
"display":"passwordField"
},
{
"id":"hostName",
"display":"textField"
}
]
}
]
}
]
},
"schema":{
"apiAppId":{
"type":{
"dataType":"string"
},
"label":"API App ID",
"constraints":{
"required":true
}
},
"privateKeyId":{
"type":{
"dataType":"string"
},
"label":"Username",
"constraints":{
"required":true
}
},
"privateKey":{
"label":"Password",
"type":{
"dataType":"secureString"
},
"constraints":{
"required":true
}
},
"hostName":{
"type":{
"dataType":"string"
},
"label":"Hostname",
"constraints":{
"required":true
}
}
},
"options":{
}
}

BIN
src/main/resources/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,19 @@
---
name: "@provider.name@"
description: "@provider.description@"
version: "@provider.version@"
abxConfig:
allocateIPActionId: "@provider.name@_AllocateIP"
deallocateIPActionId: "@provider.name@_DeallocateIP"
validateEndpointActionId: "@provider.name@_ValidateEndpoint"
updateResourceActionId: "@provider.name@_Update"
getIPRangesActionId: "@provider.name@_GetIPRanges"
allocateNetworkActionId: "@provider.name@_AllocateIPRange"
deallocateNetworkActionId: "@provider.name@_DeallocateIPRange"
getIPBlocksActionId: "@provider.name@_GetIPBlocks"
properties:
@supportsAddressSpaces@
supportsUpdateRecord: @provider.supportsUpdateRecord@
supportsOnDemandNetworks: @provider.supportsOnDemandNetworks@

View File

@ -0,0 +1,63 @@
input = {
"resourceInfo": {
"id": "11f912e71454a075574a728848458",
"name": "external-ipam-it-mcm-3234139",
"description": "test",
"type": "VM",
"owner": "mdzhigarov@vmware.com",
"orgId": "ce811934-ea1a-4f53-b6ec-465e6ca7d126",
"properties": {
"osType": "WINDOWS",
"vcUuid": "ff257ed9-070b-45eb-b2e7-d63926d5bdd7",
"__moref": "VirtualMachine:vm-288560",
"memoryGB": "4",
"datacenter": "Datacenter:datacenter-2",
"provisionGB": "1",
"__dcSelfLink": "/resources/groups/b28c7b8de065f07558b1612fce028",
"softwareName": "Microsoft Windows XP Professional (32-bit)",
"__computeType": "VirtualMachine",
"__hasSnapshot": "false",
"__placementLink": "/resources/compute/9bdc98681fb8b27557252188607b8",
"__computeHostLink": "/resources/compute/9bdc98681fb8b27557252188607b8"
}
},
"ipAllocations": [{
"id": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"ipRangeIds": ["range/ZG5zLmRoY3BfcmFuZ2UkMTAuMTAuMjQuMjEvMTAuMTAuMjQuMjIvLy8xLw:10.10.24.21/10.10.24.22/mdzh-net", "range/ZG5zLmRoY3BfcmFuZ2UkMTAuMTAuMjQuMTAvMTAuMTAuMjQuMjAvLy8xLw:10.10.24.10/10.10.24.20/mdzh-net"],
#"ipRangeIds": ["network/ZG5zLm5ldHdvcmskMTAuMTAuMjMuMTYvMjgvMQ:10.10.23.16/28/mdzh-net"],
"nicIndex": "0",
"isPrimary": "true",
"size": "1",
"properties": {
"__moref": "DistributedVirtualPortgroup:dvportgroup-307087",
"__dvsUuid": "0c 8c 0b 50 46 b6 1c f2-e8 63 f4 24 24 d7 24 6c",
"__dcSelfLink": "/resources/groups/abe46b8cfa663a7558b28a6ffe088",
"__computeType": "DistributedVirtualPortgroup",
"__portgroupKey": "dvportgroup-307087"
}
}],
"endpoint": {
"id": "112bb240-02fd-4983-9432-8ac11768150f",
"endpointProperties": {
"hostName": "infoblox.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"isLocalEnv":"true",
"certificate": """-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"""
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
import unittest
from unittest import TestCase
from unittest.mock import MagicMock
from unittest.mock import Mock
from unittest.mock import patch
context = MagicMock()
auth_credentials = {"status": 200, "content": "{\"privateKeyId\": \"admin\", \"privateKey\": \"VMware1!\"}"}
subnet_ranges = {"status": 200, "content": "{\"totalCount\": 1, \"documents\": {\"/resources/subnet-ranges/c19bd2921af950755777fd33fe060\": {\"domain\": \"test.local\"}}}"}
context.request.side_effect = [auth_credentials, subnet_ranges, subnet_ranges]
print(handler(context, input))

View File

@ -0,0 +1,60 @@
from src.main.python.deallocate_ip.source import handler
input = {
"resourceInfo": {
"id": "/resources/compute/226478cf7e3296b7",
"name": "ipantchev-test",
"description": "test",
"type": "VM",
"owner": "ipantchev@vmware.com",
"orgId": "ce811934-ea1a-4f53-b6ec-465e6ca7d126",
"properties": {
"osType": "WINDOWS",
"vcUuid": "ff257ed9-070b-45eb-b2e7-d63926d5bdd7",
"__moref": "VirtualMachine:vm-288560",
"memoryGB": "4",
"datacenter": "Datacenter:datacenter-2",
"provisionGB": "1",
"__dcSelfLink": "/resources/groups/b28c7b8de065f07558b1612fce028",
"softwareName": "Microsoft Windows XP Professional (32-bit)",
"__computeType": "VirtualMachine",
"__hasSnapshot": "false",
"__placementLink": "/resources/compute/9bdc98681fb8b27557252188607b8",
"__computeHostLink": "/resources/compute/9bdc98681fb8b27557252188607b8"
}
},
"ipDeallocations": [{
"id": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"ipAddress": "10.10.24.1",
"ipRangeId": "range/ZG5zLmRoY3BfcmFuZ2UkMTAuMTAuMjQuMjEvMTAuMTAuMjQuMjIvLy8xLw:10.10.24.21/10.10.24.22/mdzh-net",
"nicIndex": "0",
"isPrimary": "true",
"size": "1",
"properties": {
"__moref": "DistributedVirtualPortgroup:dvportgroup-307087",
"__dvsUuid": "0c 8c 0b 50 46 b6 1c f2-e8 63 f4 24 24 d7 24 6c",
"__dcSelfLink": "/resources/groups/abe46b8cfa663a7558b28a6ffe088",
"__computeType": "DistributedVirtualPortgroup",
"__portgroupKey": "dvportgroup-307087"
}
}],
"endpoint": {
"endpointProperties": {
"hostName": "infoblox.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"isLocalEnv":"true",
"certificate": """-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"""
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
from unittest.mock import MagicMock
context = MagicMock()
auth_credentials = {"status": 200, "content": "{\"privateKeyId\": \"admin\", \"privateKey\": \"VMware1!\"}"}
subnet_ranges = {"status": 200, "content": "{\"totalCount\": 1, \"documents\": {\"/resources/subnet-ranges/c19bd2921af950755777fd33fe060\": {\"domain\": \"test.local\"}}}"}
context.request.side_effect = [auth_credentials, auth_credentials, subnet_ranges, subnet_ranges]
print(handler(context, input))

View File

@ -0,0 +1,29 @@
input = {
"pagingAndSorting": {
"maxResults": 1000,
},
"endpoint": {
"id": "112bb240-02fd-4983-9432-8ac11768150f",
"endpointProperties": {
"hostName": "infoblox.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"isLocalEnv":"true",
"certificate": """-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"""
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
import unittest
from unittest import TestCase
from unittest.mock import MagicMock
from unittest.mock import Mock
from unittest.mock import patch
context = MagicMock()
auth_credentials = {"status": 200, "content": "{\"privateKeyId\": \"admin\", \"privateKey\": \"VMware1!\"}"}
subnet_ranges = {"status": 200, "content": "{\"totalCount\": 1, \"documents\": {\"/resources/subnet-ranges/c19bd2921af950755777fd33fe060\": {\"domain\": \"test.local\"}}}"}
context.request.side_effect = [auth_credentials, subnet_ranges, subnet_ranges]
print(handler(context, input))

View File

@ -0,0 +1,53 @@
input = {
"resourceInfo": {
"id": "5613490d-e64d-4797-ad70-3062d648b332",
"name": "external-ipam-it-mcm-3234139",
"description": "test",
"type": "VM",
"owner": "vraikov@vmware.com",
"hostname": "bond-006",
"orgId": "ce811934-ea1a-4f53-b6ec-465e6ca7d126",
"properties": {
"osType": "WINDOWS",
"vcUuid": "ff257ed9-070b-45eb-b2e7-d63926d5bdd7",
"__moref": "VirtualMachine:vm-288560",
"memoryGB": "4",
"datacenter": "Datacenter:datacenter-2",
"provisionGB": "1",
"__dcSelfLink": "/resources/groups/b28c7b8de065f07558b1612fce028",
"softwareName": "Microsoft Windows XP Professional (32-bit)",
"__computeType": "VirtualMachine",
"__hasSnapshot": "false",
"__placementLink": "/resources/compute/9bdc98681fb8b27557252188607b8",
"__computeHostLink": "/resources/compute/9bdc98681fb8b27557252188607b8"
}
},
"addressInfos": [{
"nicIndex": 0,
"address": "10.23.117.1",
"macAddress": "00:30:26:a7:23:26"
}],
"endpoint": {
"endpointProperties": {
"hostName": "infoblox.sof-mbu.eng.vmware.com",
"projectId": "111bb2f0-02fd-4983-94d2-8ac11768150f",
"providerId": "d8a5e3f2-d839-4365-af5b-f48de588fdc1",
"isLocalEnv":"true",
"certificate": """-----BEGIN CERTIFICATE-----\nMIID0jCCArqgAwIBAgIQQaJF55UCb58f9KgQLD/QgTANBgkqhkiG9w0BAQUFADCB\niTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1\nbm55dmFsZTERMA8GA1UEChMISW5mb2Jsb3gxFDASBgNVBAsTC0VuZ2luZWVyaW5n\nMSgwJgYDVQQDEx9pbmZvYmxveC5zb2YtbWJ1LmVuZy52bXdhcmUuY29tMB4XDTE5\nMDEyOTEzMDExMloXDTIwMDEyOTEzMDExMlowgYkxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxETAPBgNVBAoTCElu\nZm9ibG94MRQwEgYDVQQLEwtFbmdpbmVlcmluZzEoMCYGA1UEAxMfaW5mb2Jsb3gu\nc29mLW1idS5lbmcudm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMMLNTqbAri6rt/H8iC4UgRdN0qj+wk0R2blmD9h1BiZJTeQk1r9i2rz\nzUOZHvE8Bld8m8xJ+nysWHaoFFGTX8bOd/p20oJBGbCLqXtoLMMBGAlP7nzWGBXH\nBYUS7kMv/CG+PSX0uuB0pRbhwOFq8Y69m4HRnn2X0WJGuu+v0FmRK/1m/kCacHga\nMBKaIgbwN72rW1t/MK0ijogmLR1ASY4FlMn7OBHIEUzO+dWFBh+gPDjoBECTTH8W\n5AK9TnYdxwAtJRYWmnVqtLoT3bImtSfI4YLUtpr9r13Kv5FkYVbXov1KBrQPbYyp\n72uT2ZgDJT4YUuWyKpMppgw1VcG3MosCAwEAAaM0MDIwMAYDVR0RBCkwJ4cEChda\nCoIfaW5mb2Jsb3guc29mLW1idS5lbmcudm13YXJlLmNvbTANBgkqhkiG9w0BAQUF\nAAOCAQEAXFPIh00VI55Sdfx+czbBb4rJz3c1xgN7pbV46K0nGI8S6ufAQPgLvZJ6\ng2T/mpo0FTuWCz1IE9PC28276vwv+xJZQwQyoUq4lhT6At84NWN+ZdLEe+aBAq+Y\nxUcIWzcKv8WdnlS5DRQxnw6pQCBdisnaFoEIzngQV8oYeIemW4Hcmb//yeykbZKJ\n0GTtK5Pud+kCkYmMHpmhH21q+3aRIcdzOYIoXhdzmIKG0Och97HthqpvRfOeWQ/A\nPDbxqQ2R/3D0gt9jWPCG7c0lB8Ynl24jLBB0RhY6mBrYpFbtXBQSEciUDRJVB2zL\nV8nJiMdhj+Q+ZmtSwhNRvi2qvWAUJQ==\n-----END CERTIFICATE-----\n"""
},
"authCredentialsLink": "/core/auth/credentials/13c9cbade08950755898c4b89c4a0"
}
}
import unittest
from unittest import TestCase
from unittest.mock import MagicMock
from unittest.mock import Mock
from unittest.mock import patch
context = MagicMock()
auth_credentials = {"status": 200, "content": "{\"privateKeyId\": \"admin\", \"privateKey\": \"VMware1!\"}"}
subnet_ranges = {"status": 200, "content": "{\"totalCount\": 1, \"documents\": {\"/resources/subnet-ranges/c19bd2921af950755777fd33fe060\": {\"domain\": \"test.local\"}}}"}
context.request.side_effect = [auth_credentials, auth_credentials, subnet_ranges, subnet_ranges]
print(handler(context, input))

78
venv_tango/bin/activate Normal file
View File

@ -0,0 +1,78 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
unset -f pydoc >/dev/null 2>&1
# reset old environment variables
# ! [ -z ${VAR+_} ] returns true if VAR is declared at all
if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then
PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null
fi
if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "${1-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/home/jbowdre/projects/tango-ipam-sdk/venv_tango"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
if ! [ -z "${PYTHONHOME+_}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
_OLD_VIRTUAL_PS1="$PS1"
if [ "x" != x ] ; then
PS1="$PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1"
fi
export PS1
fi
# Make sure to unalias pydoc if it's already there
alias pydoc 2>/dev/null >/dev/null && unalias pydoc
pydoc () {
python -m pydoc "$@"
}
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null
fi

View File

@ -0,0 +1,36 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV "/home/jbowdre/projects/tango-ipam-sdk/venv_tango"
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
if ("" != "") then
set env_name = ""
else
set env_name = `basename "$VIRTUAL_ENV"`
endif
# Could be in a non-interactive environment,
# in which case, $prompt is undefined and we wouldn't
# care about the prompt anyway.
if ( $?prompt ) then
set _OLD_VIRTUAL_PROMPT="$prompt"
set prompt = "[$env_name] $prompt"
endif
unset env_name
alias pydoc python -m pydoc
rehash

View File

@ -0,0 +1,76 @@
# This file must be used using `. bin/activate.fish` *within a running fish ( http://fishshell.com ) session*.
# Do not run it directly.
function deactivate -d 'Exit virtualenv mode and return to the normal environment.'
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
# Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`.
set -l fish_function_path
# Erase virtualenv's `fish_prompt` and restore the original.
functions -e fish_prompt
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
end
set -e VIRTUAL_ENV
if test "$argv[1]" != 'nondestructive'
# Self-destruct!
functions -e pydoc
functions -e deactivate
end
end
# Unset irrelevant variables.
deactivate nondestructive
set -gx VIRTUAL_ENV "/home/jbowdre/projects/tango-ipam-sdk/venv_tango"
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
# Unset `$PYTHONHOME` if set.
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
function pydoc
python -m pydoc $argv
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# Copy the current `fish_prompt` function as `_old_fish_prompt`.
functions -c fish_prompt _old_fish_prompt
function fish_prompt
# Save the current $status, for fish_prompts that display it.
set -l old_status $status
# Prompt override provided?
# If not, just prepend the environment name.
if test -n ""
printf '%s%s' "" (set_color normal)
else
printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV")
end
# Restore the original $status
echo "exit $old_status" | source
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
end

View File

@ -0,0 +1,34 @@
"""By using execfile(this_file, dict(__file__=this_file)) you will
activate this virtualenv environment.
This can be used when you must use an existing Python interpreter, not
the virtualenv bin/python
"""
try:
__file__
except NameError:
raise AssertionError(
"You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))")
import sys
import os
old_os_path = os.environ.get('PATH', '')
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if sys.platform == 'win32':
site_packages = os.path.join(base, 'Lib', 'site-packages')
else:
site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = base
# Move the added items to the front of the path:
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path

8
venv_tango/bin/chardetect Executable file
View File

@ -0,0 +1,8 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from chardet.cli.chardetect import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
venv_tango/bin/easy_install Executable file
View File

@ -0,0 +1,10 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
venv_tango/bin/easy_install-3.7 Executable file
View File

@ -0,0 +1,10 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
venv_tango/bin/pip Executable file
View File

@ -0,0 +1,10 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
venv_tango/bin/pip3 Executable file
View File

@ -0,0 +1,10 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
venv_tango/bin/pip3.7 Executable file
View File

@ -0,0 +1,10 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

1
venv_tango/bin/python Symbolic link
View File

@ -0,0 +1 @@
python3

78
venv_tango/bin/python-config Executable file
View File

@ -0,0 +1,78 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python
import sys
import getopt
import sysconfig
valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags',
'ldflags', 'help']
if sys.version_info >= (3, 2):
valid_opts.insert(-1, 'extension-suffix')
valid_opts.append('abiflags')
if sys.version_info >= (3, 3):
valid_opts.append('configdir')
def exit_with_usage(code=1):
sys.stderr.write("Usage: {0} [{1}]\n".format(
sys.argv[0], '|'.join('--'+opt for opt in valid_opts)))
sys.exit(code)
try:
opts, args = getopt.getopt(sys.argv[1:], '', valid_opts)
except getopt.error:
exit_with_usage()
if not opts:
exit_with_usage()
pyver = sysconfig.get_config_var('VERSION')
getvar = sysconfig.get_config_var
opt_flags = [flag for (flag, val) in opts]
if '--help' in opt_flags:
exit_with_usage(code=0)
for opt in opt_flags:
if opt == '--prefix':
print(sysconfig.get_config_var('prefix'))
elif opt == '--exec-prefix':
print(sysconfig.get_config_var('exec_prefix'))
elif opt in ('--includes', '--cflags'):
flags = ['-I' + sysconfig.get_path('include'),
'-I' + sysconfig.get_path('platinclude')]
if opt == '--cflags':
flags.extend(getvar('CFLAGS').split())
print(' '.join(flags))
elif opt in ('--libs', '--ldflags'):
abiflags = getattr(sys, 'abiflags', '')
libs = ['-lpython' + pyver + abiflags]
libs += getvar('LIBS').split()
libs += getvar('SYSLIBS').split()
# add the prefix/lib/pythonX.Y/config dir, but only if there is no
# shared library in prefix/lib/.
if opt == '--ldflags':
if not getvar('Py_ENABLE_SHARED'):
libs.insert(0, '-L' + getvar('LIBPL'))
if not getvar('PYTHONFRAMEWORK'):
libs.extend(getvar('LINKFORSHARED').split())
print(' '.join(libs))
elif opt == '--extension-suffix':
ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
if ext_suffix is None:
ext_suffix = sysconfig.get_config_var('SO')
print(ext_suffix)
elif opt == '--abiflags':
if not getattr(sys, 'abiflags', None):
exit_with_usage()
print(sys.abiflags)
elif opt == '--configdir':
print(sysconfig.get_config_var('LIBPL'))

BIN
venv_tango/bin/python3 Executable file

Binary file not shown.

1
venv_tango/bin/python3.7 Symbolic link
View File

@ -0,0 +1 @@
python3

10
venv_tango/bin/wheel Executable file
View File

@ -0,0 +1,10 @@
#!/home/jbowdre/projects/tango-ipam-sdk/venv_tango/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from wheel.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@ -0,0 +1 @@
/usr/lib/python3.7/__future__.py

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More