VMware Cloud Community
dcoulter
Enthusiast
Enthusiast
Jump to solution

Import a configuration element via vCO REST API

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:

If the POST request is successful, you receive the status code 202.

0 Kudos
1 Solution

Accepted Solutions
iiliev
VMware Employee
VMware Employee
Jump to solution

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

View solution in original post

0 Kudos
8 Replies
igaydajiev
VMware Employee
VMware Employee
Jump to solution

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);

-------------------

iiliev
VMware Employee
VMware Employee
Jump to solution

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

0 Kudos
dcoulter
Enthusiast
Enthusiast
Jump to solution

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.

0 Kudos
iiliev
VMware Employee
VMware Employee
Jump to solution

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().

0 Kudos
cdecanini_
VMware Employee
VMware Employee
Jump to solution

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.

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you! Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator for vCenter Orchestrator tips and tutorials - @vCOTeam on Twitter
0 Kudos
dcoulter
Enthusiast
Enthusiast
Jump to solution

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.

0 Kudos
manuelperrot
Enthusiast
Enthusiast
Jump to solution

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

0 Kudos
manuelperrot
Enthusiast
Enthusiast
Jump to solution

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?

0 Kudos