def create(nova_client, neutron_client, **kwargs): ctx.logger.info('Create: runtime_properties are: %s', ctx.instance.runtime_properties) orig_nova_plugin_server.create(nova_client, neutron_client, **kwargs) ctx.logger.info("Creating floating IP") floatingip = { # No defaults } floatingip.update(ctx.node.properties['floatingip']) # Sugar: floating_network_name -> (resolve) -> floating_network_id if 'floating_network_name' in floatingip: floatingip['floating_network_id'] = neutron_client.cosmo_get_named( 'network', floatingip['floating_network_name'])['id'] del floatingip['floating_network_name'] elif 'floating_network_id' not in floatingip: provider_context = provider(ctx) ext_network = provider_context.ext_network if ext_network: floatingip['floating_network_id'] = ext_network['id'] else: raise NonRecoverableError('Missing floating network id or name') fip = neutron_client.create_floatingip( {'floatingip': floatingip})['floatingip'] ctx.logger.info('Floating IP creation response: {0}'.format(fip)) ctx.instance.runtime_properties['msw_floating_ip'] = fip['floating_ip_address'] ctx.instance.runtime_properties['msw_floating_ip_id'] = fip['id'] ctx.logger.info('Create: runtime_properties are now: %s', ctx.instance.runtime_properties)
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'], **args) # Sugar: floating_network_name -> (resolve) -> floating_network_id if 'floating_network_name' in floatingip: floatingip['floating_network_id'] = neutron_client.cosmo_get_named( 'network', floatingip['floating_network_name'])['id'] del floatingip['floating_network_name'] elif 'floating_network_id' not in floatingip: provider_context = provider(ctx) ext_network = provider_context.ext_network if ext_network: floatingip['floating_network_id'] = ext_network['id'] else: raise NonRecoverableError('Missing floating network id or name') fip = neutron_client.create_floatingip( {'floatingip': floatingip})['floatingip'] set_floatingip_runtime_properties(fip['id'], fip['floating_ip_address']) ctx.logger.info('Floating IP creation response: {0}'.format(fip))
def create(neutron_client, **kwargs): external_fip = use_external_resource( ctx, neutron_client, FLOATINGIP_OPENSTACK_TYPE, 'floating_ip_address') if external_fip: ctx.instance.runtime_properties[IP_ADDRESS_PROPERTY] = \ external_fip['floating_ip_address'] return floatingip = { # No defaults } floatingip.update(ctx.node.properties['floatingip']) # Sugar: floating_network_name -> (resolve) -> floating_network_id if 'floating_network_name' in floatingip: floatingip['floating_network_id'] = neutron_client.cosmo_get_named( 'network', floatingip['floating_network_name'])['id'] del floatingip['floating_network_name'] elif 'floating_network_id' not in floatingip: provider_context = provider(ctx) ext_network = provider_context.ext_network if ext_network: floatingip['floating_network_id'] = ext_network['id'] else: raise NonRecoverableError('Missing floating network id or name') fip = neutron_client.create_floatingip( {'floatingip': floatingip})['floatingip'] ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = fip['id'] ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ FLOATINGIP_OPENSTACK_TYPE ctx.instance.runtime_properties[IP_ADDRESS_PROPERTY] = \ fip['floating_ip_address']
def create(neutron_client, **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']) # Sugar: floating_network_name -> (resolve) -> floating_network_id if 'floating_network_name' in floatingip: floatingip['floating_network_id'] = neutron_client.cosmo_get_named( 'network', floatingip['floating_network_name'])['id'] del floatingip['floating_network_name'] elif 'floating_network_id' not in floatingip: provider_context = provider(ctx) ext_network = provider_context.ext_network if ext_network: floatingip['floating_network_id'] = ext_network['id'] else: raise NonRecoverableError('Missing floating network id or name') fip = neutron_client.create_floatingip({'floatingip': floatingip})['floatingip'] set_floatingip_runtime_properties(fip['id'], fip['floating_ip_address']) ctx.logger.info('Floating IP creation response: {0}'.format(fip))
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) # Do we have a relationship with a network? connected_network = \ get_single_connected_node_by_openstack_type( ctx, NETWORK_OPENSTACK_TYPE, True) if connected_network: network_from_rel = connected_network.runtime_properties[ OPENSTACK_ID_PROPERTY] else: network_from_rel = None # TODO: Should we check whether this is really an "external" network? network_name_provided = 'floating_network_name' in floatingip network_id_provided = 'floating_network_id' in floatingip provided = [ network_name_provided, network_id_provided, network_from_rel is not None ].count(True) # At most one is expected. if provided > 1: raise NonRecoverableError( FLOATING_NETWORK_ERROR_MSG.format(network_from_rel, floatingip)) if network_from_rel: floatingip['floating_network_id'] = network_from_rel elif network_name_provided: floatingip['floating_network_id'] = neutron_client.cosmo_get_named( 'network', floatingip['floating_network_name'])['id'] del floatingip['floating_network_name'] elif not network_id_provided: provider_context = provider(ctx) ext_network = provider_context.ext_network if ext_network: floatingip['floating_network_id'] = ext_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 create(ctx, neutron_client, **kwargs): """ Create a router. Optional relationship is to gateway network. Also supports `router.external_gateway_info.network_name`, which is translated to `router.external_gateway_info.network_id`. """ network_id_set = False provider_context = provider(ctx) ctx.logger.debug('router.create(): kwargs={0}'.format(kwargs)) router = { 'name': ctx.node_id, } router.update(ctx.properties['router']) transform_resource_name(router, ctx) # Probably will not be used. External network # is usually provisioned externally. if 'external_id' in ctx.capabilities: if 'external_gateway_info' not in router: router['external_gateway_info'] = { 'enable_snat': True } router['external_gateway_info'][ 'network_id'] = ctx.capabilities['external_id'] network_id_set = True # Sugar: external_gateway_info.network_name -> # external_gateway_info.network_id if 'external_gateway_info' in router: egi = router['external_gateway_info'] if 'network_name' in egi: egi['network_id'] = neutron_client.cosmo_get_named( 'network', egi['network_name'])['id'] del egi['network_name'] network_id_set = True if not network_id_set: router['external_gateway_info'] = router.get('external_gateway_info', {}) ext_network = provider_context.ext_network if ext_network: router['external_gateway_info']['network_id'] = ext_network['id'] network_id_set = True if not network_id_set: raise NonRecoverableError('Missing network name or network') r = neutron_client.create_router({'router': router})['router'] ctx.runtime_properties['external_id'] = r['id']
def create(neutron_client, **kwargs): # Already acquired? if ctx.runtime_properties.get(OPENSTACK_ID_PROPERTY): ctx.logger.debug("Using already allocated Floating IP {0}".format( ctx.runtime_properties[IP_ADDRESS_PROPERTY])) return floatingip = { # No defaults } floatingip.update(ctx.properties['floatingip']) # Sugar: ip -> (copy as is) -> floating_ip_address if 'ip' in floatingip: floatingip['floating_ip_address'] = floatingip['ip'] del floatingip['ip'] if 'floating_ip_address' in floatingip: fip = neutron_client.cosmo_get( 'floatingip', floating_ip_address=floatingip['floating_ip_address']) ctx.runtime_properties[OPENSTACK_ID_PROPERTY] = fip['id'] ctx.runtime_properties[IP_ADDRESS_PROPERTY] = \ fip['floating_ip_address'] ctx.runtime_properties[ENABLE_DELETION_PROPERTY] = \ False # Not acquired here return # Sugar: floating_network_name -> (resolve) -> floating_network_id if 'floating_network_name' in floatingip: floatingip['floating_network_id'] = neutron_client.cosmo_get_named( 'network', floatingip['floating_network_name'])['id'] del floatingip['floating_network_name'] elif 'floating_network_id' not in floatingip: provider_context = provider(ctx) ext_network = provider_context.ext_network if ext_network: floatingip['floating_network_id'] = ext_network['id'] else: raise NonRecoverableError('Missing floating network id or name') fip = neutron_client.create_floatingip( {'floatingip': floatingip})['floatingip'] ctx.runtime_properties[OPENSTACK_ID_PROPERTY] = fip['id'] ctx.runtime_properties[IP_ADDRESS_PROPERTY] = fip['floating_ip_address'] # Acquired here -> OK to delete ctx.runtime_properties[ENABLE_DELETION_PROPERTY] = True ctx.logger.info( "Allocated floating IP {0}".format(fip['floating_ip_address']))
def _handle_external_network_config(router, neutron_client): # attempting to find an external network for the router to connect to - # first by either a network name or id passed in explicitly; then by a # network connected by a relationship; with a final optional fallback to an # external network set in the Provider-context. Otherwise the router will # simply not get connected to an external network provider_context = provider(ctx) ext_net_id_by_rel = _get_connected_ext_net_id(neutron_client) ext_net_by_property = ctx.node.properties['external_network'] # the following is meant for backwards compatibility with the # 'network_name' sugaring if 'external_gateway_info' in router and 'network_name' in \ router['external_gateway_info']: warnings.warn( 'Passing external "network_name" inside the ' 'external_gateway_info key of the "router" property is now ' 'deprecated; Use the "external_network" property instead', DeprecationWarning) ext_net_by_property = router['external_gateway_info']['network_name'] del (router['external_gateway_info']['network_name']) # need to check if the user explicitly passed network_id in the external # gateway configuration as it affects external network behavior by # relationship and/or provider context if 'external_gateway_info' in router and 'network_id' in \ router['external_gateway_info']: ext_net_by_property = \ router['external_gateway_info'].get('network_name') if ext_net_by_property and ext_net_id_by_rel: raise RuntimeError( "Router can't have an external network connected by both a " 'relationship and by a network name/id') if ext_net_by_property: ext_net_id = get_resource_by_name_or_id(ext_net_by_property, NETWORK_OPENSTACK_TYPE, neutron_client)['id'] _insert_ext_net_id_to_router_config(ext_net_id, router) elif ext_net_id_by_rel: _insert_ext_net_id_to_router_config(ext_net_id_by_rel, router) elif ctx.node.properties['default_to_managers_external_network'] and \ provider_context.ext_network: _insert_ext_net_id_to_router_config(provider_context.ext_network['id'], router)
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_external_network_config(router, neutron_client): # attempting to find an external network for the router to connect to - # first by either a network name or id passed in explicitly; then by a # network connected by a relationship; with a final optional fallback to an # external network set in the Provider-context. Otherwise the router will # simply not get connected to an external network provider_context = provider(ctx) ext_net_id_by_rel = _get_connected_ext_net_id(neutron_client) ext_net_by_property = ctx.node.properties['external_network'] # the following is meant for backwards compatibility with the # 'network_name' sugaring if 'external_gateway_info' in router and 'network_name' in \ router['external_gateway_info']: warnings.warn( 'Passing external "network_name" inside the ' 'external_gateway_info key of the "router" property is now ' 'deprecated; Use the "external_network" property instead', DeprecationWarning) ext_net_by_property = router['external_gateway_info']['network_name'] del (router['external_gateway_info']['network_name']) # need to check if the user explicitly passed network_id in the external # gateway configuration as it affects external network behavior by # relationship and/or provider context if 'external_gateway_info' in router and 'network_id' in \ router['external_gateway_info']: ext_net_by_property = \ router['external_gateway_info'].get('network_name') if ext_net_by_property and ext_net_id_by_rel: raise RuntimeError( "Router can't have an external network connected by both a " 'relationship and by a network name/id') if ext_net_by_property: ext_net_id = get_resource_by_name_or_id( ext_net_by_property, NETWORK_OPENSTACK_TYPE, neutron_client)['id'] _insert_ext_net_id_to_router_config(ext_net_id, router) elif ext_net_id_by_rel: _insert_ext_net_id_to_router_config(ext_net_id_by_rel, router) elif ctx.node.properties['default_to_managers_external_network'] and \ provider_context.ext_network: _insert_ext_net_id_to_router_config(provider_context.ext_network['id'], router)
def _get_management_network_id_and_name(neutron_client, ctx): """Examine the context to find the management network id and name.""" management_network_id = None management_network_name = \ ctx.node.properties.get('management_network_name') provider_context = provider(ctx) if management_network_name: management_network_name = transform_resource_name( ctx, management_network_name) management_network_id = neutron_client.cosmo_get_named( 'network', management_network_name) management_network_id = management_network_id['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. return management_network_id, management_network_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 """ 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 """ 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(neutron_client, **kwargs): """Create a router. Optional relationship is to gateway network. Also supports `router.external_gateway_info.network_name`, which is translated to `router.external_gateway_info.network_id`. """ if use_external_resource(ctx, neutron_client, ROUTER_OPENSTACK_TYPE): return network_id_set = False provider_context = provider(ctx) ctx.logger.debug('router.create(): kwargs={0}'.format(kwargs)) router = { 'name': get_resource_id(ctx, ROUTER_OPENSTACK_TYPE), } router.update(ctx.node.properties['router']) transform_resource_name(ctx, router) # Probably will not be used. External network # is usually provisioned externally. # TODO: remove this or modify - it's unreasonable to look for # OPENSTACK_ID_PROPERTY in capabilities as it can be of any connected # node. If the usage of capabilities here remains, need to add # validation in the 'use_external_resource' (before returning) that the # network used is the one connected to the router. if OPENSTACK_ID_PROPERTY in ctx.capabilities: if 'external_gateway_info' not in router: router['external_gateway_info'] = { 'enable_snat': True } router['external_gateway_info'][ 'network_id'] = ctx.capabilities[OPENSTACK_ID_PROPERTY] network_id_set = True # Sugar: external_gateway_info.network_name -> # external_gateway_info.network_id if 'external_gateway_info' in router: egi = router['external_gateway_info'] if 'network_name' in egi: egi['network_id'] = neutron_client.cosmo_get_named( 'network', egi['network_name'])['id'] del egi['network_name'] network_id_set = True if not network_id_set: router['external_gateway_info'] = router.get('external_gateway_info', {}) ext_network = provider_context.ext_network if ext_network: router['external_gateway_info']['network_id'] = ext_network['id'] network_id_set = True if not network_id_set: raise NonRecoverableError('Missing network name or network') r = neutron_client.create_router({'router': router})['router'] ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = r['id'] ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] =\ ROUTER_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = r['name']
def start_new_server(ctx, nova_client): """ 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: ...' """ provider_context = provider(ctx) def rename(name): return transform_resource_name(name, ctx) # For possible changes by _maybe_transform_userdata() server = { 'name': ctx.node_id } server.update(copy.deepcopy(ctx.properties['server'])) transform_resource_name(server, ctx) ctx.logger.debug( "server.create() server before transformations: {0}".format(server)) if 'nics' in server: raise NonRecoverableError( "Parameter with name 'nics' must not be passed to" " openstack provisioner (under host's " "properties.nova.instance)") _maybe_transform_userdata(server) management_network_id = None management_network_name = None nc = None if ('management_network_name' in ctx.properties) and \ ctx.properties['management_network_name']: management_network_name = ctx.properties['management_network_name'] management_network_name = rename(management_network_name) nc = _neutron_client(ctx) 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: nc = _neutron_client(ctx) server['nics'] = [{'net-id': management_network_id}] # Sugar if 'image_name' in server: server['image'] = nova_client.images.find( name=server['image_name']).id del server['image_name'] if 'flavor_name' in server: server['flavor'] = nova_client.flavors.find( name=server['flavor_name']).id del server['flavor_name'] security_groups = map(rename, server.get('security_groups', [])) if provider_context.agents_security_group: asg = provider_context.agents_security_group['name'] if asg not in security_groups: security_groups.append(asg) server['security_groups'] = security_groups if 'key_name' in server: server['key_name'] = rename(server['key_name']) else: # 'key_name' not in server if provider_context.agents_keypair: server['key_name'] = provider_context.agents_keypair['name'] _fail_on_missing_required_parameters( server, ('name', 'flavor', 'image', 'key_name'), 'server') # Multi-NIC by networks - start network_nodes_runtime_properties = ctx.capabilities.get_all().values() if network_nodes_runtime_properties and \ management_network_id is None: # Known limitation raise NonRecoverableError( "Nova server with multi-NIC requires " "'management_network_name' in properties or id " "from provider context, which was not supplied") nics = [ {'net-id': n['external_id']} for n in network_nodes_runtime_properties if nc.cosmo_is_network(n['external_id']) ] if nics: server['nics'] = server.get('nics', []) + nics # Multi-NIC by networks - end # Multi-NIC by ports - start port_nodes_runtime_properties = ctx.capabilities.get_all().values() if port_nodes_runtime_properties and \ management_network_id is None: # Known limitation raise NonRecoverableError( "Nova server with multi-NIC requires " "'management_network_name' in properties or id " "from provider context, which was not supplied") nics = [ {'port-id': n['external_id']} for n in port_nodes_runtime_properties if nc.cosmo_is_port(n['external_id']) ] if nics: 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({}) params['meta'][NODE_ID_PROPERTY] = ctx.node_id 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 NonRecoverableError("Nova bad request error: " + str(e)) except nova_exceptions.ClientException as e: raise NonRecoverableError("Nova client error: " + str(e)) ctx.runtime_properties[OPENSTACK_SERVER_ID_PROPERTY] = s.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 """ 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']
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']