Self Service Integration of IaaS Service
JSDN Self-Service integration provides the right tools for anyone who wants to on-board IaaS Services such as Cloud Stack in JSDN and can be managed through JSDN console.
- On Demand Provider (for Cloud Stack) should be created and the IaaS Service (Cloud Stack service subscription) should be configured in the JSDN.
- The service should be resold in the store. So that the users can consume.
- Ansible Script for Cloud Stack should be available and executed (in the database) in JSDN. - This section explains how the Ansible script structure should be and what query should be executed in db.
- IaaS Adapter skeleton.
- Few RESTApi (JDFs RESTApi’s) used to execute the Ansible script through the adapter.
Add On Demand Provider in JSDN
Let’s assume that you already created an On Demand Provider for Cloud Stack service in JSDN Marketplace. If not, see how to add an On Demand Provider in JSDN.
Configure IaaS Service Subscription
See how to configure IaaS Service Subscription.
Configure IaaS Compute Service
See how to configure Cloud Stack Compute Service.
Resell IaaS Service Subscription
See how to resell IaaS Service Subscription.
Integrate IaaS Service using Ansible
pip install cs
timeout = 30
In Java.security file add the following line jdk.tls.disabledAlgorithms=DHE
File Path : /d01/jdk1.7.0_51/jre/lib/security/java.security
- hosts: localhost
connection: local
gather_facts: no
vars:
api_region: ""
name: ""
network_offering: ""
zone: ""
tasks:
- name: create a network
cs_network:
api_url: https://compute.rnp.br/client/api
api_key: "{{ accessKey }}"
api_secret: "{{ secretKey }}"
api_region: "{{ api_region }}"
api_http_method: post
state: present
poll_async: yes
name: "{{ name }}"
network_offering: "{{ network_offering }}"
zone: "{{ zone }}"
delegate_to: localhost
Request Parameters for Create a Network Ansible Script. For more information refer to Cloud Stack Parameters.
api_url | URL of the CloudStack API e.g. https://cloud.example.com/client/api. If not given, the CLOUDSTACK_ENDPOINT env variable is considered. As the last option, the value is taken from the config file. |
api_key | API key of the CloudStack API. If not given, the CLOUDSTACK_KEY env variable is considered. As the last option, the value is taken from the ini config file. |
api_secret | Secret key of the CloudStack API. If not set, the CLOUDSTACK_SECRET env variable is considered. As the last option, the value is taken from the ini config file |
api_region | Name of the ini section in the cloustack.ini file. If not given, the CLOUDSTACK_REGION env variable is considered. |
api_http_method | HTTP method used to query the API endpoint. If not given, the CLOUDSTACK_METHOD env variable is considered. As the last option, the value is taken from the ini config file. Fallback value is get if not specified. |
state | State of the network. |
poll_async | Poll async jobs until job has finished. |
name | Name (case sensitive) of the network. This is a mandatory parameter. |
network_offering | Name of the offering for the network. Required if state=present. |
zone | Name of the zone in which the network should be deployed. If not set, default zone is used. |
How to add Ansible Scripts in JSDN?
INSERT INTO jci_provider_resource_template (
provider_resource_template_id,resource_template_type_id,provider_code,actor_id,resource_type_id,template_action_code,
template_name,template_content,status,created_date,created_by,updated_date,updated_by,script_input_json)
VALUES ((select MAX(provider_resource_template_id)+1 from jci_provider_resource_template),100000,'cloudstack',1000,29,'vm','createNetwork','- hosts: localhost
connection: local
gather_facts: no
vars:
api_region: ""
name: ""
network_offering: ""
zone: ""
tasks:
- name: create a network
cs_network:
api_url: https://compute.rnp.br/client/api
api_key: "{{ accessKey }}"
api_secret: "{{ secretKey }}"
api_region: "{{ api_region }}"
api_http_method: post
state: present
poll_async: yes
name: "{{ name }}"
network_offering: "{{ network_offering }}"
zone: "{{ zone }}"
delegate_to: localhost','A',now(),'1002',now(),'1002',null);
Please insert the following UI Metadata quarries for each Ansible Scripts:
insert into jcp_ui_metadata values('jsdn.resourcescript.help.network_offering',1000,'en_US','M','Enter the Network Offering');
insert into jcp_ui_metadata values('jsdn.resourcescript.validation.network_offering',1000,'en_US','M','.*');
insert into jcp_ui_metadata values('jsdn.resourcescript.lable.network_offering',1000,'en_US','M','Network Offering');
insert into jcp_ui_metadata values('jsdn.resourcescript.validationmsg.network_offering',1000,'en_US','M','Enter the correct Network Offering');
insert into jcp_ui_metadata values('jsdn.store.resourcescript.template.createNetwork',1000,'en_US','M','Create Network');
IaaS Adapter Skeleton
Developing an Adapter
Before developing an Adapter, you must have the skeleton/format of the adapter. The image below shows how an Skeleton/format of the adapter looks like for creating a network.For each of the actions (as mentioned below), the system will call a specific executor of the adapter for example Create a Network, where the code (executing the REST API (JDF REST APIs) for executing an Ansible Script (create a network) should be written. Once the Anisble Script respond the adapter sends the status back to JSDN. If it is successful, the action is considered as completed.Life Cycle of VM (Actions)
- Launching a VM/Create a VM
- Start/Stop VM
- Reboot
- Terminate
- Create a Network
- Get Static Public IP
- Create Image
- Security Group
- Monitoring
- Deploy the adapter in JSDN (tomcat server).
- Configure the Adapter URL in the service.
Using RestAPIs to execute Ansible Scripts
JDF is a very simple rest api for executing Ansible ad-hoc-commands. Here is a sample script to execute, you just need to modify the variables as per the Ansible script that you are going to execute.
To execute the script run "executeScript" command.
Request: (Header)
POST api/v2/resource-script/executeScript
HTTP/1.1
Content-type: application/json
Accept: application/json
X-Auth-Token: v92jndh7saL1ZkCu0TrgkL3v347IQ31q
proxy-store:storeCompanyAcronym
proxy-end-customer:customerCompanyAcronym
{ "executeScript":{
"provider-code":"cloudstack",
"template-name":"createNetwork",
"template-code":"vm",
"script-type":"ansible",
"script-name":"createNetwork",
"tenant-active-state":"Y",
"parameters":{
"iam_role_name":"<name of the script>",
"policy_name":"AmazonEC2ContainerServiceforEC2Role"
},
"async":false
}
}
Response:
{
"resource-script-response": {
"response-code": "SUCCESS",
"response-description": [
"Execute script initiated successfully."
]
}
}
Request:
GET api/v2/resource-script/getResourceScriptStatus/{script-name}
HTTP/1.1
Content-type: application/json
Accept: application/json
X-Auth-Token: v92jndh7saL1ZkCu0TrgkL3v347IQ31q
proxy-store:storeCompanyAcronym
proxy-end-customer:customerCompanyAcronym
{"ExecuteScriptStatusResponse":{"resourceScript":{"scriptId":100000,"actorId":4015222,"providerResourceTemplate":{"providerTemplateId":100000,"resourceTemplateType":{"templateTypeId":100000,"templateTypeCode":"rds"},"providerCode":"aws","actorId":1000,"resourceTypeId":21,"providerName":"Amazon
Web
Services","templatecode":"rds","templateName":"launchdb","templateContent":"-
hosts: localhost\n
vars:\n vpc_name: \"\"\n private_subnet_name: \"\"\n
private_subnet_name2: \"\"\n rds_sg_cidr_ip: \"\"\n rds_db_instance_name:
\"\"\n
rds_db_name: \"\"\n rds_db_username:
\"\"\n rds_db_password:
\"\"\n
aws_region: \"\"\n rds_sg_name:
\"\"\n rds_sg_desc:
\"\"\n
db_engine: \"\"\n size: \"\"\n instance_type: \"\"\n
publicly_accessible: \"true\"\n backup_retention: \"0\"\n tasks: \n -
ec2_vpc_net_facts:\n filters:\n
\"tag:Name\": \"{{ vpc_name
}}\"
\n
aws_access_key: \"{{ accessKey }}\"\n
aws_secret_key: \"{{ secretKey
}}\"\n
region: \"{{ aws_region }}\"\n register: vpc_net_facts\n\n - name:
Gather VPC facts\n ec2_vpc_subnet_facts:\n
aws_access_key: \"{{ accessKey
}}\"\n
aws_secret_key: \"{{ secretKey }}\"\n
region: \"{{ aws_region
}}\"\n
filters:\n \"tag:Name\": \"{{
private_subnet_name }}\"\n
register: vpc_facts \n \n - name:
Gather VPC facts\n ec2_vpc_subnet_facts:\n
aws_access_key: \"{{ accessKey
}}\"\n aws_secret_key: \"{{
secretKey }}\"\n
region: \"{{
aws_region }}\"\n filters:\n \"tag:Name\": \"{{
private_subnet_name2 }}\"\n register: vpc_subnet_facts\n \n - name: Set
subnets in
variable
\n set_fact:\n rds_subnet_id:
\"{{
vpc_facts.subnets[0].id }}\"\n\n - name: Set RDS endpoint
in
variable\n
set_fact:\n rds_subnet_id2: \"{{
vpc_subnet_facts.subnets[0].id }}\"\n\n - name: Create DB Subnet Group \n
rds_subnet_group:\n state: present\n aws_access_key: \"{{ accessKey
}}\"\n
aws_secret_key: \"{{ secretKey
}}\"\n region: \"{{ aws_region
}}\"
\n
name: \"default1-{{
vpc_facts.subnets[0].vpc_id }}\"\n
description: My DB
Subnet Group\n subnets:\n - \"{{ rds_subnet_id }}\"\n - \"{{
rds_subnet_id2 }}\" \n register:
RDSSubnetGroup\n\n - name: Create RDS
security
group\n
ec2_group:\n aws_access_key: \"{{
accessKey }}\"\n
aws_secret_key: \"{{ secretKey }}\"\n name: \"{{ rds_sg_name }}\"\n
description:
\"{{ rds_sg_desc }}\"\n region: \"{{
aws_region }}\"\n vpc_id:
\"{{ vpc_facts.subnets[0].vpc_id }}\"\n state: present\n rules:\n
-
proto: tcp\n from_port: 5432\n
to_port: 5432\n
cidr_ip: \"{{ rds_sg_cidr_ip }}\"\n register:
RDSGroup\n\n - name: Create
PostgreSQL
on RDS\n
rds:\n aws_access_key: \"{{
accessKey }}\"\n
aws_secret_key: \"{{ secretKey }}\"\n command:
create\n
instance_name: \"{{ rds_db_instance_name
}}\"\n region: \"{{
aws_region
}}\"\n
subnet: \"default1-{{ vpc_facts.subnets[0].vpc_id }}\" \n
vpc_security_groups: \"{{ RDSGroup.group_id
}}\"\n db_engine: \"{{
db_engine
}}\"\n
size: \"{{ size }}\"\n
instance_type: \"{{ instance_type
}}\"\n
db_name: \"{{ rds_db_name }}\"\n username: \"{{
rds_db_username }}\"\n password: \"{{ rds_db_password }}\"\n
publicly_accessible: \"{{ publicly_accessible }}\"\n backup_retention: \"{{
backup_retention }}\"\n wait: yes\n wait_timeout: 600\n
tags:\n
Environment:
Development\n
Application:
JSDN\n
register:
rds\n\n","status":"A","createdBy":{"actorId":1002,"company":{"actorId":1000,"companyName":"jamcracker","companyShortName":"jamcracker","marketpalceId":1000,"status":"A"},"loginName":"root","firstName":"System","lastName":"User","email":"admin@newCompany.com","status":"A","primaryContact":true},"updatedBy":{"actorId":1002,"company":{"actorId":1000,"companyName":"jamcracker","companyShortName":"jamcracker","marketpalceId":1000,"status":"A"},"loginName":"root","firstName":"System","lastName":"User","email":"admin@newCompany.com","status":"A","primaryContact":true},"creationDate":1512498600000,"updateDate":1512498600000,"scriptInputJson":"{\"optional\":[{\"help\":\"jsdn.resourcescript.help.publicly_accessible\",\"validation\":\"jsdn.resourcescript.validation.publicly_accessible\",\"value\":[{\"value\":\"true\",\"key\":\"true\"},{\"value\":\"false\",\"key\":\"false\"}],\"label\":\"jsdn.resourcescript.lable.publicly_accessible\",\"key\":\"publicly_accessible\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.publicly_accessible\"},{\"help\":\"jsdn.resourcescript.help.backup_retention\",\"validation\":\"jsdn.resourcescript.validation.backup_retention\",\"value\":\"0\",\"label\":\"jsdn.resourcescript.lable.backup_retention\",\"key\":\"backup_retention\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.backup_retention\"}],\"layout\":\"double\",\"required\":[{\"help\":\"jsdn.resourcescript.help.aws_region\",\"validation\":\"jsdn.resourcescript.validation.aws_region\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.aws_region\",\"key\":\"aws_region\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.aws_region\"},{\"help\":\"jsdn.resourcescript.help.vpc_name\",\"validation\":\"jsdn.resourcescript.validation.vpc_name\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.vpc_name\",\"key\":\"vpc_name\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.vpc_name\"},{\"help\":\"jsdn.resourcescript.help.instance_type\",\"validation\":\"jsdn.resourcescript.validation.instance_type\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.instance_type\",\"key\":\"instance_type\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.instance_type\"},{\"help\":\"jsdn.resourcescript.help.rds_db_instance_name\",\"validation\":\"jsdn.resourcescript.validation.rds_db_instance_name\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.rds_db_instance_name\",\"key\":\"rds_db_instance_name\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.rds_db_instance_name\"},{\"help\":\"jsdn.resourcescript.help.rds_db_username\",\"validation\":\"jsdn.resourcescript.validation.rds_db_username\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.rds_db_username\",\"key\":\"rds_db_username\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.rds_db_username\"},{\"help\":\"jsdn.resourcescript.help.rds_sg_desc\",\"validation\":\"jsdn.resourcescript.validation.rds_sg_desc\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.rds_sg_desc\",\"key\":\"rds_sg_desc\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.rds_sg_desc\"},{\"help\":\"jsdn.resourcescript.help.size\",\"validation\":\"jsdn.resourcescript.validation.size\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.size\",\"key\":\"size\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.size\"},{\"help\":\"jsdn.resourcescript.help.private_subnet_name2\",\"validation\":\"jsdn.resourcescript.validation.private_subnet_name2\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.private_subnet_name2\",\"key\":\"private_subnet_name2\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.private_subnet_name2\"},{\"help\":\"jsdn.resourcescript.help.rds_sg_name\",\"validation\":\"jsdn.resourcescript.validation.rds_sg_name\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.rds_sg_name\",\"key\":\"rds_sg_name\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.rds_sg_name\"},{\"help\":\"jsdn.resourcescript.help.rds_db_name\",\"validation\":\"jsdn.resourcescript.validation.rds_db_name\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.rds_db_name\",\"key\":\"rds_db_name\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.rds_db_name\"},{\"help\":\"jsdn.resourcescript.help.private_subnet_name\",\"validation\":\"jsdn.resourcescript.validation.private_subnet_name\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.private_subnet_name\",\"key\":\"private_subnet_name\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.private_subnet_name\"},{\"help\":\"jsdn.resourcescript.help.rds_sg_cidr_ip\",\"validation\":\"jsdn.resourcescript.validation.rds_sg_cidr_ip\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.rds_sg_cidr_ip\",\"key\":\"rds_sg_cidr_ip\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.rds_sg_cidr_ip\"},{\"help\":\"jsdn.resourcescript.help.db_engine\",\"validation\":\"jsdn.resourcescript.validation.db_engine\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.db_engine\",\"key\":\"db_engine\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.db_engine\"},{\"help\":\"jsdn.resourcescript.help.rds_db_password\",\"validation\":\"jsdn.resourcescript.validation.rds_db_password\",\"value\":\"\",\"label\":\"jsdn.resourcescript.lable.rds_db_password\",\"key\":\"rds_db_password\",\"validationmsg\":\"jsdn.resourcescript.validationmsg.rds_db_password\"}]}"},"scriptName":"test1","scriptContent":"Launch
DB
Instance","status":"C","createdDate":1512564919928,"updatedDate":1512568950605,"createdBy":{"actorId":4015223,"company":{"actorId":4015222,"companyName":"mntstore","companyShortName":"mntstore","parentCompanyId":4015220,"marketpalceId":4015220,"status":"A"},"loginName":"mntstore.gmail.com","firstName":"mntstore","lastName":"mntstore","email":"mntstore@gmail.com","status":"A","primaryContact":true},"updatedBy":{"actorId":4015223,"company":{"actorId":4015222,"companyName":"mntstore","companyShortName":"mntstore","parentCompanyId":4015220,"marketpalceId":4015220,"status":"A"},"loginName":"mntstore.gmail.com","firstName":"mntstore","lastName":"mntstore","email":"mntstore@gmail.com","status":"A","primaryContact":true}},"resourceScriptLog":{"scriptLogId":100001,"resourceScriptId":100000,"scriptRequest":"Launch
DB Instance","scriptResponse":"ansible-playbook
2.4.1.0\n config file = None\n
configured module search path =
[u'/d01/jboss-as-7.1.1.Final/.ansible/plugins/modules',
u'/usr/share/ansible/plugins/modules']\n ansible python module location =
/usr/lib/python2.7/site-packages/ansible\n executable location = /bin/ansible-playbook\n
python version = 2.7.5 (default, Nov 6
2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat
4.8.5-11)]\nNo config file found;
using
defaults\n","isvResourceId":"NA","status":"C","createdDate":1512568950664,"createdBy":{"actorId":4015223,"company":{"actorId":4015222,"companyName":"mntstore","companyShortName":"mntstore","parentCompanyId":4015220,"marketpalceId":4015220,"status":"A"},"loginName":"mntstore.gmail.com","firstName":"mntstore","lastName":"mntstore","email":"mntstore@gmail.com","status":"A","primaryContact":true},"updatedDate":1512568950664,"updatedBy":{"actorId":4015223,"company":{"actorId":4015222,"companyName":"mntstore","companyShortName":"mntstore","parentCompanyId":4015220,"marketpalceId":4015220,"status":"A"},"loginName":"mntstore.gmail.com","firstName":"mntstore","lastName":"mntstore","email":"mntstore@gmail.com","status":"A","primaryContact":true}}}}