Understanding How This Works

 
 
 

To understand how all this works, let's take a look at how they all fit together. The following figure shows the relationship between these entities and what each of the Consumer, the Service Operator and the Connector deal with.

To summarize at a high level, the Consumer can provision resources of a given resource type either directly on a pay-as-you go basis or by purchasing a subscription to a Product Bundle.

Service Operators define Products and Product Bundles. Products and Product bundles have prices. You can pay as a utility, Pay-as-you-go, or recurring respectively. Bundles may also provide free usage in terms of entitlements along with the purchase of a subscription. Bundles in turn will also provision resources but subject to the pricing of the bundle. Resources provisioned without a subscription will be charged on a utility basis. Products have mediation rules that allow CPBM to mediate usage reported by the cloud service (via the connector).

Connectors provide meta information, in terms of the Resource Types available, their components, UsageTypes with their discriminators and Filters which allow Resource Types to be classified and Usage to be mediated. Some usage is generated only when resources of the corresponding resource type are provisioned. This usage is directly attributable to that resource. Other usage can be generated based on other activity in the cloud service which will be accrued at the user (or account) level.

Figure 1. Product Management Inter-relationships


The following sections describe how all of the above come together under various scenarios and use cases.

Product Management

When creating products, CPBM will call getResourceComponentValues(first form), getFilterValues and getDiscriminatorValues to create mediation rules based on all these discriminators. Remember that resource component values as well as filter values are both implicit discriminator candidates.

The interactions between CPBM, the connector metadata and the MetadataRegistry during the creation of products is shown in the figures below.

Figure 2. Product creation


When creating product bundles, CPBM will use metadata to identify resource types and call getResourceComponentValues to build provisioning constraints.

The interactions between CPBM, the connector metadata and the MetadataRegistry is during the creation of product bundles is shown in the figure below.

Figure 3. Product bundle creation


Subscription Process

When a customer buys a bundle, the system detects the provisioned resource type and uses that to determine the launch experience. The following steps are performed:
  • For a given resource type, the system first identifies the set of filters to present to the user. This is extracted from the service metadata. The filter values are determined by calling getFilterValues from the MetadataRegistry.
  • Once filter values are selected, the system presents the possible choices of resource components to select from. The components are presented in the order defined in service metadata. The possible value choices (with filters applied) are acquired from getResourceComponentValues in the MetadataRegistry (Note that the appropriate tenant and user handles are passed to these methods.). Selections of prior resource components may affect available choices for subsequent resource components. Bundle choices are further filtered based on bundle provisioning constraints. A choice will not be shown unless there's at least one corresponding bundle whose constraints allow the current selection of resource components.
  • Prices are shown for all bundles/products (see below for a discussion on how pricing display is determined)
  • Customer selects the bundle to subscribe to
  • The subscription is created. If user requested immediate provisioning, then provisioning flow kicks in. Otherwise user can navigate to the subscription and provision at a later time.

Displaying prices

The following items are collected as discriminators:
  1. Applied filters and their values
  2. Selected Resource components

Based on this, all products that match those discriminators (The match is non-unique, ie it is possible that multiple products match for the above discriminators - this is because they may be differentiated based on other discriminators) and their corresponding prices are shown.

Provisioning Flow

If this resource type depends on another resource type as:
  • ADDON: The system lists the resources of the target resource type for selection (the handle to that resource is passed to the provisioning call).
  • AVAILABLE: The system checks to see if a resource of a given target resource type is already provisioned for this user/account (depending on the scope of the target resource type) before proceeding, failing if the target resource type has not been provisioned.

If custom fields are needed for provisioning, they are presented to the user for input. A mechanism to customize the UI for this is available. See UI contributions for more details. Any resource component selected may be modified at this time, but only within the constraints of the subscribed bundle. The system provides subscription data to the subscription provisioning handler of underlying service to provision the resource.

Sample Product Metadata

Example 1:
<?xml version="1.0" encoding="UTF-8"?>  <Service>    <Bootstrap>      <Id type="CLOUD" singleton="false" category="IAAS">com.citrix.cloudplatform</Id>      <Connector ref="cloudPlatformConnector"/>      <Image type="logo">logo.jpg</Image>        <Image type="banner">logo.jpg</Image>       <Vendor version="1.1.8">Citrix</Vendor>      <Locales>en_US, ja_JP, ko_KR, fr, es, pt_BR, zh_CN</Locales>      <Configuration>      <!-- Any Properties that are added here must also be added to the ENUM in MetadataRegistryImpl -->        <Property id="publicProtocol" type="String" encrypted="false" validation='{"required":true, "regex":"^(http|https)$"}' default='http' />        <Property id="publicHost" type="String" encrypted="false" validation='{"required":true}' />        <Property id="publicPort" type="Integer" encrypted="false" validation='{"required":true}' default='8080' />        <Property id="cloud.jdbc.host" type="String" encrypted="false" validation='{"required":true}' />        <Property id="cloud.jdbc.username" type="String" encrypted="false" validation='{"required":true}' default='cloud' />        <Property id="cloud.jdbc.password" type="String" encrypted="true" validation='{"required":true, "confirmationRequired":true}' default='cloud' />        <Property id="cloud.jdbc.database.schemaname" type="String" encrypted="false" validation='{"required":false}' default='cloud' />        <Property id="cloud.usage.jdbc.host" type="String" encrypted="false" validation='{"required":false}' />        <Property id="cloud.usage.jdbc.username" type="String" encrypted="false" validation='{"required":false}' default='cloud' />        <Property id="cloud.usage.jdbc.password" type="String" encrypted="true" validation='{"required":false, "confirmationRequired":true}' default='cloud'/>        <Property id="cloud.usage.jdbc.database.schemaname" type="String" encrypted="false" validation='{"required":false}' default='cloud_usage' />        <Property id="ssoKey" type="String" encrypted="true" validation='{"required":true}' />        <Property id="apiKey" type="String" encrypted="false" validation='{"required":true}' />        <Property id="secretKey" type="String" encrypted="true" validation='{"required":true}' />        <Property id="parentDomainId" type="String" encrypted="false" validation='{"required":true}' default='1' />        <Property id="adminServerList" type="String" encrypted="false" validation='{"required":true}' />        <Property id="nonAdminServerList" type="String" encrypted="false" validation='{"required":true}' />        <Property id="apiProxySuffix" type="String" encrypted="false" validation='{"required":true, "regex":"^[a-zA-Z0-9_]+$"}' unique="true"/>        <Property id="apiWhitelist" type="String" encrypted="false" validation='{"required":false}' />        <Property id="apiBlacklist" type="String" encrypted="false" validation='{"required":false}' />        <Property id="default.vm.locale" type="String" encrypted="false" validation='{"required":false, "regex":"^(de|de-ch|es|fi|fr|fr-be|fr-ch|is|it|jp|nl-be|no|pt|uk|us)$"}' default='us'/>        <Property id="max.custom.disk.offering.size" type="Integer" encrypted="false" validation='{"required":false}' default='1024'/>      </Configuration>    </Bootstrap>        <AccountControls>      <Property id="sharedAccount" type="Boolean" validation='{"required":false}'/>      <Property id="defaultNetworkOffering" type="String" validation='{"required":false}'/>         <Property id="perAccountPublicIPCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountSnapshotCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountTemplateCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountVmCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountVolumeCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountNetworkCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountVPCCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountCPUCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountRAMAmount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountPrimaryStorageAmount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perAccountSecondaryStorageAmount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserPublicIPCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserSnapshotCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserTemplateCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserVmCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserVolumeCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserNetworkCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserVPCCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserCPUCount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserRAMAmount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserPrimaryStorageAmount" type="Integer" validation='{"required":false, "minval":"-1"}' />         <Property id="perUserSecondaryStorageAmount" type="Integer" validation='{"required":false, "minval":"-1"}' />    </AccountControls>      <ResourceMetadata>      <ResourceType name="VirtualMachine" constraint="NONE" componentSelector="apachecloudstack.fragment.resource.virtual.machine.components.selection">        <Properties editor="apachecloudstack.fragment.resource.virtual.machine.properties.selection">          <Property id="hostName" type="String" validation='{"required":false, "regex":"^[a-zA-Z]{1}[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]{1}$"}'/>          <Property id="displayName" type="String" validation='{"required":false}'/>          <Property id="group" type="String" validation='{"required":false}'/>          <Property id="diskOfferingUuid" type="String" validation='{"required":false}'/>          <Property id="keypair" type="String" validation='{"required":false}'/>          <Property id="diskSize" type="Integer" validation='{"required":false}'/>          <Property id="keyboard" type="String" validation='{"required":false, "regex":"de|de-ch|es|fi|fr|fr-be|fr-ch|is|it|jp|nl-be|no|pt|uk|us"}'/>          <Property id="networkIds" type="String" validation='{"required":false}'/>          <Property id="securitygroupIds" type="String" validation='{"required":false}'/>          <Property id="userData" type="String" validation='{"required":false}'/>          <Property id="ipAddress" type="String" validation='{"required":false, "regex":"^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})*$"}'/>          <Property id="ipToNetworkList" type="String" validation='{"required":false, "regex":"^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3},[0-9a-zA-Z\-]+;)*$"}'/>        </Properties>        <Component name="templateUuid" discriminator="templateUuid" />        <Component name="hypervisorType" discriminator="hypervisorType" />        <Component name="serviceOfferingUuid" discriminator="serviceOfferingUuid" reconfigurable="true"/>        <Generates>          <Usage>RUNNING_VM</Usage>          <Usage>ALLOCATED_VM</Usage>          <Usage>ROOT_VOLUME</Usage>        </Generates>      </ResourceType>        <ResourceType name="Volume" constraint="NONE">        <Properties>          <Property id="name" type="String" validation='{"required":true}'/>          <Property id="size" type="Integer" validation='{"required":false}'/>        </Properties>        <Group name="fromDiskOffering">          <Component name="diskOfferingUuid" discriminator="diskOfferingUuid"/>        </Group>        <Generates>          <Usage>VOLUME</Usage>        </Generates>      </ResourceType>            <ResourceType name="Network" constraint="NONE">        <Properties editor="apachecloudstack.fragment.resource.network.properties.selection">          <Property id="name" type="String" validation='{"required":true}'/>          <Property id="displayText" type="String" validation='{"required":true}'/>          <Property id="gateway" type="String" validation='{"required":false, "regex":"^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})*$"}'/>          <Property id="netmask" type="String" validation='{"required":false, "regex":"^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})*$"}'/>          <Property id="networkDomain" type="String" validation='{"required":false}'/>          <Property id="vpcId" type="String" validation='{"required":false}'/>        </Properties>        <Group name="fromNetworkOffering">          <Component name="networkOfferingUuid" discriminator="networkOfferingUuid"/>        </Group>        <Generates>          <Usage>NETWORK_BYTES_SENT</Usage>          <Usage>NETWORK_BYTES_RECEIVED</Usage>        </Generates>      </ResourceType>            <UsageType name="RUNNING_VM" uom="Compute-Hours">        <Discriminator>isHaEnabled</Discriminator>        <Discriminator>guestOsName</Discriminator>        <Discriminator>isIso</Discriminator>      </UsageType>          <UsageType name="ALLOCATED_VM" uom="Compute-Hours">        <Discriminator>isHaEnabled</Discriminator>        <Discriminator>guestOsName</Discriminator>        <Discriminator>isIso</Discriminator>      </UsageType>            <UsageType name="ROOT_VOLUME" uom="Byte-Hours">        <Discriminator>poolType</Discriminator>        <Discriminator>volumeTags</Discriminator>      </UsageType>            <UsageType name="VOLUME" uom="Byte-Hours">        <Discriminator>poolType</Discriminator>        <Discriminator>volumeTags</Discriminator>      </UsageType>          <UsageType name="TEMPLATE" uom="Byte-Hours" />        <UsageType name="ISO" uom="Byte-Hours"/>            <UsageType name="SNAPSHOT" uom="Byte-Hours">        <Discriminator>diskOfferingUuid</Discriminator>        <Discriminator>poolType</Discriminator>      </UsageType>            <UsageType name="IP_ADDRESS" uom="IP-Hours"/>          <UsageType name="NETWORK_BYTES_RECEIVED" uom="Bytes">        <Discriminator>isRedundantRouterServiceEnabled</Discriminator>        <Discriminator>isVlanEnabled</Discriminator>        <Discriminator>networkType</Discriminator>      </UsageType>            <UsageType name="NETWORK_BYTES_SENT" uom="Bytes">        <Discriminator>isRedundantRouterServiceEnabled</Discriminator>        <Discriminator>isVlanEnabled</Discriminator>        <Discriminator>networkType</Discriminator>      </UsageType>          <UsageType name="SECURITY_GROUP" uom="SecurityGroup-Hours"/>          <UsageType name="LOAD_BALANCER_POLICY" uom="Policy-Hours"/>          <UsageType name="PORT_FORWARDING_RULE" uom="Rule-Hours"/>          <UsageType name="VPN_USERS" uom="Vpn-Hours"/>        <Uom raw="Bytes">        <Scale name="GB" conversionFactor="1073741824" default="true" />        <Scale name="TB" conversionFactor="1099511627776" />      </Uom>            <Uom raw="Byte-Hours">        <Scale name="GB-Months" conversionFactor="1073741824" default="true" monthly="true" />        <Scale name="TB-Months" conversionFactor="1099511627776" monthly="true" />        <Scale name="GB-Days" conversionFactor="25769803776" />        <Scale name="TB-Days" conversionFactor="26388279066624" />      </Uom>            <Uom raw="Compute-Hours">        <Scale name="Compute-Days" conversionFactor="24" />      </Uom>            <Uom raw="Vpn-Hours">        <Scale name="Vpn-Days" conversionFactor="24" />        <Scale name="Vpn-Months" conversionFactor="1" monthly="true" />      </Uom>            <Uom raw="IP-Hours">        <Scale name="IP-Days" conversionFactor="24" />        <Scale name="IP-Months" conversionFactor="1" default="true" monthly="true" />      </Uom>            <Uom raw="Policy-Hours">        <Scale name="Policy-Days" conversionFactor="24" />        <Scale name="Policy-Months" conversionFactor="1" default="true" monthly="true" />      </Uom>            <Uom raw="Rule-Hours">        <Scale name="Rule-Days" conversionFactor="24" />        <Scale name="Rule-Months" conversionFactor="1" default="true" monthly="true" />      </Uom>            <Uom raw="SecurityGroup-Hours">        <Scale name="SecurityGroup-Days" conversionFactor="24" />        <Scale name="SecurityGroup-Months" conversionFactor="1" monthly="true" />      </Uom>            <Filter name="zoneUuid" />    </ResourceMetadata>        <Roles>      <Role name="ROLE_CLOUD_MANAGEMENT" scope="GLOBAL" />      <Role name="ROLE_ACCOUNT_CLOUD_MANAGEMENT" scope="TENANT" />      <Role name="ROLE_USER_CLOUD_MANAGEMENT" scope="TENANT" />    </Roles>  </Service>
Example 2:
<?xml version="1.0" encoding="UTF-8"?>  <Service>    <Bootstrap>      <Id type="CLOUD" singleton="false" category="SAAS">com.citrix.cpsm</Id>      <Connector ref="cpsmServiceConnector">com.citrix.cpsm.connector.CPSMCloudServiceConnectorImpl</Connector>      <Image type="logo">logo.jpg</Image>	      <Image type="banner">logo.jpg</Image>       <Vendor version="1.0.1">Citrix</Vendor>      <Locales>en_US</Locales>      <Configuration>        <Property id="hostURL" type="String" encrypted="false" validation='{"required":true}' />        <Property id="username" type="String" encrypted="false" validation='{"required":true}' />        <Property id="password" type="String" encrypted="true" validation='{"required":true}' />        <Property id="cortexApiURL" type="String" encrypted="false" validation='{"required":false}' />        <Property id="ecommerceApiURL" type="String" encrypted="false" validation='{"required":false}' />        <Property id="ssoURL" type="String" encrypted="false" validation='{"required":false}' />        <Property id="extendedProperties" type="String" encrypted="false" validation='{"required":false}' />      </Configuration>      <AccountConfiguration editor="com.citrix.cpsm.fragment.customAccountConfigurationEditor">        <!-- TODO: Can we allow a '-' character in the validation regex below ? -->        <Property id="code" type="String" validation='{"required":true, "regex":"^[a-zA-Z0-9]{3,5}$"}' />  	  <Property id="domain"  type="String" validation='{"required":true, "regex":"^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$"}' />  	  <Property id="cpsmUsername"  type="String" validation='{"required":true, "regex":"^[a-zA-Z0-9]{5,14}$"}' />  	</AccountConfiguration>    </Bootstrap>    <ResourceMetadata>      <ResourceType name="HE" constraint="SINGLETON">        <Group name="CustomerPlanGroup">        	<Component name="HECustomerPlanID" discriminator="HECustomerPlanID" reconfigurable="false"/>        </Group>        <Generates>          <Usage>HE</Usage>        </Generates>      </ResourceType>      <ResourceType name="HostedAppsandDesktops" constraint="SINGLETON">        <Group name="CustomerPlanGroup">        	<Component name="HostedAppsandDesktopsCustomerPlanID" discriminator="HostedAppsandDesktopsCustomerPlanID" reconfigurable="false"/>        </Group>        <Generates>          <Usage>HostedAppsandDesktops</Usage>        </Generates>      </ResourceType>      <UsageType name="HE" uom="units per month" discrete="true"/>      <UsageType name="HEUserPlan" uom="units per month" discrete="true">        <Discriminator>HEUserPlanID</Discriminator>      </UsageType>      <UsageType name="HostedAppsandDesktops" uom="units per month" discrete="true"/>      <UsageType name="HostedAppsandDesktopsUserPlan" uom="units per month" discrete="true">        <Discriminator>HostedAppsandDesktopsUserPlanID</Discriminator>      </UsageType>      <UsageType name="HostedAppsandDesktopsOffering" uom="units per month" discrete="true">        <Discriminator>HostedAppsandDesktopsOfferingID</Discriminator>      </UsageType>      <Uom raw="units per month" discrete="true"/>    </ResourceMetadata>    <Roles>      <Role name="ROLE_CPSM_GLOBAL_MANAGEMENT" scope="GLOBAL" />      <Role name="ROLE_CPSM_OPS_USER" scope="GLOBAL" />      <Role name="ROLE_CPSM_TENANT_MANAGEMENT" scope="TENANT_ADMIN" />      <Role name="ROLE_CPSM_USER" scope="TENANT_ADMIN" />    </Roles>    <ChannelSettings>      <Property id="location" type="String" encrypted="false" validation='{"required":true}' reconfigurable="false" />    </ChannelSettings>   </Service>
 
他にご質問がございましたら、リクエストを送信してください

コメント

 
Adding comment, please wait....

Provide Feedback on Article:

Subject:
Comments:*