def create(neutron_client, args, **kwargs): if use_external_resource(ctx, neutron_client, SUBNET_OPENSTACK_TYPE): try: net_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, True) if net_id: subnet_id = get_openstack_id(ctx) if neutron_client.show_subnet( subnet_id)[SUBNET_OPENSTACK_TYPE][NETWORK_ID] \ != net_id: raise NonRecoverableError( 'Expected external resources subnet {0} and network' ' {1} to be connected'.format(subnet_id, net_id)) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise net_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) subnet = create_object_dict(ctx, SUBNET_OPENSTACK_TYPE, args, {NETWORK_ID: net_id}) s = neutron_client.create_subnet( {SUBNET_OPENSTACK_TYPE: subnet})[SUBNET_OPENSTACK_TYPE] set_neutron_runtime_properties(ctx, s, SUBNET_OPENSTACK_TYPE)
def test_get_single_id_two_found_if_exists_true(self): ctx = self._make_instances([0, 1]) try: get_openstack_id_of_single_connected_node_by_openstack_type(ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) except NonRecoverableError as e: self.assertIn(NETWORK_OPENSTACK_TYPE, e.message) else: self.fail()
def test_get_single_id_two_found_if_exists_true(self): ctx = self._make_instances([0, 1]) try: get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) except NonRecoverableError as e: self.assertIn(NETWORK_OPENSTACK_TYPE, e.message) else: self.fail()
def create(neutron_client, args, **kwargs): ext_port = use_external_resource(ctx, neutron_client, PORT_OPENSTACK_TYPE) if ext_port: try: net_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, True) if net_id: port_id = ctx.instance.runtime_properties[ OPENSTACK_ID_PROPERTY] if neutron_client.show_port( port_id)['port']['network_id'] != net_id: raise NonRecoverableError( 'Expected external resources port {0} and network {1} ' 'to be connected'.format(port_id, net_id)) ctx.instance.runtime_properties[FIXED_IP_ADDRESS_PROPERTY] = \ _get_fixed_ip(ext_port) ctx.instance.runtime_properties[MAC_ADDRESS_PROPERTY] = \ ext_port['mac_address'] return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise net_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port = { 'name': get_resource_id(ctx, PORT_OPENSTACK_TYPE), 'network_id': net_id, 'security_groups': [], } _handle_fixed_ips(port) port.update(ctx.node.properties['port'], **args) transform_resource_name(ctx, port) p = neutron_client.create_port({'port': port})['port'] ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = p['id'] ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] =\ PORT_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = p['name'] ctx.instance.runtime_properties[FIXED_IP_ADDRESS_PROPERTY] = \ _get_fixed_ip(p) ctx.instance.runtime_properties[MAC_ADDRESS_PROPERTY] = p['mac_address']
def create(neutron_client, args, **kwargs): if use_external_resource(ctx, neutron_client, SUBNET_OPENSTACK_TYPE): try: net_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, True) if net_id: subnet_id = \ ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] if neutron_client.show_subnet( subnet_id)['subnet']['network_id'] != net_id: raise NonRecoverableError( 'Expected external resources subnet {0} and network' ' {1} to be connected'.format(subnet_id, net_id)) subnet_id = \ ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] subnet = {} subnet.update(ctx.node.properties['subnet'], **args) for host_route in subnet['host_routes']: if not 'nexthop' in host_route.keys(): host_route['nexthop'] = get_relationships_host_ip() neutron_client.update_subnet( subnet_id, {'subnet': subnet}) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise net_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) subnet = { 'name': get_resource_id(ctx, SUBNET_OPENSTACK_TYPE), 'network_id': net_id, } subnet.update(ctx.node.properties['subnet'], **args) transform_resource_name(ctx, subnet) s = neutron_client.create_subnet({'subnet': subnet})['subnet'] ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = s['id'] ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SUBNET_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = subnet['name']
def create(neutron_client, args, **kwargs): ext_port = use_external_resource(ctx, neutron_client, PORT_OPENSTACK_TYPE) if ext_port: try: net_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, True) if net_id: port_id = get_openstack_id(ctx) if neutron_client.show_port( port_id)[PORT_OPENSTACK_TYPE]['network_id'] != net_id: raise NonRecoverableError( 'Expected external resources port {0} and network {1} ' 'to be connected'.format(port_id, net_id)) ctx.instance.runtime_properties[FIXED_IP_ADDRESS_PROPERTY] = \ _get_fixed_ip(ext_port) ctx.instance.runtime_properties[MAC_ADDRESS_PROPERTY] = \ ext_port['mac_address'] return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise net_id = ctx.node.properties.get(PORT_OPENSTACK_TYPE, {}).get('network_id') if not net_id: net_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port = create_object_dict(ctx, PORT_OPENSTACK_TYPE, args, {'network_id': net_id}) _handle_fixed_ips(port, neutron_client) _handle_security_groups(port) p = neutron_client.create_port({PORT_OPENSTACK_TYPE: port})[PORT_OPENSTACK_TYPE] set_neutron_runtime_properties(ctx, p, PORT_OPENSTACK_TYPE) ctx.instance.runtime_properties[FIXED_IP_ADDRESS_PROPERTY] = \ _get_fixed_ip(p) ctx.instance.runtime_properties[MAC_ADDRESS_PROPERTY] = p['mac_address']
def create(neutron_client, **kwargs): sgr = _process_rule(ctx.properties['security_group_rule'], neutron_client) sg_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, SECURITY_GROUP_OPENSTACK_TYPE) sgr['security_group_id'] = sg_id rule_id = neutron_client.create_security_group_rule( {'security_group_rule': sgr})['security_group_rule']['id'] ctx.runtime_properties[OPENSTACK_ID_PROPERTY] = rule_id
def create(neutron_client, args, **kwargs): if use_external_resource(ctx, neutron_client, SUBNET_OPENSTACK_TYPE): try: net_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, True) if net_id: subnet_id = \ ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] if neutron_client.show_subnet( subnet_id)['subnet']['network_id'] != net_id: raise NonRecoverableError( 'Expected external resources subnet {0} and network' ' {1} to be connected'.format(subnet_id, net_id)) subnet_id = \ ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] subnet = {} subnet.update(ctx.node.properties['subnet'], **args) for host_route in subnet['host_routes']: if not 'nexthop' in host_route.keys(): host_route['nexthop'] = get_relationships_host_ip() neutron_client.update_subnet(subnet_id, {'subnet': subnet}) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise net_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) subnet = { 'name': get_resource_id(ctx, SUBNET_OPENSTACK_TYPE), 'network_id': net_id, } subnet.update(ctx.node.properties['subnet'], **args) transform_resource_name(ctx, subnet) s = neutron_client.create_subnet({'subnet': subnet})['subnet'] ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = s['id'] ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SUBNET_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = subnet['name']
def create(neutron_client, **kwargs): net_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) subnet = { 'name': ctx.node_id, 'network_id': net_id, } subnet.update(ctx.properties['subnet']) s = neutron_client.create_subnet({'subnet': subnet})['subnet'] ctx.runtime_properties[OPENSTACK_ID_PROPERTY] = s['id']
def create(neutron_client, **kwargs): net_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port = { 'name': ctx.node_id, 'network_id': net_id, 'security_groups': [], } port.update(ctx.properties['port']) transform_resource_name(ctx, port) p = neutron_client.create_port({'port': port})['port'] ctx.runtime_properties[OPENSTACK_ID_PROPERTY] = p['id']
def create(neutron_client, args, **kwargs): if use_external_floatingip(neutron_client, 'floating_ip_address', lambda ext_fip: ext_fip['floating_ip_address']): return floatingip = { # No defaults } floatingip.update(ctx.node.properties[FLOATINGIP_OPENSTACK_TYPE], **args) network_from_rel = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, True) if 'floating_network_id' in floatingip: ctx.logger.debug('Using floating ip network {0}.'.format( floatingip['floating_network_id'])) elif 'floating_network_name' in floatingip: floatingip['floating_network_id'] = neutron_client.cosmo_get_named( 'network', floatingip['floating_network_name'])['id'] ctx.logger.debug( 'Using floating ip network {0} from name {1} provided.'.format( floatingip['floating_network_id'], floatingip['floating_network_name'])) del floatingip['floating_network_name'] elif network_from_rel: floatingip['floating_network_id'] = network_from_rel ctx.logger.debug( 'Using floating ip network {0} from relationship.'.format( floatingip['floating_network_id'])) else: provider_context = provider(ctx) ext_network = provider_context.ext_network if ext_network: floatingip['floating_network_id'] = ext_network['id'] ctx.logger.debug( 'Using floating ip network {0} from provider context.'.format( floatingip['floating_network_id'])) else: raise NonRecoverableError( FLOATING_NETWORK_ERROR_MSG.format(None, None)) fip = neutron_client.create_floatingip( {FLOATINGIP_OPENSTACK_TYPE: floatingip})[FLOATINGIP_OPENSTACK_TYPE] set_floatingip_runtime_properties(fip['id'], fip['floating_ip_address']) ctx.logger.info('Floating IP creation response: {0}'.format(fip))
def _handle_fixed_ips(port): fixed_ips_element = {} # checking for fixed ip property if ctx.node.properties['fixed_ip']: fixed_ips_element['ip_address'] = ctx.node.properties['fixed_ip'] # checking for a connected subnet subnet_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, SUBNET_OPENSTACK_TYPE, if_exists=True) if subnet_id: fixed_ips_element['subnet_id'] = subnet_id # applying fixed ip parameter, if available if fixed_ips_element: port['fixed_ips'] = [fixed_ips_element]
def _validate_external_server_keypair(nova_client): keypair_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, KEYPAIR_OPENSTACK_TYPE, True) if not keypair_id: return keypair_instance_id = \ [node_instance_id for node_instance_id, runtime_props in ctx.capabilities.get_all().iteritems() if runtime_props.get(OPENSTACK_ID_PROPERTY) == keypair_id][0] keypair_node_properties = _get_properties_by_node_instance_id( keypair_instance_id) if not is_external_resource_by_properties(keypair_node_properties): raise NonRecoverableError( "Can't connect a new keypair node to a server node " "with '{0}'=True".format(USE_EXTERNAL_RESOURCE_PROPERTY)) server = get_server_by_context(nova_client) if keypair_id == _get_keypair_name_by_id(nova_client, server.key_name): return raise NonRecoverableError( "Expected external resources server {0} and keypair {1} to be " "connected".format(server.id, keypair_id))
def _handle_fixed_ips(port): fixed_ips_element = {} # checking for fixed ip property if ctx.node.properties['fixed_ip']: fixed_ips_element['ip_address'] = ctx.node.properties['fixed_ip'] # checking for a connected subnet subnet_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, SUBNET_OPENSTACK_TYPE, if_exists=True) if subnet_id: fixed_ips_element['subnet_id'] = subnet_id fixed_ips = port.get('fixed_ips', [] if not fixed_ips_element else [fixed_ips_element]) addresses = [ip.get('ip_address') for ip in fixed_ips] subnets = [net.get('subnet_id') for net in fixed_ips] # applying fixed ip parameter, if available if fixed_ips_element and not \ (fixed_ips_element.get('ip_address') in addresses or fixed_ips_element.get('subnet_id') in subnets): fixed_ips.append(fixed_ips_element) if fixed_ips: port['fixed_ips'] = fixed_ips
def test_get_single_id(self): ctx = self._make_instances(["the node id"]) found_id = get_openstack_id_of_single_connected_node_by_openstack_type(ctx, NETWORK_OPENSTACK_TYPE) self.assertEqual("the node id", found_id)
def test_get_single_id_if_exists_none_found(self): ctx = self._make_instances([]) found = get_openstack_id_of_single_connected_node_by_openstack_type(ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) self.assertIsNone(found)
def create(nova_client, neutron_client, args, **kwargs): """ Creates a server. Exposes the parameters mentioned in http://docs.openstack.org/developer/python-novaclient/api/novaclient.v1_1 .servers.html#novaclient.v1_1.servers.ServerManager.create """ external_server = use_external_resource(ctx, nova_client, SERVER_OPENSTACK_TYPE) if external_server: _set_network_and_ip_runtime_properties(external_server) if ctx._local: return else: network_ids = \ get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, PORT_OPENSTACK_TYPE) try: _validate_external_server_nics( neutron_client, network_ids, port_ids ) _validate_external_server_keypair(nova_client) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise provider_context = provider(ctx) def rename(name): return transform_resource_name(ctx, name) server = { 'name': get_resource_id(ctx, SERVER_OPENSTACK_TYPE), } server.update(copy.deepcopy(ctx.node.properties['server'])) server.update(copy.deepcopy(args)) _handle_boot_volume(server, ctx) handle_image_from_relationship(server, 'image', ctx) if 'meta' not in server: server['meta'] = dict() transform_resource_name(ctx, server) ctx.logger.debug( "server.create() server before transformations: {0}".format(server)) if ('block_device_mapping' in server or 'block_device_mapping_v2' in server) \ and 'image' not in server: # python-novaclient requires an image field even if BDM is used. server['image'] = ctx.node.properties.get('image') else: _handle_image_or_flavor(server, nova_client, 'image') _handle_image_or_flavor(server, nova_client, 'flavor') if provider_context.agents_security_group: security_groups = server.get('security_groups', []) asg = provider_context.agents_security_group['name'] if asg not in security_groups: security_groups.append(asg) server['security_groups'] = security_groups elif not server.get('security_groups', []): # Make sure that if the server is connected to a security group # from CREATE time so that there the user can control # that there is never a time that a running server is not protected. security_group_names = \ get_openstack_names_of_connected_nodes_by_openstack_type( ctx, SECURITY_GROUP_OPENSTACK_TYPE) server['security_groups'] = security_group_names # server keypair handling keypair_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, KEYPAIR_OPENSTACK_TYPE, True) if 'key_name' in server: if keypair_id: raise NonRecoverableError("server can't both have the " '"key_name" nested property and be ' 'connected to a keypair via a ' 'relationship at the same time') server['key_name'] = rename(server['key_name']) elif keypair_id: server['key_name'] = _get_keypair_name_by_id(nova_client, keypair_id) elif provider_context.agents_keypair: server['key_name'] = provider_context.agents_keypair['name'] else: server['key_name'] = None ctx.logger.info( 'server must have a keypair, yet no keypair was connected to the ' 'server node, the "key_name" nested property ' "wasn't used, and there is no agent keypair in the provider " "context. Agent installation can have issues.") _fail_on_missing_required_parameters( server, ('name', 'flavor'), 'server') _prepare_server_nics(neutron_client, ctx, server) # server group handling server_group_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, SERVER_GROUP_OPENSTACK_TYPE, True) if server_group_id: scheduler_hints = server.get('scheduler_hints', {}) scheduler_hints['group'] = server_group_id server['scheduler_hints'] = scheduler_hints ctx.logger.debug( "server.create() server after transformations: {0}".format(server)) userdata.handle_userdata(server) ctx.logger.info("Creating VM with parameters: {0}".format(str(server))) # Store the server dictionary contents in runtime properties assign_payload_as_runtime_properties(ctx, SERVER_OPENSTACK_TYPE, server) ctx.logger.debug( "Asking Nova to create server. All possible parameters are: {0})" .format(','.join(server.keys()))) try: s = nova_client.servers.create(**server) except nova_exceptions.BadRequest as e: if 'Block Device Mapping is Invalid' in str(e): return ctx.operation.retry( message='Block Device Mapping is not created yet', retry_after=30) raise ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = s.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SERVER_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = server['name']
def test_get_single_id_if_exists_none_found(self): ctx = self._make_instances([]) found = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, if_exists=True) self.assertIsNone(found)
def create(nova_client, neutron_client, args, **kwargs): """ Creates a server. Exposes the parameters mentioned in http://docs.openstack.org/developer/python-novaclient/api/novaclient.v1_1 .servers.html#novaclient.v1_1.servers.ServerManager.create """ external_server = use_external_resource(ctx, nova_client, SERVER_OPENSTACK_TYPE) if external_server: network_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, PORT_OPENSTACK_TYPE) try: _validate_external_server_nics( neutron_client, network_ids, port_ids ) _validate_external_server_keypair(nova_client) _set_network_and_ip_runtime_properties(external_server) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise provider_context = provider(ctx) def rename(name): return transform_resource_name(ctx, name) server = { 'name': get_resource_id(ctx, SERVER_OPENSTACK_TYPE), } server.update(copy.deepcopy(ctx.node.properties['server'])) server.update(copy.deepcopy(args)) if 'meta' not in server: server['meta'] = dict() transform_resource_name(ctx, server) ctx.logger.debug( "server.create() server before transformations: {0}".format(server)) _handle_image_or_flavor(server, nova_client, 'image') _handle_image_or_flavor(server, nova_client, 'flavor') if provider_context.agents_security_group: security_groups = server.get('security_groups', []) asg = provider_context.agents_security_group['name'] if asg not in security_groups: security_groups.append(asg) server['security_groups'] = security_groups # server keypair handling keypair_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, KEYPAIR_OPENSTACK_TYPE, True) if 'key_name' in server: if keypair_id: raise NonRecoverableError("server can't both have the " '"key_name" nested property and be ' 'connected to a keypair via a ' 'relationship at the same time') server['key_name'] = rename(server['key_name']) elif keypair_id: server['key_name'] = _get_keypair_name_by_id(nova_client, keypair_id) elif provider_context.agents_keypair: server['key_name'] = provider_context.agents_keypair['name'] else: raise NonRecoverableError( 'server must have a keypair, yet no keypair was connected to the ' 'server node, the "key_name" nested property ' "wasn't used, and there is no agent keypair in the provider " "context") _fail_on_missing_required_parameters( server, ('name', 'flavor', 'image', 'key_name'), 'server') _prepare_server_nics(neutron_client, ctx, server) ctx.logger.debug( "server.create() server after transformations: {0}".format(server)) userdata.handle_userdata(server) ctx.logger.info("Creating VM with parameters: {0}".format(str(server))) ctx.logger.debug( "Asking Nova to create server. All possible parameters are: {0})" .format(','.join(server.keys()))) try: s = nova_client.servers.create(**server) except nova_exceptions.BadRequest as e: if str(e).startswith(MUST_SPECIFY_NETWORK_EXCEPTION_TEXT): raise NonRecoverableError( "Can not provision server: management_network_name or id" " is not specified but there are several networks that the " "server can be connected to.") raise ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = s.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SERVER_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = server['name']
def test_get_single_id(self): ctx = self._make_instances(['the node id']) found_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) self.assertEqual('the node id', found_id)
def create(nova_client, neutron_client, args, **kwargs): """ Creates a server. Exposes the parameters mentioned in http://docs.openstack.org/developer/python-novaclient/api/novaclient.v1_1 .servers.html#novaclient.v1_1.servers.ServerManager.create """ external_server = use_external_resource(ctx, nova_client, SERVER_OPENSTACK_TYPE) if external_server: _set_network_and_ip_runtime_properties(external_server) if ctx._local: return else: network_ids = \ get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, PORT_OPENSTACK_TYPE) try: _validate_external_server_nics( neutron_client, network_ids, port_ids ) _validate_external_server_keypair(nova_client) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise provider_context = provider(ctx) def rename(name): return transform_resource_name(ctx, name) server = { 'name': get_resource_id(ctx, SERVER_OPENSTACK_TYPE), } server.update(copy.deepcopy(ctx.node.properties['server'])) server.update(copy.deepcopy(args)) _handle_boot_volume(server, ctx) handle_image_from_relationship(server, 'image', ctx) if 'meta' not in server: server['meta'] = dict() transform_resource_name(ctx, server) ctx.logger.debug( "server.create() server before transformations: {0}".format(server)) if ('block_device_mapping' in server or 'block_device_mapping_v2' in server) \ and 'image' not in server: # python-novaclient requires an image field even if BDM is used. server['image'] = ctx.node.properties.get('image') else: _handle_image_or_flavor(server, nova_client, 'image') _handle_image_or_flavor(server, nova_client, 'flavor') if provider_context.agents_security_group: security_groups = server.get('security_groups', []) asg = provider_context.agents_security_group['name'] if asg not in security_groups: security_groups.append(asg) server['security_groups'] = security_groups elif not server.get('security_groups', []): # Make sure that if the server is connected to a security group # from CREATE time so that there the user can control # that there is never a time that a running server is not protected. security_group_names = \ get_openstack_names_of_connected_nodes_by_openstack_type( ctx, SECURITY_GROUP_OPENSTACK_TYPE) server['security_groups'] = security_group_names # server keypair handling keypair_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, KEYPAIR_OPENSTACK_TYPE, True) if 'key_name' in server: if keypair_id: raise NonRecoverableError("server can't both have the " '"key_name" nested property and be ' 'connected to a keypair via a ' 'relationship at the same time') server['key_name'] = rename(server['key_name']) elif keypair_id: server['key_name'] = _get_keypair_name_by_id(nova_client, keypair_id) elif provider_context.agents_keypair: server['key_name'] = provider_context.agents_keypair['name'] else: server['key_name'] = None ctx.logger.info( 'server must have a keypair, yet no keypair was connected to the ' 'server node, the "key_name" nested property ' "wasn't used, and there is no agent keypair in the provider " "context. Agent installation can have issues.") _fail_on_missing_required_parameters( server, ('name', 'flavor'), 'server') _prepare_server_nics(neutron_client, ctx, server) # server group handling server_group_id = \ get_openstack_id_of_single_connected_node_by_openstack_type( ctx, SERVER_GROUP_OPENSTACK_TYPE, True) if server_group_id: scheduler_hints = server.get('scheduler_hints', {}) scheduler_hints['group'] = server_group_id server['scheduler_hints'] = scheduler_hints ctx.logger.debug( "server.create() server after transformations: {0}".format(server)) userdata.handle_userdata(server) ctx.logger.info("Creating VM with parameters: {0}".format(str(server))) # Store the server dictionary contents in runtime properties assign_payload_as_runtime_properties(ctx, SERVER_OPENSTACK_TYPE, server) ctx.logger.debug( "Asking Nova to create server. All possible parameters are: [{0}]" .format(','.join(server.keys()))) try: s = nova_client.servers.create(**server) except nova_exceptions.BadRequest as e: if 'Block Device Mapping is Invalid' in str(e): return ctx.operation.retry( message='Block Device Mapping is not created yet', retry_after=30) raise ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = s.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SERVER_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = server['name']
def create(nova_client, neutron_client, **kwargs): """ Creates a server. Exposes the parameters mentioned in http://docs.openstack.org/developer/python-novaclient/api/novaclient.v1_1 .servers.html#novaclient.v1_1.servers.ServerManager.create Userdata: In all cases, note that userdata should not be base64 encoded, novaclient expects it raw. The 'userdata' argument under nova.instance can be one of the following: - A string - A hash with 'type: http' and 'url: ...' """ network_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, PORT_OPENSTACK_TYPE) external_server = use_external_resource(ctx, nova_client, SERVER_OPENSTACK_TYPE) if external_server: try: _validate_external_server_nics(network_ids, port_ids) _validate_external_server_keypair(nova_client) _set_network_and_ip_runtime_properties(external_server) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise provider_context = provider(ctx) def rename(name): return transform_resource_name(ctx, name) # For possible changes by _maybe_transform_userdata() server = { 'name': get_resource_id(ctx, SERVER_OPENSTACK_TYPE), } server.update(copy.deepcopy(ctx.node.properties['server'])) transform_resource_name(ctx, server) ctx.logger.debug( "server.create() server before transformations: {0}".format(server)) _maybe_transform_userdata(server) management_network_id = None management_network_name = None if ('management_network_name' in ctx.node.properties) and \ ctx.node.properties['management_network_name']: management_network_name = \ ctx.node.properties['management_network_name'] management_network_name = rename(management_network_name) nc = _neutron_client() management_network_id = nc.cosmo_get_named( 'network', management_network_name)['id'] else: int_network = provider_context.int_network if int_network: management_network_id = int_network['id'] management_network_name = int_network['name'] # Already transform. if management_network_id is not None: server['nics'] = \ server.get('nics', []) + [{'net-id': management_network_id}] _handle_image_or_flavor(server, nova_client, 'image') _handle_image_or_flavor(server, nova_client, 'flavor') if provider_context.agents_security_group: security_groups = server.get('security_groups', []) asg = provider_context.agents_security_group['name'] if asg not in security_groups: security_groups.append(asg) server['security_groups'] = security_groups # server keypair handling keypair_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, KEYPAIR_OPENSTACK_TYPE, True) if 'key_name' in server: if keypair_id: raise NonRecoverableError("server can't both have the " '"key_name" nested property and be ' 'connected to a keypair via a ' 'relationship at the same time') server['key_name'] = rename(server['key_name']) elif keypair_id: server['key_name'] = _get_keypair_name_by_id(nova_client, keypair_id) elif provider_context.agents_keypair: server['key_name'] = provider_context.agents_keypair['name'] else: raise NonRecoverableError( 'server must have a keypair, yet no keypair was connected to the ' 'server node, the "key_name" nested property' "wasn't used, and there is no agent keypair in the provider " "context") _fail_on_missing_required_parameters( server, ('name', 'flavor', 'image', 'key_name'), 'server') if management_network_id is None and (network_ids or port_ids): # Known limitation raise NonRecoverableError( "Nova server with NICs requires " "'management_network_name' in properties or id " "from provider context, which was not supplied") # Multi-NIC by networks - start nics = [{'net-id': net_id} for net_id in network_ids] if nics: if management_network_id in network_ids: # de-duplicating the management network id in case it appears in # network_ids. There has to be a management network if a # network is connected to the server. # note: if the management network appears more than once in # network_ids it won't get de-duplicated and the server creation # will fail. nics.remove({'net-id': management_network_id}) server['nics'] = server.get('nics', []) + nics # Multi-NIC by networks - end # Multi-NIC by ports - start nics = [{'port-id': port_id} for port_id in port_ids] if nics: port_network_ids = get_port_network_ids_(neutron_client, port_ids) if management_network_id in port_network_ids: # de-duplicating the management network id in case it appears in # port_ids. There has to be a management network if a # network is connected to the server. # note: if the management network appears more than once in # network_ids it won't get de-duplicated and the server creation # will fail. server['nics'].remove({'net-id': management_network_id}) server['nics'] = server.get('nics', []) + nics # Multi-NIC by ports - end ctx.logger.debug( "server.create() server after transformations: {0}".format(server)) # First parameter is 'self', skipping params_names = inspect.getargspec(nova_client.servers.create).args[1:] params_default_values = inspect.getargspec( nova_client.servers.create).defaults params = dict(itertools.izip(params_names, params_default_values)) # Fail on unsupported parameters for k in server: if k not in params: raise NonRecoverableError( "Parameter with name '{0}' must not be passed to" " openstack provisioner (under host's " "properties.nova.instance)".format(k)) for k in params: if k in server: params[k] = server[k] if not params['meta']: params['meta'] = dict({}) if management_network_id is not None: params['meta']['cloudify_management_network_id'] = \ management_network_id if management_network_name is not None: params['meta']['cloudify_management_network_name'] = \ management_network_name ctx.logger.info("Creating VM with parameters: {0}".format(str(params))) ctx.logger.debug( "Asking Nova to create server. All possible parameters are: {0})" .format(','.join(params.keys()))) try: s = nova_client.servers.create(**params) except nova_exceptions.BadRequest as e: if str(e).startswith(MUST_SPECIFY_NETWORK_EXCEPTION_TEXT): raise NonRecoverableError( "Can not provision server: management_network_name or id" " is not specified but there are several networks that the " "server can be connected to.") raise ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = s.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SERVER_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = server['name']
def create(nova_client, neutron_client, args, **kwargs): """ Creates a server. Exposes the parameters mentioned in http://docs.openstack.org/developer/python-novaclient/api/novaclient.v1_1 .servers.html#novaclient.v1_1.servers.ServerManager.create """ network_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE) port_ids = get_openstack_ids_of_connected_nodes_by_openstack_type( ctx, PORT_OPENSTACK_TYPE) external_server = use_external_resource(ctx, nova_client, SERVER_OPENSTACK_TYPE) if external_server: try: _validate_external_server_nics( neutron_client, network_ids, port_ids ) _validate_external_server_keypair(nova_client) _set_network_and_ip_runtime_properties(external_server) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise provider_context = provider(ctx) def rename(name): return transform_resource_name(ctx, name) server = { 'name': get_resource_id(ctx, SERVER_OPENSTACK_TYPE), } server.update(copy.deepcopy(ctx.node.properties['server'])) server.update(copy.deepcopy(args)) transform_resource_name(ctx, server) ctx.logger.debug( "server.create() server before transformations: {0}".format(server)) management_network_id = None management_network_name = None if ('management_network_name' in ctx.node.properties) and \ ctx.node.properties['management_network_name']: management_network_name = \ ctx.node.properties['management_network_name'] management_network_name = rename(management_network_name) management_network_id = neutron_client.cosmo_get_named( 'network', management_network_name)['id'] else: int_network = provider_context.int_network if int_network: management_network_id = int_network['id'] management_network_name = int_network['name'] # Already transform. if management_network_id is not None: server['nics'] = \ server.get('nics', []) + [{'net-id': management_network_id}] _handle_image_or_flavor(server, nova_client, 'image') _handle_image_or_flavor(server, nova_client, 'flavor') if provider_context.agents_security_group: security_groups = server.get('security_groups', []) asg = provider_context.agents_security_group['name'] if asg not in security_groups: security_groups.append(asg) server['security_groups'] = security_groups # server keypair handling keypair_id = get_openstack_id_of_single_connected_node_by_openstack_type( ctx, KEYPAIR_OPENSTACK_TYPE, True) if 'key_name' in server: if keypair_id: raise NonRecoverableError("server can't both have the " '"key_name" nested property and be ' 'connected to a keypair via a ' 'relationship at the same time') server['key_name'] = rename(server['key_name']) elif keypair_id: server['key_name'] = _get_keypair_name_by_id(nova_client, keypair_id) elif provider_context.agents_keypair: server['key_name'] = provider_context.agents_keypair['name'] else: raise NonRecoverableError( 'server must have a keypair, yet no keypair was connected to the ' 'server node, the "key_name" nested property ' "wasn't used, and there is no agent keypair in the provider " "context") _fail_on_missing_required_parameters( server, ('name', 'flavor', 'image', 'key_name'), 'server') if management_network_id is None and (network_ids or port_ids): # Known limitation raise NonRecoverableError( "Nova server with NICs requires " "'management_network_name' in properties or id " "from provider context, which was not supplied") # Multi-NIC by networks - start nics = [{'net-id': net_id} for net_id in network_ids] if nics: if management_network_id in network_ids: # de-duplicating the management network id in case it appears in # network_ids. There has to be a management network if a # network is connected to the server. # note: if the management network appears more than once in # network_ids it won't get de-duplicated and the server creation # will fail. nics.remove({'net-id': management_network_id}) server['nics'] = server.get('nics', []) + nics # Multi-NIC by networks - end # Multi-NIC by ports - start nics = [{'port-id': port_id} for port_id in port_ids] if nics: port_network_ids = get_port_network_ids_(neutron_client, port_ids) if management_network_id in port_network_ids: # de-duplicating the management network id in case it appears in # port_ids. There has to be a management network if a # network is connected to the server. # note: if the management network appears more than once in # network_ids it won't get de-duplicated and the server creation # will fail. server['nics'].remove({'net-id': management_network_id}) server['nics'] = server.get('nics', []) + nics # Multi-NIC by ports - end ctx.logger.debug( "server.create() server after transformations: {0}".format(server)) if 'meta' not in server: server['meta'] = dict() if management_network_id is not None: server['meta']['cloudify_management_network_id'] = \ management_network_id if management_network_name is not None: server['meta']['cloudify_management_network_name'] = \ management_network_name userdata.handle_userdata(server) ctx.logger.info("Creating VM with parameters: {0}".format(str(server))) ctx.logger.debug( "Asking Nova to create server. All possible parameters are: {0})" .format(','.join(server.keys()))) try: s = nova_client.servers.create(**server) except nova_exceptions.BadRequest as e: if str(e).startswith(MUST_SPECIFY_NETWORK_EXCEPTION_TEXT): raise NonRecoverableError( "Can not provision server: management_network_name or id" " is not specified but there are several networks that the " "server can be connected to.") raise ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = s.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SERVER_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = server['name']