Comment 3 for bug 1828112

Revision history for this message
Bo Tran (ministry.nd) wrote :

Nope, that is my wrong remember. But, current i was resolved this problem by:

I don't use security_groups property not in each network. We can still use security_groups like:
type: os.nova.server
version: 1.0
properties:
  name: cirros_server
  flavor: 1
  image: "cirros-0.4.0-x86_64-disk"
  networks:
   - network: private
  metadata:
    test_key: test_value
  security_groups:
    - 46f7acd4-109a-446c-b6b3-325a7f2b8b07
    - 30e334ff-57d6-4c40-bc09-9489f0e3b5b6
  user_data: |
    #!/bin/sh
    echo 'hello, world' > /tmp/test_file

because in code, we create server with security groups is wrong order step.
I here: https://github.com/openstack/senlin/blob/master/senlin/profiles/os/nova/server.py#L868
we maybe change code like:

secgroups = self.properties[self.SECURITY_GROUPS]
if secgroups:
    kwargs['security_groups'] = [{'name': sg} for sg in secgroups]
    port_security_groups = [
        self.network(obj).security_group_find(
            sg).id for sg in secgroups]
else:
    port_security_groups = None

ports = self._create_ports_from_properties(
    obj, networks, 'create', port_security_groups)
kwargs['networks'] = [
    {'port': port['id']} for port in ports]

and in function `_create_ports_from_properties`: https://github.com/openstack/senlin/blob/master/senlin/profiles/os/nova/server.py#L720
we maybe change code to create port with port_security_groups attr. and in this function. we will create a port with security groups.

We add a function _create_port like:

def _create_port(self, obj, net_spec, security_groups=None):
    """Fetch or create a port.

    :param obj: The node object.
    :param net_spec: The parameters to create a port.
    :returns: Created port object and error message.
    """
    port_id = net_spec.get(self.PORT, None)
    if port_id:
        try:
            port = self.network(obj).port_find(port_id)
            return port, None
        except exc.InternalError as ex:
            return None, ex
    port_attr = {
        'network_id': net_spec.get(self.NETWORK),
    }
    fixed_ip = net_spec.get(self.FIXED_IP, None)
    if fixed_ip:
        port_attr['fixed_ips'] = [fixed_ip]
    if security_groups:
        port_attr['security_groups'] = security_groups
    try:
        port = self.network(obj).port_create(**port_attr)
        return port, None
    except exc.InternalError as ex:
        return None, ex

(this function is same _get_port function), and in _create_ports_from_properties function, we will use _create_port function to create a port with sec_groups and return.
def _create_ports_from_properties(self, obj, networks, action_type,
                                  port_security_groups=None):
    """Create or find ports based on networks property.

    :param obj: The node object.
    :param networks: The networks property used for node.
    :param action_type: Either 'create' or 'update'.

    :returns: A list of created port's attributes.
    """
    internal_ports = obj.data.get('internal_ports', [])
    if not networks:
        return []

    for net_spec in networks:
        net = self._validate_network(obj, net_spec, action_type)
        # Create port
        port, ex = self._create_port(
                    obj, net, port_security_groups)
        # Delete created ports before raise error
        if ex:
            d_ex = self._delete_ports(obj, internal_ports)
            if d_ex:
                raise d_ex
            else:
                raise ex
        port_attrs = {
            'id': port.id,
            'network_id': port.network_id,
            'security_group_ids': port.security_group_ids,
            'fixed_ips': port.fixed_ips
        }
        if self.PORT not in net:
            port_attrs.update({'remove': True})
        # Create floating ip
        if 'floating_ip_id' in net or self.FLOATING_NETWORK in net:
            fip, ex = self._get_floating_ip(obj, net, port_attrs['id'])
            if ex:
                d_ex = self._delete_ports(obj, internal_ports)
                if d_ex:
                    raise d_ex
                else:
                    raise ex
            port_attrs['floating'] = {
                'id': fip.id,
                'floating_ip_address': fip.floating_ip_address,
                'floating_network_id': fip.floating_network_id,
            }
            if self.FLOATING_NETWORK in net:
                port_attrs['floating'].update({'remove': True})
        internal_ports.append(port_attrs)
    if internal_ports:
        node_data = obj.data
        node_data.update(internal_ports=internal_ports)
        node_obj.Node.update(self.context, obj.id, {'data': node_data})
    return internal_ports

Tks and sorry with my problem if have.