import socket
import time
-import heatclient
+import heatclient.client
import pkg_resources
from oslo_utils import encodeutils
if self.uuid is None:
return
- log.info("Deleting stack '%s', uuid:%s", self.name, self.uuid)
+ log.info("Deleting stack '%s' START, uuid:%s", self.name, self.uuid)
heat = self.heat_client
template = heat.stacks.get(self.uuid)
start_time = time.time()
template.delete()
for status in iter(self.status, u'DELETE_COMPLETE'):
- log.debug("stack state %s", status)
+ log.debug("Deleting stack state: %s", status)
if status == u'DELETE_FAILED':
raise RuntimeError(
heat.stacks.get(self.uuid).stack_status_reason)
time.sleep(2)
end_time = time.time()
- log.info("Deleted stack '%s' in %d secs", self.name,
+ log.info("Deleting stack '%s' DONE in %d secs", self.name,
end_time - start_time)
self.uuid = None
'value': {'get_resource': name}
}
+ def add_volume(self, name, size=10):
+ """add to the template a volume description"""
+ log.debug("adding Cinder::Volume '%s' size '%d' ", name, size)
+
+ self.resources[name] = {
+ 'type': 'OS::Cinder::Volume',
+ 'properties': {'name': name,
+ 'size': size}
+ }
+
+ self._template['outputs'][name] = {
+ 'description': 'Volume %s ID' % name,
+ 'value': {'get_resource': name}
+ }
+
+ def add_volume_attachment(self, server_name, volume_name, mountpoint=None):
+ """add to the template an association of volume to instance"""
+ log.debug("adding Cinder::VolumeAttachment server '%s' volume '%s' ", server_name,
+ volume_name)
+
+ name = "%s-%s" % (server_name, volume_name)
+
+ volume_id = op_utils.get_volume_id(volume_name)
+ if not volume_id:
+ volume_id = {'get_resource': volume_name}
+ self.resources[name] = {
+ 'type': 'OS::Cinder::VolumeAttachment',
+ 'properties': {'instance_uuid': {'get_resource': server_name},
+ 'volume_id': volume_id}
+ }
+
+ if mountpoint:
+ self.resources[name]['properties']['mountpoint'] = mountpoint
+
def add_network(self, name, physical_network='physnet1', provider=None,
- segmentation_id=None):
+ segmentation_id=None, port_security_enabled=None, network_type=None):
"""add to the template a Neutron Net"""
log.debug("adding Neutron::Net '%s'", name)
if provider is None:
self.resources[name] = {
'type': 'OS::Neutron::Net',
- 'properties': {'name': name}
+ 'properties': {
+ 'name': name,
+ }
}
else:
self.resources[name] = {
'type': 'OS::Neutron::ProviderNet',
'properties': {
'name': name,
- 'network_type': 'vlan',
- 'physical_network': physical_network
- }
+ 'network_type': 'flat' if network_type is None else network_type,
+ 'physical_network': physical_network,
+ },
}
if segmentation_id:
- seg_id_dit = {'segmentation_id': segmentation_id}
- self.resources[name]["properties"].update(seg_id_dit)
+ self.resources[name]['properties']['segmentation_id'] = segmentation_id
+ if network_type is None:
+ self.resources[name]['properties']['network_type'] = 'vlan'
+ # if port security is not defined then don't add to template:
+ # some deployments don't have port security plugin installed
+ if port_security_enabled is not None:
+ self.resources[name]['properties']['port_security_enabled'] = port_security_enabled
def add_server_group(self, name, policies): # pragma: no cover
"""add to the template a ServerGroup"""
'policies': policies}
}
- def add_subnet(self, name, network, cidr):
- """add to the template a Neutron Subnet"""
+ def add_subnet(self, name, network, cidr, enable_dhcp='true', gateway_ip=None):
+ """add to the template a Neutron Subnet
+ """
log.debug("adding Neutron::Subnet '%s' in network '%s', cidr '%s'",
name, network, cidr)
self.resources[name] = {
'properties': {
'name': name,
'cidr': cidr,
- 'network_id': {'get_resource': network}
+ 'network_id': {'get_resource': network},
+ 'enable_dhcp': enable_dhcp,
}
}
+ if gateway_ip == 'null':
+ self.resources[name]['properties']['gateway_ip'] = None
+ elif gateway_ip is not None:
+ self.resources[name]['properties']['gateway_ip'] = gateway_ip
self._template['outputs'][name] = {
'description': 'subnet %s ID' % name,
}
}
- def add_port(self, name, network_name, subnet_name, sec_group_id=None,
- provider=None):
- """add to the template a named Neutron Port"""
- log.debug("adding Neutron::Port '%s', network:'%s', subnet:'%s', "
- "secgroup:%s", name, network_name, subnet_name, sec_group_id)
+ def add_port(self, name, network_name, subnet_name, vnic_type, sec_group_id=None,
+ provider=None, allowed_address_pairs=None):
+ """add to the template a named Neutron Port
+ """
+ log.debug("adding Neutron::Port '%s', network:'%s', subnet:'%s', vnic_type:'%s', "
+ "secgroup:%s", name, network_name, subnet_name, vnic_type, sec_group_id)
self.resources[name] = {
'type': 'OS::Neutron::Port',
'depends_on': [subnet_name],
'properties': {
'name': name,
+ 'binding:vnic_type': vnic_type,
'fixed_ips': [{'subnet': {'get_resource': subnet_name}}],
'network_id': {'get_resource': network_name},
'replacement_policy': 'AUTO',
self.resources[name]['properties']['security_groups'] = \
[sec_group_id]
+ if allowed_address_pairs:
+ self.resources[name]['properties'][
+ 'allowed_address_pairs'] = allowed_address_pairs
+
self._template['outputs'][name] = {
'description': 'Address for interface %s' % name,
'value': {'get_attr': [name, 'fixed_ips', 0, 'ip_address']}
'type': 'OS::Neutron::SecurityGroup',
'properties': {
'name': name,
- 'description': "Group allowing icmp and upd/tcp on all ports",
+ 'description': "Group allowing IPv4 and IPv6 for icmp and upd/tcp on all ports",
'rules': [
{'remote_ip_prefix': '0.0.0.0/0',
'protocol': 'tcp',
'port_range_min': '1',
'port_range_max': '65535'},
{'remote_ip_prefix': '0.0.0.0/0',
- 'protocol': 'icmp'}
+ 'protocol': 'icmp'},
+ {'remote_ip_prefix': '::/0',
+ 'ethertype': 'IPv6',
+ 'protocol': 'tcp',
+ 'port_range_min': '1',
+ 'port_range_max': '65535'},
+ {'remote_ip_prefix': '::/0',
+ 'ethertype': 'IPv6',
+ 'protocol': 'udp',
+ 'port_range_min': '1',
+ 'port_range_max': '65535'},
+ {'remote_ip_prefix': '::/0',
+ 'ethertype': 'IPv6',
+ 'protocol': 'ipv6-icmp'}
]
}
}
:param: timeout: timeout in seconds for Heat create, default 3600s
:type timeout: int
"""
- log.info("Creating stack '%s'", self.name)
+ log.info("Creating stack '%s' START", self.name)
# create stack early to support cleanup, e.g. ctrl-c while waiting
stack = HeatStack(self.name)
if not block:
self.outputs = stack.outputs = {}
end_time = time.time()
- log.info("Created stack '%s' in %.3e secs",
+ log.info("Creating stack '%s' DONE in %d secs",
self.name, end_time - start_time)
return stack
time_limit = start_time + timeout
for status in iter(self.status, self.HEAT_CREATE_COMPLETE_STATUS):
- log.debug("stack state %s", status)
+ log.debug("Creating stack state: %s", status)
if status == u'CREATE_FAILED':
stack_status_reason = heat_client.stacks.get(self.uuid).stack_status_reason
heat_client.stacks.delete(self.uuid)
end_time = time.time()
outputs = heat_client.stacks.get(self.uuid).outputs
- log.info("Created stack '%s' in %.3e secs",
+ log.info("Creating stack '%s' DONE in %d secs",
self.name, end_time - start_time)
# keep outputs as unicode