def create(neutron_client, **kwargs): """ Create security group with rules. Parameters transformations: rules.N.remote_group_name -> rules.N.remote_group_id rules.N.remote_group_node -> rules.N.remote_group_id (Node name in YAML) """ security_group = { 'description': None, 'name': get_resource_id(ctx, SECURITY_GROUP_OPENSTACK_TYPE), } security_group.update(ctx.node.properties['security_group']) rules_to_apply = ctx.node.properties['rules'] from neutron_plugin.security_group_rule import _process_rule security_group_rules = [] for rule in rules_to_apply: security_group_rules.append(_process_rule(rule, neutron_client)) disable_default_egress_rules = ctx.node.properties.get( 'disable_default_egress_rules') external_sg = use_external_resource(ctx, neutron_client, SECURITY_GROUP_OPENSTACK_TYPE) if external_sg: try: _ensure_existing_sg_is_identical( external_sg, security_group, security_group_rules, not disable_default_egress_rules) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise transform_resource_name(ctx, security_group) sg = neutron_client.create_security_group( {'security_group': security_group})['security_group'] ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = sg['id'] ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SECURITY_GROUP_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = sg['name'] try: if disable_default_egress_rules: for er in _egress_rules(_rules_for_sg_id(neutron_client, sg['id'])): neutron_client.delete_security_group_rule(er['id']) for sgr in security_group_rules: sgr['security_group_id'] = sg['id'] neutron_client.create_security_group_rule( {'security_group_rule': sgr}) except neutron_exceptions.NeutronClientException: delete_resource_and_runtime_properties(ctx, neutron_client, RUNTIME_PROPERTIES_KEYS) raise
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(nova_client, args, **kwargs): if use_external_resource(ctx, nova_client, FLAVOR_OPENSTACK_TYPE): return flavor_dict = create_object_dict(ctx, FLAVOR_OPENSTACK_TYPE, args, {}) flavor = nova_client.flavors.create(**flavor_dict) set_openstack_runtime_properties(ctx, flavor, FLAVOR_OPENSTACK_TYPE)
def create(glance_client, **kwargs): if use_external_resource(ctx, glance_client, IMAGE_OPENSTACK_TYPE): return img_dict = { 'name': get_resource_id(ctx, IMAGE_OPENSTACK_TYPE) } _validate_image_dictionary() img_properties = ctx.node.properties['image'] img_dict.update({key: value for key, value in img_properties.iteritems() if key != 'data'}) img = glance_client.images.create(**img_dict) img_path = img_properties.get('data', '') img_url = ctx.node.properties.get('image_url') try: _validate_image() if img_path: with open(img_path, 'rb') as image_file: glance_client.images.upload( image_id=img.id, image_data=image_file) elif img_url: img = glance_client.images.add_location(img.id, img_url, {}) except Exception: _remove_protected(glance_client) glance_client.images.delete(image_id=img.id) raise ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = img.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ IMAGE_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = img.name
def create(cinder_client, args={}, status_timeout=15, status_attempts=20, **kwargs): external_volume = use_external_resource( ctx, cinder_client, VOLUME_OPENSTACK_TYPE, VOLUME_OPENSTACK_ID_KEY) if external_volume: _set_volume_runtime_properties(external_volume) return volume_dict = create_object_dict(ctx, VOLUME_OPENSTACK_TYPE, args, {}) handle_image_from_relationship(volume_dict, 'imageRef', ctx) v = cinder_client.volumes.create(**volume_dict) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = v.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ VOLUME_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = \ volume_dict[VOLUME_OPENSTACK_ID_KEY] wait_until_status(cinder_client=cinder_client, volume_id=v.id, status=VOLUME_STATUS_AVAILABLE, num_tries=status_attempts, timeout=status_timeout, ) _set_volume_runtime_properties(v)
def create(cinder_client, status_attempts, status_timeout, args, **kwargs): if use_external_resource(ctx, cinder_client, VOLUME_OPENSTACK_TYPE, 'name'): return name = get_resource_id(ctx, VOLUME_OPENSTACK_TYPE) volume_dict = {'name': name} volume_dict.update(ctx.node.properties['volume'], **args) handle_image_from_relationship(volume_dict, 'imageRef', ctx) volume_dict['name'] = transform_resource_name( ctx, volume_dict['name']) v = cinder_client.volumes.create(**volume_dict) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = v.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ VOLUME_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = \ volume_dict['name'] wait_until_status(cinder_client=cinder_client, volume_id=v.id, status=VOLUME_STATUS_AVAILABLE, num_tries=status_attempts, timeout=status_timeout, ) ctx.instance.runtime_properties[OPENSTACK_AZ_PROPERTY] = \ v.availability_zone
def _test_use_external_resource(self, is_external, create_if_missing, exists): properties = {'create_if_missing': create_if_missing, 'use_external_resource': is_external, 'resource_id': 'resource_id'} client_mock = mock.MagicMock() os_type = 'test' def _raise_error(*_): raise NonRecoverableError('Error') def _return_something(*_): return mock.MagicMock() return_value = _return_something if exists else _raise_error if exists: properties.update({'resource_id': 'rid'}) node_context = MockCloudifyContext(node_id='a20847', properties=properties) with mock.patch( 'openstack_plugin_common._get_resource_by_name_or_id_from_ctx', new=return_value): return common.use_external_resource(node_context, client_mock, os_type)
def create(glance_client, **kwargs): if use_external_resource(ctx, glance_client, IMAGE_OPENSTACK_TYPE): return img_dict = {'name': get_resource_id(ctx, IMAGE_OPENSTACK_TYPE)} _validate_image_dictionary() img_properties = ctx.node.properties['image'] img_dict.update({ key: value for key, value in img_properties.iteritems() if key != 'data' }) img = glance_client.images.create(**img_dict) img_path = img_properties.get('data', '') img_url = ctx.node.properties.get('image_url') try: _validate_image() if img_path: with open(img_path, 'rb') as image_file: glance_client.images.upload(image_id=img.id, image_data=image_file) elif img_url: img = glance_client.images.add_location(img.id, img_url, {}) except: _remove_protected(glance_client) glance_client.images.delete(image_id=img.id) raise ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = img.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ IMAGE_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = img.name
def add_routes(neutron_client, args, **kwargs): # Since routes is part of router and not single API resource for routes # "router" resource is used router = use_external_resource(ctx, neutron_client, ROUTER_OPENSTACK_TYPE) if router: # Update routes as part of runtime properties ctx.instance.runtime_properties[ROUTES_OPENSTACK_TYPE]\ = router[ROUTES_OPENSTACK_TYPE] # Update type to match it as routes types ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY]\ = ROUTES_OPENSTACK_TYPE return routes = ctx.node.properties.get(ROUTES_OPENSTACK_TYPE, {}) if not routes: raise NonRecoverableError('routes param is required and must be ' 'provided when creating static routes !!') # Force to pass only the "routes" provided by the node properties routes_args = {'routes': routes} # This will update the router and add new static routes based on the # routes param provided by the "cloudify.openstack.nodes.Routes" r = _update_router_routes(neutron_client, routes_args, **kwargs) router = r.get(ROUTER_OPENSTACK_TYPE) if r and router: set_neutron_runtime_properties(ctx, router, ROUTES_OPENSTACK_TYPE) ctx.instance.runtime_properties[ROUTES_OPENSTACK_TYPE] = routes else: raise NonRecoverableError( 'Failed while trying to retrieve router instance')
def create(neutron_client, args, **kwargs): if use_external_resource(ctx, neutron_client, ROUTER_OPENSTACK_TYPE): try: ext_net_id_by_rel = _get_connected_ext_net_id(neutron_client) if ext_net_id_by_rel: router_id = get_openstack_id(ctx) router = neutron_client.show_router(router_id)['router'] if not (router['external_gateway_info'] and 'network_id' in router['external_gateway_info'] and router['external_gateway_info']['network_id'] == ext_net_id_by_rel): raise NonRecoverableError( 'Expected external resources router {0} and ' 'external network {1} to be connected'.format( router_id, ext_net_id_by_rel)) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise router = create_object_dict(ctx, ROUTER_OPENSTACK_TYPE, args, {}) ctx.logger.info('router: {0}'.format(router)) _handle_external_network_config(router, neutron_client) r = neutron_client.create_router({ROUTER_OPENSTACK_TYPE: router})[ROUTER_OPENSTACK_TYPE] set_neutron_runtime_properties(ctx, r, ROUTER_OPENSTACK_TYPE)
def _test_use_external_resource(self, is_external, create_if_missing, exists): properties = { 'create_if_missing': create_if_missing, 'use_external_resource': is_external, 'resource_id': 'resource_id' } client_mock = mock.MagicMock() os_type = 'test' def _raise_error(*_): raise NonRecoverableError('Error') def _return_something(*_): return mock.MagicMock() return_value = _return_something if exists else _raise_error if exists: properties.update({'resource_id': 'rid'}) node_context = MockCloudifyContext(node_id='a20847', properties=properties) with mock.patch( 'openstack_plugin_common._get_resource_by_name_or_id_from_ctx', new=return_value): return common.use_external_resource(node_context, client_mock, os_type)
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 create(cinder_client, status_attempts, status_timeout, args, **kwargs): if use_external_resource(ctx, cinder_client, VOLUME_OPENSTACK_TYPE, 'name'): return name = get_resource_id(ctx, VOLUME_OPENSTACK_TYPE) volume_dict = {'name': name} volume_dict.update(ctx.node.properties['volume'], **args) handle_image_from_relationship(volume_dict, 'imageRef', ctx) volume_dict['name'] = transform_resource_name(ctx, volume_dict['name']) v = cinder_client.volumes.create(**volume_dict) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = v.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ VOLUME_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = \ volume_dict['name'] wait_until_status( cinder_client=cinder_client, volume_id=v.id, status=VOLUME_STATUS_AVAILABLE, num_tries=status_attempts, timeout=status_timeout, ) ctx.instance.runtime_properties[OPENSTACK_AZ_PROPERTY] = \ v.availability_zone
def _remove_protected(glance_client): if use_external_resource(ctx, glance_client, IMAGE_OPENSTACK_TYPE): return is_protected = ctx.node.properties['image'].get('protected', False) if is_protected: img_id = ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] glance_client.images.update(img_id, protected=False)
def create(keystone_client, args, **kwargs): if use_external_resource(ctx, keystone_client, USER_OPENSTACK_TYPE): return user_dict = create_object_dict(ctx, USER_OPENSTACK_TYPE, args, {}) user = keystone_client.users.create(**user_dict) set_openstack_runtime_properties(ctx, user, USER_OPENSTACK_TYPE)
def create(keystone_client, args, **kwargs): if use_external_resource(ctx, keystone_client, PROJECT_OPENSTACK_TYPE): return project_dict = create_object_dict(ctx, PROJECT_OPENSTACK_TYPE, args, {'domain': 'default'}) project = keystone_client.projects.create(**project_dict) set_openstack_runtime_properties(ctx, project, PROJECT_OPENSTACK_TYPE)
def _remove_protected(glance_client): if use_external_resource(ctx, glance_client, IMAGE_OPENSTACK_TYPE): return is_protected = ctx.node.properties[IMAGE_OPENSTACK_TYPE].get( 'protected', False) if is_protected: img_id = get_openstack_id(ctx) glance_client.images.update(img_id, protected=False)
def use_external_floatingip(client, ip_field_name, ext_fip_ip_extractor): external_fip = use_external_resource( ctx, client, FLOATINGIP_OPENSTACK_TYPE, ip_field_name) if external_fip: ctx.instance.runtime_properties[IP_ADDRESS_PROPERTY] = \ ext_fip_ip_extractor(external_fip) return True return False
def create(neutron_client, args, **kwargs): if use_external_resource(ctx, neutron_client, NETWORK_OPENSTACK_TYPE): return network = create_object_dict(ctx, NETWORK_OPENSTACK_TYPE, args, {ADMIN_STATE_UP: True}) net = neutron_client.create_network({NETWORK_OPENSTACK_TYPE: network})[NETWORK_OPENSTACK_TYPE] set_neutron_runtime_properties(ctx, net, NETWORK_OPENSTACK_TYPE)
def use_external_floatingip(client, ip_field_name, ext_fip_ip_extractor): external_fip = use_external_resource(ctx, client, FLOATINGIP_OPENSTACK_TYPE, ip_field_name) if external_fip: ctx.instance.runtime_properties[IP_ADDRESS_PROPERTY] = \ ext_fip_ip_extractor(external_fip) return True return False
def create(nova_client, args, **kwargs): if use_external_resource(ctx, nova_client, SERVER_GROUP_OPENSTACK_TYPE): return server_grp = create_object_dict( ctx, SERVER_GROUP_OPENSTACK_TYPE, args, {'policies': [ctx.node.properties['policy']]}) server_grp = nova_client.server_groups.create(**server_grp) set_openstack_runtime_properties(ctx, server_grp, SERVER_GROUP_OPENSTACK_TYPE)
def create(nova_client, args, **kwargs): if use_external_resource(ctx, nova_client, FLAVOR_OPENSTACK_TYPE): return flavor_dict = create_object_dict(ctx, FLAVOR_OPENSTACK_TYPE, args, {}) ctx.logger.info('Creating flavor: {0}'.format(flavor_dict)) flavor = nova_client.flavors.create(**flavor_dict) set_openstack_runtime_properties(ctx, flavor, FLAVOR_OPENSTACK_TYPE) _set_extra_specs(ctx, flavor) _set_tenants_access(ctx, nova_client, flavor)
def create(nova_client, args, **kwargs): if use_external_resource(ctx, nova_client, HOST_AGGREGATE_OPENSTACK_TYPE): return host_aggregate_dict = create_object_dict(ctx, HOST_AGGREGATE_OPENSTACK_TYPE, args) host_aggregate = nova_client.aggregates.create(**host_aggregate_dict) _add_hosts(ctx, nova_client, host_aggregate, kwargs) _set_metadata(ctx, nova_client, host_aggregate, kwargs) set_openstack_runtime_properties(ctx, host_aggregate, HOST_AGGREGATE_OPENSTACK_TYPE)
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(keystone_client, **kwargs): if use_external_resource(ctx, keystone_client, PROJECT_OPENSTACK_TYPE): return project_dict = { 'name': get_resource_id(ctx, PROJECT_OPENSTACK_TYPE), 'domain': 'default' } project_dict.update(ctx.node.properties['project']) project = keystone_client.projects.create(**project_dict) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = project.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ PROJECT_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = project.name
def create(neutron_client, args, **kwargs): if use_external_resource(ctx, neutron_client, NETWORK_OPENSTACK_TYPE): return network = { 'admin_state_up': True, 'name': get_resource_id(ctx, NETWORK_OPENSTACK_TYPE), } network.update(ctx.node.properties['network'], **args) transform_resource_name(ctx, network) net = neutron_client.create_network({'network': network})['network'] ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = net['id'] ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] =\ NETWORK_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = net['name']
def create(nova_client, args, **kwargs): private_key_path = _get_private_key_path() pk_exists = _check_private_key_exists(private_key_path) if use_external_resource(ctx, nova_client, KEYPAIR_OPENSTACK_TYPE): if not pk_exists: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise NonRecoverableError( 'Failed to use external keypair (node {0}): the public key {1}' ' is available on Openstack, but the private key could not be ' 'found at {2}'.format(ctx.node.id, ctx.node.properties['resource_id'], private_key_path)) return if pk_exists: raise NonRecoverableError( "Can't create keypair - private key path already exists: {0}" .format(private_key_path)) keypair = { 'name': get_resource_id(ctx, KEYPAIR_OPENSTACK_TYPE), } keypair.update(ctx.node.properties['keypair'], **args) transform_resource_name(ctx, keypair) keypair = nova_client.keypairs.create(keypair['name'], keypair.get('public_key')) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = keypair.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ KEYPAIR_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = keypair.name try: # write private key file _mkdir_p(os.path.dirname(private_key_path)) with open(private_key_path, 'w') as f: f.write(keypair.private_key) os.chmod(private_key_path, 0600) except Exception: _delete_private_key_file() delete_resource_and_runtime_properties(ctx, nova_client, RUNTIME_PROPERTIES_KEYS) raise
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(nova_client, args, **kwargs): private_key_path = _get_private_key_path() pk_exists = _check_private_key_exists(private_key_path) if use_external_resource(ctx, nova_client, KEYPAIR_OPENSTACK_TYPE): if not pk_exists: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise NonRecoverableError( 'Failed to use external keypair (node {0}): the public key {1}' ' is available on Openstack, but the private key could not be ' 'found at {2}'.format(ctx.node.id, ctx.node.properties['resource_id'], private_key_path)) return if pk_exists: raise NonRecoverableError( "Can't create keypair - private key path already exists: {0}". format(private_key_path)) keypair = { 'name': get_resource_id(ctx, KEYPAIR_OPENSTACK_TYPE), } keypair.update(ctx.node.properties['keypair'], **args) transform_resource_name(ctx, keypair) keypair = nova_client.keypairs.create(keypair['name'], keypair.get('public_key')) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = keypair.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ KEYPAIR_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = keypair.name try: # write private key file _mkdir_p(os.path.dirname(private_key_path)) with open(private_key_path, 'w') as f: f.write(keypair.private_key) os.chmod(private_key_path, 0600) except Exception: _delete_private_key_file() delete_resource_and_runtime_properties(ctx, nova_client, RUNTIME_PROPERTIES_KEYS) raise
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(nova_client, args, **kwargs): if use_external_resource(ctx, nova_client, SERVER_GROUP_OPENSTACK_TYPE): return server_grp = { 'name': get_resource_id(ctx, SERVER_GROUP_OPENSTACK_TYPE), 'policies': [ctx.node.properties['policy']] } server_grp.update(copy.deepcopy(ctx.node.properties['server_group'])) server_grp.update(copy.deepcopy(args)) transform_resource_name(ctx, server_grp) server_grp = nova_client.server_groups.create(**server_grp) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = server_grp.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ SERVER_GROUP_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = server_grp.name
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(cinder_client, args, **kwargs): if use_external_resource(ctx, cinder_client, VOLUME_OPENSTACK_TYPE, 'display_name'): return name = get_resource_id(ctx, VOLUME_OPENSTACK_TYPE) volume_dict = {'display_name': name} volume_dict.update(ctx.node.properties['volume'], **args) volume_dict['display_name'] = transform_resource_name( ctx, volume_dict['display_name']) v = cinder_client.volumes.create(**volume_dict) ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = v.id ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ VOLUME_OPENSTACK_TYPE ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = \ volume_dict['display_name'] wait_until_status(cinder_client=cinder_client, volume_id=v.id, status=VOLUME_STATUS_AVAILABLE)
def create(neutron_client, args, **kwargs): if use_external_resource(ctx, neutron_client, ROUTER_OPENSTACK_TYPE): try: ext_net_id_by_rel = _get_connected_ext_net_id(neutron_client) if ext_net_id_by_rel: router_id = \ ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] router = neutron_client.show_router(router_id)['router'] if not (router['external_gateway_info'] and 'network_id' in router['external_gateway_info'] and router['external_gateway_info']['network_id'] == ext_net_id_by_rel): raise NonRecoverableError( 'Expected external resources router {0} and ' 'external network {1} to be connected'.format( router_id, ext_net_id_by_rel)) return except Exception: delete_runtime_properties(ctx, RUNTIME_PROPERTIES_KEYS) raise router = { 'name': get_resource_id(ctx, ROUTER_OPENSTACK_TYPE), } router.update(ctx.node.properties['router'], **args) ctx.logger.info('router: {0}'.format(router)) transform_resource_name(ctx, router) _handle_external_network_config(router, neutron_client) 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 create(glance_client, args, **kwargs): if use_external_resource(ctx, glance_client, IMAGE_OPENSTACK_TYPE): return _validate_image_dictionary() img_dict = create_object_dict(ctx, IMAGE_OPENSTACK_TYPE, args, {}) img_path = img_dict.pop('data', '') img = glance_client.images.create(**img_dict) img_url = ctx.node.properties.get('image_url') try: _validate_image() if img_path: with open(img_path, 'rb') as image_file: glance_client.images.upload(image_id=img.id, image_data=image_file) elif img_url: img = glance_client.images.add_location(img.id, img_url, {}) except Exception: _remove_protected(glance_client) glance_client.images.delete(image_id=img.id) raise set_openstack_runtime_properties(ctx, img, IMAGE_OPENSTACK_TYPE)
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, 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 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 use_external_sg(client): return use_external_resource(ctx, client, SECURITY_GROUP_OPENSTACK_TYPE)
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 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']