a2a60bf359870ad8542f0e08ba1ff4d6e7c64282
[optf/has.git] / conductor / doc / template / README.md
1 ###### Apache License, Version 2.0
2
3 ===========================
4
5 ``Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.``
6
7 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
8
9     http://www.apache.org/licenses/LICENSE-2.0
10
11 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.
12
13 # Homing Specification Guide
14
15 *Updated: 10 October 2017*
16
17 This document describes the Homing Template format, used by the Homing service. It is a work in progress and subject to frequent revision.
18
19 ## Template Structure
20
21 Homing templates are defined in YAML and follow the structure outlined below.
22
23 ```yaml
24 homing_template_version: 2017-10-10
25 parameters:
26   PARAMETER_DICT
27 locations:
28   LOCATION_DICT
29 demands:
30   DEMAND_DICT
31 constraints:
32   CONSTRAINT_DICT
33 reservations:
34   RESERVATION_DICT
35 optimization:
36   OPTIMIZATION
37 ```
38
39 * ``homing_template_version``: This key with value 2017-10-10 (or a later date) indicates that the YAML document is a Homing template of the specified version.
40 * ``parameters``: This section allows for specifying input parameters that have to be provided when instantiating the homing template. Typically, this section is used for providing runtime parameters (like SLA thresholds), which in turn is used in the existing homing policies. The section is optional and can be omitted when no input is required.
41 * ``locations``: This section contains the declaration of geographic locations. This section is optional and can be omitted when no input is required.
42 * ``demands``: This section contains the declaration of demands. This section with at least one demand should be defined in any Homing template, or the template would not really do anything when being instantiated.
43 * ``constraints``: This section contains the declaration of constraints. The section is optional and can be omitted when no input is required.
44 * ``reservations``: This section contains the declaration of required reservations. This section is optional and can be omitted when reservations are not required.
45 * ``optimization``: This section allows the declaration of an optimization. This section is optional and can be omitted when no input is required.
46
47 ## Homing Template Version
48
49 The value of ``homing_template_version`` tells HAS not only the format of the template but also features that will be validated and supported. Only one value is supported: ``2017-10-10`` in the initial release of HAS.
50
51 ```yaml
52 homing_template_version: 2017-10-10
53 ```
54
55 ## Parameters
56
57 The **parameters** section allows for specifying input parameters that have to be provided when instantiating the template. Such parameters are typically used for providing runtime inputs (like SLA thresholds), which in turn is used in the existing homing policies. This also helps build reusable homing constraints where these parameters can be embedded design time, and it corresponding values can be supplied during runtime.
58
59 Each parameter is specified with the name followed by its value. Values can be strings, lists, or dictionaries.
60
61 ### Example
62
63 In this example, ``provider_name`` is a string and ``service_info`` is a dictionary containing both a string and a list (keyed by ``base_url`` and ``nod_config``, respectively).
64
65 ```yaml
66 parameters:
67   provider_name: multicloud
68   service_info:
69     base_url: http://serviceprovider.sdngc.com/
70     nod_config:
71     - http://nod/config_a.yaml
72     - http://nod/config_b.yaml
73     - http://nod/config_c.yaml
74     - http://nod/config_d.yaml
75 ```
76
77 A parameter can be referenced in place of any value. See the **Intrinsic Functions** section for more details.
78
79 ## Locations
80
81 One or more **locations** may be declared. A location may be referenced by one or more ``constraints``. Locations may be defined in any of the following ways:
82
83 ### Coordinate
84
85 A geographic coordinate expressed as a latitude and longitude.
86
87 | Key                         | Value                      |
88 |-----------------------------|----------------------------|
89 | ``latitude``                | Latitude of the location.  |
90 | ``longitude``               | Longitude of the location. |
91
92 ### Host Name
93
94 An opaque host name that can be translated to a coordinate via an inventory provider (e.g., A&AI).
95
96 | Key                         | Value                      |
97 |-----------------------------|----------------------------|
98 | ``host_name``               | Host name identifying a location. |
99
100 ### CLLI
101
102 Common Language Location Identification (CLLI) code(https://en.wikipedia.org/wiki/CLLI_code).
103
104 | Key                         | Value                      |
105 |-----------------------------|----------------------------|
106 | ``clli_code``               | 8 character CLLI. |
107
108 **Questions**
109
110 * Do we need functions that can convert one of these to the other? E.g., CLLI Codes to a latitude/longitude
111
112 ### Placemark
113
114 An address expressed in geographic region-agnostic terms (referred to as a *placemark*).
115
116 *Support for this schema is deferred.*
117
118 | Key                         | Value                      |
119 |-----------------------------|----------------------------|
120 | ``iso_country_code``        | The abbreviated country name associated with the placemark. |
121 | ``postal_code``             | The postal code associated with the placemark. |
122 | ``administrative_area``     | The state or province associated with the placemark. |
123 | ``sub_administrative_area`` | Additional administrative area information for the placemark. |
124 | ``locality``                | The city associated with the placemark. |
125 | ``sub_locality``            | Additional city-level information for the placemark. |
126 | ``thoroughfare``            | The street address associated with the placemark. |
127 | ``sub_thoroughfare``        | Additional street-level information for the placemark. |
128
129 **Questions**
130
131 * What geocoder can we use to convert placemarks to a latitude/longitude?
132
133 ### Examples
134
135 The following examples illustrate a location expressed in coordinate, host_name, CLLI, and placemark, respectively.
136
137 ```yaml
138 locations:
139   location_using_coordinates:
140     latitude: 32.897480
141     longitude: -97.040443
142
143   host_location_using_host_name:
144     host_name: USESTCDLLSTX55ANZ123
145
146   location_using_clli:
147     clli_code: DLLSTX55
148
149   location_using_placemark:
150     sub_thoroughfare: 1
151     thoroughfare: ATT Way
152     locality: Bedminster
153     administrative_area: NJ
154     postal_code: 07921-2694
155 ```
156
157 ## Demands
158
159 A **demand** can be satisfied by using candidates drawn from inventories. Each demand is uniquely named. Inventory is considered to be opaque and can represent anything from which candidates can be drawn.
160
161 A demand's resource requirements are determined by asking an **inventory provider** for one or more sets of **inventory candidates** against which the demand will be made. An explicit set of candidates may also be declared, for example, if the only candidates for a demand are predetermined.
162
163 Demand criteria is dependent upon the inventory provider in use.
164
165 **Provider-agnostic Schema**
166
167 | Key                    | Value                    |
168 |------------------------|--------------------------|
169 | ``inventory_provider`` | A HAS-supported inventory provider. |
170 | ``inventory_type`` | The reserved word ``cloud`` (for cloud regions) or the reserved word ``service`` (for existing service instances). Exactly one inventory type may be specified. |
171 | ``attributes`` (Optional) | A list of key-value pairs, that is used to select inventory candidates that match *all* the specified attributes. The key should be a uniquely identifiable attribute at the inventory provider. |
172 | ``service_type`` (Optional) | If ``inventory_type`` is ``service``, a list of one or more provider-defined service types. If only one service type is specified, it may appear without list markers (``[]``). |
173 | ``service_id`` (Optional) | If ``inventory_type`` is ``service``, a list of one or more provider-defined service ids. If only one service id is specified, it may appear without list markers (``[]``). |
174 | ``default_cost`` (Optional) | The default cost of an inventory candidate, expressed as currency. This must be specified if the inventory provider may not always return a cost. |
175 | ``required_candidates`` (Optional) | A list of one or more candidates from which a solution will be explored. Must be a valid candidate as described in the **candidate schema**. |
176 | ``excluded_candidates`` (Optional) | A list of one or more candidates that should be excluded from the search space. Must be a valid candidate as described in the **candidate schema**. |
177 | ``existing_placement`` (Optional) | The current placement for the demand. Must be a valid candidate as described in the **candidate schema**. |
178
179
180 ### Examples
181
182 The following example helps understand a demand specification using Active & Available Inventory (A&AI), the inventory provider-of-record for ONAP.
183
184 **Inventory Provider Criteria**
185
186 | Key                    | Value                    |
187 |------------------------|--------------------------|
188 | ``inventory_provider`` | Examples: ``aai``, ``multicloud``. |
189 | ``inventory_type`` | The reserved word ``cloud`` (for new inventory) or the reserved word ``service`` (for existing inventory). Exactly one inventory type may be specified. |
190 | ``attributes`` (Optional) | A list of key-value pairs to match against inventory when drawing candidates. |
191 | ``service_type`` (Optional) | Examples may include ``vG``, ``vG_MuxInfra``, etc. |
192 | ``service_id`` (Optional) | Must be a valid service id. Examples may include ``vCPE``, ``VoLTE``, etc. |
193 | ``default_cost`` (Optional) | The default cost of an inventory candidate, expressed as a unitless number. |
194 | ``required_candidates`` (Optional) | A list of one or more valid candidates. See **Candidate Schema** for details. |
195 | ``excluded_candidates`` (Optional) | A list of one or more valid candidates. See **Candidate Schema** for details. |
196 | ``existing_placement`` (Optional) | A single valid candidate, representing the current placement for the demand. See **candidate schema** for details. |
197
198 **Candidate Schema**
199
200 The following is the schema for a valid ``candidate``:
201 * ``candidate_id`` uniquely identifies a candidate. Currently, it is either a Service Instance ID or Cloud Region ID.
202 * ``candidate_type`` identifies the type of the candidate. Currently, it is either ``cloud`` or ``service``.
203 * ``inventory_type`` is defined as described in **Inventory Provider Criteria** (above).
204 * ``inventory_provider`` identifies the inventory from which the candidate was drawn.
205 * ``host_id`` is an ID of a specific host (used only when referring to service/existing inventory).
206 * ``cost`` is expressed as a unitless number.
207 * ``location_id`` is always a location ID of the specified location type (e.g., for a type of ``cloud`` this will be an Cloud Region ID).
208 * ``location_type`` is an inventory provider supported location type.
209 * ``latitude`` is a valid latitude corresponding to the *location_id*.
210 * ``longitude`` is a valid longitude corresponding to the *location_id*.
211 * ``city`` (Optional) city corresponding to the *location_id*.
212 * ``state`` (Optional) state corresponding to the *location_id*.
213 * ``country`` (Optional) country corresponding to the *location_id*.
214 * ``region`` (Optional) geographic region corresponding to the *location_id*.
215 * ``complex_name`` (Optional) Name of the complex corresponding to the *location_id*.
216 * ``cloud_owner`` (Optional) refers to the *cloud owner* (e.g., ``azure``, ``aws``, ``att``, etc.).
217 * ``cloud_region_version`` (Optional) is an inventory provider supported version of the cloud region.
218 * ``physical_location_id`` (Optional) is an inventory provider supported CLLI code corresponding to the cloud region.
219
220 **Examples**
221
222 **``Service Candidate``**
223 ```json
224 {
225         "candidate_id": "1ac71fb8-ad43-4e16-9459-c3f372b8236d",
226         "candidate_type": "service",
227         "inventory_type": "service",
228         "inventory_provider": "aai",
229         "host_id": "vnf_123456",
230         "cost": "100",
231         "location_id": "DLLSTX9A",
232         "location_type": "azure",
233         "latitude": "32.897480",
234         "longitude": "-97.040443",
235         "city": "Dallas",
236         "state": "TX",
237         "country": "USA",
238         "region": "US",
239         "complex_name": "dalls_one",
240         "cloud_owner": "att-aic",
241         "cloud_region_version": "1.1",
242         "physical_location_id": "DLLSTX9A"
243 }
244 ```
245 **``Cloud Candidate``**
246 ```json
247 {
248       "candidate_id": "NYCNY55",
249       "candidate_type": "cloud",
250       "inventory_type": "cloud",
251       "inventory_provider": "aai",
252       "cost": "100",
253       "location_id": "NYCNY55",
254       "location_type": "azure",
255       "latitude": "40.7128",
256       "longitude": "-74.0060",
257       "city": "New York",
258       "state": "NY",
259       "country": "USA",
260       "region": "US",
261       "complex_name": "ny_one",
262       "cloud_owner": "att-aic",
263       "cloud_region_version": "1.1",
264       "physical_location_id": "NYCNY55",
265       "flavors": {
266            "flavor":[
267               {
268                  "flavor-id":"9cf8220b-4d96-4c30-a426-2e9382f3fff2",
269                  "flavor-name":"flavor-numa-cpu-topology-instruction-set",
270                  "flavor-vcpus":64,
271                  "flavor-ram":65536,
272                  "flavor-disk":1048576,
273                  "flavor-ephemeral":128,
274                  "flavor-swap":"0",
275                  "flavor-is-public":false,
276                  "flavor-selflink":"pXtX",
277                  "flavor-disabled":false,
278                  "hpa-capabilities":{
279                     "hpa-capability":[
280                        {
281                           "hpa-capability-id":"01a4bfe1-1993-4fda-bd1c-ef333b4f76a9",
282                           "hpa-feature":"cpuInstructionSetExtensions",
283                           "hpa-version":"v1",
284                           "architecture":"Intel64",
285                           "resource-version":"1521306560982",
286                           "hpa-feature-attributes":[
287                              {
288                                 "hpa-attribute-key":"instructionSetExtensions",
289                                 "hpa-attribute-value":"{\"value\":{['AAA', 'BBB', 'CCC', 'DDD']}}",
290                                 "resource-version":"1521306560989"
291                              }
292                           ]
293                        },
294                        {
295                           "hpa-capability-id":"167ad6a2-7d9c-4bf2-9a1b-30e5311b8c66",
296                           "hpa-feature":"numa",
297                           "hpa-version":"v1",
298                           "architecture":"generic",
299                           "resource-version":"1521306561020",
300                           "hpa-feature-attributes":[
301                              {
302                                 "hpa-attribute-key":"numaCpu-1",
303                                 "hpa-attribute-value":"{\"value\":4}",
304                                 "resource-version":"1521306561060"
305                              },
306                              {
307                                 "hpa-attribute-key":"numaNodes",
308                                 "hpa-attribute-value":"{\"value\":2}",
309                                 "resource-version":"1521306561088"
310                              },
311                              {
312                                 "hpa-attribute-key":"numaCpu-0",
313                                 "hpa-attribute-value":"{\"value\":2}",
314                                 "resource-version":"1521306561028"
315                              },
316                              {
317                                 "hpa-attribute-key":"numaMem-0",
318                                 "hpa-attribute-value":"{\"value\":2, \"unit\":\"GB\" }",
319                                 "resource-version":"1521306561044"
320                              },
321                              {
322                                 "hpa-attribute-key":"numaMem-1",
323                                 "hpa-attribute-value":"{\"value\":4, \"unit\":\"GB\" }",
324                                 "resource-version":"1521306561074"
325                              }
326                           ]
327                        },
328                        {
329                           "hpa-capability-id":"13ec6d4d-7fee-48d8-9e4a-c598feb101ed",
330                           "hpa-feature":"basicCapabilities",
331                           "hpa-version":"v1",
332                           "architecture":"generic",
333                           "resource-version":"1521306560909",
334                           "hpa-feature-attributes":[
335                              {
336                                 "hpa-attribute-key":"numVirtualCpu",
337                                 "hpa-attribute-value":"{\"value\":64}",
338                                 "resource-version":"1521306560932"
339                              },
340                              {
341                                 "hpa-attribute-key":"virtualMemSize",
342                                 "hpa-attribute-value":"{\"value\":65536, \"unit\":\"MB\" }",
343                                 "resource-version":"1521306560954"
344                              }
345                           ]
346                        },
347                        {
348                           "hpa-capability-id":"8fa22e64-41b4-471f-96ad-6c4708635e4c",
349                           "hpa-feature":"cpuTopology",
350                           "hpa-version":"v1",
351                           "architecture":"generic",
352                           "resource-version":"1521306561109",
353                           "hpa-feature-attributes":[
354                              {
355                                 "hpa-attribute-key":"numCpuCores",
356                                 "hpa-attribute-value":"{\"value\":8}",
357                                 "resource-version":"1521306561114"
358                              },
359                              {
360                                 "hpa-attribute-key":"numCpuThreads",
361                                 "hpa-attribute-value":"{\"value\":8}",
362                                 "resource-version":"1521306561138"
363                              },
364                              {
365                                 "hpa-attribute-key":"numCpuSockets",
366                                 "hpa-attribute-value":"{\"value\":6}",
367                                 "resource-version":"1521306561126"
368                              }
369                           ]
370                        }
371                     ]
372                  },
373                  "resource-version":"1521306560203"
374               },
375               {
376                  "flavor-id":"f5aa2b2e-3206-41b6-80d5-cf041b098c43",
377                  "flavor-name":"flavor-cpu-pinning-ovsdpdk-instruction-set",
378                  "flavor-vcpus":32,
379                  "flavor-ram":131072,
380                  "flavor-disk":2097152,
381                  "flavor-ephemeral":128,
382                  "flavor-swap":"0",
383                  "flavor-is-public":false,
384                  "flavor-selflink":"pXtX",
385                  "flavor-disabled":false,
386                  "hpa-capabilities":{
387                     "hpa-capability":[
388                        {
389                           "hpa-capability-id":"4d04f4d8-e257-4442-8417-19a525e56096",
390                           "hpa-feature":"cpuInstructionSetExtensions",
391                           "hpa-version":"v1",
392                           "architecture":"generic",
393                           "resource-version":"1521306561223",
394                           "hpa-feature-attributes":[
395                              {
396                                 "hpa-attribute-key":"instructionSetExtensions",
397                                 "hpa-attribute-value":"{\"value\":{['A11', 'B22']}}",
398                                 "resource-version":"1521306561228"
399                              }
400                           ]
401                        },
402                        {
403                           "hpa-capability-id":"8d36a8fe-bfee-446a-bbcb-881ee66c8f78",
404                           "hpa-feature":"ovsDpdk",
405                           "hpa-version":"v1",
406                           "architecture":"generic",
407                           "resource-version":"1521306561170",
408                           "hpa-feature-attributes":[
409                              {
410                                 "hpa-attribute-key":"dataProcessingAccelerationLibrary",
411                                 "hpa-attribute-value":"{\"value\":\"v18.02\"}",
412                                 "resource-version":"1521306561175"
413                              }
414                           ]
415                        },
416                        {
417                           "hpa-capability-id":"c140c945-1532-4908-86c9-d7f71416f1dd",
418                           "hpa-feature":"cpuPinning",
419                           "hpa-version":"v1",
420                           "architecture":"generic",
421                           "resource-version":"1521306561191",
422                           "hpa-feature-attributes":[
423                              {
424                                 "hpa-attribute-key":"logicalCpuPinningPolicy",
425                                 "hpa-attribute-value":"{\"value\":\"dedicated\"}",
426                                 "resource-version":"1521306561196"
427                              },
428                              {
429                                 "hpa-attribute-key":"logicalCpuThreadPinningPolicy",
430                                 "hpa-attribute-value":"{value:\"prefer\"}",
431                                 "resource-version":"1521306561206"
432                              }
433                           ]
434                        },
435                        {
436                           "hpa-capability-id":"4565615b-1077-4bb5-a340-c5be48db2aaa",
437                           "hpa-feature":"basicCapabilities",
438                           "hpa-version":"v1",
439                           "architecture":"generic",
440                           "resource-version":"1521306561244",
441                           "hpa-feature-attributes":[
442                              {
443                                 "hpa-attribute-key":"numVirtualCpu",
444                                 "hpa-attribute-value":"{\"value\":32}",
445                                 "resource-version":"1521306561259"
446                              },
447                              {
448                                 "hpa-attribute-key":"virtualMemSize",
449                                 "hpa-attribute-value":"{\"value\":131072, \"unit\":\"MB\" }",
450                                 "resource-version":"1521306561248"
451                              }
452                           ]
453                        }
454                     ]
455                  },
456                  "resource-version":"1521306561164"
457               }
458            ]
459       }
460 }
461 ```
462 **Questions**
463 * Currently, candidates are either service instances or cloud regions. As new services are on-boarded, this can be evolved to represent different types of resources.
464
465 **Examples**
466
467 The following examples illustrate two demands:
468
469 * ``vGMuxInfra``: A vGMuxInfra service, drawing candidates of type *service* from the inventory. Only candidates that match the customer_id and orchestration-status will be included in the search space.
470 * ``vG``: A vG, drawing candidates of type *service* and *cloud* from the inventory. Only candidates that match the customer_id and provisioning-status will be included in the search space.
471
472
473 ```yaml
474 demands:
475   vGMuxInfra:
476   - inventory_provider: aai
477     inventory_type: service
478     attributes:
479       equipment_type: vG_Mux
480       customer_id: some_company
481       orchestration-status: Activated
482       model-id: 174e371e-f514-4913-a93d-ed7e7f8fbdca
483       model-version: 2.0
484   vG:
485   - inventory_provider: aai
486     inventory_type: service
487     attributes:
488       equipment_type: vG
489       customer_id: some_company
490       provisioning-status: provisioned
491   - inventory_provider: aai
492     inventory_type: cloud
493 ```
494
495 **Questions**
496 * Do we need to support cost as a function ?
497
498 ## Constraints
499
500 A **Constraint** is used to *eliminate* inventory candidates from one or more demands that do not meet the requirements specified by the constraint. Since reusability is one of the cornerstones of HAS, Constraints are designed to be service-agnostic, and is parameterized such that it can be reused across a wide range of services. Further, HAS is designed with a plug-in architecture that facilitates easy addition of new constraint types.
501
502 Constraints are denoted by a ``constraints`` key. Each constraint is uniquely named and set to a dictionary containing a constraint type, a list of demands to apply the constraint to, and a dictionary of constraint properties.
503
504 **Considerations while using multiple constraints**
505 * Constraints should be treated as a unordered list, and no assumptions should be made as regards to the order in which the constraints are evaluated for any given demand.
506 * All constraints are effectively AND-ed together. Constructs such as "Constraint X OR Y" are unsupported.
507 * Constraints are reducing in nature, and does not increase the available candidates at any point during the constraint evaluations.
508
509
510 **Schema**
511
512 | Key                 | Value       |
513 |---------------------|-------------|
514 | ``CONSTRAINT_NAME`` | Key is a unique name. |
515 | ``type`` | The type of constraint. See **Constraint Types** for a list of currently supported values. |
516 | ``demands`` | One or more previously declared demands. If only one demand is specified, it may appear without list markers (``[]``). |
517 | ``properties`` (Optional) | Properties particular to the specified constraint type. Use if required by the constraint. |
518
519 ```yaml
520 constraints:
521   CONSTRAINT_NAME_1:
522     type: CONSTRAINT_TYPE
523     demands: DEMAND_NAME | [DEMAND_NAME_1, DEMAND_NAME_2, ...]
524     properties: PROPERTY_DICT
525
526   CONSTRAINT_NAME_2:
527     type: CONSTRAINT_TYPE
528     demands: DEMAND_NAME | [DEMAND_NAME_1, DEMAND_NAME_2, ...]
529     properties: PROPERTY_DICT
530
531   ...
532 ```
533
534 #### Constraint Types
535
536 | Type                | Description |
537 |---------------------|-------------|
538 | ``attribute`` | Constraint that matches the specified list of Attributes. |
539 | ``distance_between_demands`` | Geographic distance constraint between each pair of a list of demands. |
540 | ``distance_to_location`` | Geographic distance constraint between each of a list of demands and a specific location.  |
541 | ``instance_fit`` | Constraint that ensures available capacity in an existing service instance for an incoming demand. |
542 | ``inventory_group`` | Constraint that enforces two or more demands are satisfied using candidates from a pre-established group in the inventory. |
543 | ``region_fit`` | Constraint that ensures available capacity in an existing cloud region for an incoming demand. |
544 | ``zone`` | Constraint that enforces co-location/diversity at the granularities of clouds/regions/availability-zones. |
545 | ``hpa`` | Constraint that recommends cloud region with an optimal flavor based on required HPA capabilities for an incoming demand. |
546 | ``vim_fit`` | Constraint that checks if the incoming demand fits the VIM instance. |
547 | ``license`` (Deferred) | License availability constraint. |
548 | ``network_between_demands`` (Deferred) | Network constraint between each pair of a list of demands. |
549 | ``network_to_location`` (Deferred) | Network constraint between each of a list of demands and a specific location/address. |
550
551 *Note: Constraint names marked "Deferred" **will not** be supported in the initial release of HAS.*
552
553 #### Threshold Values
554
555 Constraint property values representing a threshold may be an integer or floating point number, optionally prefixed with a comparison operator: ``=``, ``<``, ``>``, ``<=``, or ``>=``. The default is ``=`` and optionally suffixed with a unit.
556
557 Whitespace may appear between the comparison operator and value, and between the value and units. When a range values is specified (e.g., ``10-20 km``), the comparison operator is omitted.
558
559 Each property is documented with a default unit. The following units are supported:
560
561 | Unit       | Values                       | Default  |
562 |------------|------------------------------|----------|
563 | Currency   | ``USD``                      | ``USD``  |
564 | Time       | ``ms``, ``sec``              | ``ms``   |
565 | Distance   | ``km``, ``mi``               | ``km``   |
566 | Throughput | ``Kbps``, ``Mbps``, ``Gbps`` | ``Mbps`` |
567
568 ### Attribute
569
570 Constrain one or more demands by one or more attributes, expressed as properties. Attributes are mapped to the **inventory provider** specified properties, referenced by the demands. For example, properties could be hardware capabilities provided by the platform (flavor, CPU-Pinning, NUMA), features supported by the services, etc.  
571
572 **Schema**
573
574 | Property     | Value                                                       |
575 |--------------|-------------------------------------------------------------|
576 | ``evaluate`` | Opaque dictionary of attribute name and value pairs. Values must be strings or numbers. Encoded and sent to the service provider via a plugin. |
577
578 *Note: Attribute values are not detected/parsed as thresholds by the Homing framework. Such interpretations and evaluations are inventory provider-specific and delegated to the corresponding plugin*
579
580 ```yaml
581 constraints:
582   sriov_nj:
583     type: attribute
584     demands: [my_vnf_demand, my_other_vnf_demand]
585     properties:
586       evaluate:
587         cloud_version: 1.1
588         flavor: SRIOV
589         subdivision: US-TX
590         vcpu_pinning: True
591         numa_topology: numa_spanning
592 ```
593
594 #### Proposal: Evaluation Operators
595
596 To assist in evaluating attributes, the following operators and notation are proposed:
597
598 | Operator     | Name      | Operand                                        |
599 |--------------|-----------|------------------------------------------------|
600 | ``eq``       | ``==``    | Any object (string, number, list, dict)        |
601 | ``ne``       | ``!=``    |                                                |
602 | ``lt``       | ``<``     | A number (strings are converted to float)      |
603 | ``gt``       | ``>``     |                                                |
604 | ``lte``      | ``<=``    |                                                |
605 | ``gte``      | ``>=``    |                                                |
606 | ``any``      | ``Any``   | A list of objects (string, number, list, dict) |
607 | ``all``      | ``All``   |                                                |
608 | ``regex``    | ``RegEx`` | A regular expression pattern                   |
609
610 Example usage:
611
612 ```yaml
613 constraints:
614   sriov_nj:
615     type: attribute
616     demands: [my_vnf_demand, my_other_vnf_demand]
617     properties:
618       evaluate:
619         cloud_version: {gt: 1.0}
620         flavor: {regex: /^SRIOV$/i}
621         subdivision: {any: [US-TX, US-NY, US-CA]}
622 ```
623
624 ### Distance Between Demands
625
626 Constrain each pairwise combination of two or more demands by distance requirements.
627
628 **Schema**
629
630 | Name         | Value                                                       |
631 |--------------|-------------------------------------------------------------|
632 | ``distance`` | Distance between demands, measured by the geographic path.  |
633
634 The constraint is applied between each pairwise combination of demands. For this reason, at least two demands must be specified, implicitly or explicitly.
635
636 ```yaml
637 constraints:
638   distance_vnf1_vnf2:
639     type: distance_between_demands
640     demands: [my_vnf_demand, my_other_vnf_demand]
641     properties:
642       distance: < 250 km
643 ```
644
645 ### Distance To Location
646
647 Constrain one or more demands by distance requirements relative to a specific location.
648
649 **Schema**
650
651 | Property     | Value                                                      |
652 |--------------|------------------------------------------------------------|
653 | ``distance`` | Distance between demands, measured by the geographic path. |
654 | ``location`` | A previously declared location.                            |
655
656 The constraint is applied between each demand and the referenced location, not across all pairwise combinations of Demands.
657
658 ```yaml
659 constraints:
660   distance_vnf1_loc:
661     type: distance_to_location
662     demands: [my_vnf_demand, my_other_vnf_demand, another_vnf_demand]
663     properties:
664       distance: < 250 km
665       location: LOCATION_ID
666 ```
667
668 ### Instance Fit
669
670 Constrain each demand by its service requirements.
671
672 Requirements are sent as a request to a **service controller**. Service controllers are defined by plugins in Homing (e.g., ``sdn-c``).
673
674 A service controller plugin knows how to communicate with a particular endpoint (via HTTP/REST, DMaaP, etc.), obtain necessary information, and make a decision. The endpoint and credentials can be configured through plugin settings.
675
676 **Schema**
677
678 | Property       | Description                       |
679 |----------------|-----------------------------------|
680 | ``controller`` | Name of a service controller.     |
681 | ``request``    | Opaque dictionary of key/value pairs. Values must be strings or numbers. Encoded and sent to the service provider via a plugin. |
682
683 ```yaml
684 constraints:
685   check_for_availability:
686     type: instance_fit
687     demands: [my_vnf_demand, my_other_vnf_demand]
688     properties:
689       controller: sdn-c
690       request: REQUEST_DICT
691 ```
692
693 ### Region Fit
694
695 Constrain each demand's inventory candidates based on inventory provider membership.
696
697 Requirements are sent as a request to a **service controller**. Service controllers are defined by plugins in Homing (e.g., ``sdn-c``).
698
699 A service controller plugin knows how to communicate with a particular endpoint (via HTTP/REST, DMaaP, etc.), obtain necessary information, and make a decision. The endpoint and credentials can be configured through plugin settings.
700
701 **Schema**
702
703 | Property       | Description                       |
704 |----------------|-----------------------------------|
705 | ``controller`` | Name of a service controller.     |
706 | ``request``    | Opaque dictionary of key/value pairs. Values must be strings or numbers. Encoded and sent to the service provider via a plugin. |
707
708 ```yaml
709 constraints:
710   check_for_membership:
711     type: region_fit
712     demands: [my_vnf_demand, my_other_vnf_demand]
713     properties:
714       controller: sdn-c
715       request: REQUEST_DICT
716 ```
717 ### Zone
718
719 Constrain two or more demands such that each is located in the same or different zone category.
720
721 Zone categories are inventory provider-defined, based on the demands being constrained.
722
723 **Schema**
724
725 | Property      | Value                                                       |
726 |---------------|-------------------------------------------------------------|
727 | ``qualifier`` | Zone qualifier. One of ``same`` or ``different``.     |
728 | ``category``  | Zone category. One of ``disaster``, ``region``, ``complex``, ``time``, or ``maintenance``. |
729
730 For example, to place two demands in different disaster zones:
731
732 ```yaml
733 constraints:
734   vnf_diversity:
735     type: zone
736     demands: [my_vnf_demand, my_other_vnf_demand]
737     properties:
738       qualifier: different
739       category: disaster
740 ```
741
742 Or, to place two demands in the same region:
743
744 ```yaml
745 constraints:
746   vnf_affinity:
747     type: zone
748     demands: [my_vnf_demand, my_other_vnf_demand]
749     properties:
750       qualifier: same
751       category: region
752 ```
753
754 **Notes**
755
756 * These categories could be any of the following: ``disaster_zone``, ``region``, ``complex``, ``time_zone``, and ``maintenance_zone``. Really, we are talking affinity/anti-affinity at the level of DCs, but these terms may cause confusion with affinity/anti-affinity in OpenStack.
757
758 ### HPA
759
760 Constrain each demand's inventory candidates based on cloud regions' Hardware platform capabilities (HPA)
761
762 Requirements mapped to the inventory provider specified properties, referenced by the demands. For example, properties could be hardware capabilities provided by the platform through flavors or cloud-region eg:(CPU-Pinning, NUMA), features supported by the services, etc.
763
764 **Schema**
765
766 | Property      | Value                                                       |
767 |---------------|-------------------------------------------------------------|
768 | ``evaluate``  | List of flavorLabel, flavorProperties of each VM of the VNF demand. |
769
770 ```yaml
771 constraints:
772   hpa_constraint:
773     type: hpa
774     demands: [my_vnf_demand, my_other_vnf_demand]
775     properties:
776       evaluate:
777         - [ List of {flavorLabel : {flavor label name}, 
778                     flavorProperties: HPACapability DICT} ]
779 HPACapability DICT :
780   hpa-feature: basicCapabilities
781   hpa-version: v1
782   architecture: generic
783   hpa-feature-attributes:
784     - HPAFEATUREATTRIBUTES LIST
785     
786 HPAFEATUREATTRIBUTES LIST:
787   hpa-attribute-key: String
788   hpa-attribute-value: String
789   operator: One of OPERATOR
790   unit: String
791 OPERATOR : ['=', '<', '>', '<=', '>=', 'ALL']
792 ```
793
794 **Example**
795 ```json
796 {
797     "hpa_constraint":{
798         "type":"hpa",
799         "demands":[
800            "vG"
801         ],
802         "properties":{
803            "evaluate":[
804               {
805                  "flavorLabel":"flavor_label_1",
806                  "flavorProperties":[
807                     {
808                        "hpa-feature":"basicCapabilities",
809                        "hpa-version":"v1",
810                        "architecture":"generic",
811                        "mandatory": "True",
812                        "hpa-feature-attributes":[
813                           {
814                              "hpa-attribute-key":"numVirtualCpu",
815                              "hpa-attribute-value":"32",
816                              "operator":"="
817                           },
818                           {
819                              "hpa-attribute-key":"virtualMemSize",
820                              "hpa-attribute-value":"64",
821                              "operator":"=",
822                              "unit":"GB"
823                           }
824                        ]
825                     },
826                     {
827                        "hpa-feature":"ovsDpdk",
828                        "hpa-version":"v1",
829                        "architecture":"generic",
830                        "mandatory": "False",
831                        "score": "10",
832                        "hpa-feature-attributes":[
833                           {
834                              "hpa-attribute-key":"dataProcessingAccelerationLibrary",
835                              "hpa-attribute-value":"v18.02",
836                              "operator":"="
837                           }
838                        ]
839                     }
840                  ]
841               },
842               {
843                  "flavorLabel":"flavor_label_2",
844                  "flavorProperties":[
845                     {
846                        "hpa-feature":"basicCapabilities",
847                        "hpa-version":"v1",
848                        "architecture":"generic",
849                        "mandatory": "False",
850                        "score": "5",
851                        "hpa-feature-attributes":[
852                           {
853                              "hpa-attribute-key":"numVirtualCpu",
854                              "hpa-attribute-value":"8",
855                              "operator":">="
856                           },
857                           {
858                              "hpa-attribute-key":"virtualMemSize",
859                              "hpa-attribute-value":"16",
860                              "operator":">=",
861                              "unit":"GB"
862                           }
863                        ]
864                     }
865                  ]
866               }
867            ]
868         }
869     }
870 }
871 ```
872
873 ### VIM Fit
874
875 Constrain each demand's inventory candidates based on capacity check for available capacity at the VIM instances.
876
877 Requirements are sent as an opaque request object understood by the VIM controllers or MultiCloud. Each controller is defined and implemented as a plugin in Conductor.
878
879 A vim controller plugin knows how to communicate with a particular endpoint (via HTTP/REST, DMaaP, etc.), obtain necessary information, and make a decision. The endpoint and credentials can be configured through plugin settings.
880
881 **Schema**
882
883 | Property      | Value                                                       |
884 |---------------|-------------------------------------------------------------|
885 | ``controller``| Name of a vim controller. (e.g., multicloud) |
886 | ``request``   | Opaque dictionary of key/value pairs. Values must be strings or numbers. Encoded and sent to the vim controller via a plugin. |
887
888 For example, to place two demands in different disaster zones:
889
890 ```yaml
891 constraints:
892   check_cloud_capacity:
893     type: vim_fit
894     demands: [my_vnf_demand, my_other_vnf_demand]
895     properties:
896       controller: multicloud
897       request: REQUEST_DICT
898 ```
899
900 **Notes**
901
902 * For ONAP Beijing release the REQUEST_DICT is of the following format as defined by the policy for vim_fit. The REQUEST_DICT is an opaque request object defined through policy, so it is not restricted to this format. In ONAP Beijing release MultiCloud supports the check_vim_capacity using the following grammar.
903   ```json
904   {
905     "request":{
906       "vCPU":10,
907       "Memory":{
908         "quantity":{
909           "get_param":"REQUIRED_MEM"
910         },
911         "unit":"GB"
912       },
913       "Storage":{
914         "quantity":{
915           "get_param":"REQUIRED_DISK"
916         },
917         "unit":"GB"
918       }
919     }
920   }
921   ```
922
923 ### Inventory Group
924
925 Constrain demands such that inventory items are grouped across two demands.
926
927 This constraint has no properties.
928
929 ```yaml
930 constraints:
931   my_group:
932     type: inventory_group
933     demands: [demand_1, demand_2]
934 ```
935
936 *Note: Only pair-wise groups are supported at this time. If three or more demands are specified, only the first two will be used.*
937
938 ### License
939
940 Constrain demands according to license availability.
941
942 *Support for this constraint is deferred.*
943
944 **Schema**
945
946 | Property | Value                                                    |
947 |----------|----------------------------------------------------------|
948 | ``id``   | Unique license identifier                                |
949 | ``key``  | Opaque license key, particular to the license identifier |
950
951 ```yaml
952 constraints:
953   my_software:
954     type: license
955     demands: [demand_1, demand_2, ...]
956     properties:
957       id: SOFTWARE_ID
958       key: LICENSE_KEY
959 ```
960
961 ### Network Between Demands
962
963 Constrain each pairwise combination of two or more demands by network requirements.
964
965 *Support for this constraint is deferred.*
966
967 **Schema**
968
969 | Property                 | Value                                                           |
970 |--------------------------|-----------------------------------------------------------------|
971 | ``bandwidth`` (Optional) | Desired network bandwidth.                                      |
972 | ``distance`` (Optional)  | Desired distance between demands, measured by the network path. |
973 | ``latency`` (Optional)   | Desired network latency.                                        |
974
975 Any combination of ``bandwidth``, ``distance``, or ``latency`` must be specified. If none of these properties are used, it is treated as a malformed request.
976
977 The constraint is applied between each pairwise combination of demands. For this reason, at least two demands must be specified, implicitly or explicitly.
978
979 ```yaml
980 constraints:
981   network_requirements:
982     type: network_between_demands
983     demands: [my_vnf_demand, my_other_vnf_demand]
984     properties:
985       bandwidth: >= 1000 Mbps
986       distance: < 250 km
987       latency: < 50 ms
988 ```
989
990 ### Network To Location
991
992 Constrain one or more demands by network requirements relative to a specific location.
993
994 *Support for this constraint is deferred.*
995
996 **Schema**
997
998 | Property      | Value                                                           |
999 |---------------|-----------------------------------------------------------------|
1000 | ``bandwidth`` | Desired network bandwidth.                                      |
1001 | ``distance``  | Desired distance between demands, measured by the network path. |
1002 | ``latency``   | Desired network latency.                                        |
1003 | ``location``  | A previously declared location.                                 |
1004
1005 Any combination of ``bandwidth``, ``distance``, or ``latency`` must be specified. If none of these properties are used, it is treated as a malformed request.
1006
1007 The constraint is applied between each demand and the referenced location, not across all pairwise combinations of Demands.
1008
1009 ```yaml
1010 constraints:
1011   my_access_network_constraint:
1012     type: network_to_location
1013     demands: [my_vnf_demand, my_other_vnf_demand]
1014     properties:
1015       bandwidth: >= 1000 Mbps
1016       distance: < 250 km
1017       latency: < 50 ms
1018       location: LOCATION_ID
1019 ```
1020 ### Capabilities
1021
1022 Constrain each demand by its cluster capability requirements. For example, as described by an OpenStack Heat template and operational environment.
1023
1024 *Support for this constraint is deferred.*
1025
1026 **Schema**
1027
1028 | Property     | Value                                                       |
1029 |--------------|-------------------------------------------------------------|
1030 | ``specification`` | Indicates the kind of specification being provided in the properties. Must be ``heat``. Future values may include ``tosca``, ``Homing``, etc. |
1031 | ``template`` | For specifications of type ``heat``, a single stack in OpenStack Heat Orchestration Template (HOT) format. Stacks may be expressed as a URI reference or a string of well-formed YAML/JSON. Templates are validated by the Heat service configured for use by HAS. Nested stack references are unsupported. |
1032 | ``environment`` (Optional) | For specifications of type ``heat``, an optional Heat environment. Environments may be expressed as a URI reference or a string of well-formed YAML/JSON. Environments are validated by the Heat service configured for use by Homing. |
1033
1034 ```yaml
1035 constraints:
1036   check_for_fit:
1037     type: capability
1038     demands: [my_vnf_demand, my_other_vnf_demand]
1039     properties:
1040       specification: heat
1041       template: http://repository/my/stack_template
1042       environment: http://repository/my/stack_environment
1043 ```
1044
1045
1046 ## Reservations
1047
1048 A **Reservation** allows reservation of resources associated with candidate that satisfies one or more demands.
1049
1050 Similar to the *instance_fit* constraint, requirements are sent as a request to a **service controller** that handles the reservation. Service controllers are defined by plugins in Homing (e.g., ``sdn-c``).
1051
1052 The service controller plugin knows how to make a reservation (and initiate rollback on a failure) with a particular endpoint (via HTTP/REST, DMaaP, etc.) of the service controller. The endpoint and credentials can be configured through plugin settings.
1053
1054 **Schema**
1055
1056 | Property       | Description                       |
1057 |----------------|-----------------------------------|
1058 | ``controller`` | Name of a service controller.     |
1059 | ``request``    | Opaque dictionary of key/value pairs. Values must be strings or numbers. Encoded and sent to the service provider via a plugin. |
1060
1061
1062 ```yaml
1063 resource_reservation:
1064   type: instance_reservation
1065   demands: [my_vnf_demand, my_other_vnf_demand]
1066   properties:
1067     controller: sdn-c
1068     request: REQUEST_DICT
1069 ```    
1070
1071 ## Optimizations
1072
1073 An **Optimization** allows specification of a objective function, which aims to maximize or minimize a certain value that varies based on the choice of candidates for one or more demands that are a part of the objective function. For example, an objective function may be to find the *closest* cloud-region to a customer to home a demand.
1074
1075 ### Optimization Components
1076
1077 Optimization definitions can be broken down into three components:
1078
1079 | Component | Key                  | Value                                                   |
1080 |-----------|----------------------|---------------------------------------------------------|
1081 | Goal      | ``minimize``         | A single Operand (usually ``sum``) or Function          |
1082 | Operator  | ``sum``, ``product`` | Two or more Operands (Numbers, Operators, Functions)    |
1083 | Function  | ``distance_between`` | A two-element list consisting of a location and demand. |
1084
1085
1086 ### Example
1087
1088 Given a customer location ``cl``, two demands ``vG1`` and ``vG2``, and weights ``w1`` and ``w2``, the optimization criteria can be expressed as:
1089
1090 ``minimize(weight1 * distance_between(cl, vG1) + weight2 * distance_between(cl, vG2))``
1091
1092 This can be read as: "Minimize the sum of weighted distances from cl to vG1 and from cl to vG2."
1093
1094 Such optimizations may be expressed in a template as follows:
1095
1096 ```yaml
1097 parameters:
1098   w1: 10
1099   w2: 20
1100
1101 optimization:
1102   minimize:
1103     sum:
1104     - product:
1105       - {get_param: w1}
1106       - {distance_between: [cl, vG1]}
1107     - product:
1108       - {get_param: w2}
1109       - {distance_between: [cl, vG2]}
1110 ```
1111
1112 Or without the weights as:
1113
1114 ```yaml
1115 optimization:
1116   minimize:
1117     sum:
1118     - {distance_between: [cl, vG1]}
1119     - {distance_between: [cl, vG2]}
1120 ```
1121
1122 **Template Restriction**
1123
1124 While the template format supports any number of arrangements of numbers, operators, and functions, HAS's solver presently expects a very specific arrangement.
1125
1126 Until further notice:
1127
1128 * Optimizations must conform to a single goal of ``minimize`` followed by a ``sum`` operator.
1129 * The sum can consist of two ``distance_between`` function calls, or two ``product`` operators.
1130 * If a ``product`` operator is present, it must contain at least a ``distance_between`` function call, plus one optional number to be used for weighting.
1131 * Numbers may be referenced via ``get_param``.
1132 * The objective function has to be written in the sum-of-product format. In the future, HAS can convert product-of-sum into sum-of-product automatically.
1133
1134 The first two examples in this section illustrate both of these use cases.
1135
1136 **Inline Operations**
1137
1138 If desired, operations can be rewritten inline. For example, the two ``product`` operations from the previous example can also be expressed as:
1139
1140 ```yaml
1141 parameters:
1142   w1: 10
1143   w2: 20
1144
1145 optimization:
1146   minimize:
1147     sum:
1148     - {product: [{get_param: w1}, {distance_between: [cl, vG1]}]}
1149     - {product: [{get_param: w2}, {distance_between: [cl, vG2]}]}
1150 ```
1151
1152 In turn, even the ``sum`` operation can be rewritten inline, however there is a point of diminishing returns in terms of readability!
1153
1154 **Notes**
1155
1156 * In the first version, we do not support more than one dimension in the optimization (e.g., Minimize distance and cost). For supporting multiple dimensions we would need a function the normalize the unit across dimensions.
1157
1158 ## Intrinsic Functions
1159
1160 Homing provides a set of intrinsic functions that can be used inside templates to perform specific tasks. The following section describes the role and syntax of the intrinsic functions.
1161
1162 Functions are written as a dictionary with one key/value pair. The key is the function name. The value is a list of arguments. If only one argument is provided, a string may be used instead.
1163
1164 ```yaml
1165 a_property: {FUNCTION_NAME: [ARGUMENT_LIST]}
1166
1167 a_property: {FUNCTION_NAME: ARGUMENT_STRING}
1168 ```
1169
1170 *Note: These functions can only be used within "properties" sections.*
1171
1172 ### get_file
1173
1174 The ``get_file`` function inserts the content of a file into the template. It is generally used as a file inclusion mechanism for files containing templates from other services (e.g., Heat).
1175
1176 The syntax of the ``get_file`` function is:
1177
1178 ```yaml
1179 {get_file: <content key>}
1180 ```
1181
1182 The ``content`` key is used to look up the ``files`` dictionary that is provided in the REST API call. The Homing client command (``Homing``) is ``get_file`` aware and populates the ``files`` dictionary with the actual content of fetched paths and URLs. The Homing client command supports relative paths and transforms these to the absolute URLs required by the Homing API.
1183
1184 **Note**: The ``get_file`` argument must be a static path or URL and not rely on intrinsic functions like ``get_param``. The Homing client does not process intrinsic functions. They are only processed by the Homing engine.
1185
1186 The example below demonstrates the ``get_file`` function usage with both relative and absolute URLs:
1187
1188 ```yaml
1189 constraints:
1190   check_for_fit:
1191     type: capacity
1192     demands: [my_vnf_demand, my_other_vnf_demand]
1193     properties:
1194       template: {get_file: stack_template.yaml}
1195       environment: {get_file: http://hostname/environment.yaml}
1196 ```
1197
1198 The ``files`` dictionary generated by the Homing client during instantiation of the plan would contain the following keys. Each value would be of that file's contents.
1199
1200 * ``file:///path/to/stack_template.yaml``
1201 * ``http://hostname/environment.yaml``
1202
1203 **Questions**
1204
1205 * If Homing will only be accessed over DMaaP, files will need to be embedded using the Homing API request format.
1206
1207 ### get_param
1208
1209 The ``get_param`` function references an input parameter of a template. It resolves to the value provided for this input parameter at runtime.
1210
1211 The syntax of the ``get_param`` function is:
1212
1213 ```yaml
1214 {get_param: <parameter name>}
1215
1216 {get_param: [<parameter name>, <key/index1> (optional), <key/index2> (optional), ...]}
1217 ```
1218
1219 **parameter name** is the parameter name to be resolved. If the parameters returns a complex data structure such as a list or a dict, then subsequent keys or indices can be specified. These additional parameters are used to navigate the data structure to return the desired value. Indices are zero-based.
1220
1221 The following example demonstrates how the ``get_param`` function is used:
1222
1223 ```yaml
1224 parameters:
1225   software_id: SOFTWARE_ID
1226   license_key: LICENSE_KEY
1227   service_info:
1228     provider: dmaap:///full.topic.name
1229     costs: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
1230
1231 constraints:
1232   my_software:
1233     type: license
1234     demands: [demand_1, demand_2, ...]
1235     properties:
1236       id: {get_param: software_id}
1237       key: {get_param: license_key}
1238
1239   check_for_availability:
1240     type: service
1241     demands: [my_vnf_demand, my_other_vnf_demand]
1242     properties:
1243       provider_url: {get_param: [service_info, provider]}
1244       request: REQUEST_DICT
1245       cost: {get_param: [service_info, costs, 4]}
1246 ```
1247
1248 In this example, properties would be set as follows:
1249
1250 | Key              | Value                    |
1251 |------------------|--------------------------|
1252 | ``id``           | SOFTWARE_ID              |
1253 | ``key``          | LICENSE_KEY              |
1254 | ``provider_url`` | dmaap:///full.topic.name |
1255 | ``cost``         | 50                       |
1256
1257 ## Contact ##
1258
1259 Shankar Narayanan <shankarpnsn@gmail.com>