Beispiel #1
0
    def test_extract_ports_with_ids(self, mock_port, mock_subnet):
        # NOTE: default, in the case, subnets will be extracted.
        fake_port = copy.deepcopy(fake_port_dict)
        mock_port.return_value = fake_port

        fake_subnet = copy.deepcopy(fake_subnet_dict)
        fake_subnet_id = fake_subnet['id']
        fake_subnet_name = fake_subnet['name']
        mock_subnet.return_value = fake_subnet

        fake_subnet_res = resource.Resource(
            fake_subnet_name,
            'OS::Neutron::Subnet',
            fake_subnet_id,
            properties={'network_id': {
                'get_resource': 'network_0'
            }})
        fake_subnet_dep = resource.ResourceDependency(fake_subnet_id,
                                                      fake_subnet_name,
                                                      'subnet_0',
                                                      'OS::Neutron::Subnet')
        self.net_resource = networks.NetworkResource(
            self.context,
            collected_resources={fake_subnet_id: fake_subnet_res},
            collected_dependencies={fake_subnet_id: fake_subnet_dep})

        result = self.net_resource.extract_ports([fake_port['id']])
        self.assertTrue(1 == len(result))
        self.assertTrue(2 == len(self.net_resource.get_collected_resources()))
Beispiel #2
0
 def test_extract_subnets_from_cache(self, mock_subnet_list):
     fake_subnet = copy.deepcopy(fake_subnet_dict)
     fake_subnet_id = fake_subnet['id']
     fake_subnet_name = fake_subnet['name']
     mock_subnet_list.return_value = [fake_subnet]
     fake_subnet_res = resource.Resource(fake_subnet_name,
                                         'OS::Neutron::Subnet',
                                         fake_subnet_id)
     fake_subnet_dep = resource.ResourceDependency(fake_subnet_id,
                                                   fake_subnet_name,
                                                   'subnet_0',
                                                   'OS::Neutron::Subnet')
     self.net_resource = networks.NetworkResource(
         self.context,
         collected_resources={fake_subnet_id: fake_subnet_res},
         collected_dependencies={fake_subnet_id: fake_subnet_dep})
     result = self.net_resource.extract_subnets([])
     self.assertTrue(1 == len(result))
     self.assertEqual(fake_subnet_id, result[0].id)
     collected_res = self.net_resource.get_collected_resources()
     collected_deps = self.net_resource.get_collected_dependencies()
     self.assertTrue(1 == len(collected_res))
     self.assertTrue(1 == len(collected_deps))
     subnet_dep = collected_deps[fake_subnet_id]
     self.assertFalse(len(subnet_dep.dependencies))
Beispiel #3
0
 def test_extract_fips_with_port(self, mock_fip, mock_net, mock_port):
     # NOTE: without router; with secgroup, router interface
     # Here, we will make net_0 and port_0 in cache and without any
     # dependencies, so only net_0, fip, fipAss, port_0 will be extracted
     # at last.
     # ----------------------------------------------------
     # |                                       net_1      |
     # |                                      /    |      |
     # | subnet_0(ext-sb)                    /   subnet_1 |
     # |     |                               \     |      |
     # |     |                                \    |      |
     # |  net_0(ext-net)<---fip<----fipAss--->port_0      |
     # ----------------------------------------------------
     fake_fip = copy.deepcopy(fake_fip_dict)
     fake_fip['floating_network_id'] = ext_net_id
     fake_fip['port_id'] = fake_port_dict['id']
     mock_fip.return_value = fake_fip
     fake_port = copy.deepcopy(fake_port_dict)
     mock_port.return_value = fake_port
     fake_port_id = fake_port['id']
     fake_port_name = fake_port['name']
     fake_port_res = resource.Resource('port_0', 'OS::Neutron::Port',
                                       fake_port_id)
     fake_port_dep = resource.ResourceDependency(fake_port_id,
                                                 fake_port_name, 'port_0',
                                                 'OS::Neutron::Port')
     fake_net = copy.deepcopy(fake_net_dict)
     fake_net['id'] = fake_fip['floating_network_id']
     fake_net_id = fake_net['id']
     mock_net.return_value = fake_net
     fake_net_res = resource.Resource('net_0', 'OS::Neutron::Net',
                                      fake_net_id)
     fake_net_dep = resource.ResourceDependency(fake_net_id,
                                                fake_net_dict['name'],
                                                'net_0', 'OS::Neutron::Net')
     self.net_resource = networks.NetworkResource(self.context,
                                                  collected_resources={
                                                      fake_port_id:
                                                      fake_port_res,
                                                      fake_net_id:
                                                      fake_net_res
                                                  },
                                                  collected_dependencies={
                                                      fake_port_id:
                                                      fake_port_dep,
                                                      fake_net_id:
                                                      fake_net_dep
                                                  })
     result = self.net_resource.extract_floatingips([fake_fip['id']])
     self.assertEqual(1, len(result))
     self.assertEqual(4, len(self.net_resource.get_collected_resources()))
     deps = self.net_resource.get_collected_dependencies()
     net_dep = deps.pop(fake_net_id)
     fip_dep = deps.pop(fake_fip['id'])
     port_dep = deps.pop(fake_port_id)
     fip_ass_dep = deps.values()[0]
     self.assertIn(net_dep.name_in_template, fip_dep.dependencies)
     self.assertIn(fip_dep.name_in_template, fip_ass_dep.dependencies)
     self.assertIn(port_dep.name_in_template, fip_ass_dep.dependencies)
Beispiel #4
0
 def test_extract_ports_from_cache(self, mock_port_list):
     fake_port = copy.deepcopy(fake_port_dict)
     mock_port_list.return_value = [fake_port]
     fake_port_id = fake_port['id']
     fake_port_name = fake_port['name']
     fake_port_des = resource.Resource(fake_port_name, 'OS::Neutron::Port',
                                       fake_port_id)
     fake_port_dep = resource.ResourceDependency(fake_port_id,
                                                 fake_port_name, 'port_0',
                                                 'OS::Neutron::Port')
     self.net_resource = networks.NetworkResource(
         self.context,
         collected_resources={fake_port_id: fake_port_des},
         collected_dependencies={fake_port_id: fake_port_dep})
     result = self.net_resource.extract_ports([])
     self.assertTrue(1 == len(result))
     self.assertTrue(1 == len(self.net_resource.get_collected_resources()))
Beispiel #5
0
 def test_extract_fips_from_cache(self, mock_fip_list):
     fake_fip = copy.deepcopy(fake_fip_dict)
     mock_fip_list.return_value = [fake_fip]
     fake_fip_id = fake_fip['id']
     fake_fip_name = ''
     fake_fip_res = resource.Resource(fake_fip_name,
                                      'OS::Neutron::FloatingIP',
                                      fake_fip_id)
     fake_fip_dep = resource.ResourceDependency(fake_fip_id, fake_fip_name,
                                                'floatingip_0',
                                                'OS::Neutron::FloatingIP')
     self.net_resource = networks.NetworkResource(
         self.context,
         collected_resources={fake_fip_id: fake_fip_res},
         collected_dependencies={fake_fip_id: fake_fip_dep})
     result = self.net_resource.extract_floatingips([])
     self.assertTrue(1 == len(result))
     self.assertTrue(1 == len(self.net_resource.get_collected_resources()))
Beispiel #6
0
    def _update_subnet_and_port(self, context, updated_res, updated_dep,
                                resource_id, subnet_id):

        resource_obj = updated_res[resource_id]
        org_subnet_id = resource_obj.id

        if not uuidutils.is_uuid_like(subnet_id):
            msg = "Subnet id <%s> must be uuid." % subnet_id
            LOG.error(msg)
            raise exception.PlanResourcesUpdateError(message=msg)

        if org_subnet_id == subnet_id:
            LOG.info(
                "Subnet <%s> is the same as original subnet. "
                "Skip updating.", subnet_id)
            return

        # Extracted subnet resource.
        nr = networks.NetworkResource(context)
        subnet_res = nr.extract_subnets([subnet_id])[0]

        # Update subnet info
        subnet_res.name = resource_id
        updated_res[resource_id] = subnet_res

        # Remove fixed ip on all ports corresponding to this subnet.
        # add by liuling
        # need to remove the port_id
        for rid, dep in updated_dep.items():
            if dep.type == "OS::Neutron::Port" and \
                            resource_id in dep.dependencies:
                port_res = updated_res.get(rid)
                if not port_res:
                    continue
                port_res.id = None
                fixed_ips = port_res.properties.get('fixed_ips')

                if not fixed_ips:
                    continue

                for fip in fixed_ips:
                    if fip.get('ip_address') and fip.get('subnet_id') == \
                            {'get_resource': resource_id}:
                        del fip['ip_address']
Beispiel #7
0
    def test_extract_routers_from_cache(self, mock_router_list):
        fake_router = copy.deepcopy(fake_route_dict)
        mock_router_list.return_value = [fake_router]
        fake_router_id = fake_router['id']
        fake_router_name = fake_router['name']
        fake_router_res = resource.Resource(fake_router_name,
                                            'OS::Neutron::Router',
                                            fake_router_id)

        fake_router_dep = resource.ResourceDependency(fake_router_id,
                                                      fake_router_name,
                                                      'router_0',
                                                      'OS::Neutron::Router')
        self.net_resource = networks.NetworkResource(
            self.context,
            collected_resources={fake_router_id: fake_router_res},
            collected_dependencies={fake_router_id: fake_router_dep})
        result = self.net_resource.extract_routers([])
        self.assertTrue(1 == len(result))
        self.assertEqual(fake_router_id, result[0].id)
        self.assertTrue(1 == len(self.net_resource.get_collected_resources()))
        self.assertFalse(
            len(self.net_resource.get_collected_dependencies()
                [fake_router_id].dependencies))
Beispiel #8
0
    def extract_loadbalanceVip(self, vip_id, pool_name):

        # if vip resource exist in collect resource
        vip_col = self._collected_resources.get(vip_id)
        if vip_col:
            return vip_col
        dependences = []
        properties = {}

        # 1. query vip info
        try:
            vip_info = self.neutron_api.get_vip(self.context, vip_id)
        except Exception as e:
            _msg = 'Create LB vip resource error: %s' % e
            LOG.error(_msg)
            raise exception.ResourceExtractFailed(reason=_msg)

        properties['protocol_port'] = vip_info.get('protocol_port')
        properties['session_persistence'] = vip_info.\
            get('session_persistence')
        # properties['protocol'] = vip_info.get('protocol')
        vip_name = vip_info.get('name')
        vip_address = vip_info.get('address')
        vip_admin = vip_info.get('admin_state_up')
        vip_connection = vip_info.get('connection_limit')
        vip_des = vip_info.get('description')
        if vip_name:
            properties['name'] = vip_name

        if vip_address:
            properties['address'] = vip_address

        if vip_admin:
            properties['admin_state_up'] = vip_admin
        if vip_connection:
            properties['connection_limit'] = vip_connection
        if vip_des:
            properties['description'] = vip_des

        properties['pool_id'] = {'get_resource': pool_name}
        dependences.append(pool_name)

        # build subnet resource and build dependence relation
        subnet_id = vip_info.get('subnet_id')

        if subnet_id:
            newtwork_driver = \
                networks.NetworkResource(
                    self.context,
                    collected_resources=self._collected_resources,
                    collected_parameters=self._collected_parameters,
                    collected_dependencies=self._collected_dependencies)
            subnet_ids = []
            subnet_ids.append(subnet_id)
            subnet_res = newtwork_driver.extract_subnets(subnet_ids)
            dependences.append(subnet_res[0].name)
            properties['subnet'] = {'get_resource': subnet_res[0].name}

            # update collect resources and dependences
            self._collected_resources = \
                newtwork_driver.get_collected_resources()

            self._collected_dependencies = \
                newtwork_driver.get_collected_dependencies()

        vip_type = "OS::Neutron::Vip"
        vip_name = 'loadbalanceVip_%d' % self._get_resource_num(vip_type)

        # build listener resource and build dependence relation
        listener_extras = vip_info.get('extra_listeners')
        listener_ids = None
        if listener_extras:
            listener_ids = []
            for listener_extra in listener_extras:
                listener_id = listener_extra.get('id')
                listener_ids.append(listener_id)

        if listener_ids:
            listener_driver = \
                LoadbalanceListener(
                    self.context,
                    collected_resources=self._collected_resources,
                    collected_parameters=self._collected_parameters,
                    collected_dependencies=self._collected_dependencies)
            listener_driver.extract_loadbalanceListeners(
                listener_ids, vip_id, vip_name)

            # update collect resources and dependences
            self._collected_resources = \
                listener_driver.get_collected_resources()

            self._collected_dependencies = \
                listener_driver.get_collected_dependencies()

        vip_res = resource.Resource(vip_name,
                                    vip_type,
                                    vip_id,
                                    properties=properties)

        # remove duplicate dependencies
        dependencies = {}.fromkeys(dependences).keys()
        vip_dep = resource.ResourceDependency(vip_id,
                                              vip_name,
                                              '',
                                              vip_type,
                                              dependencies=dependencies)

        self._collected_resources[vip_id] = vip_res
        self._collected_dependencies[vip_id] = vip_dep

        return vip_res
Beispiel #9
0
    def extract_loadbalancePool(self, pool_id):

        pool_col = self._collected_resources.get(pool_id)

        if pool_col:
            return pool_col

        dependencies = []
        properties = {}

        # 1. query pool info
        try:
            pool = self.neutron_api.show_pool(self.context, pool_id)
        except Exception as e:
            LOG.error('Create LB pool %(pool)s resource error %(error)s', {
                'pool': pool_id,
                'error': e
            })
            _msg = 'Create LB pool resource error: %s' % e
            raise exception.ResourceExtractFailed(_msg)

        pool_info = pool.get('pool')

        properties['lb_method'] = pool_info.get('lb_method')
        properties['protocol'] = pool_info.get('protocol')
        pool_name = pool_info.get('name')
        pool_des = pool_info.get('description')
        pool_admin = pool_info.get('admin_state_up')
        if pool_name:
            properties['name'] = pool_name
        if pool_des:
            properties['description'] = pool_des
        if pool_admin:
            properties['admin_state_up'] = pool_admin

        # properties['provider'] = pool_info.get('provider')
        pool_type = "OS::Neutron::Pool"
        pool_name = 'loadbalancePool_%d' % self._get_resource_num(pool_type)

        # 2. build vip of pool and build dependence relation
        vip_id = pool_info.get('vip_id')
        if vip_id:
            vip_driver = \
                LoadbalanceVip(
                    self.context,
                    collected_resources=self._collected_resources,
                    collected_parameters=self._collected_parameters,
                    collected_dependencies=self._collected_dependencies)
            vip_res = vip_driver.extract_loadbalanceVip(vip_id, pool_name)
            properties['vip'] = {'get_resource': vip_res.name}
            # vip resource in lb resource list
            self._collected_resources = vip_driver.get_collected_resources()
            self._collected_dependencies = \
                vip_driver.get_collected_dependencies()

        subnet_id = pool_info.get('subnet_id')

        if subnet_id:
            # 3. build subnet resource and build dependence relation
            newtwork_driver = \
                networks.NetworkResource(
                    self.context,
                    collected_resources=self._collected_resources,
                    collected_parameters=self._collected_parameters,
                    collected_dependencies=self._collected_dependencies)
            subnet_ids = []
            subnet_ids.append(subnet_id)
            subnet_res = newtwork_driver.extract_subnets(subnet_ids)
            dependencies.append(subnet_res[0].name)
            properties['subnet'] = {'get_resource': subnet_res[0].name}

            # 3.2 add subnet resource in lb resource list
            self._collected_resources = \
                newtwork_driver.get_collected_resources()
            self._collected_dependencies = \
                newtwork_driver.get_collected_dependencies()

        # 4. build members of pool and build dependence relation
        member_ids = pool_info.get('members')

        if member_ids:
            lb_member_driver = \
                LoadbalanceMember(
                    self.context,
                    collected_resources=self._collected_resources,
                    collected_parameters=self._collected_parameters,
                    collected_dependencies=self._collected_dependencies)
            lb_member_driver.extract_loadbalanceMembers(member_ids, pool_name)

            # update collect resource
            self._collected_resources = \
                lb_member_driver.get_collected_resources()
            self._collected_dependencies = \
                lb_member_driver.get_collected_dependencies()

        # 4. query health monitor of pool and build dependence relation
        healthmonitor_ids = pool_info.get('health_monitors')

        if healthmonitor_ids:
            lb_healthmonitor_driver = \
                LoadbalanceHealthmonitor(
                    self.context,
                    collected_resources=self._collected_resources,
                    collected_parameters=self._collected_parameters,
                    collected_dependencies=self._collected_dependencies)
            ids = healthmonitor_ids
            h = lb_healthmonitor_driver.extract_loadbalanceHealthmonitors(ids)

            # update collect resource
            self._collected_resources = \
                lb_healthmonitor_driver.get_collected_resources()
            self._collected_dependencies = \
                lb_healthmonitor_driver.get_collected_dependencies()

            # add all healthmonitor to pool dependences
            monitors = []
            for res in h:
                dependencies.append(res.name)
                monitors.append({'get_resource': res.name})

            properties['monitors'] = monitors

        pool_type = "OS::Neutron::Pool"
        pool_name = 'loadbalancePool_%d' % self._get_resource_num(pool_type)

        pool_res = resource.Resource(pool_name,
                                     pool_type,
                                     pool_id,
                                     properties=properties)

        # remove duplicate dependencies
        dependencies = {}.fromkeys(dependencies).keys()
        pool_dep = resource.ResourceDependency(pool_id,
                                               pool_name,
                                               '',
                                               pool_type,
                                               dependencies=dependencies)

        self._collected_resources[pool_id] = pool_res
        self._collected_dependencies[pool_id] = pool_dep
Beispiel #10
0
    def _update_network_resource(self,
                                 context,
                                 updated_res,
                                 updated_dep,
                                 resource,
                                 except_subnet=None):

        LOG.debug("Update network %s resource with %s.",
                  resource['resource_id'], resource)

        properties = resource
        new_res_id = properties.pop('id', None)
        resource_id = properties.pop('resource_id', None)
        properties.pop('resource_type', None)

        org_net = updated_res[resource_id]
        org_net_id = org_net.id

        if new_res_id and not uuidutils.is_uuid_like(new_res_id):
            msg = "Network id <%s> must be uuid." % new_res_id
            LOG.error(msg)
            raise exception.PlanResourcesUpdateError(message=msg)

        if new_res_id and new_res_id != org_net_id:
            # Make sure the number of subnets larger than one.
            net = self.neutron_api.get_network(context, new_res_id)
            subnets = net.get('subnets', [])
            if not subnets:
                msg = "No subnets found in network %s." % new_res_id
                LOG.error(msg)
                raise exception.PlanResourcesUpdateError(message=msg)

            # Validate whether network exists on a server.
            self._validate_server_network_duplication(updated_res, resource_id,
                                                      new_res_id)

            # Extracted network resource.
            nr = networks.NetworkResource(context)
            net_res = nr.extract_nets([new_res_id])[0]

            # Update network resource.
            net_res.name = resource_id
            updated_res[resource_id] = net_res

            # Update corresponding subnet resources.
            for rid, dep in updated_dep.items():
                if dep.type == "OS::Neutron::Subnet" and resource_id in \
                        dep.dependencies:
                    subnet_res = updated_res.get(rid)

                    if not subnet_res or except_subnet == subnet_res.name:
                        continue

                    # Randomly choose a subnet.
                    random_index = random.randint(0, len(subnets) - 1)
                    random_sub_id = subnets[random_index]

                    self._update_subnet_and_port(context, updated_res,
                                                 updated_dep, rid,
                                                 random_sub_id)
        else:
            # need to modify
            LOG.info(
                "Network <%s> is the same as original network. "
                "updating the org_net info", org_net_id)
            self._update_org_net_info(context, updated_res, updated_dep,
                                      resource_id)

            if properties.get('value_specs') and \
               not properties.get('value_specs').\
                       get('provider:segmentation_id'):
                if updated_res[resource_id].properties.\
                        get('value_specs').get('provider:segmentation_id'):
                    updated_res[resource_id].properties.\
                        get('value_specs').pop('provider:segmentation_id')
            elif not properties.get('value_specs'):
                if updated_res[resource_id].properties.\
                        get('value_specs').get('provider:segmentation_id'):
                    updated_res[resource_id].properties.\
                        get('value_specs').pop('provider:segmentation_id')

        # Update other fields.
        for k, v in properties.items():
            updated_res[resource_id].properties[k] = v
Beispiel #11
0
    def _update_port_resource(self, context, updated_res, resource):

        LOG.debug("Update port %s resource with %s.", resource['resource_id'],
                  resource)

        properties = resource
        resource_id = properties.pop('resource_id', None)
        resource_obj = updated_res[resource_id]
        properties.pop('resource_type', None)
        # Only fixed_ips can be updated.
        ips_to_update = properties.pop('fixed_ips')
        if not ips_to_update:
            msg = "Only 'fixed_ips' property is allowed be updated on a port."
            LOG.error(msg)
            raise exception.PlanResourcesUpdateError(message=msg)

        # Validate the number of ips on a port
        original_ips = resource_obj.properties.get('fixed_ips')
        if len(original_ips) != len(ips_to_update):
            msg = "The number of fixed ips must remain the same."
            LOG.error(msg)
            raise exception.PlanResourcesUpdateError(message=msg)

        def _get_pools(subnet_id):
            """Get subnet allocation_pools by neutron api."""
            try:
                subnet = self.neutron_api.get_subnet(context, subnet_id)
                return subnet.get('allocation_pools', [])
            except Exception as e:
                msg = "Subnet <%s> not found. %s" % (subnet_id, unicode(e))
                LOG.error(msg)
                raise exception.PlanResourcesUpdateError(message=msg)

        # Validate whether ip address matches the subnet.
        for item in ips_to_update:
            ip_address = item.get('ip_address')
            subnet_id = item.get('subnet_id')

            LOG.debug("Check fixed ip: %s", item)

            # subnet_id is required, ip_address is optional
            if not subnet_id:
                msg = "subnet_id must be provided when updating fixed_ips."
                LOG.error(msg)
                raise exception.PlanResourcesUpdateError(message=msg)

            # If ip_address is provided, validate it.
            if ip_address:
                LOG.debug("Validate ip address %s.", ip_address)
                # Get subnet range from exist subnet resource.
                allocation_pools = []
                if isinstance(subnet_id, dict) and len(subnet_id) == 1:
                    # Only support 'get_param' and 'get_resource'
                    if subnet_id.get('get_param'):
                        sub_param_id = subnet_id['get_param']
                        if isinstance(sub_param_id, six.string_types):
                            subnet_id = resource_obj.\
                                parameters .\
                                get(sub_param_id, {}).get('default')
                            LOG.debug(
                                "Get subnet id <%s> "
                                "from parameter <%s>.", subnet_id,
                                sub_param_id)
                            if subnet_id:
                                allocation_pools = _get_pools(subnet_id)
                            else:
                                msg = "%s parameter not found." % sub_param_id
                                LOG.error(msg)
                                raise exception.\
                                    PlanResourcesUpdateError(message=msg)
                    elif subnet_id.get('get_resource'):
                        sub_res_id = subnet_id['get_resource']
                        if isinstance(sub_res_id, six.string_types) \
                            and updated_res.get(sub_res_id):
                            allocation_pools = updated_res[sub_res_id].\
                                properties.get('allocation_pools')
                        else:
                            msg = "%s resource not found." % sub_res_id
                            LOG.error(msg)
                            raise exception.\
                                PlanResourcesUpdateError(message=msg)
                elif isinstance(subnet_id, six.string_types):
                    if uuidutils.is_uuid_like(subnet_id):
                        allocation_pools = _get_pools(subnet_id)
                    else:
                        msg = "Subnet id must be uuid."
                        LOG.error(msg)
                        raise exception.PlanResourcesUpdateError(message=msg)

                if not allocation_pools:
                    msg = "Can not found subnet allocation_pools information."
                    LOG.error(msg)
                    raise exception.PlanResourcesUpdateError(message=msg)

                # Validate whether ip address in ip range.
                ip_valid = False
                for pool in allocation_pools:
                    start = pool.get('start')
                    end = pool.get('end')
                    if isinstance(start, six.string_types) \
                        and isinstance(end, six.string_types) \
                        and netaddr.IPAddress(ip_address) in \
                                    netaddr.IPRange(start, end):
                        ip_valid = True

                if not ip_valid:
                    msg = ("Ip address doesn't match allocation_pools %s." %
                           allocation_pools)
                    LOG.error(msg)
                    raise exception.PlanResourcesUpdateError(message=msg)

            # Begin to update.
            ip_index = ips_to_update.index(item)
            original_ip_item = original_ips[ip_index]
            original_subnet = original_ip_item.get('subnet_id')

            # Update ip_address
            if ip_address:
                original_ips[ip_index]['ip_address'] = ip_address

            # If subnets are the same, only update ip_address if provided.
            if original_subnet == subnet_id:
                pass
            # If subnet_id is from other exist resource, replace directly.
            elif isinstance(subnet_id, dict) and len(subnet_id) == 1 \
                            and subnet_id.get('get_resource'):
                sub_res_id = subnet_id['get_resource']
                if isinstance(sub_res_id, six.string_types) \
                              and updated_res.get(sub_res_id):
                    original_ips[ip_index]['subnet_id'] = subnet_id
                    LOG.debug("Update ip_address property %s.",
                              original_ips[ip_index])
                else:
                    msg = "%s resource not found." % sub_res_id
                    LOG.error(msg)
                    raise exception.PlanResourcesUpdateError(message=msg)
            # If subnet_id is a uuid, get resource by neutron driver.
            # If this subnet has been extracted, it won't be extracted again.
            elif uuidutils.is_uuid_like(subnet_id):
                # Replace the keys by actual_id
                LOG.debug("Extract subnet <%s> resource.", subnet_id)

                # Extracted subnet resource.
                self._resource_id_to_actual_id(updated_res)
                nr = networks.NetworkResource(context,
                                              collected_resources=updated_res)
                subnet_res = nr.extract_subnets([subnet_id])[0]

                # Restore the keys
                self._actual_id_to_resource_id(updated_res)
                original_ips[ip_index]['subnet_id'] = {
                    'get_resource': subnet_res.name
                }

                LOG.debug("Update ip_address property %s.",
                          original_ips[ip_index])
            else:
                msg = "subnet_id (%s) is invalid." % subnet_id
                LOG.error(msg)
                raise exception.PlanResourcesUpdateError(message=msg)

        # we need to create new port
        resource_obj.id = None
        # Update other fields.
        for k, v in properties.items():
            updated_res[resource_id].properties[k] = v
Beispiel #12
0
    def _edit_plan_resource(self, context, plan, updated_res, updated_dep,
                            resource, resources_list):
        resource.pop('action', None)
        properties = copy.deepcopy(resource)

        resource_id = properties.pop('resource_id', None)
        resource_obj = updated_res.get(resource_id)
        new_res_id = properties.pop('id', None)
        properties.pop('resource_type', None)
        copy_data = properties.pop('copy_data', None)
        if not resource_id or not resource_obj:
            msg = "%s resource not found." % resource_id
            LOG.error(msg)
            raise exception.PlanResourcesUpdateError(message=msg)

        # Validate properties
        res_type = resource_obj.type
        heat_api = heat.API()

        try:
            uncheck_type = ['OS::Neutron::Vip']
            if res_type not in uncheck_type:
                heat_res_type = heat_api.get_resource_type(context, res_type)
                res_properties = heat_res_type.get('properties')
                LOG.debug("Validate the properties to be updated.")
                self._simple_validate_update_properties(
                    properties, res_properties)
        except exception.PlanResourcesUpdateError:
            raise
        except Exception as e:
            LOG.error(unicode(e))
            raise exception.PlanResourcesUpdateError(message=unicode(e))

        def _update_simple_fields(resource_id, properties):
            for k, v in properties.items():
                updated_res[resource_id].properties[k] = v

        simple_handle_type = ['OS::Neutron::Vip']
        # Update resource
        if 'OS::Nova::Server' == res_type:
            allowed_fields = ['user_data', 'metadata']
            for key, value in properties.items():
                if key in allowed_fields:
                    resource_obj.properties[key] = value
                else:
                    msg = ("'%s' field of server is not "
                           "allowed to update." % key)
                    LOG.error(msg)
                    raise exception.PlanResourcesUpdateError(message=msg)
        elif res_type in ('OS::Nova::KeyPair'):
            public_key = properties.get('public_key', None)
            if not new_res_id and not public_key:
                msg = ("'id' or 'public_key' must be provided "
                       "when updating keypair resource.")
                LOG.error(msg)
                raise exception.PlanResourcesUpdateError(message=msg)

            if new_res_id and new_res_id != resource_obj.id:
                ir = instances.InstanceResource(context)
                kp_res = ir.extract_keypairs([new_res_id])[0]
                kp_res.name = resource_id
                updated_res[resource_id] = kp_res
            else:
                resource_obj.id = None

            # Update other fields.
            _update_simple_fields(resource_id, properties)

        elif 'OS::Neutron::SecurityGroup' == res_type:
            rules = properties.get('rules', None)

            if not new_res_id and not rules:
                msg = ("'id' or 'rules' must be provided "
                       "when updating security group resource.")
                LOG.error(msg)
                raise exception.PlanResourcesUpdateError(message=msg)

            if new_res_id and new_res_id != resource_obj.id:
                nr = secgroup.SecGroup(context)
                sec_res = nr.extract_secgroups([new_res_id])[0]
                sec_res.name = resource_id
                updated_res[resource_id] = sec_res
            else:
                resource_obj.id = None
            # Update other fields.
            _update_simple_fields(resource_id, properties)

        elif 'OS::Neutron::FloatingIP' == res_type:
            if not new_res_id:
                msg = "'id' must be provided when " \
                      "updating floating ip resource."
                LOG.error(msg)
                raise exception.PlanResourcesUpdateError(message=msg)

            if new_res_id != resource_obj.id:

                floatingip = self.neutron_api.get_floatingip(
                    context, new_res_id)
                if floatingip.get('port_id'):
                    msg = "FloatingIp <%s> is in use."
                    LOG.error(msg)
                    raise exception.PlanResourcesUpdateError(message=msg)

                # Extracted floatingip resource.
                self._resource_id_to_actual_id(updated_res)
                nr = networks.NetworkResource(context,
                                              collected_resources=updated_res)
                floatingip_res = nr.extract_floatingips([new_res_id])[0]
                floatingip_res.name = resource_id

                # Reserve port_id
                port_id = resource_obj.properties.get('port_id')
                if port_id:
                    floatingip_res.properties['port_id'] = port_id

                # Remove original floatingip resource
                updated_res.pop(resource_obj.id, None)
                self._actual_id_to_resource_id(updated_res)
            else:
                resource_obj.id = None
            # Update other fields.
            _update_simple_fields(resource_id, properties)

        elif 'OS::Neutron::Port' == res_type:
            self._update_port_resource(context, updated_res, resource)
        elif 'OS::Neutron::Net' == res_type:
            self._update_network_resource(context, updated_res, updated_dep,
                                          resource)
        elif 'OS::Neutron::Subnet' == res_type:
            self._update_subnet_resource(context, updated_res, updated_dep,
                                         resource, resources_list)
        elif res_type in simple_handle_type:
            _update_simple_fields(resource_id, properties)
        elif 'OS::Cinder::Volume' == res_type:
            org_volume_id = resource_obj.id
            org_dependices = updated_dep.get(resource_id).dependencies
            if new_res_id and new_res_id != org_volume_id:
                self._resource_id_to_actual_id(updated_res)
                vr = volumes.Volume(context, updated_res)
                volume_res = vr.extract_volume(new_res_id)
                volume_res.name = resource_id
                volume_res.extra_properties['exist'] = 'true'
                # openstackid:object
                updated_res = vr.get_collected_resources()
                updated_res.pop(org_volume_id, None)
                self._actual_id_to_resource_id(updated_res)
                plan.updated_resources = updated_res
                plan.rebuild_dependencies()
                new_updated_dep = copy.deepcopy(plan.updated_dependencies)
                if org_dependices:
                    self._remove_org_depends(org_dependices, new_updated_dep,
                                             updated_res)
            if copy_data is not None:
                resource_obj.extra_properties['copy_data'] = copy_data
            # Update other fields.
            _update_simple_fields(resource_id, properties)
        elif 'OS::Cinder::VolumeType' == res_type:
            org_volume_type_id = resource_obj.id
            org_dependices = updated_dep.get(resource_id).dependencies
            if new_res_id != org_volume_type_id:
                self._resource_id_to_actual_id(updated_res)
                vtr = volumes.VolumeType(context, updated_res)
                vt_res = vtr.extract_volume_type(new_res_id)
                vt_res.name = resource_id
                updated_res = vtr.get_collected_resources()
                updated_res.pop(org_volume_type_id, None)
                self._actual_id_to_resource_id(updated_res)
                plan.updated_resources = updated_res
                plan.rebuild_dependencies()
                new_updated_dep = copy.deepcopy(plan.updated_dependencies)
                if org_dependices:
                    self._remove_org_depends(org_dependices, new_updated_dep,
                                             updated_res)
        else:
            msg = "%s resource is unsupported to update." % res_type
            LOG.error(msg)
            raise exception.PlanResourcesUpdateError(message=msg)
Beispiel #13
0
    def extract_floatingips(self,
                            floatingip_ids,
                            parent_name=None,
                            parent_resources=None):

        # 1. get floating ips info
        floatingip_objs = []
        floatingipResources = []

        if not floatingip_ids:
            LOG.debug('Extract resources of floating ips.')
            floatingip_list = self.neutron_api.floatingip_list(self.context)
            floatingip_objs = filter(self._tenant_filter, floatingip_list)

        else:
            LOG.debug('Extract resources of floating ips: %s', floatingip_ids)
            # remove duplicate floatingips
            floatingip_ids = {}.fromkeys(floatingip_ids).keys()
            for floatingip_id in floatingip_ids:
                try:
                    floatingip = self.neutron_api.get_floatingip(
                        self.context, floatingip_id)
                    floatingip_objs.append(floatingip)
                except Exception as e:
                    msg = "FloatingIp resource <%s> could not be found. %s" \
                            % (floatingip_id, unicode(e))
                    LOG.error(msg)
                    raise exception.ResourceNotFound(message=msg)

        for floatingip in floatingip_objs:
            floatingip_id = floatingip.get('id')
            floatingip_res = self._collected_resources.get(floatingip_id)
            if floatingip_res:
                floatingipResources.append(floatingip_res)
                continue

            properties = {}
            dependencies = []

            floating_network_id = floatingip.get('floating_network_id')
            floating_ip_address = floatingip.get('floating_ip_address')

            if not floating_network_id or not floating_ip_address:
                msg = "FloatingIp information is abnormal. \
                      'floating_network_id' or 'floating_ip_address' is None"

                LOG.error(msg)
                raise exception.ResourceAttributesException(message=msg)

            # 2.get network and subnetwork for floating ip
            col_res = self._collected_resources
            cold_eps = self._collected_dependencies
            network_cls = \
                networks.NetworkResource(self.context,
                                         collected_resources=col_res,
                                         collected_dependencies=cold_eps)

            net_res =  \
                network_cls.extract_nets([floating_network_id],
                                         with_subnets=True,
                                         parent_name=parent_name,
                                         parent_resources=parent_resources)

            # refresh collected resource in order
            # to add network and subnet resource
            self._collected_resources = \
                network_cls.get_collected_resources()
            self._collected_dependencies = \
                network_cls.get_collected_dependencies()

            properties['floating_network_id'] = \
                {'get_resource': net_res[0].name}

            resource_type = "OS::Neutron::FloatingIP"
            resource_name = 'floatingip_%d' % \
                self._get_resource_num(resource_type)
            if parent_name and floatingip_id in parent_resources:
                resource_name = parent_name + '.' + resource_name
            floatingip_res = resource.Resource(resource_name,
                                               resource_type,
                                               floatingip_id,
                                               properties=properties)

            # remove duplicate dependencies
            dependencies = {}.fromkeys(dependencies).keys()
            floatingip_dep = \
                resource.ResourceDependency(floatingip_id, resource_name,
                                            '',
                                            resource_type)
            dep_res_name = net_res[0].properties.get('name', '')
            floatingip_dep.add_dependency(net_res[0].id, dep_res_name,
                                          net_res[0].name, net_res[0].type)

            self._collected_resources[floatingip_id] = floatingip_res
            self._collected_dependencies[floatingip_id] = floatingip_dep
            floatingipResources.append(floatingip_res)

        if floatingip_ids and not floatingipResources:
            msg = "FloatingIp resource extracted failed, \
                    can't find the floatingip with id of %s." % floatingip_ids
            LOG.error(msg)
            raise exception.ResourceNotFound(message=msg)

        return floatingipResources
Beispiel #14
0
 def setUp(self):
     super(NetworkResourceTestCase, self).setUp()
     self.context = context.RequestContext(fake_object.fake_user_id,
                                           fake_object.fake_project_id,
                                           is_admin=False)
     self.net_resource = networks.NetworkResource(self.context)