Hello, I'm attempting to import a configuration element via vCO's REST API (5.5.1 appliance), documented here: http://pubs.vmware.com/vsphere-55/index.jsp?topic=%2Fcom.vmware.vsphere.vco_develop_web_services.doc...
The doc states that you should add request headers to define the properties of the configuration element that you want to import, but gives no specifics. I've tried a few variations but each yield error 400 (bad request). For the purposes of this post I'm using vCO as the REST client as well. I think there may be a chicken and egg issue here, in that you probably have to define a configuration element category (folder) relationship to the imported configuration element - not sure how to do this, but how else would it know where to store the configuration element being imported?
Here's what I've tried:
// I have pre-defined a REST host on the vCO server that points to itself (var restHost)
// restHost.url is https://<vco IP>:8281/vco/api
var reqString = restHost.url + "/configurations/";
System.log("Request Query: " + reqString);
// Got the following content from a REST query to export a config element - this is a vanilla config element
var xmlContent = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"yes\"?>\n<config-element " +
// I've tried both omitting and including the id
//"id=\"CB808080808080808080808080808080038A808001334613384319bad96d0cacb\" +
"version=\"0.0.0\" >\n" +
"<display-name><![CDATA[test_element]]></display-name>\n<atts>\n" +
"</atts>\n</config-element>\n";
var req = restHost.createRequest("POST", reqString);
req.contentType = "application/vcoobject+xml;charset=UTF-8";
req.setHeader("contentAsString", xmlContent);
var response = req.execute();
System.log("Response: " + response.toSource());
httpResponse:HTTP/1.1 400 Bad Request
VMware Documentation:
1 | In a REST client application, add request headers to define the properties of the configuration element that you want to import. |
2 | Make a POST request at the URL of the configuration element objects: POST http://{vcoHost}:{port}/vco/api/configurations/ |
If the POST request is successful, you receive the status code 202.
Not sure if the vCO REST plug-in supports multi-part content directly.
Do you need to import configuration elements programatically? If not, the easiest way would be to import them from shell script or from terminal using curl. Something like the following command:
curl -i -v -k -u user:password -X POST https://10.23.12.20:8281/vco/api/configurations -F categoryId=8a978c4b46aa6b9a0146aa6d116d0008 -F file=@d:/downloads/abcconfig.vsoconf
where:
user:password - your vCO credentials
10.23.12.20 - your vCO server address/IP
8a978c4b46aa6b9a0146aa6d116d0008 - ID of the configuration elements category
d:/downloads/abcconfig.vsoconf - path to the file containing configuration elements you want to import
According the documentation
....
Prerequisites
The configuration element binary content should be available as multi-part content. For details, see RFC-2387.
....
This endpoint is used to import existing configuration not to create new one.
Aditional information regarding vCO REST API is available within vCO server itself https://vco_ip:8281/vco/api/docs/
There is also sample request for importing vCO Configuration element https://localhost:8281/vco/api/docs/resource_Configuration%20Service.html#.configurations
POST since: 5.1.0
A REST endpoint for importing configuration.
Imports configuration in a given category. The configuration binary content should be available as multi-part content (see RFC-2387 for details).
Details of working with multi-part resources depend on the used client's HTTP/REST library. For example, in Spring it will look like:
Sample client code:
-------------------
String url = "http://127.0.0.1:8280/api/configurations/";
MultiValueMap parts = new LinkedMultiValueMap();
Resource r = new FileSystemResource("D:/path/to/some.vsoconf");
parts.put("file", Arrays.asList(r));
parts.put("categoryId", "828080808080808080808080808080807F818080013217004819830adebdb10ea");
new RestTemplate().postForLocation(url, parts);
-------------------
Not sure if the vCO REST plug-in supports multi-part content directly.
Do you need to import configuration elements programatically? If not, the easiest way would be to import them from shell script or from terminal using curl. Something like the following command:
curl -i -v -k -u user:password -X POST https://10.23.12.20:8281/vco/api/configurations -F categoryId=8a978c4b46aa6b9a0146aa6d116d0008 -F file=@d:/downloads/abcconfig.vsoconf
where:
user:password - your vCO credentials
10.23.12.20 - your vCO server address/IP
8a978c4b46aa6b9a0146aa6d116d0008 - ID of the configuration elements category
d:/downloads/abcconfig.vsoconf - path to the file containing configuration elements you want to import
Hi Ilian, thanks for the very helpful responses. I am attempting to import the configuration elements programatically. Using the vCO server itself would be most convenient but I can use curl in a pinch. Too bad there's not a way to create or delete config elements within a vCO scripting class directly.
I could only speculate here, but maybe the idea behind not exposing a scripting API to create/delete configuration elements is that the structure of configuration categories/elements is relatively static, and the dynamic part is the attributes/values of the configuration elements. So you are creating categories/elements by deploying a plugin or importing a package, and after that in scripting you get access to categories/elements (via Server.getConfigurationElementCategoryWithPath(), etc.) and, once you have the config element, you can add/modify/remove its attributes and values with config element's API removeAttributeWithKey()/setAttributeWithKey().
Config elements were designed to be static. The fact that you can add an attribute programmatically is indeed a bug.
You can use resource elements to have the functionality you are looking for.
Hi Ilian, Chris, thanks for your comments and continued contributions to the vCO community. I do agree with where you are coming from regarding resource versus config elements, and if I were writing a brand new workflow/system I would definitely use resource elements as you suggest. However in this case I am integrating another system with an existing vCO implementation that utilizes static config elements, and I need to create and initialize elements in a specific category based on values in another system. I don't want to introduce more risk by re-writing dozens of existing flows/actions to use resource elements and have factored for the limitations of config elements (no support for locking, values are static, programmatic deletion/creation will orphan linked workflow attributes). That said, I do see why you would omit this functionality from vCO's native scripting class.
Even if you don't agree with my use case, I wouldn't consider the capability of adding a config element programmatically a bug. The fact that the REST API allows for manipulation of all things vCO is a testament to the openness and flexibility of vCO, giving the developer choice, which is also why I keep advocating it's relevance in multi-vendor solutions.
Hello hello,
I have done the same in PowerShell and it's work fine.
Maybe that can be helpful to someone:
#API authentication
$username = 'vcoadmin'
$upassword = 'vcoadmin'
$auth = $username + ':' + $upassword
$Encoded = [System.Text.Encoding]::UTF8.GetBytes($auth)
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)
$headers = @{"Authorization"="Basic $($EncodedPassword)";}
# uri
$vcoapi = "https://"+$vCOfqdn+":8281/vco/api"
$vsoconfname = "filename.vsoconf"
# Download current ConfigurationElement folder structure:
$folderCategories = Invoke-WebRequest -uri:"$vcoapi/categories?categoryType=ConfigurationElementCategory" -Method:"GET" -Headers:$headers -ContentType:"application/json"
##### Find the "categoryID" (folder ID) ######
$categoryId = (($folderCategories.Content | ConvertFrom-Json).link | where {$_.attributes -match "Folder name"}).href.Split("/")[-2]
######## file content to upload (with configuration element definition) its the same format than when you export conf element from vCO ##############
$filecontent = @"
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<config-element id="2b41d7cd-8dfb-46a2-b4fb-23884f6050c9" version="1.0.0" >
<display-name><![CDATA[CUSTOM_FIELDS]]></display-name>
<atts>
<att name='VCO_SERVER' type='string' read-only='false' ><value encoded='n'><![CDATA[vCOHostname]]></value>
<description><![CDATA[vCO server's full computer name]]></description>
</att>
<att name='VCO_ENV' type='string' read-only='false' ><value encoded='n'><![CDATA[PROD]]></value>
<description><![CDATA[vCO server's environment (DEV, UAT or PROD)]]></description>
</att>
</atts>
</config-element>
"@
# Create multipart content with "--BlockBoundary" separator
$body = @"
--BlockBoundary
Content-Disposition:form-data; name="file"; filename="$vsoconfname";
Content-Type:application/zip;
$filecontent
--BlockBoundary
Content-Disposition:form-data; name="categoryId"
$categoryId
--BlockBoundary--
"@
# Upload the config (multipart)
Invoke-WebRequest -Uri "$vcoapi/configurations" -Method POST -Headers $headers -ContentType "multipart/form-data; boundary=BlockBoundary" -Body $body
Going further you can create configuration elements on your vCO and then exporting them as a template (export configuration).
Then you can:
[xml]$filecontentxml = get-content "C:\temp\myDNSconftemplate.vsoconf"
and update the conf with what you need:
$filecontentxml.'config-element'.atts.att | where { $_.name -like "DNS_SERVER" }).value.'#cdata-section' ="192.168.4.1,192.168.4.2"
# prepare multi-content body
[string] $filecontent = $newucsconfig.OuterXMl
This is easy to do with String/Number/vCO Objects.
But my problem is with the SecureString:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<config-element id="69c606d7-407b-4c83-b1c6-7765f4f09f65" version="0.0.0" >
<display-name><![CDATA[myConfigurationElement]]></display-name>
<atts>
<att name='SecurePassword' type='SecureString' read-only='false' ><value encoded='n'><![CDATA[16AC6DC79873965263C75772F65370361173B7377746FF7246411096E658DAE406D11506852EE8450309FD102375A7C58E3]]></value></att>
</atts>
</config-element>
I can't find how to encrypt my password so they will be accepted by vCO.
I know that: "16AC6DC79873965263C75772F65370361173B7377746FF7246411096E658DAE406D11506852EE8450309FD102375A7C58E3" equal to "mysecurepassword"
But I can't find how to encrypt "mysecurepassword" to "16AC6DC79873965263C75772F65370361173B7377746FF7246411096E658DAE406D11506852EE8450309FD102375A7C58E3"
vCO is not using any salt or random encryption, as I can import this string on any servers and it will be recognized.
Any idea someone?